From 659388745779601d391d7daa7fc029cc4a6eb009 Mon Sep 17 00:00:00 2001 From: fanxuehan <fanxuehan@qq.com> Date: Wed, 19 Aug 2020 14:38:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8Bform=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- form/.editorconfig | 13 + form/.gitignore | 47 + form/README.md | 356 + form/angular.json | 132 + form/bin/publish.js | 114 + form/browserslist | 12 + form/e2e/protractor.conf.js | 32 + form/e2e/src/app.e2e-spec.ts | 23 + form/e2e/src/app.po.ts | 11 + form/e2e/tsconfig.json | 13 + form/karma.conf.js | 32 + form/package-lock.json | 12897 +++++ form/package.json | 57 + form/src/app/MyError.ts | 9 + form/src/app/app.component.html | 3 + form/src/app/app.component.scss | 0 form/src/app/app.component.ts | 29 + form/src/app/app.module.ts | 65 + .../audio-recorder.component.html | 61 + .../audio-recorder.component.scss | 107 + .../audio-recorder.component.ts | 234 + form/src/app/common/custom-hot-zone/Unit.ts | 3108 + .../custom-hot-zone.component.html | 100 + .../custom-hot-zone.component.scss | 210 + .../custom-hot-zone.component.ts | 986 + .../lesson-title-config.component.html | 93 + .../lesson-title-config.component.scss | 365 + .../lesson-title-config.component.ts | 339 + .../player-content-wrapper.component.html | 8 + .../player-content-wrapper.component.scss | 54 + .../player-content-wrapper.component.ts | 55 + .../upload-image-with-preview.component.html | 37 + .../upload-image-with-preview.component.scss | 106 + .../upload-image-with-preview.component.ts | 158 + .../upload-video/upload-video.component.html | 94 + .../upload-video/upload-video.component.scss | 152 + .../upload-video/upload-video.component.ts | 211 + form/src/app/form/form.component.css | 35 + form/src/app/form/form.component.html | 36 + form/src/app/form/form.component.ts | 115 + form/src/app/pipes/background-image.pipe.ts | 23 + form/src/app/pipes/resource.pipe.ts | 28 + form/src/app/pipes/time.pipe.ts | 19 + form/src/app/play/Unit.ts | 1676 + form/src/app/play/play.component.css | 19 + form/src/app/play/play.component.html | 3 + form/src/app/play/play.component.ts | 679 + form/src/app/play/resources.js | 18 + form/src/app/style/colors.scss | 16 + form/src/app/style/common_mixin.css | 6 + form/src/assets/.gitkeep | 0 form/src/assets/common/arrow.png | Bin 0 -> 18955 bytes form/src/assets/common/arrow_right.png | Bin 0 -> 16122 bytes form/src/assets/common/arrow_top.png | Bin 0 -> 15943 bytes form/src/assets/default/video-not-upload.jpg | Bin 0 -> 33779 bytes form/src/assets/font/BRLNSB.TTF | Bin 0 -> 96880 bytes form/src/assets/font/BRLNSDB.TTF | Bin 0 -> 96852 bytes form/src/assets/font/BRLNSR.TTF | Bin 0 -> 97284 bytes form/src/assets/font/GOTHIC.TTF | Bin 0 -> 137568 bytes form/src/assets/font/GOTHICB.TTF | Bin 0 -> 129676 bytes form/src/assets/font/GOTHICBI.TTF | Bin 0 -> 139084 bytes form/src/assets/font/GOTHICI.TTF | Bin 0 -> 148520 bytes form/src/assets/font/MMTextBook-Bold.otf | Bin 0 -> 11496 bytes .../src/assets/font/MMTextBook-BoldItalic.otf | Bin 0 -> 12340 bytes form/src/assets/font/MMTextBook-Italic.otf | Bin 0 -> 12148 bytes form/src/assets/font/MMTextBook.otf | Bin 0 -> 11172 bytes .../assets/libs/audio-recorder/lame.min.js | 308 + .../assets/libs/audio-recorder/recorder.js | 141 + form/src/assets/libs/audio-recorder/worker.js | 108 + .../libs/service-worker/cache-service.js | 535 + .../assets/libs/video-js-7.0.0/video-js.css | 1699 + .../libs/video-js-7.0.0/video-js.min.css | 1 + form/src/assets/libs/video-js-7.0.0/video.js | 47623 ++++++++++++++++ .../assets/libs/video-js-7.0.0/video.min.js | 12 + form/src/assets/play/bg.jpg | Bin 0 -> 26413 bytes form/src/assets/play/btn_left.png | Bin 0 -> 2022 bytes form/src/assets/play/btn_right.png | Bin 0 -> 1921 bytes form/src/assets/play/default/audio.mp3 | Bin 0 -> 2520 bytes form/src/assets/play/default/pic.jpg | Bin 0 -> 29421 bytes form/src/assets/play/music/click.mp3 | Bin 0 -> 10054 bytes form/src/assets/play/text_bg.png | Bin 0 -> 293 bytes form/src/environments/environment.prod.ts | 3 + form/src/environments/environment.ts | 16 + form/src/favicon.ico | Bin 0 -> 5430 bytes form/src/index.html | 16 + form/src/main.ts | 12 + form/src/online.html | 16 + form/src/polyfills.ts | 63 + form/src/styles.css | 1 + form/src/test.ts | 20 + form/tsconfig.app.json | 20 + form/tsconfig.json | 27 + form/tsconfig.spec.json | 18 + form/tslint.json | 100 + 94 files changed, 73735 insertions(+) create mode 100644 form/.editorconfig create mode 100644 form/.gitignore create mode 100644 form/README.md create mode 100644 form/angular.json create mode 100644 form/bin/publish.js create mode 100644 form/browserslist create mode 100644 form/e2e/protractor.conf.js create mode 100644 form/e2e/src/app.e2e-spec.ts create mode 100644 form/e2e/src/app.po.ts create mode 100644 form/e2e/tsconfig.json create mode 100644 form/karma.conf.js create mode 100644 form/package-lock.json create mode 100644 form/package.json create mode 100644 form/src/app/MyError.ts create mode 100644 form/src/app/app.component.html create mode 100644 form/src/app/app.component.scss create mode 100644 form/src/app/app.component.ts create mode 100644 form/src/app/app.module.ts create mode 100644 form/src/app/common/audio-recorder/audio-recorder.component.html create mode 100644 form/src/app/common/audio-recorder/audio-recorder.component.scss create mode 100644 form/src/app/common/audio-recorder/audio-recorder.component.ts create mode 100644 form/src/app/common/custom-hot-zone/Unit.ts create mode 100644 form/src/app/common/custom-hot-zone/custom-hot-zone.component.html create mode 100644 form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss create mode 100644 form/src/app/common/custom-hot-zone/custom-hot-zone.component.ts create mode 100644 form/src/app/common/lesson-title-config/lesson-title-config.component.html create mode 100644 form/src/app/common/lesson-title-config/lesson-title-config.component.scss create mode 100644 form/src/app/common/lesson-title-config/lesson-title-config.component.ts create mode 100644 form/src/app/common/player-content-wrapper/player-content-wrapper.component.html create mode 100644 form/src/app/common/player-content-wrapper/player-content-wrapper.component.scss create mode 100644 form/src/app/common/player-content-wrapper/player-content-wrapper.component.ts create mode 100644 form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html create mode 100644 form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss create mode 100644 form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts create mode 100644 form/src/app/common/upload-video/upload-video.component.html create mode 100644 form/src/app/common/upload-video/upload-video.component.scss create mode 100644 form/src/app/common/upload-video/upload-video.component.ts create mode 100644 form/src/app/form/form.component.css create mode 100644 form/src/app/form/form.component.html create mode 100644 form/src/app/form/form.component.ts create mode 100644 form/src/app/pipes/background-image.pipe.ts create mode 100644 form/src/app/pipes/resource.pipe.ts create mode 100644 form/src/app/pipes/time.pipe.ts create mode 100644 form/src/app/play/Unit.ts create mode 100644 form/src/app/play/play.component.css create mode 100644 form/src/app/play/play.component.html create mode 100644 form/src/app/play/play.component.ts create mode 100644 form/src/app/play/resources.js create mode 100644 form/src/app/style/colors.scss create mode 100644 form/src/app/style/common_mixin.css create mode 100644 form/src/assets/.gitkeep create mode 100644 form/src/assets/common/arrow.png create mode 100644 form/src/assets/common/arrow_right.png create mode 100644 form/src/assets/common/arrow_top.png create mode 100644 form/src/assets/default/video-not-upload.jpg create mode 100644 form/src/assets/font/BRLNSB.TTF create mode 100644 form/src/assets/font/BRLNSDB.TTF create mode 100644 form/src/assets/font/BRLNSR.TTF create mode 100644 form/src/assets/font/GOTHIC.TTF create mode 100644 form/src/assets/font/GOTHICB.TTF create mode 100644 form/src/assets/font/GOTHICBI.TTF create mode 100644 form/src/assets/font/GOTHICI.TTF create mode 100644 form/src/assets/font/MMTextBook-Bold.otf create mode 100644 form/src/assets/font/MMTextBook-BoldItalic.otf create mode 100644 form/src/assets/font/MMTextBook-Italic.otf create mode 100644 form/src/assets/font/MMTextBook.otf create mode 100644 form/src/assets/libs/audio-recorder/lame.min.js create mode 100644 form/src/assets/libs/audio-recorder/recorder.js create mode 100644 form/src/assets/libs/audio-recorder/worker.js create mode 100644 form/src/assets/libs/service-worker/cache-service.js create mode 100644 form/src/assets/libs/video-js-7.0.0/video-js.css create mode 100644 form/src/assets/libs/video-js-7.0.0/video-js.min.css create mode 100644 form/src/assets/libs/video-js-7.0.0/video.js create mode 100644 form/src/assets/libs/video-js-7.0.0/video.min.js create mode 100644 form/src/assets/play/bg.jpg create mode 100644 form/src/assets/play/btn_left.png create mode 100644 form/src/assets/play/btn_right.png create mode 100644 form/src/assets/play/default/audio.mp3 create mode 100644 form/src/assets/play/default/pic.jpg create mode 100644 form/src/assets/play/music/click.mp3 create mode 100644 form/src/assets/play/text_bg.png create mode 100644 form/src/environments/environment.prod.ts create mode 100644 form/src/environments/environment.ts create mode 100644 form/src/favicon.ico create mode 100644 form/src/index.html create mode 100644 form/src/main.ts create mode 100644 form/src/online.html create mode 100644 form/src/polyfills.ts create mode 100644 form/src/styles.css create mode 100644 form/src/test.ts create mode 100644 form/tsconfig.app.json create mode 100644 form/tsconfig.json create mode 100644 form/tsconfig.spec.json create mode 100644 form/tslint.json diff --git a/form/.editorconfig b/form/.editorconfig new file mode 100644 index 0000000..e89330a --- /dev/null +++ b/form/.editorconfig @@ -0,0 +1,13 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/form/.gitignore b/form/.gitignore new file mode 100644 index 0000000..6b772c3 --- /dev/null +++ b/form/.gitignore @@ -0,0 +1,47 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc +# Only exists if Bazel was run +/bazel-out + +# dependencies +/node_modules +/publish + +# profiling files +chrome-profiler-events*.json +speed-measure-plugin*.json + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files +.DS_Store +Thumbs.db diff --git a/form/README.md b/form/README.md new file mode 100644 index 0000000..265f002 --- /dev/null +++ b/form/README.md @@ -0,0 +1,356 @@ +# ng-template-generator + +angularjs技术框架下的H5äº’åŠ¨æ¨¡æ¿æ¡†æž¶è„šæ‰‹æž¶ï¼ŒåŸºäºŽNG-ZORRO实现快速开å‘基于绘玩云的H5互动课件。 + +# 使用简介 + +## 剿œŸå‡†å¤‡ + +* git下载 https://git-scm.com/downloads +* nodejs下载 https://nodejs.org/zh-cn/download/ +* è°·æŒæµè§ˆå™¨ä¸‹è½½ https://www.google.cn/chrome/ + +都下载最新版就行,然åŽé»˜è®¤å®‰è£…å°±å¯ä»¥ + + +## 生æˆé¡¹ç›® + +* 登录绘玩云课件开å‘å¹³å°ï¼šhttp://staging-teach.ireadabc.com/ +* 点击“登录账å·ï¼ŒæŸ¥çœ‹æˆ‘的课件†+* 输入测试的用户å/密ç :developers/12345678 +* 在å³ä¸Šè§’“个人ä¸å¿ƒâ€çš„下拉èœå•里,点击“我的模æ¿â€ èœå•,然åŽç‚¹å‡»â€œæ–°å»ºæ¨¡æ¿â€, 填写必è¦çš„ä¿¡æ¯ï¼Œåœ¨â€œæŠ€æœ¯é€‰åž‹â€ä¸€é¡¹ä¸Šé€‰æ‹©â€œAngular†+* 点击“确定â€åŽï¼Œåˆ—表页就会出现一个新生æˆçš„æ¨¡æ¿é¡¹ç›® +* 在项目的å¡ç‰‡ä¸‹æ‰¾åˆ°â€œå¼€å‘â€æŒ‰é’®ï¼Œåˆ™ä¼šå¼¹å‡ºç›¸å¯¹åº”çš„gitåœ°å€ + +## 获å–å¹¶å¯åŠ¨é¡¹ç›® + +``` +// xxx 是上é¢é¡¹ç›®å¯¹åº”çš„Gitåœ°å€ +git clone xxx +cd 项目åç§°/ +npm install -g yarn +yarn install +npm start + +//å¯åЍæˆåŠŸåŽæ‰“å¼€æµè§ˆå™¨ï¼Œè¾“入:http://localhost:4200 则å¯ä»¥çœ‹åˆ°è¿™ä¸ªé¡¹ç›®çš„åˆå§‹åŒ–效果了 + +``` + +## 项目结构 + +|-- bin + +|-- dist + +|-- e2e + +|-- node_modules + +|-- publish + +|-- src + +| |-- app + +| | |-- common + +| | |-- form + +| | |-- pipes + +| | |-- play + +| | |-- services + +| | |-- style + +| | |-- app.component.html + +| | |-- app.component.scss + +| | |-- app.component.ts + +| | |-- app.module.ts + +| |-- assets + +| |-- environments + +| |-- services + +| |-- index.html + +| |-- main.ts + +| |--....... + + + +* å…¶ä¸ play 文件夹是H5模æ¿å±•示页é¢ï¼Œform文件夹是模æ¿çš„é…ç½®é¡µé¢ +* common文件夹是以往åšè¿‡çš„æ¨¡æ¿ç§¯ç´¯çš„一些比较常用的 AngularJs 的组件 +* assetsæ–‡ä»¶å¤¹å˜æ”¾æ¨¡æ¿æ ·å¼çš„陿€èµ„æºï¼Œä¾‹å¦‚å°å›¾æ ‡ã€èƒŒæ™¯å›¾ç‰‡ã€å—ä½“ã€æ ·å¼ç‰ç‰ +* 其他文件夹开å‘者å¯ä»¥ä¸åšä»»ä½•更改 + +## å¼€å§‹å¼€å‘ + +本脚手架的页é¢ç±»UI框架是基于 [NG-ZORRO](https://ng.ant.design/docs/introduce/zh "With a Title") 框架实现的,在é…置页é¢ï¼ˆform文件夹),一些表å•è¾“å…¥ï¼Œä¸Šä¼ å›¾ç‰‡ç‰ç»„件也å¯ä»¥ä½¿ç”¨ NG-ZORRO 现æˆçš„组件 + +### å¼€å‘é…置页é¢ï¼ˆform/) + +é…置页é¢ä¸»è¦ä½œç”¨æ˜¯ä¸ºäº†å‘ˆçŽ°å¤šæ ·åŒ–æ¨¡æ¿ï¼Œæé«˜H5模æ¿çš„高å¤ç”¨æ€§ã€çµæ´»æ€§æä¾›çš„一个é…ç½®å·¥å…·ï¼Œæ ¹æ®H5模æ¿çš„设计规划或特性,会规定æŸäº›å…ƒç´ 是å¯ä»¥é…置的,比如背景图片ã€éŸ³é¢‘ã€é€‰é¡¹ã€æ ‡é¢˜ç‰ç‰ç‰ç‰ã€‚(课件制作者) 通过é…置页é¢ï¼Œå°±å¯ä»¥çµæ´»çš„æ›´æ¢è¿™äº›ï¼Œä»Žè€Œå½¢æˆå¤šç§å¤šæ ·çš„课件。 + + +é…置页é¢çš„å¼€å‘è¦æ±‚很简å•,我们ä¸å…³å¿ƒå¸ƒå±€ã€æ ·å¼ã€äº¤äº’ç‰æ‰€æœ‰å®žçŽ°ç»†èŠ‚ä¸Žæ•ˆæžœï¼Œåªéœ€è°ƒç”¨ä¸¤ä¸ªå†…置的全局接å£å³å¯ï¼š + +* setData 接å£ï¼Œç”¨äºŽå°†é…置的数æ®å˜å‚¨åˆ°äº‘端。 + + æ¤æ–¹æ³•是一个异æ¥çš„æ–¹æ³•,接收三个必è¦å‚æ•° + + obj: 一个json对象 + + callback: 回调函数 + + t_name: 模æ¿åç§° + + 一般使用例å如下: + + ``` + // tsè¯æ³•,ä¸èƒ½ç›´æŽ¥ä½¿ç”¨jsçš„window对象自定义方法 + (<any> window).courseware.setData(obj, callback, t_name); + ``` + +* getData 接å£ï¼Œç”¨äºŽå½“点击修改的时候将é…置的数æ®ä»Žäº‘端获å–下æ¥ã€‚ + + æ¤æ–¹æ³•是一个异æ¥çš„æ–¹æ³•,接收两个必è¦å‚æ•° + + > callback: 回调函数, 回调函数里会得到云端ä¿å˜çš„æ•°æ® + + > t_name: 模æ¿åç§° + + 一般使用例å如下: + + ``` + // tsè¯æ³•,ä¸èƒ½ç›´æŽ¥ä½¿ç”¨jsçš„window对象自定义方法 + const getData = (<any> window).courseware.getData; + getData((data) => { + //data 就是云端获å–的数æ®ï¼Œä¹Ÿå°±æ˜¯setData方法å˜åˆ°äº‘端的那个obj + //模æ¿å¼€å‘è€…éœ€è¦æ ¹æ®æ•°æ®ï¼Œä¾æ¬¡å¡«å†™åˆ°è¡¨å•的相应ä½ç½®ï¼Œæ–¹ä¾¿ç”¨æˆ·äºŒæ¬¡ä¿®æ”¹ç¼–辑 + }); + ``` + +### å¼€å‘展示页é¢ï¼ˆplay/) + +展示页é¢ä¸»è¦æ˜¯å‘ˆçŽ°æ¨¡æ¿ï¼Œé€šè¿‡H5æŠ€æœ¯ï¼Œå®žçŽ°å¤šæ ·åŒ–çš„äº¤äº’ä¸Žå±•ç¤ºæ–¹å¼ã€‚ + + +å±•ç¤ºé¡µé¢æ›´ç®€å•,开å‘者å¯ä»¥è¿ç”¨å„ç§æŠ€æœ¯ï¼Œå®žçŽ°Web端å¯ä»¥å®žçŽ°çš„ä»»ä½•æ•ˆæžœï¼ŒåŒ…æ‹¬2Dã€3Dã€åŠ¨ç”»ã€æ¸¸æˆç‰å„ç§åœºæ™¯ï¼ŒæŠŠè¡¨å•é…置的数æ®èŽ·å–到,用于渲染相对应的页é¢å³å¯ï¼š + +* getData 接å£ï¼Œç”¨äºŽå½“点击修改的时候将é…置的数æ®ä»Žäº‘端获å–下æ¥ã€‚ + + æ¤æ–¹æ³•是一个异æ¥çš„æ–¹æ³•,接收两个必è¦å‚æ•° + + > callback: 回调函数, 回调函数里会得到云端ä¿å˜çš„æ•°æ® + + > t_name: 模æ¿åç§° + + 一般使用例å如下: + + ``` + // tsè¯æ³•,ä¸èƒ½ç›´æŽ¥ä½¿ç”¨jsçš„window对象自定义方法 + const getData = (<any> window).courseware.getData; + getData((data) => { + //data 就是云端获å–的数æ®ï¼Œä¹Ÿå°±æ˜¯setData方法å˜åˆ°äº‘端的那个obj + //模æ¿å¼€å‘è€…éœ€è¦æ ¹æ®æ•°æ®æ¥æ¸²æŸ“或控制展示页é¢çš„呈现,达到模æ¿çš„互动目的 + }); + ``` + + ### 互动课件 + + 通过H5的交互方å¼ï¼Œæˆ‘们å¯ä»¥å¾ˆè½»æ¾çš„制作在线的互动课件,使è€å¸ˆç«¯ä¸Žå¦ç”Ÿç«¯å®žçްè”åŠ¨ï¼Œä½¿åœ¨çº¿è¯¾å ‚æ›´å…·æœ‰äº¤äº’æ€§ã€‚ + + * onEvent å®šä¹‰äº‹ä»¶ï¼šç”¨äºŽè‡ªå®šä¹‰åŒæ¥äº‹ä»¶ï¼Œé…åˆå¤šç«¯äº’动使用,与sendEvent方法é…åˆä½¿ç”¨ï¼Œç”¨äºŽç›‘å¬å¤šç«¯å‘é€çš„åŒæ¥äº‹ä»¶ + + 傿•° + + > evtName : 自定义事件的åç§° + + > callback : å›žè°ƒå‡½æ•°ï¼Œå›žè°ƒå‡½æ•°é‡Œä¼šå¾—åˆ°ä¼ è¿‡æ¥çš„æ•°æ® + + 使用例å: + + ``` + const cw = (<any> window).courseware; + //订阅一个事件 + cw.onEvent('testEvent', (data,next) => { + console.log(data); + //处ç†äº‹ä»¶çš„åŒæ¥é€»è¾‘ + + //在逻辑处ç†å®Œä¹‹åŽä¸€å®šè¦æ‰§è¡Œnext方法,用于解é”事件队列 + next(); + }); + ``` + + * sendEvent å‘é€äº‹ä»¶ï¼šç”¨äºŽè‡ªå®šä¹‰åŒæ¥äº‹ä»¶ï¼Œé…åˆå¤šç«¯äº’动使用,与onEvent方法é…åˆä½¿ç”¨ï¼Œç”¨äºŽå¯¹ç«¯å‘é€åŒæ¥äº‹ä»¶ + + 傿•° + + > evtName : 自定义事件的åç§° + + > data : ä¼ é€’çš„å‚æ•° + + 使用例å: + + ``` + const cw = (<any> window).courseware; + //å‘é€äº‹ä»¶ + //è¿™æ ·ï¼Œæ‰€æœ‰ç«¯ï¼ˆæ•™å¸ˆã€å¦ç”Ÿï¼‰ éƒ½ä¼šè§¦å‘ testEvent 方法 + cw.sendEvent('testEvent', 'Hello world'); + + ``` + + * storeAspect å˜å‚¨åˆ‡é¢æ•°æ®ï¼š 课件的切é¢çŠ¶æ€æ•°æ®ï¼›äº’åŠ¨è¯¾ä»¶éœ€è¦æ¯ä¸€ä¸ªå¼€å‘者设计切é¢çжæ€ï¼Œç”¨äºŽå¦ç”Ÿè¿›å…¥å·²ç»è¿›è¡Œçš„课件,æ¢å¤è¯¾ä»¶åŒæ¥ã€‚例如è€å¸ˆè®²å›¾ç‰‡è½®æ’到第四页,这个时候å¦ç”Ÿè¿›å…¥æ•™å¸ˆï¼Œè¦æ¢å¤åˆ°ç¬¬å››é¡µï¼Œæ‰èƒ½è·Ÿè€å¸ˆåŒæ¥ä¸Šè¯¾ã€‚ + + 傿•° + + > data : ä¿å˜çš„æ•°æ®ï¼Œä¸€ä¸ªJSON对象 + + 使用例å: + + ``` + const cw = (<any> window).courseware; + //å˜å‚¨åˆ‡é¢æ•°æ®ï¼Œç”¨äºŽå¦ç”Ÿè¿›å…¥æ•™å®¤ï¼ŒåŒæ¥è¯¾å ‚ä¿¡æ¯ç‰ + cw.storeAspect({page: 5}); + ``` + + * getAspect 获å–åˆ‡é¢æ•°æ®ï¼š 课件的切é¢çŠ¶æ€æ•°æ®ï¼›äº’åŠ¨è¯¾ä»¶éœ€è¦æ¯ä¸€ä¸ªå¼€å‘者设计切é¢çжæ€ï¼Œç”¨äºŽå¦ç”Ÿè¿›å…¥å·²ç»è¿›è¡Œçš„课件,æ¢å¤è¯¾ä»¶åŒæ¥ã€‚例如è€å¸ˆè®²å›¾ç‰‡è½®æ’到第四页,这个时候å¦ç”Ÿè¿›å…¥æ•™å¸ˆï¼Œè¦æ¢å¤åˆ°ç¬¬å››é¡µï¼Œæ‰èƒ½è·Ÿè€å¸ˆåŒæ¥ä¸Šè¯¾ã€‚ + + 傿•° + + > callback : 获å–åˆ‡é¢æ•°æ®çš„回调函数 + + 使用例å: + + ``` + const cw = (<any> window).courseware; + //å˜å‚¨åˆ‡é¢æ•°æ®ï¼Œç”¨äºŽå¦ç”Ÿè¿›å…¥æ•™å®¤ï¼ŒåŒæ¥è¯¾å ‚ä¿¡æ¯ç‰ + cw.getAspect(function(aspect){ + //æ¢å¤åˆ‡é¢çжæ€çš„逻辑 + }); + ``` + + * 补充项 + + 1) æœ‰æ—¶å€™æˆ‘ä»¬åœ¨å®žçŽ°æ¨¡æ¿æ•ˆæžœçš„æ—¶å€™ï¼Œéœ€è¦ä¸€äº›åŸºæœ¬çš„ä¿¡æ¯ï¼Œæ¯”如教室信æ¯ã€å½“å‰ç”¨æˆ·ä¿¡æ¯ç‰ç‰ï¼Œä¾‹å¦‚,è€å¸ˆä¼šæ˜¾ç¤ºæŸä¸ªæŒ‰é’®ï¼Œè€Œå¦ç”Ÿä¸æ˜¾ç¤ºï¼Œæˆ‘们å¯ä»¥ç”¨å¦‚下方å¼èŽ·å–æ•™å®¤ä¿¡æ¯ï¼›åŽç»å¤§éƒ¨åˆ†é™æ€ä¿¡æ¯éƒ½ä¼šå®Œå–„到这个对象里 + + ``` + //èŽ·å–æ•™å®¤ä¿¡æ¯ï¼Œå€¼å¾—注æ„的是获å–这个信æ¯ä¸€å®šè¦å† getData方法之åŽï¼Œæˆ–者确ä¿é¡µé¢å®Œæˆä¹‹åŽ + getData((data, aspect) => { + let airClassInfo = window["air"].airClassInfo; + console.log(airClassInfo); + }); + ``` + + 2) 互动课件的 getData 方法的回调函数里多返回了一个切é¢å‚数,类似如下: + + ``` + const getData = (<any> window).courseware.getData; + getData((data, aspect) => { + //data 就是云端获å–的数æ®ï¼Œä¹Ÿå°±æ˜¯setData方法å˜åˆ°äº‘端的那个obj + //aspect 切é¢å‚数,用于æ¢å¤é¡µé¢çš„çŠ¶æ€ + //模æ¿å¼€å‘è€…éœ€è¦æ ¹æ®æ•°æ®æ¥æ¸²æŸ“或控制展示页é¢çš„呈现,达到模æ¿çš„互动目的 + }); + ``` + + 3) 一些必è¦çš„内置事件,通过监å¬è¿™äº›äº‹ä»¶ï¼Œæˆ‘们å¯ä»¥å®žçŽ°ä¸€äº›ç›¸å…³çš„åŠŸèƒ½ + + * userchange 事件,用æ¥ç›‘嬿•™å®¤å†…部的人员å˜åŠ¨æƒ…å†µï¼Œä¾‹å¦‚æŸäººè¿›å…¥ï¼ŒæŸäººé€€å‡ºéƒ½ä¼šè§¦å‘æ¤äº‹ä»¶ + + 示例: + + ``` + const cw = (<any> window).courseware; + //订阅一个事件 + cw.onEvent('userchange', (data,next) => { + //data的结构如下 + /*{ + * id: 'å˜åŠ¨ç”¨æˆ·çš„ID', + * connected: true/false, true: 连接的,false:dæ–开的 + * status: 'connect/reconnect', connect:新建连接,reconnect:釿–°è¿žæŽ¥ï¼›è¿™ä¸ªå—段在æ–开连接的事件里是缺失的 + * all_user: [] 这个是现有的用户列表 + *} + */ + console.log(data); + //处ç†äº‹ä»¶çš„åŒæ¥é€»è¾‘ + + //在逻辑处ç†å®Œä¹‹åŽä¸€å®šè¦æ‰§è¡Œnext方法,用于解é”事件队列 + next(); + }); + + ``` + + 4) 测试互动课件 + + 我们在本地开å‘ä¸ï¼Œæ— 法模拟线上è€å¸ˆå’Œå¦ç”Ÿäº’动的交互场景,所以æä¾›äº†ä¸€å¥—å¼€å‘者测试的账å·ï¼Œå¦‚下: + + 测试地å€ï¼šhttp://staging-ac.ireadabc.com/ + + è€å¸ˆç”¨æˆ·å/密ç :devtea / 1 + + å¦ç”Ÿç”¨æˆ·å/密ç : å¦ç”Ÿ1(13877777711 / 1) å¦ç”Ÿ2(13877777712 / 1) + + + 测试方法: + + 1ã€é¦–先开å‘者å‘布完模æ¿ä¹‹åŽï¼Œåœ¨åˆ¶ä½œè¯¾ä»¶çš„èœå•下用这个模æ¿åˆ¶ä½œä¸€ä¸ªè¯¾ä»¶ + + 2ã€åœ¨æœ¬åœ°æ‰“开两个æµè§ˆå™¨çª—å£ ä¸€ä¸ªç™»é™†è€å¸ˆç”¨æˆ·ï¼Œå¦ä¸€ä¸ªç™»é™†å¦ç”Ÿç”¨æˆ· + + 3ã€è€å¸ˆç”¨æˆ·è¿›å޻之åŽï¼Œå°±ä¼šæœ‰å¾ˆå¤šè¯¾ä»¶ï¼Œè¿™ä¸ªæ—¶å€™åŒå‡»è‡ªå·±åˆ¶ä½œçš„课件,å¦ç”Ÿçš„窗å£å°±ä¼šåŒæ¥çš„æ‰“开课件了 + + 4ã€æµ‹è¯•自己的交互事件,看看è€å¸ˆç«¯å’Œå¦ç”Ÿç«¯æ˜¯å¦æ˜¯è‡ªå·±æƒ³è¦çš„展示效果 + + + + ### 补充方法 + + 在模æ¿çš„编辑或展示过程ä¸ï¼Œè¿˜ä¼šç»å¸¸é‡åˆ°å¦‚下两个场景,特æä¾›é’ˆå¯¹æ€§çš„解决办法 + + 1) 表å•录入往往需è¦ä¸Šä¼ 图片ã€éŸ³è§†é¢‘ç‰å¤šåª’体文件,所以脚手架内置如下方法,用于获å–ä¸€ä¸ªä¸Šä¼ åˆ°äº‘ç«¯çš„æŽ¥å£æ–¹æ³• + + ``` + const uploadUrl = (<any> window).courseware.uploadUrl; + const uploadData = (<any> window).courseware.uploadData; + + //例如用于NG-ZORROçš„ä¸Šä¼ ç»„ä»¶åˆ™å¦‚ä¸‹å†™æ³•ï¼š + <nz-upload class="p-image-uploader" [nzDisabled]="disableUpload" + [nzShowUploadList]="false" + nzAccept = "image/*" + [nzAction]="uploadUrl" <!-- 注æ„这里 --> + [nzData]="uploadData" <!-- 注æ„这里 --> + (nzChange)="handleChange($event)"> + </nz-upload> + + ``` + + 2) 在展示页é¢åŠ è½½å®Œæˆçš„æ—¶å€™ï¼Œéœ€è¦è°ƒç”¨ä¸€ä¸‹ä¸‹é¢çš„æ–¹æ³•,用于释放切æ¢è¯¾ä»¶çš„é®ç½©å±‚ + + ``` + //æ¤æ–¹æ³•为固定写法, + //å…¶ä¸t_name为模æ¿å称,obj是云端å˜å‚¨çš„é…ç½®æ•°æ® + window["air"].hideAirClassLoading(t_name,obj); + ``` + + + ## 打包å‘布 + + 模æ¿å¼€å‘完æˆä¹‹åŽï¼Œè¦æŽ¨é€åˆ°äº‘å¹³å°ä¸Šä½¿ç”¨åˆ™éœ€è¦è¿›è¡Œæ‰“包å‘布æ“作 + + ``` + npm run publish + ``` + åœ¨é¡¹ç›®æ ¹ç›®å½•ä¸‹æ‰§è¡Œä¸Šè¿°å‘½ä»¤ï¼Œåˆ™åœ¨ ./publish 目录下生产一个 .zipçš„åŽ‹ç¼©åŒ…ï¼Œæ¤æ—¶æ‰“å¼€äº‘å¹³å° + http://staging-teach.ireadabc.com/ + 点击“模æ¿ç®¡ç†â€ èœå•,找到对应的模æ¿å¡ç‰‡ï¼Œç‚¹å‡»â€œå‘å¸ƒâ€æŒ‰é’®ï¼Œåœ¨å¼¹å‡ºçš„å¯¹è¯æ¡†ä¸é€‰ä¸åŽ‹ç¼©åŒ…ï¼Œç„¶åŽç‚¹å‡»â€œç¡®å®šâ€ï¼Œä¸Šä¼ 完æˆåŽï¼Œåˆ™å‘布就æˆåŠŸäº† + + + \ No newline at end of file diff --git a/form/angular.json b/form/angular.json new file mode 100644 index 0000000..5952480 --- /dev/null +++ b/form/angular.json @@ -0,0 +1,132 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "ng-template-generator": { + "projectType": "application", + "schematics": {}, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/ng-template-generator", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.app.json", + "aot": true, + "assets": [ + "src/favicon.ico", + "src/assets", + { + "glob": "**/*", + "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", + "output": "/assets/" + } + ], + "styles": [ + "./node_modules/ng-zorro-antd/ng-zorro-antd.min.css", + "src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "ng-template-generator:build" + }, + "configurations": { + "production": { + "browserTarget": "ng-template-generator:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "ng-template-generator:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.spec.json", + "karmaConfig": "karma.conf.js", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "./node_modules/ng-zorro-antd/ng-zorro-antd.min.css", + "src/styles.css" + ], + "scripts": [] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "tsconfig.app.json", + "tsconfig.spec.json", + "e2e/tsconfig.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + }, + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "ng-template-generator:serve" + }, + "configurations": { + "production": { + "devServerTarget": "ng-template-generator:serve:production" + } + } + } + } + } + }, + "defaultProject": "ng-template-generator" +} diff --git a/form/bin/publish.js b/form/bin/publish.js new file mode 100644 index 0000000..6a7490e --- /dev/null +++ b/form/bin/publish.js @@ -0,0 +1,114 @@ +/**** + * 批é‡ç¼–译打包模æ¿å·¥å…· + * è¿è¡Œ npm run publish T_01 å‘½ä»¤æ¥æ‰“包T_01æ¨¡æ¿ + * è¿è¡Œ npm run publish T_01,T_02,T_03,T_04 命令æ¥åˆ†åˆ«æ‰“包 T_01,T_02,T_03,T_04 这四个模æ¿ï¼Œæ³¨æ„逗å·è¦ç”¨è‹±æ–‡çš„ + * è¿è¡Œ npm run publish all å‘½ä»¤æ¥æ‰“åŒ…æ‰€æœ‰æ¨¡æ¿ + */ + +const spawn = require('child_process').spawn; +const path = require("path"); +const fs = require("fs"); +const os = require('os'); +const compressing = require("compressing"); + +//Linux系统上'Linux' +//macOS 系统上'Darwin' +//Windows系统上'Windows_NT' +let sysType = os.type(); + +Date.prototype.Format = function(fmt) { + var o = { + "M+" : this.getMonth() + 1, + "d+" : this.getDate(), + "h+" : this.getHours(), + "m+" : this.getMinutes(), + "s+" : this.getSeconds(), + "q+" : Math.floor((this.getMonth() + 3) / 3), + "S" : this.getMilliseconds() + }; + if (/(y+)/.test(fmt)) + fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); + for (var k in o) + if (new RegExp("(" + k + ")").test(fmt)) + fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); + return fmt; +} + +function clean(zipPath){ + if(fs.existsSync(zipPath)){ + fs.unlinkSync(zipPath); + } +} + +const runSpawn = async function (){ + + await new Promise(function(resolve,reject){ + + let pkg = require("../package.json"); + + let ls; + if(sysType==="Windows_NT"){ + //ng build --prod --build--optimizer --base-href /ng-one/ + ls = spawn("cmd.exe", ['/c', 'ng', 'build', '--prod', '--build--optimizer', '--base-href', '/template-base-href/'] ); + }else{ + ls = spawn("ng", ['build', '--prod', '--build--optimizer', '--base-href', '/template-base-href/'] ); + } + + ls.stdout.on('data', (data) => { + console.log(` ${data}`); + }); + + ls.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); + reject(); + }); + + ls.on('close', (code) => { + console.log(`child process exited with code ${code}`); + //è¦åŽ‹ç¼©çš„ç›®å½• + let zippath = path.resolve(__dirname,"../dist", pkg.name); + //åŽ‹ç¼©åŒ…çš„å˜æ”¾ç›®å½• + let date = new Date(); + let zipname = pkg.name+"_"+date.Format("yyyyMMdd hh-mm-ss"); + let zipdir = path.resolve(__dirname,"../publish/"+zipname+".zip"); + clean(zipdir); //åˆ é™¤åŽŸæœ‰çš„åŒ… + + const tarStream = new compressing.zip.Stream(); + fs.readdir(zippath,function(err,files){ + if(err){ + console.log("======文件打开异常======"); + console.log(err); + reject(); + } + for(let i=0;i<files.length;i++){ + tarStream.addEntry(zippath+"/"+files[i]); + } + let writeStream = fs.createWriteStream(zipdir); + tarStream.pipe(writeStream); + writeStream.on('close', () => { + console.log(`æ¨¡æ¿ ${pkg.name} 打包已完æˆï¼`); + resolve(); + }) + }); + + }); + + }); +} + +// let projects = ""; +// if(process.argv.length<3){ +// console.log("ç¼ºå°‘å‚æ•°"); +// return; +// } +// projects = process.argv[2]; + +let exec = async function(){ + //åŽ‹ç¼©æ¨¡æ¿ + await runSpawn(); +} + +exec(); + + + diff --git a/form/browserslist b/form/browserslist new file mode 100644 index 0000000..8084853 --- /dev/null +++ b/form/browserslist @@ -0,0 +1,12 @@ +# This file is used by the build system to adjust CSS and JS output to support the specified browsers below. +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries + +# You can see what browsers were selected by your queries by running: +# npx browserslist + +> 0.5% +last 2 versions +Firefox ESR +not dead +not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file diff --git a/form/e2e/protractor.conf.js b/form/e2e/protractor.conf.js new file mode 100644 index 0000000..73e4e68 --- /dev/null +++ b/form/e2e/protractor.conf.js @@ -0,0 +1,32 @@ +// @ts-check +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts + +const { SpecReporter } = require('jasmine-spec-reporter'); + +/** + * @type { import("protractor").Config } + */ +exports.config = { + allScriptsTimeout: 11000, + specs: [ + './src/**/*.e2e-spec.ts' + ], + capabilities: { + 'browserName': 'chrome' + }, + directConnect: true, + baseUrl: 'http://localhost:4200/', + framework: 'jasmine', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + onPrepare() { + require('ts-node').register({ + project: require('path').join(__dirname, './tsconfig.json') + }); + jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + } +}; \ No newline at end of file diff --git a/form/e2e/src/app.e2e-spec.ts b/form/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000..8879545 --- /dev/null +++ b/form/e2e/src/app.e2e-spec.ts @@ -0,0 +1,23 @@ +import { AppPage } from './app.po'; +import { browser, logging } from 'protractor'; + +describe('workspace-project App', () => { + let page: AppPage; + + beforeEach(() => { + page = new AppPage(); + }); + + it('should display welcome message', () => { + page.navigateTo(); + expect(page.getTitleText()).toEqual('Welcome to ng-one!'); + }); + + afterEach(async () => { + // Assert that there are no errors emitted from the browser + const logs = await browser.manage().logs().get(logging.Type.BROWSER); + expect(logs).not.toContain(jasmine.objectContaining({ + level: logging.Level.SEVERE, + } as logging.Entry)); + }); +}); diff --git a/form/e2e/src/app.po.ts b/form/e2e/src/app.po.ts new file mode 100644 index 0000000..5776aa9 --- /dev/null +++ b/form/e2e/src/app.po.ts @@ -0,0 +1,11 @@ +import { browser, by, element } from 'protractor'; + +export class AppPage { + navigateTo() { + return browser.get(browser.baseUrl) as Promise<any>; + } + + getTitleText() { + return element(by.css('app-root h1')).getText() as Promise<string>; + } +} diff --git a/form/e2e/tsconfig.json b/form/e2e/tsconfig.json new file mode 100644 index 0000000..39b800f --- /dev/null +++ b/form/e2e/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/e2e", + "module": "commonjs", + "target": "es5", + "types": [ + "jasmine", + "jasminewd2", + "node" + ] + } +} diff --git a/form/karma.conf.js b/form/karma.conf.js new file mode 100644 index 0000000..4a9333c --- /dev/null +++ b/form/karma.conf.js @@ -0,0 +1,32 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, './coverage/ng-one'), + reports: ['html', 'lcovonly', 'text-summary'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false, + restartOnFileChange: true + }); +}; diff --git a/form/package-lock.json b/form/package-lock.json new file mode 100644 index 0000000..b03c7c3 --- /dev/null +++ b/form/package-lock.json @@ -0,0 +1,12897 @@ +{ + "name": "ng-template-generator", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.900.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.900.7.tgz", + "integrity": "sha512-hfiTVYc72kzbXrzK4tea6jnTDnSKpE1D+vEptBXN2tdXEVNEAQI5Qm5L1zVDtt16UdqoUTUypIgUc9jcNH1mUQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "9.0.7", + "rxjs": "6.5.3" + }, + "dependencies": { + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular-devkit/build-angular": { + "version": "0.900.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.900.7.tgz", + "integrity": "sha512-Yv2y3OEaYEd0fE0pKvtqBpmkQYs9xJws7thHnJYCwIfYO55RfolYsXkJgAXke/4NPLrD3EsIDqoPxF7l+uw2/Q==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.900.7", + "@angular-devkit/build-optimizer": "0.900.7", + "@angular-devkit/build-webpack": "0.900.7", + "@angular-devkit/core": "9.0.7", + "@babel/core": "7.7.7", + "@babel/generator": "7.7.7", + "@babel/preset-env": "7.7.7", + "@ngtools/webpack": "9.0.7", + "ajv": "6.10.2", + "autoprefixer": "9.7.1", + "babel-loader": "8.0.6", + "browserslist": "^4.9.1", + "cacache": "13.0.1", + "caniuse-lite": "^1.0.30001032", + "circular-dependency-plugin": "5.2.0", + "copy-webpack-plugin": "5.1.1", + "core-js": "3.6.4", + "coverage-istanbul-loader": "2.0.3", + "cssnano": "4.1.10", + "file-loader": "4.2.0", + "find-cache-dir": "3.0.0", + "glob": "7.1.5", + "jest-worker": "24.9.0", + "karma-source-map-support": "1.4.0", + "less": "3.10.3", + "less-loader": "5.0.0", + "license-webpack-plugin": "2.1.3", + "loader-utils": "1.2.3", + "magic-string": "0.25.4", + "mini-css-extract-plugin": "0.8.0", + "minimatch": "3.0.4", + "open": "7.0.0", + "parse5": "4.0.0", + "postcss": "7.0.21", + "postcss-import": "12.0.1", + "postcss-loader": "3.0.0", + "raw-loader": "3.1.0", + "regenerator-runtime": "0.13.3", + "rimraf": "3.0.0", + "rollup": "1.25.2", + "rxjs": "6.5.3", + "sass": "1.23.3", + "sass-loader": "8.0.0", + "semver": "6.3.0", + "source-map": "0.7.3", + "source-map-loader": "0.2.4", + "source-map-support": "0.5.16", + "speed-measure-webpack-plugin": "1.3.1", + "style-loader": "1.0.0", + "stylus": "0.54.7", + "stylus-loader": "3.0.2", + "terser": "4.5.1", + "terser-webpack-plugin": "2.3.3", + "tree-kill": "1.2.2", + "webpack": "4.41.2", + "webpack-dev-middleware": "3.7.2", + "webpack-dev-server": "3.9.0", + "webpack-merge": "4.2.2", + "webpack-sources": "1.4.3", + "webpack-subresource-integrity": "1.3.4", + "worker-plugin": "3.2.0" + }, + "dependencies": { + "glob": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", + "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "rimraf": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", + "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "@angular-devkit/build-optimizer": { + "version": "0.900.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.900.7.tgz", + "integrity": "sha512-gxin2oPNMN+PYo82At2JP1Q+uxnvwyDFWA1Wl+Ufuc5zHGhjKqxdQjkdMF7OT0ihtmkllN+t/NTB7rcx/Sx9Wg==", + "dev": true, + "requires": { + "loader-utils": "1.2.3", + "source-map": "0.7.3", + "tslib": "1.10.0", + "typescript": "3.6.4", + "webpack-sources": "1.4.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "typescript": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz", + "integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==", + "dev": true + } + } + }, + "@angular-devkit/build-webpack": { + "version": "0.900.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.900.7.tgz", + "integrity": "sha512-Nwwqjo1ZpHFLavN+nXOmuBgGjhoMBZGelDCvHtiQlQ9N6i7k9cKnP7eU5pY7jbalBguS+gWg5wJIGnbqk1K9Rg==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.900.7", + "@angular-devkit/core": "9.0.7", + "rxjs": "6.5.3" + }, + "dependencies": { + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular-devkit/core": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-9.0.7.tgz", + "integrity": "sha512-tMrz36sM1xrwvFf9Qm59GwALscVlMP7rQBjtd0fIR/QbsiOAIX4AQbV+vN6Vtwnzo5NIRZY1IXJUhesWms+h5w==", + "dev": true, + "requires": { + "ajv": "6.10.2", + "fast-json-stable-stringify": "2.0.0", + "magic-string": "0.25.4", + "rxjs": "6.5.3", + "source-map": "0.7.3" + }, + "dependencies": { + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "@angular-devkit/schematics": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-9.0.7.tgz", + "integrity": "sha512-ryPC+l24f3gX5DFMTLkDM/q2Kp6LPzBn6400k7j4qVdb1cIrZx+JUQd7F4iAksTTkX15EQPanptQXeztUrl9Ng==", + "dev": true, + "requires": { + "@angular-devkit/core": "9.0.7", + "ora": "4.0.2", + "rxjs": "6.5.3" + }, + "dependencies": { + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular/animations": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-9.0.7.tgz", + "integrity": "sha512-74gY7onajmmnksy5E0/32bFv3B9NuWxV64kqD15YjGrh8AWe1BHt5enQI+rJ2tO8m2DKnwZsctis6k0Kcy+YKQ==" + }, + "@angular/cdk": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.2.3.tgz", + "integrity": "sha512-ZwO5Sn720RA2YvBqud0JAHkZXjmjxM0yNzCO8RVtRE9i8Gl26Wk0j0nQeJkVm4zwv2QO8MwbKUKGTMt8evsokA==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^1.7.1" + } + }, + "@angular/cli": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-9.0.7.tgz", + "integrity": "sha512-/9CUNSSVyTtTNUADZ/VXJDEdhineMN/rfd35w6VsHiob49tKkeOTggaoiSne3RY4VCTqlo7GGf4KhhVXEMGnDQ==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.900.7", + "@angular-devkit/core": "9.0.7", + "@angular-devkit/schematics": "9.0.7", + "@schematics/angular": "9.0.7", + "@schematics/update": "0.900.7", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.1", + "debug": "^4.1.1", + "ini": "1.3.5", + "inquirer": "7.0.0", + "npm-package-arg": "6.1.1", + "npm-pick-manifest": "3.0.2", + "open": "7.0.0", + "pacote": "9.5.8", + "read-package-tree": "5.3.1", + "rimraf": "3.0.0", + "semver": "6.3.0", + "symbol-observable": "1.2.0", + "universal-analytics": "^0.4.20", + "uuid": "^3.3.2" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "rimraf": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", + "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@angular/common": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-9.0.7.tgz", + "integrity": "sha512-B58YgxZva1DBaeayOBsaUOOkoyR+GRibuNC3gfOMm2vXeW9eCNX+jvDtw767GnKm2yGzIq8wB3x6GHojN00dPw==" + }, + "@angular/compiler": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.7.tgz", + "integrity": "sha512-hFpkuGpzxpK5h59LHHAjTFWsY6DCXZwgJFqvCuTPxWi/srvLGZRXrpC6Z1SlgHI9xxXaPfoa4uWw2VfA3BnqEg==" + }, + "@angular/compiler-cli": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-9.0.7.tgz", + "integrity": "sha512-+RXghex63v0Vi8vpQtDpWiqpAAnrTaN3bHT5fntRenq5+Ok5vL1MJ1mzbTmBXs2tuwTqNlwMm2AlZB7G/xcDMQ==", + "dev": true, + "requires": { + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "fs-extra": "4.0.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^6.3.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "yargs": "13.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "yargs": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.1.0.tgz", + "integrity": "sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "@angular/core": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.7.tgz", + "integrity": "sha512-E9XZH5Dl+9MWG3MDC6wrKllhA8Rljpz66HOIeqKv2fHPed8kzuJZU3WJWLtbhDAXFwtGTyTZ4c82ZLSmqwTorg==" + }, + "@angular/forms": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-9.0.7.tgz", + "integrity": "sha512-PaHAmjMJDtg/3aGCPuq5BCRC1eZ/DBCpva9f7NrA1kqk0LcLdebm0v2uHwTOBtiz/VEgPvxiS4tXC4rjvUtfEg==" + }, + "@angular/language-service": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-9.0.7.tgz", + "integrity": "sha512-IZG1kvw48JyFRy7bfMHqBixWrEHZmXmkP5DWsi5Tw6KusaczkMghI20BevCkodPcajXWHAUHNKyp1tlE3OnH0w==", + "dev": true + }, + "@angular/platform-browser": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-9.0.7.tgz", + "integrity": "sha512-Por8omrEiSV2U/K2mm/Kuv+2R2rJkbAZ3ctEM6CWj9Y4Gz2akjOCxmEgWhhBeqdigcC3T1v707f52osf9jWBkg==" + }, + "@angular/platform-browser-dynamic": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.0.7.tgz", + "integrity": "sha512-jwpyd93ofcRtchbayKD5v4GN4Lc7vbPe6dMUiwfnVnVAql0bOD/3YRI7w5qJ0Xx0sgQT+9Xo6jTXYnyUsZpEww==" + }, + "@angular/router": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-9.0.7.tgz", + "integrity": "sha512-uKru9F/Zju//gg6INl54abnlpLdEUUO/GpCfMk4zqu8LCZGNFta6OY7VT+9DK9Vdrh/XUD70oE9WoelcRwwTYA==" + }, + "@ant-design/colors": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz", + "integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==", + "requires": { + "tinycolor2": "^1.4.1" + } + }, + "@ant-design/icons-angular": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons-angular/-/icons-angular-8.1.1.tgz", + "integrity": "sha512-JMfavPHwahJcGWT13bTCt4IHzrsNgbJzzB+VWYtzjwWszMCVkkOOn+aJbslupHOl72KWDvklN/LjCQPBgu7xLQ==", + "requires": { + "@ant-design/colors": "^3.1.0", + "tslib": "^1.9.0" + } + }, + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/core": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.7.tgz", + "integrity": "sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.7", + "@babel/helpers": "^7.7.4", + "@babel/parser": "^7.7.7", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.7.tgz", + "integrity": "sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" + } + }, + "@babel/helper-define-map": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz", + "integrity": "sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A==", + "dev": true, + "requires": { + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", + "dev": true, + "requires": { + "lodash": "^4.17.19" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz", + "integrity": "sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.0.tgz", + "integrity": "sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", + "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz", + "integrity": "sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", + "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/preset-env": { + "version": "7.7.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.7.tgz", + "integrity": "sha512-pCu0hrSSDVI7kCVUOdcMNQEbOPJ52E+LrQ14sN8uL2ALfSqePZQlKrOy+tM4uhEdYlCHi4imr8Zz2cZe9oSdIg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.7.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.7.4", + "@babel/plugin-proposal-dynamic-import": "^7.7.4", + "@babel/plugin-proposal-json-strings": "^7.7.4", + "@babel/plugin-proposal-object-rest-spread": "^7.7.7", + "@babel/plugin-proposal-optional-catch-binding": "^7.7.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.7.7", + "@babel/plugin-syntax-async-generators": "^7.7.4", + "@babel/plugin-syntax-dynamic-import": "^7.7.4", + "@babel/plugin-syntax-json-strings": "^7.7.4", + "@babel/plugin-syntax-object-rest-spread": "^7.7.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.7.4", + "@babel/plugin-syntax-top-level-await": "^7.7.4", + "@babel/plugin-transform-arrow-functions": "^7.7.4", + "@babel/plugin-transform-async-to-generator": "^7.7.4", + "@babel/plugin-transform-block-scoped-functions": "^7.7.4", + "@babel/plugin-transform-block-scoping": "^7.7.4", + "@babel/plugin-transform-classes": "^7.7.4", + "@babel/plugin-transform-computed-properties": "^7.7.4", + "@babel/plugin-transform-destructuring": "^7.7.4", + "@babel/plugin-transform-dotall-regex": "^7.7.7", + "@babel/plugin-transform-duplicate-keys": "^7.7.4", + "@babel/plugin-transform-exponentiation-operator": "^7.7.4", + "@babel/plugin-transform-for-of": "^7.7.4", + "@babel/plugin-transform-function-name": "^7.7.4", + "@babel/plugin-transform-literals": "^7.7.4", + "@babel/plugin-transform-member-expression-literals": "^7.7.4", + "@babel/plugin-transform-modules-amd": "^7.7.5", + "@babel/plugin-transform-modules-commonjs": "^7.7.5", + "@babel/plugin-transform-modules-systemjs": "^7.7.4", + "@babel/plugin-transform-modules-umd": "^7.7.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.7.4", + "@babel/plugin-transform-new-target": "^7.7.4", + "@babel/plugin-transform-object-super": "^7.7.4", + "@babel/plugin-transform-parameters": "^7.7.7", + "@babel/plugin-transform-property-literals": "^7.7.4", + "@babel/plugin-transform-regenerator": "^7.7.5", + "@babel/plugin-transform-reserved-words": "^7.7.4", + "@babel/plugin-transform-shorthand-properties": "^7.7.4", + "@babel/plugin-transform-spread": "^7.7.4", + "@babel/plugin-transform-sticky-regex": "^7.7.4", + "@babel/plugin-transform-template-literals": "^7.7.4", + "@babel/plugin-transform-typeof-symbol": "^7.7.4", + "@babel/plugin-transform-unicode-regex": "^7.7.4", + "@babel/types": "^7.7.4", + "browserslist": "^4.6.0", + "core-js-compat": "^3.6.0", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.5.0" + } + }, + "@babel/runtime": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.0.tgz", + "integrity": "sha512-qArkXsjJq7H+T86WrIFV0Fnu/tNOkZ4cgXmjkzAu3b/58D5mFIO8JH/y77t7C9q0OdDRdh9s7Ue5GasYssxtXw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + } + } + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "@babel/generator": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", + "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@fortawesome/angular-fontawesome": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.6.1.tgz", + "integrity": "sha512-ARQjtRuT+ZskzJDJKPwuiGO3+7nS0iyNLU/uHVJHfG4LwGJxwVIGldwg1SU957sra0Z0OtWEajHMhiS4vB9LwQ==" + }, + "@fortawesome/fontawesome-common-types": { + "version": "0.2.30", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.30.tgz", + "integrity": "sha512-TsRwpTuKwFNiPhk1UfKgw7zNPeV5RhNp2Uw3pws+9gDAkPGKrtjR1y2lI3SYn7+YzyfuNknflpBA1LRKjt7hMg==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "1.2.30", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.30.tgz", + "integrity": "sha512-E3sAXATKCSVnT17HYmZjjbcmwihrNOCkoU7dVMlasrcwiJAHxSKeZ+4WN5O+ElgO/FaYgJmASl8p9N7/B/RttA==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.30" + } + }, + "@fortawesome/free-regular-svg-icons": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.14.0.tgz", + "integrity": "sha512-6LCFvjGSMPoUQbn3NVlgiG4CY5iIY8fOm+to/D6QS/GvdqhDt+xZklQeERdCvVRbnFa1ITc1rJHPRXqkX5wztQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.30" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.14.0.tgz", + "integrity": "sha512-M933RDM8cecaKMWDSk3FRYdnzWGW7kBBlGNGfvqLVwcwhUPNj9gcw+xZMrqBdRqxnSXdl3zWzTCNNGEtFUq67Q==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.30" + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@ngtools/webpack": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.0.7.tgz", + "integrity": "sha512-MvoMaErkjESefoIrbt8F2RpKDr9KavwvH4v3hwSAKooVNFdFKNsjJ7m3gCQehumEfsYFq2mrEK2sTW4/CpFlMQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "9.0.7", + "enhanced-resolve": "4.1.1", + "rxjs": "6.5.3", + "webpack-sources": "1.4.3" + }, + "dependencies": { + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@schematics/angular": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-9.0.7.tgz", + "integrity": "sha512-3UCeexYx/YVo3kboyPZ8KgqBTduMA18AAm3s2yrC0qj41fBFVVZAZLa74uouTf4RYVgy9kR7J3uv6VLxrJPOnQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "9.0.7", + "@angular-devkit/schematics": "9.0.7" + } + }, + "@schematics/update": { + "version": "0.900.7", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.900.7.tgz", + "integrity": "sha512-e9tX2DGNYfj/k9mVICpQt2bWIYyD92dlsip7LzPeZGt+R9zCp5w19uBLa8Z00OgEGzFR1krhRvkQE5OxkkAnVw==", + "dev": true, + "requires": { + "@angular-devkit/core": "9.0.7", + "@angular-devkit/schematics": "9.0.7", + "@yarnpkg/lockfile": "1.1.0", + "ini": "1.3.5", + "npm-package-arg": "^7.0.0", + "pacote": "9.5.8", + "rxjs": "6.5.3", + "semver": "6.3.0", + "semver-intersect": "1.4.0" + }, + "dependencies": { + "npm-package-arg": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-7.0.0.tgz", + "integrity": "sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.2", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@tweenjs/tween.js": { + "version": "18.5.0", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.5.0.tgz", + "integrity": "sha512-/qyhdvbc6vWsFuiK7Wq74ZMu1F/9sFRlBv2qnjeu70XI0HRC8zOfUqbXT2irVLCSVuCI/fI7HphGdbsbyQ/Q5w==" + }, + "@types/estree": { + "version": "0.0.45", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz", + "integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/jasmine": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.12.tgz", + "integrity": "sha512-vJaQ58oceFao+NzpKNqLOWwHPsqA7YEhKv+mOXvYU4/qh+BfVWIxaBtL0Ck5iCS67yOkNwGkDCrzepnzIWF+7g==", + "dev": true + }, + "@types/jasminewd2": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.8.tgz", + "integrity": "sha512-d9p31r7Nxk0ZH0U39PTH0hiDlJ+qNVGjlt1ucOoTUptxb2v+Y5VMnsxfwN+i3hK4yQnqBi3FMmoMFcd1JHDxdg==", + "dev": true, + "requires": { + "@types/jasmine": "*" + } + }, + "@types/json-schema": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "12.12.53", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.53.tgz", + "integrity": "sha512-51MYTDTyCziHb70wtGNFRwB4l+5JNvdqzFSkbDvpbftEgVUBEE+T5f7pROhWMp/fxp07oNIEQZd5bbfAH22ohQ==", + "dev": true + }, + "@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", + "dev": true + }, + "@types/selenium-webdriver": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.17.tgz", + "integrity": "sha512-tGomyEuzSC1H28y2zlW6XPCaDaXFaD6soTdb4GNdmte2qfHtrKqhy0ZFs4r/1hpazCfEZqeTSRLvSasmEx89uw==", + "dev": true + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "@types/webpack-sources": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.8.tgz", + "integrity": "sha512-JHB2/xZlXOjzjBB6fMOpH1eQAfsrpqVVIbneE0Rok16WXwFaznaI5vfg75U5WgGJm7V9W1c4xeRQDjX/zwvghA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.6.1" + } + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", + "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==", + "dev": true + }, + "address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" + }, + "adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ali-oss": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ali-oss/-/ali-oss-6.10.0.tgz", + "integrity": "sha512-kWguelLe4QZCvqisN3i9i+kyaG2JCj+4AqXbc+HKJ3b4WYwkn2hS9INJHtrUSlo95yn9FKSNXwTAfLMrXyQlnA==", + "requires": { + "address": "^1.0.0", + "agentkeepalive": "^3.4.1", + "any-promise": "^1.3.0", + "bowser": "^1.6.0", + "co-defer": "^1.0.0", + "copy-to": "^2.0.1", + "dateformat": "^2.0.0", + "debug": "^2.2.0", + "destroy": "^1.0.4", + "end-or-error": "^1.0.1", + "get-ready": "^1.0.0", + "humanize-ms": "^1.2.0", + "is-type-of": "^1.0.0", + "js-base64": "^2.5.2", + "jstoxml": "^0.2.3", + "merge-descriptors": "^1.0.1", + "mime": "^2.4.5", + "mz-modules": "^2.1.0", + "platform": "^1.3.1", + "pump": "^3.0.0", + "sdk-base": "^2.0.1", + "stream-http": "2.8.2", + "stream-wormhole": "^1.0.4", + "urllib": "^2.33.1", + "utility": "^1.8.0", + "xml2js": "^0.4.16" + } + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-root-path": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz", + "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==", + "dev": true + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.3.tgz", + "integrity": "sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA==" + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.1.tgz", + "integrity": "sha512-w3b5y1PXWlhYulevrTJ0lizkQ5CyqfeU6BIRDbuhsMupstHQOeb1Ur80tcB1zxSu7AwyY/qCQ7Vvqklh31ZBFw==", + "dev": true, + "requires": { + "browserslist": "^4.7.2", + "caniuse-lite": "^1.0.30001006", + "chalk": "^2.4.2", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.21", + "postcss-value-parser": "^4.0.2" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "dev": true + }, + "axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, + "babel-loader": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", + "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", + "dev": true, + "requires": { + "find-cache-dir": "^2.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "pify": "^4.0.1" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "blocking-proxy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", + "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "bowser": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz", + "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "browserify-sign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz", + "integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.2", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz", + "integrity": "sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001093", + "electron-to-chromium": "^1.3.488", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" + } + }, + "browserstack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.0.tgz", + "integrity": "sha512-HJDJ0TSlmkwnt9RZ+v5gFpa1XZTBYTj0ywvLwJ3241J7vMw2jAsGNVhKHtmCOyg+VxeLZyaibO9UL71AsUeDIw==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + } + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "cacache": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", + "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", + "dev": true, + "requires": { + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001109", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001109.tgz", + "integrity": "sha512-4JIXRodHzdS3HdK8nSgIqXYLExOvG+D2/EenSvcub2Kp3QEADjo2v2oUn5g0n0D+UNwG9BtwKOyGcSq2qvQXvQ==", + "dev": true + }, + "canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz", + "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-dependency-plugin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz", + "integrity": "sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.4.0.tgz", + "integrity": "sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA==", + "dev": true + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "co-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/co-defer/-/co-defer-1.0.0.tgz", + "integrity": "sha1-Pkp4eo7tawoh7ih8CU9+jeDTyBg=" + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "codelyzer": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.2.2.tgz", + "integrity": "sha512-jB4FZ1Sx7kZhvZVdf+N2BaKTdrrNZOL0Bj10RRfrhHrb3zEvXjJvvq298JPMJAiyiCS/v4zs1QlGU0ip7xGqeA==", + "dev": true, + "requires": { + "app-root-path": "^2.2.1", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + } + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compressing": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/compressing/-/compressing-1.5.1.tgz", + "integrity": "sha512-1AGBR4Vh0/rpPKSXHoV9cerLo0CUlAhZ/xsJqU3a9+2cbSaFjWT3fk2MIGkCnbpk//DGWrcWw03rhKFQrA9RQw==", + "requires": { + "flushwritable": "^1.0.0", + "get-ready": "^1.0.0", + "iconv-lite": "^0.5.0", + "mkdirp": "^0.5.1", + "pump": "^3.0.0", + "streamifier": "^0.1.1", + "tar-stream": "^1.5.2", + "yauzl": "^2.7.0", + "yazl": "^2.4.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-to": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", + "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=" + }, + "copy-webpack-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg==", + "dev": true, + "requires": { + "cacache": "^12.0.3", + "find-cache-dir": "^2.1.0", + "glob-parent": "^3.1.0", + "globby": "^7.1.1", + "is-glob": "^4.0.1", + "loader-utils": "^1.2.3", + "minimatch": "^3.0.4", + "normalize-path": "^3.0.0", + "p-limit": "^2.2.1", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + } + } + }, + "core-js": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", + "dev": true + }, + "core-js-compat": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", + "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", + "dev": true, + "requires": { + "browserslist": "^4.8.5", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "coverage-istanbul-loader": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/coverage-istanbul-loader/-/coverage-istanbul-loader-2.0.3.tgz", + "integrity": "sha512-LiGRvyIuzVYs3M1ZYK1tF0HekjH0DJ8zFdUwAZq378EJzqOgToyb1690dp3TAUlP6Y+82uu42LRjuROVeJ54CA==", + "dev": true, + "requires": { + "convert-source-map": "^1.7.0", + "istanbul-lib-instrument": "^4.0.0", + "loader-utils": "^1.2.3", + "merge-source-map": "^1.1.0", + "schema-utils": "^2.6.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "^2.0.0" + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-selector-tokenizer": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + } + }, + "css-what": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", + "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==", + "dev": true + }, + "cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", + "dev": true, + "requires": { + "through": "X.X.X" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", + "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.39" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", + "dev": true, + "requires": { + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", + "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", + "dev": true + } + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "damerau-levenshtein": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", + "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + } + }, + "default-user-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz", + "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", + "requires": { + "os-name": "~1.0.3" + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "dependency-graph": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", + "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "digest-header": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/digest-header/-/digest-header-0.0.1.tgz", + "integrity": "sha1-Ecz23uxXZqw3l0TZAcEsuklRS+Y=", + "requires": { + "utility": "0.1.11" + }, + "dependencies": { + "utility": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/utility/-/utility-0.1.11.tgz", + "integrity": "sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU=", + "requires": { + "address": ">=0.0.1" + } + } + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "electron-to-chromium": { + "version": "1.3.516", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.516.tgz", + "integrity": "sha512-WDM5AAQdOrvLqSX8g3Zd5AujBXfMxf96oeZkff0U2HF5op3tjShE+on2yay3r1UD4M9I3p0iHpAS4+yV8U8A9A==", + "dev": true + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "end-or-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/end-or-error/-/end-or-error-1.0.1.tgz", + "integrity": "sha1-3HpiEP5403L+4kqLSJnb0VVBTcs=" + }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "dev": true + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-loader": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.2.0.tgz", + "integrity": "sha512-+xZnaK5R8kBJrHK0/6HRlrKNamvVS5rjyuju+rnyxRGuwUJwpAMsVzUl5dz6rK8brkzjV6JpcFNjp6NqV0g1OQ==", + "dev": true, + "requires": { + "loader-utils": "^1.2.3", + "schema-utils": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "find-cache-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.0.0.tgz", + "integrity": "sha512-t7ulV1fmbxh5G9l/492O1p5+EBbr3uwpt6odhFTMc+nWyhmbloe+ja9BZ8pIBtqFWhOmCWVjx+pTW4zDkFoclw==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.0", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "flushwritable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flushwritable/-/flushwritable-1.0.0.tgz", + "integrity": "sha1-PjKNj95BKtR+c44751C00pAENJg=" + }, + "follow-redirects": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.12.1.tgz", + "integrity": "sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formstream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/formstream/-/formstream-1.1.0.tgz", + "integrity": "sha1-UfOXDyYTbrCtRDBN5M67UCB7RHk=", + "requires": { + "destroy": "^1.0.4", + "mime": "^1.3.4", + "pause-stream": "~0.0.11" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + } + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-ready": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-ready/-/get-ready-1.0.0.tgz", + "integrity": "sha1-+RgX8emt7P6hOlYq38jeiDqzR4I=" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-uri": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", + "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", + "requires": { + "data-uri-to-buffer": "1", + "debug": "2", + "extend": "~3.0.2", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "2" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.5.tgz", + "integrity": "sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "dev": true + }, + "html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-parser-js": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz", + "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", + "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz", + "integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + } + } + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "dev": true + }, + "is-class-hotfix": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", + "integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==" + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-docker": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.0.tgz", + "integrity": "sha512-mB2WygGsSeoXtLKpSYzP6sa0Z9DyU9ZyKlnvuZWxCociaI0qsF8u12sR72DFTX236g1u6oWSWYFuUk09nGQEjg==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dev": true, + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-type-of": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-type-of/-/is-type-of-1.2.1.tgz", + "integrity": "sha512-uK0kyX9LZYhSDS7H2sVJQJop1UnWPWmo5RvR3q2kFH6AUHYs7sOrVg0b4nyBHw29kRRNFofYN/JbHZDlHiItTA==", + "requires": { + "core-util-is": "^1.0.2", + "is-class-hotfix": "~0.0.6", + "isstream": "~0.1.2" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul-api": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.7.tgz", + "integrity": "sha512-LYTOa2UrYFyJ/aSczZi/6lBykVMjCCvUmT64gOe+jPZFy4w6FYfPGqFT2IiQ2BxVHHDOvCD7qrIXb0EOh4uGWw==", + "dev": true, + "requires": { + "async": "^2.6.2", + "compare-versions": "^3.4.0", + "fileset": "^2.0.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.5", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "minimatch": "^3.0.4", + "once": "^1.4.0" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "dev": true, + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0" + } + }, + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "requires": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "dependencies": { + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + } + } + }, + "jasmine-core": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.5.0.tgz", + "integrity": "sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==", + "dev": true + }, + "jasmine-spec-reporter": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", + "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "dev": true, + "requires": { + "colors": "1.1.2" + } + }, + "jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "dev": true + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" + }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jstoxml": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jstoxml/-/jstoxml-0.2.4.tgz", + "integrity": "sha1-/z+2eFaIOgMpU8fOjOdIYhD0hEc=" + }, + "jszip": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.5.0.tgz", + "integrity": "sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, + "karma": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.3.0.tgz", + "integrity": "sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ==", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "braces": "^3.0.2", + "chokidar": "^3.0.0", + "colors": "^1.1.0", + "connect": "^3.6.0", + "core-js": "^3.1.3", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.14", + "log4js": "^4.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + } + }, + "karma-chrome-launcher": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "dev": true, + "requires": { + "which": "^1.2.1" + } + }, + "karma-coverage-istanbul-reporter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.1.1.tgz", + "integrity": "sha512-CH8lTi8+kKXGvrhy94+EkEMldLCiUA0xMOiL31vvli9qK0T+qcXJAwWBRVJWnVWxYkTmyWar8lPz63dxX6/z1A==", + "dev": true, + "requires": { + "istanbul-api": "^2.1.6", + "minimatch": "^3.0.4" + } + }, + "karma-jasmine": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz", + "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==", + "dev": true, + "requires": { + "jasmine-core": "^3.3" + } + }, + "karma-jasmine-html-reporter": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.5.4.tgz", + "integrity": "sha512-PtilRLno5O6wH3lDihRnz0Ba8oSn0YUJqKjjux1peoYGwo0AQqrWRbdWk/RLzcGlb+onTyXAnHl6M+Hu3UxG/Q==", + "dev": true + }, + "karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "ko-sleep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ko-sleep/-/ko-sleep-1.0.3.tgz", + "integrity": "sha1-KKKgoUhei39BX/SI3uF9JHiKsII=", + "requires": { + "ms": "^2.0.0" + } + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "less": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/less/-/less-3.10.3.tgz", + "integrity": "sha512-vz32vqfgmoxF1h3K4J+yKCtajH0PWmjkIFgbs5d78E/c/e+UQTnI+lWK+1eQRE95PXM2mC3rJlLSSP9VQHnaow==", + "dev": true, + "requires": { + "clone": "^2.1.2", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.4.1", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", + "request": "^2.83.0", + "source-map": "~0.6.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true + } + } + }, + "less-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-5.0.0.tgz", + "integrity": "sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^4.0.1" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "license-webpack-plugin": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.3.tgz", + "integrity": "sha512-vTSY5r9HOq4sxR2BIxdIXWKI+9n3b+DoQkhKHedB3TdSxTfXUDRxKXdAj5iejR+qNXprXsxvEu9W+zOhgGIkAw==", + "dev": true, + "requires": { + "@types/webpack-sources": "^0.1.5", + "webpack-sources": "^1.2.0" + } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "log4js": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", + "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "dev": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.6" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "loglevel": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz", + "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "magic-string": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz", + "integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "make-fetch-happen": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", + "dev": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + } + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz", + "integrity": "sha512-MNpRGbNA52q6U92i0qbVpQNsgk7LExy41MdAlG84FeytfDOtRIf/mCHdEgG8rpTKOaNKiqUnZdlptF469hxqOw==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "requires": { + "minipass": "^2.9.0" + }, + "dependencies": { + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + } + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "mz-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mz-modules/-/mz-modules-2.1.0.tgz", + "integrity": "sha512-sjk8lcRW3vrVYnZ+W+67L/2rL+jbO5K/N6PFGIcLWTiYytNr22Ah9FDXFs+AQntTM1boZcoHi5qS+CV1seuPog==", + "requires": { + "glob": "^7.1.2", + "ko-sleep": "^1.0.3", + "mkdirp": "^0.5.1", + "pump": "^3.0.0", + "rimraf": "^2.6.1" + } + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" + }, + "ng-zorro-antd": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/ng-zorro-antd/-/ng-zorro-antd-8.5.2.tgz", + "integrity": "sha512-x+QJULyU1IXiAbf/lFPxYC/JUJvBGzU9UXnXSyLnMPZpdtEXodaF/L1N1CpSUr5SimLiHRe/jsVHDWkg0HqfYg==", + "requires": { + "@angular/cdk": "^8.0.0", + "@ant-design/icons-angular": "^8.0.2", + "date-fns": "^1.30.1", + "tslib": "^1.9.0" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-fetch-npm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", + "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-forge": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", + "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-releases": { + "version": "1.1.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", + "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + } + } + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, + "npm-registry-fetch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.5.tgz", + "integrity": "sha512-yQ0/U4fYpCCqmueB2g8sc+89ckQ3eXpmU4+Yi2j5o/r0WkKvE2+Y0tK3DEILAtn2UaQTkjTHxIXe2/CSdit+/Q==", + "dev": true, + "requires": { + "JSONStream": "^1.3.4", + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.1.tgz", + "integrity": "sha512-ZpZpjcJeugQfWsfyQlshVoowIIQ1qBGSVll4rfDq6JJVO//fesjoX808hXWfBjY+ROZgpKDI5TRSRBSoJiZ8eg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.0.0.tgz", + "integrity": "sha512-K6EKzYqnwQzk+/dzJAQSBORub3xlBTxMz+ntpZpH/LyCa1o6KjXhuN+2npAaI9jaSmU3R1Q8NWf4KUWcyytGsQ==", + "dev": true, + "requires": { + "is-wsl": "^2.1.0" + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "ora": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.2.tgz", + "integrity": "sha512-YUOZbamht5mfLxPmk4M35CD/5DuOkAacxlEUbStVXpBAt4fyhBf+vZHI/HRkI++QUp3sNoeA2Gw4C+hi4eGSig==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.2.0", + "is-interactive": "^1.0.0", + "log-symbols": "^3.0.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "os-name": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", + "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", + "requires": { + "osx-release": "^1.0.0", + "win-release": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "osx-release": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz", + "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "requires": { + "minimist": "^1.1.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pac-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz", + "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==", + "requires": { + "agent-base": "^4.2.0", + "debug": "^4.1.1", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^3.0.0", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } + }, + "pacote": { + "version": "9.5.8", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.8.tgz", + "integrity": "sha512-0Tl8Oi/K0Lo4MZmH0/6IsT3gpGf9eEAznLXEQPKgPq7FscnbUOyopnVpwXlnQdIbCUaojWy1Wd7VMyqfVsRrIw==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "cacache": "^12.0.2", + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.3", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.12", + "npm-pick-manifest": "^3.0.0", + "npm-registry-fetch": "^4.0.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.6.0", + "ssri": "^6.0.1", + "tar": "^4.4.10", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "~2.3" + } + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-calc": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz", + "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==", + "dev": true, + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + }, + "dependencies": { + "postcss": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-import": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", + "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-load-config": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", + "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "dev": true, + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "optional": true, + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + } + } + }, + "protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, + "requires": { + "genfun": "^5.0.0" + } + }, + "protractor": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.4.tgz", + "integrity": "sha512-BaL4vePgu3Vfa/whvTUAlgaCAId4uNSGxIFSCXMgj7LMYENPWLp85h5RBi9pdpX/bWQ8SF6flP7afmi2TC4eHw==", + "dev": true, + "requires": { + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.0.6", + "yargs": "^12.0.5" + }, + "dependencies": { + "@types/q": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "webdriver-manager": { + "version": "12.1.7", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.7.tgz", + "integrity": "sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA==", + "dev": true, + "requires": { + "adm-zip": "^0.4.9", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + } + } + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "proxy-agent": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz", + "integrity": "sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==", + "requires": { + "agent-base": "^4.2.0", + "debug": "4", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^3.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^3.0.1", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "raw-loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-3.1.0.tgz", + "integrity": "sha512-lzUVMuJ06HF4rYveaz9Tv0WRlUMxJ0Y1hgSkkgg+50iEdaI0TthyEDe08KIHb0XsF6rn8WYTqPCaGTZg3sX+qA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^2.0.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-package-json": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.1.tgz", + "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==", + "dev": true, + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" + } + }, + "read-package-tree": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", + "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", + "dev": true, + "requires": { + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "util-promisify": "^2.1.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "regenerate": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "regexpu-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rollup": { + "version": "1.25.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.25.2.tgz", + "integrity": "sha512-+7z6Wab/L45QCPcfpuTZKwKiB0tynj05s/+s2U3F2Bi7rOLPr9UcjUwO7/xpjlPNXA/hwnth6jBExFRGyf3tMg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.23.3.tgz", + "integrity": "sha512-1DKRZxJMOh4Bme16AbWTyYeJAjTlrvw2+fWshHHaepeJfGq2soFZTnt0YhWit+bohtDu4LdyPoEj6VFD4APHog==", + "dev": true, + "requires": { + "chokidar": ">=2.0.0 <4.0.0" + } + }, + "sass-loader": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.0.tgz", + "integrity": "sha512-+qeMu563PN7rPdit2+n5uuYVR0SSVwm0JsOUsaJXzgYcClWSlmX0iHDnmeOobPkf5kUglVot3QS6SyLyaQoJ4w==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "saucelabs": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "sdk-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/sdk-base/-/sdk-base-2.0.1.tgz", + "integrity": "sha1-ukAonovfJy7RHdnql+r5jgNtJMY=", + "requires": { + "get-ready": "~1.0.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "requires": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + } + } + }, + "selfsigned": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz", + "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==", + "dev": true, + "requires": { + "node-forge": "0.9.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "semver-intersect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", + "dev": true, + "requires": { + "semver": "^5.0.0" + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "socket.io-adapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "dev": true, + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" + } + }, + "sockjs-client": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", + "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", + "dev": true, + "requires": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "dependencies": { + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "requires": { + "es6-promisify": "^5.0.0" + } + } + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-loader": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", + "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", + "dev": true, + "requires": { + "async": "^2.5.0", + "loader-utils": "^1.1.0" + } + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "spark-md5": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.1.tgz", + "integrity": "sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "speed-measure-webpack-plugin": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz", + "integrity": "sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", + "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.2.tgz", + "integrity": "sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "stream-wormhole": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", + "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==" + }, + "streamifier": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", + "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=" + }, + "streamroller": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", + "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", + "dev": true, + "requires": { + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.14" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "style-loader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.0.0.tgz", + "integrity": "sha512-B0dOCFwv7/eY31a5PCieNwMgMhVGFe9w+rh7s/Bx8kfFkrth9zfTZquoYvdw8URgiqxObQKcpW51Ugz1HjfdZw==", + "dev": true, + "requires": { + "loader-utils": "^1.2.3", + "schema-utils": "^2.0.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "stylus": { + "version": "0.54.7", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.7.tgz", + "integrity": "sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug==", + "dev": true, + "requires": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.3", + "mkdirp": "~0.5.x", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.0.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "stylus-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "dependencies": { + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + } + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "terser": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.5.1.tgz", + "integrity": "sha512-lH9zLIbX8PRBEFCTvfHGCy0s9HEKnNso1Dx9swSopF3VUnFLB8DpQ61tHxoofovNC/sG0spajJM3EIIRSTByiQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.3.tgz", + "integrity": "sha512-gWHkaGzGYjmDoYxksFZynWTzvXOAjQ5dd7xuTMYlv4zpWlLSb6v0QLSZjELzP5dMs1ox30O1BIPs9dgqlMHuLQ==", + "dev": true, + "requires": { + "cacache": "^13.0.1", + "find-cache-dir": "^3.2.0", + "jest-worker": "^25.1.0", + "p-limit": "^2.2.2", + "schema-utils": "^2.6.4", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.4.3", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz", + "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "ts-node": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.3.0.tgz", + "integrity": "sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + } + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + }, + "tslint": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", + "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", + "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==", + "dev": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "unescape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz", + "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", + "requires": { + "extend-shallow": "^2.0.1" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universal-analytics": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.23.tgz", + "integrity": "sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "request": "^2.88.2", + "uuid": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "urllib": { + "version": "2.36.1", + "resolved": "https://registry.npmjs.org/urllib/-/urllib-2.36.1.tgz", + "integrity": "sha512-g0Gh7bH5AwfPUzFetxPtJwumGHE6D7KQn0K68MwcJXPgO2K0AliwEIxLAwGMF+TpY75DYAsvz1h9ekagYoq33w==", + "requires": { + "any-promise": "^1.3.0", + "content-type": "^1.0.2", + "debug": "^2.6.9", + "default-user-agent": "^1.0.0", + "digest-header": "^0.0.1", + "ee-first": "~1.1.1", + "formstream": "^1.1.0", + "humanize-ms": "^1.2.0", + "iconv-lite": "^0.4.15", + "ip": "^1.1.5", + "proxy-agent": "^3.1.0", + "pump": "^3.0.0", + "qs": "^6.4.0", + "statuses": "^1.3.1", + "utility": "^1.16.1" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util-promisify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", + "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utility": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/utility/-/utility-1.16.3.tgz", + "integrity": "sha512-kYghm8fknkPkUd9ncODj/b2Zojc23gnRC29QmpmL3BBsSX6W++RNRTQ1tB7l0UA7d4SisIjUyvRfVET3lBwurw==", + "requires": { + "copy-to": "^2.0.1", + "escape-html": "^1.0.3", + "mkdirp": "^0.5.1", + "mz": "^2.7.0", + "unescape": "^1.0.1" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "watchpack": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "optional": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "webdriver-js-extender": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", + "dev": true, + "requires": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + } + }, + "webpack": { + "version": "4.41.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz", + "integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.1", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "terser-webpack-plugin": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz", + "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^3.1.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "webpack-dev-server": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz", + "integrity": "sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.2.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.4", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.25", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.4.0", + "spdy": "^4.0.1", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "12.0.5" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "webpack-subresource-integrity": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.3.4.tgz", + "integrity": "sha512-6XbGYzjh30cGQT/NsC+9IAkJP8IL7/t47sbwR5DLSsamiD56Rwv4/+hsgEHsviPvrEFZ0JRAQtCRN3UsR2Pw9g==", + "dev": true, + "requires": { + "webpack-sources": "^1.3.0" + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "when": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", + "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "win-release": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", + "requires": { + "semver": "^5.0.1" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "worker-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-3.2.0.tgz", + "integrity": "sha512-W5nRkw7+HlbsEt3qRP6MczwDDISjiRj2GYt9+bpe8A2La00TmJdwzG5bpdMXhRt1qcWmwAvl1TiKaHRa+XDS9Q==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "requires": { + "buffer-crc32": "~0.2.3" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "zone.js": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", + "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==" + } + } +} diff --git a/form/package.json b/form/package.json new file mode 100644 index 0000000..c9142ed --- /dev/null +++ b/form/package.json @@ -0,0 +1,57 @@ +{ + "name": "ng-template-generator", + "version": "0.0.1", + "scripts": { + "start": "ng serve", + "build": "ng build --build--optimizer --aot --base-href /JGT/v3/", + "publish": "node ./bin/publish.js", + "ng": "ng", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "private": true, + "dependencies": { + "@angular/animations": "~9.0.2", + "@angular/common": "~9.0.2", + "@angular/compiler": "~9.0.2", + "@angular/core": "~9.0.2", + "@angular/forms": "~9.0.2", + "@angular/platform-browser": "~9.0.2", + "@angular/platform-browser-dynamic": "~9.0.2", + "@angular/router": "~9.0.2", + "@fortawesome/angular-fontawesome": "^0.6.0", + "@fortawesome/fontawesome-svg-core": "^1.2.27", + "@fortawesome/free-regular-svg-icons": "^5.12.1", + "@fortawesome/free-solid-svg-icons": "^5.12.1", + "@tweenjs/tween.js": "~18.5.0", + "ali-oss": "^6.5.1", + "compressing": "^1.5.0", + "ng-zorro-antd": "^8.5.2", + "rxjs": "~6.5.4", + "spark-md5": "^3.0.0", + "tslib": "^1.10.0", + "zone.js": "~0.10.2" + }, + "devDependencies": { + "@angular-devkit/build-angular": "~0.900.3", + "@angular/cli": "~9.0.3", + "@angular/compiler-cli": "~9.0.2", + "@angular/language-service": "~9.0.2", + "@types/jasmine": "~3.5.0", + "@types/jasminewd2": "~2.0.3", + "@types/node": "^12.11.1", + "codelyzer": "^5.1.2", + "jasmine-core": "~3.5.0", + "jasmine-spec-reporter": "~4.2.1", + "karma": "~4.3.0", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage-istanbul-reporter": "~2.1.0", + "karma-jasmine": "~2.0.1", + "karma-jasmine-html-reporter": "^1.4.2", + "protractor": "~5.4.3", + "ts-node": "~8.3.0", + "tslint": "~5.18.0", + "typescript": "~3.7.5" + } +} diff --git a/form/src/app/MyError.ts b/form/src/app/MyError.ts new file mode 100644 index 0000000..e1264c7 --- /dev/null +++ b/form/src/app/MyError.ts @@ -0,0 +1,9 @@ + +import { ErrorHandler } from '@angular/core'; + +export class MyErrorHandler implements ErrorHandler { + handleError(error) { + console.log(error.stack); + (<any> window).courseware.sendErrorLog(error); + } +} \ No newline at end of file diff --git a/form/src/app/app.component.html b/form/src/app/app.component.html new file mode 100644 index 0000000..44b4b71 --- /dev/null +++ b/form/src/app/app.component.html @@ -0,0 +1,3 @@ +<app-form *ngIf="type==='form'"></app-form> + +<app-play *ngIf="type==='play'"></app-play> \ No newline at end of file diff --git a/form/src/app/app.component.scss b/form/src/app/app.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/form/src/app/app.component.ts b/form/src/app/app.component.ts new file mode 100644 index 0000000..43e76cf --- /dev/null +++ b/form/src/app/app.component.ts @@ -0,0 +1,29 @@ +import { Component , OnInit} from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent implements OnInit { + type = 'play'; + + constructor() { + const tp = this.getQueryString('type'); + if (tp) { + this.type = tp; + } + } + + ngOnInit() { + + } + getQueryString(name) { + const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i'); + const r = window.location.search.substr(1).match(reg); + if (r != null) { + return unescape(r[2]); + } + return null; + } +} diff --git a/form/src/app/app.module.ts b/form/src/app/app.module.ts new file mode 100644 index 0000000..a0995a7 --- /dev/null +++ b/form/src/app/app.module.ts @@ -0,0 +1,65 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule, ErrorHandler } from '@angular/core'; + +import {MyErrorHandler} from './MyError'; + +import { AppComponent } from './app.component'; +import { NgZorroAntdModule, NZ_I18N, zh_CN } from 'ng-zorro-antd'; +import { FormsModule } from '@angular/forms'; +import { HttpClientModule } from '@angular/common/http'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { registerLocaleData } from '@angular/common'; +import zh from '@angular/common/locales/zh'; +import {FormComponent} from './form/form.component'; +import {PlayComponent} from './play/play.component'; +import {LessonTitleConfigComponent} from './common/lesson-title-config/lesson-title-config.component'; +import {BackgroundImagePipe} from './pipes/background-image.pipe'; +import {UploadImageWithPreviewComponent} from './common/upload-image-with-preview/upload-image-with-preview.component'; +import {PlayerContentWrapperComponent} from './common/player-content-wrapper/player-content-wrapper.component'; +import {CustomHotZoneComponent} from './common/custom-hot-zone/custom-hot-zone.component'; +import {UploadVideoComponent} from './common/upload-video/upload-video.component'; +import {TimePipe} from './pipes/time.pipe'; +import {ResourcePipe} from './pipes/resource.pipe'; +import {AudioRecorderComponent} from './common/audio-recorder/audio-recorder.component'; +import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome'; +import { fas } from '@fortawesome/free-solid-svg-icons'; +import { far } from '@fortawesome/free-regular-svg-icons'; + +registerLocaleData(zh); + +@NgModule({ + declarations: [ + AppComponent, + FormComponent, + PlayComponent, + LessonTitleConfigComponent, + AudioRecorderComponent, + UploadImageWithPreviewComponent, + BackgroundImagePipe, + ResourcePipe, + TimePipe, + UploadVideoComponent, + CustomHotZoneComponent, + + PlayerContentWrapperComponent + + ], + imports: [ + BrowserModule, + NgZorroAntdModule, + FormsModule, + HttpClientModule, + BrowserAnimationsModule, + FontAwesomeModule + ], + providers: [ + {provide: ErrorHandler, useClass: MyErrorHandler}, + { provide: NZ_I18N, useValue: zh_CN } + ], + bootstrap: [AppComponent] +}) +export class AppModule { + constructor(library: FaIconLibrary) { + library.addIconPacks(fas, far); + } +} diff --git a/form/src/app/common/audio-recorder/audio-recorder.component.html b/form/src/app/common/audio-recorder/audio-recorder.component.html new file mode 100644 index 0000000..e174c34 --- /dev/null +++ b/form/src/app/common/audio-recorder/audio-recorder.component.html @@ -0,0 +1,61 @@ +<div class="d-flex"> + <div class="p-btn-record d-flex"> + <div class="btn-clear" style="cursor: pointer" (click)="onBtnClearAudio()" *ngIf="withRmBtn && (audioUrl || audioBlob)"> + <fa-icon icon="times"></fa-icon> + </div> + <div class="btn-record" *ngIf="type===Type.RECORD && !isUploading" + [class.p-recording]="isRecording" + (click)="onBtnRecord()"> + <fa-icon icon="microphone"></fa-icon> + Record Audio + </div> + <nz-upload + [nzAccept] = "'.mp3'" + [nzShowUploadList]="false" + [nzAction]="uploadUrl" + [nzData]="uploadData" + (nzChange)="handleChange($event)"> + + <div class="btn-upload" [ngClass]="{'has-clear': withRmBtn && (audioUrl || audioBlob)}" *ngIf="type===Type.UPLOAD && !isUploading"> + <fa-icon icon="upload"></fa-icon> + Upload Audio + </div> + </nz-upload> + <div class="p-upload-progress-bg" *ngIf="isUploading"> + <div class="i-bg" [style.width]="progress+'%'"></div> + <div class="i-text"> + <fa-icon icon="cloud-upload-alt"></fa-icon> + Uploading... + </div> + </div> + + + <div *ngIf="audioUrl && needRemove; then truthyTemplate else falsyTemplate"></div> + + <ng-template #truthyTemplate > + + <div class="btn-delete" (click)="onBtnDeleteAudio()"> + <fa-icon icon="close"></fa-icon> + </div> + + </ng-template> + + <ng-template #falsyTemplate> + <div class="btn-switch" (click)="onBtnSwitchType()"> + <fa-icon icon="cog"></fa-icon> + </div> + </ng-template> + + + + + </div> + + <div class="p-progress ml-2" (click)="onBtnPlay()" *ngIf="audioUrl || audioBlob"> + <nz-progress [nzPercent]="percent" [nzWidth]="30" [nzFormat]="progressText" + nzType="circle"></nz-progress> + <div class="p-btn-play" [style.left]="isPlaying?'8px':''"> + <fa-icon [icon]="playIcon"></fa-icon> + </div> + </div> +</div> diff --git a/form/src/app/common/audio-recorder/audio-recorder.component.scss b/form/src/app/common/audio-recorder/audio-recorder.component.scss new file mode 100644 index 0000000..8267c9d --- /dev/null +++ b/form/src/app/common/audio-recorder/audio-recorder.component.scss @@ -0,0 +1,107 @@ +.d-flex{ + display: flex; +} +.p-btn-record { + font-size: 0.9rem; + color: #555; + font-family: "Monospaced Number", "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; + + .btn-record, .btn-upload { + cursor: pointer; + text-align: center; + width: 130px; + height: 33px; + line-height: 33px; + border-radius: 0.5rem 0 0 0.5rem; + border: 1px solid #ddd; + border-right: 0.5px; + &:hover { + color: rgb(64, 169, 255); + } + } + .btn-record.has-clear, .btn-upload.has-clear{ + border-radius:0; + border-left: 0; + } + .btn-clear{ + text-align: center; + color: #aaa; + padding: 0 0.5rem; + border: 1px solid #ddd; + border-radius: 0.5rem 0 0 0.5rem; + height: 33px; + line-height: 33px; + } + .btn-switch { + text-align: center; + color: #aaa; + padding: 0 0.5rem; + border: 1px solid #ddd; + border-radius: 0 0.5rem 0.5rem 0; + height: 33px; + line-height: 33px; + &:hover { + color: rgb(64, 169, 255); + } + } + .btn-delete { + text-align: center; + color: #aaa; + padding: 0 0.5rem; + border: 1px solid #ddd; + border-radius: 0 0.5rem 0.5rem 0; + height: 33px; + line-height: 33px; + &:hover { + color: #ec5b56; + } + } +} + +.p-recording { + background: orangered; + color: white !important; +} + +.p-upload-progress-bg { + position: relative; + width: 130px; + height: 33px; + line-height: 33px; + & .i-text { + position: absolute; + width: 100%; + height: 100%; + text-align: center; + border-radius: 0.5rem 0 0 0.5rem; + border: 1px solid #ddd; + border-right: 0.5px; + color: white; + text-shadow: 0 0 2px rgba(0, 0, 0, .85); + } + & .i-bg { + position: absolute; + left: 0; + top: 0; + height: 100%; + background-color: #27b43f; + border-radius: 0.5rem 0 0 0.5rem; + } +} + +.p-progress { + margin-top: 2px; + position: relative; + line-height: 26px; + .p-btn-play { + position: absolute; + left: 10px; + top: 3px; + color: #555; + } +} + +:host ::ng-deep nz-upload { + line-height: 33px; +} + diff --git a/form/src/app/common/audio-recorder/audio-recorder.component.ts b/form/src/app/common/audio-recorder/audio-recorder.component.ts new file mode 100644 index 0000000..605db0a --- /dev/null +++ b/form/src/app/common/audio-recorder/audio-recorder.component.ts @@ -0,0 +1,234 @@ +import {Component, EventEmitter, Input, OnDestroy, OnInit, Output, NgZone, OnChanges} from '@angular/core'; +import {NzMessageService, NzNotificationService, UploadFile} from 'ng-zorro-antd'; +import {HttpClient, HttpEvent, HttpEventType, HttpRequest} from '@angular/common/http'; +import {environment} from '../../../environments/environment'; + +declare var Recorder; + +@Component({ + selector: 'app-audio-recorder', + templateUrl: './audio-recorder.component.html', + styleUrls: ['./audio-recorder.component.scss'] +}) +export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { + _audioUrl: string; + audio = new Audio(); + playIcon = 'play'; + isPlaying = false; + isRecording = false; + isUploading = false; + type = Type.UPLOAD; // record | upload + Type = Type; + @Input() + withRmBtn = false; + + uploadUrl; + uploadData; + + @Input() + needRemove = false; + + @Input() + audioItem: any = null; + + @Input() + set audioUrl(url) { + this._audioUrl = url; + if (url) { + this.audio.src = this._audioUrl; + this.audio.load(); + } + this.init(); + } + + get audioUrl() { + return this._audioUrl; + } + + @Output() audioUploaded = new EventEmitter(); + @Output() audioUploadFailure = new EventEmitter(); + @Output() audioRemoved = new EventEmitter(); + percent = 0; + progress = 0; + recorder: any; + audioBlob: any; + + + constructor( private nzMessageService: NzMessageService ) { + this.uploadUrl = (<any> window).courseware.uploadUrl(); + this.uploadData = (<any> window).courseware.uploadData(); + + window['air'].getUploadCallback = (url, data) => { + this.uploadUrl = url; + this.uploadData = data; + }; + } + + init() { + this.playIcon = 'play'; + this.isPlaying = false; + this.isRecording = false; + this.isUploading = false; + this.percent = 0; + this.progress = 0; + this.audioBlob = null; + } + ngOnChanges() { + // if (!this.audioItem || !this.audioItem.type) { + // return; + // } + // this.beforeUpload(this.audioItem); + } + ngOnInit() { + + this.audio.onplay = () => { + this.onPlay(); + }; + this.audio.onpause = () => { + this.onPause(); + }; + this.audio.ontimeupdate = (event) => { + this.onTimeUpdate(event); + }; + this.audio.onended = (event) => { + this.onEnded(); + }; + } + + ngOnDestroy() { + this.audio.pause(); + this.isPlaying = false; + this.audio.remove(); + // if (this.recorder.worker) { + // this.recorder.worker.terminate(); + // } + } + + progressText(percent) { + return ``; + } + + onPlay() { + console.log('play'); + this.playIcon = 'pause'; + this.isPlaying = true; + } + + onPause() { + console.log('pause'); + this.playIcon = 'play'; + this.isPlaying = false; + } + + onEnded() { + console.log('on end'); + this.playIcon = 'play'; + this.percent = 0; + this.isPlaying = false; + } + + onTimeUpdate(event) { + this.percent = Math.floor((this.audio.currentTime / this.audio.duration) * 100); + } + + onBtnPlay() { + if (this.isRecording) { + this.nzMessageService.warning('In Recording'); + return; + } + if (this.isPlaying) { + this.audio.pause(); + } else { + this.audio.play(); + } + } + + // 开始录音 + onBtnRecord = () => { + } + + // åˆ‡æ¢æ¨¡å¼ + onBtnSwitchType() { + } + onBtnClearAudio() { + this.audioUrl = null; + this.audioRemoved.emit(); + } + + onBtnDeleteAudio() { + this.audioUrl = null; + this.audioRemoved.emit(); + } + + handleChange(info: { type: string, file: UploadFile, event: any }): void { + switch (info.type) { + case 'start': + this.isUploading = true; + this.progress = 0; + break; + case 'success': + this.isUploading = false; + this.uploadSuccess(info.file.response); + this.audioUploaded.emit(info.file.response); + break; + case 'progress': + this.progress = parseInt(info.event.percent, 10); + break; + } + } + checkSelectFile(file: any) { + if (!file) { + return; + } + const isAudio = ['audio/mp3', 'audio/wav', 'audio/ogg'].includes(file.type); + if (!isAudio) { + this.nzMessageService.error('You can only upload Audio file ( mp3 | wav |ogg)'); + return; + } + const delta = 25; + const isOverSize = (file.size / 1024 / 1024) < delta; + if (!isOverSize) { + this.nzMessageService.error(`audio file must smaller than ${delta}MB!`); + return false; + } + return true; + } + beforeUpload = (file: File) => { + + this.audioUrl = null; + if (!this.checkSelectFile(file)) { + return false; + } + this.isUploading = true; + this.progress = 0; + } + uploadSuccess = (url) => { + this.nzMessageService.info('Upload Success'); + this.isUploading = false; + this.audioUrl = url; + } + uploadFailure = (err, file) => { + this.isUploading = false; + if (err.name && err.name === 'cancel') { + return; + } + console.log(err); + this.nzMessageService.error('Upload Error ' + err.message); + this.audioUploadFailure.emit(file); + } + doProgress = (p) => { + if (p > 1) { + p = 1; + } + if (p < 0) { + p = 0; + } + // console.log(Math.floor(p * 100)); + this.progress = Math.floor(p * 100); + } + +} + +enum Type { + RECORD = 1, UPLOAD +} diff --git a/form/src/app/common/custom-hot-zone/Unit.ts b/form/src/app/common/custom-hot-zone/Unit.ts new file mode 100644 index 0000000..7b99189 --- /dev/null +++ b/form/src/app/common/custom-hot-zone/Unit.ts @@ -0,0 +1,3108 @@ + +import TWEEN from '@tweenjs/tween.js'; + +interface AirWindow extends Window { + air: any; + curCtx: any; +} +declare let window: AirWindow; + +class Sprite { + x = 0; + y = 0; + color = ''; + radius = 0; + alive = false; + margin = 0; + angle = 0; + ctx; + + constructor(ctx = null) { + if (!ctx) { + this.ctx = window.curCtx; + } else { + this.ctx = ctx; + } + } + update($event) { + this.draw(); + } + draw() { + + } + +} + + + + + +export class MySprite extends Sprite { + + _width = 0; + _height = 0; + _anchorX = 0; + _anchorY = 0; + _offX = 0; + _offY = 0; + scaleX = 1; + scaleY = 1; + _alpha = 1; + rotation = 0; + visible = true; + skewX = 0; + skewY = 0; + + _shadowFlag = false; + _shadowColor; + _shadowOffsetX = 0; + _shadowOffsetY = 0; + _shadowBlur = 5; + + _radius = 0; + + children = [this]; + + childDepandVisible = true; + childDepandAlpha = false; + + img; + _z = 0; + + _showRect; + + + _bitmapFlag = false; + _offCanvas; + _offCtx; + + + init(imgObj = null, anchorX: number = 0.5, anchorY: number = 0.5) { + + if (imgObj) { + + this.img = imgObj; + + this.width = this.img.width; + this.height = this.img.height; + + + } + + this.anchorX = anchorX; + this.anchorY = anchorY; + } + + + setShowRect(rect) { + this._showRect = rect; + } + + setShadow(offX, offY, blur, color = 'rgba(0, 0, 0, 0.3)') { + + + this._shadowFlag = true; + this._shadowColor = color; + this._shadowOffsetX = offX; + this._shadowOffsetY = offY; + this._shadowBlur = blur; + + } + + setRadius(r) { + this._radius = r; + } + + + + + update($event = null) { + if (!this.visible && this.childDepandVisible) { + return; + } + + this.draw(); + + } + draw() { + + this.ctx.save(); + + this.drawInit(); + + this.updateChildren(); + + this.ctx.restore(); + + + } + + drawInit() { + + this.ctx.translate(this.x, this.y); + + this.ctx.rotate(this.rotation * Math.PI / 180); + + this.ctx.scale(this.scaleX, this.scaleY); + + this.ctx.globalAlpha = this.alpha; + + this.ctx.transform(1, this.skewX, this.skewY, 1, 0, 0); + + + + + // + // if (this._radius) { + // + // const r = this._radius; + // const w = this.width; + // const h = this.height; + // + // this.ctx.lineTo(-w / 2, h / 2); // 创建水平线 + // this.ctx.arcTo(-w / 2, -h / 2, -w / 2 + r, -h / 2, r); + // this.ctx.arcTo(w / 2, -h / 2, w / 2, -h / 2 + r, r); + // this.ctx.arcTo(w / 2, h / 2, w / 2 - r, h / 2, r); + // this.ctx.arcTo(-w / 2, h / 2, -w / 2, h / 2 - r, r); + // + // this.ctx.clip(); + // } + + } + + drawSelf() { + + + + if (this._shadowFlag) { + + this.ctx.shadowOffsetX = this._shadowOffsetX; + this.ctx.shadowOffsetY = this._shadowOffsetY; + this.ctx.shadowBlur = this._shadowBlur; + this.ctx.shadowColor = this._shadowColor; + } else { + this.ctx.shadowOffsetX = 0; + this.ctx.shadowOffsetY = 0; + this.ctx.shadowBlur = null; + this.ctx.shadowColor = null; + } + + + if (this.img) { + + if (this._showRect) { + const rect = this._showRect; + this.ctx.drawImage(this.img, rect.x, rect.y, rect.width, rect.height, this._offX, this._offY + rect.y, this.width, rect.height); + } else { + this.ctx.drawImage(this.img, this._offX, this._offY); + } + } + + + + + } + + updateChildren() { + + if (this.children.length <= 0) { return; } + + for (const child of this.children) { + if (child === this) { + if (this.visible) { + this.drawSelf(); + } + } else { + child.update(); + } + } + } + + + load(url, anchorX = 0.5, anchorY = 0.5) { + + return new Promise((resolve, reject) => { + const img = new Image(); + img.onload = () => resolve(img); + img.onerror = reject; + img.src = url; + }).then(img => { + + this.init(img, anchorX, anchorY); + return img; + }); + } + + addChild(child, z = 1) { + if (this.children.indexOf(child) === -1) { + this.children.push(child); + child._z = z; + child.parent = this; + } + + this.children.sort((a, b) => { + return a._z - b._z; + }); + + + if (this.childDepandAlpha) { + child.alpha = this.alpha; + } + + } + removeChild(child) { + const index = this.children.indexOf(child); + if (index !== -1) { + this.children.splice(index, 1); + } + } + + removeChildren() { + for (let i = 0; i < this.children.length; i++) { + if (this.children[i]) { + if (this.children[i] !== this) { + this.children.splice(i, 1); + i --; + } + } + } + } + + _changeChildAlpha(alpha) { + for (const child of this.children) { + if (child !== this) { + child.alpha = alpha; + } + } + } + + + set btimapFlag(v) { + this._bitmapFlag = v; + } + get btimapFlag() { + return this._bitmapFlag; + } + set alpha(v) { + this._alpha = v; + if (this.childDepandAlpha) { + this._changeChildAlpha(v); + } + } + get alpha() { + return this._alpha; + } + set width(v) { + this._width = v; + this.refreshAnchorOff(); + } + get width() { + return this._width; + } + set height(v) { + this._height = v; + this.refreshAnchorOff(); + } + get height() { + return this._height; + } + set anchorX(value) { + this._anchorX = value; + this.refreshAnchorOff(); + } + get anchorX() { + return this._anchorX; + } + set anchorY(value) { + this._anchorY = value; + this.refreshAnchorOff(); + } + get anchorY() { + return this._anchorY; + } + refreshAnchorOff() { + this._offX = -this._width * this.anchorX; + this._offY = -this._height * this.anchorY; + } + + setScaleXY(value) { + this.scaleX = this.scaleY = value; + } + + getBoundingBox() { + + const getParentData = (item) => { + + let px = item.x; + let py = item.y; + + let sx = item.scaleX; + let sy = item.scaleY; + const parent = item.parent; + if (parent) { + + const obj = getParentData(parent); + + const _x = obj.px; + const _y = obj.py; + const _sx = obj.sx; + const _sy = obj.sy; + + px = _x + item.x * _sx; + py = _y + item.y * _sy; + + sx *= _sx; + sy *= _sy; + + } + + return {px, py, sx, sy}; + }; + + + const data = getParentData(this); + + + const x = data.px + this._offX * Math.abs(data.sx); + const y = data.py + this._offY * Math.abs(data.sy); + const width = this.width * Math.abs(data.sx); + const height = this.height * Math.abs(data.sy); + + return {x, y, width, height}; + } + +} + + +export class RoundSprite extends MySprite { + + _newCtx; + + init(imgObj = null, anchorX: number = 0.5, anchorY: number = 0.5) { + + if (imgObj) { + + this.img = imgObj; + + this.width = this.img.width; + this.height = this.img.height; + + + } + + this.anchorX = anchorX; + this.anchorY = anchorY; + + const canvas = window['curCanvas']; + const w = canvas.nativeElement.width; + const h = canvas.nativeElement.height; + + + this._offCanvas = document.createElement('canvas'); + this._offCanvas.width = w; + this._offCanvas.height = h; + + this._offCtx = this._offCanvas.getContext('2d'); + + // this._newCtx = this.ctx; + // this.ctx = this._offCtx; + + } + + + + drawSelf() { + // + // if (this._shadowFlag) { + // + // this.ctx.shadowOffsetX = this._shadowOffsetX; + // this.ctx.shadowOffsetY = this._shadowOffsetY; + // this.ctx.shadowBlur = this._shadowBlur; + // this.ctx.shadowColor = this._shadowColor; + // } else { + // this.ctx.shadowOffsetX = 0; + // this.ctx.shadowOffsetY = 0; + // this.ctx.shadowBlur = null; + // this.ctx.shadowColor = null; + // } + + + if (this._radius) { + + const r = this._radius; + const w = this.width; + const h = this.height; + const x = -this._offX; + const y = -this._offY; + + this._offCtx.lineTo(x - w / 2, y + h / 2); // 创建水平线 + this._offCtx.arcTo(x - w / 2, y - h / 2, x - w / 2 + r, y - h / 2, r); + this._offCtx.arcTo(x + w / 2, y - h / 2, x + w / 2, y - h / 2 + r, r); + this._offCtx.arcTo(x + w / 2, y + h / 2, x + w / 2 - r, y + h / 2, r); + this._offCtx.arcTo(x - w / 2, y + h / 2, x - w / 2, y + h / 2 - r, r); + + this._offCtx.clip(); + } + + + if (this.img) { + + this._offCtx.drawImage(this.img, 0, 0); + this.ctx.drawImage(this._offCanvas,this._offX, this._offX); + } + + } +} + + + + + +export class ColorSpr extends MySprite { + + r = 0; + g = 0; + b = 0; + + createGSCanvas() { + + if (!this.img) { + return; + } + + + + const rect = this.getBoundingBox(); + if (rect.width <= 1 || rect.height <= 1) { + return; + } + + + const c = this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height); + for ( let i = 0; i < c.height; i++) { + for ( let j = 0; j < c.width; j++) { + + const x = (i * 4) * c.width + ( j * 4 ); + const r = c.data[x]; + const g = c.data[x + 1]; + const b = c.data[x + 2]; + + c.data[x] = this.r; + c.data[x + 1] = this.g; + c.data[x + 2] = this.b; + + + + // c.data[x] = c.data[x + 1] = c.data[x + 2] = (r + g + b) / 3 ; + // // c.data[x + 3] = 255; + } + } + + this.ctx.putImageData(c, rect.x, rect.y, 0, 0, rect.width, rect.height); + } + + + drawSelf() { + super.drawSelf(); + this.createGSCanvas(); + } + +} + + +export class GrayscaleSpr extends MySprite { + + grayScale = 120; + + createGSCanvas() { + + if (!this.img) { + return; + } + + + + const rect = this.getBoundingBox(); + + const c = this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height); + for ( let i = 0; i < c.height; i++) { + for ( let j = 0; j < c.width; j++) { + + const x = (i * 4) * c.width + ( j * 4 ); + const r = c.data[x]; + const g = c.data[x + 1]; + const b = c.data[x + 2]; + // const a = c.data[x + 3]; + + c.data[x] = c.data[x + 1] = c.data[x + 2] = this.grayScale; // (r + g + b) / 3; + // c.data[x + 3] = 255; + } + } + + this.ctx.putImageData(c, rect.x, rect.y, 0, 0, rect.width, rect.height); + } + + + drawSelf() { + super.drawSelf(); + this.createGSCanvas(); + } + +} + + + + + + +export class BitMapLabel extends MySprite { + + + labelArr; + baseUrl; + + setText(data, text) { + + this.labelArr = []; + + const labelArr = []; + const tmpArr = text.split(''); + let totalW = 0; + let h = 0; + for (const tmp of tmpArr) { + + const label = new MySprite(this.ctx); + label.init(data[tmp], 0); + this.addChild(label); + labelArr.push(label); + + totalW += label.width; + h = label.height; + } + + + this.width = totalW; + this.height = h; + + let offX = -totalW / 2; + for (const label of labelArr) { + label.x = offX; + offX += label.width; + } + + this.labelArr = labelArr; + } + +} + + + + +export class Label extends MySprite { + private _text: string; + + // fontSize:String = '40px'; + fontName = 'Verdana'; + textAlign = 'left'; + fontSize = 40; + fontColor = '#000000'; + fontWeight = 900; + _maxWidth; + outline = 0; + outlineColor = '#ffffff'; + // _shadowFlag = false; + // _shadowColor; + // _shadowOffsetX; + // _shadowOffsetY; + // _shadowBlur; + + _outlineFlag = false; + + _outLineWidth; + _outLineColor; + constructor(ctx = null) { + super(ctx); + this.init(); + } + + + get text(): string { + return this._text; + } + + set text(value: string) { + this._text = value; + this.refreshSize(); + } + + refreshSize() { + + this.ctx.save(); + + this.ctx.font = `${this.fontSize * this.scaleX}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = this.fontWeight; + + this._width = this.ctx.measureText(this.text).width; + this._height = this.fontSize; + this.refreshAnchorOff(); + + this.ctx.restore(); + + } + + setMaxSize(w) { + + this._maxWidth = w; + this.refreshSize(); + if (this.width >= w) { + this.scaleX *= w / this.width; + this.scaleY *= w / this.width; + } + } + + show(callBack = null) { + + this.visible = true; + + if (this.alpha >= 1) { + return; + } + + const tween = new TWEEN.Tween(this) + .to({ alpha: 1 }, 800) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }) + .start(); // Start the tween immediately. + } + + setOutline(width = 5, color = '#ffffff') { + + this._outlineFlag = true; + this._outLineWidth = width; + this._outLineColor = color; + + } + + drawText() { + + + if (!this.text) { return; } + + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = this.fontWeight; + + if (this._outlineFlag) { + this.ctx.lineWidth = this._outLineWidth; + this.ctx.strokeStyle = this._outLineColor; + this.ctx.strokeText(this.text, 0, 0); + } + + this.ctx.fillStyle = this.fontColor; + + + + if (this.outline > 0) { + this.ctx.lineWidth = this.outline; + this.ctx.strokeStyle = this.outlineColor; + this.ctx.strokeText(this.text, 0, 0); + + } + + this.ctx.fillText(this.text, 0, 0); + + + } + + + drawSelf() { + super.drawSelf(); + this.drawText(); + } + +} + +export class RichTextOld extends Label { + + textArr = []; + fontSize = 40; + + setText(text: string, words) { + + let newText = text; + for (const word of words) { + + const re = new RegExp(word, 'g'); + newText = newText.replace( re, `#${word}#`); + // newText = newText.replace(word, `#${word}#`); + } + + this.textArr = newText.split('#'); + this.text = newText; + + // this.setSize(); + } + + refreshSize() { + + this.ctx.save(); + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = this.fontWeight; + + let curX = 0; + for (const text of this.textArr) { + const w = this.ctx.measureText(text).width; + curX += w; + } + + this.width = curX; + this.height = this.fontSize; + this.refreshAnchorOff(); + + this.ctx.restore(); + + } + + + show(callBack = null) { + + // console.log(' in show '); + this.visible = true; + // this.alpha = 0; + + const tween = new TWEEN.Tween(this) + .to({ alpha: 1 }, 800) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }) + .start(); // Start the tween immediately. + + } + + + + drawText() { + + // console.log('in drawText', this.text); + + if (!this.text) { return; } + + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = 900; + + this.ctx.lineWidth = 5; + this.ctx.strokeStyle = '#ffffff'; + // this.ctx.strokeText(this.text, 0, 0); + + this.ctx.fillStyle = '#000000'; + // this.ctx.fillText(this.text, 0, 0); + + + let curX = 0; + for (let i = 0; i < this.textArr.length; i++) { + + const w = this.ctx.measureText(this.textArr[i]).width; + + if ((i + 1) % 2 === 0) { + this.ctx.fillStyle = '#c8171e'; + } else { + this.ctx.fillStyle = '#000000'; + } + + this.ctx.fillText(this.textArr[i], curX, 0); + curX += w; + + } + + + } + +} + + + + + +export class RichText extends Label { + + + disH = 30; + + constructor(ctx?: any) { + super(ctx); + + // this.dataArr = dataArr; + } + + + + drawText() { + + if (!this.text) { + return; + } + + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = this.fontWeight; + this.ctx.fillStyle = this.fontColor; + + + const selfW = this.width * this.scaleX; + + + const chr = this.text.split(' '); + let temp = ''; + const row = []; + const w = selfW - 80; + const disH = (this.fontSize + this.disH) * this.scaleY; + + + + + for (const c of chr) { + if (this.ctx.measureText(temp).width < w && this.ctx.measureText(temp + (c)).width <= w) { + temp += ' ' + c; + } else { + row.push(temp); + temp = ' ' + c; + } + } + row.push(temp); + + const x = 0; + const y = -row.length * disH / 2; + // for (let b = 0 ; b < row.length; b++) { + // this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // æ¯è¡Œå—体yåæ ‡é—´éš”20 + // } + + + if (this._outlineFlag) { + this.ctx.lineWidth = this._outLineWidth; + this.ctx.strokeStyle = this._outLineColor; + for (let b = 0 ; b < row.length; b++) { + this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // æ¯è¡Œå—体yåæ ‡é—´éš”20 + } + // this.ctx.strokeText(this.text, 0, 0); + } + + + // this.ctx.fillStyle = '#ff7600'; + for (let b = 0 ; b < row.length; b++) { + this.ctx.fillText(row[b], x, y + ( b + 1 ) * disH ); // æ¯è¡Œå—体yåæ ‡é—´éš”20 + } + + } + + + drawSelf() { + super.drawSelf(); + this.drawText(); + } + +} + + + + +export class LineRect extends MySprite { + + lineColor = '#ffffff'; + lineWidth = 10; + + setSize(w, h) { + this.width = w; + this.height = h; + } + + drawLine() { + + this.ctx.beginPath(); + this.ctx.moveTo(this._offX, this._offY); + this.ctx.lineTo(this._offX + this.width, this._offY); + this.ctx.lineTo(this._offX + this.width, this._offY + this.height); + this.ctx.lineTo(this._offX, this._offY + this.height); + this.ctx.closePath(); + + this.ctx.lineWidth = this.lineWidth; + // this.ctx.fillStyle = "rgb(2,33,42)"; //指定填充颜色 + // this.ctx.fill(); //对多边形进行填充 + + this.ctx.strokeStyle = this.lineColor; // "#ffffff"; + this.ctx.stroke(); + + } + + + drawSelf() { + super.drawSelf(); + this.drawLine(); + } +} + + +export class ShapeRect extends MySprite { + + fillColor = '#FF0000'; + + setSize(w, h) { + this.width = w; + this.height = h; + + // console.log('w:', w); + // console.log('h:', h); + } + + drawShape() { + + this.ctx.fillStyle = this.fillColor; + this.ctx.fillRect(this._offX, this._offY, this.width, this.height); + + } + + + drawSelf() { + super.drawSelf(); + this.drawShape(); + } +} + + + +export class Line extends MySprite { + + + lineWidth = 5; + lineColor = '#000000'; + _pointArr = []; + + roundFlag = true; + + _pointS = 1; + + + imgObj; + bitMap; + _offCtx; + _offCanvas; + + lastPointIndex = 0; + + init() { + + const canvas = window['curCanvas']; + const w = canvas.nativeElement.width; + const h = canvas.nativeElement.height; + + console.log('w: ', w); + console.log('h: ', h); + + + this._offCanvas = document.createElement('canvas'); + this._offCanvas.width = w; + this._offCanvas.height = h; + // this._offCanvas = _offCanvas; + // this._offCtx = this._offCanvas.getContext('2d'); + + + // this._offCanvas = new OffscreenCanvas(w, h); + this._offCtx = this._offCanvas.getContext('2d'); + } + + addPoint(x, y) { + + this._pointArr.push([x, y]); + + if (this._pointArr.length < 2) { + return; + } + // + // const lastP = this._pointArr[this._pointArr.length - 1]; + // + // + // const context = this._offCtx; + // context.moveTo (lastP[0], lastP[1]); // è®¾ç½®èµ·ç‚¹çŠ¶æ€ + // context.lineTo (x, y); // è®¾ç½®æœ«ç«¯çŠ¶æ€ + // + // context.lineWidth = this.lineWidth; //è®¾ç½®çº¿å®½çŠ¶æ€ + // context.strokeStyle = this.lineColor; + // context.stroke(); + // + // + // this.bitMap = this._offCanvas.transferToImageBitmap(); + + + + // const tmpLine = new MySprite(this._offCtx); + // tmpLine.init(this.imgObj); + // tmpLine.anchorY = 1; + // tmpLine.anchorX = 0.5; + // tmpLine.x = lastP[0]; + // tmpLine.y = lastP[1]; + // + // const disH = getPosDistance(lastP[0], lastP[1], x, y); + // tmpLine.scaleX = this.lineWidth / tmpLine.width; + // tmpLine.scaleY = disH / tmpLine.height * 1.1; + // + // const angle = getAngleByPos(lastP[0], lastP[1], x, y); + // tmpLine.rotation = angle; + // + // this.addChild(tmpLine); + + } + + setPointArr(arr, imgObj) { + + this.removeChildren(); + + if (arr.length < 2) { + return; + } + + let p1 = arr[0]; + let p2; + for (let i = 1; i < arr.length; i++) { + + p2 = arr[i]; + + const tmpLine = new MySprite(); + tmpLine.init(imgObj); + tmpLine.anchorY = 1; + tmpLine.anchorX = 0.5; + tmpLine.x = p1[0]; + tmpLine.y = p1[1]; + + const disH = getPosDistance(p1[0], p1[1], p2[0], p2[1]); + tmpLine.scaleX = this.lineWidth / tmpLine.width; + tmpLine.scaleY = disH / tmpLine.height * 1.1; + + const angle = getAngleByPos(p1[0], p1[1], p2[0], p2[1]); + tmpLine.rotation = angle; + + this.addChild(tmpLine); + + p1 = p2; + } + } + + + + + drawLine() { + + if (this._pointArr.length < 2) { + return; + } + + + const curMaxPointIndex = this._pointArr.length - 1; + if (curMaxPointIndex > this.lastPointIndex) { + + const arr = this._pointArr; + + const context = this._offCtx; + context.moveTo (arr[this.lastPointIndex][0] * this._pointS, arr[this.lastPointIndex][1] * this._pointS); // è®¾ç½®èµ·ç‚¹çŠ¶æ€ + for (let i = this.lastPointIndex + 1; i < arr.length; i++) { + context.lineTo (arr[i][0] * this._pointS, arr[i][1] * this._pointS); // è®¾ç½®æœ«ç«¯çŠ¶æ€ + } + + if (this.roundFlag) { + context.lineCap = "round"; + } + context.lineWidth = this.lineWidth; //è®¾ç½®çº¿å®½çŠ¶æ€ + context.strokeStyle = this.lineColor; + context.stroke(); + + + this.lastPointIndex = curMaxPointIndex; + + // this.bitMap = this._offCanvas.transferToImageBitmap(); + + } + + + // this.ctx.drawImage(this.bitMap, this._offX, this._offY); + this.ctx.drawImage(this._offCanvas, this._offX, this._offY); + + } + + drawSelf() { + super.drawSelf(); + this.drawLine(); + + + // if (this.img) { + // this.ctx.drawImage(this._offCanvas, 0, 0, this.width, this.height); + // } + + // if (this.bitMap) { + // this.bitMap = this._offCanvas.transferToImageBitmap(); + // this.ctx.drawImage(this.bitMap, 0, 0, this.width, this.height); + // } + + } +} + + +export class ShapeCircle extends MySprite { + + fillColor = '#FF0000'; + radius = 0; + + + setRadius(r) { + this.anchorX = this.anchorY = 0.5; + + this.radius = r; + this.width = r * 2; + this.height = r * 2; + } + + drawShape() { + + this.ctx.beginPath(); + this.ctx.fillStyle = this.fillColor; + this.ctx.arc(0, 0, this.radius, 0, angleToRadian(360)); + this.ctx.fill(); + } + + drawSelf() { + super.drawSelf(); + this.drawShape(); + } +} + + + + +export class ShapeRectNew extends MySprite { + + + radius = 0; + fillColor = '#ffffff'; + strokeColor = '#000000'; + fill = true; + stroke = false; + lineWidth = 1; + + setSize(w, h, r) { + this.width = w; + this.height = h; + this.radius = r; + } + + setOutLine(color, lineWidth) { + this.stroke = true; + this.strokeColor = color; + this.lineWidth = lineWidth; + } + + + drawShape() { + + const ctx = this.ctx; + const width = this.width; + const height = this.height; + const radius = this.radius; + + ctx.save(); + ctx.beginPath(0); + // 从å³ä¸‹è§’顺时针绘制,弧度从0到1/2PI + ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2); + + // 矩形下边线 + ctx.lineTo(radius, height); + + // 左下角圆弧,弧度从1/2PI到PI + ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI); + + // 矩形左边线 + ctx.lineTo(0, radius); + + // 左上角圆弧,弧度从PI到3/2PI + ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2); + + // 上边线 + ctx.lineTo(width - radius, 0); + + // å³ä¸Šè§’圆弧 + ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2); + + // å³è¾¹çº¿ + ctx.lineTo(width, height - radius); + ctx.closePath(); + + if (this.fill) { + ctx.fillStyle = this.fillColor; + ctx.fill(); + } + if (this.stroke) { + ctx.lineWidth = this.lineWidth; + ctx.strokeStyle = this.strokeColor; + ctx.stroke(); + } + ctx.restore(); + + } + + + drawSelf() { + super.drawSelf(); + this.drawShape(); + } + +} +export class MyAnimation extends MySprite { + + + frameArr = []; + frameIndex = 0; + playFlag = false; + lastDateTime; + curDelay = 0; + + + loop = false; + playEndFunc; + delayPerUnit = 1; + + restartFlag = false; + reverseFlag = false; + + addFrameByImg(img) { + + const spr = new MySprite(this.ctx); + spr.init(img); + this._refreshSize(img); + + spr.visible = false; + + this.addChild(spr); + this.frameArr.push(spr); + + this.frameArr[this.frameIndex].visible = true; + } + + addFrameByUrl(url) { + + const spr = new MySprite(this.ctx); + spr.load(url).then(img => { + + this._refreshSize(img); + }); + spr.visible = false; + + this.addChild(spr); + this.frameArr.push(spr); + + this.frameArr[this.frameIndex].visible = true; + } + + _refreshSize(img: any) { + + if (this.width < img.width) { + this.width = img.width; + } + if (this.height < img.height) { + this.height = img.height; + } + } + + + + play() { + this.playFlag = true; + this.lastDateTime = new Date().getTime(); + } + + stop() { + this.playFlag = false; + } + + + replay() { + this.restartFlag = true; + this.play(); + } + + + reverse() { + this.reverseFlag = !this.reverseFlag; + this.frameArr.reverse(); + this.frameIndex = 0; + } + + showAllFrame() { + for (const frame of this.frameArr ) { + frame.alpha = 1; + } + } + + hideAllFrame() { + for (const frame of this.frameArr) { + frame.alpha = 0; + } + } + + + playEnd() { + + this.playFlag = false; + this.curDelay = 0; + + this.frameArr[this.frameIndex].visible = true; + + if (this.playEndFunc) { + this.playEndFunc(); + this.playEndFunc = null; + } + } + + updateFrame() { + if (this.frameArr[this.frameIndex]) { + this.frameArr[this.frameIndex].visible = false; + } + + this.frameIndex ++; + if (this.frameIndex >= this.frameArr.length) { + if (this.loop) { + this.frameIndex = 0; + } else if (this.restartFlag) { + this.restartFlag = false; + this.frameIndex = 0; + } else { + this.frameIndex -- ; + this.playEnd(); + return; + } + } + + this.frameArr[this.frameIndex].visible = true; + + } + + + + + _updateDelay(delay) { + + this.curDelay += delay; + if (this.curDelay < this.delayPerUnit) { + return; + } + this.curDelay -= this.delayPerUnit; + this.updateFrame(); + } + + _updateLastDate() { + if (!this.playFlag) { return; } + + let delay = 0; + if (this.lastDateTime) { + delay = (new Date().getTime() - this.lastDateTime) / 1000; + } + this.lastDateTime = new Date().getTime(); + this._updateDelay(delay); + } + + update($event: any = null) { + super.update($event); + this._updateLastDate(); + } + + +} + + + + +// --------=========== util func =============------------- + + +export function tweenChange(item, obj, time = 0.8, callBack = null, easing = null, update = null) { + + const tween = new TWEEN.Tween(item).to(obj, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + if (update) { + tween.onUpdate( (a, b) => { + update(a, b); + }); + } + + tween.start(); + return tween; +} + + + + +export function rotateItem(item, rotation, time = 0.8, callBack = null, easing = null) { + + const tween = new TWEEN.Tween(item).to({ rotation }, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + + +export function scaleItem(item, scale, time = 0.8, callBack = null, easing = null) { + + const tween = new TWEEN.Tween(item).to({ scaleX: scale, scaleY: scale}, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + + tween.start(); + return tween; +} + + +export function moveItem(item, x, y, time = 0.8, callBack = null, easing = null) { + + const tween = new TWEEN.Tween(item).to({ x, y}, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + + tween.start(); + + return tween; +} + + + + + + + +export function endShow(item, s = 1) { + + item.scaleX = item.scaleY = 0; + item.alpha = 0; + + const tween = new TWEEN.Tween(item) + .to({ alpha: 1, scaleX: s, scaleY: s }, 800) + .easing(TWEEN.Easing.Elastic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + + }) + .start(); +} + +export function hideItem(item, time = 0.8, callBack = null, easing = null) { + + if (item.alpha === 0) { + return; + } + + const tween = new TWEEN.Tween(item) + .to({alpha: 0}, time * 1000) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }); + + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + +export function showItem(item, time = 0.8, callBack = null, easing = null) { + + if (item.alpha === 1) { + if (callBack) { + callBack(); + } + return; + } + + item.visible = true; + const tween = new TWEEN.Tween(item) + .to({alpha: 1}, time * 1000) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }); + + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + +export function alphaItem(item, alpha, time = 0.8, callBack = null, easing = null) { + + + const tween = new TWEEN.Tween(item) + .to({alpha}, time * 1000) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }); + + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + +export function showStar(item, time = 0.8, callBack = null, easing = null) { + + + const tween = new TWEEN.Tween(item) + .to({alpha: 1, scale: 1}, time * 1000) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }); + + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + +export function randomSortByArr(arr) { + if (!arr) { + return; + } + const newArr = []; + const tmpArr = arr.concat(); + while (tmpArr.length > 0) { + const randomIndex = Math.floor( tmpArr.length * Math.random() ); + newArr.push(tmpArr[randomIndex]); + tmpArr.splice(randomIndex, 1); + } + return newArr; +} + + +export function radianToAngle(radian) { + return radian * 180 / Math.PI; + // 角度 = 弧度 * 180 / Math.PI; +} + +export function angleToRadian(angle) { + return angle * Math.PI / 180; + // 弧度= 角度 * Math.PI / 180; +} + +export function getPosByAngle(angle, len) { + + const radian = angle * Math.PI / 180; + const x = Math.sin(radian) * len; + const y = Math.cos(radian) * len; + + return {x, y}; + +} + +export function getAngleByPos(px, py, mx, my) { + + const x = Math.abs(px - mx); + const y = Math.abs(py - my); + + const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + const cos = y / z; + const radina = Math.acos(cos); // 用å三角函数求弧度 + let angle = Math.floor(180 / (Math.PI / radina) * 100) / 100; // å°†å¼§åº¦è½¬æ¢æˆè§’度 + + if (mx > px && my > py) {// é¼ æ ‡åœ¨ç¬¬å››è±¡é™ + angle = 180 - angle; + } + if (mx === px && my > py) {// é¼ æ ‡åœ¨yè½´è´Ÿæ–¹å‘上 + angle = 180; + } + if (mx > px && my === py) {// é¼ æ ‡åœ¨xè½´æ£æ–¹å‘上 + angle = 90; + } + if (mx < px && my > py) {// é¼ æ ‡åœ¨ç¬¬ä¸‰è±¡é™ + angle = 180 + angle; + } + if (mx < px && my === py) {// é¼ æ ‡åœ¨xè½´è´Ÿæ–¹å‘ + angle = 270; + } + if (mx < px && my < py) {// é¼ æ ‡åœ¨ç¬¬äºŒè±¡é™ + angle = 360 - angle; + } + + // console.log('angle: ', angle); + return angle; + +} + + +export function removeItemFromArr(arr, item) { + const index = arr.indexOf(item); + if (index !== -1) { + arr.splice(index, 1); + } +} + + + + + + +export function circleMove(item, x0, y0, time = 2, addR = 360, xPer = 1, yPer = 1, callBack = null, easing = null) { + + const r = getPosDistance(item.x, item.y, x0, y0); + let a = getAngleByPos(item.x, item.y, x0, y0); + a += 90; + const obj = {r, a}; + + item._circleAngle = a; + const targetA = a + addR; + + const tween = new TWEEN.Tween(item).to({_circleAngle: targetA}, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + + tween.onUpdate( (item, progress) => { + + // console.log(item._circleAngle); + const r = obj.r; + const a = item._circleAngle; + + const x = x0 + r * xPer * Math.cos(a * Math.PI / 180); + const y = y0 + r * yPer * Math.sin(a * Math.PI / 180); + + item.x = x; + item.y = y; + + // obj.a ++; + }); + + tween.start(); +} + + +export function getPosDistance(sx, sy, ex, ey) { + + const _x = ex - sx; + const _y = ey - sy; + const len = Math.sqrt( Math.pow(_x, 2) + Math.pow(_y, 2) ); + return len; +} + +export function delayCall(callback, second) { + const tween = new TWEEN.Tween(this) + .delay(second * 1000) + .onComplete(() => { + if (callback) { + callback(); + } + }) + .start(); +} + + +export function formatTime(fmt, date) { + + // "yyyy-MM-dd HH:mm:ss"; + + const o = { + 'M+': date.getMonth() + 1, // 月份 + 'd+': date.getDate(), // æ—¥ + 'h+': date.getHours(), // å°æ—¶ + 'm+': date.getMinutes(), // 分 + 's+': date.getSeconds(), // ç§’ + 'q+': Math.floor((date.getMonth() + 3) / 3), // å£åº¦ + S: date.getMilliseconds() // 毫秒 + }; + if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); } + for (const k in o) { + if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) + ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))); + } + } + return fmt; +} + +export function getMinScale(item, maxLen) { + const sx = maxLen / item.width; + const sy = maxLen / item.height; + const minS = Math.min(sx, sy); + return minS; +} + + + +export function jelly(item, time = 0.7) { + + + if (item.jellyTween) { + TWEEN.remove(item.jellyTween); + } + + const t = time / 9; + const baseSX = item.scaleX; + const baseSY = item.scaleY; + let index = 0; + + const run = () => { + if (index >= arr.length) { + item.jellyTween = null; + return; + } + const data = arr[index]; + const t = tweenChange(item, {scaleX: data[0], scaleY: data[1]}, data[2], () => { + index ++; + run(); + }, TWEEN.Easing.Sinusoidal.InOut); + item.jellyTween = t; + }; + + const arr = [ + [baseSX * 1.1, baseSY * 0.9, t], + [baseSX * 0.98, baseSY * 1.02, t * 2], + [baseSX * 1.02, baseSY * 0.98, t * 2], + [baseSX * 0.99, baseSY * 1.01, t * 2], + [baseSX * 1.0, baseSY * 1.0, t * 2], + ]; + + + run(); +} + + + +export function showPopParticle(img, pos, parent, num = 20, minLen = 40, maxLen = 80, showTime = 0.4) { + + + for (let i = 0; i < num; i ++) { + + const particle = new MySprite(); + particle.init(img); + particle.x = pos.x; + particle.y = pos.y; + parent.addChild(particle); + + const randomR = 360 * Math.random(); + particle.rotation = randomR; + + const randomS = 0.3 + Math.random() * 0.7; + particle.setScaleXY(randomS * 0.3); + + const randomX = Math.random() * 20 - 10; + particle.x += randomX; + + const randomY = Math.random() * 20 - 10; + particle.y += randomY; + + const randomL = minLen + Math.random() * (maxLen - minLen); + const randomA = 360 * Math.random(); + const randomT = getPosByAngle(randomA, randomL); + moveItem(particle, particle.x + randomT.x, particle.y + randomT.y, showTime, () => { + + + + }, TWEEN.Easing.Exponential.Out); + + // scaleItem(particle, 0, 0.6, () => { + // + // }); + + scaleItem(particle, randomS, 0.6, () => { + + }, TWEEN.Easing.Exponential.Out); + + setTimeout(() => { + + hideItem(particle, 0.4, () => { + + }, TWEEN.Easing.Cubic.In); + + }, showTime * 0.5 * 1000); + + + } +} + + + +export function shake(item, time = 0.5, callback = null, rate = 1) { + + if (item.shakeTween) { + return; + } + + item.shakeTween = true; + const offX = 15 * item.scaleX * rate; + const offY = 15 * item.scaleX * rate; + const baseX = item.x; + const baseY = item.y; + const easing = TWEEN.Easing.Sinusoidal.InOut; + + + const move4 = () => { + moveItem(item, baseX, baseY, time / 4, () => { + item.shakeTween = false; + if (callback) { + callback(); + } + }, easing); + }; + + const move3 = () => { + moveItem(item, baseX + offX / 4, baseY + offY / 4, time / 4, () => { + move4(); + }, easing); + }; + + const move2 = () => { + moveItem(item, baseX - offX / 4 * 3, baseY - offY / 4 * 3, time / 4, () => { + move3(); + }, easing); + }; + + const move1 = () => { + moveItem(item, baseX + offX, baseY + offY, time / 7.5, () => { + move2(); + }, easing); + }; + + move1(); + +} + +// --------------- custom class -------------------- + + + +export class HotZoneItem extends MySprite { + + + lineDashFlag = false; + arrow: MySprite; + label: Label; + title; + + arrowTop; + arrowRight; + + audio_url; + pic_url; + text; + private _itemType; + private shapeRect: ShapeRect; + + get itemType() { + return this._itemType; + } + set itemType(value) { + this._itemType = value; + } + + setSize(w, h) { + this.width = w; + this.height = h; + + + const rect = new ShapeRect(this.ctx); + rect.x = -w / 2; + rect.y = -h / 2; + rect.setSize(w, h); + rect.fillColor = '#ffffff'; + rect.alpha = 0.2; + this.addChild(rect); + } + + showLabel(text = null) { + + + if (!this.label) { + this.label = new Label(this.ctx); + this.label.anchorY = 0; + this.label.fontSize = 40; + this.label.textAlign = 'center'; + this.addChild(this.label); + // this.label.scaleX = 1 / this.scaleX; + // this.label.scaleY = 1 / this.scaleY; + + this.refreshLabelScale(); + + } + + if (text) { + this.label.text = text; + } else if (this.title) { + this.label.text = this.title; + } + this.label.visible = true; + + } + + hideLabel() { + if (!this.label) { return; } + + this.label.visible = false; + } + + refreshLabelScale() { + if (this.scaleX == this.scaleY) { + this.label.setScaleXY(1); + } + + if (this.scaleX > this.scaleY) { + this.label.scaleX = this.scaleY / this.scaleX; + } else { + this.label.scaleY = this.scaleX / this.scaleY; + } + } + + showLineDash() { + this.lineDashFlag = true; + + if (this.arrow) { + this.arrow.visible = true; + } else { + this.arrow = new MySprite(this.ctx); + this.arrow.load('assets/common/arrow.png', 1, 0); + this.arrow.setScaleXY(0.06); + + this.arrowTop = new MySprite(this.ctx); + this.arrowTop.load('assets/common/arrow_top.png', 0.5, 0); + this.arrowTop.setScaleXY(0.06); + + this.arrowRight = new MySprite(this.ctx); + this.arrowRight.load('assets/common/arrow_right.png', 1, 0.5); + this.arrowRight.setScaleXY(0.06); + } + + this.showLabel(); + } + + hideLineDash() { + + this.lineDashFlag = false; + + if (this.arrow) { + this.arrow.visible = false; + } + + this.hideLabel(); + } + + + + drawArrow() { + if (!this.arrow) { return; } + + const rect = this.getBoundingBox(); + this.arrow.x = rect.x + rect.width; + this.arrow.y = rect.y; + + this.arrow.update(); + + + this.arrowTop.x = rect.x + rect.width / 2; + this.arrowTop.y = rect.y; + this.arrowTop.update(); + + this.arrowRight.x = rect.x + rect.width; + this.arrowRight.y = rect.y + rect.height / 2; + this.arrowRight.update(); + } + + drawFrame() { + + + this.ctx.save(); + + + const rect = this.getBoundingBox(); + + const w = rect.width; + const h = rect.height; + const x = rect.x + w / 2; + const y = rect.y + h / 2; + + this.ctx.setLineDash([5, 5]); + this.ctx.lineWidth = 2; + this.ctx.strokeStyle = '#1bfff7'; + // this.ctx.fillStyle = '#ffffff'; + + this.ctx.beginPath(); + + this.ctx.moveTo( x - w / 2, y - h / 2); + + this.ctx.lineTo(x + w / 2, y - h / 2); + + this.ctx.lineTo(x + w / 2, y + h / 2); + + this.ctx.lineTo(x - w / 2, y + h / 2); + + this.ctx.lineTo(x - w / 2, y - h / 2); + + // this.ctx.fill(); + this.ctx.stroke(); + + + + + this.ctx.restore(); + + } + + draw() { + super.draw(); + + if (this.lineDashFlag) { + this.drawFrame(); + this.drawArrow(); + } + } +} + +export class HotZoneImg extends MySprite { + + drawFrame() { + + this.ctx.save(); + + const rect = this.getBoundingBox(); + const w = rect.width; + const h = rect.height; + const x = rect.x + w / 2; + const y = rect.y + h / 2; + + this.ctx.setLineDash([5, 5]); + this.ctx.lineWidth = 2; + this.ctx.strokeStyle = '#1bfff7'; + + this.ctx.beginPath(); + this.ctx.moveTo( x - w / 2, y - h / 2); + this.ctx.lineTo(x + w / 2, y - h / 2); + this.ctx.lineTo(x + w / 2, y + h / 2); + this.ctx.lineTo(x - w / 2, y + h / 2); + this.ctx.lineTo(x - w / 2, y - h / 2); + + // this.ctx.fill(); + this.ctx.stroke(); + + this.ctx.restore(); + } + + draw() { + super.draw(); + + this.drawFrame(); + } +} + +export class HotZoneLabel extends Label { + + drawFrame() { + + this.ctx.save(); + + const rect = this.getBoundingBox(); + const w = rect.width / this.scaleX; + const h = this.height * this.scaleY; + const x = this.x; + const y = this.y; + + this.ctx.setLineDash([5, 5]); + this.ctx.lineWidth = 2; + this.ctx.strokeStyle = '#1bfff7'; + + this.ctx.beginPath(); + this.ctx.moveTo( x - w / 2, y - h / 2); + this.ctx.lineTo(x + w / 2, y - h / 2); + this.ctx.lineTo(x + w / 2, y + h / 2); + this.ctx.lineTo(x - w / 2, y + h / 2); + this.ctx.lineTo(x - w / 2, y - h / 2); + + // this.ctx.fill(); + this.ctx.stroke(); + + this.ctx.restore(); + } + + draw() { + super.draw(); + + this.drawFrame(); + } +} + + + + +export class EditorItem extends MySprite { + + lineDashFlag = false; + arrow: MySprite; + label: Label; + text; + + showLabel(text = null) { + + + if (!this.label) { + this.label = new Label(this.ctx); + this.label.anchorY = 0; + this.label.fontSize = 50; + this.label.textAlign = 'center'; + this.addChild(this.label); + this.label.setScaleXY(1 / this.scaleX); + } + + if (text) { + this.label.text = text; + } else if (this.text) { + this.label.text = this.text; + } + this.label.visible = true; + + } + + hideLabel() { + if (!this.label) { return; } + + this.label.visible = false; + } + + showLineDash() { + this.lineDashFlag = true; + + if (this.arrow) { + this.arrow.visible = true; + } else { + this.arrow = new MySprite(this.ctx); + this.arrow.load('assets/common/arrow.png', 1, 0); + this.arrow.setScaleXY(0.06); + + } + + this.showLabel(); + } + + hideLineDash() { + + this.lineDashFlag = false; + + if (this.arrow) { + this.arrow.visible = false; + } + + this.hideLabel(); + } + + + + drawArrow() { + if (!this.arrow) { return; } + + const rect = this.getBoundingBox(); + this.arrow.x = rect.x + rect.width; + this.arrow.y = rect.y; + + this.arrow.update(); + } + + drawFrame() { + + + this.ctx.save(); + + + const rect = this.getBoundingBox(); + + const w = rect.width; + const h = rect.height; + const x = rect.x + w / 2; + const y = rect.y + h / 2; + + this.ctx.setLineDash([5, 5]); + this.ctx.lineWidth = 2; + this.ctx.strokeStyle = '#1bfff7'; + // this.ctx.fillStyle = '#ffffff'; + + this.ctx.beginPath(); + + this.ctx.moveTo( x - w / 2, y - h / 2); + + this.ctx.lineTo(x + w / 2, y - h / 2); + + this.ctx.lineTo(x + w / 2, y + h / 2); + + this.ctx.lineTo(x - w / 2, y + h / 2); + + this.ctx.lineTo(x - w / 2, y - h / 2); + + // this.ctx.fill(); + this.ctx.stroke(); + + + + + this.ctx.restore(); + + } + + draw() { + super.draw(); + + if (this.lineDashFlag) { + this.drawFrame(); + this.drawArrow(); + } + } +} + + + +// +// +// import TWEEN from '@tweenjs/tween.js'; +// +// +// class Sprite { +// x = 0; +// y = 0; +// color = ''; +// radius = 0; +// alive = false; +// margin = 0; +// angle = 0; +// ctx; +// +// constructor(ctx) { +// this.ctx = ctx; +// } +// update($event) { +// this.draw(); +// } +// draw() { +// +// } +// +// } +// +// +// +// +// +// export class MySprite extends Sprite { +// +// width = 0; +// height = 0; +// _anchorX = 0; +// _anchorY = 0; +// _offX = 0; +// _offY = 0; +// scaleX = 1; +// scaleY = 1; +// alpha = 1; +// rotation = 0; +// visible = true; +// +// children = [this]; +// +// img; +// _z = 0; +// +// +// init(imgObj = null, anchorX:number = 0.5, anchorY:number = 0.5) { +// +// if (imgObj) { +// +// this.img = imgObj; +// +// this.width = this.img.width; +// this.height = this.img.height; +// } +// +// this.anchorX = anchorX; +// this.anchorY = anchorY; +// } +// +// +// +// update($event = null) { +// if (this.visible) { +// this.draw(); +// } +// } +// draw() { +// +// this.ctx.save(); +// +// this.drawInit(); +// +// this.updateChildren(); +// +// this.ctx.restore(); +// } +// +// drawInit() { +// +// this.ctx.translate(this.x, this.y); +// +// this.ctx.rotate(this.rotation * Math.PI / 180); +// +// this.ctx.scale(this.scaleX, this.scaleY); +// +// this.ctx.globalAlpha = this.alpha; +// +// } +// +// drawSelf() { +// if (this.img) { +// this.ctx.drawImage(this.img, this._offX, this._offY); +// } +// } +// +// updateChildren() { +// +// if (this.children.length <= 0) { return; } +// +// for (let i = 0; i < this.children.length; i++) { +// +// if (this.children[i] === this) { +// +// this.drawSelf(); +// } else { +// +// this.children[i].update(); +// } +// } +// } +// +// +// load(url, anchorX = 0.5, anchorY = 0.5) { +// +// return new Promise((resolve, reject) => { +// const img = new Image(); +// img.onload = () => resolve(img); +// img.onerror = reject; +// img.src = url; +// }).then(img => { +// +// this.init(img, anchorX, anchorY); +// return img; +// }); +// } +// +// addChild(child, z = 1) { +// if (this.children.indexOf(child) === -1) { +// this.children.push(child); +// child._z = z; +// child.parent = this; +// } +// +// this.children.sort((a, b) => { +// return a._z - b._z; +// }); +// +// } +// removeChild(child) { +// const index = this.children.indexOf(child); +// if (index !== -1) { +// this.children.splice(index, 1); +// } +// } +// +// set anchorX(value) { +// this._anchorX = value; +// this.refreshAnchorOff(); +// } +// get anchorX() { +// return this._anchorX; +// } +// set anchorY(value) { +// this._anchorY = value; +// this.refreshAnchorOff(); +// } +// get anchorY() { +// return this._anchorY; +// } +// refreshAnchorOff() { +// this._offX = -this.width * this.anchorX; +// this._offY = -this.height * this.anchorY; +// } +// +// setScaleXY(value) { +// this.scaleX = this.scaleY = value; +// } +// +// getBoundingBox() { +// +// const x = this.x + this._offX * this.scaleX; +// const y = this.y + this._offY * this.scaleY; +// const width = this.width * this.scaleX; +// const height = this.height * this.scaleY; +// +// return {x, y, width, height}; +// } +// +// } +// +// +// +// +// +// export class Item extends MySprite { +// +// baseX; +// +// move(targetY, callBack) { +// +// const self = this; +// +// const tween = new TWEEN.Tween(this) +// .to({ y: targetY }, 2500) +// .easing(TWEEN.Easing.Quintic.Out) +// .onComplete(function() { +// +// self.hide(callBack); +// // if (callBack) { +// // callBack(); +// // } +// }) +// .start(); +// +// } +// +// show(callBack = null) { +// +// const tween = new TWEEN.Tween(this) +// .to({ alpha: 1 }, 800) +// // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. +// .onComplete(function() { +// if (callBack) { +// callBack(); +// } +// }) +// .start(); // Start the tween immediately. +// +// } +// +// hide(callBack = null) { +// +// const tween = new TWEEN.Tween(this) +// .to({ alpha: 0 }, 800) +// // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. +// .onComplete(function() { +// if (callBack) { +// callBack(); +// } +// }) +// .start(); // Start the tween immediately. +// } +// +// +// shake(id) { +// +// +// if (!this.baseX) { +// this.baseX = this.x; +// } +// +// const baseX = this.baseX; +// const baseTime = 50; +// const sequence = [ +// {target: {x: baseX + 40 * id}, time: baseTime - 25}, +// {target: {x: baseX - 20 * id}, time: baseTime}, +// {target: {x: baseX + 10 * id}, time: baseTime}, +// {target: {x: baseX - 5 * id}, time: baseTime}, +// {target: {x: baseX + 2 * id}, time: baseTime}, +// {target: {x: baseX - 1 * id}, time: baseTime}, +// {target: {x: baseX}, time: baseTime}, +// +// ]; +// +// +// const self = this; +// +// function runSequence() { +// +// if (self['shakeTween']) { +// self['shakeTween'].stop(); +// } +// +// const tween = new TWEEN.Tween(self); +// +// if (sequence.length > 0) { +// // console.log('sequence.length: ', sequence.length); +// const action = sequence.shift(); +// tween.to(action['target'], action['time']); +// tween.onComplete( () => { +// runSequence(); +// }); +// tween.start(); +// +// self['shakeTween'] = tween; +// } +// } +// +// runSequence(); +// +// } +// +// +// +// drop(targetY, callBack = null) { +// +// const self = this; +// +// const time = Math.abs(targetY - this.y) * 2.4; +// +// this.alpha = 1; +// +// const tween = new TWEEN.Tween(this) +// .to({ y: targetY }, time) +// .easing(TWEEN.Easing.Cubic.In) +// .onComplete(function() { +// +// // self.hideItem(callBack); +// if (callBack) { +// callBack(); +// } +// }) +// .start(); +// +// +// } +// +// +// } +// +// +// export class EndSpr extends MySprite { +// +// show(s) { +// +// this.scaleX = this.scaleY = 0; +// this.alpha = 0; +// +// const tween = new TWEEN.Tween(this) +// .to({ alpha: 1, scaleX: s, scaleY: s }, 800) +// .easing(TWEEN.Easing.Elastic.Out) // Use an easing function to make the animation smooth. +// .onComplete(function() { +// +// }) +// .start(); // Start the tween immediately. +// +// } +// } +// +// +// +// export class ShapeRect extends MySprite { +// +// fillColor = '#FF0000'; +// +// setSize(w, h) { +// this.width = w; +// this.height = h; +// +// console.log('w:', w); +// console.log('h:', h); +// } +// +// drawShape() { +// +// this.ctx.fillStyle = this.fillColor; +// this.ctx.fillRect(this._offX, this._offY, this.width, this.height); +// +// } +// +// +// drawSelf() { +// super.drawSelf(); +// this.drawShape(); +// } +// } +// +// +// export class HotZoneItem extends MySprite { +// +// +// lineDashFlag = false; +// arrow: MySprite; +// label: Label; +// title; +// +// arrowTop; +// arrowRight; +// +// audio_url; +// pic_url; +// text; +// private _itemType; +// private shapeRect: ShapeRect; +// +// get itemType() { +// return this._itemType; +// } +// set itemType(value) { +// this._itemType = value; +// } +// +// setSize(w, h) { +// this.width = w; +// this.height = h; +// +// +// const rect = new ShapeRect(this.ctx); +// rect.x = -w / 2; +// rect.y = -h / 2; +// rect.setSize(w, h); +// rect.fillColor = '#ffffff'; +// rect.alpha = 0.2; +// this.addChild(rect); +// } +// +// showLabel(text = null) { +// +// +// if (!this.label) { +// this.label = new Label(this.ctx); +// this.label.anchorY = 0; +// this.label.fontSize = '40px'; +// this.label.textAlign = 'center'; +// this.addChild(this.label); +// // this.label.scaleX = 1 / this.scaleX; +// // this.label.scaleY = 1 / this.scaleY; +// +// this.refreshLabelScale(); +// +// } +// +// if (text) { +// this.label.text = text; +// } else if (this.title) { +// this.label.text = this.title; +// } +// this.label.visible = true; +// +// } +// +// hideLabel() { +// if (!this.label) { return; } +// +// this.label.visible = false; +// } +// +// refreshLabelScale() { +// if (this.scaleX == this.scaleY) { +// this.label.setScaleXY(1); +// } +// +// if (this.scaleX > this.scaleY) { +// this.label.scaleX = this.scaleY / this.scaleX; +// } else { +// this.label.scaleY = this.scaleX / this.scaleY; +// } +// } +// +// showLineDash() { +// this.lineDashFlag = true; +// +// if (this.arrow) { +// this.arrow.visible = true; +// } else { +// this.arrow = new MySprite(this.ctx); +// this.arrow.load('assets/common/arrow.png', 1, 0); +// this.arrow.setScaleXY(0.06); +// +// this.arrowTop = new MySprite(this.ctx); +// this.arrowTop.load('assets/common/arrow_top.png', 0.5, 0); +// this.arrowTop.setScaleXY(0.06); +// +// this.arrowRight = new MySprite(this.ctx); +// this.arrowRight.load('assets/common/arrow_right.png', 1, 0.5); +// this.arrowRight.setScaleXY(0.06); +// } +// +// this.showLabel(); +// } +// +// hideLineDash() { +// +// this.lineDashFlag = false; +// +// if (this.arrow) { +// this.arrow.visible = false; +// } +// +// this.hideLabel(); +// } +// +// +// +// drawArrow() { +// if (!this.arrow) { return; } +// +// const rect = this.getBoundingBox(); +// this.arrow.x = rect.x + rect.width; +// this.arrow.y = rect.y; +// +// this.arrow.update(); +// +// +// this.arrowTop.x = rect.x + rect.width / 2; +// this.arrowTop.y = rect.y; +// this.arrowTop.update(); +// +// this.arrowRight.x = rect.x + rect.width; +// this.arrowRight.y = rect.y + rect.height / 2; +// this.arrowRight.update(); +// } +// +// drawFrame() { +// +// +// this.ctx.save(); +// +// +// const rect = this.getBoundingBox(); +// +// const w = rect.width; +// const h = rect.height; +// const x = rect.x + w / 2; +// const y = rect.y + h / 2; +// +// this.ctx.setLineDash([5, 5]); +// this.ctx.lineWidth = 2; +// this.ctx.strokeStyle = '#1bfff7'; +// // this.ctx.fillStyle = '#ffffff'; +// +// this.ctx.beginPath(); +// +// this.ctx.moveTo( x - w / 2, y - h / 2); +// +// this.ctx.lineTo(x + w / 2, y - h / 2); +// +// this.ctx.lineTo(x + w / 2, y + h / 2); +// +// this.ctx.lineTo(x - w / 2, y + h / 2); +// +// this.ctx.lineTo(x - w / 2, y - h / 2); +// +// // this.ctx.fill(); +// this.ctx.stroke(); +// +// +// +// +// this.ctx.restore(); +// +// } +// +// draw() { +// super.draw(); +// +// if (this.lineDashFlag) { +// this.drawFrame(); +// this.drawArrow(); +// } +// } +// } +// +// +// export class EditorItem extends MySprite { +// +// lineDashFlag = false; +// arrow: MySprite; +// label:Label; +// text; +// +// showLabel(text = null) { +// +// +// if (!this.label) { +// this.label = new Label(this.ctx); +// this.label.anchorY = 0; +// this.label.fontSize = '50px'; +// this.label.textAlign = 'center'; +// this.addChild(this.label); +// this.label.setScaleXY(1 / this.scaleX); +// } +// +// if (text) { +// this.label.text = text; +// } else if (this.text) { +// this.label.text = this.text; +// } +// this.label.visible = true; +// +// } +// +// hideLabel() { +// if (!this.label) { return; } +// +// this.label.visible = false; +// } +// +// showLineDash() { +// this.lineDashFlag = true; +// +// if (this.arrow) { +// this.arrow.visible = true; +// } else { +// this.arrow = new MySprite(this.ctx); +// this.arrow.load('assets/common/arrow.png', 1, 0); +// this.arrow.setScaleXY(0.06); +// +// } +// +// this.showLabel(); +// } +// +// hideLineDash() { +// +// this.lineDashFlag = false; +// +// if (this.arrow) { +// this.arrow.visible = false; +// } +// +// this.hideLabel(); +// } +// +// +// +// drawArrow() { +// if (!this.arrow) { return; } +// +// const rect = this.getBoundingBox(); +// this.arrow.x = rect.x + rect.width; +// this.arrow.y = rect.y; +// +// this.arrow.update(); +// } +// +// drawFrame() { +// +// +// this.ctx.save(); +// +// +// const rect = this.getBoundingBox(); +// +// const w = rect.width; +// const h = rect.height; +// const x = rect.x + w / 2; +// const y = rect.y + h / 2; +// +// this.ctx.setLineDash([5, 5]); +// this.ctx.lineWidth = 2; +// this.ctx.strokeStyle = '#1bfff7'; +// // this.ctx.fillStyle = '#ffffff'; +// +// this.ctx.beginPath(); +// +// this.ctx.moveTo( x - w / 2, y - h / 2); +// +// this.ctx.lineTo(x + w / 2, y - h / 2); +// +// this.ctx.lineTo(x + w / 2, y + h / 2); +// +// this.ctx.lineTo(x - w / 2, y + h / 2); +// +// this.ctx.lineTo(x - w / 2, y - h / 2); +// +// // this.ctx.fill(); +// this.ctx.stroke(); +// +// +// +// +// this.ctx.restore(); +// +// } +// +// draw() { +// super.draw(); +// +// if (this.lineDashFlag) { +// this.drawFrame(); +// this.drawArrow(); +// } +// } +// } +// +// +// +// export class Label extends MySprite { +// +// text:String; +// fontSize:String = '40px'; +// fontName:String = 'Verdana'; +// textAlign:String = 'left'; +// +// +// constructor(ctx) { +// super(ctx); +// this.init(); +// } +// +// drawText() { +// +// // console.log('in drawText', this.text); +// +// if (!this.text) { return; } +// +// this.ctx.font = `${this.fontSize} ${this.fontName}`; +// this.ctx.textAlign = this.textAlign; +// this.ctx.textBaseline = 'middle'; +// this.ctx.fontWeight = 900; +// +// this.ctx.lineWidth = 5; +// this.ctx.strokeStyle = '#ffffff'; +// this.ctx.strokeText(this.text, 0, 0); +// +// this.ctx.fillStyle = '#000000'; +// this.ctx.fillText(this.text, 0, 0); +// +// +// } +// +// +// drawSelf() { +// super.drawSelf(); +// this.drawText(); +// } +// +// } +// +// +// +// export function getPosByAngle(angle, len) { +// +// const radian = angle * Math.PI / 180; +// const x = Math.sin(radian) * len; +// const y = Math.cos(radian) * len; +// +// return {x, y}; +// +// } +// +// export function getAngleByPos(px, py, mx, my) { +// +// // const _x = p2x - p1x; +// // const _y = p2y - p1y; +// // const tan = _y / _x; +// // +// // const radina = Math.atan(tan); // 用å三角函数求弧度 +// // const angle = Math.floor(180 / (Math.PI / radina)); // +// // +// // console.log('r: ' , angle); +// // return angle; +// // +// +// +// +// const x = Math.abs(px - mx); +// const y = Math.abs(py - my); +// // const x = Math.abs(mx - px); +// // const y = Math.abs(my - py); +// const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); +// const cos = y / z; +// const radina = Math.acos(cos); // 用å三角函数求弧度 +// let angle = Math.floor(180 / (Math.PI / radina) * 100) / 100; // å°†å¼§åº¦è½¬æ¢æˆè§’度 +// +// if(mx > px && my > py) {// é¼ æ ‡åœ¨ç¬¬å››è±¡é™ +// angle = 180 - angle; +// } +// +// if(mx === px && my > py) {// é¼ æ ‡åœ¨yè½´è´Ÿæ–¹å‘上 +// angle = 180; +// } +// +// if(mx > px && my === py) {// é¼ æ ‡åœ¨xè½´æ£æ–¹å‘上 +// angle = 90; +// } +// +// if(mx < px && my > py) {// é¼ æ ‡åœ¨ç¬¬ä¸‰è±¡é™ +// angle = 180 + angle; +// } +// +// if(mx < px && my === py) {// é¼ æ ‡åœ¨xè½´è´Ÿæ–¹å‘ +// angle = 270; +// } +// +// if(mx < px && my < py) {// é¼ æ ‡åœ¨ç¬¬äºŒè±¡é™ +// angle = 360 - angle; +// } +// +// // console.log('angle: ', angle); +// return angle; +// +// } diff --git a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.html b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.html new file mode 100644 index 0000000..9028527 --- /dev/null +++ b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.html @@ -0,0 +1,100 @@ +<div class="p-image-children-editor"> + + <h5 style="margin-left: 2.5%;"> preview: </h5> + + <div class="preview-box" #wrap> + <canvas id="canvas" #canvas></canvas> + </div> + + <div nz-row nzType="flex" nzAlign="middle"> + <div nz-col nzSpan="5" nzOffset="1"> + + <h5> add background: </h5> + + <div class="bg-box"> + <app-upload-image-with-preview + [picUrl]="bgItem?.url" + (imageUploaded)="onBackgroundUploadSuccess($event)"> + </app-upload-image-with-preview> + </div> + </div> + + <div nz-col nzSpan="5" nzOffset="1" class="img-box" + *ngFor="let it of hotZoneArr; let i = index"> + + <div + style="margin: auto; padding: 5px; margin-top: 30px; width:90%; border: 2px dashed #ddd; border-radius: 10px"> + <span style="margin-left: 40%;"> item-{{i + 1}} + </span> + <button style="float: right;" nz-button nzType="danger" nzSize="small" (click)="deleteBtnClick(i)"> + X + </button> + + <nz-divider style="margin-top: 10px;"></nz-divider> + + + <div style="margin-top: -20px; margin-bottom: 5px"> + <nz-radio-group [ngModel]="it.itemType" (ngModelChange)="radioChange($event, it)"> + <label *ngIf="isHasRect" nz-radio nzValue="rect">矩形</label> + <label *ngIf="isHasPic" nz-radio nzValue="pic">图片</label> + <label *ngIf="isHasText" nz-radio nzValue="text">文本</label> + </nz-radio-group> + </div> + + <div *ngIf="it.itemType == 'pic'"> + <app-upload-image-with-preview + [picUrl]="it?.pic_url" + (imageUploaded)="onItemImgUploadSuccess($event, it)"> + </app-upload-image-with-preview> + </div> + + <div *ngIf="it.itemType == 'text'"> + <input type="text" nz-input [(ngModel)]="it.text" (blur)="saveText(it)"> + </div> + + <div style="width: 100%; margin-top: 5px;"> + <app-audio-recorder + [audioUrl]="it.audio_url" + (audioUploaded)="onItemAudioUploadSuccess($event, it)" + ></app-audio-recorder> + </div> + + </div> + + </div> + + + <div nz-col nzSpan="5" nzOffset="1"> + + <div class="bg-box"> + <button nz-button nzType="dashed" (click)="addBtnClick()" + class="add-btn"> + <i nz-icon nzType="plus-circle" nzTheme="outline"></i> + <!--Add Image--> + Add hot zone + </button> + </div> + + </div> + </div> + + + <nz-divider></nz-divider> + + <div class="save-box"> + + <button class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round" + (click)="saveClick()" > + <i nz-icon nzType="save"></i> + Save + </button> + + </div> + + +</div> + + +<label style="opacity: 0; position: absolute; top: 0px; font-family: 'BRLNSR_1'">1</label> + + diff --git a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss new file mode 100644 index 0000000..9e2c2bf --- /dev/null +++ b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.scss @@ -0,0 +1,210 @@ + +.p-image-children-editor { + + width: 100%; + height: 100%; + border-radius: 0.5rem; + + border: 2px solid #ddd; + + + + .preview-box { + + margin: auto; + width: 95%; + height: 35vw; + + border: 2px dashed #ddd; + border-radius: 0.5rem; + background-color: #fafafa; + text-align: center; + color: #aaa; + + + .preview-img { + height: 100%; + width: auto; + } + + } + + + + .bg-box{ + //width: 100%; + margin-bottom: 1rem; + + } + + .img-box { + margin-bottom: 1rem; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + .img-box-upload{ + width: 80%; + } + + .add-btn { + margin-top: 1rem; + width: 200px; + height: 90px; + + display: flex; + align-items: center; + justify-content: center; + } +} + + +.save-box { + width: 100%; + + display: flex; + align-items: center; + justify-content: center; + + .save-btn { + width: 160px; + height: 40px; + + //margin-top: 20px; + margin-bottom: 20px; + + display: flex; + align-items: center; + justify-content: center; + } +} + +h5 { + margin-top: 1rem; +} + + + +@font-face +{ + font-family: 'BRLNSR_1'; + src: url("/assets/font/BRLNSR_1.TTF") ; +} + + + + + + + + + + + + + + + +//@import '../../../style/common_mixin'; +// +//.p-image-uploader { +// position: relative; +// display: block; +// width: 100%; +// height: 0; +// padding-bottom: 56.25%; +// .p-box { +// position: absolute; +// left: 0; +// top: 0; +// right: 0; +// bottom: 0; +// border: 2px dashed #ddd; +// border-radius: 0.5rem; +// background-color: #fafafa; +// text-align: center; +// color: #aaa; +// .p-upload-icon { +// text-align: center; +// margin: auto; +// .anticon-upload { +// color: #888; +// font-size: 5rem; +// } +// .p-progress-bar { +// position: relative; +// width: 20rem; +// height: 1.5rem; +// border: 1px solid #ccc; +// border-radius: 1rem; +// .p-progress-bg { +// background-color: #1890ff; +// border-radius: 1rem; +// height: 100%; +// } +// .p-progress-value { +// position: absolute; +// top: 0; +// left: 0; +// width: 100%; +// height: 100%; +// text-shadow: 0 0 4px #000; +// color: white; +// text-align: center; +// font-size: 0.9rem; +// line-height: 1.5rem; +// } +// } +// } +// .p-preview { +// width: 100%; +// height: 100%; +// //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"); +// @include k-img-bg(); +// } +// } +//} +// +//.p-btn-delete { +// position: absolute; +// right: -0.5rem; +// top: -0.5rem; +// width: 2rem; +// height: 2rem; +// border: 0.2rem solid white; +// border-radius: 50%; +// font-size: 1.2rem; +// background-color: #fb781a; +// color: white; +// text-align: center; +//} +// +//.p-upload-progress-bg { +// position: absolute; +// width: 100%; +// height: 100%; +// display: flex; +// align-items: center; +// justify-content: center; +// & .i-text { +// position: absolute; +// text-align: center; +// color: white; +// text-shadow: 0 0 2px rgba(0, 0, 0, .85); +// } +// & .i-bg { +// position: absolute; +// left: 0; +// top: 0; +// height: 100%; +// background-color: #27b43f; +// border-radius: 0.5rem; +// } +//} +// +// +//:host ::ng-deep .ant-upload { +// display: block; +//} diff --git a/form/src/app/common/custom-hot-zone/custom-hot-zone.component.ts b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.ts new file mode 100644 index 0000000..dc2a4cf --- /dev/null +++ b/form/src/app/common/custom-hot-zone/custom-hot-zone.component.ts @@ -0,0 +1,986 @@ +import { + Component, + ElementRef, + EventEmitter, + HostListener, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + ViewChild +} from '@angular/core'; +import {Subject} from 'rxjs'; +import {debounceTime} from 'rxjs/operators'; +import {EditorItem, HotZoneImg, HotZoneItem, HotZoneLabel, Label, MySprite, removeItemFromArr} from './Unit'; +import TWEEN from '@tweenjs/tween.js'; +import {getMinScale} from "../../play/Unit"; +import {tar} from "compressing"; + + +@Component({ + selector: 'app-custom-hot-zone', + templateUrl: './custom-hot-zone.component.html', + styleUrls: ['./custom-hot-zone.component.scss'] +}) +export class CustomHotZoneComponent implements OnInit, OnDestroy, OnChanges { + + + @Input() + imgItemArr = null; + @Input() + hotZoneItemArr = null; + @Input() + hotZoneArr = null; + @Output() + save = new EventEmitter(); + @ViewChild('canvas', {static: true}) canvas: ElementRef; + @ViewChild('wrap', {static: true}) wrap: ElementRef; + + @Input() + isHasRect = true; + @Input() + isHasPic = true; + @Input() + isHasText = true; + @Input() + hotZoneFontObj = { + size: 50, + name: 'BRLNSR_1', + color: '#8f3758' + } + @Input() + defaultItemType = 'text'; + + @Input() + hotZoneImgSize = 190; + + saveDisabled = true; + + canvasWidth = 1280; + canvasHeight = 720; + canvasBaseW = 1280; + // @HostListener('window:resize', ['$event']) + canvasBaseH = 720; + mapScale = 1; + ctx; + mx; + my; // ç‚¹å‡»åæ ‡ + // 声音 + bgAudio = new Audio(); + images = new Map(); + animationId: any; + + + // èµ„æº + // rawImages = new Map(res); + winResizeEventStream = new Subject(); + canvasLeft; + canvasTop; + renderArr; + imgArr = []; + oldPos; + radioValue; + curItem; + bg: MySprite; + changeSizeFlag = false; + changeTopSizeFlag = false; + changeRightSizeFlag = false; + + constructor() { + } + + _bgItem = null; + + get bgItem() { + return this._bgItem; + } + + @Input() + set bgItem(v) { + this._bgItem = v; + + this.init(); + } + + onResize(event) { + this.winResizeEventStream.next(); + } + + + ngOnInit() { + + this.initListener(); + + // this.init(); + this.update(); + + } + + ngOnDestroy() { + window.cancelAnimationFrame(this.animationId); + } + + + ngOnChanges() { + + } + + + onBackgroundUploadSuccess(e) { + console.log('e: ', e); + this.bgItem.url = e.url; + this.refreshBackground(); + } + + onItemImgUploadSuccess(e, item) { + item.pic_url = e.url; + this.loadHotZonePic(item.pic, e.url); + } + + onItemAudioUploadSuccess(e, item) { + item.audio_url = e.url; + } + + + refreshBackground(callBack = null) { + + if (!this.bg) { + this.bg = new MySprite(this.ctx); + this.renderArr.push(this.bg); + } + + const bg = this.bg; + if (this.bgItem.url) { + + bg.load(this.bgItem.url).then(() => { + const rate1 = this.canvasWidth / bg.width; + const rate2 = this.canvasHeight / bg.height; + + const rate = Math.min(rate1, rate2); + bg.setScaleXY(rate); + + + bg.x = this.canvasWidth / 2; + bg.y = this.canvasHeight / 2; + + if (callBack) { + callBack(); + } + }); + } + + } + + + addBtnClick() { + // this.imgArr.push({}); + // this.hotZoneArr.push({}); + + const item = this.getHotZoneItem(); + this.hotZoneArr.push(item); + + this.refreshItem(item); + + this.refreshHotZoneId(); + + } + + deleteBtnClick(index) { + + const item = this.hotZoneArr.splice(index, 1)[0]; + removeItemFromArr(this.renderArr, item.pic); + removeItemFromArr(this.renderArr, item.textLabel); + + this.refreshHotZoneId(); + + } + + onImgUploadSuccessByImg(e, img) { + img.pic_url = e.url; + this.refreshImage(img); + } + + refreshImage(img) { + + this.hideAllLineDash(); + + img.picItem = this.getPicItem(img); + + this.refreshImageId(); + + } + + + refreshHotZoneId() { + for (let i = 0; i < this.hotZoneArr.length; i++) { + this.hotZoneArr[i].index = i; + + if (this.hotZoneArr[i]) { + this.hotZoneArr[i].title = 'item-' + (i + 1); + + } + } + } + + + refreshImageId() { + for (let i = 0; i < this.imgArr.length; i++) { + this.imgArr[i].id = i; + + if (this.imgArr[i].picItem) { + this.imgArr[i].picItem.text = 'Image-' + (i + 1); + } + } + + } + + getHotZoneItem(saveData = null) { + + + const itemW = 200; + const itemH = 200; + const item = new HotZoneItem(this.ctx); + item.setSize(itemW, itemH); + item.anchorX = 0.5; + item.anchorY = 0.5; + + item.x = this.canvasWidth / 2; + item.y = this.canvasHeight / 2; + + item.itemType = this.defaultItemType; + + if (saveData) { + + const saveRect = saveData.rect; + item.scaleX = saveRect.width / item.width; + item.scaleY = saveRect.height / item.height; + item.x = saveRect.x + saveRect.width / 2; + item.y = saveRect.y + saveRect.height / 2; + + } + + item.showLineDash(); + + const pic = new HotZoneImg(this.ctx); + pic.visible = false; + item['pic'] = pic; + if (saveData && saveData.pic_url) { + this.loadHotZonePic(pic, saveData.pic_url); + } + pic.x = item.x; + pic.y = item.y; + this.renderArr.push(pic); + + const textLabel = new HotZoneLabel(this.ctx); + textLabel.fontSize = this.hotZoneFontObj.size; + textLabel.fontName = this.hotZoneFontObj.name; + textLabel.fontColor = this.hotZoneFontObj.color; + textLabel.textAlign = 'center'; + // textLabel.setOutline(); + // console.log('saveData:', saveData); + item['textLabel'] = textLabel; + textLabel.setScaleXY(this.mapScale); + if (saveData && saveData.text) { + textLabel.text = saveData.text; + textLabel.refreshSize(); + } + textLabel.x = item.x; + textLabel.y = item.y; + this.renderArr.push(textLabel); + + return item; + } + + + getPicItem(img, saveData = null) { + + + const item = new EditorItem(this.ctx); + item.load(img.pic_url).then(img => { + + let maxW, maxH; + if (this.bg) { + maxW = this.bg.width * this.bg.scaleX; + maxH = this.bg.height * this.bg.scaleY; + } else { + maxW = this.canvasWidth; + maxH = this.canvasHeight; + } + + let scaleX = maxW / 3 / item.width; + let scaleY = maxH / 3 / item.height; + + if (item.height * scaleX < this.canvasHeight) { + item.setScaleXY(scaleX); + } else { + item.setScaleXY(scaleY); + } + item.x = this.canvasWidth / 2; + item.y = this.canvasHeight / 2; + + if (saveData) { + + const saveRect = saveData.rect; + item.setScaleXY(saveRect.width / item.width); + item.x = saveRect.x + saveRect.width / 2; + item.y = saveRect.y + saveRect.height / 2; + + } else { + item.showLineDash(); + } + + }); + return item; + } + + + onAudioUploadSuccessByImg(e, img) { + img.audio_url = e.url; + } + + deleteItem(e, i) { + // this.imgArr.splice(i , 1); + // this.refreshImageId(); + + this.hotZoneArr.splice(i, 1); + this.refreshHotZoneId(); + } + + + radioChange(e, item) { + item.itemType = e; + + this.refreshItem(item); + + // console.log(' in radioChange e: ', e); + } + + refreshItem(item) { + switch (item.itemType) { + case 'rect': + this.setRectState(item); + break; + case 'pic': + this.setPicState(item); + break; + case 'text': + this.setTextState(item); + break; + default: + + } + } + + + init() { + + this.initData(); + this.initCtx(); + + this.initItem(); + } + + initItem() { + if (!this.bgItem) { + this.bgItem = {}; + } else { + this.refreshBackground(() => { + + // if (!this.imgItemArr) { + // this.imgItemArr = []; + // } else { + // this.initImgArr(); + // } + + // console.log('aaaaa'); + + if (!this.hotZoneItemArr) { + this.hotZoneItemArr = []; + } else { + this.initHotZoneArr(); + } + + }); + } + + } + + initHotZoneArr() { + + // console.log('this.hotZoneArr: ', this.hotZoneArr); + let curBgRect; + if (this.bg) { + curBgRect = this.bg.getBoundingBox(); + } else { + curBgRect = {x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight}; + } + + let oldBgRect = this.bgItem.rect; + if (!oldBgRect) { + oldBgRect = curBgRect; + } + + const rate = curBgRect.width / oldBgRect.width; + + console.log('rate: ', rate); + + this.hotZoneArr = []; + const arr = this.hotZoneItemArr.concat(); + for (let i = 0; i < arr.length; i++) { + + const data = JSON.parse(JSON.stringify(arr[i])); + // const img = {pic_url: data.pic_url}; + + data.rect.x *= rate; + data.rect.y *= rate; + data.rect.width *= rate; + data.rect.height *= rate; + + data.rect.x += curBgRect.x; + data.rect.y += curBgRect.y; + + // img['picItem'] = this.getPicItem(img, data); + // img['audio_url'] = arr[i].audio_url; + // this.imgArr.push(img); + + const item = this.getHotZoneItem(data); + item.audio_url = data.audio_url; + item.pic_url = data.pic_url; + item.text = data.text; + item.itemType = data.itemType; + this.refreshItem(item); + + console.log('item: ', item); + this.hotZoneArr.push(item); + + } + + this.refreshHotZoneId(); + + // this.refreshImageId(); + + } + + + initImgArr() { + + console.log('this.imgItemArr: ', this.imgItemArr); + let curBgRect; + if (this.bg) { + curBgRect = this.bg.getBoundingBox(); + } else { + curBgRect = {x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight}; + } + + let oldBgRect = this.bgItem.rect; + if (!oldBgRect) { + oldBgRect = curBgRect; + } + + const rate = curBgRect.width / oldBgRect.width; + + console.log('rate: ', rate); + + this.imgArr = []; + const arr = this.imgItemArr.concat(); + for (let i = 0; i < arr.length; i++) { + + const data = JSON.parse(JSON.stringify(arr[i])); + const img = {pic_url: data.pic_url}; + + data.rect.x *= rate; + data.rect.y *= rate; + data.rect.width *= rate; + data.rect.height *= rate; + + data.rect.x += curBgRect.x; + data.rect.y += curBgRect.y; + + img['picItem'] = this.getPicItem(img, data); + img['audio_url'] = arr[i].audio_url; + this.imgArr.push(img); + } + this.refreshImageId(); + } + + + initData() { + + this.canvasWidth = this.wrap.nativeElement.clientWidth; + this.canvasHeight = this.wrap.nativeElement.clientHeight; + this.mapScale = this.canvasWidth / this.canvasBaseW; + this.renderArr = []; + this.bg = null; + + this.imgArr = []; + this.hotZoneArr = []; + } + + initCtx() { + this.ctx = this.canvas.nativeElement.getContext('2d'); + this.canvas.nativeElement.width = this.canvasWidth; + this.canvas.nativeElement.height = this.canvasHeight; + } + + + mapDown(event) { + + this.oldPos = {x: this.mx, y: this.my}; + + for (let i = 0; i < this.hotZoneArr.length; i++) { + + const item = this.hotZoneArr[i]; + let callback; + let target; + switch (item.itemType) { + case 'rect': + target = item; + callback = this.clickedHotZoneRect.bind(this); + break; + case 'pic': + target = item.pic; + callback = this.clickedHotZonePic.bind(this); + break; + case 'text': + target = item.textLabel; + callback = this.clickedHotZoneText.bind(this); + break; + } + + if (this.checkClickTarget(target)) { + callback(target); + return; + } + } + + + } + + + mapMove(event) { + if (!this.curItem) { + return; + } + + if (this.changeSizeFlag) { + this.changeSize(); + + } else if (this.changeTopSizeFlag) { + this.changeTopSize(); + + } else if (this.changeRightSizeFlag) { + this.changeRightSize(); + + } else { + + const addX = this.mx - this.oldPos.x; + const addY = this.my - this.oldPos.y; + this.curItem.x += addX; + this.curItem.y += addY; + } + + this.oldPos = {x: this.mx, y: this.my}; + + this.saveDisabled = true; + + } + + mapUp(event) { + this.curItem = null; + this.changeSizeFlag = false; + this.changeTopSizeFlag = false; + this.changeRightSizeFlag = false; + } + + + changeSize() { + const rect = this.curItem.getBoundingBox(); + + let lenW = (this.mx - (rect.x + rect.width / 2)) * 2; + let lenH = ((rect.y + rect.height / 2) - this.my) * 2; + + + let minLen = 20; + let s; + if (lenW < lenH) { + if (lenW < minLen) { + lenW = minLen; + } + s = lenW / this.curItem.width; + + } else { + if (lenH < minLen) { + lenH = minLen; + } + s = lenH / this.curItem.height; + } + + + // console.log('s: ', s); + this.curItem.setScaleXY(s); + this.curItem.refreshLabelScale(); + } + + + changeTopSize() { + const rect = this.curItem.getBoundingBox(); + + // let lenW = ( this.mx - (rect.x + rect.width / 2) ) * 2; + let lenH = ((rect.y + rect.height / 2) - this.my) * 2; + + + let minLen = 20; + let s; + // if (lenW < lenH) { + // if (lenW < minLen) { + // lenW = minLen; + // } + // s = lenW / this.curItem.width; + // + // } else { + if (lenH < minLen) { + lenH = minLen; + } + s = lenH / this.curItem.height; + // } + + + // console.log('s: ', s); + this.curItem.scaleY = s; + this.curItem.refreshLabelScale(); + } + + changeRightSize() { + const rect = this.curItem.getBoundingBox(); + + let lenW = (this.mx - (rect.x + rect.width / 2)) * 2; + // let lenH = ( (rect.y + rect.height / 2) - this.my ) * 2; + + let minLen = 20; + let s; + if (lenW < minLen) { + lenW = minLen; + } + s = lenW / this.curItem.width; + + this.curItem.scaleX = s; + this.curItem.refreshLabelScale(); + } + + changeItemSize(item) { + this.curItem = item; + this.changeSizeFlag = true; + } + + changeItemTopSize(item) { + this.curItem = item; + this.changeTopSizeFlag = true; + } + + changeItemRightSize(item) { + this.curItem = item; + this.changeRightSizeFlag = true; + } + + changeCurItem(item) { + + this.hideAllLineDash(); + + this.curItem = item; + this.curItem.showLineDash(); + } + + hideAllLineDash() { + + for (let i = 0; i < this.imgArr.length; i++) { + if (this.imgArr[i].picItem) { + this.imgArr[i].picItem.hideLineDash(); + } + } + } + + + update() { + if (!this.ctx) { + return; + } + + + this.animationId = window.requestAnimationFrame(this.update.bind(this)); + // 清除画布内容 + this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); + + for (let i = 0; i < this.renderArr.length; i++) { + this.renderArr[i].update(this); + } + + // for (let i = 0; i < this.imgArr.length; i++) { + // const picItem = this.imgArr[i].picItem; + // if (picItem) { + // picItem.update(this); + // } + // } + + this.updateArr(this.hotZoneArr); + this.updatePos() + + + TWEEN.update(); + } + + updateArr(arr) { + if (arr) { + for (let i = 0; i < arr.length; i++) { + arr[i].update(); + } + } + } + + + renderAfterResize() { + this.canvasWidth = this.wrap.nativeElement.clientWidth; + this.canvasHeight = this.wrap.nativeElement.clientHeight; + this.init(); + } + + initListener() { + + this.winResizeEventStream + .pipe(debounceTime(500)) + .subscribe(data => { + this.renderAfterResize(); + }); + + if (this.IsPC()) { + + this.canvas.nativeElement.addEventListener('mousedown', (event) => { + setMxMyByMouse(event); + this.mapDown(event); + }); + + this.canvas.nativeElement.addEventListener('mousemove', (event) => { + setMxMyByMouse(event); + this.mapMove(event); + }); + + this.canvas.nativeElement.addEventListener('mouseup', (event) => { + setMxMyByMouse(event); + this.mapUp(event); + }); + + const setMxMyByMouse = (event) => { + this.mx = event.offsetX; + this.my = event.offsetY; + }; + + } else { + + this.canvas.nativeElement.addEventListener('touchstart', (event) => { + setMxMyByTouch(event); + this.mapDown(event); + }); + + this.canvas.nativeElement.addEventListener('touchmove', (event) => { + setMxMyByTouch(event); + this.mapMove(event); + }); + + this.canvas.nativeElement.addEventListener('touchend', (event) => { + setMxMyByTouch(event); + this.mapUp(event); + }); + + this.canvas.nativeElement.addEventListener('touchcancel', (event) => { + setMxMyByTouch(event); + this.mapUp(event); + }); + + + const setMxMyByTouch = (event) => { + if (event.touches.length <= 0) { + return; + } + + if (this.canvasLeft == null) { + setParentOffset(); + } + + this.mx = event.touches[0].pageX - this.canvasLeft; + this.my = event.touches[0].pageY - this.canvasTop; + }; + + + const setParentOffset = () => { + + const rect = this.canvas.nativeElement.getBoundingClientRect(); + this.canvasLeft = rect.left; + this.canvasTop = rect.top; + }; + } + } + + IsPC() { + if (window['ELECTRON']) { + return false; // å°è£…å®¢æˆ·ç«¯æ ‡è®° + } + if (document.body.ontouchstart !== undefined) { + return false; + } else { + return true; + } + } + + + checkClickTarget(target) { + + const rect = target.getBoundingBox(); + if (this.checkPointInRect(this.mx, this.my, rect)) { + return true; + } + return false; + } + + checkPointInRect(x, y, rect) { + if (x >= rect.x && x <= rect.x + rect.width) { + if (y >= rect.y && y <= rect.y + rect.height) { + return true; + } + } + return false; + } + + + saveClick() { + const bgItem = this.bgItem; + if (this.bg) { + bgItem['rect'] = this.bg.getBoundingBox(); + } else { + bgItem['rect'] = { + x: 0, + y: 0, + width: Math.round(this.canvasWidth * 100) / 100, + height: Math.round(this.canvasHeight * 100) / 100 + }; + } + + + const hotZoneItemArr = []; + const hotZoneArr = this.hotZoneArr; + for (let i = 0; i < hotZoneArr.length; i++) { + + const hotZoneItem = { + index: hotZoneArr[i].index, + pic_url: hotZoneArr[i].pic_url, + text: hotZoneArr[i].text, + audio_url: hotZoneArr[i].audio_url, + itemType: hotZoneArr[i].itemType, + fontSize: this.hotZoneFontObj.size, + fontName: this.hotZoneFontObj.name, + fontColor: this.hotZoneFontObj.color, + fontScale: hotZoneArr[i].textLabel ? hotZoneArr[i].textLabel.scaleX : 1, + imgScale: hotZoneArr[i].pic ? hotZoneArr[i].pic.scaleX : 1, + mapScale: this.mapScale + }; + hotZoneItem['rect'] = hotZoneArr[i].getBoundingBox(); + hotZoneItem['rect'].x = Math.round((hotZoneItem['rect'].x - bgItem['rect'].x) * 100) / 100; + hotZoneItem['rect'].y = Math.round((hotZoneItem['rect'].y - bgItem['rect'].y) * 100) / 100; + hotZoneItem['rect'].width = Math.round((hotZoneItem['rect'].width) * 100) / 100; + hotZoneItem['rect'].height = Math.round((hotZoneItem['rect'].height) * 100) / 100; + + + hotZoneItemArr.push(hotZoneItem); + } + + console.log('hotZoneItemArr: ', hotZoneItemArr); + + this.save.emit({bgItem, hotZoneItemArr}); + } + + private updatePos() { + this.hotZoneArr.forEach((item) => { + let x, y; + switch (item.itemType) { + case 'rect': + x = item.x; + y = item.y; + break; + + case 'pic': + x = item.pic.x; + y = item.pic.y; + break; + + case 'text': + x = item.textLabel.x; + y = item.textLabel.y; + break; + } + + item.x = x; + item.y = y; + item.pic.x = x; + item.pic.y = y; + item.textLabel.x = x; + item.textLabel.y = y; + }); + } + + private setPicState(item: any) { + item.visible = false; + item.textLabel.visible = false; + item.pic.visible = true; + } + + private setRectState(item: any) { + item.visible = true; + item.textLabel.visible = false; + item.pic.visible = false; + } + + private setTextState(item: any) { + item.visible = false; + item.pic.visible = false; + item.textLabel.visible = true; + } + + private clickedHotZoneRect(item: any) { + if (this.checkClickTarget(item)) { + + if (item.lineDashFlag && this.checkClickTarget(item.arrow)) { + this.changeItemSize(item); + } else if (item.lineDashFlag && this.checkClickTarget(item.arrowTop)) { + this.changeItemTopSize(item); + } else if (item.lineDashFlag && this.checkClickTarget(item.arrowRight)) { + this.changeItemRightSize(item); + } else { + this.changeCurItem(item); + } + return; + } + } + + private clickedHotZonePic(item: any) { + if (this.checkClickTarget(item)) { + this.curItem = item; + } + } + + private clickedHotZoneText(item: any) { + if (this.checkClickTarget(item)) { + this.curItem = item; + } + } + + saveText(item) { + item.textLabel.text = item.text; + } + + private loadHotZonePic(pic: HotZoneImg, url) { + const baseLen = this.hotZoneImgSize * this.mapScale; + pic.load(url).then(() => { + const s = getMinScale(pic, baseLen); + pic.setScaleXY(s); + }); + } +} diff --git a/form/src/app/common/lesson-title-config/lesson-title-config.component.html b/form/src/app/common/lesson-title-config/lesson-title-config.component.html new file mode 100644 index 0000000..996dc65 --- /dev/null +++ b/form/src/app/common/lesson-title-config/lesson-title-config.component.html @@ -0,0 +1,93 @@ + +<div class="title-config"> + + <div class="title-wrap"> + <div class="row" style="margin: 5px;"> + <div class="p-content" style="width:100%"> + <div class="p-tool-box d-flex" style="background: #fff;"> + <nz-select class="ml-1" style="width: 120px;" [(ngModel)]="__fontFamily" + (ngModelChange)="onChangeFontFamily($event)" + nzPlaceHolder="Font Family" + [nzDropdownMatchSelectWidth]="false"> + <nz-option [nzValue]="font" nzCustomContent [nzLabel]="font" *ngFor="let font of fontFamilyList"> + <span [ngStyle]="{'font-family': font}" >{{font}}</span> + </nz-option> + </nz-select> + <nz-select class="ml-1" style="width: 110px;" [(ngModel)]="__fontSize" + (ngModelChange)="onChangeFontSize()" + nzPlaceHolder="Font Size"> + <nz-option [nzValue]="i" [nzLabel]="'Size - ' + i" *ngFor="let i of fontSizeRange"></nz-option> + </nz-select> + <div class="p-divider"></div> + <div class="i-tool-font-btn d-flex mr-2"> + <div class="position-relative fa-icon" (click)="onChangeBold()"> +<!-- <div class="fa fa-bold"></div>--> + <fa-icon icon="bold"></fa-icon> + </div> + </div> + <div class="i-tool-font-btn d-flex mr-2"> + <div class="position-relative fa-icon" (click)="onChangeItalic()"> +<!-- <div class="fa fa-italic"></div>--> + <fa-icon icon="italic"></fa-icon> + </div> + </div> + <div class="i-tool-font-btn d-flex mr-2"> + <div class="position-relative fa-icon" (click)="onChangeUnderline()"> +<!-- <div class="fa fa-underline"></div>--> + <fa-icon icon="underline"></fa-icon> + </div> + </div> + <div class="i-tool-font-btn d-flex"> + <div class="position-relative fa-icon" (click)="onChangeStrikethrough()"> +<!-- <div class="fa fa-strikethrough"></div>--> + <fa-icon icon="strikethrough"></fa-icon> + </div> + </div> + <div class="p-divider"></div> + <div class="i-tool-font-color d-flex"> + <div class="position-relative i-left flex-fill" (click)="onChangeFontColor($event)"> +<!-- <div class="fa fa-font"></div>--> + <fa-icon icon="palette"></fa-icon> + <div class="i-color" [style.background-color]="__fontColor"></div> + </div> + <div class="i-dropdown-menu" nzPlacement="bottom" + nz-popover [(nzVisible)]="isShowFontColorPane" nzTrigger="click" + [nzContent]="colorPane"> + <i nz-icon type="down" theme="outline"></i> + </div> + </div> + <div class="p-divider"></div> + <div style="background: #fff;display: block;"> + <div class="position-relative"> + <app-audio-recorder [audioUrl]="titleObj && titleObj.audio_url" (audioUploaded)="titleAudioUploaded($event)"></app-audio-recorder> + </div> + </div> + </div> + + <div class="width-100 d-flex"> + <iframe #titleEl id="titleContentEgret" frameborder="0" style="overflow: hidden;width: 100%; height:48px; margin: 0; padding: 0;"></iframe> + </div> + </div> + + <ng-template #colorPane> + <div class="p-color-pane" nz-row nzGutter="16" nzType="flex"> + <div nz-col class="p-color-item" *ngFor="let color of colorList" + [style.background-color]="color" + (click)="onSelectColor(color)" + > + </div> + </div> + </ng-template> + + </div> + + + + + + + </div> + + + +</div> diff --git a/form/src/app/common/lesson-title-config/lesson-title-config.component.scss b/form/src/app/common/lesson-title-config/lesson-title-config.component.scss new file mode 100644 index 0000000..d8dca53 --- /dev/null +++ b/form/src/app/common/lesson-title-config/lesson-title-config.component.scss @@ -0,0 +1,365 @@ +@import '../../style/common_mixin.css'; + +.title-config { + .letter-wrap{ + width: 3rem; + flex: 0 0 3rem; + } + .str-wrap{ + margin-left: 1rem;flex: 1 1; + } + .type-row{ + margin: 0;padding-top: 1rem; + } + +} +@font-face +{ + font-family: 'BRLNSDB'; + src: url("../../../assets/font/BRLNSDB.TTF") ; +} + +@font-face +{ + font-family: 'BRLNSB'; + src: url("../../../assets/font/BRLNSB.TTF") ; +} + +@font-face +{ + font-family: 'BRLNSR'; + src: url("../../../assets/font/BRLNSR.TTF") ; +} + +@font-face +{ + font-family: 'GOTHIC'; + src: url("../../../assets/font/GOTHIC.TTF") ; +} + +@font-face +{ + font-family: 'GOTHICB'; + src: url("../../../assets/font/GOTHICB.TTF") ; +} + +@font-face +{ + font-family: 'GOTHICBI'; + src: url("../../../assets/font/GOTHICBI.TTF") ; +} + +@font-face +{ + font-family: 'GOTHICI'; + src: url("../../../assets/font/GOTHICI.TTF") ; +} + +@font-face +{ + font-family: 'MMTextBook'; + src: url("../../../assets/font/MMTextBook.otf") ; +} + +@font-face +{ + font-family: 'MMTextBook-Bold'; + src: url("../../../assets/font/MMTextBook-Bold.otf") ; +} + +@font-face +{ + font-family: 'MMTextBook-BoldItalic'; + src: url("../../../assets/font/MMTextBook-BoldItalic.otf") ; +} + +@font-face +{ + font-family: 'MMTextBook-Italic'; + src: url("../../../assets/font/MMTextBook-Italic.otf") ; +} +@mixin tool-btn { + border: 1px solid #ddd; + display: flex; + justify-content: center; + align-items: center; + height: 100%; + outline: none; + border-radius: 6px; + color: #555; +} +.d-flex{ + display: flex; +} + +.position-relative { + position: relative; +} + .flex-fill { + -webkit-box-flex: 1; + flex: 1 1 auto; + justify-content: center; + display: flex; + } + +.i-dropdown-menu{ + width: 15px; + font-size: 10px; + border-left: 1px solid #ddd; + display: -webkit-box; + display: flex; + -webkit-box-align: center; + align-items: center; + flex: 0 +} +.p-title-box .p-title { + font-size: 20px; + } +.p-title-box input { + width: 300px; + margin-left: 10px; + } + +.p-content { + border: 1px solid #ddd; + box-shadow: 0 0 8px #eee; + margin-top: 10px; +} + +.p-divider { + border-left: 1px solid #ccc; + margin: 5px 8px; + height: 85%; +} + +.p-tool-box { + background-color: #efefef; + padding: 2px; + height: 37px; + display: flex; + align-items: center; + border-bottom: 1px solid #ddd; + + + +} +// save +.i-tool-save { + //@include tool-btn(); + color: white; +} +.i-tool-save:disabled { + color: #555; +} + +// font-size +.i-tool-font-size { + //@include tool-btn(); + width: 37px; + +} +.i-tool-font-size:hover { + color: black; + border-color: #bbb; +} + +// font-color +.i-tool-font-color, .i-tool-font-btn { + border: 1px solid #ddd; + //padding: 3px 7px; + border-radius: 6px; + width: 45px; + height: 31px; + background-color: white; + color: #555; + ::ng-deep > span { + display: flex; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + padding: 3px 7px; + } + .i-left { + .fa-font,.fa-bold,.fa-italic,.fa-strikethrough, .fa-underline { + font-size: 10px; + position: absolute; + color: #555; + left: 8px; + top: 7px; + } + .i-color { + width: 68%; + height: 5px; + background-color: black; + position: absolute; + top: 21px; + left: 5px; + } + } + .i-dropdown-menu { + width: 15px; + font-size: 10px; + border-left: 1px solid #ddd; + display: flex; + align-items: center; + .anticon-down { + transform: scale(0.6); + } + } +} +.i-tool-font-btn{ + width: 31px; +} +.fa-icon{ + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; +} +// bg-color +.i-tool-bg-color { + @include tool-btn(); + padding: 0 9px; + ::ng-deep > span { + display: flex; + align-items: center; + } + + .i-color { + display: block; + width: 16px; + height: 16px; + background-color: white; + margin-left: 10px; + } +} + + +// horizontal-center +.i-tool-horizontal-center { + @include tool-btn(); + width: 37px; +} +.p-box { + width: 1280px; + height: 720px; + left: 0; + top: 0; + transform-origin: top left; + overflow: hidden; +} + + + +.p-animation-index-box { + .i-animation-index { + position: absolute; + font-size: 34px; + font-family: Arial; + border: 1px solid #ddd; + border-radius: 4px; + min-width: 50px; + min-height: 50px; + display: flex; + align-items: center; + justify-content: center; + background-color: darkorange; + color: white; + } +} + +.p-edit { + background-color: white; + border: 1px solid black; + padding: 2px 15px; +} + +.p-selected { + border: 1px solid darkorange; + box-shadow: 0 0 8px #ddd; +} + +.p-tool-item-disable { + color: rgba(0, 0, 0, .25) !important; + background-color: transparent !important; + pointer-events: none; +} + +// ----------- +.p-color-pane { + width: 80px; + .p-color-item { + width: 17px; + height: 17px; + cursor: pointer; + margin: 4px; + border: 1px solid #bbb; + } + .p-color-item-active { + border: 1px solid white; + transform: scale(1.1); + } +} + +.p-user-guide { + font-size: 40px; + display: flex; + justify-content: center; + align-items: center; +} + +.p-animation-box { + width: 400px; + background-color: #efefef; + border-left: 1px solid #ddd; + padding: 10px; + text-align: center; + + .p-animation-label { + z-index: 1; + position: relative; + } + + ::ng-deep .ant-radio-button-wrapper { + padding: 0 10px; + } + + .i-toolbox { + & > div { + font-size: 20px; + cursor: pointer; + color: #555; + padding: 0 3px; + margin: 0 5px; + } + & > div:hover { + color: #1585ff; + transform: scale(1.1); + } + } + + .p-animation-list { + background-color: white; + border-radius: 10px; + height: calc(100% - 86px); + overflow-y: auto; + .p-animation-item { + padding: 0 20px; + background-color: aliceblue; + margin-top: 6px; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + cursor: pointer; + text-align: left; + display: flex; + } + .i-active { + background-color: antiquewhite; + } + } +} + diff --git a/form/src/app/common/lesson-title-config/lesson-title-config.component.ts b/form/src/app/common/lesson-title-config/lesson-title-config.component.ts new file mode 100644 index 0000000..6b7601f --- /dev/null +++ b/form/src/app/common/lesson-title-config/lesson-title-config.component.ts @@ -0,0 +1,339 @@ + +import { + Component, + ElementRef, + EventEmitter, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + ViewChild +} from '@angular/core'; + +const editorTpl = `<html lang="en"><head><meta charset="utf-8"> + <meta name="viewport" + content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/> + <style> +@font-face{ + font-family: 'BRLNSDB'; + src: url("../../../assets/font/BRLNSDB.TTF") ; +} + +@font-face{ + font-family: 'BRLNSB'; + src: url("../../../assets/font/BRLNSB.TTF") ; +} + +@font-face{ + font-family: 'BRLNSR'; + src: url("../../../assets/font/BRLNSR.TTF") ; +} + +@font-face{ + font-family: 'GOTHIC'; + src: url("../../../assets/font/GOTHIC.TTF") ; +} + +@font-face{ + font-family: 'GOTHICB'; + src: url("../../../assets/font/GOTHICB.TTF") ; +} + +@font-face{ + font-family: 'GOTHICBI'; + src: url("../../../assets/font/GOTHICBI.TTF") ; +} + +@font-face{ + font-family: 'GOTHICI'; + src: url("../../../assets/font/GOTHICI.TTF") ; +} + +@font-face{ + font-family: 'MMTextBook'; + src: url("../../../assets/font/MMTextBook.otf") ; +} + +@font-face{ + font-family: 'MMTextBook-Bold'; + src: url("../../../assets/font/MMTextBook-Bold.otf") ; +} + +@font-face{ + font-family: 'MMTextBook-BoldItalic'; + src: url("../../../assets/font/MMTextBook-BoldItalic.otf") ; +} + +@font-face{ + font-family: 'MMTextBook-Italic'; + src: url("../../../assets/font/MMTextBook-Italic.otf") ; +} +html, body{ +/*font-size: 30px;*/ +} +body{ + height:48px; + + overflow: hidden; + margin: 0; + padding: 0 .5rem; + font-family: 'BRLNSB, BRLNSDB, BRLNSR, GOTHIC, GOTHICB, MMTextBook'; + background: #FFF; + line-height: 48px; +} +</style> + </head> + <body>{{content}}</body> +</html>`; + +@Component({ + selector: 'app-lesson-title-config', + templateUrl: './lesson-title-config.component.html', + styleUrls: ['./lesson-title-config.component.scss'] +}) +export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, OnChanges { + + fontFamilyList = [ + 'Arial', + 'BRLNSB', + 'BRLNSDB', + 'BRLNSR', + 'GOTHIC', + 'GOTHICB', + // "GOTHICBI", + // "GOTHICI", + 'MMTextBook', + // "MMTextBook-Bold", + // "MMTextBook-Italic", + // "MMTextBook-BoldItalic", + ]; + + + + colorList = [ + '#000000', + '#ffffff', + '#595959', + '#0075c2', + '#c61c1e', + '#9cbc3a', + '#008000', + '#FF0000', + '#D2691E', + ]; + MIN_FONT_SIZE = 1; + MAX_FONT_SIZE = 7; + isShowFontColorPane = false; + isShowBGColorPane = false; + fontSizeRange = [ + // {name: '1å·', value: 9}, + // {name: '2å·', value: 13}, + // {name: '3å·', value: 16}, + // {name: '4å·', value: 18}, + // {name: '5å·', value: 24}, + // {name: '6å·', value: 32}, + + ]; + + editorContent = ''; + + + __fontFamily = 'Arial'; + __fontColor = ''; + __fontSize = 3; + + loopCnt = 0; + maxLoops = 20; + + @ViewChild('titleEl', {static: true}) titleEl: ElementRef; + titleEW = null; + + + @Input() + titleObj = { + content: '', + audio_url: '' + }; + + + @Output() + titleUpdated = new EventEmitter(); + + constructor() { + this.fontSizeRange = []; + for (let i = this.MIN_FONT_SIZE; i <= this.MAX_FONT_SIZE; ++i) { + this.fontSizeRange.push(i); + } + this.__fontSize = 3; + this.__fontColor = this.colorList[0]; + + } + ngOnChanges(vars) { + if (!vars.titleObj.previousValue) {// åˆå§‹åŒ–,内容是空 + return; + } + let defObj = this.titleObj; + if (!vars.titleObj.currentValue) { + defObj = { + content: '', + audio_url: '' + }; + } else { + defObj = vars.titleObj.currentValue; + } + this.titleObj.content = defObj.content || ''; + this.titleObj.audio_url = defObj.audio_url || ''; + this.titleEW.document.body.innerHTML = this.titleObj.content; + } + + ngOnInit() { + if (!this.titleObj) { + this.titleObj = { + content: '', + audio_url: '' + }; + } + this.titleObj.content = this.titleObj.content || ''; + this.titleObj.audio_url = this.titleObj.audio_url || ''; + + this.editorContent = editorTpl.replace('{{content}}', this.titleObj.content) ; + this.titleEW = this.titleEl.nativeElement.contentWindow; + console.log('this.titleEW', this.titleEW); + const tdoc = this.titleEW.document; + tdoc.designMode = 'on'; + tdoc.open('text/html', 'replace'); + tdoc.write(this.editorContent); + tdoc.close(); + tdoc.addEventListener('keypress', this.keyPress, true); + tdoc.addEventListener('blur', () => { + if (this.titleObj.content === this.titleEW.document.body.innerHTML.trim()) { + return; + } + this.shouldSave(); + }, true); + } + htmlEncode(text) { + if (!text) { + return ''; + } + return text.replace(/\&/ig, '&') + .replace(/\</ig, '<') + .replace(/\>/ig, '>') + .replace(/\"/ig, '"'); + } + + htmlDecode(text) { + if (!text) { + return ''; + } + return text.replace(/\&\;/ig, '&') + .replace(/\<\;/ig, '<') + .replace(/\>\;/ig, '>') + .replace(/\"\;/ig, '"'); + } + + + ngOnDestroy(): void { + + } + + keyPress(evt) { + try { + + if (evt.charCode === 13) { + evt.preventDefault(); + evt.stopPropagation(); + return; + } + if (evt.ctrlKey) { + const key = String.fromCharCode(evt.charCode).toLowerCase(); + let cmd = ''; + switch (key) { + case 'b': cmd = 'bold'; break; + case 'i': cmd = 'italic'; break; + case 'u': cmd = 'underline'; break; + } + + + if (cmd) { + this.execEditorCommand(cmd); + + // stop the event bubble + evt.preventDefault(); + evt.stopPropagation(); + } + } + } catch (e) { + console.log(1, e); + alert(e); + } + } + + execEditorCommand(command, option?: any) { + console.log('sssss'); + try { + this.titleEW.focus(); + const result = this.titleEW.document.execCommand(command, false, option); + console.log(result); + this.loopCnt = 0; + + return false; + } catch (e) { + alert(e); + if (this.loopCnt < this.maxLoops) { + setTimeout(() => { + this.execEditorCommand(command, option); + }, 100); + this.loopCnt += 1; + } else { + alert('Error executing command.'); + } + } + } + + onSelectColor(color) { + this.execEditorCommand('forecolor', color); + this.__fontColor = color; + } + onChangeFontColor(val) { + this.execEditorCommand('forecolor', this.__fontColor); + } + onChangeFontFamily(font) { + this.execEditorCommand('fontName', font); + } + onChangeFontSize(size?: any) { + + if (size) { + size += this.__fontSize; + } else { + size = this.__fontSize; + } + size = Math.max(this.MIN_FONT_SIZE, size); + size = Math.min(this.MAX_FONT_SIZE, size); + this.execEditorCommand('fontsize', size); + } + onChangeBold() { + this.execEditorCommand('bold'); + } + onChangeItalic() { + this.execEditorCommand('italic'); + } + onChangeUnderline() { + this.execEditorCommand('underline'); + } + onChangeStrikethrough() { + this.execEditorCommand('strikethrough'); + } + titleAudioUploaded(res) { + this.titleObj.audio_url = res.url; + this.titleUpdated.emit(this.titleObj); + } + shouldSave = () => { + console.log('title shouldSave', this.titleObj); + this.titleObj.content = this.titleEW.document.body.innerHTML.trim(); + this.titleUpdated.emit(this.titleObj); + } +} + + diff --git a/form/src/app/common/player-content-wrapper/player-content-wrapper.component.html b/form/src/app/common/player-content-wrapper/player-content-wrapper.component.html new file mode 100644 index 0000000..864df8e --- /dev/null +++ b/form/src/app/common/player-content-wrapper/player-content-wrapper.component.html @@ -0,0 +1,8 @@ +<div class="cmp-player-content-wrapper" #wrapperEl> + <div class="cmp-cnt-box"> + <img [src]="'assets/'+ratio+'.png'" alt=""> + <div class="cmp-cnt-main"> + <ng-content></ng-content> + </div> + </div> +</div> \ No newline at end of file diff --git a/form/src/app/common/player-content-wrapper/player-content-wrapper.component.scss b/form/src/app/common/player-content-wrapper/player-content-wrapper.component.scss new file mode 100644 index 0000000..6aec336 --- /dev/null +++ b/form/src/app/common/player-content-wrapper/player-content-wrapper.component.scss @@ -0,0 +1,54 @@ +@import '../../style/common_mixin.css'; + +.cmp-player-content-wrapper{ + max-height: 100%; + display: block; + position: relative; + height: 100%; + .cmp-cnt-box{ + display: inline-block; + max-width: 100%; + max-height: 100%; + width: auto; + height: 100%; + position: relative; + img{ + height: 100%; + width: auto; + } + + } + .cmp-cnt-main{ + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: flex; + flex-direction: column; + } +} + + +[style*="--aspect-ratio"] > :first-child { + width: 100%; +} +[style*="--aspect-ratio"] > img { + height: auto; +} +@supports (--custom:property) { + [style*="--aspect-ratio"] { + position: relative; + } + [style*="--aspect-ratio"]::before { + content: ""; + display: block; + padding-bottom: calc(100% / (var(--aspect-ratio))); + } + [style*="--aspect-ratio"] > :first-child { + position: absolute; + top: 0; + left: 0; + height: 100%; + } +} diff --git a/form/src/app/common/player-content-wrapper/player-content-wrapper.component.ts b/form/src/app/common/player-content-wrapper/player-content-wrapper.component.ts new file mode 100644 index 0000000..0780a42 --- /dev/null +++ b/form/src/app/common/player-content-wrapper/player-content-wrapper.component.ts @@ -0,0 +1,55 @@ +import { + AfterViewInit, + Component, + ElementRef, + Input, + OnChanges, + OnDestroy, + OnInit, + ViewChild +} from '@angular/core'; + + +@Component({ + selector: 'app-player-content-wrapper', + templateUrl: './player-content-wrapper.component.html', + styleUrls: ['./player-content-wrapper.component.scss'] +}) +export class PlayerContentWrapperComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit { + + + @ViewChild('wrapperEl', {static: true }) wrapperEl: ElementRef; + + // // aspect ratio? + @Input() ratio; + _w: string; + _h: string; + + constructor() { + if (window.innerHeight < window.innerWidth) { + this._h = '100%'; + this._w = 'auto'; + } else { + this._w = '100%'; + this._h = 'auto'; + } + } + ngOnInit() { + if (!this.ratio) { + this.ratio = '20-9'; + } + + + } + ngOnChanges() { + + } + ngOnDestroy(): void { + + } + + ngAfterViewInit() { + + } +} + diff --git a/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html b/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html new file mode 100644 index 0000000..b5c26bb --- /dev/null +++ b/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html @@ -0,0 +1,37 @@ +<div class="position-relative"> + <nz-upload class="p-image-uploader" [nzDisabled]="disableUpload" + [nzShowUploadList]="false" + nzAccept = "image/*" + [nzAction]="uploadUrl" + [nzData]="uploadData" + (nzChange)="handleChange($event)"> + <!--[nzBeforeUpload]="customUpload">--> + <div class="p-box d-flex align-items-center"> + <div class="p-upload-icon" *ngIf="!picUrl && !uploading"> + <i nz-icon nzType="cloud-upload" nzTheme="outline" [style.font-size]="iconSize + 'em'"></i> + <div class="m-3"></div> + <span>{{TIP}}</span> + <!--<div class="mt-5 p-progress-bar" *ngIf="uploading">--> + <!--<div class="p-progress-bg" [style.width]="progress*0.2+'rem'"></div>--> + <!--<div class="p-progress-value">{{progress}}%</div>--> + <!--</div>--> + </div> + <div class="p-upload-progress-bg" *ngIf="uploading"> + <div class="i-bg" [style.width]="progress+'%'"></div> + <div class="i-text"> + <fa-icon icon="cloud-upload-alt"></fa-icon> + Uploading... + </div> + </div> + <div class="p-preview" *ngIf="!uploading && picUrl " + [style.background-image]="picUrl | backgroundImage "> + </div> + </div> + </nz-upload> + <div class="p-btn-delete" *ngIf="canDelete" + nz-popconfirm nzTitle="Are you sure ?" + (nzOnConfirm)="onDelete()" + > + <i nz-icon nzType="close" nzTheme="outline"></i> + </div> +</div> diff --git a/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss b/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss new file mode 100644 index 0000000..98dad11 --- /dev/null +++ b/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss @@ -0,0 +1,106 @@ +@import '../../style/common_mixin.css'; + +.p-image-uploader { + position: relative; + display: block; + width: 100%; + height: 0; + padding-bottom: 56.25%; + .p-box { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + border: 2px dashed #ddd; + border-radius: 0.5rem; + background-color: #fafafa; + text-align: center; + color: #aaa; + .p-upload-icon { + text-align: center; + margin: auto; + .anticon-upload { + color: #888; + font-size: 5rem; + } + .p-progress-bar { + position: relative; + width: 20rem; + height: 1.5rem; + border: 1px solid #ccc; + border-radius: 1rem; + .p-progress-bg { + background-color: #1890ff; + border-radius: 1rem; + height: 100%; + } + .p-progress-value { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-shadow: 0 0 4px #000; + color: white; + text-align: center; + font-size: 0.9rem; + line-height: 1.5rem; + } + } + } + .p-preview { + width: 100%; + height: 100%; + background-size: contain; + background-repeat: no-repeat; + background-position: 50% 50%; + //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"); + } + } + .d-flex{ + display: flex; + } +} + +.p-btn-delete { + position: absolute; + right: -0.5rem; + top: -0.5rem; + width: 2rem; + height: 2rem; + border: 0.2rem solid white; + border-radius: 50%; + font-size: 1.2rem; + background-color: #fb781a; + color: white; + text-align: center; +} + +.p-upload-progress-bg { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + & .i-text { + position: absolute; + text-align: center; + color: white; + text-shadow: 0 0 2px rgba(0, 0, 0, .85); + } + & .i-bg { + position: absolute; + left: 0; + top: 0; + height: 100%; + background-color: #27b43f; + border-radius: 0.5rem; + } +} + + +:host ::ng-deep .ant-upload { + display: block; +} diff --git a/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts b/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts new file mode 100644 index 0000000..f4694a1 --- /dev/null +++ b/form/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts @@ -0,0 +1,158 @@ +import {Component, EventEmitter, Input, OnChanges, OnDestroy, Output} from '@angular/core'; +import { NzMessageService, UploadXHRArgs, UploadFile } from 'ng-zorro-antd'; + + +@Component({ + selector: 'app-upload-image-with-preview', + templateUrl: './upload-image-with-preview.component.html', + styleUrls: ['./upload-image-with-preview.component.scss'] +}) +export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges { + uploading = false; + progress = 0; + @Input() + picUrl; + @Input() + canDelete = false; + @Output() + imageUploaded = new EventEmitter(); + @Output() + imageUploadFailure = new EventEmitter(); + @Output() + delete = new EventEmitter(); + @Input() + picItem = null; + @Input() + iconSize = 2; + @Input() + TIP = 'Click here to upload image'; + @Input() + disableUpload = false; + + uploadUrl; + uploadData; + + constructor(private nzMessageService: NzMessageService) { + + this.uploadUrl = (<any> window).courseware.uploadUrl(); + this.uploadData = (<any> window).courseware.uploadData(); + + window['air'].getUploadCallback = (url, data) => { + this.uploadUrl = url; + this.uploadData = data; + }; + + } + ngOnChanges() { + if (!this.picItem) { + return; + } + } + + + + + + handleChange(info: { type: string, file: UploadFile, event: any }): void { + + console.log('info:' , info); + + switch (info.type) { + case 'start': + // this.isUploading = true; + // this.progress = 0; + + this.picUrl = null; + // this.beforeUpload(item.file as any); + if (!this.checkSelectFile(info.file)) { + return; + } + this.uploading = true; + this.progress = 0; + + break; + + case 'success': + // this.isUploading = false; + // this.uploadSuccess(info.file.response); + // this.audioUploaded.emit(info.file.response); + + this.uploadSuccess(info.file); + + break; + case 'progress': + this.progress = parseInt(info.event.percent, 10); + this.doProgress(this.progress); + break; + } + } + + onDelete() { + this.delete.emit(); + } + checkSelectFile(file) { + const isImg = ['image/jpeg', 'image/png', 'image/jpeg', 'image/gif', 'image/bmp'].includes(file.type); + if (!isImg) { + this.nzMessageService.error('You can only upload Image file (jpg|gif|png|bmp)'); + return false; + } + const isGif = !['image/jpeg', 'image/png', 'image/jpeg', 'image/bmp'].includes(file.type); + const delta = isGif ? 20 : 5; + const isOverSize = file.size / 1024 / 1024 < delta; + if (!isOverSize) { + this.nzMessageService.error(`${isGif ? 'Gif' : 'Image'} must smaller than ${delta}MB!`); + return false; + } + return true; + } + + uploadSuccess = (file) => { + this.nzMessageService.info('Upload Success'); + this.uploading = false; + this.picUrl = file.response.url ; + // this.uploadFinished(url); + // if (!inOSS) { + const img = new Image(); + img.addEventListener('load', () => { + + const height = img.naturalHeight; + const width = img.naturalWidth; + file['height'] = height; + file['width'] = width; + img.remove(); + this.imageUploaded.emit(file.response); + // this.resService.updateImage(id, {width, height}).then( () => { + // this.imageUploaded.emit({res_id: id, id, name, hash, url}); + // }); + + }); + img.src = file.response.url; + // } else { + // this.imageUploaded.emit({res_id: id, id, name, hash, url}); + // } + } + + uploadFailure = (err, file) => { + this.uploading = false; + if (err.name && err.name === 'cancel') { + return; + } + console.log(err); + this.nzMessageService.error('Upload Error ' + err.message); + this.imageUploadFailure.emit(file); + } + + doProgress = function(p) { + if (p > 1) { + p = 1; + } + if (p < 0) { + p = 0; + } + // console.log(Math.floor(p * 100)); + this.progress = Math.floor(p * 100); + } + ngOnDestroy() { + } + +} diff --git a/form/src/app/common/upload-video/upload-video.component.html b/form/src/app/common/upload-video/upload-video.component.html new file mode 100644 index 0000000..8f15339 --- /dev/null +++ b/form/src/app/common/upload-video/upload-video.component.html @@ -0,0 +1,94 @@ +<div class="p-video-box"> +<div class="up-video" style="display: flex;"> + <!--<nz-upload class="" [nzDisabled]="!showUploadBtn"--> + <!--[nzShowUploadList]="false"--> + <!--[nzBeforeUpload]="beforeUpload"--> + <!--nzAccept = ".mp4"--> + <!--style="margin-right: 1rem">--> + + <nz-upload class="p-image-uploader" [nzDisabled]="uploading" + [nzShowUploadList]="false" + nzAccept = ".mp4" + [nzAction]="uploadUrl" + [nzData]="uploadData" + (nzChange)="handleChange($event)" + style="margin-right: 1rem"> + + <button type="button" nz-button nzType="default" *ngIf="showUploadBtn" [disabled]="uploading" + [nzLoading]="uploading" > + <i nz-icon nzType="plus" nzTheme="outline"></i> + <span>{{ uploading ? 'Uploading' : 'Select Video' }}</span> + <!--<span>Select Video</span>--> + </button> + + + + + </nz-upload> + <!--<button nz-button nzType="primary" *ngIf="showUploadBtn"--> + <!--style="margin-right: 1rem"--> + <!--type="button"--> + <!--[nzLoading]="uploading"--> + <!--(click)="handleUpload()"--> + <!--[disabled]="!videoFile || uploading">--> + <!--<i nz-icon type="upload" theme="outline"></i>--> + <!--<span>{{ uploading ? 'Uploading' : 'Start Upload' }}</span>--> + <!--</button>--> + + <!-- + <button type="button" + (click)="extraCover()" + nz-button nzType="default" + [disabled]=" !(videoUrl && videoUrl.constructor.name === 'String')">设置å°é¢</button> + --> + <!-- + <nz-divider></nz-divider> + + <div [style.display]="!uploading?'none':''" style="position:relative"> + <div style="width: calc( 100% - 20px);"> + <nz-progress [nzPercent]="progress"> + </nz-progress> + </div> + <i (click)="cancelUpload()" class="anticon anticon-close-circle" style="position: absolute;top: 50%;right: 0;transform: translateY(-50%);cursor: pointer"></i> + </div> + --> + + +</div> +<div class="p-box d-flex align-items-center p-video-uploader"> + <div class="p-upload-icon" *ngIf="!showUploadBtn && !videoUrl && !uploading"> + <i nz-icon nzType="upload" nzTheme="outline"></i> + <div class="m-3"></div> + <span>Click here to upload video</span> + <div class="mt-5 p-progress-bar" *ngIf="uploading"> + <div class="p-progress-bg" [style.width]="progress*0.2+'rem'"></div> + <div class="p-progress-value">{{progress}}%</div> + </div> + </div> + <div class="p-upload-progress-bg dddd " *ngIf="uploading" + [ngClass]="{'smart-bar': showUploadBtn}" > + <div class="i-bg" [style.width]="progress+'%'"></div> + <div class="i-text"> + <fa-icon icon="cloud-upload-alt"></fa-icon> + Uploading... + </div> + </div> + <div class="p-upload-check-bg" *ngIf="checking"> + <div class="i-bg" [style.width]="progress+'%'"></div> + <div class="i-text"> + <fa-icon icon="cloud-upload-alt"></fa-icon> + <i nz-icon nzType="loading" nzTheme="outline"></i>Checking... + </div> + </div> + <div class="p-preview" *ngIf="!uploading && videoUrl " > + <!--<video crossorigin="anonymous" [src]="videoUrl" controls #videoNode></video>--> + <video [src]="safeVideoUrl(videoUrl)" controls #videoNode></video> + </div> +</div> +<div [style.display]="!checkVideoExists?'none':''"> + <span><i nz-icon nzType="loading" nzTheme="outline"></i> checking file to upload</span> +</div> +</div> + + + diff --git a/form/src/app/common/upload-video/upload-video.component.scss b/form/src/app/common/upload-video/upload-video.component.scss new file mode 100644 index 0000000..3e0fc1c --- /dev/null +++ b/form/src/app/common/upload-video/upload-video.component.scss @@ -0,0 +1,152 @@ +@import '../../style/common_mixin.css'; +/*.p-video-box{ + bottom: 0; + border: 2px dashed #ddd; + border-radius: 0.5rem; + background-color: #fafafa; + text-align: center; + color: #aaa; + padding-top: 56.25%; + //font-size: 4rem; + position: relative; + .p-upload-icon{ + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50% ,-50%); + } +}*/ +.p-video-uploader { + position: relative; + display: block; + width: 100%; + height: 0; + padding-bottom: 56.25%; + .p-box { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + border: 2px dashed #ddd; + //border-radius: 0.5rem; + background-color: #fafafa; + text-align: center; + color: #aaa; + + + } +} +.p-upload-icon { + text-align: center; + margin: auto; + +} +.p-upload-icon .anticon-upload { + color: #888; + font-size: 5rem; +} +p-progress-bar { + position: relative; + width: 20rem; + height: 1.5rem; + border: 1px solid #ccc; + border-radius: 1rem; + +} +.p-progress-bar .p-progress-bg { + background-color: #1890ff; + border-radius: 1rem; + height: 100%; +} +.p-progress-bar .p-progress-value { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-shadow: 0 0 4px #000; + color: white; + text-align: center; + font-size: 0.9rem; + line-height: 1.5rem; +} +.p-preview { + width: 100%; + height: 100%; + //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"); + +} +.p-preview video{ + max-height: 100%; + max-width: 100%; + position: absolute; + display: flex; + } +.p-btn-delete { + position: absolute; + right: -0.5rem; + top: -0.5rem; + width: 2rem; + height: 2rem; + border: 0.2rem solid white; + border-radius: 50%; + font-size: 1.2rem; + background-color: #fb781a; + color: white; + text-align: center; +} + +.p-upload-progress-bg, .p-upload-check-bg { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + & .i-text { + position: absolute; + text-align: center; + color: white; + text-shadow: 0 0 2px rgba(0, 0, 0, .85); + } + & .i-bg { + position: absolute; + left: 0; + top: 0; + height: 100%; + background-color: #1890ff; + //border-radius: 0.5rem 0 0 0.5rem; + } +} +.p-upload-progress-bg.smart-bar{ + height: 50px!important; + margin-top: 20px!important; +} +.p-upload-check-bg { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + & .i-text { + position: absolute; + text-align: center; + color: white; + text-shadow: 0 0 2px rgba(0, 0, 0, .85); + } + & .i-bg { + position: absolute; + left: 0; + top: 0; + height: 100%; + background-color: #17a2b8; + //border-radius: 0.5rem 0 0 0.5rem; + } +} + + +//:host ::ng-deep .ant-upload { +// display: block; +//} diff --git a/form/src/app/common/upload-video/upload-video.component.ts b/form/src/app/common/upload-video/upload-video.component.ts new file mode 100644 index 0000000..013f8ad --- /dev/null +++ b/form/src/app/common/upload-video/upload-video.component.ts @@ -0,0 +1,211 @@ +import {Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, Output, SecurityContext, ViewChild} from '@angular/core'; +import {NzMessageService, UploadChangeParam, UploadFile, UploadFileStatus} from 'ng-zorro-antd'; +import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser'; + + +@Component({ + selector: 'app-upload-video', + templateUrl: './upload-video.component.html', + styleUrls: ['./upload-video.component.scss'] +}) +export class UploadVideoComponent implements OnChanges, OnDestroy { + uploading = false; + checking = false; + checkVideoExists = false; + uploadClicked = false; + + @Input() + videoFile = null; + uploaderInst = null; + + progress = 0; + // @Input() + // setCovering = false; + + @Input() + videoUrl = ''; + @ViewChild('videoNode', {static: true }) + videoNode: ElementRef; + + + + + // @Input() + // extractCoverFunc = null; + + @Output() + videoUploaded = new EventEmitter(); + @Output() + videoUploadFailure = new EventEmitter(); + @Output() + extractVideoCover = new EventEmitter(); + + + @Input() + showUploadBtn = true; + @Input() + item: any; + // videoItem = null; + + uploadUrl; + uploadData; + + constructor(private nzMessageService: NzMessageService, + private sanitization: DomSanitizer + // private cwService: _coursewareService, + // private resService: ResourceService + ) { + this.uploading = false; + this.videoFile = null; + + + this.uploadUrl = (<any> window).courseware.uploadUrl(); + this.uploadData = (<any> window).courseware.uploadData(); + + window['air'].getUploadCallback = (url, data) => { + + this.uploadUrl = url; + this.uploadData = data; + }; + + } + ngOnChanges() { + // if (!this.videoFile || this.showUploadBtn) { + // return; + // } + // this.beforeUpload(this.videoFile); + // this.handleUpload(); + } + ngOnDestroy(): void { + URL.revokeObjectURL(this.videoUrl); + } + + safeVideoUrl(url) { + console.log(url); + return this.sanitization.bypassSecurityTrustResourceUrl(url); // `${url}`; + } + videoLoadedMetaData() { + + } + + + handleChange(info: UploadChangeParam/* { type: string, file: UploadFile, event: any }*/): void { + + console.log('info:' , info); + + switch (info.type) { + case 'start': + + // this.beforeUpload(info.file); + + + if (!this.checkSelectFile(info.file)) { + return; + } + + + this.uploading = true; + this.progress = 0; + + break; + + case 'success': + + + this.uploadSuccess(info.file); + + // this.beforeUpload(info.file); + // this.uploadSuccess(info.file); + + break; + case 'progress': + this.progress = info.event.percent; + this.doProgress(this.progress); + break; + } + } + + + checkSelectFile(file) { + if (!file.lastModified) { + return false; + } + const delta = 500; + const isOverSize = (file.size / 1024 / 1024) < delta; + if (!isOverSize) { + this.nzMessageService.error(`video must smaller than ${delta}MB!`); + return false; + } + return true; + } + checkHashFinish = (hash) => { + this.checking = false; + this.uploading = true; + } + + uploadSuccess = (file) => { + + this.nzMessageService.info('Upload Success'); + // this.updateStatus(false); + this.uploading = false; + this.videoFile = null; + // this.updateSource(url); + this.videoUrl = file.response.url; + // console.log(this.picUrl) + // this.uploadFinished(url); + // if (!inOSS) { + const vid = document.createElement('video'); + vid.addEventListener('loadedmetadata', () => { + const height = vid.videoHeight; + const width = vid.videoWidth; + let duration = vid.duration; + if (duration) { + duration = duration * 1000; + } + file.height = height; + file.width = width; + file.duration = duration; + vid.preload = 'none'; + vid.src = ''; + vid.remove(); + + this.videoUploaded.emit(file.response); + + // this.resService.updateVideo(id, {width, height, duration}).then( () => { + // this.videoUploaded.emit({res_id: id, id, name, hash, url}); + // }); + + }); + vid.src = file.response.url; + // } else { + // this.videoUploaded.emit(file.response); + // } + + + + } + + + + uploadFailure = (err, file) => { + this.uploading = false; + if (err.name && err.name === 'cancel') { + return; + } + console.log(err); + this.nzMessageService.error('Upload Error ' + err.message); + this.videoUploadFailure.emit(file); + } + + doProgress = (p) => { + if (p > 1) { + p = 1; + } + if (p < 0) { + p = 0; + } + // console.log(Math.floor(p * 100)); + this.progress = Math.floor(p * 100); + } +} + diff --git a/form/src/app/form/form.component.css b/form/src/app/form/form.component.css new file mode 100644 index 0000000..5d78cd0 --- /dev/null +++ b/form/src/app/form/form.component.css @@ -0,0 +1,35 @@ +@import '../style/common_mixin.css'; + + +.model-content { + width: 100%; + height: 100%; + +} + +.radioPaire { + float: left; + margin: 3px; + border-style: dashed; + border-color: #000; + border-width: 1px; +} + +.border { + border-radius: 20px; + border-style: dashed; + padding: 20px; + margin: 20px; + /*width: 500px; */ + /*//border-radius: 20px;*/ + /*//border-width: 2px;*/ + /*//border-color: #000000;*/ +} + + +.border-lite { + border: 2px dashed #ddd; + border-radius: 0.5rem; + padding: 10px; + margin: 10px; +} diff --git a/form/src/app/form/form.component.html b/form/src/app/form/form.component.html new file mode 100644 index 0000000..3836ff9 --- /dev/null +++ b/form/src/app/form/form.component.html @@ -0,0 +1,36 @@ +<div class="model-content"> + <!-- <div class="border" style=" width: 520px; height: 120px;"> + <span style="height: 30px; font-size: 18px;">å•è¯éŸ³é¢‘:</span> + <br> + <app-audio-recorder [audioUrl]=" item.audio" (audioUploaded)="onAudioUploadSuccess($event)"> + </app-audio-recorder> + </div> + <div class="border" style="width: 520px;"> + <span style="height: 30px; font-size: 18px;">æ£ç¡®å—æ¯ï¼š</span> + <div> + <div *ngFor="let rightWord of item.rightWordList; let i = index"> + <div style="padding: 2px;"> + <input style="width: 150px;float: left;" type="text" nz-input [(ngModel)]="rightWord.word" (blur)="save()"> + <app-audio-recorder style="float: left;" [audioUrl]="rightWord.audio" + (audioUploaded)="onRightAudioUploadSuccess($event, i)"> + </app-audio-recorder> + <button style="float: right; margin-left: 10px; height: 32px; color: red;" nz-button nzType="dashed" + class="add-btn" (click)="removeRightWord(i)"> + <i nz-icon nzType="minus-circle" nzTheme="outline"></i> + åˆ é™¤å—æ¯ + </button> + </div> + <br> <br> + </div> + </div> + <div *ngIf="(item.rightWordList.length +item.wrongWordList.length < 5)"> + <button style="margin-left: 2px; margin-top: 2px; height: 32px;" nz-button nzType="dashed" class="add-btn" + (click)="addRightWord()"> + <i nz-icon nzType="plus-circle" nzTheme="outline"></i> + æ·»åŠ <span style="color: #44bb44;">æ£ç¡®</span>çš„å—æ¯ + </button> + </div> + </div> + --> + +</div> diff --git a/form/src/app/form/form.component.ts b/form/src/app/form/form.component.ts new file mode 100644 index 0000000..082e3ec --- /dev/null +++ b/form/src/app/form/form.component.ts @@ -0,0 +1,115 @@ +import { Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef } from '@angular/core'; +import { JsonPipe } from '@angular/common'; + + +@Component({ + selector: 'app-form', + templateUrl: './form.component.html', + styleUrls: ['./form.component.css'] +}) +export class FormComponent implements OnInit, OnChanges, OnDestroy { + + // å‚¨å˜æ•°æ®ç”¨ + saveKey = "test_001"; + // 储å˜å¯¹è±¡ + item; + + constructor(private appRef: ApplicationRef, private changeDetectorRef: ChangeDetectorRef) { + + } + + createShell() { + this.item.wordList.push({ + word: '', + audio: '', + backWord: '', + backWordAudio: '', + }); + this.save(); + } + + removeShell(idx) { + this.item.wordList.splice(idx, 1); + this.save(); + } + + ngOnInit() { + + this.item = { + wordList: [] + }; + + // 获å–å˜å‚¨çš„æ•°æ® + (<any>window).courseware.getData((data) => { + + if (data) { + this.item = data; + } + + this.init(); + this.changeDetectorRef.markForCheck(); + this.changeDetectorRef.detectChanges(); + this.refresh(); + + }, this.saveKey); + } + + ngOnChanges() { + } + + ngOnDestroy() { + } + + init() { + + } + + + /** + * 储å˜å›¾ç‰‡æ•°æ® + * @param e + */ + onImageUploadSuccess(e, key) { + + this.item[key] = e.url; + this.save(); + } + + /** + * 储å˜éŸ³é¢‘æ•°æ® + * @param e + */ + onAudioUploadSuccess(e) { + this.item.audio = e.url; + this.save(); + } + + onWordAudioUploadSuccess(e, idx) { + this.item.wordList[idx].audio = e.url; + this.save(); + } + + onBackWordAudioUploadSuccess(e, idx) { + this.item.wordList[idx].backWordAudio = e.url; + this.save(); + } + + /** + * å‚¨å˜æ•°æ® + */ + save() { + (<any>window).courseware.setData(this.item, null, this.saveKey); + this.refresh(); + console.log('this.item = ' + JSON.stringify(this.item)); + } + + /** + * 刷新 æ¸²æŸ“é¡µé¢ + */ + refresh() { + setTimeout(() => { + this.appRef.tick(); + }, 1); + } + +} \ No newline at end of file diff --git a/form/src/app/pipes/background-image.pipe.ts b/form/src/app/pipes/background-image.pipe.ts new file mode 100644 index 0000000..bc15f66 --- /dev/null +++ b/form/src/app/pipes/background-image.pipe.ts @@ -0,0 +1,23 @@ +import {Pipe, PipeTransform} from '@angular/core'; +// import {ElectronUtil} from '../util/ElectronUtil'; + +declare const APP_PATH; +// const isInElectron = localStorage.getItem('electron'); + +@Pipe({ + name: 'backgroundImage' +}) +export class BackgroundImagePipe implements PipeTransform { + + transform(value: any, coursewareSid?: string) { + // const ret = value ? `url(${value})` : ''; + const ret = value ? `url(${value})` : ''; + return ret; + // let ret = value > 0 ? `url(/api/media-resource/${value}/file)` : ''; + // if (isInElectron && ElectronUtil.hasCached(coursewareSid, value)) { + // ret = `url(file://${APP_PATH}/courseware_cache/${coursewareSid}/${value})`; + // } + // return ret; + } + +} diff --git a/form/src/app/pipes/resource.pipe.ts b/form/src/app/pipes/resource.pipe.ts new file mode 100644 index 0000000..d7f5f8d --- /dev/null +++ b/form/src/app/pipes/resource.pipe.ts @@ -0,0 +1,28 @@ +import {Pipe, PipeTransform} from '@angular/core'; +// import {ElectronUtil} from '../util/ElectronUtil'; + +declare const APP_PATH; +// const isInElectron = localStorage.getItem('electron'); + +@Pipe({ + name: 'resource' +}) +export class ResourcePipe implements PipeTransform { + + transform(pic_url: any, coursewareSid?: string): string { + // return pic_url; + if (pic_url && typeof pic_url === 'object') { + return pic_url; + } + // console.log('resource', pic_url) + return `${pic_url}?t=${Math.random()}`; + + // let ret = value ? `/api/resource/${value}/file` : ''; + // let ret = res_id ? `/resource/audio/${res_id}` : ''; + // if (isInElectron && ElectronUtil.hasCached(coursewareSid, res_id)) { + // ret = `file://${APP_PATH}/courseware_cache/${coursewareSid}/${res_id}`; + // } + // return ret; + } + +} diff --git a/form/src/app/pipes/time.pipe.ts b/form/src/app/pipes/time.pipe.ts new file mode 100644 index 0000000..af84a0c --- /dev/null +++ b/form/src/app/pipes/time.pipe.ts @@ -0,0 +1,19 @@ +import {Pipe, PipeTransform} from '@angular/core'; +import * as _ from 'lodash'; + +@Pipe({ + name: 'time' +}) +export class TimePipe implements PipeTransform { + + transform(value: any, args?: any): any { + let ret = '00:00'; + if (_.isNumber(value) && value > 0) { + const minutes = Math.floor(value / 60); + const seconds = Math.floor(value % 60); + ret = _.padStart(minutes, 2, '0') + ':' + _.padStart(seconds, 2, '0'); + } + return ret; + } + +} diff --git a/form/src/app/play/Unit.ts b/form/src/app/play/Unit.ts new file mode 100644 index 0000000..4a84782 --- /dev/null +++ b/form/src/app/play/Unit.ts @@ -0,0 +1,1676 @@ + +import TWEEN from '@tweenjs/tween.js'; + +interface AirWindow extends Window { + air: any; + curCtx: any; +} +declare let window: AirWindow; + +class Sprite { + x = 0; + y = 0; + color = ''; + radius = 0; + alive = false; + margin = 0; + angle = 0; + ctx; + + constructor(ctx = null) { + if (!ctx) { + this.ctx = window.curCtx; + } else { + this.ctx = ctx; + } + } + update($event) { + this.draw(); + } + draw() { + + } + +} + + + + + +export class MySprite extends Sprite { + + _width = 0; + _height = 0; + _anchorX = 0; + _anchorY = 0; + _offX = 0; + _offY = 0; + scaleX = 1; + scaleY = 1; + _alpha = 1; + rotation = 0; + visible = true; + skewX = 0; + skewY = 0; + + _shadowFlag = false; + _shadowColor; + _shadowOffsetX = 0; + _shadowOffsetY = 0; + _shadowBlur = 5; + + _radius = 0; + + children = [this]; + + childDepandVisible = true; + childDepandAlpha = false; + + img; + _z = 0; + + + init(imgObj = null, anchorX: number = 0.5, anchorY: number = 0.5) { + + if (imgObj) { + + this.img = imgObj; + + this.width = this.img.width; + this.height = this.img.height; + + + } + + this.anchorX = anchorX; + this.anchorY = anchorY; + } + + + setShadow(offX, offY, blur, color = 'rgba(0, 0, 0, 0.3)') { + + + this._shadowFlag = true; + this._shadowColor = color; + this._shadowOffsetX = offX; + this._shadowOffsetY = offY; + this._shadowBlur = blur; + + } + + setRadius(r) { + this._radius = r; + } + + + update($event = null) { + if (!this.visible && this.childDepandVisible) { + return; + } + + this.draw(); + + } + draw() { + + this.ctx.save(); + + this.drawInit(); + + this.updateChildren(); + + this.ctx.restore(); + + + } + + drawInit() { + + this.ctx.translate(this.x, this.y); + + this.ctx.rotate(this.rotation * Math.PI / 180); + + this.ctx.scale(this.scaleX, this.scaleY); + + this.ctx.globalAlpha = this.alpha; + + this.ctx.transform(1, this.skewX, this.skewY, 1, 0, 0); + + + + + + if (this._radius) { + + const r = this._radius; + const w = this.width; + const h = this.height; + + this.ctx.lineTo(-w / 2, h / 2); // 创建水平线 + this.ctx.arcTo(-w / 2, -h / 2, -w / 2 + r, -h / 2, r); + this.ctx.arcTo(w / 2, -h / 2, w / 2, -h / 2 + r, r); + this.ctx.arcTo(w / 2, h / 2, w / 2 - r, h / 2, r); + this.ctx.arcTo(-w / 2, h / 2, -w / 2, h / 2 - r, r); + + this.ctx.clip(); + } + + } + + drawSelf() { + + + + if (this._shadowFlag) { + + this.ctx.shadowOffsetX = this._shadowOffsetX; + this.ctx.shadowOffsetY = this._shadowOffsetY; + this.ctx.shadowBlur = this._shadowBlur; + this.ctx.shadowColor = this._shadowColor; + } else { + this.ctx.shadowOffsetX = 0; + this.ctx.shadowOffsetY = 0; + this.ctx.shadowBlur = null; + this.ctx.shadowColor = null; + } + + + if (this.img) { + this.ctx.drawImage(this.img, this._offX, this._offY); + } + + + + + } + + updateChildren() { + + if (this.children.length <= 0) { return; } + + for (const child of this.children) { + if (child === this) { + if (this.visible) { + this.drawSelf(); + } + } else { + child.update(); + } + } + } + + + load(url, anchorX = 0.5, anchorY = 0.5) { + + return new Promise((resolve, reject) => { + const img = new Image(); + img.onload = () => resolve(img); + img.onerror = reject; + img.src = url; + }).then(img => { + + this.init(img, anchorX, anchorY); + return img; + }); + } + + addChild(child, z = 1) { + if (this.children.indexOf(child) === -1) { + this.children.push(child); + child._z = z; + child.parent = this; + } + + this.children.sort((a, b) => { + return a._z - b._z; + }); + + + if (this.childDepandAlpha) { + child.alpha = this.alpha; + } + + } + removeChild(child) { + const index = this.children.indexOf(child); + if (index !== -1) { + this.children.splice(index, 1); + } + } + + removeChildren() { + for (let i = 0; i < this.children.length; i++) { + if (this.children[i]) { + if (this.children[i] !== this) { + this.children.splice(i, 1); + i --; + } + } + } + } + + _changeChildAlpha(alpha) { + for (const child of this.children) { + if (child !== this) { + child.alpha = alpha; + } + } + } + + set alpha(v) { + this._alpha = v; + if (this.childDepandAlpha) { + this._changeChildAlpha(v); + } + } + get alpha() { + return this._alpha; + } + set width(v) { + this._width = v; + this.refreshAnchorOff(); + } + get width() { + return this._width; + } + set height(v) { + this._height = v; + this.refreshAnchorOff(); + } + get height() { + return this._height; + } + set anchorX(value) { + this._anchorX = value; + this.refreshAnchorOff(); + } + get anchorX() { + return this._anchorX; + } + set anchorY(value) { + this._anchorY = value; + this.refreshAnchorOff(); + } + get anchorY() { + return this._anchorY; + } + refreshAnchorOff() { + this._offX = -this._width * this.anchorX; + this._offY = -this._height * this.anchorY; + } + + setScaleXY(value) { + this.scaleX = this.scaleY = value; + } + + getBoundingBox() { + + + const getParentData = (item) => { + + let px = item.x; + let py = item.y; + + let sx = item.scaleX; + let sy = item.scaleY; + const parent = item.parent; + if (parent) { + + const obj = getParentData(parent); + + const _x = obj.px; + const _y = obj.py; + const _sx = obj.sx; + const _sy = obj.sy; + + px = _x + item.x * _sx; + py = _y + item.y * _sy; + + sx *= _sx; + sy *= _sy; + + } + + return {px, py, sx, sy}; + }; + + + const data = getParentData(this); + + + const x = data.px + this._offX * Math.abs(data.sx); + const y = data.py + this._offY * Math.abs(data.sy); + const width = this.width * Math.abs(data.sx); + const height = this.height * Math.abs(data.sy); + + // const x = this.x + this._offX * Math.abs(this.scaleX); + // const y = this.y + this._offY * Math.abs(this.scaleY); + // const width = this.width * Math.abs(this.scaleX); + // const height = this.height * Math.abs(this.scaleY); + + return {x, y, width, height}; + } + +} + + + + + +export class ColorSpr extends MySprite { + + r = 0; + g = 0; + b = 0; + + createGSCanvas() { + + if (!this.img) { + return; + } + + + + const rect = this.getBoundingBox(); + if (rect.width <= 1 || rect.height <= 1) { + return; + } + + + const c = this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height); + for ( let i = 0; i < c.height; i++) { + for ( let j = 0; j < c.width; j++) { + + const x = (i * 4) * c.width + ( j * 4 ); + const r = c.data[x]; + const g = c.data[x + 1]; + const b = c.data[x + 2]; + + c.data[x] = this.r; + c.data[x + 1] = this.g; + c.data[x + 2] = this.b; + + + + // c.data[x] = c.data[x + 1] = c.data[x + 2] = (r + g + b) / 3 ; + // // c.data[x + 3] = 255; + } + } + + this.ctx.putImageData(c, rect.x, rect.y, 0, 0, rect.width, rect.height); + } + + + drawSelf() { + super.drawSelf(); + this.createGSCanvas(); + } + +} + + +export class GrayscaleSpr extends MySprite { + + grayScale = 120; + + createGSCanvas() { + + if (!this.img) { + return; + } + + + + const rect = this.getBoundingBox(); + + const c = this.ctx.getImageData(rect.x, rect.y, rect.width, rect.height); + for ( let i = 0; i < c.height; i++) { + for ( let j = 0; j < c.width; j++) { + + const x = (i * 4) * c.width + ( j * 4 ); + const r = c.data[x]; + const g = c.data[x + 1]; + const b = c.data[x + 2]; + // const a = c.data[x + 3]; + + c.data[x] = c.data[x + 1] = c.data[x + 2] = this.grayScale; // (r + g + b) / 3; + // c.data[x + 3] = 255; + } + } + + this.ctx.putImageData(c, rect.x, rect.y, 0, 0, rect.width, rect.height); + } + + + drawSelf() { + super.drawSelf(); + this.createGSCanvas(); + } + +} + + + + + + +export class BitMapLabel extends MySprite { + + + labelArr; + baseUrl; + + setText(data, text) { + + this.labelArr = []; + + const labelArr = []; + const tmpArr = text.split(''); + let totalW = 0; + let h = 0; + for (const tmp of tmpArr) { + + const label = new MySprite(this.ctx); + label.init(data[tmp], 0); + this.addChild(label); + labelArr.push(label); + + totalW += label.width; + h = label.height; + } + + + this.width = totalW; + this.height = h; + + let offX = -totalW / 2; + for (const label of labelArr) { + label.x = offX; + offX += label.width; + } + + this.labelArr = labelArr; + } + +} + + + + +export class Label extends MySprite { + + text: string; + // fontSize:String = '40px'; + fontName = 'Verdana'; + textAlign = 'left'; + fontSize = 40; + fontColor = '#000000'; + fontWeight = 900; + _maxWidth; + outline = 0; + outlineColor = '#ffffff'; + + // _shadowFlag = false; + // _shadowColor; + // _shadowOffsetX; + // _shadowOffsetY; + // _shadowBlur; + + _outlineFlag = false; + _outLineWidth; + _outLineColor; + + + constructor(ctx = null) { + super(ctx); + this.init(); + } + + refreshSize() { + + this.ctx.save(); + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = this.fontWeight; + + this._width = this.ctx.measureText(this.text).width; + this._height = this.fontSize; + this.refreshAnchorOff(); + + this.ctx.restore(); + + } + + setMaxSize(w) { + + this._maxWidth = w; + this.refreshSize(); + if (this.width >= w) { + this.scaleX *= w / this.width; + this.scaleY *= w / this.width; + } + } + + show(callBack = null) { + + this.visible = true; + + if (this.alpha >= 1) { + return; + } + + const tween = new TWEEN.Tween(this) + .to({ alpha: 1 }, 800) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }) + .start(); // Start the tween immediately. + } + + // setShadow(offX = 0, offY = 2, blur = 2, color = 'rgba(0, 0, 0, 0.2)') { + // + // this._shadowFlag = true; + // this._shadowColor = color; + // // 将阴影å‘å³ç§»åЍ15px,å‘上移动10px + // this._shadowOffsetX = 5; + // this._shadowOffsetY = 5; + // // 轻微模糊阴影 + // this._shadowBlur = 5; + // } + + setOutline(width = 5, color = '#ffffff') { + + this._outlineFlag = true; + this._outLineWidth = width; + this._outLineColor = color; + + } + + drawText() { + + // console.log('in drawText', this.text); + + if (!this.text) { return; } + + + // if (this._shadowFlag) { + // + // this.ctx.shadowColor = this._shadowColor; + // // 将阴影å‘å³ç§»åЍ15px,å‘上移动10px + // this.ctx.shadowOffsetX = this._shadowOffsetX; + // this.ctx.shadowOffsetY = this._shadowOffsetY; + // // 轻微模糊阴影 + // this.ctx.shadowBlur = this._shadowBlur; + // } + + + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = this.fontWeight; + + if (this._outlineFlag) { + this.ctx.lineWidth = this._outLineWidth; + this.ctx.strokeStyle = this._outLineColor; + this.ctx.strokeText(this.text, 0, 0); + } + + this.ctx.fillStyle = this.fontColor; + + + + if (this.outline > 0) { + this.ctx.lineWidth = this.outline; + this.ctx.strokeStyle = this.outlineColor; + this.ctx.strokeText(this.text, 0, 0); + + } + + this.ctx.fillText(this.text, 0, 0); + + + } + + + drawSelf() { + super.drawSelf(); + this.drawText(); + } + +} + +export class RichTextOld extends Label { + + textArr = []; + fontSize = 40; + + setText(text: string, words) { + + let newText = text; + for (const word of words) { + + const re = new RegExp(word, 'g'); + newText = newText.replace( re, `#${word}#`); + // newText = newText.replace(word, `#${word}#`); + } + + this.textArr = newText.split('#'); + this.text = newText; + + // this.setSize(); + } + + refreshSize() { + + this.ctx.save(); + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = this.fontWeight; + + let curX = 0; + for (const text of this.textArr) { + const w = this.ctx.measureText(text).width; + curX += w; + } + + this.width = curX; + this.height = this.fontSize; + this.refreshAnchorOff(); + + this.ctx.restore(); + + } + + + show(callBack = null) { + + // console.log(' in show '); + this.visible = true; + // this.alpha = 0; + + const tween = new TWEEN.Tween(this) + .to({ alpha: 1 }, 800) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }) + .start(); // Start the tween immediately. + + } + + + + drawText() { + + // console.log('in drawText', this.text); + + if (!this.text) { return; } + + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = 900; + + this.ctx.lineWidth = 5; + this.ctx.strokeStyle = '#ffffff'; + // this.ctx.strokeText(this.text, 0, 0); + + this.ctx.fillStyle = '#000000'; + // this.ctx.fillText(this.text, 0, 0); + + + let curX = 0; + for (let i = 0; i < this.textArr.length; i++) { + + const w = this.ctx.measureText(this.textArr[i]).width; + + if ((i + 1) % 2 === 0) { + this.ctx.fillStyle = '#c8171e'; + } else { + this.ctx.fillStyle = '#000000'; + } + + this.ctx.fillText(this.textArr[i], curX, 0); + curX += w; + + } + + + } + +} + + + + + +export class RichText extends Label { + + + disH = 30; + + constructor(ctx?: any) { + super(ctx); + + // this.dataArr = dataArr; + } + + + + drawText() { + + if (!this.text) { + return; + } + + + this.ctx.font = `${this.fontSize}px ${this.fontName}`; + this.ctx.textAlign = this.textAlign; + this.ctx.textBaseline = 'middle'; + this.ctx.fontWeight = this.fontWeight; + this.ctx.fillStyle = this.fontColor; + + + const selfW = this.width * this.scaleX; + + + const chr = this.text.split(' '); + let temp = ''; + const row = []; + const w = selfW - 80; + const disH = (this.fontSize + this.disH) * this.scaleY; + + + + + for (const c of chr) { + if (this.ctx.measureText(temp).width < w && this.ctx.measureText(temp + (c)).width <= w) { + temp += ' ' + c; + } else { + row.push(temp); + temp = ' ' + c; + } + } + row.push(temp); + + const x = 0; + const y = -row.length * disH / 2; + // for (let b = 0 ; b < row.length; b++) { + // this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // æ¯è¡Œå—体yåæ ‡é—´éš”20 + // } + + + if (this._outlineFlag) { + this.ctx.lineWidth = this._outLineWidth; + this.ctx.strokeStyle = this._outLineColor; + for (let b = 0 ; b < row.length; b++) { + this.ctx.strokeText(row[b], x, y + ( b + 1 ) * disH ); // æ¯è¡Œå—体yåæ ‡é—´éš”20 + } + // this.ctx.strokeText(this.text, 0, 0); + } + + + // this.ctx.fillStyle = '#ff7600'; + for (let b = 0 ; b < row.length; b++) { + this.ctx.fillText(row[b], x, y + ( b + 1 ) * disH ); // æ¯è¡Œå—体yåæ ‡é—´éš”20 + } + + } + + + drawSelf() { + super.drawSelf(); + this.drawText(); + } + +} + + + + +export class LineRect extends MySprite { + + lineColor = '#ffffff'; + lineWidth = 10; + + setSize(w, h) { + this.width = w; + this.height = h; + } + + drawLine() { + + this.ctx.beginPath(); + this.ctx.moveTo(this._offX, this._offY); + this.ctx.lineTo(this._offX + this.width, this._offY); + this.ctx.lineTo(this._offX + this.width, this._offY + this.height); + this.ctx.lineTo(this._offX, this._offY + this.height); + this.ctx.closePath(); + + this.ctx.lineWidth = this.lineWidth; + // this.ctx.fillStyle = "rgb(2,33,42)"; //指定填充颜色 + // this.ctx.fill(); //对多边形进行填充 + + this.ctx.strokeStyle = this.lineColor; // "#ffffff"; + this.ctx.stroke(); + + } + + + drawSelf() { + super.drawSelf(); + this.drawLine(); + } +} + + +export class ShapeRect extends MySprite { + + fillColor = '#FF0000'; + + setSize(w, h) { + this.width = w; + this.height = h; + + // console.log('w:', w); + // console.log('h:', h); + } + + drawShape() { + + this.ctx.fillStyle = this.fillColor; + this.ctx.fillRect(this._offX, this._offY, this.width, this.height); + + } + + + drawSelf() { + super.drawSelf(); + this.drawShape(); + } +} + + + +export class ShapeCircle extends MySprite { + + fillColor = '#FF0000'; + radius = 0; + + + setRadius(r) { + this.anchorX = this.anchorY = 0.5; + + this.radius = r; + this.width = r * 2; + this.height = r * 2; + } + + drawShape() { + + this.ctx.beginPath(); + this.ctx.fillStyle = this.fillColor; + this.ctx.arc(0, 0, this.radius, 0, angleToRadian(360)); + this.ctx.fill(); + } + + drawSelf() { + super.drawSelf(); + this.drawShape(); + } +} + +export class ShapeRectNew extends MySprite { + + + radius = 0; + fillColor = '#ffffff'; + strokeColor = '#000000'; + fill = true; + stroke = false; + lineWidth = 1; + + setSize(w, h, r) { + this.width = w; + this.height = h; + this.radius = r; + } + + setOutLine(color, lineWidth) { + this.stroke = true; + this.strokeColor = color; + this.lineWidth = lineWidth; + } + + + drawShape() { + + const ctx = this.ctx; + const width = this.width; + const height = this.height; + const radius = this.radius; + + ctx.save(); + ctx.beginPath(0); + // 从å³ä¸‹è§’顺时针绘制,弧度从0到1/2PI + ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2); + + // 矩形下边线 + ctx.lineTo(radius, height); + + // 左下角圆弧,弧度从1/2PI到PI + ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI); + + // 矩形左边线 + ctx.lineTo(0, radius); + + // 左上角圆弧,弧度从PI到3/2PI + ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2); + + // 上边线 + ctx.lineTo(width - radius, 0); + + // å³ä¸Šè§’圆弧 + ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2); + + // å³è¾¹çº¿ + ctx.lineTo(width, height - radius); + ctx.closePath(); + + if (this.fill) { + ctx.fillStyle = this.fillColor; + ctx.fill(); + } + if (this.stroke) { + ctx.lineWidth = this.lineWidth; + ctx.strokeStyle = this.strokeColor; + ctx.stroke(); + } + ctx.restore(); + + } + + + drawSelf() { + super.drawSelf(); + this.drawShape(); + } + +} +export class MyAnimation extends MySprite { + + + frameArr = []; + frameIndex = 0; + playFlag = false; + lastDateTime; + curDelay = 0; + + + loop = false; + playEndFunc; + delayPerUnit = 1; + + restartFlag = false; + reverseFlag = false; + + addFrameByImg(img) { + + const spr = new MySprite(this.ctx); + spr.init(img); + this._refreshSize(img); + + spr.visible = false; + + this.addChild(spr); + this.frameArr.push(spr); + + this.frameArr[this.frameIndex].visible = true; + } + + addFrameByUrl(url) { + + const spr = new MySprite(this.ctx); + spr.load(url).then(img => { + + this._refreshSize(img); + }); + spr.visible = false; + + this.addChild(spr); + this.frameArr.push(spr); + + this.frameArr[this.frameIndex].visible = true; + } + + _refreshSize(img: any) { + + if (this.width < img.width) { + this.width = img.width; + } + if (this.height < img.height) { + this.height = img.height; + } + } + + + + play() { + this.playFlag = true; + this.lastDateTime = new Date().getTime(); + } + + stop() { + this.playFlag = false; + } + + + replay() { + this.restartFlag = true; + this.play(); + } + + + reverse() { + this.reverseFlag = !this.reverseFlag; + this.frameArr.reverse(); + this.frameIndex = 0; + } + + showAllFrame() { + for (const frame of this.frameArr ) { + frame.alpha = 1; + } + } + + hideAllFrame() { + for (const frame of this.frameArr) { + frame.alpha = 0; + } + } + + + playEnd() { + + this.playFlag = false; + this.curDelay = 0; + + this.frameArr[this.frameIndex].visible = true; + + if (this.playEndFunc) { + this.playEndFunc(); + this.playEndFunc = null; + } + } + + updateFrame() { + if (this.frameArr[this.frameIndex]) { + this.frameArr[this.frameIndex].visible = false; + } + + this.frameIndex ++; + if (this.frameIndex >= this.frameArr.length) { + if (this.loop) { + this.frameIndex = 0; + } else if (this.restartFlag) { + this.restartFlag = false; + this.frameIndex = 0; + } else { + this.frameIndex -- ; + this.playEnd(); + return; + } + } + + this.frameArr[this.frameIndex].visible = true; + + } + + + + + _updateDelay(delay) { + + this.curDelay += delay; + if (this.curDelay < this.delayPerUnit) { + return; + } + this.curDelay -= this.delayPerUnit; + this.updateFrame(); + } + + _updateLastDate() { + if (!this.playFlag) { return; } + + let delay = 0; + if (this.lastDateTime) { + delay = (new Date().getTime() - this.lastDateTime) / 1000; + } + this.lastDateTime = new Date().getTime(); + this._updateDelay(delay); + } + + update($event: any = null) { + super.update($event); + this._updateLastDate(); + } + + +} + + + + +// --------=========== util func =============------------- + + +export function tweenChange(item, obj, time = 0.8, callBack = null, easing = null, update = null) { + + const tween = new TWEEN.Tween(item).to(obj, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + if (update) { + tween.onUpdate( (a, b) => { + update(a, b); + }); + } + + tween.start(); + return tween; +} + + + + +export function rotateItem(item, rotation, time = 0.8, callBack = null, easing = null) { + + const tween = new TWEEN.Tween(item).to({ rotation }, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + + +export function scaleItem(item, scale, time = 0.8, callBack = null, easing = null) { + + const tween = new TWEEN.Tween(item).to({ scaleX: scale, scaleY: scale}, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + + tween.start(); + return tween; +} + + +export function moveItem(item, x, y, time = 0.8, callBack = null, easing = null) { + + const tween = new TWEEN.Tween(item).to({ x, y}, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + + tween.start(); + + return tween; +} + + + + + + + +export function endShow(item, s = 1) { + + item.scaleX = item.scaleY = 0; + item.alpha = 0; + + const tween = new TWEEN.Tween(item) + .to({ alpha: 1, scaleX: s, scaleY: s }, 800) + .easing(TWEEN.Easing.Elastic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + + }) + .start(); +} + +export function hideItem(item, time = 0.8, callBack = null, easing = null) { + + if (item.alpha === 0) { + return; + } + + const tween = new TWEEN.Tween(item) + .to({alpha: 0}, time * 1000) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }); + + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + +export function showItem(item, time = 0.8, callBack = null, easing = null) { + + if (item.alpha === 1) { + if (callBack) { + callBack(); + } + return; + } + + item.visible = true; + const tween = new TWEEN.Tween(item) + .to({alpha: 1}, time * 1000) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }); + + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + +export function alphaItem(item, alpha, time = 0.8, callBack = null, easing = null) { + + + const tween = new TWEEN.Tween(item) + .to({alpha}, time * 1000) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }); + + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + +export function showStar(item, time = 0.8, callBack = null, easing = null) { + + + const tween = new TWEEN.Tween(item) + .to({alpha: 1, scale: 1}, time * 1000) + // .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth. + .onComplete(() => { + if (callBack) { + callBack(); + } + }); + + if (easing) { + tween.easing(easing); + } + + tween.start(); +} + + +export function randomSortByArr(arr) { + const newArr = []; + const tmpArr = arr.concat(); + while (tmpArr.length > 0) { + const randomIndex = Math.floor( tmpArr.length * Math.random() ); + newArr.push(tmpArr[randomIndex]); + tmpArr.splice(randomIndex, 1); + } + return newArr; +} + + +export function radianToAngle(radian) { + return radian * 180 / Math.PI; + // 角度 = 弧度 * 180 / Math.PI; +} + +export function angleToRadian(angle) { + return angle * Math.PI / 180; + // 弧度= 角度 * Math.PI / 180; +} + +export function getPosByAngle(angle, len) { + + const radian = angle * Math.PI / 180; + const x = Math.sin(radian) * len; + const y = Math.cos(radian) * len; + + return {x, y}; + +} + +export function getAngleByPos(px, py, mx, my) { + + const x = Math.abs(px - mx); + const y = Math.abs(py - my); + + const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + const cos = y / z; + const radina = Math.acos(cos); // 用å三角函数求弧度 + let angle = Math.floor(180 / (Math.PI / radina) * 100) / 100; // å°†å¼§åº¦è½¬æ¢æˆè§’度 + + if (mx > px && my > py) {// é¼ æ ‡åœ¨ç¬¬å››è±¡é™ + angle = 180 - angle; + } + if (mx === px && my > py) {// é¼ æ ‡åœ¨yè½´è´Ÿæ–¹å‘上 + angle = 180; + } + if (mx > px && my === py) {// é¼ æ ‡åœ¨xè½´æ£æ–¹å‘上 + angle = 90; + } + if (mx < px && my > py) {// é¼ æ ‡åœ¨ç¬¬ä¸‰è±¡é™ + angle = 180 + angle; + } + if (mx < px && my === py) {// é¼ æ ‡åœ¨xè½´è´Ÿæ–¹å‘ + angle = 270; + } + if (mx < px && my < py) {// é¼ æ ‡åœ¨ç¬¬äºŒè±¡é™ + angle = 360 - angle; + } + + // console.log('angle: ', angle); + return angle; + +} + + +export function removeItemFromArr(arr, item) { + const index = arr.indexOf(item); + if (index !== -1) { + arr.splice(index, 1); + } +} + + + + + + +export function circleMove(item, x0, y0, time = 2, addR = 360, xPer = 1, yPer = 1, callBack = null, easing = null) { + + const r = getPosDistance(item.x, item.y, x0, y0); + let a = getAngleByPos(item.x, item.y, x0, y0); + a += 90; + const obj = {r, a}; + + item._circleAngle = a; + const targetA = a + addR; + + const tween = new TWEEN.Tween(item).to({_circleAngle: targetA}, time * 1000); + + if (callBack) { + tween.onComplete(() => { + callBack(); + }); + } + if (easing) { + tween.easing(easing); + } + + tween.onUpdate( (item, progress) => { + + // console.log(item._circleAngle); + const r = obj.r; + const a = item._circleAngle; + + const x = x0 + r * xPer * Math.cos(a * Math.PI / 180); + const y = y0 + r * yPer * Math.sin(a * Math.PI / 180); + + item.x = x; + item.y = y; + + // obj.a ++; + }); + + tween.start(); +} + + +export function getPosDistance(sx, sy, ex, ey) { + + const _x = ex - sx; + const _y = ey - sy; + const len = Math.sqrt( Math.pow(_x, 2) + Math.pow(_y, 2) ); + return len; +} + +export function delayCall(callback, second) { + const tween = new TWEEN.Tween(this) + .delay(second * 1000) + .onComplete(() => { + if (callback) { + callback(); + } + }) + .start(); +} + + +export function formatTime(fmt, date) { + + // "yyyy-MM-dd HH:mm:ss"; + + const o = { + 'M+': date.getMonth() + 1, // 月份 + 'd+': date.getDate(), // æ—¥ + 'h+': date.getHours(), // å°æ—¶ + 'm+': date.getMinutes(), // 分 + 's+': date.getSeconds(), // ç§’ + 'q+': Math.floor((date.getMonth() + 3) / 3), // å£åº¦ + S: date.getMilliseconds() // 毫秒 + }; + if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); } + for (const k in o) { + if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) + ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))); + } + } + return fmt; +} + +export function getMinScale(item, maxLen) { + const sx = maxLen / item.width; + const sy = maxLen / item.height; + const minS = Math.min(sx, sy); + return minS; +} + + + +export function jelly(item, time = 0.7) { + + + if (item.jellyTween) { + TWEEN.remove(item.jellyTween); + } + + const t = time / 9; + const baseSX = item.scaleX; + const baseSY = item.scaleY; + let index = 0; + + const run = () => { + if (index >= arr.length) { + item.jellyTween = null; + return; + } + const data = arr[index]; + const t = tweenChange(item, {scaleX: data[0], scaleY: data[1]}, data[2], () => { + index ++; + run(); + }, TWEEN.Easing.Sinusoidal.InOut); + item.jellyTween = t; + }; + + const arr = [ + [baseSX * 1.1, baseSY * 0.9, t], + [baseSX * 0.98, baseSY * 1.02, t * 2], + [baseSX * 1.02, baseSY * 0.98, t * 2], + [baseSX * 0.99, baseSY * 1.01, t * 2], + [baseSX * 1.0, baseSY * 1.0, t * 2], + ]; + + + run(); +} + + + +export function showPopParticle(img, pos, parent, num = 20, minLen = 40, maxLen = 80, showTime = 0.4) { + + + for (let i = 0; i < num; i ++) { + + const particle = new MySprite(); + particle.init(img); + particle.x = pos.x; + particle.y = pos.y; + parent.addChild(particle); + + const randomR = 360 * Math.random(); + particle.rotation = randomR; + + const randomS = 0.3 + Math.random() * 0.7; + particle.setScaleXY(randomS * 0.3); + + const randomX = Math.random() * 20 - 10; + particle.x += randomX; + + const randomY = Math.random() * 20 - 10; + particle.y += randomY; + + const randomL = minLen + Math.random() * (maxLen - minLen); + const randomA = 360 * Math.random(); + const randomT = getPosByAngle(randomA, randomL); + moveItem(particle, particle.x + randomT.x, particle.y + randomT.y, showTime, () => { + + + + }, TWEEN.Easing.Exponential.Out); + + // scaleItem(particle, 0, 0.6, () => { + // + // }); + + scaleItem(particle, randomS, 0.6, () => { + + }, TWEEN.Easing.Exponential.Out); + + setTimeout(() => { + + hideItem(particle, 0.4, () => { + + }, TWEEN.Easing.Cubic.In); + + }, showTime * 0.5 * 1000); + + + } +} + + + +export function shake(item, time = 0.5, callback = null, rate = 1) { + + if (item.shakeTween) { + return; + } + + item.shakeTween = true; + const offX = 15 * item.scaleX * rate; + const offY = 15 * item.scaleX * rate; + const baseX = item.x; + const baseY = item.y; + const easing = TWEEN.Easing.Sinusoidal.InOut; + + + const move4 = () => { + moveItem(item, baseX, baseY, time / 4, () => { + item.shakeTween = false; + if (callback) { + callback(); + } + }, easing); + }; + + const move3 = () => { + moveItem(item, baseX + offX / 4, baseY + offY / 4, time / 4, () => { + move4(); + }, easing); + }; + + const move2 = () => { + moveItem(item, baseX - offX / 4 * 3, baseY - offY / 4 * 3, time / 4, () => { + move3(); + }, easing); + }; + + const move1 = () => { + moveItem(item, baseX + offX, baseY + offY, time / 7.5, () => { + move2(); + }, easing); + }; + + move1(); + +} + +// --------------- custom class -------------------- + diff --git a/form/src/app/play/play.component.css b/form/src/app/play/play.component.css new file mode 100644 index 0000000..bbda495 --- /dev/null +++ b/form/src/app/play/play.component.css @@ -0,0 +1,19 @@ +.game-container { + width: 100%; + height: 100%; + background: #ffffff; + background-size: cover; +} + +#canvas { + +} + + + +@font-face +{ + font-family: 'BRLNSDB'; + src: url("../../assets/font/BRLNSDB.TTF") ; +} + diff --git a/form/src/app/play/play.component.html b/form/src/app/play/play.component.html new file mode 100644 index 0000000..960fb49 --- /dev/null +++ b/form/src/app/play/play.component.html @@ -0,0 +1,3 @@ +<div class="game-container" #wrap> + <canvas id="canvas" #canvas></canvas> +</div> diff --git a/form/src/app/play/play.component.ts b/form/src/app/play/play.component.ts new file mode 100644 index 0000000..f4b8a86 --- /dev/null +++ b/form/src/app/play/play.component.ts @@ -0,0 +1,679 @@ +import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener} from '@angular/core'; + +import { + Label, + MySprite, tweenChange, + +} from './Unit'; +import {res, resAudio} from './resources'; + +import {Subject} from 'rxjs'; +import {debounceTime} from 'rxjs/operators'; + +import TWEEN from '@tweenjs/tween.js'; + + + + +@Component({ + selector: 'app-play', + templateUrl: './play.component.html', + styleUrls: ['./play.component.css'] +}) +export class PlayComponent implements OnInit, OnDestroy { + + @ViewChild('canvas', {static: true }) canvas: ElementRef; + @ViewChild('wrap', {static: true }) wrap: ElementRef; + + // æ•°æ® + data; + + ctx; + + canvasWidth = 1280; // canvas实际宽度 + canvasHeight = 720; // canvas实际高度 + + canvasBaseW = 1280; // canvas 资æºé¢„设宽度 + canvasBaseH = 720; // canvas 资æºé¢„设高度 + + mx; // 点击xåæ ‡ + my; // 点击yåæ ‡ + + + // èµ„æº + rawImages = new Map(res); + rawAudios = new Map(resAudio); + + images = new Map(); + + animationId: any; + winResizeEventStream = new Subject(); + + audioObj = {}; + + renderArr; + mapScale = 1; + + canvasLeft; + canvasTop; + + saveKey = 'test_0011'; + + + btnLeft; + btnRight; + pic1; + pic2; + + canTouch = true; + + curPic; + + @HostListener('window:resize', ['$event']) + onResize(event) { + this.winResizeEventStream.next(); + } + + + ngOnInit() { + + this.data = {}; + + // èŽ·å–æ•°æ® + const getData = (<any> window).courseware.getData; + getData((data) => { + + if (data && typeof data == 'object') { + this.data = data; + } + // console.log('data:' , data); + + // åˆå§‹åŒ– å„äº‹ä»¶ç›‘å¬ + this.initListener(); + + // è‹¥æ— æ•°æ® åˆ™ä¸ºé¢„è§ˆæ¨¡å¼ éœ€è¦å¡«å……一些默认数æ®ç”¨æ¥æ˜¾ç¤º + this.initDefaultData(); + + // åˆå§‹åŒ– éŸ³é¢‘èµ„æº + this.initAudio(); + // åˆå§‹åŒ– å›¾ç‰‡èµ„æº + this.initImg(); + // å¼€å§‹é¢„åŠ è½½èµ„æº + this.load(); + + }, this.saveKey); + + } + + ngOnDestroy() { + window['curCtx'] = null; + window.cancelAnimationFrame(this.animationId); + } + + + load() { + + // é¢„åŠ è½½èµ„æº + this.loadResources().then(() => { + window["air"].hideAirClassLoading(this.saveKey, this.data); + this.init(); + this.update(); + }); + } + + + init() { + + this.initCtx(); + this.initData(); + this.initView(); + } + + initCtx() { + this.canvasWidth = this.wrap.nativeElement.clientWidth; + this.canvasHeight = this.wrap.nativeElement.clientHeight; + this.canvas.nativeElement.width = this.wrap.nativeElement.clientWidth; + this.canvas.nativeElement.height = this.wrap.nativeElement.clientHeight; + + + this.ctx = this.canvas.nativeElement.getContext('2d'); + this.canvas.nativeElement.width = this.canvasWidth; + this.canvas.nativeElement.height = this.canvasHeight; + + window['curCtx'] = this.ctx; + } + + + + + + + updateItem(item) { + if (item) { + item.update(); + } + } + + updateArr(arr) { + if (!arr) { + return; + } + for (let i = 0; i < arr.length; i++) { + arr[i].update(this); + } + } + + + + + + + + initListener() { + + this.winResizeEventStream + .pipe(debounceTime(500)) + .subscribe(data => { + this.renderAfterResize(); + }); + + + // --------------------------------------------- + const setParentOffset = () => { + const rect = this.canvas.nativeElement.getBoundingClientRect(); + this.canvasLeft = rect.left; + this.canvasTop = rect.top; + }; + const setMxMyByTouch = (event) => { + if (event.touches.length <= 0) { + return; + } + if (this.canvasLeft == null) { + setParentOffset(); + } + this.mx = event.touches[0].pageX - this.canvasLeft; + this.my = event.touches[0].pageY - this.canvasTop; + }; + + const setMxMyByMouse = (event) => { + this.mx = event.offsetX; + this.my = event.offsetY; + }; + // --------------------------------------------- + + + let firstTouch = true; + + const touchDownFunc = (e) => { + if (firstTouch) { + firstTouch = false; + removeMouseListener(); + } + setMxMyByTouch(e); + this.mapDown(e); + }; + const touchMoveFunc = (e) => { + setMxMyByTouch(e); + this.mapMove(e); + }; + const touchUpFunc = (e) => { + setMxMyByTouch(e); + this.mapUp(e); + }; + + const mouseDownFunc = (e) => { + if (firstTouch) { + firstTouch = false; + removeTouchListener(); + } + setMxMyByMouse(e); + this.mapDown(e); + }; + const mouseMoveFunc = (e) => { + setMxMyByMouse(e); + this.mapMove(e); + }; + const mouseUpFunc = (e) => { + setMxMyByMouse(e); + this.mapUp(e); + }; + + + const element = this.canvas.nativeElement; + + const addTouchListener = () => { + element.addEventListener('touchstart', touchDownFunc); + element.addEventListener('touchmove', touchMoveFunc); + element.addEventListener('touchend', touchUpFunc); + element.addEventListener('touchcancel', touchUpFunc); + }; + const removeTouchListener = () => { + element.removeEventListener('touchstart', touchDownFunc); + element.removeEventListener('touchmove', touchMoveFunc); + element.removeEventListener('touchend', touchUpFunc); + element.removeEventListener('touchcancel', touchUpFunc); + }; + + const addMouseListener = () => { + element.addEventListener('mousedown', mouseDownFunc); + element.addEventListener('mousemove', mouseMoveFunc); + element.addEventListener('mouseup', mouseUpFunc); + }; + const removeMouseListener = () => { + element.removeEventListener('mousedown', mouseDownFunc); + element.removeEventListener('mousemove', mouseMoveFunc); + element.removeEventListener('mouseup', mouseUpFunc); + }; + + addMouseListener(); + addTouchListener(); + } + + + playAudio(key, now = false, callback = null) { + + const audio = this.audioObj[key]; + if (audio) { + if (now) { + audio.pause(); + audio.currentTime = 0; + } + + if (callback) { + audio.onended = () => { + callback(); + }; + } + audio.play(); + } + } + + + + loadResources() { + const pr = []; + this.rawImages.forEach((value, key) => {// é¢„åŠ è½½å›¾ç‰‡ + + const p = this.preload(value) + .then(img => { + this.images.set(key, img); + }) + .catch(err => console.log(err)); + + pr.push(p); + }); + + this.rawAudios.forEach((value, key) => {// é¢„åŠ è½½éŸ³é¢‘ + + const a = this.preloadAudio(value) + .then(() => { + // this.images.set(key, img); + }) + .catch(err => console.log(err)); + + pr.push(a); + }); + return Promise.all(pr); + } + + preload(url) { + return new Promise((resolve, reject) => { + const img = new Image(); + // img.crossOrigin = "anonymous"; + img.onload = () => resolve(img); + img.onerror = reject; + img.src = url; + }); + } + + preloadAudio(url) { + return new Promise((resolve, reject) => { + const audio = new Audio(); + audio.oncanplay = (a) => { + resolve(); + }; + audio.onerror = () => { + reject(); + }; + audio.src = url; + audio.load(); + }); + } + + + renderAfterResize() { + this.canvasWidth = this.wrap.nativeElement.clientWidth; + this.canvasHeight = this.wrap.nativeElement.clientHeight; + this.init(); + } + + + + + + checkClickTarget(target) { + + const rect = target.getBoundingBox(); + + if (this.checkPointInRect(this.mx, this.my, rect)) { + return true; + } + return false; + } + + getWorlRect(target) { + + let rect = target.getBoundingBox(); + + if (target.parent) { + + const pRect = this.getWorlRect(target.parent); + rect.x += pRect.x; + rect.y += pRect.y; + } + return rect; + } + + checkPointInRect(x, y, rect) { + if (x >= rect.x && x <= rect.x + rect.width) { + if (y >= rect.y && y <= rect.y + rect.height) { + return true; + } + } + return false; + } + + + + + + addUrlToAudioObj(key, url = null, vlomue = 1, loop = false, callback = null) { + + const audioObj = this.audioObj; + + if (url == null) { + url = key; + } + + this.rawAudios.set(key, url); + + const audio = new Audio(); + audio.src = url; + audio.load(); + audio.loop = loop; + audio.volume = vlomue; + + audioObj[key] = audio; + + if (callback) { + audio.onended = () => { + callback(); + }; + } + } + + addUrlToImages(url) { + this.rawImages.set(url, url); + } + + + + + + + // ======================================================编写区域========================================================================== + + + + + + /** + * æ·»åŠ é»˜è®¤æ•°æ® ä¾¿äºŽæ— æ•°æ®æ—¶çš„展示 + */ + initDefaultData() { + + if (!this.data.pic_url) { + this.data.pic_url = 'assets/play/default/pic.jpg'; + this.data.pic_url_2 = 'assets/play/default/pic.jpg'; + } + } + + + /** + * æ·»åŠ é¢„åŠ è½½å›¾ç‰‡ + */ + initImg() { + + this.addUrlToImages(this.data.pic_url); + this.addUrlToImages(this.data.pic_url_2); + + } + + /** + * æ·»åŠ é¢„åŠ è½½éŸ³é¢‘ + */ + initAudio() { + + // éŸ³é¢‘èµ„æº + this.addUrlToAudioObj(this.data.audio_url); + this.addUrlToAudioObj(this.data.audio_url_2); + + // 音效 + this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3); + + } + + + + /** + * åˆå§‹åŒ–æ•°æ® + */ + initData() { + + const sx = this.canvasWidth / this.canvasBaseW; + const sy = this.canvasHeight / this.canvasBaseH; + const s = Math.min(sx, sy); + this.mapScale = s; + + // this.mapScale = sx; + // this.mapScale = sy; + + + this.renderArr = []; + + + + } + + + + /** + * åˆå§‹åŒ–试图 + */ + initView() { + + + this.initPic(); + + this.initBottomPart(); + + } + + initBottomPart() { + + const btnLeft = new MySprite(); + btnLeft.init(this.images.get('btn_left')); + btnLeft.x = this.canvasWidth - 150 * this.mapScale; + btnLeft.y = this.canvasHeight - 100 * this.mapScale; + + btnLeft.setScaleXY(this.mapScale); + + this.renderArr.push(btnLeft); + + this.btnLeft = btnLeft; + + + + const btnRight = new MySprite(); + btnRight.init(this.images.get('btn_right')); + btnRight.x = this.canvasWidth - 50 * this.mapScale; + btnRight.y = this.canvasHeight - 100 * this.mapScale; + btnRight.setScaleXY(this.mapScale); + + this.renderArr.push(btnRight); + + this.btnRight = btnRight; + } + + initPic() { + + const maxW = this.canvasWidth * 0.7; + + const pic1 = new MySprite(); + pic1.init(this.images.get(this.data.pic_url)); + pic1.x = this.canvasWidth / 2; + pic1.y = this.canvasHeight / 2; + pic1.setScaleXY(maxW / pic1.width); + + this.renderArr.push(pic1); + this.pic1 = pic1; + + + const label1 = new Label(); + label1.text = this.data.text; + label1.textAlign = 'center'; + label1.fontSize = 50; + label1.fontName = 'BRLNSDB'; + label1.fontColor = '#ffffff'; + + pic1.addChild(label1); + + + + + + const pic2 = new MySprite(); + pic2.init(this.images.get(this.data.pic_url_2)); + pic2.x = this.canvasWidth / 2 + this.canvasWidth; + pic2.y = this.canvasHeight / 2; + pic2.setScaleXY(maxW / pic2.width); + + this.renderArr.push(pic2); + this.pic2 = pic2; + + this.curPic = pic1; + } + + + btnLeftClicked() { + + this.lastPage(); + } + + btnRightClicked() { + + this.nextPage(); + } + + lastPage() { + + if (this.curPic == this.pic1) { + return; + } + + this.canTouch = false; + + const moveLen = this.canvasWidth; + tweenChange(this.pic1, {x: this.pic1.x + moveLen}, 1); + tweenChange(this.pic2, {x: this.pic2.x + moveLen}, 1, () => { + this.canTouch = true; + this.curPic = this.pic1; + }); + } + + nextPage() { + + if (this.curPic == this.pic2) { + return; + } + + this.canTouch = false; + + const moveLen = this.canvasWidth; + tweenChange(this.pic1, {x: this.pic1.x - moveLen}, 1); + tweenChange(this.pic2, {x: this.pic2.x - moveLen}, 1, () => { + this.canTouch = true; + this.curPic = this.pic2; + }); + } + + pic1Clicked() { + this.playAudio(this.data.audio_url); + } + + pic2Clicked() { + this.playAudio(this.data.audio_url_2); + } + + + + + + mapDown(event) { + + if (!this.canTouch) { + return; + } + + if ( this.checkClickTarget(this.btnLeft) ) { + this.btnLeftClicked(); + return; + } + + if ( this.checkClickTarget(this.btnRight) ) { + this.btnRightClicked(); + return; + } + + if ( this.checkClickTarget(this.pic1) ) { + this.pic1Clicked(); + return; + } + + if ( this.checkClickTarget(this.pic2) ) { + this.pic2Clicked(); + return; + } + + } + + mapMove(event) { + + } + + mapUp(event) { + + } + + + + update() { + + // ---------------------------------------------------------- + this.animationId = window.requestAnimationFrame(this.update.bind(this)); + // 清除画布内容 + this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); + // tween 更新动画 + TWEEN.update(); + // ---------------------------------------------------------- + + + + this.updateArr(this.renderArr); + + + } + + + +} diff --git a/form/src/app/play/resources.js b/form/src/app/play/resources.js new file mode 100644 index 0000000..d9b584c --- /dev/null +++ b/form/src/app/play/resources.js @@ -0,0 +1,18 @@ +const res = [ + + // ['bg', "assets/play/bg.jpg"], + ['btn_left', "assets/play/btn_left.png"], + ['btn_right', "assets/play/btn_right.png"], + // ['text_bg', "assets/play/text_bg.png"], + +]; + + + +const resAudio = [ + + ['click', "assets/play/music/click.mp3"], + +]; + +export {res, resAudio}; diff --git a/form/src/app/style/colors.scss b/form/src/app/style/colors.scss new file mode 100644 index 0000000..13a0b00 --- /dev/null +++ b/form/src/app/style/colors.scss @@ -0,0 +1,16 @@ +$color_black: #111111; +$color_gray: #aaaaaa; +$color_silver: #dddddd; +$color_navy: #001f3f; +$color_blue: #0074d9; +$color_aqua: #7fdbff; +$color_teal: #39cccc; +$color_olive: #3d9970; +$color_green: #2ecc40; +$color_lime: #01ff70; +$color_yellow: #ffdc00; +$color_orange: #ff851b; +$color_red: #ff4136; +$color_maroon: #85144b; +$color_fuchsia: #f012be; +$color_purple: #b10dc9; diff --git a/form/src/app/style/common_mixin.css b/form/src/app/style/common_mixin.css new file mode 100644 index 0000000..3e7ed8c --- /dev/null +++ b/form/src/app/style/common_mixin.css @@ -0,0 +1,6 @@ +/* +global css to mixin +*/ + + + diff --git a/form/src/assets/.gitkeep b/form/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/form/src/assets/common/arrow.png b/form/src/assets/common/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..d69b353b4da29da2a821723bee68d51e9aaeee05 GIT binary patch literal 18955 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 N0RJGr13yG&{u?M75C8xG literal 0 HcmV?d00001 diff --git a/form/src/assets/common/arrow_right.png b/form/src/assets/common/arrow_right.png new file mode 100644 index 0000000000000000000000000000000000000000..65859da4bfbcf54c25e481b232ce21f9184c7425 GIT binary patch literal 16122 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/common/arrow_top.png b/form/src/assets/common/arrow_top.png new file mode 100644 index 0000000000000000000000000000000000000000..d4bcadc92d0400e6d2bdbb4c47fb4b7c55ed77ea GIT binary patch literal 15943 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/default/video-not-upload.jpg b/form/src/assets/default/video-not-upload.jpg new file mode 100644 index 0000000000000000000000000000000000000000..31fbbcc7703958c0153d883aeded25e2a53e0542 GIT binary patch literal 33779 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/font/BRLNSB.TTF b/form/src/assets/font/BRLNSB.TTF new file mode 100644 index 0000000000000000000000000000000000000000..509477ede1b11d912a8f5503001a917720522d08 GIT binary patch literal 96880 zcmcG%2b>(mnLb=SIZt;_&-CQ!$$4is=iSjpWvy0$m5^Xp+EqXi1)>BJ7y}Yu0XD`M zn_xgTCakalVZdM`2^$lP0b`Rn@Zo?k=K!2RJO8I@c7?DxbNBmxU#<F`>goz_J@uyQ z=^hb|5F&zTh|;rQM*p-+?$|=ORV6~C;_QVBreAvDPhKNLzJw5N)4T<RnvK<$oQ?c< z(Q5JHo;gFS-rKm25cfxfXx~`5VPtbhn@S=?Xd^_uZRHu;l<kSN$R`(~&9$pGuio&h z^KQMJknk(0zkT({*3CpFMnY8Rj_|A3pS|kL9k0Gh$jL>*8FXt#H=K2Bx2A)Ts%r_! zUAty%Wb}y}9y$qq<xsz24GQ>`I$Y;QaUNT<VcS{fUNB7{B=s)(zhnKTl_SMP+clWW zIL7$RhLN*2tG};%2lX)@qHG-5F!s|QPya2h@r2m3n>TIUcIBIwZYJEyCh)J_yk%_j z;VaL6iICuLaIPX0D;#xCezS0@z3uPBYd`@Z;}`uULO&1uV%PQM)yI|^59+6(p0P45 zTtFNBv|~#NF}{WCUo#$LJ<%qUiCafYK)*)x<aVruitwaB22u8mb~{nyoKyc&^$^h# zgZ4UYEz0ASPxX!DER|?bscc4-N~=<-b?8z()i3?*>zbhu{C%uqJiMr{;|?l}r^#As zVqoKO<uYs8tL{3^AF!UxbHqkYn#`-f;n-weO<ZK{WL`rY<owCJmRQJDlX)Ex$hRl+ zdU64|8{=>qIx8DjJ(<^#9M{S6T9liB1+AmSNGXmYz-e?S*KyyP%xg%D`wq+NQEuQK zpUi7Wf_sML>8vc=-zW1Ll2LIi4|yYZsj`!Kj`&r-oy?;jRi(ZWB{|ix$#V3mPEY2w z#I2q;nb(nsdi7*pj|p8mnKzJ(=JLtBk+?PYPv%Xk9hwSnMq(y4`dO3Z7SgBR$?_)f zY|}qBnFl8NXIb8ia#3I5#|%u020JUa(778bxLHu1F!Zx>8_IdZhRM8!R2eG$^Ryqs z_gOj5`gxe;9Vpisj!x!*t>LdMFQMFKlqd7x#~5dMC(0$`{K>qA)ELKD-o@&FeKJq$ z-^%hHR=+YA55}!A{*IOVP;N3+`uCwcWeT(M0Lpcy8IyVNW2#^tV)eJO@(`<EnO6+u z7E@)c7|JuI1FTM-)qi<1Py1)%8W_%ID=kMJe42eM&-gbp3=J+;zKE7vD)o0y=4t(} zusp-x{NQ9B_?sW=-n9AbEo)b=*`}mcrj_dE=0;`VnlYts)5dK|*Y+)ABinPzjEyU+ zlxgeNE3D#HWy{#su`OqejaDf=V_Vm*-Z(a@tT<cg898I^sM0mIW&NfztLVqtjmm<N zja!wzuC7h%NBg?iwNDEbTKd^~tZ4DrmaS_yZB(kOip9!h+Dl(op4R_ocAM&RV7jT1 z(I!Tl|1T5xbO2@TR%Jxlwq;~=Y{STwb;_nypWhFe3uCgHYysUyMo1Svw~+NPDjQ+8 z7NBG!*@|2rt|<RhcN^KxS#kXjU(o8)daKa;=oi$k)ahgVZ2N+`leN^Bs2^4zQa=KE z;NQ3SOwDexiEJikW4>#Fz#7b7At|zwr14ozn(^0&+(KL#!)G6AZ)A14$aaR;2tIST zG6Ur+NfmO_fZTd~e%d3&j$*qN#};x1=qRh%!^-Hm8(En`R)7<Q^Z@ZQz|Sc1Q){t_ zoQXD5XP>t+UEpm!+EiBQ-_@kOR_gxmYAt4bZv{tm_7s;YQpDeht*4}fj-Ef>{}-X# zMCuuO6zL`)O_8kRn@-3#qxAou75KavD3~W*u@M~GuwEm;bc}4k=N7UKWt+&V{}Vs| zd(Qu-bw82I6ZNse=L&E}C5uW+Wql~;E5PkqCW&ity&|(CINuCO9>G<r=?Z4D1#LDU zw{23w*W>CoT%{#v;*+*qi_fiWJ*H}{LfICS(LT1a{wZSgDs8Qh+0crWs6$7dlHrZ) z>K4Z57}J6+xJI$1k~O6RR07sAv{&PEBkON1t4&vABWq19(>DCAN83EsWFzKqCTK<b zwzB>xZxu``IyHy&RN?<j#?yAz2i3^6;B_6F-~Y4%3i>(=*i|^F^gD$G<$fdhr`%9P zrz`|5-G;M@Bvo|3g5;D8(Yn-%C=BT-`%^)ht`)T+pVnE4+8e+F9jCHFXEGetpjI#A zj?RUmzj6}k5#(r1IszSk8z{w>_OTuLio8&+M<?e%WvL<;m047wCyMlD(t=>P06yto z)$v)bVEm7v)pnFtIQ+l2DEyNYP|2F|NOYzDw;ridcQ)oi<?syPMN77S#!j86KNU;) zul4(Z7}cr&N$)D{rfT)U_pOKge1H-EfR_Kh)j!vs>ZP(iR9^ml`+u!Zt@9W8$V#2* znALi4NxkbAwfJn^0r0gNbK4HfQSkz2e*vGL*W$!A{i1n(rmiNW>Cm)lx-|`&CQV7x zu9>B2{`cd5Zi|Kg%UI>pdX?DX->*oe&Mb;8wo)7aJzwP0db5D%7&L3$7q0n<HD{wX z)z&Z4iBIdDh~yWw`fS}3&;C#A_5VS8r{w$JV?I?2`^d^Y0o-7qI{<8zy*RJ~N0udy z?!?*6jmZM~fs1O5R;M=@O=gSLX6FUbAvs;L+vD~51Hq6IjznYeL^74mWOMndLb1B0 zwywURv8lPGwXMCQvox)%yQjCWfBKA>vu4kkJ8xkA;DUvV7N0b<Wa-JvmY;I!Fg)za z(Xmyl*Q`Bl-TDn1H*G$B%hqk%&p7j}v(Gtq$IkQ4-?jUK3%_*HmoL8L(mi`GyZnl; z?7Q-+tH1iSYrcN%H?I5U_22sT4L9C&^LK8!^|t-r{od{0zvIrk?jApI&kufh?|t_l zeBeh9KJ@U9A9?gAKYi@b;Uka#?B`GX;>o9;e&(0Y{_45sU-<QlzxnM;FTe8YYp=iY zCef&Hw}T9k67E>I$$6yARdZe30&avmi#w0IO7*zv=c-rLUsZok{gC=mg;ylSs|1yZ zl2D3Di_)WPQ|<^y!ik6~qKnugV#FEoMuL%SWO`&cG8TX0ebvV*+^ryR9yg-rY1|+; zjGlL*=OgI(Hz)M$P~3`NQCQE-|I)L7o;}BV9!1aG$G8ttev6RuZRMNFr<A``?k=w_ z<DS+8?kgRWKKbC2mp^&=4f4hfbSVjW<DxgN!Ex3bm%j1+*H3%>?ANY&?dI3^67t%9 z9NS(y{k2nHE4)^G>CgNl+DDjJEUvVhqD)%oJ)7f+({KjPa{TnOnSbDv9{-%~Am1Th zA{UW|$u;En<jdp=vX^{|e2?5h-XnX+OXNawHF=->7rC5#om@g5Bd?J^<BrVj<ger} z<Zt9=awqvYd7Rt@1G|#!gNpwG#^Gn=3Gxhik~~G8hHF_xo+G~`&*I+AYB-xK$*;-t z<OR68KaqFIrQ|dig>?uJ*24td2qSSiObd0SG|V{zPWz7t5zfK(;#{(m>>vlpO}I~V z9@#~9lfRRr<VWN;<W2H2d4;@6-XOmvuao=8{p1k&A-R_v#{Ht7l8ebVFq6l~t(bUZ z@^3SFl6y{dp;}Tuq0wp<Xl~M4wA-}f+K+UKZmsTi-N*WM`gaUB8so;xjDIqnYkJ-6 zGw(3JWNEkDV41Lf+tz72Y**|T@IL-#At>A{{6k#qusTkYBGP-#7Uyj)t82g9A>Zqc zyC3#E=pFRF=iBak(I52h_Wx%f7+4c{E;u9j)sQZ<H}tV`MVJe(3qKRt9C;|ZI{J9b z5<4UI`*>&k?};-LFDFk)wWt1?zABT>+>`l7c2D-#+4pl-=WfV7nEO@k-TYno$MV0) zAFa|>d8?|cx~fj9T35BJ>e{M1svfO+zHn|~U*Xom1BIsx|5^CB$QR?qmf~RX@#3-S zOKa+Dx!Ppy6Ll-=Gxc{jtZ%r#(ciePX{c#!)8VFnG}knr)-t2zyp~5=xz?)IrLA9X zliT*Rz21IrM{UPfJKpM4b?zwXN+*~0Oe;)#sVj@WuC66ro4bSEk9B|C)6_HGo9aEi z_h9cQeWkvk{{H^2_Wxn}^y&L&^v`&4=AN0~o%#N((`LJ7r)Iazo<FC5&WbrZ=X`Z; z?cBL@SIyly_lCI#=RP<05A!th=Fhuj-X{ai18WC%4?Hk%Y<|o9E%Sdp|IPXD&Yu{x z4~7S82fs0R%i!IEFD#h7;K2odU0A>H`bCaK(M7e3x)%*CdSP*5@$$uYE&k-Bc_&>q z)H3vkB~LEB<K%VAOv~<FzWbEiDStin@!{zsx{*6a?j3n}<X0=sUfD4k9IYLlJ~}+Q zee{yiePgk)RbxL~6<hV~)dQ=aU;WCOnl%U4de&ZdTE{xWx*x1>UVq8@|JZQmh7UGw z-=y0#W7Ex>J2&5Q`ra+dmfN@bx9-{I*>>0V#P;zs+Rqfuy!EWiS%=SFdG^M$&pvza z+221We@^E)^Uqmx&N=6N^_=gYJMY|)bI(2Z>T_@1am|i9cKmq9FL(UM&hMS~t@AgW z|IV%ryKdVZ+`W7E3l}WB;D;AHe8G_mp1I&R7rc4FA20ap1)p4~z0me0_z7+uN0V94 zNi1XK><%u$vT=@!+c}&hIFF9wA}HKz&2tuZQI@!zN3?TR{3SW9mecOyIMX#>b6hiE z3Olsidsa?xxg4yn$HN+HS>kpfU4vu_(?l!ySuGx8A&DG!gp+0NXE(;|C{g{6b0jz~ zyTsWzboFU+aMBGN7pk=Pz@kR>B28Yu=F@r{C%;F}v}^=R4aXH7R!%!vA;WQMj<e<H z`FoTwHs9kayvMl$a7YN8$EQ-^q9@PkxOwQ&ZQ^(n?ZU^oK?RyT9u*QT<Wi`{aX}{+ z<TyGa&3OPf{i6x@sXsE5aSz;3K8AbtMo<$mftrcA{0Xj7Y9$s>8?lx@CU!=7Vn<#e zeEA<lWYj?f<R#)L|2J_m>LL>IGI5qaf){jwdWa0_CGPTv#78`!e&PiU5MTKN5@a+) z{KzXLQ2sj!lOSk>gg~Q2DgTYcNEkFuBA^KpE&r7yNenba;-G1gDF20IND?&5XpW@I z|AmbzrBx&YS|Hi-`?!IU1FdGXhE$dROlldeBSqxvLEj?{qz1H+(I!$`K8hP9b)YSz z9<&woUD8GxLE9PaAkF1JkxoWSqy_nDpnpVA+6LN9+Ch6rNBIxfGE&+{IzjtMsr-8~ zopgcDAl;xdLEk~J+6y|H(K)0K`MIRO{GVhVnGQNYW`NEoGt0lj_au}qAhSRhk~!tK z$s#frbTOkRk$LdvLyRsV^O0W)`XA(EvH)}$qsz&n@|)xoMo%S+ksl@}mES<1y99Iv zqbteM^6T)8l#Y>;L06Gw<=5a3PXS%S=vs1W`BiwsVbFDC1QfS4%CEpPt_0mk#y~fL zz6}4k3iNbFw~#gEm*6ca-9}CW-46O&c+Pd8XOi`xXORu%-@t=z1U-jr0zH>(F24wG zdOGM%M$aQ#%D;wZ-3q#kYzN&9`T{)Y8K4(3`XzE!`FTVNlzy3<19~y&bBGFdfL_Yz z9<sCiD?||IfnLVw<z#pHSwt0-euZ2Bx)1c1hy%U^dKIHrlP{N_Azx+mYvdB-uK|4; z5yz#V*E0GIvbX#cxsF^0`b}~<==GpaB38Kq^xNbspf`{!%fCPrLFrB8D$twB)#WD; z;d~YJ7DjI+*OY%wZX;g@-A}Fs{VwRw5b=Bi^mcL`==aGt%a4;g$n~Iil5c_D1$qP# z%nhL9<VMf~pohsl<Yv$xkne#0kla!}gt&v!`^c@J_k%u$nB}{m4>0;8^1bp;$%BkO zM81#w!=OJQKPGpAKEmju<nHpL<R^^&l#C<)80aI2Y7T&6G|(gDhvgq5?xOT(<X+I9 zll#gKBksB%^cUnH=#%7u@<WKhegyh7c@Xp&&<7EVJp}qJc^LFp<dO1^5T8-{Jb4uK z1@e>f1BlUn3i={B1o|7$gNUsTgT6$LfWAx~FW--ti_%xg&p}@!Pn7RN^z{qSHyC}B zJc;~&fZj{qB2R<9O`ZY$9r<PXhvYvQeTV!C`QL;70CD1TpnoLKgZ_#9x_l3!LrRa5 z7eU_xJ%GsbH=ys6mq7oEyj&hf3`*%=$t$3LBd?b4MpXD3=m+F=&=1KQ<-5p7<Uc_F zo6&!ex5{^tj~V@hyp8-Z@}K29$OL%@v`p#2@}u`0G56!6R6Zg~eWk0V{?gU9{zret z74PQ?_jTT<Dn7pXaaHla@PW+-Zakpb^bj}i0j~HHjz6dz95|@v@7a8hihr>5;N}O_ zp}RS9XXp;)&f=XK{#@?X+Z-YCo#Ot|{(=3QZX4dedH=5c`}W`cox5)v-~Z@->%fuW zBb$$?kDTNTUGsH!=-Vd;L(6g8gyYBG3Wm<xX$tM=a)!?AGK9{+vAx?C+SY9dZN;$# z$LT2BjAIjyja{zLY4}`=V@<alT8(4XVm>t1?Fx-{MMEobeFcsY9H(>zLQ7F^367J7 zqM@N~F|-){Eh_z_+Y&n5C59GuNudQe264>CF>vqjy{b7~LTEOQd%K0utZqkWCYsH_ z=X4zXDDT73gM)PQ-KFkb-J0%cVyJ7H6e>>RqPE_Mr8jKqRSdl$U2jm+8&LK7NpHg7 zHMk8fgJcj5yuoI$7)%C(L1)kyRB*E;_dfTH?)TlA5<VXBKH}4y>fJ1z@7*P7s7oeB z4&P~#R0^TKC>T_wMtkQ$jvR1tvkvOZgR{mB11Aq1;J7Q6jEl3#tc6_<pi%jv%e%P1 ztnt8tq4D9sl3C-skRgEsF4DCmdq73H?vVxV5@kFxe^2zR@zUT~2TaN(2YIsStOF{p zYh3L|{L{O3L9~0>(k^b+z|a8$8g?(Me7g9}9S2K98ISd@99Q)!<7DAb_@Is~Surkl z5BUzN$nZf8SrMJejGMF3CFAC3*SIO#MLIj(S-y=c=q%$p6zQW~Teoe^ettsv371aD zetz|-(yd#wTR)TN1wu+K^9Sb5oilsZ%o)@B`+9r2yQY;oJKEb?Tk!o}Lw%ttpGzg; zv1laZmIU5zHJgkEy-ur9<BRfKZ?tb%8BYw4YZB4v)ARH^I)Z|c6AFgM6%_S-w$8Xh z+l}DTXKI#EbJai9ELCcjj@RUPrH!=Zb4qVi8GouLsvP8&&L2Yl@}B4tW&9}1&tZ8@ zf}L1#5)Pw<((7K+ql|OIO7D2z8Ef|R4)^49+yS$xJK8;F%IC-dlNnhva^tD!<^x=+ zgJT(0s<#CaVzAO-$JO!Pk<syi`9r-uzHoR6D<j>kuW?=XxSsW;tQ`l>WUq1{_voI> zAVw>OvzF25=*Y66arFoq?NRsc*>mx@kR4A)d&bk}yzK^nW8=AKPw#j(3dUv)9v^@k z*T(s%vghvv%tw#D3$9Nn8JR56#d++Magk2(I85WXp)v^>0dL?C^9zS5FMA=eD{wNt zYyME>9AC@$?jfZ@cFDMEm|l5w>WXs_y|QcS%JJsIQ6SqJ?H!){cg7m`_^uU7K8KZM z|Kj7CIIb(>>csGhm22qd$k?7}4`v7~p(f*{9%M=*lVJ89C>BtEWEhiJOJSHlG+u~q z9+#qB6|_-+PU29-A=ac)+B+_FkCWk*ldZ-Jy=V&&>D@yYhB8R|iq0Q;072>-2kI2x z4{AvrSwi_3cXeY?61{tdMpuo8hJB-u&sEBhFFama0{E6hhsKuBRf_WC={GPO5*CoP z!rcC;_Ecp|dt4tkC_^frdI?=E6exWl(XKXJ;Ky~9Q@WyEZORbmBU9Bd%47|i`%FJL zQOCQdqcJ|ww0pWQ4B=+!->~GXOaN?*8;<j&0TbF!d8&-_KeAS-O&Llny<<HmF!-5H zal#m!?CtaUR8cG@!2k;ex}4ML9P&98@(L~+##NXnE269DhD9AvhN5H9B~i#wX<&#h z4#k?S@2myUS@V|;vDKcGl7*i+t6Xn7er+<B&sF}EJ%;G41$$^8(aB3h*)wCDK=?{f zye6@((zFjIZ_l2-sM5D*c+bee@~#z8g^%tzP%7=&+zV4h28JLp2g^U&>l^R8Y{@u3 zyoPImr0<E&7~K<HFw}<S%EN1E&m}W)WHrAalKOS*$q1rvg8d6A|8C;(^53*S!rjE_ zxG~&W{=Ie;S;$>cKB{>b0{bsX{XU*Hy7FI&zp#M22Y(@zmHbvkR72cPx$C$Iu9<s{ zo4^xVIwEtgaz96nKXSK`ALH{H?jf!XyI2pIfg9Sl6Fc{NY~?>t^>7{7oPWS=BA;N- zWXFy&%>9jXlXto6$gemD`3JX#I|b)XFl16$x!>Y^Huo;Mg)`#wcJ4(k%iY3Vh!L=b zSI;It<j&+e)FL-Wt>H#Be%#ml0q$o0lzWBy8g>#FsomJ=7U=Gq)L?Hl3p>wM*p&`p z7aT@pd=*)ydRLWFO{k2jnCeTa0d6L@n0%s|qgu~xBonHu5xK4;ZQKjEi?EP9&8^^G zSE;!zDjoM1E{88i&c%a(yC`(@hCDmIO@`IakRI&>*{GRIX6pVzY}#u`r)rQ4s=q=O z<A|x>C1K4%5>g#5|5<$>8B!f4Y22&{YiHwABvH)@64Ge!jMsDc>_OefaRi7-Q%!Wp z%c`xUQMI*v5PdDwG_rnsu%ZE-hSX{y720dbd~GB0Z;?UGkH~z@K{8vXBegm_{ik{r z^*hVQATNWO>&XJ$&&i-JjiVm*H<4LWpXz5xP%}i#;C+^MCu!BcMOwA^no!$Le40KI zR^Lvp2hSmV)@rULLG|y-e^7@>tL78P=mcq2Zw1d2B(51G1$C16HNV68o1|BDBe1xG z=(J%n9r=EJC#gYsLURh{A0qX%y?PkW)lCqe`V{bh$8a<klaOu$uvm=#?jQoNaHuaL zvoZdQ_*|oTsQdw&H=R4?P3L@kPS=p>j3>(1KOKxm@JD%^JTl;^S#@Li5RQX5R!{Lp z`TNX4`8x4<i!4-MNNUw_GJy5#&}<-i?R{ia%aeMojV#nYM3%ARLSh3>?U+kOeKA?3 z`yI(s%rzfCF8WB1>PKWYj$zEVM$MBA>QS;o^)gwcj*%oixOd8LXm%q10SRantV<g6 z0&iG<N%d{;a2GjKe;s6pCw&?dxm{fgK4gq9<N3b1WIFv8X$mVku6{1$;(8L*4v}g4 zbIHl-7a@Z$5+`JG7)K9y>QlF19e_Jsd(}hbgPOzS3f22$A&xYj8})1FVtwBt15}P# z8?-lkKtwtYU5m-jc{C6Co1uEO{05FKI9{SWu=zue=qHmmDswoftf+C93daZP5OBlO zc{uLFu?|N8hlFDZt)scV{GfV!`Bf^nstKG!MyZ^rt|Z^qzEysU$|B{T$~fe#p#Bn> zqgo70*h^gM0`cf2;?_rS{IUEeCSwapU!|R@k@da1{3`gH1FW0Xn~9{oi}>|#;&_Mn zbv9sdGs$Q_A{pZ~M9|HI?0!rX!<pdW6Vk8!F$o&#k%#_Lxn^Zl9<E{f<e}&Pe9$?l zFNIv(j<uyWA&d3?Je#ly>rZXMSD-i7kOFLoOM5=aX*<b$^$Wmr1@!$R<Uhi^e~$C( zCT+kAzymfw{U%wUuSWS-$e{5pe1>2H()jEovo!a>=fs%}n5nylNQQ%$+bLMrcZsBV zhB(2GN4ui@mio=|AyyaVv^~AXc%Xcoct9Q~Pm}ymo_cY#)3JfY%o7jY>m;wSkVf?} zJogG&R)3TD)g_!iKs@SIShw#G1$j3uKXD!D+I(I;?F+cO2zx~cx7ldM<G?DlR<AYa z)EbROtJbL1I(6j^wpOdgH>nzpUZ>OPwOYMit<h->dc97s!xyYNBMLRFf=-7E8l8?d zHKMW(J?XF?)w1h2M_XEqgfiMKYJQq9EV`o!qoIGWphr&{jY_LA8gv-Lh@LPY2R^Wc zGH6f(jdZ9)`@xAxr`1*Z)$6r%EIOIVgc)D}HD#Ojr7;-L9o>k5eVx&Wa<g7*Licox z$wZMj4gxLKU`~4Us?!*BX7q#(^hS)O1<yFEG-Cs@Ec&9u(sY~?JwP{EwS-PyuQdWq z$`%mU)A>{W=}gef01UvZ!GKGk2F#f<Oz}py3~8{0f1kzMNG}0+x<Y6)$rAneSG*|} z7zCqXPYN^*m<RCIX^lo;q%|?T%^U{Db-+dO*6G!HfB+QKS~G4pRQfd-s7TPsOeMOC z6}%xQC^s6hIuv^YAUBy%+rlt30dF=@aERU~L7+<qY$1^l8ej{cte6sAc{ANU>+#io zWoi@-By^#tEK+RH2k=CqIf}R0t^?j0NVmyA7nJg*F#tLy4VXEFy#le$U{qsqO$H+t zR;xEuhGTd$nZnGeTvB;~;IQ?8U?W49i^9YblLU%)g~>`8#-nu%7#IMfwFX)OF4Z^% zHX15@=$_(jG#T|2eekK%Lo!edqP0*V!1!u47RZR6PQ;rn7F8TDrq*gqCNmumeM4K# zW>mHsbr!&fF_>u4E`h{x5HJOXH~7;Uv?ha{DjB9^q4z6*cZGNKLqVo!flVr}6m2TO z72LH3;BBek4OwM)V+s^sfJOgsM&Z;_{-HZYinrcmGy*&f$M8nCbdA9d{Rg>Jn*kh^ zd%fNS(ZhHQYc!(MWwk1}R8A{pXiCM_h=H}h6KGO^nM@j?>l$b<pfOlf;KOVJFjx%Q zF(iX3AB55RFL<-LG6F=f${Nf7h@hR>Y{7V71tS?P0L^HF%<7F6OaxP%VhL>+48R`q zr|M&bJQ#ImgPlr`!C<n2SCmuUDaHVqCYA;Nm^=H&P^UTiqJ@>$Q~B1J^kyR#l&%)= z#rzrnm=1-VLX10vCX)s%noTCi7=+zqHJAV>#hbDN4?t(HvC#1_Pr4pdh)@%gKqJNn zxI>~ERyk#qE*LHwjTl&GHcjG<KA;3f=(+~dN4vMFU<xc|00Sm5f)N%06hvpILV)qH zQYI=AMm9@Y3+saF7}I0`4|EkR7OW1;2qvvFS^=7gH|cE#qZMPIC1VL}e+mMChSC6U zSV(Ask*7Uj<!#g$0SbEel%@*a=)wpop}0`^C+!k46mOfTCy*5kZ!u8?q7nwYDcV#^ zsM6{H0eAv_W~__BVm6!1CJbW2a12jK3Dse+13RFxfjK&`5w~$GcvGy=i17jLkSH#d zd9gw&6R2Y{nPAs|C(xt<4a<q?SPjTop(;kBT?JEMwE!3}iALZP%mM|io(Gzhe$8eo z5)h5!36hCb)?f~h6HL-#v9a+WsXCL*hT4KzZ#SB37z0(NSenEey`q@fP}q6^rMH?y zqZyMlS?tg?luz=GL78gc(`15xQ2RjtQ88vY6Y#b>4GeFy!D^zWkeU)5(1f(mC8SCV zy9t)eSTl=OXEs_b7L&z<K}>eKywpnriYdHJpTQf7hU*k-G@6{q=ip7<De9me)C70} zZwu8lcr=PPEENFKnM}M2rod(aFbr=aT^<xuE(J3%U{1<nf#?8lI?GCeU&jDiGr%;# zUh1q?Xaj09H)*$<&1TV}=Z$7NM23nMO<?;|5cCi*Y8}mHEkYTq$q4|^nVE-dK*!Mt zywmh4-psyXT$D`Wjpo3cml)m#i_wP8U~1_~n1LRXXgDT{x5Z*MS&YC8hSX@onFXf8 zZ05lm#gjq-9R_9cO<6%P)fg(^u#4c1cEJ*?G}Qy>J<U)EXl*Pe_%~x<z0Cr%s<l!+ zU~`#m)#~jGZ$V|TSa4sRo>2@<@OV0^Y&wHzf%jtlQoPaAiFoS)q(O^Sptee{v)Op~ zI`EE>%sfD|IIIQ%@L?iUv}mf}O+mn_QiY+`(PGx&!)BJKQG=!lR!q@M`>G^nN&yTK z1f=2!AQ}vH08bx66P!lKw+<fKZh?ga-k6FRpkOEvW*!X?X|vU2vRbuz2$$7rv05;Q z1uOz<=rI-^=AWvY)~topvxSEIQ#Aze6l*kMe9*2dayZE&{h+QGmjNag&u&E{9YmPf z0E5wP!WcZH5n>3ut-KAuP`n{^)TmOe&>0+5=`cQ4%1Twx0^ylTP(}=(wPFM~U%lRL z7feQc8=}WZ76G7HC96R+TLg>&URi?vehPwt3K+%PqJxpNTbyRJhNd}eF#cxvO^72) zRCiGeiTM+Zi*v>a%~^rBC>sfNomLZX1>T6hs60bj(IJG68cFym3NhBqrh_usZ8qpM zyro5i;G!RZil7SYL)|FeXbIj>0OYCXHdCx^HgrG}wbBfiiXc_WuvEB=de92sc>>-> zBTqwXf#K~?S*<qS4q$*Y@V3C?QRRcPkgUJ}8LX7e2!0_N#}i}}OzNz3LFw#yUZmrh z3^tR&DvGG>vKbv_s|YJIB^TfycvBFtsuV)1K2|G$GV)g0g4tNCb_pLShfASdLl&qk zp%#)I8HP5)yON`LJKQFQx6LFViU;1*FIX{u3<UzbVH5zC#Rj|)cS5-Ab}M8MoH?LQ z@FS3HW-~$QQVEbWs#q4Y9bHhou|Q@tVl3gSP$tl*Ni!9>K(t_nnZhs>Z#w|i*%?~Y z<_eH+BLKprC6&!)7kB`}VmpL&u$WLb=!es028Xnf-EOjD!pG5u-K2P%bQl48iAf5A z!)yXi2B?nJ0U@=?cB2Gw#Tb|=OBC-42-L`76#z8WQIF73u)3*HgQhv{aJGN~eKC-2 zpW@9^`+#v#f)N2MayH;Cc_`j`lie)XU`0(>RlUIq;lz>w4M+~e+-|p7?a&d5w?(k? zHr@t+Y?2kr%K~D${AQ|dI;&2^;1#@iYPex|DAs6HnF#YNR1PbO%L-}u0x7fEY;a=& z1R633yr_>enMACo(E+@zR;Su-=S9JaGkVoxrFc`V(3@O#3pk`8^Sp^iPi&TSrl<!i z45MSm!`;}}7!0B)K>)xr4{sz%cAMSJo17M#lj1!IIM~J-Q4q`);0?n8gKD$s5tNBG z4+IXK@h<2Z%7H%GAwi*$SXMxWq0R8F<m|xP=`l0Bd9!G*;0<esZ{(q!RKqKHL!@os zkLUHU@*-cs+ir8xSjqsq2`FF>K^fj?NfnFP8@e9A+lIDO=#Y-%U9m5fGAtD?qaN@U zfr4HyP|L@BoP&A>35E!2Pw{pLHi?;hfCJH`$_KpNC*Vz0(EeGxF{<8<1qI$lgTvtj z-Vj-gWOq7wJMR%pF00*z;EReDV-t8|{`kYH8UZ1Ve(iPxjHJWvffKPn(`4uxf^ZAZ zWMv9(3~slJ%pTLwfsV-Bp^4({3YZCOp^3LR><BQ-?9m51#TynIL%~QQJmu{+^eG4i z7%zt)*af>8D7t_n@P?36n+c6Wb(<bm2B**-*mr6qO;#)r+QRPB1V3Am!;0e4A~+o^ zCZY!34p;9GtZ*43@P?0rr<D+Vnw(}jh^*#$K@#maqgSn19^h@aLis(s6&%tv5(Kk= z3B&qMB`d5jJS9f3+e{EDhvc$iJgZ3n<SrK!)+?B08!sbB!%SJCyE))p0RceU%!nI# zyTQzxC40aoVDaptTLj*AGtkF6A@R%`v8)4GYEmHP7_ovkezbwe0SoXpm<5Z(Q-g(7 zMMwbQq)rh6RKXj73pSe|QoJQm<ROEQSlMnzTm%sS6tIV&u%3D+2Df1#n-zG&pqOkF zYc#4%gjsB=_Z2x}g@_ickV&5Bfwv@{fHxM*X@xa#LHq4?w^|THrvrjm!5ea6Fi@>9 zn7x7x98$bRk*Xk6@pxi*!?EC15j%}KB&Te(2*6uJlpsS$1;1!^+XOeodlGQq4I!W) zSYbrakm4=y6mKUVu!~T5-r*4i8#X;aAMKC?hBwQ?Vqxyo1y<r5n!^ha#2u{QEn1xd z0u1bQfj3X_wz8r0)U1f2z>7AU=rEX|%%X#L@CZJ6naA={ZviOaqd+lxgA4AI8Zx`h zfiCEEinZvVLWhLNup);Q`@+hg$5vd%bG|T3P6q%sIH&+4rmz5S1V1udf!*#=i=x9N z@j##6AwU?7paBTMMEgV=IHY(x92Te`RPlI%vq3av5V4?k>II!nH-rHqi;)DkTNK2A z!{V_E9t2+kM2oR$wjBonAR|hLHv)ea!Qv8vcFf2wNM45sOKGv8F9tFKHYEDIvfxC9 zh8$P{j7VVzjKJF$u@Sg;t7MlQu%d`#tVWXvu&9y7gkU5Q7f23K;(5twG&^|N=@gx! z)$VZk5KAE#0qBANd7;a15DaeU0$peU_6BAS*Ck2holXh@67wt+m&&{<We8tz+2L@& zjmb_sT(k>*2$6x^%EK}nEnc_^LGY_3$?0*49_k>V-l7p(E(ilmOHks$A%)oKv^mjJ zW!q5^I9LT3GD$#HYL(q?A8*GKNfxKw;_&$-hom^I0m0$N7!HTXSc3k-@lg=$P&&~e zT1Bf>a+na5xg8O~De{8D6>v(BBrA`;FrveO00N0+Wh$@C`qL3BIlSaU0&zRV+vegu z5<HTPr}K2cQc)vqr!#>Zx}1{3Dd4Gkqs1wBT(TrfHlP@AI1m?EfwTyA?4YoXMxV$# z5Tih;Wgcb@*D2O$B(lUT9mRzzJtAS6tPmilC_0^znYVgm9xg++P`qJtc`pxV?1$+R z#h}LNl)Y|;5B3XoNpK)|F#{opy5bbTA?;U|?Xo0E%r7&z&4Lxy*KTy;wKHraEf%jg zAYeSfijkawfJ<^kWm`ye1~CQ9l(7W1(T0M+L+Q}aCfRIG$%G)mE5#iyhv1OhitH2+ zgbSD-MuaRd>&UVm7#wPp5!qlwYMHDyC-7F%Jbu8$WOoaG7Yr~=5L}@XV4*`SA!Y)z z=$2hhx5MG~Sgf+>^LShymmTOUP7G&(ZdoM>W(E|}Wei9nPO)bbz32iK&>_oC2O2Rx zBv==^F0i6(UaSz>EdnE1c46`S9tTXA7qKSn4#X%R*i7~yOqV2uHL~mpcmWKIDFn%h z8y^<BN@jaZcF3?KNFERGaZ%AYo<sy!0&jBTB|iyP!s-tw4#6!Ut`lssqPS&u!ox=- zISeO;nKG8ZHrh}SL<c~2IqfbuESK3X^8r^{@;Dt%mpAHhI}j8)+>!$$x?D1KLGZvx zK4hpPgLlD*m7EN`!x;g1n|Y5IkYOQtk>c&LiU<QFK|tU|#oPnH(Wl32fin3$UYFO! zi?SScxkTXY;H^}LDc-P+rl15t1<Vrc4UD$MF1g(<$>W6`qKV;6E!scf?S@r#%TN=) z*MXgjkGc=50c#$F=Ga5nb~~LBjoa-F`dlF%k$}zWa521Hz?+Y|CATC|h`nCHE6XzT z6HLFY4jXR~1+&}f0&FM`1i}u{?R40@qD>BmJ+dd|<)cn_M6fuiXwigeA*P}rh?3dv zl3l=+cgq&u%?ITSjGDtK`(j=^C`s{lLROI66mEE6BtN_`92xMYBUbQs1Mhg=L2&az z^y3XjXtgNeCXCGku%KlQOvntgDENI|x6kGB2ds9lGvp6=0v=KFdSY%22W<k^GB3je zz^l0}5m|D}h|XkZ5M96^xO_f0+ENgZV23KWP^G6bP0Q?(gv&l32IiH33=<Yan8<8^ z5SHK^qA*=<cS7s)1tK9&6eb8)U2ZFs-0hLARx#~!fkTRKAm9jiz23?Wgeka_hb%ZO zKD@!|=3ynm;kZlk$%r!~-W!Yiz5ZN4Ov=85!zyE@j3q1YvSI$1fzxHd>pE`HBZ@w+ zRrHEsZ{F>9yRh=9fX{^>#fABKXo5pS!r)%7;-JC?(BaD<#w_Op-kCZlfviX&ITo;B zBOu!ycHR%LsL^o2F~L+hlu*DI@^}=*E(F~%B^(F`BsmaB`~3hE+QfUkqE{BY@M=C= z!V9KFyXbXCWcW5-^n^k_4;nE(ywD3-rZ80SXN965%R!$n7!2^TBNm35+af&pfDLd; z3E5$Dq+q&yzMM7`3MZoeBsPU`${xSXYq$ISAW|XZ0f#iQ2#1~FKp;?w7?{AhMahn} z2zmVhpNQ}w9?y8>kk>7SWigmeE5T4r*qQSNvo5<g81OTe><%~YVj##KtHU4gOMa&_ z7_du0DG{jiDSnSH5UmP_JWjvl!Tc~{AP|zMYOrh!8CZ4dGB6@F7Y+$u(37fWnP7A0 zig;2A41(<8om7QAGCG7G$EF=-FB(yT5uYy_;~imNG8zlTLN1`64+cGOQ(l)C2uKil zKfGGNp7CRF7(Tx@jxHoY@<k#+v{e`%0f`C%#l=rE9zRWz=<xufa99yNQYz+i@O)g5 z;7iS3*_-w_?arJmW00aQ5{YFJp{xtajrb^tjfxNq`C&8bB0g|P;f=-Qm;%vYvc`x{ zatR){J%V?$1CrGtrqfkEPbA=zVjd}+&qtL=V@$3NgbQvV5LSYWPp~bz83<mV-5FGZ zt`H2U!n?w*w9*`i27N&#Q4^2&<&eu43D7r`6(!=L!o;#EWMJdz0$@ah8^}d~cTI<f zV6)+l`?668fyakUsw3?1dC;NP3&#Xo?MlR=;dn5ZND5LckVz&Z$%xw*jZ}xjKDeoX zTMC6-As;BuD|}VRr-U$6$e;2Bye@|;7>k92$z(Ld60A!Fmk`bPDrJ(-4~$~5h~#r+ zlOcGHl!Llm3!FvX=i=p}$0I39oh}wjR;2-q8@5#ngt1W(!(kYAcT+4F3kGQ@mrQz+ z(P)&}EoQQ$fD0jwmyd_S5yb`5mCIKLeDP4gmGn7d)zyh;ye;Xe55;P|ju2+bSVFMp z@G=nmL4X_yyCWV?EGoKV?tHXENrnSTG~Jkr2R#vYAP#Y)Ddwgkgu$cHEHa4WoPZr8 z!oDLH1KthYK7yT$Hx(!(czC0L!{d-*&Y%w+`uz%K;&;2#$wV}zDCvykN`|U3nRq7d z4J6|Av1q^pZSp!J5jhfYhQopo6{^F5C~UYK4rS2=+?WEal}skVSc<?71p*Wos`ON* zk=)K;Fd2y?lW}LjUC4x8qL`JiWKL_)=Pd?cJ8OMDS0vJ;PbM?fc>v>uZFMP8F(66N zSlHq4wk4IMqELJ@8DA!mNFWNGN+H=R1^hxP5{*Zxl_(bLl|Tw_1!MwpqP{+zNKMQ5 znj^_ZzZAht8K06n<n%KTf{Ngd#iQPs&zDR%yh(3$qC1+2D$zu)HJei4G?i3TiPMzy zQW3)7i9{7Lu<9}_KSq>UE(yF_`U3=;4SzONlZFBIha_lU!leYFp=dA&$K(xpy}3*} zk&Q%hd8a!QuFmI^`J`V-r<xOq5ZqMQFUMk@SV)e-tHmAl7(51d5(^hXksxB32*o;| zPsdn-H4la8mLSUXj+R9|(7`mUY9<A<T9c0=(kM8oMA*Usf1ToW_!<KNIUaA*XEOQv zVzL1y2u?YYz(&QHNJJ&cKP?l<L?RU7d_Is*r_+c+r&8GCcZGtEY%GzCdjz*!Th|;3 zW#K3CiYMLNoJ(i>ssin?Ok2<u!%P{QVA~aBASh9XH<3#ClYu}c?eu5-b*cV%J`sth zi=9>3Xdvm2WaH5kO&LEGp%g|>*C2x+13xk0#fTo3%K-20g%N_Cj8YS8DL8_`a7+%# zo}4!xNyQ)!a8p6RUQ=DjRi{!lb+WIRY_6-Ts;g3Bg{rPxE(SN12zxV`Kql%<r=8BM zvppTp!iM|PiH2A*f><V1U7btS)fF-<1*o=BTmUc<<t-iX#^c3IrdX`<#)2(%X`d`N zcztfKmrsPlZE@JnQY7NbX8R1))phNS`A$Wl(M&QY$3320E)APGt2zY^DZ+Jik-9>m z;H<c3N|OP_6N|X2Gr6j4K=S!o+q#mm>P#|F7Y`J>x@rqG1NGtlOtClW$rKAY#-=Bj z^hOy7@su-|tI8?)aJX1-D@CQPurOPfOJ)m=GwN$nk-U<u$)>7ks#d7BV(>ztB@%|$ z3i*SfAVx&Efm}84p0zwd91c&cDK)Lmg+M9oje7kxfpj9D$|sX~_=r?E+|*cC-I&WY zwfKS!*-}eOZA)z|T~|A^x;ho1s~ad3ltMCCRVB+sxw|S|EZ`?DsxocqTr%tr=NcQU zb1f|t1SD9OWRl`i#h_+<h6CwzL!r>nP!~vtr?upvQf+~-FAxwj@pyMS?1}a#62W3| zuCcMPrKh8&FBbE9L&03NH|O_P*Hn4Ev4xE}a7fj;r6ti)S69dE78SQZAgjdusieEH zP+eOLL(;ptXXet4g>1Mbt<=w)*<9bWv^74j&@d<IFErFuGd96?Ajv?;<lT{)y6RX> zJl;_6i#5c$>y{T=s&mD<j={F3e4-|nYbxe3VqINhjEWG;mJ;zqBnVd=jbKED<r;za zg4G$~box>q`ROfgh+96841^k$e5NK>lg-w6Jn>vS-qGID&|Y2LSqem2i+!b1Q>iJH zZ)qNEY{(@-iDF8rtBciT!?m!h_1>Aa`T9CoquN4uzL<@N;??c#4b`O*1pz6RMWRwy zo2RLkrdT*%)mmTI*4C`#<I_uph~M8Gj0D4BsgTaj%*TC+d6`VOzJ9T(y}dNMw{dPN z6$nJa#Rh*(Fxb#o3msnGUJVW@x}{PEBGKYy=8BPGEEURSeeHD(P4zK%Bs^p0U@_lb zSB#bNvDU%C&X$gq)6zqAZHuy@y0(@E#%3s9RI&_&sv2LsvAH4Dluoy`1XHc4SuLyU zOAXcaEj>%S+G{dRsp|Innr52XnJK~GEiL`{F^hO48HEYMh%uIH2j0uJRuKfhx!#(A zk}sXk*C<&f+8(W`YOHQ76dV2ibTOUo?Jl+TG&J<~N8(-ebNl-{`a5zprOuPv+p06s zOnpAq+?;AI#G0D?{#O5BQ%!4gGMsFxn_1IPNJUc(-Q8^s{rx4zQge!m4-EpFYG`Vr zDHW@!?P_W1>gtTur04ZFCPJZ^v1B+FbJbN<4c4TCnUe}t@z&O1OLuqw!rASMb9jF& z5pQS<HAEt9?M;f3TixBz-GH-5q`$wazf>yunHgrJK9vhs7lJ*_Z5^#CUm`w#@Z^S? zp62>ge@$xI$tU+s>)klLYNWaAlw!EKtJKE$45u5SMFv7`V<6q$*_P|5s_HI<b6xob zrLC>~Z4IrZ*`qUh8ml_;4Lz-moiuglsJdeCQfXeHssO{9%w*FTF~xG-z<YE@4MFf* zoYinrUm%yOZirSz6J3eMnzs73+Pbz-C|94$&zjLUZDwohtU0mt^p-_)=Jw3(DK_-= zuI!ptUzMn8u1<DzWIO7U?d_pZDYUe`vDA@CWZIht8d_>|@ZvLOOlzGpx37bxY&{b7 zneB}<wbPVKHa7Nmc21w(n{3D}p4*;|L<ZvNSTgCxqAYF9hpSGltx1(iYpgS7%sqKQ z_bJ6<G@4GeOpCO|<I}p@qtW8#8Lcx~TPeJA=hn>a>+1_qyH!ao*<zx;R+-r`t*4X= zq*FsnR<<<E>}bi&ZOrzsSUJ0I)>-pvPV1Pyx-QW%y>A+0Gm&da)G-hm+mw7)Z&$Iq zre=CytT?^6w0B2oPFHKGZ*arF%(j~DV(ZLOTQ5yBid2MpF?!$P+M3#Yx{%2i@)$A8 zax;K8UL4tlC!=@iM(~SIdg3dYwQ8e=81VDIcxkosslrnn|JqadS6!?X!a_VOgm<aQ zv0W;>oU9x9?;Cb$M`$0z<#$vI@s5xizvqxGc`h+uYyPfTO*UFQ3ris`6xT=2_nV#g zLaDR1^VriI|Lf&PpFdh%T+T^4JEx245z?#b9d)%euG*T0+8W8FmUPibqP`9%F4e+F zZn`PjK09RDsq)0X7RNu2N^|Lk4VPZBal@sWtFOKJoS%j1uYDBr+#jL_L(heuq&Hl8 z>4uG$TngTL)YH|MYcIn4Kq=B#ir6!ujOt?N*PZ*FYVPuV#v6^lG^&m9%ZL4(Kdp6J z!(g)Q)i%cCj^~%VDVxhVr=$l%NpM8DY^;%M@S7nhN+c7>`npD!TqC>e9QeL`nPF&! zagNFs*cSM%Z6c|vaT!)D)h$uqcV)n==2U8xc68_WUvWzhDsIl{)9EJeRjySejr7~? z_xbRoZzkB#;U1=#ZY*D>-KG5|xq$2;=a+h$XU#cPQ@<j6$(J{3^6MKHbmtpWmtMF@ zli0fRe52W|@$a;go&H4Q-uf>a=WIED<EdG9^Oj4@v+SpGr_MTcR$=?7I*4B#Jk)te zY;G<Tmh)|gj~zP9A8rHX3jD8MdGeK44hf>%%s(km^2#Cp6=a^mQC-A3O-@#)$C5bN zX-zT_M{xxh;E<@79MK3KS7t~}7O=}esDb{~0wuYj@n6dvQx|ck$|<R9Kdns*>eOhd zO=LNpzP3TTi|4dfwJ!aR;(vC~#jCVd&Xk(?U9f2K7#v!oobvf1+vW|_M(659z0sBN zSDR0dFPWd0bq2h(rE}IVTbFRetJbY(kac<vzr!tct~)O`Xmsf$ozayKXAPU5_0=1l zddUz<sbP#Zf4AE;q0bi2N{cTz)dx-cwfHF+y?)z>#%H=sC#rOYvmU5g;#Qkoc&5<d z<gQj-Iq{~fHM#UIJa5CD&uKLwJ{UEpiXvVV>${xOX@f!_HhIp~<`=uvHrdE)t;UHf zMxV$oatkgM9&>QmCN9)Gr~1mwe*Ct}%<^K57jIO|C6|>J%2K1G(n*}DnNtg#zLV>B zah<Mtu18$YxL$W@U6EP#&JcbOsk2p7uP61R;y`MBm1VSbUVUq)dRDDyh{P-gmn)_< ztm&JjE!GZ!8`AmYu|u6t9oq@{a2Ld8`bWh9ig5J#xB1sV1hKiW{HYh7T27WPXIcTp zkaSK7no8FlyG*ux5D6?ID}*F8PU;Plhl+;R*HuoaNYo!!di-RZOXFSUm9Gxr<`z8Q zN6+f^ns}j46#4{#^JR9VeFl{zW?e(Bvlnbh4UR3}r?xxhO42;ZHgorW%@V`!n_M&S zwX1^LPZ!@fahj&?G9hFzT!^R4eM3FYnZ0(eaeAa_Zg$C*%QuZ>q6-2#-9^TD5w9f? zTlt9YEo~CNk`u<S%QTZ-GP{%t;Rd#xB6a8K_Ew!o`diM6>@A&_>g(PY-`l<~l&#)p z+}pTMQUkj~M?X1QpoGHp$x%iqT%M=guX<oSfzxq&#z|_GUPZM8=7ejg$iC|{HR=-4 z2=H{l8geJ(b#Hxm_gx=;c-P$@PH4WqUw_9izW6wUTkPLbwGa>d3{PzR@b0@mq=%}l zHj${QizRA5IiseMtKlxJT>DV<J>$fi6OZu|-<tSSs$_MlMrt_AnrD-36IV^vICfH^ zt_~aiI+Ze+fj#Ohzp7oTy_B@zcW%CSPY0hoSbo2>)WFw?$z)emiyY%LF)r4ngo|NS z7`qbA)XH_V8r*K&g%w+-cYR~CxJ%q8s>S|frmn8()Z(V1syLR(1a0OHS}}%u8!=T- z)qAha+O!70tk8KBe=t^_LP0>#u^f213rClWC=i=DH+3TX(?W9r=8Rrm&OfzWpdW_> z)DZ9+$W2Yv#W)0!B25K!%7inylP0|jY*{@6ni?l+=8p?<yo#%cHI_lUG#$S>KI<N% zs;z&<hBNn{GIVm|mXmuPzx}HH=P%^dcQ5F$%O2f~9+NV=<Jb!IR>2!l8q*6J8+GIL zow54OYj3|{L#eyot-rnPdx!U5HTTzg`;y&8YvWCeWw*<xGDS@WN3(NxYhy6o2yGu! z{RQuaT!i0Lij<s1QUd&!3<$%*E@7Xb5&Q-T%K^^}1fYl&<2*S_s#)zElnN#je5-W) zph32`*{yYW>aQ+i;g#J=_{$Nm=C;kJJS}N7?zIOS*6j=79Zilbo|vv)k2ka8BwBLt zL^kx}2QGF55@c7D=XXgWTM>+UZ22pP=&%&4DYPos!9`YaOu6~ShB#$Gy*@F0S#?AS zgwtJPxWb$Ki{2}Jxv%Zu54d`tnJ;N^@3eTw((A6;bo$+o4ScEFBRgl#H3cqj-TBf( z&v89}e{a3%BJdUiZ_QJ@Sp#lolT+o~L6U)83UA$IoZ{`Z6L@0|n)z(H;MCMm&ZrLu zW3oneshit+FD|{e$Zz74@x-dG6mEh=ip%>Gor1~F)&1b0D)8JxFYRo-JYbqT(<ytp zzcldJ-KTH5>bj+O6mj?cBGdZ!{!YMKSY=j^Lo;egSIHklm{T%x#%vPbK-lr*n`NHJ zi8^;7n#Q8N(&l-!?bYS(L!75jyR#tF?kITp!-ro%iHCp1U4a$ALiZt<Ol~O!%Tq=Z z6F~sNC^fg3Nsv>ITedA<+L!Zv%O&sg=lTZLY&7c<zKv%@4SdMe)abH>4Y94GzLdt| zGI4V|M9p|6+kC?}nzPwEIJu?WZE*xzG`8f@jktGoZ_=je#H>POu_lIhg&Rn1DPT}t zQG2=n3KvNXB!&~}M53|Dw$I?Ysy4qb@fFC$;bVu7a?C%p9X)pRFqMwUFo3y)O6Y_o zU^-X{2UswGnK4miiie45VxrbsKfE>%r}?uR?V?&6+P<vWW#iNaNBzQ0UQN9CXt7JH z;XW+6R3E!1o)wW-&RpJ{#xt=kBimAF7tq`^XMsbl=H6>|>ZFDhr&VdNO65OK98q1% z{T@0MD&b)g{CXAE#e2TrVkFc|^Y3y{r&m0TcgS@`dca>rbm$UL<W<*Z<-TdFW~~m% zSLK_1d1LjD@2|;m_ujRsW%=S$o9Eo(v)4{54xY@H?7^yh7B~)ZE7Z%>!|*HVl5E$7 zbSfRW(ka{;u@4w-Fwam1<QsgX@b=rs-hP|oKREpNCz(oDG;7juMI)a=*2ytG)XPNP zE_;*LCl^0=Iv2=gMT4mHcf~yM|5|O5)UDa>hQ{Ghysyl6MQ{3MLewMF;qdSUhhI*6 zM|HhwDLh@Y<m|L=vfg0D+syQT($HD(V>L$V&YoHhHGhga`4ioe>iP$E?>=~N_wEO{ z@a_j#o=SgtgX(4NmBddnB}v8);+%mmpG8q7K{0?ACPfn|)OOZ#{1N`h#kQ*K#kQSH z%HabMDV`8KioVLsWS8pY;njwQxkA<`YK_^2xjClM?HAdidPi#W*;>Uo@#w^@{wF40 zoc9g9Y8*9%bXNQl>s8#lJzsXE@OuR+%<y$>RP$TRP$sdG!?Kci3LZ{esdL*`8@0~W zYU`9GJGvZ!4TO~^VTA~cp6GA2(TTkiAK`B=w;jJ?YT&j{m<Adf2k4<%_L*|jtCSB= zix4e;qPka8#%`#l6bOYRvQ9JN7S<7Im$Xm15z&5J9`i=Sc(n$<r*rrf8Z|6``^jT( zBVwo+Ru8qVQ|eE(U#Lsq_*Cyz_p0&8LJGT#=;hI@?Hk^^24tJYy!vTDb3o@@IkD#0 z%}J|KrOUMZzJ*K0g*wh2GL@Ei)s6(!2K)lw3z}uXsF8G+BKVeUWf3nn*Ex&L(e<g6 zu-@4e4i05<+B(k~yI})m^X)^&b{=+j9zJ#i%)Z^mzm4rdGXle-LS=sdb47zbdP7}9 z<(1l5%C3mJOA%ddB<ZTh6i^hN^0P6h`!bs<sygMYzs{RDJTG6XTUcM;`Tmx*Kh>pm zs<i7CuIKQjxAqpU;2hpCcYbI`D0W#iAp6De$#*(+9xGn1;euW3SGCz!*WH9Kc-Ie( zKJd+TGj>`qKR4dT{s8l9BlAnC_-Ip$-+`a%^A~M~T(LcKYLZK?scUI*t{RSV(Ws_Q zYZHbv5DSFAZp0jg<wp@ixcOtt4`H^4pZ6Sg^M@cRVl&;gR@P=}g3QmdNlsb0&z4l` zQELYy2V4EYt(QH%`nKQdtFs2TxG#R@4riaK*^&{AVfQk*W{r0YPt)QZ&hU93+;!>x z+egmf7C*G=BzG{Y6ZhVz6sL7-REEg6>Ox{oqZGDnIL#BWH_usi)4d~so2cxE@DBOq zS`A{flgRGUOt){ar?qySZe@RAuygSILG|F^sWZ44^X9FMXQg;N8;?hZvYNnHYdkw| zJ{OvQ>ikXf|2)4uUps&Pym>Q(YE#ymRb{pKP8~6B=W@C^XclVSh2^J<&4B9IA#5Fw z)D);<@8l10%WH7y(6P4<Ke>~C0cswX^bItIl3n#D$TM@nlZY{){&f4t_LkHcIAu7w z$uk!R5vmx(R%#;}8#I@v;$xClqrxkl{=oKN<BPR;=qVHEoGA5s4}Iu#MFrd9wfZv_ zMMV5+rX!nj;@!hzciBwQrWs!M^>{1Nu6Zb^R{I>Wf+mEwteki>T{9*{4YN3X)O`<k zZ93iQ3**j3?Nha}MRT&#jRwDWwKsUSs#ThM?qEP?nm%JuGoApa_U|2yN9zOP1Eox1 zU5#UuOz%+ES-k!3Q=Oc1jQ-Ntc(=N{Ta#{TU6qZeH8x>QMb?hEI}hzV0u<pncNCVp zE8=$OZQO9dc8l62y)Mimm<AftMd0nHV50#6{z0RtWYyNtV2i0B6|;)laO#+A#jeV8 zaNor5{`eI?FK|Dpz4@-_#o;twB5`o$(eJ*-S&UjdVXlfJzP*p*ysjbnz6<tp;}ieb zuvpgE!n?!YReBc=xe`_PSHYIpTdcgw)}`_V&k24fqEnkK0jJw?+UZpG!sXXBci>km zBKT#_j*@~08K7MA3BEi{uhbV3tMJ{FhC;H&tj#e55a1(Z-&t@UV*93=0_MFO$~LKD z)Fj8Ly})Bz6=Mh?z+5Xg60|35j5K%L`Hc@JKAyOrv;UbJby`-1B=1^ZQ)!V=t=C%H zPriHe857yYbh@!Am2Tt?9^JW#Yr_vypY)U4gA)@WDWw<Wgi6D&T=PSGVTC(+%~)4c z`5pCy)=a8Np(MNAJgE(>kLpJGnt=DD<c7QkPZv|AIMn$zv;Z5vSKg+(ksXr;oQ7~y z_B+W8Aq_y;USukyU;z*d;auv8@P&Qz>oVWVruV0<hBKS}b=7iH``_C9KwFa!%|FFk z^UxCyH45r0U4iXS|NW&g7>GardUb9=oyQ=U1Bt%Ha`HzBr%c~%Kac*8X}a>Onxy7c zk^ukhWL+s&=LpqsH7ki7rf;V&Y&BG6NhhD>vMU{=g=;y_&=IzVt*16{4Qr|nmOm<4 ztEx2kCW@0aZL9EW2-u1(e+q`N>F9E{BcuB-tQB>jLNm5!G)EWnMC%Aeor+p3OU9x+ z07C;;s?%(T`~N6=6Tqmdvv2&Kd++S~zGe1gCX-1r$!yt^$wEj1WPz|IVV6x1P!JGM zLD@tFm*QH2E4X8;R=cS!vGoP2ZLw-A+P;letytgIS{HKj|D8KCEVl3WeSfk|W-gO^ zp7We%`8``znuD^)dRov3;YV-&<wrL^+ERs>rOEf`u9H97^N8P494L-Ci-oQ2P1VRW z)7`#=mDmcLOZv%-A1$3Z=h8p4ZVw<O&{rI&o%G|uu1Q0W4>UyzJqoV4qN0;kHFh{A zm50af9}19odBGgYt2WT*ap(uis|^{iA-IUC;N?t&MEYE@(j^FQDnrY>l3pcIW?6Np z3DSQ{o>eKA+V$^_Wes*Vdq_pO5Ah@}=A1I{*{m0{>Zae1{n4ymkak|`OgGO0he|a~ zvyWcB;i-GRBGQKrj|u4z;)})M6npn?o)V6EKWi+O8mu9fGb~#6<lnZgx_9`_P<6Vv zIGqNUR*iqk(hfW(V4I$pWuAqV8Er-sS`+jtWHu|MFvU>4t_f4K4w?;aM~v=W{TP6J z5ydIWK@(Nf#KjV@NmjP)?o})AzVy<&SFXBy`SQ<K-F4ThJzbgW>Cf#glR>}n=Y?b9 z-&FxENxy(bynoEtn9Wl4RDXN9%kp~ZA4@+g<w`@`HHt8_>bqNy4cTLk5&Y#Ve`go5 zU#9v((~>j89HbwVY<bO^GZ?Z)54|P&_gCHRxpJz1%5<Lr`DYDnFmOx}NvL6iW=@YT z$?jWu;K0gN-}#QPV!iN}nZZoEMy88YX*KrJ22aam$3llsDYJ4uHz?Q7=($P!JalL( z&KOI~QZJ*f^j4HSS$L!KM)Q+W*o<f1fBy{b_!UqKrcQRN=}m%r^H4$lhI1+{XY*va z9S-Is^ZGx@U{RmmZ1#qU*^46fTl%N38U{!m+<Eu)I~+<`oQnjxUaf6+52uv!JqH~c zMdKtk+^f5+xw$v0@VHhN*caJd>e%AJA;VhflnmwGsm$-W&$z$C=B{Sk8I7B%HN|Q| zmn4;!*rk-*RGil1GkY3wlc1?TYnNrI$tU74zYLV>l;Z#4HSRN+oaNN4Bqc0s6aL<2 zRs%dWwG+q0E>hfO()}M^<K8fD-=Wl_ZMU+B?4B?g<;#NKB7CjVWuIxEtXERJp$$7w zhaIS3$}={rwmcq`yS0^(8-q{EpJZ?BwZ3F!t=NX4_ebA<U*y?S_4-%xBIY7yX(aU6 z<=y-266q$<ZKA$3R~I<6s(<=^8R~%RYRu`^rlBrW<*GVxnK@X(#$_tU^*ip`6~L*v z-=m23HaB0Ub8Wa>rg60GbF!$LSD5Orv1wJADblrup~1y5wF`Svuo^qzhL+d?@23cI zwmf4uFJ@fwg@^P+AKFqH*D7OoMpO>#dh`JUxH|T(s3=YiojGwjXGZ3ko^Aux3+Ge> z9%Z@c!bk|WV@~<DOEf$u^Y3g_N<+cAHNJVWQuevqx_-X>X5prV3va$@(ZZW}_L;e{ zy7DR{i5a=ltLv8}=NEnHT;fFJckyLstqX6wapA%nZlHXW7=J_ZJ;}qk_gdz*Orlsr zYTP8IBX)UwEtB4*3*jTm)O%OUp(yH}O1_w6lNq(HBe}<FI#hGChOMC;X$$d8%^p;n zq5X%-tLjm4Cghk0n-EdiQ%)*i1nenRK!ZSpLPOBtgRw?`Y~)N7SRKBBSApbVWATdq zjDE~<Y|Al7CT57h`(!9(LczGmrdgW60-$Oo7+|O-NyOd69L#xd7pN7<_k<7p7GGUL zBfX({-`v>)^N%(?CJ)#b9e!E(;+ktucs#;!p@%$8Ql#d&M}_&9FQ|=P#{SqVJRsv| zbY8aX*6%O7tlO=3EEE3vvlH8Q=sz=)?~^31e)gST2|r!5s3Z;g;h*F!?0zM>haboc zZcUQfB#9)6D@infb{{vixt>VIA6K@ahjN765h2$^$ixUqM@TqAq);~1ZsJZR>l-Q> zh_`_-4MeByNCu%{!@a)VAS)RL0w=c)n;d{c6QlKpgnqPXl)8z=nz4E^G(<sBM{Hzh z1P|%Iv-Yu3haTVG2S$&7SpXEYqVzM1+?6FLeFErnBgrYPyfI>=Bn;Ct1LINhR&n&n zX!OyjlMj8=tB~6x4@Qa~D0Y*#6<T|6Pw=K{wZvdkcGN77KT^q!T{3G{Dp;7LbtoPZ zFLuOB<#LBdl6I(!T0WqA@apj$W24t8*lj(jOj|IOqIOCjC^(47VGwe-fti^}mZaNs zh3)Q&c4}Lj)ZMy=8hyTb@zrrQzO1)=emPrSuA~?g8+z8t)_2N=(WrvbhT4*%<2D3> zKw5k;`pP>r%BUa9Nx@(MtzpGg!zJZHF%n8pS5y=cDKJvj$;h&l3C0Pv;3#`lr6q&w zHXa@j4$Miup77gMoSd*O_KCB%Oo)WnJGPF!cyAExcod-nf#*ul^hQ}a)iHq_eRSIn zx!k>qJiF?0(md@!t!-g!cK@vQAFJf1xnyCtURGABGzbk-b+FPEdiVnbr}1q`spJsi zl!**7d?ieYT}!m>frld!RaX&bF?4xxj6@d|-{=~t`2|BHXENu6IXxQL4ZP6mI)6kY zr9VMoha?;;ZJRuQ$By~;&D6@&m#wz-+;ZKG=gvgcF+2Z^MR-i7_J=LLz4I5`G+%%J z!v!YKlG+q`LOcjh{~Q_kR2MOrQnD3zVT`HH1mr&AYoE=ajbbrge6TXyX6n{->mRBJ zc3RoePSjV?Xh{<^)EA?pXY|5Q4#URH`zcJH-yt@YtRvLahy9eZphQt_F^gMrbnX17 zg?H*cuA_T`-2Stn_DLaf`wzGGOddOX-}*SuS8wd@Vn_B0|GoJ6+(xV;zrMmo$mZ!s zhVQ%b;b})oA`e8$=F9-)`_QrSVQ^s&Gd)w@^xYaJ_}!57r%YdLVw<De&~1LGx4C!1 zvsH<N&Q;tS?R2r-!;?DI!}4AoR<m`~4)CsNOpK4cGPd;tk^4RvtJl9fdg^_>=*YpN z%`2>&u06+u@vJVkS>fem9k+9g7lcbk{~KOFu$9`&Hmjc^`~1Ti*mw?!PiZ_VobDBV z)|2PUZc@|JLo&V9Dv8IE{(aSKP4^J&<S9!`PKBCiyo&jk-Z-Fk6FuBL2f3xNVTNkL zP8(;JyVsDH*IZ7jdWW?(xjbPOUPU%LoZ$*JCs(=)Y9|_Z)>ze=xLswZygGUOEB+w5 zr%hxgWg>0gbuyjB-O4~)Ek>qPJ=9Uq>+3Y?)kLkXtY>?roh`jh!}TSVbn8W=Q$&jM zr1}7)LV)oYb$CGmy3neNNI;qSLK0+MT#?No#LQKcl;IGlA{sR|pbh*%i`;zn@~M37 zT;r<###t7Zg3m5pMx=b9$~g0`&|M+FLWc<<&K}axJB>`4)&RK7%e`h{gGAykS0Sz& z@NM_`uJ)oHKYs6SeY(tP<J5Au<v5vh`yw{3vC9jZt1dm3JGrmp<ko>2;Yhc%sIA6n zPIoiiH4VOY)x-74;j-b%O0C@4>+aHW!7eE)=Rk{*GdRtZZS0^54#XL7%;+h=Z2GYp zP=m&<VADu*M>i*|vV25OO4fbKnaf!i0KAd4cqFd};|mtYe*T#7nlOnxMXGK;_;`<L z^|FxJY`9}!{*IgGHz!#w%psjD)_zUt(Ned`TIDeq$zrI)3Q|R$YMHp!W%6vk!mgRO zcfo?&?T&RbQ|NtzLS=jUt#lK{RUu9_J}x;e*@AO3FO$x6Yn0s$ZCzOQl>7VQ-S%!v zs;#&?&|UOUZ%0dsp+jFoYHEBF%7!aSSc!WWn$78>vKwk`G!79S7v;D9SX`71W5-5E z^#aAkDQ8ex&^1%7h5e?RPtQgE%;cYk)DRV#NC!4Az;ieWgn9mXqvW)^<l#v4krJ=b z9=c>nv0d$rJ{}E!Hw<B7FL|V-?0aQ;w=uF|b;x1RmpmRVITCT2%x;fDUero-t;Oi; zBPnhb{-?F*yl`1(l`G6`!r$5q=+-3lH;py<pflGAmFrdsld{xe_d?2enX-(-f4>ui za<}QbmED?$e0IyQ5$YZ^p~|dj6o5J8BVq!d{@dEWy+$Lu*ByPLH1be{-h1iOW#{kJ zeHHm+^HOrpC06X(5@G3*%>t?d$@rM?L-s@5NePq8czoRjZA>?Je`!VOno?F>VV)0= znlnd3!$H=prYR%f%~L}TxNz8yG4Ys!v{s8=c248uT{h9<XTvF+#w@kj4^4b*=1))+ ztBo(KzY?W@?*5=p4Oq@z_8jiC#35O*L|DGWf4yJ$*S*5%qb6PLn#2m)XhdmlS-b2< z2frY5YSa$Ug;Ef@=8$9?u+6QR39}$yjK(Rw{pQ}@{{G$>*829YE^Et-*%h-%I??0k zv9?9JgWaKrX7#K6y~fV2`e<#fKT}yg9A!PjE<f5*C@8gKS%L%FgjH2@hN2mH;vXB* zzXQV*AU9q)2XfLK0mFd>>G!PHkrmJXZ|q2wnuu|VIw33Iv)+p2P?5G^wX5o#D!o!- zPi0JY7f(#zV$JBIC3sa4+~zY+G=GAzLM0}dlQVlmlTuZ|UggbfjjjaSt!Z4mF`Q|Z z#QzhQwhMo0FIE{ox_PD7Em1TPfAL=ZjK;}bNrQCv>?aKGh%tg`<Dc-Gak|S9#c;7q zg{M2%X71MLABq(?hOKN_Z@5!F%u|K_3RQq2&*ISs`gijPo~X4D4gmO1L7oc^Ck_7O zk0&)#_{~A7Lw{&=cc<`9rxz{zm5Tf^BoqT<bt|^syiy@GlAoXapipIyhYJ?6O{+fp z%X%C-i|P^KiS3j6*M!wt2c2O!b^JZ)2Fb0=6z0CnvRDtfCqpvI9!+}(j+}lHne<fk z?Eu4^J+}6e?!xYHhq5#Ll#!{{S65W`R<EhPw)#-Dth&0VyL~t_+#1!@>DZ{H&cYT} zC#%_Ni;fG#drNc1xp%lAAXg!j2z+G-oRqWCkvRkN`xL~wXrT|;M;v2OJ3Y}OLk`3h zat{$<`<7%223Ya)f01n<6+S7qP%|j&>Ea=tvzT!xjnWPN@OO*D!(p#lYI@sT@VZ&5 z_7op1&Puj29J8W3ixjR^TS{d*e{kXwoy}NuXQ=2F6d<B9N}iQ&Zb44IbpIRQNDZY& z|1x#*)J>1MqH>MxN+Gm?3bx$2d|Pri)6D!iGj*1ZEY%V2modU8h)NG5psXx5QA=RV zO0~omBU)fkll7?G(`yse-Kjn_tA_Y#)mwUueMQ~g?!ZGWI}@Zou{g0V!L?&3-1Fmi zX6n_Qg$ZIzkjM07kDd(ZFV%0>bDet9s3%c9aq9`I)hA-SJJT>+3;d*vRSc`qOU*fK zbBi)Hw=rN-?9DvUJEGsB_{tskS0LWr9~(UvrlkJW5Dn4Cx5nU35$crA6TMQ_!kyDc zVTKxJ|MBEs07Sr_zd&wF-nOzq|8@Sr4MBrl_>M=b_7>h!nBAjD*#Yy+mSU~Tuz$+K zN~gK_P%$)<Q8NE>A$7&rQW$4`@`bxw_(gYK^;}MVvDRu}b?T_=zt+AftDQosri78v zk@fEd`1dptTAL}n6B4t%9sBj5;|_3ad#990AGSZDBf2gH_b`z8E-vq<gCsD_VV;W_ zCjVP}R1kWE6X$$}Bzan3cFbRR{jPcQcd$RkD^v15voJ|GzF_YS3+LUihx!bY#=nxZ zL;r-CI5QzryfZ{5hDdQc^I%flt%$X`yKUXhhZ2>Y=zM4?=?n~eS>v!4t?5Kb4IDO> z5dDV_U?b=SKq+(!bN)ltRurwsoKc_`jl=9AVREoD^&%wgd-n@pB6}=lG|P-LpP&|@ zy@0UJ#xEOFr&3>%s<A)qi}0QU+*IN7I}ggd;d?@&0Z1)nj9<Ho8p<%QzP{}?+Z-FZ zcTjq3C6wMStgItbf*u2Cx@qQ!iL(}9b&){3_2FV~mxC+nKr2a&Ps3?AyNQ^vvZ0Za zLs_>7P7#)fe5VBRL&R_ba~^V}79n7e5R>}%Xtf~x@k6bxu3NR^l0{!tJLRW^|3R<% zBuS9((S2ET-Ol;gmyv%6n<u&oI_nj@O{;XMy%jh1ku4vSIC)Cw6Gj&7-Lq)^o^!jj z6xz0$X<@F)bnVfS6<RV&OG>m|TGpi{N_eMA<zyxen<AY~8=0E+$_LvTEZxSoP`9r; z_)x1>$#9;u{@LbcPhDpT>l*gR0cl{h&=wR=k3rkg6vHn@KY*Esbt8A{d@zw7zl#wJ zQQ4k5Zg~#?1|i+!szBEMr<k8;8|L<!ZuL@E=@ZeChav%$G2m}N%MKT|e8!XcEw`}6 ztH|@0eSGKB)7RL)9Q&__BYfn3+SSBSHZb*Y)ZZq2mbrNAk>0Xs{k!{*_M)$YAm>)C z-Kwki;ADBmZ{)6*9L8*chclSHNouXctt4g%NqUGKs7L`ZJ4u8iGd#%KBc1}^Iw!fr zNoF{SbD~s-@(eb_NXvT52#@eSt2OW9$YzeL;K*!_OymeR(f3fP&lxgHIW5x};>?{o ztryoZh*&p$0?UOODn$SJ8Ig9t1%_a>y?aWu-RN_;Vu+@1Qqe|_4IWXi8q$lJAru<A z5Pm=ZI0%(vvU1lyc6WW#Q@4FbBSXKcOD}2ZD`_e1Bc(_8oh(B8+tNok-p;SflnGxg z-?nJ^lIf+KRX6fORu+yGXWAPx>)5H6{_v_rZi#iJa8^R~hH8AA?~>e!%&CD)>Zuf2 zlOjDS5-9LJXDw$cpHp;8+w7+9{Z?YNCR4E#aSq$rVZO7px3IUE)egf9$ch9Q9dCR< zC>RzS8hvGK^z5-?`m=~n!wwOb7>pPF2WKHHm0bkb`^Cs&)_>wBS{=d}-r|An57f(V z;b$F10|x|QI5n^SB`KW!&#M$3rIGu<tUH>3S$!2;1JT^Bd|V2{ST(T7Ft|<5T5W0_ zM0;Q-R*QLl5;{qvifPUiZ&Hx5?h?`PuEAMpvjJtOPNWOioyDZM^G@XvCA$Z~C&*)p zkTjhFbo>RZhnxkDZOfV9Qok>^P05^!fg2pg8NlmUGsQ}wc&gIWV1Sh%=`yjsn}l-V ztE;ap_7Ic3i$uFJx`2h<u)ts_oV`&g+T@F<*W%yq7d{@^pNg-WeZt++5(0j*&dL+c zbcGPVLX$DP{GHuwV7G_Re%5q1>);JehP~LxY{_VPG9)Gsm8HwBEaS?aM|db1>W;J( z^f<m(mg=c&V|uvnm7$tYr7A0H%IGtsp?0{6jW{Yf&Qn%~D)V6vtD$l+K@~Q&%xyK) z!ps7mFK><MU#6*ZV-$MH{a~uW(xf^|nk+k?$2!9y4rGAmn0HJ>0>O?FZ72#M<X@0X zR?eE}tM74^tBuqz-rzQAJ8wLqvcW5iK3<}?6?r`cfuNMIGF|jBIEHXx7EKa<J<0Ox z$J(#EJ2uyY6tr70r*l&j$U;vM%+u+@W7Es0H8#a(FQ`l|C6x;Jg(AHK*-_AI5%X!r zrN5-&lFu&TeDa_5k}G>jymw(Q>+2=vUeZgcXZ%^3T$v{E^ujdjOA|BVwDjqP)Gi&c zTx#KGcK5d}=wY7kH5hv3^4=fRTP*eM6MMRTkdAf7+lqPu&!_iz2<orwb|y{qX<xcG zy(Z147tb3Up3P2Z8E#@N>E1Z%C+oWup0bkRFl+aq;gPrn;wFe2K=%NdibHF2TL5GB zY<3Uu<4jEh_T=nK`P~s;VTP)yoXLI9?ND}mDj{)lLL5BIQEy80slv>E+N!L<i-eK< zPUW`{oK5}C3+yXMG}+OiMf|+WRJ<`*Kgr^~+H2H=`!;Eec;vgrM|11N9Sz-4q}P;` zn$V;U%@s-xmp~;rl<1HESEDGX(NpW|krJDd+sys^H_G3BWRswVgOhj`yezy+H<~M| z$?x(s;d|5E3zyowGv*YKlhpO6T;ZEHyU?<9foB@&o@N1h&?Eeuo|P8Nr}#v&3%d2j z%=B38yjs?lB=PF+OU>Hv_ovpS*wz%0rmQJ8^>WcB0~s)o$p)e@I1H@eWvR5LR$rT` zT~m8)EuV@9*dkK&GFq3tT&*+*3<hN+z;YB6uWzc)CQBP@-p424ar;Q_0EzkmJ_-Ff zMsrW`jmk<mBmMvj!6?N~kQ(O#WCd|A@ZF5`%m6#j3QBPkFp%MssPLR|L}Hpd-7Gv8 z{o-p@9(8Z>IF>q0zu=9R3|L4*R4V<3FlIBc5Zw)1&7{RiqCp=ib2=||A&<?h=Y_x0 zS1hj8u7XuAzwjz=7ES<TCYU2TE(zkKw88IJ^|a4xXC?Y%k|gO7XsBo_47^~kt8Qc1 z7v#yLUDYjbvvkv;e5~C*p}nG==-NqZX1IZ^sP^$mxm{)|jSPoa{cu*mP|p=Efhb*a zDuia@H6Z`%ENW!%?Tjc|s%bn*YNnt^&dAJit4JRzgR>v!C5Z*sWhKl-^pgaYx_wU; zX#v_$lf-Yf*I$;IU?oJYvcUz2y%f{&DEGE{0va7Gf50RVFzMf~^a(Hiv7#V#DoHg> z@>I%KG533`u8X+STh}!~%2;pT?`W!WIFj}D_%AC_ivqg&$3NoBpkHg46&cOu3bM{Z zLKVbTK`LnSesm`upu5)Ok_wd3SMW@6NuAHBHP%*G;-$9EKyQex?ls0cq`hiz6JTzj zl1-y$;vzuuyJM%25jS#bB%jnt=m{51anY6#&oUw|lqjhr4m4#bF%c$9pmS+}qLRvb zN_-jm%1JDBf32G(9GX?iaaKFo;uJ<)YCUInMxQKY7uzK^$K<Pz7}qt{U162z$&u9k zkA`gqsjYMWbfuil6q{Ya+Ah<J1@LCKJmU#0`_aFg=!>l5L5+KbP22{YxfD~Hv3Z#C zjiHStTa6pl8+B=4;Witatk@=FV*fnW^iLY6g|Gg>2k#(wB*A*}l1Y?H7YLdx6pdgK z&`23Hu8D?>s%TV=+rUfAiPsYK|5NYtczpPQUy!oqaISDnOJcMG8hFZ*(;O?Dj_>@~ z0na-C;O6Gr*zVhq9N>2RIHo0}Q1^oHUyD}>|7g3u5R;_oN$?`u_H9HQ#cW#(x~X1? zC@A`3GAJoBSU42z{fBH@x&rzk?gl4nLW;Ri6v1R<-&U6NMEm7ZqrzN#y?oicO>4qt znciPId!<h!RlD^;-rjQ;`9}d6AQ?qLS+TWk=YzuY!p*pw1SqP_Q?$ew*y!Bo*(%-0 zY~-qn3%6CWX8Sf(HuMdO0^80}R5V^L@R)PRke9}LL^MAQt$+;dY)m{a?m6v$q9d}f zFl0PS$nzAJEWT~*d$-*@_KTYX=c#FYj%ZdbCg};+QEJ9Ss#BVJkTkxMJBvJoWX5iB zJ*km0Pi7FD4Qe!%aZN~uj*Kn~lEg>q^~iudnMHI)Mux^l^keySaY|dU^g$$aj?@=e zms#tJQXJ8Vm0H(^E2J97gqvLiLkTX-E_g~YqfzS+vkP3=RD@OJMg=dct2U=z>qi%K zWkLFmRpwxXi_4UbZ?wDaqPZl)tENxi4_x;nVIKE4OlNa5#^)HX(c`!k<cF(#Ob_WU z$!B{|l}mGU&AC%2x=q~QfU;>hiSgQ}e==D(HOU4DM`rFO)jd;5=TvK_QTR3L-Z+eY zi5MQ6+;0>!IO_NU_V1WIWJkVVV1|WkG?Q25WSNZgf~-!H%CT8RR6e7nLuI<tCb<oX z<^OaXL&P5mNRDI3tbx3saq6sK4d&%1y)Ar*v||6RvM3IH@0F!GQ*eT}MXH^BW7{qp z|EGer)qvr<7ScASwhC{pMAk4fI6(y;JPMijGwwqgMP=GvfJ63WrqE}M^vRj~_y<zu z{XcLJ$B|@sFer`A@(sGBm9vb47W9Kedej*>;AfiN7qJf*+OLe&V|$UOL<PRhT4|P5 zWFg;+(-DGsM2`BKR5ifR=6}XV^{VJI{vG}Zua-RDaBR!E>sI|U@jQ#>nf?dATWS<E zb0XE%k#K_BDKn1lUHPlKiaB}jyu0@O*I)15*4*yL*%RgtCefxML6L=;@qh7ukUWSO zYaP>;DX!>$9u$70Aze5iEADgNXB@B|u20M=87!500z(CiMp-jUHi#))bU{s{HTaSB zvX3Ek8=y`$F$hvEA!69#vZ!=6ATn-2J!_UTpyA!boDfCDMLBGLSikvn*#l_DZwTET z_Fe0%f~M8@yYDTW-d%#Ok{hSLw`r~5t_nxe=}06+{{E+3`_nZt-X+x@Ax~~62T!RG zc;i^D#vi=7@O^j7t-F6;oKE3V<OGNrwWyf*8Wj`e8LL~aH%pkHs^4`aAd%1X$n=_- zc3`bEpN9HGh?(Uh;B=>`&;WajN=3YH>e(Vy1S*IMJZ>-?Hk)(}`bf<}d#}tD^j^QB z_P4?aDgE#JSNORjy8Sn%q>0F&^T_ShXl6vJfBPpAPN7pMi+S{a;eR1{1Za3IxV<n| zG+^}i$p<J`)u;L$N9xLk0B6nef~BfOmQtT*sZsGpg%3u@Mn-8mLK3<H?eB1JNRP(t zU7X-zizC}tG`O<caA8RT{|odWW%bfCzN>w->F|q<r#G)(yXn2&t>_im@QinEU)VY( zR274iXo?}(%l=(hf1lu8q?MW_tgL3z{@s6kf7kxzf)9Mxc>P*Vr#;(PTtzntlxLY3 z&Q1W>zaM<IKGPy8o>rhWS3VNh#S|Q=xVB_}$)OUiWQIg?ZTWsAV$67veT`+WVfV3Y z1)E{<&mJrKTM=87(Hc66CVA1|AL&8QsdOERN#d48X?8s_eyE#1wD!yppjG=BioTvc z^C_%}Ts9?2!g2KTI5!R+-9qZ+ihIc988Pb)@PTIAnUB@!Xj$1En24bBhXR__!e_$S zTfa+Ue}09ygtakuu+DGtMU)6<Ez?U;9&Fadje!=Du8^qImu|jJc%P(&KV0KUCjvH! zl%N`hFa_ghIh$kzr>#B{C_Y$HQz0MV`@Akwy=9mu{B-aBN>V9pDkY__gosAm=^<cv zV?!e_9ZnnrnsxG>_vtBvUbxs=G$g}Ts))sEj;w|NXXX$XH$1$22$!=3XQnho!M(x2 zo<P{7Nd_evkFrwwi|qnNjKmr{l?K}adm%4lC%dKhG=9~HqKO1K?c`WjBMAjCVx%YZ z=ByfpL3l;u!w3yygNFCG*A`$mk*h8Ifqw`(FTpf1mu0%j28st<2a|o6!uLS4QCr*Z zJCcbF#-+Ut^BdTPNv=VkdyV^A_fhvt?$_N?w_91Ytaz|cX7*X<Th~~xwH`&X-s>oM zUXN;@v7uKWZn7EeX8>JLd3xs5h=^Q#eqr<w2_M*0>P+Bd((P<OF92HXmNQQBZU;*B zE;<4aDcH7Kgp~_#eZ}Qd7&z&X#p(2v-c2w6<BAPGUE1n)^Ky-q{7hmL3X(;IXkk*A z;(j~{Dh<L|_-y%mc3*t$jUl#7Yb=Zweg4u**Y2qCdN2hfsWAmvsW7W3ktixkBq<k6 z82_5TTk;Iz8mWv&-^V=As%s@Ri2++*^kDFCOPys_qqK6Uj8XZ(0reEqJc-2ul0e{) z;?km_lNCtRmdP#%_@&`o^Z-5<Cpr#U+nDY>wbTII1Vpm%ck@MooqjMunCB}KQRL$X zb_b&>c%d53u<Z6vR3@-2T8<u{zH#;<_Op#bU_(UCCd!{J59|)qHVXcPoQ;y-ensLF zCQM6dP!q2-#R`0>ChLzLwy$fN2wrHy(VveAcp7j+L&i_!sRt|r`h&*45HnX=d@wi= zI-HEhhS>R~QioTmMCJn4`svou`fQ>L&9VA`#;IvaZ#EM;yMZS7N;zyXPXl_0;Zt(> zkvHqu8RN{V3Eh2Nmt4}-r(}aNR^r5R@#&PX(g5czzAqBFuh_%?^f&S9Ws4fBs~d!2 znMv5as1=5>Ut&NPV2QttXj<<ittL5I)lf+$9e1;X$jH!O4sChHk$ylsVD1ZJJ<)^y z@ZnS$R+Esr=vrb;pHlIBVwA3fF5}`wApbJ&=$^Og#EsO`#fX*)c8VRmU=?&y&E2=2 zbl5yna;eP685ZyCzC$Z@@vr_iUcG#wxP<!=ct9RS{FjMWuiL^)T4gi+izhVvqk#mj zLW&st1J1-@9UbHUlGvd4Yf+JYU8d&-1L;6=DcWS}XJaY_BG^)C<~7B8ig7ftsOx7Y zu9>)hBAbXEG-mpW2D}4-!|iCPZZt~uGrX<)TG`fCXXE-*jg;ytwG&Kx3`~2BBJrqr ziqkr4%D<>+pd9?}nPUKq^LRW60|$>9Ln63tF-HlGFVZl?<eVIGllPCRs3i}wSdt<y z<F|xQJj2wUKw_b-p{T3=iPs-lty*qUd3ZZAv5;%yWzD{>TZ`w;s4yC38i{7h)#TZ+ zKUYQO&5NekgKMTGlO-yn@U_xod{J7k9!(4Q=wfo~;w|LU&4}AjbHew}8TWc+twJ(V z)iR~Jj-KI(V23$~VuYBYjJfy$*#HAU?i#QR*bj#TjLIOM-0Z5wYzwTAML)=_-GKE$ zB!vO3W|0uOCab8L*g33QMkKB*s}@M4ZlzRH{M|4-c&}uM)Ql>{->w!~S4TPIURb&4 zYVwoSE6J0WS|l7obGWbg_*v;^+*g<fye`wxo#<<tR?t^E=K+T6v+A!gkwYdj&$Qaa znyx7&hf2x3($%GGY3sqJ!?U{w`}(F&7@9P_(mu;NEi{dlOe50<r%MY}HFPcYNQ4|h z@)>IL>h+@4_YRaT{W^AR?AWJpS#pY&nyTlERL)B$x?}(Gg^R`3h1_q=N-Ge@W|e-X zkmN;{RGO+%6TUEbLm;p#00~xCTZzIU=(A{$GcLG6J=E#6MkTV7J%4K1`GXAu%Q&X? z<JyeSg!&{Z!hoFD%u;Tu8Li1bvA?LMO3){i(kOZR>#g*ps4cA1eD(T!@2zVCRYT)v z`2(OT%)Ly3rZ4$GT9+neCFZ`ugTBM5&`?R4aaM&??iP3b%*j*q=))?@$?FSa@&8#^ z=T}YHAS<CQ{DJ&(dA_DL3O=Umi*be}H@@aID^>FMIycR_q=;(goK&tB+zBa_%5OhT zSD=C4y{@M93M#i~HCY1+QPl9Ml9_;J8uJKR1g>^o<K%RB(Bs_a<W1A0M;!W@sAQN) zt2%N~!=be~m4kRR%w5W<=WHd)vV4Q^)(3wSesjxrKKy_b3*D)3IF$+)C&`x|2yc+W z_ddSs9^rQ%gsalU_`;o}gc1I0+({T(p)pfb+|N9cnxERAV$1#VKI=i_;be4{f3Q$$ zAM(gF+R9ndL7v_WbvK$m5&3TH*f}*Qiq3#2NQ2apgAsIr@XVg5Z`H|seckTgOx>d3 zqr&Tpqkh(~VjtNu)8{d$O&fi`*|SrS(wk3*!YT5HH*Pu5;zq_+Le3R)(qH{fBQ>GN zJTYr~oVV>iSzK3F9ICIS)Qt-7^QYhyK~*vBnUczoalq227+?<a57egmXL*)+SkIA~ z*kG9~F)K6}kXFsK4WiGnMoR@HmiEa7-XYcU@T#dmG{|yRYR-=W>s;g_QtKuQ0V0_- z8<j-H%PC2eNTkvDZRlrY#Sp5a^>7kbtRKC;Rxg$5;HAD{8ap#E<C4kTak=4Iq4jv@ z)*YE*j#mX^KZ&W^;VFKy=Z+XA7R1yB48C^HpFfw%l@eI4b=+Uzr$FyX2bhWy{eY&= zd(d?_<{t`|463@yq?i&!z1<x5kB$KCqAR)J;9o2PzP(+P^SL^;bkNeK=+Nd_KFS#! zy+hU$8Z*Y~e1Fi%JzaE12#YI~RM&k{m*x21e^(_(pB>D8j9kAGck3Fzg8i89LjA;7 zna6jB$!-_fU?+R5q{~VM)MO)126$43ZVXCtm-7)Po3@byQt~e?>DA8HuF)RS9@W02 zm9}dMgJ87T`J(SNAG^m#Rs-W_2YjT{M|4O?X2Lhv$SfO4qMmI;n$bEs>X7<?*y=Kb zRBP}xavTBJ!|09dqmk7U3}FWtq7!qPImY*rnLKO;bgei0kQk@UD9jyNW=kyUI05it zYmEMwM?<S(@O3LPC+uT*V(6WrD8<)*b?O+t<DWkJfFd3uPAWc$Z+XH~&H61HL$oib zR7F+%$M<e3(5HfRy>_kbjrG>2cC74Mf<YAe*1uc0BH3`Pba-xajjuD_I;g+1PNkH* z-dw(Y>d-Bh4eAUNp4EZYp7FnPwUPp$=slSjVDS_;z(k7&pm+uxCgng(a}9a{yr_8% zn)mPoUBmP;&rrx(CT(t=MML&uuQVYu6;+O7aB;psx%x4jfckevaR#z0p!e>}tC6hq zq-CqLVN@3P$~iWo`pnx@qG6a#1mkK=hQceqFFdN8E0y&T-r?x#Eilb&E-uizv7L4; z??srvJ+<OeBe@2pl0`Oi(|f5mQzfj&HehpJ;y`cTtv6cdBTCDv6;|jDx76gh+6R2X z!TV=<O!RcLjDN{LiOJJRNLRP1tPckSE>AktUl8ec9!|wQK!r?$bR0w$4-z4UH;|G+ zjUswRzHQNpt~(WJ=y;O14d~+ZIP%oRL!g9zQm@u2{m8v4yd`MDD8G?GVLa(9))cun zcwo(kQ9fffq{#Xx_q|@>#ol(|!*(yG9;&ap^0Upa5XE+=j!@;RapCJK^4o+CbL?n$ z4u)TXiPkA*-Lq?|NRd29i#996JkeG4RI#x9`ixH(Mg~HC%+qQqQ@Ey(^%eFO&c}oO zg|8P%3(K9h%BZc7Mo<)mg=)7ABc-rrv}!<QcdXiwNTB3Bjy5GjYZHlcWhJAObE|2L zHOs0w`$)w2vE>&M0Cpa2T5#?;3Vbe6`>)(pN;Tw;K<UmaiVFB>=$;UK8mGK*qS{4Y z*cGs;<$CtDliq1R{GD9>#t&vrI84(tkeU`bT=FMU2@e*DPfA;5mI~5tP+=+aL}ux} z<-^NgTh6UnPISw?%X^m3Th7mNE^|Kb{H2rE`)2nsznDf#Q>Oj0exOFLubDP^py!u~ zl7X^5&o2^od%|d(pIDPPl;9GJ7aW=^?P@;MDAi9(6tFX6GJA2+p@7tAr!(C|8l4Ln ziSf|b(79eNc}j_~P`iHA@d=X0;xtr!){Za|IEbG5EcxhJ&k^waBaxIBvl5g`)<33E zPLZNsk~T+Kv;xT;sc*e(6^|H9v2M3>$%;aB=bvqLEq5lb-cpK_Vw+_Re5ZCofm&7w zj~HDQToR5L(Hh^R=T#b4@#Yu=qEuNtr`CnJJPu5rU|HUU>-^UTf*9ia+L5+~qt8W< z{PgwLa{2pn9-MIa@tW-ZM7sPY^t~;zS9cfPUQ~qlC4`j};c>ceWkrd}--Y^S?4G}d z@^BG&xQcrZ+W60z;cMbA#$StbGt0@$60*!nW?RWK0Lsj5=4Z@YPaO6#saP68`;v+X z8#(GV=xj|k)^_ya(&tLqsig~H9KZaCnGBg%nOXD83dUREo$o#5{i9dntty>}S0m1s zyyO`#x!+6BlCa8)BSgF}KW88Y?T-}X2?gm<kQ%f<dD-Tyz`%{7A2@&EWSvs(dF?Ne zUxQsAs>dgdr=l_1`*ahHHACW0`p7;qM2|{6p1|kWP(4yShw8;to7|RXL#q_xrkU#q zhCwva?WBeMG!~YHv+&RjbwKmIEPPd&@Ql}}E{e)6JtnX4V%c-gm62wzsmCIZ7O9P1 zGP&$|A|L7x2Hob0s?F};=LL_MbdS6L5iHnT6|)os|KWbpV4mLX1+5LjgZwU>ln!QN zMzN-Ae;2!<np8hO{#K?sF_7*H>F=|K;FpA+u5K8ph0O5!kO?~<xv=}ICDjvJ4mC-u zz13b<W%;3~)TKQnKcvzji)-{GJqRe=Lk)lKB#dNF0CJJ=9Cbp*Mze_-BGYF(zT}ub zhkJ-ZLrfeGvD7O3zsM1YkzHEjyO%$0GP^EwMGh64F(im9_GvX$+N}wbF7z8UCy7G( zQv^ZY*eQ1b>O`L$p9)gtc&bHs^2uM?Bsyz-uY5+U)hdaZP=M_xZ83EkiGSagGyXW` zRMYq$cnxo6x|pFCm{y3)vOB>&zE-b0(^N0LkEx#=zAtKbyIpW9Cp86Tl?^4Norm15 zv-F@86{}lE5j~BM(je*?vAiJ>qqKQv>nZ!F{uIiKYpRE+a1h06RxX4?^k>#g7LPqV z>T_N;C0AapQelx-r;y4tbb@Dijm!{0+aC*ZOt1gxzN-u_bf09c)&sjxQCzU5z+71v zu@%R33pe%cy&vt9WLp>4>~s#cV9*~qC^wYcI;p3>2w^fz$<taV))u;#VMtonK^}8O zAGvk|rpd5chy}jLKG$v=wD~qJi1JA9MM)%TgM`(bTXGvS2|e_R!kzUV>DJ1oYICyw zYO`xKj@abV*tS4*wQifk!3Mat=4}9;0q2Y5^|`()P`keyI(A|Vlz9iG>UtW7%@zlV zo_Ib|l$VFO9H;Yi$e9%)bWC&CMEYD{cyR8we=vLZ9D~U#YmVvlo<no@3_SC;M&@>3 z?oQUPT5!V+3s=@BJ)7JXnMT-K5UM>`MP$ivaZH7V5=L_$Z8~V)l_b{cd+S04`c|X4 z-|SLWxc`#e(KE55XJ_g|cNzm^Cg4&^kvC!G`Xo1@ACNtx46N2@LPai4&ePfov1=Bf zLWz~;!iZaLMJrSa3c`uY)o0r9q6M=&STE6ABQe8eg=k(%6hy-5m1{MYeyazaP*5o_ z8=?b&6{AP7lRf+rv6-jT7Zo6)&K87*Hfw}>VTJH8y`N>+p&IN^57V6qg@aS%t*Wi% zzF@UA8oauFJ~|!sg~RN&jt*T@qGDSU=kjdR<-)iyaVcn@t+9L;y<Y0yp}T`EI&ooT z_Bq%uccAljK#q~o4k&xj&pS+XwP0JiRWPygJIU3=GBS)8nzL)pbKfa-XryK&l_cv| zqJDY7s`_NX748DWQA@w`%$z-Q4`Hei*<+N*ICXh(I4OKpb+9(1mYEG*CTxVuly-lZ z+S$`Fv1do}FYXGZ3tOhI*8xBX)!kbye4N}RZYtfc@h^y(Kgs<W8Y-C4!h6tKL+;IJ z__5jN#GZ}4L;IB=sS@(dk#hmRZ4QaMhmaHGy0|Jxt&>Bom7V^Y%)H^!@?lIquB&Zs z(`$+D(W%?Yn_rhGRdsh7*tz!Jx?oCQu<;&CZ%=;<rmpEpaK}^D^>5h5QF4X)m$#&U zVAJ3vhS->!nV&IVFwTsjskv#<zUF<4c#dT@PYMQmqsb&gqpJvJ(ElTgLd!M)3)`G& z+?pZiEniZSL5mHKC)4t{v8~{VOruz(oXK=_GM%I_S(_=DP^;H=cxoq1a3VQr*zA;_ zFHb^+l9-b>_6l`*&>lFKR+P7X#@<KfGHfFIN%|8EbCTZ7d2}UPihLo>P>Xy42gs0Y zYP<mTM<poj5<>k`(DTBw<c~v<3+j@8-nDx9jW;b{J-KU7<)f%b-rkW)bWJGsm$bOg z*Cx9O3f(o8v^ZHR(av14XK>cc!5dc1ctH5U^<$&gD<tnEnlka?iEU?J&lM_z@(H1z z*5-opArREYyh|F!&*FKpa#Z>eo-Y=6<R%hh{?2$Z)~1=)%-lC~c;-_xU!3{cOc`MY zdp#a(3nc{pAFX71TY3uruTuPfZ<FPuh%sl>*L3XbV9}kTMV~r<HLcSZr0?Nss*dQs z|AYBj+;?|V(?0jUCc5u4!wSU(``$sbO{HHV+jI_d70`}QNB=A?pK`ioWB)R9KJ9dK z@0!N>1;{-u?xgvqXJRz7N9=(tW}E^Sr)6LIZ0jo=PFnf(|1<40jDSZlulDmkV*Yew zm6zmvOypY$XSvsD=IT`fl8dk2kjq>xoz$cY<}+6}iJ7a`9$!lfiZ*=_1us>UhVBXD zG19xn8q31>gabSL#R^S2bVsP*@`6^aQ8M{*q55(-h{C6XHzg~tnE7f!b92!Z<kicq z$n!I=73wb6G#Y<$>rU3O(~aKEykf|L%xsz7GR<O}Yxl`Hi+!QPKIk$_BsR-bGmLDv zge|bmx7&so?6R1PAo&;etu4nLXi&%KGb+|y+ru)Mq}z=hi=Mmk%X3$@G9&pbt8r!1 zx37Hj+?8)JZ|ARUr|+35k6iSgKh0ffWp2LoZN`?-bMAp2)?L#Bmbs$U?V~Icjh?^T zr_R0e+stSAccypSo)j-Wcem2Pb61`Q&#S?`8jf{W(>LyH%e`?DYx4`2(|A6vrbYc$ z=G|#dM)@3JN&_wie;rqdac7ZE9a%atFX#TUw+er`zQXIxttopYr4zl<%CxS?($ky7 zb#>pqj#4T6j&Cuy<=-()-x00kbMII}W8RVz=ic#V<}V_Zyfb@PZ;CEvb(45;j!JM{ z*w4g!eN()Ho6d@NKs=>Aa8fYgBm2JN$8g<d3BA+ob*-qWz|Ip-39hR=f8FzFgCLR6 zJI!AA7V<;I>%{kqXWx(E#+TwcD{8EYAjOw5Et%l-OY9SxQY5vU#xxG{eFX<;Ok-KY zP;^S6f5;=vg*Ha(^Jf`{c=Xe)=xKgZf9j-YY<?Tepjzu&;kl}F$MRdM9BS?V?clQW z|M#HYbM?-}4#xt!Ps&SV0l*=69M%}d{yXT|;6ck0k4#yDNRM@<HKEdSFa00Ge$$*R zf`KOcLVLkw1w{(p;f8f^sUN^bfqlN+yV;9&Wqw$`1*^buVw^xid7UbJ8_v+5v;09S z>aaf(Q$}NsKSV@c+;7NiTzM0N9TU&6(g#i|awwG-T}gMGUJ2e@n7hu6>k7Yp9o_Nl zJHEvn%D<zRzGKn1-tqNw?|3uwSCKcBnI2Z@p}aY(SiCsLo7sDP>)boP%^YAN*?Xn$ z96f&zA`T|5YF2htgpRuq`Hrr?ITelOR+YVyt}1(FEAxx|l}LSNGT*+Et}A=xTg<2V zE5-M0{?>c`ICmu^)3P_|x>(O(5Ai_O5N2JQcrjfU?A88pIe!c4syfg^)!fSMP+gxW z*?}n-o%Nj3zq2)g?7Ue0*htox{^Z!$C!$rBgR|pB=d9732Fix>!XnsuUKzm$M`mXV zd`*oE%H1*=w~X_*$fZ7s@bN{_KGt#Bw4@(_q<H_Lpq#gd4p5}qEekI0j~8%)Z@VAu zy<+M)8wKyiG8R~gjV;?q{<N{Q6v>7$yyoBT3!+EuMD)lrNTt5@UvMzhP(jAt#C7E= z_PiOr`T%pU@qpBBIl$ekJD@<g`dp83dVt{|;>6NB&S%BYTj#nyeDMB{K78Pzzl<~8 zjdi`#s_T1s$Ace!^uPljfAnC()c(4fX*5Bvcl;an8~#lu!z_9M;m9vD(PUX9-Qe=p zc_WbugN0{W)YB@OmA5vOHE3^jB-1WO13m&ZX-NP+ZElhPZ4|FZ1R1f$t$H-~LTaDb zk%V?NIDsCaHE;~j7EVl~gT)8SpB8ZC%;Id6HM<ky=2VD=bGoXWWMk{%W*~}80q}49 zJ~^w_xjgErQ%!B0#pAqe4kkq*5kjdfQ7OU-r4$29SL|4J=^-%sBAcwJG(Cm;Z~4Y6 z>`EoePM&PryR{S}<D{+IO)8$1DBUyb>QleD^8PK?>YsGz<ol(1JLR^<@xSx5f9zD| zij1zKt<9RMWVrsuDfLq$Qz*(BnX=XzmWRXEh$iU9BvqoBW}R{XQ%96#`>IG)?ImRr zBhzyUMl>_%mpU?nCJ(RB#BzHKzln}546IWp&`eK%2A`-er^(dW?sDR;(x@y?<7C-9 zFzV2U^R1Jq>kHpMfKg`W93~pE4aP;f+C=9clMQGGV{{D>p(H+7R@N+h(=41^9dv}7 zrA0&^!w@AYi^<cL6*aeB_w@f<ZQ$%h<nET`^@fggKrNB0c@^O#{PpTtH{JXZVXY6u z{k)oYT!tp4h2|jdZ$T#wiGE_aHWsp~Bpp*8TQ;~-r<bVLZ0^`xQ#t{eqKcB~)vbi% zQ%j^W4dv~!@dmz5a)9Y%rlUG;P@*R79i*v-@%N(}rBc^Ly4Lo9{4=j@BW=?vqtVK+ z%gmtuWo>wdyQ%k@miJoNmhGwjeyLL0#qd#WcXu1EoD?OMDStGoO>wT?HQv{~tam%= z;l_r5wZKbhpm^O-4b3&9;|vVcD*-sSbrg7Awuj+K;M{0Dg?tATT8R(g)}5f4sWdMY zgamc7NoW*~$?~TNy;9Kbe1pUDk7&!9Y#L8Kx`7NPiP*Cu8|mQdifrXY@>vh<{_U1E zcgBspJz6hQOBGk%RCC=E6Rz9f^@Yv8hjyJJRkKuz!LURr`&oT$J7HFC6Z$7MloWS0 z6&JBT>}iga79#&+;(f;!_PK%`4xLOMXj`oX>g)GL!kxSBn`Yr;?qDP{gbQ|Jey)1k zYTX*Q&(M^a^80|>?)SRH>Wanam)ynw996>lXVC;&>;O&ql-dXvRQ^i3gna`2w~wqP zEI!t<z4+}GvO4>lun&8j8b8GU6!NPDdUZ~wytlHbz13}Fid03aYG&G`snt^*9n0#% zYtT<D*u5^1eh=Nj(!sQ>xsKBz`Tk_n2!#_dp5){i{plf^6NnoT`~1`HV5i?bNvjX& zAwdGA1mX`HBF4z73Jnn5Vq=hVw9i6hSzr|rSzs$Z+T$4*1NMiel!^VYM4u8ZWq-;F z!NaeX>RGeZTR*%QYqWW0N-Nu++;jI_yWB9PZ)2OmY?UbPjSK70Aw_-Jfo<DjcEQD0 zPFi$Dmqw$OMCJ+C%^Q2}<<=lS!GYein$r8(wBB8yZgT~rv%a|N)L_S>$inV0gi1_u zzK+~M)TF}Yasm<)!mv-23nq0gBlYmv`^Pu)Um(jLvnNnZcjXHZNuOmJXCz4EY8^&& zp;@avH4=^u<FsTdGQAm=Z-~k3re?ERnrdcLhQqzcPps4<M9($I)rWXJWYMwFH%7#& z+o41QcwdasBdT=_0-IKeB7&LE+M~>0jgo5Gx&aMnvOr`GtATweik>`LBjbyb*=8(M z_L#ut)K9mi`7b^Z-t_B@{u-sypp*I9m!R~jOsh_mH}C$<ts8bXklwNHRu)@ynvy_a zTa{#qTK+J3Pk435k!a7-U@)n6%7Y8Z-bGcXtEMiR)3jsqti6|Sy5Z~oiHUS+z!^)8 z{k1W|SJlnFr+qT!cMLLnF`eQj+SMG9?@n;vcQV}#HGX%rtIZtax(eN&b&<*40e2TZ z)ZLFs)sHdKsUe5S;jhN@wOD0kOIuq@Q&U6B!ZI@15$G*zag?>RlsUL|{bP#u$2h8c z-#G(mZ381hlpxwmOSHurZ9RGm0MI=N>7qXgeig5yY)o|{SQ&Chf7(zpLamYu4%E56 zr&MWYp)bf9TRK;_Y{ApC5m}bYbH)rsfU`Ytvu)aJM#&uE2H{`ASHf;`B_Kf+S$D^- z8{WKYy^@uOhl}r9b=NxG=H<ftg$0~iv+#d1uH`O^WKhE!6bPo)r1n4k<R;_Ta_#0V z(4u&o8^}f?BTBMK*e(3yt^K#okjZ6yNyDxiCn*(Ywv&q55_Mc97pAFr?T4&c0hnE; z;IEmhB{x5G=iZUSx6|xd?t<Mw-vMSyrZAYqs5*NRA8KQk_I19hP$j0QRa$h9DJ&Pz zS8M}#@?tt-MgnbeX4ij9BymZa?1BOq<hmeHkMb$#LrHZ3Me{ZiWbnU}N*FzH0{OqL z6DLT)>(vsKMw`}#YtkjA29?I+zH~<E1E2osXkzNhe<RK}Cy8Hp@8k*LPsGbwWiM)6 zvifjIwQbExpTlZ+|Nf(I=}eG^T8@#VB>Rv-dL`4D@vrNe)09xkHL+66vb|)^hK`|? z24#%H96}8@wKTC3p8m08r;i=07bh{Dh7^AH#5<?sBaU}atoKgbK5|lj8mfuV<U7%F z&9Mgxkg(`~&*l=zV9m}`qUs84mUY^)U^+di|Ng(EL21_bqDNf(PwAYemy-RrPR6S) zRp{eLVVB4ZfWZwDjZ&pj4|`U5yHwWMsIde~bh;+JOrbpch00Nq(y~gOsn=whWYR0y zYYbAkf@P(g236IF%4m5x=h7IE6sGy_Rckq-!6O6DYbuY$(Ry32{F`FqQp6BBnLPbw zDt?Syiy2uYoPki#;41tuwCLqPynSI+X%dD3k?I<B`bG%G2Gpi}F8LSZVJb6D8{^X{ z)ZQ1ER~hym<}rr70aw`WG)QSp3OY{Gm@Lp-l#Qb>h0>R*eO->mIdKOw42pw(u%GJ& zMow>6I;ASx(#36iWqP^V(-NFuk|dPcnNwzR#HEg_^%=cESymUDEs=6^UyZFo2Yx6) zc9&oBJ~Hf^ff8!Gcj<JkO?SmwY*iRO6svy&gU3$MbWB79=oV3KrZV`vmvZ4I{@)-o z-rww6S%4ULP{v7Qg}}M+II1&^Jzs>!@RI#<Rhf6I*FM))rPA_41sp8`b1rwn`7T!S zF3%R9=Zc_1Ci6I!IT0%^l5vIZjb6`sY9%jWCUAcK33MKwnkh2rc)5z>)WoReSdBu$ za%N~ml@^&xGUIWc*37bI2Cd?$(e*}rEdD!ujo>$03bgg4{gwC|5UgA2v@tx!+WlPE z6ioT6{3*Z5#w9F%nV<6u5B09^_%k65!q3QH4;~8R4QOGxOZcgq6m9ro6Un%R)0@7? z+L~viuS)hZE0_(;otfU!QVa;4>|KQ+(W}<FysK8N+OTkPpVwm8Fk#@k(<exO$~1p> z!lsG6U7fW<z4M=)*6p%&uD>F7MK?ZltDdc{EgbfT<;#bce7oykVl*~_{erBA8UM=I zD|(Dc7=?j}yh3#U189oRV+dp&Gb9`_nf9gnUFCMMRerX!2W7LocBLg*)Rw`XXP?fC zv-7Frcs1KAUy|(uC|WXEHi62G=gv3%-#Jl`wKs8$sZOEU*wh+INnb_#K!si6QyC7= zM)$y8AIp($*FcX+g2{hzxy!Yt0NrU2s9)Ale^)_N2@|EKjqIs-xuROlsmzw(O@+60 zvTLm~EKY@rRr@^aJ#*@`Q<13dID3aqt-q~gb`?*%3r<((x(m8v8I4@dvJxG4JrEg} zeSsb3fOhoy>&amCWnnWfPo$P^?lN1WDWx&rZqN~rDOn9WrM5)aURhw+R8CP!5et_* z4D5hn;a27wU<}IV0I;C-F(3<QpF(CYe~Md<E-XHvWteptW{wy5y%uTVac!ue@VMF? zJZ?AOcR#BRG5X)d9j7oS@l+h4Sv`%;{%-3SWG$ZAI%a=`hAkj$W0>}b4{U`2eJQQT zAV?!9VdD%znXM=sG$i;_Yrn~KEm~M&aYx72t{rRXSg^1&^UWHv^V9q87v6g4ub-V= zyY`N|noUkvmS@+JHFw;xb}jlWeg4%qU!E0^)58KI{wc@vJZu;pQ<lLTAtgDEe(oB* zQg&Ry0(U;H(c^Z<eiuJ^QoPUjJ2*ur#p7bZVM+N77}99MPmU4Z+aSD40vm{*AIq>W zu{Q|9<wP!gIrg*7_)C+STi6c13=<z!=o@a8q0f$7A!S*GT7pP|RK_TeV?qx4o8xRc z-iXKF*m@EN6@wmdRP`hASe&+{38ERUMMDhudu)ePP?EF4P2>uJCud1HnbSdr_Wtv8 z;jImHW%Kd(26KNeow343KvQKN5ll5;KZbVu68|2ShQD_@9zQMqy<gEkq(4djYGs9j zq{>JtK{)#72Ju%e7jBl4FNh!^->|!dhxdN|&%MF}V=v?H(cJ2BDL@KlBdY6DvF482 zj_T^r%(jjfLi#ILOIFKdws~!<U$6}fgq+>Bw!-dEXwy|ImJTnTEU8`HVGGHs2WVcD zexSMoAAzYo!;{4}U(|$-WfLA?+EwdEPLJr1;p-HdBETYyp?OrcZhVZ2a6lrbPw3A- z%u94JM4#8g)NwDmSO@3lBj$tK(AzMn6X)tjs-y|j=$%KYaMmFQV0(*(`329TxGbmb zrD?bST3@8w)=?LXDD)m8?ACcueva~To26|3`iUOBA`)qyVJhoAp~U0rrW>`i7QNy{ z3`{BXSy78F*P#;%@|PWIGMA6YbzGm0op>`a0Iy}b#WLNhqY4@g4%|b(2g0SZ(kCrm zUfO!AL~ofve?b7{0Ua$=_wV-SE7gNH22iPPcdc;d-iPkqDq$b{Aa{~6FtLo)WH^p; zH}HpEVbnmA=rGVjZe;Yos@I<ejt$o^PJTBQe>Xmcqv{W)sJg^h`h<asIzxhe@Vd5j zb6wY6cf-7i*B7{pg=Lb)v5LKD{Z9FE3%-3M#fWyXe}2J#AsTxeIbs%qlV&<DHye*L zYP0FMM52ZAI)-$5{i!(Irgz8apUZ0LAz}awht{<a3`q7P2@~d|vL7{83TrDH8!O2r z!V7o&M0k`N7&Ft~*=>~#?2BK|Wmk+Hplh9uJJ^FeP%~W_KX+WIl*t&a{5a36juQ<p zKQ2`&01Qestm-&}ViuaxAE%*q^zlc6URGM2!9bR+XT<Y~vjWQ@LQ*&`ev2Qi7X0j< zu@mHKVLMwc4B~F?C6BCRkFwWq-8}Z}hOv9-J%n)&XK@cICYmuZ<Tx)mj!BksA~~*9 zb21qOK|Ma+9jm8PQBRI-dDlKh?eHMTEPmiXp1pn71H1OKZ%FR{dT#b>^SO8Cw&I;5 z7re8C$p7;@zx%(wFUOu0vS0Ll$Nwm-CZ}=78q{<cG#d7}LMBsand54$;<!x9=;46T zp-K=SAdx7m46x{evQ)wZ=}k`m*y%~W@e{J<HOY~$s!F|uWWDs4YoR&9%uRfU<T3o5 z2oJI;<MSFicJbxKGKQZvWp}-OYADdP-CJNyY-sJ>Zcv%ckO(7Z-aXSaf&w=X=NPI{ zkI}{mV&yQkBD2u*|G93Mqt+(9KiZ)>Zv}|pUbdqx)!o!k2Nd1GhOI>pz&tCID7gpI zPp!Um{rvaJA0+5N=(y`UUV~SqhHYIjLHJ}sm+<B!KYo>Sh0TO-Mq}XaQep1YU?LHm zD(RQ#-(1`(eBKh^q-}lIUiH1>J66{;dfZCM+4=Ueq$xINQ|K^cJz=UCvM6+Hu(vE2 zjDkXL<|gjfz<0D_9c)#`ms%TKhJ+D|F1B_lcxiQ<#Mi5B&J88=kzcl+w*avo0)bHG zi4vnz$1om9G;Om+PZq+2>y{?~Y@a*<L?9DuE~Lf_p3hPs&Hei3y)V7Ici+CfFTX?_ zQE|QHNH5O_;~6ZMV6<i-+=4cuYl{j;;)ST>D=dt2@BMV=_U$`fd~xS?=)mB`ON`B> zOOzMJD~p0aKClXOGU7f2e|edSnSdX2YaGWpHw%dFxE`*KkCh&G(@qt~%^u}(q5!m# zI1_(I1WyuMaVG5|=Z&2{{qE`0;6MGZklsUevxI|whMuM#sVFTlZ3EIHN-TcvLt)GF zV`s?o!e*kMCrXOW%I3z(c|=FZ$J`6#Y=>aoex|XK`!#*>Y^<{J4E3}TVV3!Mf*QUl zh`JojEGg4h7qnLfyGJBGv_4_m+e<RL%rsYa&b0nnCCf_Kk|VRP?bzROsDtaEmAsk# znL`;ab3rXHE#qzd8*0U98E@;P>cM2atan!BV7YY0%-~=MwT@z4Z$=>&_7)7%(%v&; zVr_5J`zVk&gMzYLk?(~yzUcA)yP*?QG19Cd3iIWH0vDD0QfLm`K+6cjqGfz>X|y$8 zY@da>&xJj*AfM#iK}pN}=jwtFsP#&%9~H5*FnIRjHA(OM<@#?`<x7o)(gn*k>2S~0 z&mOq@!kXc+hFqQge=HuhIg8Z=p5D24X3O?_D-x2lIdc1*o6Z#zFF0Sr?;rmo-^3T7 zcSo4nmg(s*lRFKh#y}=YNEJJgWz%-jsiaA$tX*N?O}vwFPvakn=px=oPh?+YI3iK& z0@FItFYrh)<5U<}J1_Iiw90hqqFFM!2^1m$z-Oz$127>vIMNPq=-NwvQbd8`dhm4d zCFUT5)WA=|V$D2`BD_pmBoA+af}=D_gX5Rxn^vw6PW=A<oA{+leM|pJlKlO1+pdzT zx`lz-$`wtqk_PUGX64?;e=oecNIiG4k(<5uN53c4E4C~VYAahWkI^bTmNAdN$!$dy z9-XIzd6Ln^Ht#}p7)2D)7o~qgFW7iR*?N=4U&P(100x3d8De$+J40iqPMpaO%aG=A z9IJ^Is+<=faEe53plAhsJ{MeK|9&&(VbHI=><@08^t0{z2FkWAQS+eLu11BdC{VxF zJ6~4H-?nhio`sl+@y+LGR#Xweh>V{+Gq<9)yxL|%B|-F>`Xz}4MOZ;U<|cL^XHJE# z$$^YPcbS*zmqwjenXj^`!kBY|ki)N#5eqFK&bPTRI49olML0_qQfMU9hcL2jbdEWl zXU?k>=LVeXjirs|;GX}Fwl@Kcs=V7r&wI|9GyA^pGs&!(OeUG^>rD2A5JDgjmauOs zh=3q22rh`$1+>^|YYn2H)wZbBR;zVs0c(}ETIknB^s`c1ZK<|j>$R3l{?B{POcK<# z_kQ<Y5;8MqPBQ1b%WwZZ4@l4Xd%<MBVZ)6#j%%V{iB|luqFAXc#<RO-&At2^&7R!P zu)8lK{ah{kCqzOKRUof0a!!!F0#k_<U@B2H2yKXlPEl<`1aY-jjX%r2K>A7OD*U!% zA}PN`FrnKW-hj?hUT*Q#G0ibw6I)mA^O<6DgNaEULpBA~&ko87FT!^qZcII29H6Ex zM7a1xi5=+|4O<kx3gILvW=y?SY*>>tZK!R$CFF3nUbVjdrt5ExE0spajI<tw`h9=A z{XqGWVsvHqRF$vv7&VcdH{4tkw7BCJzI@>gKS}$F1G2bY!SjX-7j-|9JD2;@vA(`b zHQ}ac<hMWBHE1p|`3-ulv$m#Yjnmq_Z~ry@n@G|7SKjpVb&IKt@5&wGo<Wwc2encD zaH2x*8OqdFRP^>CLCExZD(C4lnQ*5<J<=%)Gbx(Go0h_J9!2FYrEN>0*B=hRRL}@F zUdY5@FVT^p+bc><{Halq#sk?3j8Y+QG?mcfp5YMFGRYNWL#kIeOeV8&C4*c;>j5qB zj<Xjl^%3y%EReEzJGEcD?y<ggU*NaP)HAMg#N_FD@|p5N0<P@YvL9S_{Svw7{s(jl zrN+0%eQz|ZF?6MLWf6;B=pI1s&gP@L^kLG@E#v+Pd)N<qwAiP8#jm#suh``Quia#_ z+kGyV)u+?SSynCw@`?<#k%l*36=UFtf4_=Q$K-RYku;Pd{!4yOGz=FNUW;8;4ci<e zGVL|DY$#om+jHGeWi`3{y6Mlk&^*h&dtaMp-Fxr&1Cvj2rKqFgfUyp|BQ+Dr>Xi)7 zsnkTHVAVv$5hisC)b?rW%b#-o0{$ySf`nB}Dgk&Tk0P@vACHjuO{zO?C13d6nJZ)u zHjHP+hgcnd|363RUT1dmIgCRL6|&2+soIL(c(%yEC|=;Nb|$aRW(VWF$%@+KE+$*V z?^0w9yL^5NN=Erke<Nv3g0l#WEC34{J?1*?devo+ejGELrlcLeaGibQtP3&Tqj-I? zfFG3Cd()SQ<j+Z)1aBjJO;^z5iPHWm1O}&_#^<&-H8nPDmIneMJvutf2VMdQQql9@ zvT9WF7+(?^zx}f2rpCribqxw$rL{cvB!v+A`VVayl|bKS-z#nMczwQ>lv3Z=*j1-9 zk9BC=1s<xl`z`KKWp}f-a1ys=yH966)G~ES!y{%FJ%z5Qa*X7!Fp_b2It#Oj^18mZ z7h2{-vp}V`y<o~l=ePB>)Rni`d?t;stH_VEqRBMi2dqZRd80_jPWl!{@C3&1<T01w z4e`ljz_u_XbTB9#R6*=u)rrGKO-Km~OFDD%jDK-1|EuCBAG2sxyrQ9QK}Vxp(URE` zD&dVTPNlIOeF(!getXeN2h3VEuMY(Ra-5@(x3p|2rswb~jrGWL7<qEgt!X)A*7>$? z;bL_q7FOx=)g`sf-O8eFo%xZ5Jeic+t?3vu>*_lj8}-UhpQpFn-&P=<g4NeE@mGbw zQnq?K@?BL~k3Wol76iXFe&9Mgd?BmS5+p%A=X4X03y(H6oyLFch7)g$(r?tDPS;Pe z>4hZIo-2gImu@|Lc<ZHy$D1CMo;^6;NMF<AL?b;GUQa&KC>{Qx>KOf+`AX$>=2xUh ztZ&Wk1yl?(d$w4loUeuz&lY|@dG@ccRYT(0ZF}2r_CVA0v!!a-pXMWgsNEtrl7M)& zZ?6w$mpH^iSh4<@Vlw|uUWN?JY-W^MoUQ1sm@_nFEkVS$A@sG9r6XO|!%INzQeCa{ z4EH%xy+w%h41(Q7x2VsgQ4Q)S^4+_R<03dj>daB-b}IFcL!XLt9Y;@!v@Zqdn!^4K ziXq(M02nMO<1N%3zH6j)NG)73vOgJ|m9i`Oqtt-OhjOR;J@PVxo$v;kiPv0_`^&@} z+i+V6MczL3I>{iC-t=J;f;9mpuOfQ2w)pn&HTA|p{}zi;rZ9%@2sbDrbA=7A3tjee zukTs5eE06<%l44{MO~};)~hM|3#(I;`w94<UVYi3&{d{a$X2z+Eru}IUravV6@C;f z70FmdxD+HZmgP6!yqrQrbKp7ty>K0R#N((kZfCB|c8g#@C3`GPXUJ7IM^@f4$Nx~r zuJpe2fi#z<?nceNngcal&Ad>=Mg5HA2T3+b{fy*{h`e!rk-T-jNB#M*LA1|ZgbqSZ zbsBWgSrp@=1Rbt7oo{M}{0n~qsy2@TCC)>kV5;CbL?%5<;kq{4pWjp0mQY9`qv$#W zwHN0;IJ4*agKy<tBauJcb@#3ppT6VH+@^AGQ4<2LF?I3y-PQSi`p@+fuDOnO*psT; zZ~Nkxc1`*QiwfQLglQ#hG9M?vHvn=Qu>4flIYi_(ux8V{f=wmDqfK*<5e*QXW0}u_ zx<_^V@mGJiD0k-~w~@%?jwR&EC9BA7t6c0m*4$p1jpY%;ig^w#T4w`r8>}B-`N>Q0 zd0y1rDH+ypF!|KiImM6s1=_(SwS=w{&}2nJpF<BQFEK;gI(7A*<bIp`U}uis8F6qj zWzqGlY4^=+>gEvpcG><pmpWMSlcVxymaNWya-6-8J1+Y(I`Dh4-ee_Hvm+{(N26h< zKfJ?S?{_An@}!oLRVLxoI$w31hEIdqsCrtH1KI!P_#4hwDFbmO%_NP#`X;T^!K{l$ z)-=0Q68#0iPq!s@Ro+n$l|dC%2Hf#$?(itXH_out6dN>Jd;LIde>gMj(;561={!M` z+oi28u9@l68)`@Na}RMlE$c1|JlSYUmY9ttYkO}zczNTj_2%LsfZ_xqk%snA*}4Ty z-K)*59iS7ws<QTBjI@<q$UQE56ZhMl^|%6&;vE*yG-yo8q-h7!khCOR8X@4Sj3j_C z_^RXRY5c&gLdew9+dV60%<}g<b-R=H^^_%95Is<8mb~deyN9OVH1~LaC^K*J?mX`E z?v4&cZ1=RG;5R%V-QR57jXxS`XbUITjZEI(m6dg07c3WS3qILkrUQ~#OG~YpW$eZ5 zHL|}#F9ot{tD6b#(1jS42%t!3Q<}tAaYxc_rI#%^3ovD<;y!=QZ0t2UYek!CZW8lj zd$GbFZW;FKjKOs}chKy9l)GMSbOuWm9o1&zzMnKbmTnqYZw?O@=A-^WdPN=Ve0G)W zG*d*cNYGd@?jem}1!0-EzCL?J)9r}KYL~*bv8x6nO~YQjA-GPDCE|G$*Vn2Vs6;Ei z;{|@h*sf+=LS&X&i6s$jXsdn%tv=3RQUNet(>}<|F4Dm<@a<`q$BjIXMFZ*pgG~@@ zT8|m*pB&OW9x=^B_aSsP(k?XTA_)RWF`5j9J`wXg)08!<ZZ1tUHz!J)|32Que(&#v zSKOnenM`SEOH1y~t8>reu@tXinfaJD&c`>vV^jhUAg*|YQwpyr7zf^xGl;eal!G9? zRI1eSS9nhO3YdvdYldVE?6M{WzL?XFvrYqk<QYz2V&o6dWKFRWk#IGL4}7^pJ-PeI zXwT37{`bGLEn<4;9DZ)e-I}|VS_($mnJPODZBE@X)B+d1E!F}jE}2CV1GE<S#*vx^ zWcI{bU{1mU7JiFt*&5~sX7`g*NWh)f&%IOv1D-o~75lk>z!?W|IQHBqq5&_ys&D<j zMFggG^R%m#D*Vw=RL@TX1%^EUT;P)hWZ?fVaDi!$4Anw(^%czeg5B_cuhRa1fh_Es zg}gqB0ZM4QOfq^;49}}fw(*)W(8!<}Kc>>vM(&P!w|LsMrvDWTaTnARSa{6?X4{C> zC+94-#dh1U%On%*rkP^3zKnIDLESbV(?9Xl!~*uT%#PIwPFT6q=v>Iifp05k0!F`+ zG0J(R8<Cb2Vp+s+!tiPVd{~ktYBDJoMbqA7t|?H<v!{i*W8ZZ(sEu+ZqG>af!WZtW zU2iT?7>X|0#^0jQzL>ir=bw3pU1m+_qjHr}ha~2nTZpq^i=~dXe4yv*_k1`1qL?dM zl#S~V+UD3-bTR|bW{|y<t3mz+0#uFm6%{clS@SEX`rzdP5=SRbrJcvp&{k=bJ*3CQ zSCH+WIeZ*v;YL74E{_J~(OP4))*h_okWb>fAA4-u4|3mmaT|RkeJ{S1`wKtg@!VFt z`oXrx$<6d}d<QAZy#{$Vm$`xc5ipPvh~~ILj6uO)?Ji}qOG6|id8+|G7!`QQ!ODB6 zqb@22e{mLmRl%K_^fV>$Ok+8PWm%AgRFkqly0RtH+`KIiAyyx!R67m^2li5r@|iz6 zAO!V3E?&&Omu!Sf>1`=jw)FAQL9J=CIax8~F=h{$v_<Vge=Dv&j;p`7aP<L)LT9-; zo^)iF21vlNOP5vb3Q;f7@;O)k=JczdTnTw6@L#xi?7hYNW(E&Bk!AzN?r29wA<wp6 zR$RiF+?-P7{NppY6Y9WKB+Z*mTJN^a@_23BN?o|xGIeXe5bV&J4rL3j8O4pv@#kb8 z!rPsfEpN+~3=}Q$4V73IxrW3hotkvXywWk?@DI<OeV}IF00F~A28GYZn}{(=OEfbm zO$JEj=&>_L3s{mMkwW(!h@%W|NM;$zIK*hur^H1RK1Z?mmY7IFhT%M*Nkdpvt=7qb zp=Bo4ykEkfqdhu;3pE*Nn|BJVz`L^bK~1PF_eom{*po#9#h&CzeC2m@5BM6)D!aU) zRheBe<g+%s+fe!Aw4Zwx-8p-<W+t)$!JtqWgg|y8qhG<YUv2nfL!7T5z*8Wu29gM> zd0ADAWG*OPX|n&c-e<9~#&l?&0DNnfj-Sjd`xyC*K185OdVCnUNY*g~pw)Y2>9WX- zOgm{m4#xVJV+@cz!#(?ua1u<#;@DCA&Ev<Aj02`9KsZlh-~e`ZMjSN}p4()#Sg8h` zl(Oc?zZo&HuvjujU<K3R0z!3-%&a0FRIvE34iw!|<mHKM>oQHa72_1fI0fY*MrY@` z1Iypqe9M=XgmWr%4PF^6AtZR4>=L<M$Zh!bBrcqTO}WVl3A_^{Bw}|~k_w95IT+c! z;QE-;7pO4jmbdM8_%?+ohWQ}0CGCV+51n1Y?OuC*|L)=8a_er5@A~%o-R0#QE>?Bk zuy$CNy}?($beIg650^)ma40Q9@D@c%qXx9e(En1~dF6QeEIM@0j*B@tY7tW>lyarm zLxtJ_dIUWiqBJNBow%pya+@ql0JBIHtj;JuRi{8l4wVZK8dF*fw%$}vjXw82&yt=9 z+Gsr0BNr4CwbC2;QaG|d;z8`Qc-{OeFG75v4CC3{Q(@X{Q#F5GF%Yvo`EDD9iWFZk zQjLBa{}q1cDrZX57VC4XQ@{d386nzhs;{}UHGuA#_RZI)Ij$H7ovU3bt+CbEnoy<i z8~8n(R&~v#ZS=IZORud&wjDBvJj~w1(~P+O2~@;`6-x|yi*atcek2Qwz31s`u6gRI zYp!{keMfqH8o%3-dxu@cu9fUxxz@()Fo(2qTR^lnPf7OgS;_tdjbOp}74;RY-_J2O z%LC!&&)A!yJ#2sB<ATXMOD(w|us1>4F=-OxdaSv3xW{ol4U+#+4A;YCNu`(_mK`7v zk0h!Cu9T%(BUCdfSm#(J)cv5H?X=|Q%~!|I!qcJ-7c6$Xre=Hib0gW)?&LiGBTum+ z?W6zfftb6S?9+UZk0xD^{QZ5}1$kJYKG|S<(WF-fW5L8Qir>gqi}A4}*bmx(MKKrA zpH#vTprz&A8%^ySH7y&3hK<a;{*7gW8>@!rY^)gAn5YdXTKhKYn>sfttsFoPnod$| zgYl+JiiUn5R`65&L7z~=(0Kw*&8HT|^mrPvAR)qX(yAeOd&D+9`j#*Eu1wQ9dTc?d zSWkSS_|5D4?|l9BJNLgnF1&UpeRk(-xjkQgQ2vc&I+bA?D5N&0=IB($Wx2}=Z}V^U z_Ll~F$K`$fNq^tDTpwQbkv02YFZ?C(k@Kl?Z|A_c^|jpl(X7_WF0UZkwXemRa$n4! zId1Lm_m|F~KiK=|	=MZ8A>xOEN$*V)b25j~JnYJuh~|%RM+J27}Jd{E~Twbc+4H zix-O>@RQNOz~tY#mAp*iVg!$Zlmhj1D&7Z&V-{s+7T!lJeiL&$vniXQ49!dLp0#o5 zMs}mb)cnQ0cki@JvNhkacF*u-?*Av0%~;v_hIfz=)2gChoH_ZslSo<r|H0lojXQAC zqM8zsR0{vc!rm$V=f`qy{;&C;muEfe-C}t#FUUjwT|u!t*fjn$%7cSoVJVack2-2K z`u{CiG;g<}6-KVN3|edp?S2JkLAkMg#0A`9yJf)QT<!G8ST}VF78F*G@Zsd@X=lF9 ze9U;Vmdx<Z;l0CS!$*dn9~Kb5IuA{u7xfy9@K^j+skr8DMLpF&#ovnTjO>k!MUF(C zkKnh;16C`o5fw2QCjJ}0l@!J&f9sbMe<Trc6{h#5;dhpnPM(ea>&-ZOnecmL##))> zOnWwh75J<+b$903mFH3UuBe?K?*0s&Z((_fJ=o{qJVN76;b9cuWv5mFY&?_s|FuK- z`OLtlT3wj-wXPyLro9-@dU#%fs_^H+cn(Y@aoVr+J4Wp_YCWYq{yZ9CS)?$nX0RVh z)9SE&?zBR3O#FIcg1ue%XmYIEC&rkZI76YGp}nE8(2>ydA<R%>`V2|6zH$qGi`M$0 z_nN#-yo@cY3;1{X_kt!CRlk$5eykobGa#>;JpY&EHZn?QbXoj`IOIwwG<h~`&0WYL z?h=+m!pIqSRxRU{JcIgY{6JFxRrqh7z;{JCigt|QpfR|MW5#!}xNKqhKgM>+mQ#r+ zeIhgYiR~mp5Jbruc6#=D#ym$nJj)b2Oq$76C$Yc@f5LCn<?rb>=I`Q2wCrrz+cMU2 zq~-Y*j6_FW3|#XCybzH)PHvd|tzVK(QqP#Os-1lV=XQMNTyYOcpU}?yDZhuBb~f#8 z8f!Yz^n4ROp?&HTU?*f?elO#GgNo^rtUY=jra<I;Jb_PvC4aiR8Zr$%V&_48{~H8= z|IpNrA)5F*Z{pfy{{`fglC0U}(7>lAOp#xsiN-VmnF%c%O(*K5DAciIr$^BuL-p}A z(<(acdEOlqtG8j(a&4SKy<#ydbAK^{x>erX-V>LpXRekjFSpEyDQ$nT3%=|qzY=XH zp`f~P9?x^|02^ekI4Y)9*Etu?Gnp25EvA@3puvmEj-a!nCmZ&qaEZn9DMNLU>H8Y8 z6wlN+<of{4eh&A$phcmrC&x!mzj0zzEYd-QNi5otDt17(UC0bm%OUTt6pX}zn84*n zo64OF+gcZUlPd+evT}<`k)E@pBR#LAc$Z8mzl;BoHXS!K^(|6ouT+6Nrlq=RV72-b zMwQXwR!p*c7$4Ri5F!Isqu=X#Qm3YuC3amR{8$JDKqrY;AzA#A_YXS-rFopmWYF8( zz*ZSP1=O#yQoX`dbW?FBvA0`fJA-wJ(t$w@@6c8|cVFYwsi{f8@VuLIqZY_Ycb$Q; zs}(k+S$KT#={IP*=Vbl?w=TI4v|gk}ylc*V`T7SBZMeMRIb-#_o_TS|o@Uv)`xXuj zEjr+I&Rju#r0?*1*-b(%b~UVb9*NRv);slBfY!bVm3eQ<7QXVzX~=<#xcAs^3xkO4 zIBE3^^RU7Cu)?Kz*yMPaM}?AO{7q{3;inX3k}gULRLfzqQH6~^`R&npn>P<HUO0T| zrSlg3rpH@S>h6&_caO}Ov*7wY3+D|lylJ4c$X|l%OXWt`7nr*k7n9Dy;j-E7uvZZ} z&>~81vl|499RlbWs+(#57wx7;;oOP()Une$uqLMR*OC(=wjkHq#RmBoVxiE5PmV3+ z4{J4b`UO3!o=bt*V^gBDIkaYljFWxcl4>Y=O#M}h*-t;vf_eBpI;2qlOY>&5oi<Wv zGe6G}!9JnmPq)kW^+$6fD!HM!IMW^Qp#RD6O#3Y;52~$HXqRbkZAS}~TKi-#TWhj9 zkkJ;qpbTooGTH?tudJA}JWY{k7v$Ekzn{n<*o^TuGA@nMsVfJq2IUgR2F6{Vpf^4_ z-Xa=6P+9~u=7gxz?}gd7{p6zZEJsv|tF<Y$4vNF=ispVU2+J=j|5~SBbGxC~?yy<| zq6G0mg8U8=1c-Ep?BoFp*{&lGScx5^$3}M$jkHvzs0QUk?si9GK{xvRzwNdv>6)ys zJDL|RqmVA6C`CAyCr>RDJ)u8Ds&uNZ5>qbp3a8~VxVGVRI_necf3YcJ{asy3{Yyeo zM^;DVJZtUhi)zdLfwi*RW%JUNU5iboc?$;yR4PH$+0qb_fdV03-)z=ui>VfUMq*@# z7DypwZe#wz(4(g(a@?0?JDD10*0LOqenO9mOtcRPf55plm|r{dHnWCsq8;Ad9T1>d z@SA_1*n)An1Lw@cIX0a0P4NuS1W0E{40590K{<!`R~{e<@tpbdO(o)Ak<bxk|AW6W znm=bR>Vql5&zd#v4Ao&Qb8qfGG9ehS!z!7&tgi%2VPzYG22h3BHmbJE<)Q7tU{!S_ zkisg^V84z+|5En~bVbx;LKNprVKpGI#fp_g*gKS;h%N`QyqosseC8c8;kfx53f0ql zq25^t;qzay$IxJ;CXcicRa?M-KILY^BKcFD`)>K?H`SAG1dS?#0dELTckH_bqxKGJ z8y=PI!2M$9V7&h?alF9~B&(Nw9Y?#xqaTY$Mdm_*;><LOV{<Dh27XK$@#B7ff2x0J z|IYrgej(F83r{!V#q<3??SHHPgZ_zr6=7y~R#k~6z$O%KO03x#@W+<HqwUX@rn;6g zgtmY`&=>`6c4dc0q|I(Xu~J>H95IZzJTA9V>TJrKO%dC~01$eZsRF0m+3^2B!-H}C zPvqIiG>aJsQ3^AK{$zAm$TDBZb7(uxBUE<vk&?ckyx6zZ`wvnx{@Z<VneR*Nd%3^g zb+6zL&eon!rfg>&3ZEh><bIa>$Nv5B5)8Q86vdxMM|Uagr21?id5md@6faUPs+{e- z*Zg38`AFnI+&voPbh;W!b%oS5g`Q94q36%w=B5NTXs*QT&tuQ$!4>mc)MhFOmO@Pc zea(Mz-JYK}-J_xa^v@0^jGUP@T)2<BVt&A`Q>*0v4uqbMa>8~py7{*{f%1w1hu)W4 zYMl;6PnenHF|LX8VLt@22F9&(X|52iP;PTvVY<S4J4IH-f+vQ2_FoFENLD~~mAR&% z|G6eX03ln`Uz@>@VALw~D0~Nnh?ygS8~3X8SnL(VV7BS7Mu4f#D*3;_dx>OCUay(q z_t^C2fC|Vm4lguO=GdvT8OUAQs)%hT?KS6A3o4Wi1tY=#y!L06tSXJh9{&|SpK6_H zYpp?<`Xm2+&d`(lAh)^%237Px>}97q^psVeXf~GN8f>7lPV>J+1#m~!Z&g^0j!oTV zq)b=JRQijJy0q8zg{a$Fc9TY?bfD_yr~{>ywC<87CXSxOYr~s6PNM7H0mu{)ELAj1 zD4q;7S0QlL0^k@Npa_!^P5}Z>K7!&)j2f2~f@HzwJL-O0=ZkifCZe}?v|hpq3SH^J zYq}53O19j5Q{2wpUHW*b#bDOjif?q7<vb_6nCR({sax){MEs7lXLHTILrUC@6L+KJ ze+TJ0oJ|I9tf;gbLFXEd+f_nsxadpC%1X1_x2qi0+GaNC)|BfX)xV(U^j~0|sBad7 z{21rWbhO1v25R`6JPw+qU!X)@gxWI{xOAwgfhCFPDu|<~{hEK7w+f{rV%<C>A*al( z>%8J_K5Q3sn#+S*7RDc#rNTfBS}InXdyP7!{OWl#uG@I~7y8oG?2cT{WcTpejf<^; z(wL0(T~ut<6os|(+hYJ`D9>!Us@+soN41G#Vp#5#nQ^xtK)Tg3&ysIVoI~~5huj}? zJH_`G$o<IMO}+mT&a*S)+{3wzkePp+SRnrq-p6mU+r_^y&d<qhg!KH&>-6tSS>Usf zlQauVJw1NnBN30PVh|`(ivc<gNtnR6cQKoJ1K*7JDwuOGGm=$Ca#=C?2ytPMDcZ;$ z3lYrZdNUDB<OUPD)JU$!x03urK|Ya_>+vlRB~NNmuer-bE<+B%FED!K!?e8L9}4@m zybY-(blabh6wnF!bkk|dkqhPTIEv5#vx(NvgHT2K!UHPmMO%PsBx)W~hl3hZsHvw0 zEGEoOCyh6(Umkw{cXr*XQHyQCa+U6%zjrKO^Ea*a_)Avz2VA3h**wQ{e$NM&tn>L+ zuK&AM{S(vDRZ8u-5B_ilgEH|BYhyp*mZPh+IU8g2{7ztuppA8@b)$96${(>lZ+*-9 zftA0+N;bl*32ubXvCRXyI7+TEoTS(5IC^TdVA6{*+^EF=SMZ4na)tebw$-rS?kkS5 zRX?lp;uVpz?z*?@TRv_vb3?9Ft)*-fMM)el*w9O3Dqms&`3GTZxxYaNHlvEk@?D*Y z5qywnVolM>qo<?~))8oIj7_1-hl-OTsg9{$rQsFsO}U0m^aB-~OL_4!a_w@DEQ*f^ zyFKxg_+jSM5=<@~k7vjUZY$q`8m6W!sDlIp&jchQ2$Z<628&^vfTIFyvnT}6qNXYf z*<!|637K+obki}~5+TkUp9hnna|XR2<;tjK!ELoJI+Qz`JBi8>UR_UYv%dBc`GQ7J z$rNUzgXKJGb+Bpm7G5{&C@<3}J@wsRmg&n!ONZsS!qa32_hs&Hkgv_zBG!y66iHk? z;$<3uEABR6oVS?`7BkR&agid~(jMIoS}1%Jj4mKxDqNxrLsqadLC_+_({X)YwncO6 zbDNQ+kedu{)?ULIl=R|sZo<B*Rh#zTu1k%!bqeS$aF75lEiq4y(PL&#oRK{zTZhia z`PrJ7u1<%>F%o5KS=P!DfhBQcJ;<i19~)8BC|C>n0nz8B&^R=##=;m`jRGwvh<@Wg z70{#36If!7)AW(DTi_oZSb{I<x@$>IEtpoH^Nr`^_vfB8Xp8|LfD-sKa*Jvv|B=f7 z&z$;j?)!$yltu30f2CA%tMS?O`JNdIdJ|11#wJ%;oj42@GY4#STme3hUV_9aitglJ zNWplZQx&!#sM0A=zKzfL#!qc{+o&<Lxp^}9G+A$ws|UD;RQ~ZFZF}3W%A|7gWaN9~ za?2W;iL{W-SY02%nw!IHewrDW_(QgGU|=v2PVDa+u=Mo}^!0>`-Gh6C+DxY~Ts(Im zGx#OGFTqy_yy0pzB~(<qELs4HWscH>?hdqzI?xgfHAYLjPz-SFIMwfOzIqDXf;-Si z;W(NW*QWxLFF}FV(3GRyRxK9!(C3op3D-=N{CQnWm#gHAQZG$3bCB1yi^t$xijDuY zY#ax;EuqK)y^I4rxD_$K3+94qK`A%;qTem4u$j!-^6(<H+N|X@)py;O_R>yUeJE&B z$a7((&e_nwU&rY*<YUkQ7&PdBw=2yinM|$FR%)%`(%;*?cDud1<_BI+g45X?uA*Ct zo%Pk;G&pW{pdRsvF1>hE#(75iFnwTGl-+|Y`6#m@Tiev!Y;N~1at_624lLq3%|mlR zwOCaiTap3x*YO#d49OgCAWnX)gp>@=?brw2Z^01GCw!45KMGKz(UbX{?;B^1fwKEF z^eE_gpkPHG661!E$j2}+itrQYP!>|Z5y^l+zFa7Vyq+Rv#2y2O9Tt+^S_y&=Q7A|U ztjKMOLv54YQ#`L)6Q+st8;hb&e{-u_d<71usN3N*@nSysx!cd!gz`*}+DLxDlZv5- zZSquOyWV(<Dj*Zsfoc4WzXdbu6q%!!5Z;<4A&JfLl_fpK+|weLW49LElZo|SymlDO zb{AN{;>x9{*pWt8eh{O36|*DTF=u!<xwvXk`A}y4+GM^CVG%!?9NLP?gc;qL9c!8O znayPL@s*kRWd8Blq}(^wN?M1n+`4$*3^GF~F*aeSn~tI+0sLVY?5i>k47X&#z-D>% zs5s<rh(!u-&|n1;?uCK>SNwm|OBE(ZA8nA7cC8TZI<I~K!w<O(=q{W<Cj=PIg$c1) zQSmEo4bc)TR5ZvBqN0J5(PfCap;Usrr>8wQHB(RNER>c^qSlnk8-(sJk^X=<PX;<o zv%mN5GZBj;B~$So-G;{W#`g3}>6VY1{bJB^&sMSLR4R5TYA3o59j$g~`KLt0`L5@y zASi6tPLguglSD|t&5GVM^S~q}XD^+`(hc5~W<_)Vn91qlHQgI{hg1o1PJRTH5Sy4Q znQhtPd5agvS5z)a4Yh2}S3|6c4_$%si2k0It1?^3*5m6zwwm=@>^<u<OURPrb4kiI zmL=KYD^~97C;dXi)Tn~t1@1<1E(`kx6h%|BSg4qwJ4e*lf|VvB=$IF#g>vCdRZUDz z-skQoU_OfzBkI(=W-aKg!aTyV6}fXHShjqfh25H#A5n|^dVw7QRHS%hvTaMJ=B~KD z+d8?+f`Cq!`8mKf`Goni_kLlsRj$&qS`~Ji0gN*IYhNM3&9{DONhGHyGTWwLDY+96 z5O&$WD#Q>c%*%08yU<6RYsbTK!p@4`ylB|xHO^S8ZArPsjo7PYF@?fKv&2e`nVmP; z1DlJfe)UZJRrWp@WY;sRvUMCYy0)sW&fKP2q@6QoZBfR)$UM8Oq-aB?fixUXldjQ$ z;j-2GF_dTxx9x*dB=}VqjVQ45;MAgDb`;%0r``a+s5Dt(F;J5v;f@;KkV>{-<Wrp| zQ80<>;?qL!{CXg1#0&F4{fmMcnN%dAzc0zT{Kk}e7G&=isG1_~s#@pgkkqn+S~;&U zMq1?Ik+r<c?CQ;PIcYseGUd6PJhMN;<;3w*!+su<E!kx3TYsI=$MKxLNv->XE0E`T z@?GWk2<Fg!3TZUO^8^+&MAVKUt~EDXRs({o+0pjSxk7_=cE4&7NI;_x&d+p{?&GcK zkhG38&>d1kSvyQ2D(y00w}Om2MKw1a@{i6?A&1DHs8<R)CGu&l0u}w4A<r-Sywe6% zEglGC8%&9^nn`7HyVFro<(M4L{<hxf>}sxAi|r>g7L`^|tzRJga2Mez5pYSjyu_NE z8Ri8xgSK>XU!Dq>)mPN?eID`JZp9+qtk_!%8bA&FvLV39Sba0v=6DyNprAmoc1y5! zPl73IIjY!FHCVGliw8NTw`<YjV7Uz|H+*mK!4)%SB%4M%lEVx2BUR<m(WKy0EgPXm zA&tYldU6~v2w)4NxCj(R9@T4L3&S$Ts--sfXIATf9ywZH1nE<dAbDe_Fm{tEiu@8i zX*Px_o0#Bf&vZ^7#XLuyN+&2gcX^0Qq#2vn7ISO8ztHhc&E}v_u9;J@&OF63R`v6$ zczI>(=MQE!p)!Yhdcw2w3lfAYZWhfJU|QZ?<Z*L?d)Oxi_>B_{%0bzE%tq#-Y)$WT zv$G`~9odF-X-9U+bE__}gM?=`YSbenlD*`D#nzGa!m7oCBeQ$EVv(NV5jNeRpe(~j zX?0HK==kxIVwuk0=&Q58L$30T(c`DVV2g$%19~JVHw8d2&d{NT2ro!)_@ZK<1cfHk zIEcYyOFdSxM*=R7BoZWZQ!<D07U!h<5dx_hZJa4gg_U+w<oPg_gJ3M)T?C;mF%|;~ z8BD|pf$-}tnBj14>uE7+%SQrj2BT7c`0}4xNyhOEc)0a}Xi6v}8%Xn7a`&1aHM%u= zoh8m!CYrRmpAByx`Ip?r>@yFV>>RJCsJ<`PRic;aG`8&Sj+=^9D;9r^Y}s>%TG6=3 z-MsCpK7~wceOTvITPl_)XSN#I`Q2Sx!GA1r5DF2j_C-`uD@sX^>n;~tu3DrU8X4dg zF`XkNzEDZ@n8S3e<iW*r#^#ZE!@Xs7quDZ@;dptO5b`aQBsFCO0pRa(aoIy;W8sg# zff5qz1Im*}4I`2FZ`#^N!5360U9p8>r;1dJ8RP?67-GtmIcefg%4Ql8`jlv{ObZb- zZEbx5cr)Bc|E2y?LtuHRewJHj6A1$^xb)XgA7bIl%Ph{`*&fsU*0@{SR1n7=@1LeE z`PN-~8m;xV;&M;@jFo#TGb4sOTL5|Sv)06(3ocx>QRP9Fvo=`}!a$nzD$LF`E>N{O z?ZL~CQxD`;@crlwOC$2#!Mv2+)s<Chds3z`6MMw;yy>SVE~Oe%u^*@iUmE73LOG+a zB$Yb`;V?Guuyuh<x^73bDBxj0?0EGHMWm>cf4NMa%8X^$BbnzjKh1ENtVZ9H*<#XD zMr2cIxFpb6-pDq-tkS4TOe&Mgk*dkmur)82$Xf<WBC6orX9U<KS?@0Qrlj6c88? z31}_bl%Z)pU;snN!=0d2UU>0_2%NysP!IM}0zPd`vA9DpQCRfS9<UlHKRxxssCXBD zAUA5K`vWfTB$fh2^Q7RNyg$A49@Vv1pC~R;c<*1nXx6p4bngAzy`0%fgheyzzeLzq zcCKBu)2o%&<@~9l!Lp*+sloKuchzlSe`993((*?ySk0+5ewjDX`PJNBm&~zkk5*B& zyy?!Wwcq*9hZP>T?(M65iC%wVe5=K8f;StScu%oG_5iaA(&wsdyTN3d<d0U4F1Xin z;q303bhmQ#F=j@4Xi<0bvBV_?rOqOl=55&ES$BM;eExx1Oym4Ad3$DlD5lnVs3-z- zBB<VxTA-*N;Ex70FGlbz);dHHg;J#60MZP2m%6q)3{nh86g1F&ViX8Qd-<m*qybPz zg-^a)FE5Tn2`1s!)xuDr1qN0;+JOi{#~pj2ipnohDh0&GNd%f;zbH0Ps_Dn$)D}<K zSLjO$WYYoJ+8Il?f0%ohl>YY6>R_Z8WOv#+{e>5H4bQISIHT5P@F!)pBhjV*j*i-x z`>W2(Mjw&6w^2Uo4pW0{K`2T5AHGe3l}3%}3p=Alip2|yiz-61XU4ut46g`QxeUZv zl&w1W(Wls|S*Cm9kKm{LGy2<Wn049K5%ljm9GbGBlKbm?fy&tmwD&$(>q)sXpaLFq z9dXHAFNew<iy7N8+a)&cL&Py{x{y2oT8Ni5IyH+~qUF%Y{eZ{u><J2dO+!l*8RVED z2W)agGwU{?pi@F9qUvGNVyBXanvql*iN2SZWs?YO#gXQ}m3RW(Bh|9&);zQN#;Y%X zc~AedU;UOrHB<XH;{V|0`vgP>a<O@l>P7PsF-~FQEwXI)vd8b7JF9wiuiW*c8mnyC zCA+{6a@F#tyGh-w(&7O~V_!}udmhqw4YN91<!}i)7rsKiq2-oi%({``MWLatY~`Z5 zwYGUK*Xq^6l7%xy=PX>_5E$-QC{(C)!-%560698-^aPc|$BaM#NA)V*+A!*1d>Brl za#NH624Dmrp^oHNLDxyQN>>+dJQBsa5})C2@l8*Hu+EPU-igw*G#=@eM=<7dh)(TT zpOTr!%bx%5<`rw&EM`@yC8<cadef`C6^Uwo;k;GNi@dzR`QWDF+an`#zqNFV0o61j zGN7)0y<v0li-}l>*j2f|ULExM!lo^?3k<B<?65`aFVL3XZ5o+V9?{D@ptm_);Z^Wf zKHl>8=3Q`oof1K+M;@O}kh(wYl>xvl_mfzBW>4^1j6I};{6pCj%u;43o18y;k$rYs zXMJU-c{bB~Z)8zt%dygB3t*Wn7G{mkV46UT*_NFjiKzhzM2%*sK1mwT!G;t#1A9c2 z0Vne|-+wYhqBabwi2WlW(R^m>W3*wbi0&la@nR@o((sUf2*cxs;H2RJT2V@_ig4FG zx$!^TawGQn!3%@2uvTN%Ht1KZyZ(O8&l=Y4KdVA1B2g&S#}{s2@UP5_3g1O$<I{KE z{@&Z9xSH<kYeNCmiji$#I3^dLrinh4IpqmdXKdel&~Yiu3gk3|iPL<PKh4_E=SN@X zxsLG~*>=1Z_d4a^K*gAp^8g5k$kq{R0b56VZ73w>JossN$~Ley%wR6aR+k%EHL>pY z&L)4X6<_wwM+7?{t^0LYJWaI??f#zb(guHNLqn;bYjHoKY?%hJJPpDcz}2*m3KIrP z1$i|Qv>F}O^*DN(itA~3)f8TdTItYW5}G{(E}r9CGG4?O05%GyP24F|)iGg_w#!as z^k?Ch$6sFJ7c|-><bVWOO>Tn|_vM947tg=W8i^xzMnS6UYW6+$Q{p`LJ>8Xyi&3NX zX(;A<yJu-DH43wYR?V?9XYb!Nvxnm?O4uV5otij)OTnqXyh9bfU?D7%HZWuL%dSSH zRy$%V$fR!?xVWPqj1nCK{RelfopoWy{BTG0=)n9#SFP`TXg0ZfHkqxwY=t`6#JT`Z zlsVl5c%so!F^vu*8_hYnGvXsPwx``cBt=0!Pz8n2z)#eMPmR#$o<V4f4m}4n;Be<f z3mk3_UH64QBFZD`v5R{_s?JHv`n8HWKq`ZWBn^^6eJXNS1o+(X@p7$D7agO=Q;MnM zCG1aFrGh>1!;62MyK(b;qG7$U`(t1SPHQe(ZZw8Rwo^haw`?&sk$Hv*!499P&*a(Y zN$J!wWduh}-KL;S@R)iFM-{npt$#sZS@7Cm?!E5?Oxs6Ez}M9kTY9lUol^3qhCejC zcxTH$GhWJ8sKiV-CnjVeRD$_YeYlOeIa@J*&Du3=aYyB<j>S*U!;Gx&$Ufb*Zr!}z zfv%1@1M}uxw*5=%4zFXkt|Kefk-6*0x~C>S{I*ilgUA2Qy6QVgtdlr9N$31^-1333 z8M76aELSHSbre=xoVCg`=p009qAnpOD8ver$-Yin+J6o|C`#79n#jTo{Htj!ypOW~ z{47d)p)k{uabGyAP$xv~7-@B&Rb*-oYfHXf0u)Zic#6*8y)kJ9%Syjh8aoiRu&?a@ zLS<Oz1&(LQp?DBw)l2TOlzq1>HWo8m3}v<`+IMy3gQ)F&s3aiUXkY4>nnue^b3(2$ zg1k(cM7Oz@vRcMfy4=qA1oP+Cl(+WRwPuw5R-LRaD!cpckJCW?341D?jYb&&%Fxp^ zCBeWAl$T)b%-(_oYlH-A%S*6HS@-<pnZIOSoA`qy>zb*oYnNo*<e4w!&qP1)jNj6J zU@o*|78`1!oJZTb#FJ@1@Z|ZZu*qM;uNWX@PW|QHPhEo$nLP6}^M{FFFq-e;Pxg09 ze{xz)l#Tfv{tiKf?}gkFeiLw_R%UCW>yr(gE!LoVWkWB+RjoAM*Z>;e2Cg&RWxT=2 zs`W;$Sf+S6+tL|HzwB9S{W9XG#o*N20T{Md0TX#*e8*9`0x1|9QdX(6$Oj>3b@t?m zQvfp+y>)DT$<CPO6(R>zusv$?_Q$k^L}f!>D+1k;szrE{+>!yC_JGF{HYsC&`xd`d zq0=?!^bNQ`Yw;$RMa~-ZL35vJb;pvT&f$UWnqwM8=HlD9JLNwPnYumZfKF~)`PGvP z*u-8H0Khl!g3LCn##~ovu?bC{WJ{=T#kSGmqRW$UyWAhA@#^5jTl`JjN2sE7GbLGv zVdV!HJg;r#GQ|M}tMHiDY2?mzyq1QCsC}>rP?@8jQ&D+d4bDy9IP}}!9{%Px4!`rx zp+|B}tz~7cZOLRCdGD>ezWBwv-g^74{rm5FyR5yvEZN#h=c;((9Q$qFh&sPm))EYw znTz=4Zv92(sNEaf5EfJ#NbfVJPEc&_SLwF@S9LCQJg2i<px*G?oMxZBS5bUxaY9!f ziGmyYo3rgYUcL5JBlo=AFbgmkY=##~Vh7{T`Za(fo&7*Opv)|Ca>f`>ugyDgiVtIa z>XEJX)PNm!WtwX&Szl~eZ*B;B%j9+Tn$<e_1~sk`2;wMxIhHvs8tZ69Ib(Q}+N?Xo z>%{^QupDT%L(HP*?V*CLO5d4W5H!Xsnn`d+`LK=)unRB!U0?3hj6|)6+&zE6npOMP z=(NQOWT6c@8%q0LxZ=Lf`YVXs<tNL)t{S+u+3qm~OOIO2N@7trb`A^;X%gzqMTVMk zlR>wkW%f6>54ATqaDR^6C)`K4zZUQuM5C)3tSgzUX1$`!m(G-?P>i;&rm4xkW-z>r z(wFcxa-DG<inc`FUm$}@MKCmG@{6O#aKE&@O6oMD_fxR=AS9*R%x{9cTAdc2qG#sq z5g*|`I&{lRYY+dbq*SJGnD$0WBgw0*U8;IbiBTB@kx_b`Yqi6m0?I+~>W{v4(}NE$ zzhcX?Yv<Yh33k^FCV#or5pU-?MewmIzcF2F3Ft1qz*($on7R1ACzt!~!<zT!&hoeN zm8eM>W-iaRT`+?vdWqdV)X`XZk+6J7-|g?-+0Au#e`glyoi*!%aKaJ}C&J;PdC>#` z>}R4kJe1f_A<SwVTI~h<x)*bQ^bIi|>^Pn|L)~eVg;U(^y!%W>(~i_Apyv=udUc24 z)KS{W0%mc<Bt*;XQ$EV%SRt2I8!EKIPezbnW!NRxS+q&=nPM!jMx^R%_*-M))ozqO zdAwVFwf|MA)~HF`o5^LnU4(neYAZJChu12%4Hub^CpITyR@7{aKcrKJVsl)Md(gD$ z^>ZAhm-h=QofRBL0{1<4v7#TjI>-A2g~=IDkoAX49!Z4e4kUU|T0mQoeB0R~%fQHD zuUxs{n_!KCPm=pH@8pXhe`jPP6;<XNnZC@PqU|1qy4RJm6Z`6=of|vZ&Q890O){Dg z^2=(+aRf>6gGMI6$1bj`lV>1v&Qjn$tSqtQk*+N2x>XioWl=FIWrC?wC;4@BDM^7& z(d43=NiuD%f~c=S>+5`KU+#DB@AVjr?DrZEcBJcy_XOi0v@#R*tvf&Y5FmMaEmr&& z!`~sqWgD@7=h~aUll$kz!#1GjT^o2P&^fovVX{S&-z{r+uR+(KH4tkL=RvFL!D0b1 z9<SA|zHk%t9F?!%;NOP#;1u-|yg)9;m!UqgG;6h5wM?03y<b?RO}gy!LmNs2MB+g& z4SpX;J2+#8<3=zyQwvoJ^iGxF<h@*Msp)rZ2g87k%LT9Nnq4&~_vl>fWex7C3VU7i z-<mwdY|=NhM*nAWbFGoR$L8DmlfS*R$`bhC7wZypsvSy$+8ckh9F}{;;^g92!_G^< z6YA$rLoQc<g?N58P-RZ9WTHFVL9L=J!DJFE%?(#8T7uf3b}5QA)|FA3HC0&|AGh;O zYfumjrEvl?S$B4{9+E<2jiA=ro2XH#N3|UFT%=o*q=k4(1*KSUPpDB%<E)eYmMDl2 zr<}e4@!0?HZ9jVNwujql1HqU%@bI1!58e4_&>9cMQm$BTM^~oKVKM3Vui<#R$F*iI znfJ`v`3o=lP5ZS)7Nt56D{7eW?Bc$;E5EiV6A$^6T&%pjmsPj)IA@ea#}AGck#w17 zA=Q)i+$a1uASZ)}@ziDA#-f!>idV#DyUP-5%yzpr6(-?zez}%PM~a&)@xn<iHELae zfFwoHSgAZvG$m==k%nptva&M3oTo>>arv*u|J$NjUIQGjn${6u9SGXYf=4%BcI2!7 zK!r~Kc&;WAtE!4ctI2m>KaxA<|F9(n7>WqX8&<44^5-2F=Z=0kQdbj;)zn}|CMJHu zUckKrO*WcMmPU%oYFxfRJe_9ZMhnk0s&>R1d_|@5Ej1CBW{cy1gVZ=`9KJGCgF*d@ zk(W`!S@@l2D@lshJBmR9^u53urzJ8t15q1sK1F0&>`6L5RIH1Iob)d95gSo2h*6kH zsV^cVvKQ0=kfTiFPIPI@RbZtHEo@B(JiLmP_eOc0g)F$_u^X%^?FvC>BH^-D08szP zFE8~p8#JEp`20q#P`lBHP91OO5_$5`6*ryK-EJWoeY}q4^|VnSHSv3HBX0ta!e!ZT zdvmj;yp-Vv>bq+<g~Gkny{x5|^!9dN9k7HP+L_&!d4YPGn|G@8J@xgy=?$6cS=C3X zx#}%3RK)jgp*gehV=vOGP}n3_p-EZd2|Rl8jry}`gr{kI8uTJ>PGbo~>o^rfqJIbh zCTU2KBp`1X<}Jd);?K)1>;RDzfXV<Ympnfpw=o=rxu5%=IbKUsx8@5<l=!HW7x}zJ z*R4M^u<mBo5+GOCEl5A&vC0*!ObKk+jj~ynU3Tnk@BR{(OwCyrTL&!OWVKaY-e%NA zf+istj7RR7m30Oy1^K$oO>0xd&4R)bOsE=KWinHbOi)wVZbJ=PF)9bQBBD`K)>2y? zo;%d}<FI~<La;3!TK{9)$Vk{}8!8S9vp}r4zSA}fn?q4OQr(F!->QDO4?_oFB`ItH zJ_dAWP^d$!tI5Jz8tXd^ohm&_QUZ04U}2b^KM?_13pO^EmAJsB$-~buFnr1xmpnPq zAul+0&=}CmFvl@dHd%4pTiq=WXPyrgE423gXEpZF9bvfVCPVejS9F8fKG^^DP{$*3 zyH-)2+@LX1s_FwVjo@=x%npyB3GFM6-4iva$dG^*e)a|sSh8&6Wh$qs#{?fvBSgLu zF)HNF0aVU%T6(a{<Ww|X&TC9PW^gn)ICitrFP9s^d~K~Rvsx2rt9P5%C>KnQg;rkt zGoWW?X$P%rNOn8$0{WP1vi&z@$d&j8>c)VrLx~csNa&f&rGPmd&~?-ch%+<KWHK}Q zFX<;6`-!1H+t1bqO;2W0k?!tb<zVSxiuH}5qf|b|tI&l2;&^<Yp{6&5@iWyE_~F?1 z&eXYj*f!(88+97arBUKNer6O<)zku{wl0Jl-StS8Q57vkM<x$fQwBha^ph8bbjh3X zg~*eb)}&IO>TuZ*8;yP?Qu@tO2S@lIZ)l5Fv97YG%1{OrCd$N}bvsR7ByVr2SIaEc z#2rJotHz)6`aM36%dSpWY3=U@uWM5%+Db~=5TjKtRF^1g6pF@MPI|8;SKUd9Lf}3M zcIF;?GIxjXH}RRX9k#js$(T|msGtGCGAvV}cO!y)SPO%iglN}WUgE9n2-Y$WWG~5* zRPAhwW<Y-^6AV_*ID)!;%HOAoKWSr|d*v#WuR<44TShdMX$b$!@$sfnLk^^Ul+t<9 zlM3Zc7!%Eq0KKnrs?1|b{Yk1&qL(W?m#Hq@{@~2qiJ4VDs|-5SoPw}!)_d-bj*{q* z-r1K-jenyyj*4GZqN3@dl!BM3(yPg%4_~ueq3~`XPj1*uTIW2Vv#&@km^-p(A?Ux1 z<uhlK*XJ7Km1(6p*E6J(*H$Y{*!7hYA9DA|4xrPt>}j}cA7^cLF50aj4iqeR1rJA* zeIZWY=MgIjXprqJY~VMWM6`I??;|Y->?u(vNZU({&Qr8a&^vPXC?hCm9l31#d_$W7 zOTI=uC--V@IeCm!UnkoYzdwG~EbJJWzf10=oK{~9gJg)@O)7yodIal#2s4#HH<b_g zNkA%h_=&$OhO2%c8SXF*&?zbn_F7AN>52wE#F?`+xA4&!*p@k@3n5<$%`{lCg}!ch z<xo(d1qFz&p|~g?0z@z{vHR{^uJMnJbj&Sg=eg*>P=XBKeNm=<{M=zb%LX4{kL5mm z<^B8^UrJuvVrSVM^B=wEE5tMBp%UCo64wUI1@5TqOIT$C*+gq&T=*JO{I&R;bZ>{l zIAA$6)ZYDMO^x227%T4$4!T*2Z>kwn>9HY?qcj6Xq6A`!id1n~<*BPAJ44bGQ|{*E z!lESr*mLxzChg*4$hv$et1vN8GT5^?91&0Fj;b^)tD!iiTOa>4azXj?si1<$k$lqx zt`D~GB^8Da=W;tjPG+vIWqp00u-!TrHLZ6<GPBJ+J1BCg_Y(5rC7Vg@;F!*?D6Xnn zYg^b=VlfE*go@Yr!ncQ<D;zeBHeIPC8jRG8iGOfE1sZHS&`=`TuK}nuJfQG*RF@A_ z9_ny<do`M}I(AU#Z5eDFt78*m(J~CuQ7W?XV<fht&`~-Hr~K%<RG(0*OG@IOw<0HR zJU={>-i4{!z(E5|8$a%+8csKO%|!_;`%P|xz?x+Bne7cIV&+3?)BL-URS!Bm*pPEb z-<<T1DgsJQ>EzzFat2pg!|RGX8{JSPc8xB5&y9u}cmSM68W<8lqoZBnschOtk-;h_ zekD7Mo!3CogPd}bN(Cc~%fvJ}fEL`PJlt3^f%21=tHx?;1&wRa+oRz^y#ma(v*^R2 zYs8T{Bf?T)Pa-6-1Nq$(MjAyyjg)9m<hP)-BJxHCmENMrh7kUgTEz;&jySAI{_Npj z=bpwEJwj@~a@WBHPIYo#bikpN9b9@@XUl=>9@bfAXQB>;!m*6(S_a}`_SW3ls%MuE zlDkMZsU?rKc3xVfQD`Cqk(thmmdv?o_u(rMq;%L8+CU=j)CWaRatP7p5!qG9pDfMR zH4SK01N9wU1I$40!I|j+$AGoEBQ{Vp5I)r3(K^<`8hZ?|Icfvt$*~gFJLU=~WMcq9 zoYY~JR2n1sT`BH<EC-qfz$!V4DBh=#9STYdslb9RD@cYZV}Yec?xze095cyAyd{U@ ziLaOVO<qNPMhI&Bplw1}7y`qA0CDp1q``af2BQJ|O!0?GTxJV}YzVg#eS1vKv5HuG z?l0}2aubC#1jwZ}0M&KmKIrfQ)IJjc`_iSkic2@-W?+3_gxH&*rTmEC*<BbKZ--$( zHK08d_za+hbl0>i^HVp=PPdHc4SYTb#lOOpz*U4N{s69sD}e-8_cWsf^Q{kZcb49d zt6>HV+#q)e$8iS}vG7<CYwuHu%acw+4j7H^BJC(@3Vbp$D3nQL%8C=s02&k#x1Xdx zxE(t7;m2~%eM1fA&kFg)fv|$bPIHz$nMB;&DO<icw{NjysU!EyGe0N^-A+xmfUK<g zLhmgr$h~?S7KAu%IoZRw;u*}wYzxe#OvcmJ!B{%L-Q-ycKjPrbrutd_S)Pv6KzyL| zP=8<dSO+K(UA-+W(b}r93Ra{S)Qzc)=dUj@EH=5sXiwvxH(|dS;QLZ<o@yHl=uhc( zn=0pmFF<_&Dv|#4f|F_|q@j>KoO>X+qIF(f=(bSu+od+M#-I)K1~mTop%N@KhuPwe z-4{zdQsPuO+{;lq<HHCcvE-Mn;>VABOsc?|-MOBmN}+S#v}}8HWqVKV%^tr(VWX?= zV)E1mCt^IEx%aw~KfZbgRwNy{ITIgoPhd}0GF4eG)K+yOG!XA_4cHD<Q6z3QJ(%p# zjVZ?Hz|h^5AB^#L(K>;NmZBMw<6Ded79fjl)zqz@T7{?%=kjW)mbPbePXJwvMO?-f zNol{o0ZAzU3KEr)Zl?0@r;LPX3`kI^XS7+iab|Kjl<9T1T^mNmO7I%junikN{QXw! zA*=f9xo>V-aAS3pCpO$k<-}V8YEF@>eL1^b<s~u;;cj%14i{NuBeQITt*Eb`8H^$< z9aYoAL05lwho!r_<C5U6;6AWhMxW@m&FG%dZ?IVm1{*UxJky}E7>4H<RC^6$=x0(r z!JuNbd&%hVoI$pNQALA>?)n+Zct;Z(S2&a|n<SkoD>Ep6Kz<=}G%fY5kDhZJAKimM ziw+eyh$K1^VuukdZF(GqIpRzDOroY-N^@fs<#?FBwZ%0h8Uq|1<w%rv(b7VGD%+>T znq-Q@@T@HtwIM776Scnc<~d&4u`ul>vrRY`gcOV28}nNPy8weypQyV`t2OB56;~P} z=utuau)~kaGAiqQwus(k0H2A$PnjwAhXSwL&7P`@jgBy~oOgsR9I=$vxx8M5BJ4Uc z=b)EUx<{`?&fTfnL~PMMj`Q~3@tTRsLH1W)B4xLb+LsJ^Gbb3v|EvEt;z%g8T95U| zx%OP*HE~D73Y>@T<1S`Hwx_wy*3iK-16)s)-z9BgL+QTK1EoJJ<x9H*b=kUQb(hrf zmO65!3sv_S*G3oj3QBQYb(}I&0r#Yetztt;Ea4^;bBhTeG5v^YGpy<K(PLQ4$Hrf% zJW3ZdYds$yN@6wtH~X1ZnxVbtJk=qaXJ=^%CK7{);1b@rc$HJ9@k4k?iX+xV?49~; zS9_IeD~yZelSz|o*_K?@mhlVh0Q$AhHHRbSsJi6(z21@By(0znv6;NI$re2PsD*2Y zAB;x@0iF#IaFkC0k<g89_)6x&Y@1bXmB)&zAMkW7V@Nr3fO!FD#bz%nBIQK~ie4z< zipsilhpYS#ApqVdvl5k@SmkP`kqbWvpQn#gL!dW}k2Z;Z{V0OBATIdm>>Hz-#_|8` zpJ9cdq=!Z_X=#F_T7#0^0Rx*ZHN2XRoFAt3chm>RdQ?7@n+0FsgYT&n3iYwvKPiGf z^$UpZS+zo;dV<&ig8x`fxN+sG8*f~-^2T#rg=g%u_`R9WsnySsZ{wV5^5lyu)r+|q zxmQ-*cH63zx7@Na|44mkSefWuzfv5L+1YeV>eN5NyoD$cM8yNu=+{qn(SCgc8c+{a zrF(fEE=9O#jJE3=Xum#nlPjsmN4<+tv0WbuPHNXLg!!q8%Uhq=lGLP-3`=^aD7~Qd z8t|9wHn<=BC%5i93JT_G9s2a=A1WA>uDW;Xz#H%u=@|cDVVsqD%rm*6<6l9OJ~~~d ztVkcZ0#>9V_nlwu-dU28dFee?<}8Z+nD=5}Q8Z?K;FZz%%%LvE`9MWUm-%qHQj_dK zQ-7b0D|(U>Lz$Vgr<`K-8C)ew1cq7@pb5&rK@|vx!ZZ{wX)d<9P;?@ra+?pHM*yeT zpS!0d_v75W+@jnm+aHt_%kF=QJdP=;B#-BQo%=+gV((%tmVaKjTjDv`{X|jj{nqRv z!K!+;QYW)itRmgdku*7y8_J!?<#M<8a%wfZpIcU-HIU{{#-lEw30a3Z*>Y6})7(|@ zK;Ky3k-oS3xOVG+sUtiP7$`o}TU~8<vb)=t=`CU1V|Jh7JR4D*KEyUecl}+MhVa+( zd98xLq*8U--lk8dO=Z3{R?6W?dR~fOi}p0^MH%nKR7UTK6sthoYVlM#-4uu6aAAHe zY>3hTocYRwTV0Bo9;;dye`j%2!SWR&(WpY<l)rXkFp<vY#<S;7HmVmczy8giUg=RQ zgv>zQmEG(+TPsvuhKvu(w{K#I-;J5CV|Hg}UtuQBB(a$zW)?)B1~!%=?iBfjkyIJ4 zH?l=WVla|qA{Fm8${4-cc(B3sTtMBuGeuH|>r?T{uu*N54Jvvnxp0r(>PNa9bS0v< zf%QSRdcIl_#<dZ&W=NL9@<HHP{3rIA64YwI*egT@APRY_K}M^{XkeI*Zr&82hM)9O z3Kk=GvwM}-dMXkqcj;<KM{fMB+|P$gZ35z%mb7DqBONYVyd$~z!3W;hcITlX6aSGe zcc$09u_TbRY3w(BoO|cNeJYvSdEo-*lKF;!(&9|UyO!2ovhP=4`Eo4TN^x$~@Hi~8 zyO?TV1XP4Pfv0WdOy$$c0bb~Em<J5DeYOKO&StBr)z=c&n1dbTd&>qRgC*>gDfsT0 z@!y?#m(U<tY7}ng@iXU+9yOdp*+9Mxg`%~7+Rlp#a@;kw?eez@M~ikZ=3|i-TYv6P zyu}MYBK|-uXyLE?9|M{fI3uTl&-@%QtXW9vzNYl4Ox(K`{iBsv<}6nfVBjhr;*4@u zy=bLz@iiczQmE}3J=99k4ODCPO`MQj2)UPG7Cys7CO(8I|8X|iqa|8J>3~WR@2DMM zo@+SR>g%u+cNh+5tJ7m;tj9TKW23!b6=Vk$ko{*+u?pEIS$bzrL0CXZqLla;HSB={ zAi<A{HXp*@oYb$0o0Fv8G;6P#qQOj-)>yGh4AfGVU6>RevM%Tg6nppGoqO==q>gBn zE|?VXq+tB<c2gj+wAN6lfO49RoKZJ`PHjK$wyo$R9hZ{j2R~|u1<P49{ke}{zxLu8 z>)c;sFa4Sip;u1wr*i+Z-`d|s$HW3I;#*<iCYf8av)38OT9!ltH360nkX-<~0X`fv zGlWb*DBwW%*9!ri4#n9sJpqfy6Y#u%vjTxs*|HQVjgLiuVCOLf3}B*k*~dU6q@jue z14XSpctBDlb@b1ZmK?IhPQ#z4EIXP##@<2D73!0r6-rZbh-0i(g+ZhN)bout;nv)H zyH*WrOr?*Odbjz^TKN;Xn;a-TN<NX)s#42Z-S#C_o3;A*{jrj-$D^`!<5%b2e*0w~ z1eBh9le<<1;@_gfxhH<}@j+4zr<0D15h$(S!pQV7uVzt)M^4s~0ALwhu9=}2#v>N` z0ivfwhVf}_w6wN1w*H_|RohtGuT_CuUX^MDPbX<?{Gq-yR@$%C<Cs3AovVF7dr}M5 zD>qsIf5^m0Y({U_SUX!)ftBWJ4V5yrjWMl7rdMfAqJyC@iDp@04CydB4R4G#Bj`9~ zD!=DM;C1RH#&mLs5wM>20^>RgRV0oq&CdY|24gHfi$qb-J~hD9RFN|B(z?aMw2OxF zbdOB&t=z3UOmTxTcZXji3(koTYJIscT6An(V|DIc2MWOu&^D+;y&X1l#$KzkqCC$& zYIkacl2A9`BhBWv8jS`{8(bT^Y#w{=n%rv@i@jd;MiRX56R(%O>)va*3!)ax%@u!r zm#~{o!%Ee<9=$pD!MaT5<X7lKq1m2cgg)6G@E#t@F6)jHAx65RWP^d!8px_JxyVc| z(vnpS5q#TxtWqF%GejF!g=ZFNEk#9IGc3cIoY}&0X0GU2pUVBLzyko?mndblDnr;8 zGsg@9uPU;Rxnc85lhK3)U6B6}d>DP8aGb+`xGcvo^rFWyIUiIT&^!VieEJVwOR$KA z45TBEN@DT5F!Cllm5D)!LO9O2uf+I!mKWuw#l!aTj}o9?ZBC$l4nZUH59OAXi!H1= zk!v77wpd7p=<eNbQL;OWirHHPi-FI*Nc3ZOSY_i|%<l1vrJXMOBi3^rvRT<^hxe#G z)xjK<D`Dp*?5Y8Ihh@NSZ>Sd?{&1o?!P*j}PDbJ~;*=%4Oe!iji58%KOhXr?XaUkX zG5n*;l4<~Wz?6gn3Bhv`hA5F!d|_(c7F1w9jUSD0kbZ@`E^KJ34y5%ad!L;AcB@mQ z0jK4IR-^5||0@V!?c{fo7NvY?x7ptsiO3D{2TPJqmbqjrwffwa+@sr)sqDE7RR#zi z)r3;yKC%~k8~ney|I^)-fHifj?KwHw10*a7kgyzf!V*rxz6VHvAWJ0du7E+JKrjTY zT0|&ys}|cTR;|UQb+>lW+U3?RYFn+gw%WSXw)a+BYg?;bZfmXL|IG;j^xppWdH(IW z&rb|;CUYipX1<yE*7y7U$VU(MK{js~3F+-R?(>{=fSpjUO<GIspkAiPEXtoMNy+j` zNy$n{NfMe+k|FwFnD;^d!lsnjDXf$fD%cQf)UdMrwFW6baK^!5&qVB8g0P)99QTU- zpe|g%faOjSAn-oMI5gm$3?J?h;b9II%5lL=JwpX}S>f@3bvNP^#bCl?h5-)`_j#|J zg|f{&o`e(xj5`8L;Qj+XQ+<MgGsj3^pDBi#<Sr7@$D8Nc-O2jGo9pdM8Yd^-_Sm(Y za6fW9o;{?L2mmp)jx9;Gov|6y6>RTu1H2G_A&WIGQtBI$UhMHokT=WUzwINyCO1vZ z8agKv5bkjkPJKFb4Qmj5@2JRMxq+w_m1raKHC3;n37G|cGTKD3O&%rrvN|81ar?8g z+3Dky6kRcXoQDX)tFljksWa}#i7~w9Cva%Ov5Ea7F5%E%=D-}|LYU~qz|u%YQsj;D zNI)JCN8@lAbDRxM(>s)LF<cDhLK*P_AEo54EfXR*J|W9OAdcRHy=Z*hr;?a9qrpOu zq(?}9D8&9LI0pbjODOS~Cbwirt7Jh!Nq)+7mpRJdnDCVz-u%#1ZmqAM59^%V-_<3| z>tsaLlm`i6jxgbYtxc81l(#N5h;nre^nNW+EpMCUN_pky@B@<$2Z~wjYNf9i9k}92 zk6}zUu-brcXCxZIWV>_Np<RMfNb8J|@h%&|lZN46d7)66495^g#`}c8DAtfUqaqH0 z%RSVAQ=9W0_d}@Tz`a{Re2mTmc2+>PwoE%k+YMRl2DN*&uWLWhexbdl6%k0E8Xe7m zwK=ic7zt1Xy7npBG!#w5=@_^+MhL7yL>Wx@QyC0!+o&Lzt~Nvic3U*O7~nRiB*@50 zkbQns7R1nPSQ>ODJ!8)C|6CqqX3kso=VD>yHmBI&7q&Vavc|~+NKL`th};p`kah9M zx<OtbwIFa*Twp8=LViA^A0${qFP~qu5P*98uxBo_3vdC`iO3or=OOUX#pB%A7?$K1 zXU5vh^M^WNOq~_PgG4ygVWH}AadBho1dP<lLp@LjP<^}0`pW>-x5`n|f$HqAUt|37 z;TF$=Opo!$p~dRETI60Fsq--E16W_V);-&p-O+FC?*L&6EvsXyI}v!9o^m1U;BdR= z2seUadNIC#JoIAHXfHtD0Y8xcFdEU|?^J;1YqPqvMAmMhE^d!j9T^!FrA?-&fB<do zZV#Q`9<8>}fDA-vLb^6epDuAL3`p1O<>@To@#OrwBuY2}JW_AtOtjz*a$=a_y9IW0 z*c2g<(dPvIA0SIl;FI$9B|IdfI=l!kM>G@OD;=9;VgkX)33yw?Zo{534=i8e4~N$| zs8aFa0xO<#HZuB|=;)o%a(4K);YzR@D4$Y7#DG6>sK{zrzQSTHE?TPIsU~mt7AD3Q zMTXJwMgBE4i6Nm0Zjj9v5IZ7WUDYulbaFXv)iah(tf`*3thH*((1E_&m-+;p3-Q@n z4NV1R-a1p3sMUoeCSn?jA8I47ayG)KM=<p9IS~u%7}HRCh7(Pmv3~O0pbj`9W9%?A z2)|)AyKDPv2Wv^HmLSmNaxW#bJYh(nUB^9wk$dt`GU1MqrMs*8s|Kq`0!=FS(hRR> zsISKsR)(q^-*FZh8LEPYCp#J@Q6{d#y$n`ZJ6Z+NYe@~Z5nJrQqrG0(99xR*v8!h+ ztD2|y7e-ld0(P2Z!O-{_R)T>R2*Bw98Wo>}rw^Y#arfyr?9%t&HPC`6?Np^ZbTUo> z8Xpc0XO>}Ud#uNx<4|yX{y$;k%}bKS#&}Dsr2YVL$njTL6mWQixQK@W192M53Em2x zAQV81Ag@#`B&GZ>T7=o5o&<o?yMbm*Rw)hOlb*6#Z>dS{&gRHG#(DTm^;U3LzOpKr zv=UPz_6?}wxdPQ_7)m<_3A`s`6z-`dKw`B82^geqcpqY9VO}QGh4fLFDv9+(K0~?1 z;2-VS*&KCpM(X6D{e*$3Gwz-`ijg{JA!)bH(N1v)L(=4k-0chAB{R^Bm%)&CLz`Tv zCA5;7%=Ai~*-eKU%Hj{2H@C=jN`GBMu})v6%iB8BWXQ}GBpTBNbp-%1#0w1eiH2C2 z44efD@G}oHvN+bhetZ=(6<87nu7VN9fv*5z9GiWen+aC5U}+n)jX)_JCTHcyJ~PUA zj^Wov#COIP&d?5KE*QC;;W6L>mpa7uB3E`8X!?~;D`f=NJuI`tOAp(R@9ktrSLC62 zFCNe<+yM~QA;^m%<rHt5w656SDdlqs@pwWv-baX~d%j!j^D)qv9~TSvoW`Lclibb4 zW8zN%U^Zs)0Y~`D02fb=%Uer8%D;J5A%RqRBf@`wii?XF<X|lJ*Ak62?kuhd+;@jX ze#lLI=PLIo=OLJhIcS@<P74S>F-dW8#euC}fq|{F`~zECTjw+sj}Mf(&(TlVP^sr0 zL^&JcAZ%%_crH<3EHb1`GEUuZD)m=*8#+7UI!fUsZrz`f#+V5$gH7PQ!8c;}4cH{G zQ7rya+!2RD72E_tNA$MjFxcxc6cYh<`bo@ofp-jy?&%)y8^?3Y$XGmV?SbIfd${OP z*I+mZuzd%=oU`n-rUF0h5MMdqC=BzB*}-8E1da|3Gkr|t0URI0%*in0$oQFq#tthO z61hiRJy-%C4kdEmRtxSRMv6rerHTn<o*aPU*YFjJc0X+J;q#j_GuHY=3*`c$Oh+uG z-=tGqNRgK`WJTy>2G%TDl~gVev0Op|>;X0DZsiaN>U(RA*hTVKRBbXF=dP%9(Jx{g zM*QQnu6#a=#SxQz-jK-2r``wRZrv{R^$`<O+9JHz{P@J_^NYM>(TPG2f4{T>k433I z3JrJ(xw1;qqK10ae(rNIo@w%(&&i$aFHjBIuT88BI}*l94kN<Di0UxHU#w!+m1Y+l z3H>;f6&flME%sUCbHIlrea2U$6x61K&d`4fnt$vSnjIWgI7Lpd<O{tOg>tPxRwx%0 z%4SrEMB&*2Vo<PG@PXi(;EsTU4atSooQ>hnf*vSb5>AJc;kAi4paw%1Oqyi_%P<D1 zIUOB6WmdEe`;c}?E@(79SEoz@FH%jM%|`;k1)pbNnE<NWAjZw<PUUchbj&h7`jcVZ z@gPDWJOY*=%&uc!XS}R}Q3MbJLk5g;F(DJ9Z-GpK<!Zn@0AxaPCqLLl4X)e|=efJG zT*B9f6XcKXVo0bqaZ1tzahjWg%cTW|YeP>(WU4%bELhFaNzopB(3`kNsw0URKib)c zAS=X&?pz~F7#Ydu34~%dme3^&APS4Qa({aOxXwoj2qN$zA?CVql;Eu<5sC?SPOKQ3 zxkALlmJ290m&xnoO_UB^QE?J44$7ox(UHiEvZ%dLuSbzlRqfzw&aY14X~XfLlHpZi zc{c?1xK{gM-?PsqU4?PQzX_0~E@U{}l$k^KUe9DkWC9VCiO3lq3cMdOL**PAyh_OH z5fNUVfHSR3ZSXPj6d{3qGt!Q&AG)QGx)5xxM{F{SouA<NJN|Dgk3+~Zxm~<+c_KF< za-w|us+3?q???Gz#1eh6JIhxd8cM?7`Nb06yhL|+=KP^9@>Ot{*JGq}QAJivP-Kj| zQ~}BUTovUR396WUm2Xvst7~o$SFk^q7ZeGR+sCsRjuI0O#0qGRLsl>iCKQa|z~IO@ z*bG?5nsCO?3D5KJrVznAI3^rWx5EiQCnbZHoq1|3fin^}b1pE?{wnDcOth&CTu2_y z;e)c7<U|=sRo!YAp4daI6t|`mWNaSz_lN-4Xr}994?I`Yyo}t%5w=@0HC4P4o*=3+ zEsw<xOSx3B&BRs6=J@P#Gscb&jdYO|sNCYhWg<>N+0N#PvH-B+_z`xpn|+4K0u>5* zRu>?T1>9~iA?_6@03=n~O9B)xfFl6HQ{2@Hj0Yuj9C{1SCmZWOPj(OOdtqqkg?&Rq zJCnl0l9R*2lgMzmVoLEfyfMWk6CEUneGM|i<Y_~qr$`9NVhH2b%emgUQjaxRS*-5( z{&-gWn$Tdm$Zdc@0(O8y0;C?W_BdAKlf#E`lnR5>I*b6!=q+UUTpTeDVTW%<lY`fs zb8#};EY<}LZ?r&coS{hvrbvTbcwNEs`yka0Xc5K1%R{#v<FQ2|ksqiF73wSw3;W71 zt}(N=554El<H$FK$--08#Bx0$%@;%ngu)mCM~C`0in)BQK**CqU_$}60s6uSZ)9Hp zPfj)XZ^+%ey1{*H0g8|5;%k)t!NF|b0T)Hw02_}pc3%Yv<?so3M&=0}sAUZ4Fcji& zR2?}*;Lw3*hQ|Yq{TK@_x$%+NFTUQr{L7aKE&!d%BmvwQ>3C_BS_k<H#S?w{s_KXK zq$!nY84=1f){8qT^bIYq{M<WJ8k8H5;llUhh`{9PnyH@=nV1*}9>p+gK7i6%#Qq&5 z$8fE?6sagqy*QTTeH5Z-<U#=O#HTD?8lPM}F8KuKV8ATQh{*{kpRu%z%nn}d4o#CI zhNehf-=_@frGgg+iMaJ?6Fp+%kH^aZ;+6~!&Mfq<C)UThlD~_+3Wv^Z)j=BI$G0|? zOSmGQmpm>_BJcKfg}BmcNL7O<Vjek{eI9#fp#(Hl8?SQ9jxLLy5=}-gK~%d;F62gp zq9kpo5zd@hZt8Y!qDm!<h!D!*#SZpR#N&xLfg@>f5DiAYaR*@$ENnR14j6@zXqrhQ z;WU&34b#Ef;km$P0H&~e;%H!FfMVGC=Wd!mFjSjK1+r42*R-r((YCr=Mup3$p|?}x z;~-?v^}aNJ&sdX=HNP)EnNS##y?w}JrM@pKMwK~lda@XBe*=SPVzQF<PzT6|X85OO zdw~ju1+!!!2iYGow5HO^!n;sB*Cl2_fF@2ZXDbJS6>g(+h9zJ;UjV)21c4vc!H=#R z95DmSee}uhqO!p+Umm*oC-mhYz@bMmg<(n~i+%z63eE}06!HDoBC(w1mYLthP~MV= zqy!~U8psZQcW#p1<Rq3i0bxKxi=e~@iCF@24$B*3YBMFE1tc}(WGJ~lTmoRXq=1|W zB|i?Ac-^@{c9Qo)$?f5iWbkR_ke$%-1m|7wT^q>;C;>F>;qM~JBC;DwCJmQRKvHwb zsZcW6S?A6*a*(Wsk}0?ZvF=>OS`5g%GXo^rzi6A4{)DeT(bY<%w-U-$qOPc@&|HY} zbBX9&BDXamLX90JQ&ar`RLVbtmC<V5?XFYoX`Kmr545MXwR3j=Y(nf-*s8VJe6@uQ zd4s8enS)w$L%DxooR%dU^z^-3+j07Y2L4GP5b|pvO^5CyV^ryJiBWQV<tsS?^a?;u zz{sA6$5+nF6AsG&a69)ZLGEH`2?r%OIa{ZO+#!!JTn%hQ40Cg@o6TK2FBfuTdU%5R z<ezCwzA*|%6(&v7!HkU4Y{gJrf!>oLyBZsESB8Wv4e3vE;mB!)g2f93Bn-Jl9_8kd zqi9k1OqOK_R~{g5n@2S&0j&5)Ukz5M_>(_!c>y2{2loYqaakb&_XUK;=$3}^-Plc8 z*`8|uIRQ!`TLH0{0d_wHi#;%L=%?G?3Rpc(MGIbE%+Js*gwfgm;fI(xTm-4h5eIQ0 zw+<ijh6~|rbwRF>?L&+tV9)aaG-<G_fQH5!sM{BCuN8m=?hn57fq+^b1n71lC=^z3 zIC#cHf`4Ze_}IsQWmE+|Bs82M8texM*778j3|5p>(4D4(4@M?LOk@M@Ne;>dzil1x zHu<1aD?|pc9FBt+tP)fTxdDx!cPR&~<_d_#twPnnmDi#=z;v64CZWlIXfqYnqXyIn z2v}yo7MhNlkp<{_Cg5|nqBcOqY6qlM8|nZ`?*uH0IWP`$(LBHh0Tf-d0ChvQupZQl z9so_@gOGQ8F<OF_qGjkIv>fzJ52Jpx5^@thiXH>a&uTP))<AxrwP+n$kDfpq(35Bo z{Gc|W&1egH3O$XsqHSn9WVYLhcA?#nbLAPd7d?xfL(iiZ&_1*uy@(D#mXMdxE9h19 z7xWrBh+YRTsyESF=ny)Lj-a>EJLp|>6dePsgX8D~dLMm&PNEOdN9YtfjXp-7pfiwn z@f>KZKSdYNXXtbAJo+o>xxYjg(Ivn&_!?bC-=Hh#Tl5{eihh9o=STDt`WgKKnaF;< zck+p0+PJs;|HHLQleN><(b;acS*$k40};Rx5b!6wy>O&0WFN;rUhZ_Smn&BgwWx5> zZ>|7`zp>YIi0<{g3BIFhH`;~EcYMO)a1cF}E5v|@L~k;SU~ep^jdaYI62Hv>3;lqu z@v97IvID5E1*p;v?=1YHsk_@_OUNDX4vZVfkG+0lVBRaqU-)e76=&1EtT*7TWO;cm z-S^?LZ?+wNE%BZ8E0!D!JZ7qT1VCS$eI?k?rJg6%fi&pSD%nC$Srt65$uhl-s<3r- z*r`&peU8;OQ|(PlaRrg5o3jFB5^ZZ#sblCU#|I(K52y-DtC=#{>s#9`ZPO`}**4qK zXr{`oR=YZZ);MZMmzGh*hMZhOv7w@t%E`;q8!Pm>7%H++nVL*Fn{s>y9pLSnnoK9E zHFPo!KXq`Ks@BA-hcEyAAE0M&?3jb!0@<?y#(gQPrw5%<QP-RAkBL?F_&vvcew*lk zyKD7%)7j38N8_WOKmDs<Lc-5iRt^bVPJXJWd-=rWUza?$;f=*%-*weUI%eGW-Yn_u zw`+b??y8wQz`h;Z;9k??cWl<GkArLCK0fZn=}UTL)y{n-MOS`E58hL?c0te+EsNeL zDp)gP-`1p$ZwX>g?Mqz`N)_<MyqhFQ=vSKi6AyB-KDx5-kNF?(_+|IpTbx^~GiQbD zh>rYXxu<#QP|RYYziwT_G52i?e>rf_>%fOqYiIHs^lxu|`g~$HC-`$)EPD}W+x-IB zV_tdJf0LDb!h3kVq@`v^n7HQH(!np-?N3B?)j#~^H=<eVw!hQVkej)BRj}sq;HArM zPUDCE{iB;ezbD|G1a4oixvx8)cQxpb{F=U{$MTn~4Ew=r>ODRF_osn>NyNL=5p<Yi zbp$vUz&~G0&gCll)8+bKT4&BhF8qf@?oNww$9SH6Lz~@fYct#Fo(*GXfFbFJfTR~= zlHOH+b>E&9D+^X$*yldkazWVLu#&4j@&279kK~^*q^-Jgnw!00&*uB;zW@DJqrU7V zQ5$`2bJDI@!52STBX+rtpUO!r>wdqY?Bs!%+_R#SD_)v>=f#C5FAnVM4mRXUT24Lw zEK#-P&<Co)v|qZn*K9o#Z2oHbuKS+&%ejKw<_WP~xA(IMa%|^dkHZArI`xmWQ=YQC zaB6;gbVEphjvBu=MEZ`M^}FGx2>Ha_i)JPAqkrxH{IB~5zIkZdxQiX{778{zd;X#G z(npVxUkSphxR*<xDtP+C>ip9wReujUaVR`JHca#W`Y&JC7JPfQwP5yFZ_r!B3*YZP zo4#P<@2jKK(bAjmdR_hO*(;Sf?fJ1W3+P_KR(Ojyk}S|9OXfBWv_0_b$rlNawheFW zGtU~^V;1bn_3D2d^*^7Xcv|fsov0Dg$+Nb$nr)4i`WDJ$ZL-g)x0xwpXG4pnquFfh zpz?B<eKmznP$%JCb$DOJmzwy*)Wp;}x)+=%{<k}!&Zl*bo@dUPGe<QWj-L)VepHRt z);OEF-P&QXTWxdW@{A^Y-dJtzDym^FRc>xl#o+TpRa~LNXGW4bi_UPglc=*yx7gvS z4LT~XrM{zsil<_!5=*1a+5zJ*Iv7>;EtYBZc8j%*nypcbXaT;T>&dD#sXb|Te8Kk= zR@Zkl!!c&Jwy7nw8!qH|^2*KATCHu<)B&^~E+M_7qs`|*AFVc~S?A}Vi~gsd!vIrb zryZ}NUcwbYIiJ-FW}|&8KMLPI?d$KPhwik_&nXlBZjGAtzRJh6Rg?7B)6IWNylwC} zJ8;YVfys+H$UZvn??>BPSABo{g}qVqI!(>}FYcHbHht|IU(WfK^VPMB1HbJN`EGqC zqp$tT8`g<sT~=|qewp-)`9eCyxtO`BWlfr!D9rO}(0kOwsq-2h;2aH+-zwj*dqeTS znT*n!%-;Dw2okIIH@}gq-<+=A^2gcLe^kB`vwh1UW!d|`Ja(N7od2UVZO4tB#s@g9 z4c8y?T#|C`qMuvGn_TTHk%zuJ@#w5~4mLf%sUr9j(e(RoES|e`caw1E_?x$FLAMr7 zdi$3mx9@A}LrP9Qmp1LMo=;AG_rca;+1^YZEaWY{oX_Z9&N*gw{5{z$8qp#cbbm1< zDP?gs(mhM?6~XRVNH16@nLlvp!@S$gkN=!<ye<7FQSYY4|AU3p%VF&Uu8<DGJz*2X z9kw^^MPtryl-HAiFV;c?vkg^*Y%UF*=W6L*cG8$SLVRm4I|PaYH!2rKG~4a%9cgiK z|6*Zm>Lp+5=_U77G+R2TMzhUsX|god+s%}PSumIw%^i5v*vw64o4Kvg97EN&O`|OK z4yv;Qs&!BucAKTq-ZEF%(b+J=+-Rrl))>m(Y#!mnsJxMO@p>`Z>KpBts{=OAZf-TV z*{MiaqDmpG-ws?st)k&eX4hL<>Kj^cPwsAQbY)ZZ_B7$2J!m@awLZ2Lnt^&0d_%0w zJgd{(Vein6-6_&3t4#=1ofVyXpo4#mp)`r9@l>9*9vIr3*=AJ?RbuUIv)4nfsx0O? zF|Zd>sR?vKys**)c+l4Nxi-u6W_YAVB}8T=jSPaLIf}|@X`#w-jSkp|I)J}5Pg7BO z`tph#L#ePjr@TC;w8Ee_Q96SuuQ<n0qSsM5rMfZvZn2@n0PL<xh-;S`N(<7cib6eA zY0^_=`S7Q~#58BfH{|71=qb1~Rg@d@DvE0<Q)O<EKCgnRD8si1tMugtlcAt=OnpOH zDP=6r$*VBr>ES+TphRC<p`w_tFqll0@O@NHWkq3GIq=>>XD1zB2~R*7N{q#Z;XdnY zjOBWhi5h(>7=+Ti;z}KEWwcZX{Vvg$=M}=EJGuI@aw^|YQHpQRhre?uV@^4As<Jqz zoHACH8_P`k7-nFq4aLP&X<3CZSI-Pmv7WghudLLhA72TbH{=w@z%8YQ3PaWKJ;TFI zmBA>KQ@WgzoC3W`MVa(^As$M6Uf?g)>0wfeO)%1VR$yJ)V9Kmb_tN5YO9yZ@=4n)$ zwGES1lf^vE<X8wfc32q=ov?s}=KJ7&hPY?fw{)7Rj^=uxgEp(3YA{ocR`_Td(@1>> zRo~dyiB}!aeUsJJ${YqlxC<XQ@HIfGcx@SSRKhJu3lsi~`p2GsPHJzlPPeM2Tbk&e zy?7^~*gf0mh4ezMXzHRuV$lsf!6OJLh~)A?%H(ih2bKB#Y5Oopbi+tZ7F|V4W%tN; zG%zcKJkz<LB7kpzk#%e=%t<`5r%)}H`UVx%Vu!VGw-o1)l4;qPole2#)8G_#2mXyc z0D<qpoZ9N*&2uZy+b2F0_SRPFddo{M%+H_y<lwwlW^oIp9_HhdlsCqwFP-(=FJ3A4 zo$r4}v@mJqq{1~vP>Rs>x;FXFGS7%sRFLpnVX?~g)7z&O+}2rx`#*ei@Zzegm+zpX zZ~b8NJNE?H_Trn3^ELPB(w}^A*<2k|R}@x27a#y>jd4-Vk*!I}7&UG<bBn^Z(%d z_$SQZT}p$EJ@3-KBQm>yRF6Ga*uaB~9y20F;V^nFqXS28WUD>clH@EG<7-*d$}Oz& zjO*x46WucAb{F+zdg4aSLK^gGX3%-HfF`UB^m8WAkhOs}f&%?oF8t1A^b*sUYb$(W z-xR(u6w}%8Y1QiFwirInKDXUE-B#b;JojF9huuq{?ws4F_g#vfzwR^kQc4tj@V>R$ zn|qS?Q<3FWsa*}ZPkK-EJU8ds)*sGDV=wwfU0(l4e?)?M$BvqJUQhpgvL<lGds|is zPbybx-_NR@S2X>tGt;AfMZ3%=3g%q+`lHK#e7*OP-_P#8)KzC)^qe+Ds4f2DRZH9b zH?P#3TC85?_3gPSDLbO?kA39#V@Hove`PGGGhSSm>Ul8W`YB@fbKmDb{o5&NewX@Y zbllmxwT1hRxqh>A-p!Aj)?T0C+eLXC`uXcAk4wVNH+MB=d~Sb3vTj#c-szm>u0L!X zJR5Vvu=Y!9&@<bgu$)fM?+=N6c$rxHrse?a%GtDai`<WG4f?J#_}BvvR7~E~OPmCb z@A&9Ean-%VYf$tuCcvJT{_SPkKNHdKCgNJ!XY>(CwP@smM*s;sHBthOS`7M~6gpX* zprI3z)O6iHknpCD-rJ)2gMBb2V`5@iSH-=OD6oR7zK{9anuqxTS1(=4&=?OrIPTZH zS04y^^4XnDZy$TJGF<u7o>wmh>vZqsueJ{~bFUcBJ*TE3E|(cg8h$H$T3P+oOHbKf zqHb*F<cIqmeeLauJ#XB4>gX>^KU!tZzZTuH?qb2Cx|{t!iQiw=g`Ntnyd|#x3$^*{ TzRu;@uA5vnpYa0$)f4>(sxpvS literal 0 HcmV?d00001 diff --git a/form/src/assets/font/BRLNSDB.TTF b/form/src/assets/font/BRLNSDB.TTF new file mode 100644 index 0000000000000000000000000000000000000000..e5f34b2f342ffcd820a8a0956af3ab36bb1f9e1f GIT binary patch literal 96852 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%0Ag&DuNO=j<Rh4&Ggr{7ciru0DfZ%@A@ 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 Z?>EPL{t*~_Pwh-%lN=@Tekd<P{|li{yWju- literal 0 HcmV?d00001 diff --git a/form/src/assets/font/BRLNSR.TTF b/form/src/assets/font/BRLNSR.TTF new file mode 100644 index 0000000000000000000000000000000000000000..efaf22ff70a2b17519804a3f616208e73ff5896a GIT binary patch literal 97284 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 I*J<W|0RH-Uvj6}9 literal 0 HcmV?d00001 diff --git a/form/src/assets/font/GOTHIC.TTF b/form/src/assets/font/GOTHIC.TTF new file mode 100644 index 0000000000000000000000000000000000000000..c60a324123eaaeab58c400c139bcabbc6d0d2a9f GIT binary patch literal 137568 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/font/GOTHICB.TTF b/form/src/assets/font/GOTHICB.TTF new file mode 100644 index 0000000000000000000000000000000000000000..d3577b960846dd2a9d2cbaceab7b8715b3c5fd54 GIT binary patch literal 129676 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/font/GOTHICBI.TTF b/form/src/assets/font/GOTHICBI.TTF new file mode 100644 index 0000000000000000000000000000000000000000..d01cefabe3f5aac0dca611b750d07215cfe00dbf GIT binary patch literal 139084 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ǭw@ySzFLM-M>7o;8oI+Tk6Y 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 Y>+`?-?jY~ubz$tFwr$_QHqin91{%X0s{jB1 literal 0 HcmV?d00001 diff --git a/form/src/assets/font/GOTHICI.TTF b/form/src/assets/font/GOTHICI.TTF new file mode 100644 index 0000000000000000000000000000000000000000..777a6d87f5de328998284ce7c4a0df169a6474a2 GIT binary patch literal 148520 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 SFRgxX!N$JBk~XdQk@-J>4CZA3 literal 0 HcmV?d00001 diff --git a/form/src/assets/font/MMTextBook-Bold.otf b/form/src/assets/font/MMTextBook-Bold.otf new file mode 100644 index 0000000000000000000000000000000000000000..8e378d817bec7b1acd2a82cfeabcb53c90fd5960 GIT binary patch literal 11496 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 F{{!ehaW((| literal 0 HcmV?d00001 diff --git a/form/src/assets/font/MMTextBook-BoldItalic.otf b/form/src/assets/font/MMTextBook-BoldItalic.otf new file mode 100644 index 0000000000000000000000000000000000000000..04d6fb6e1ca10bec6d4df267184f8179b9ba1468 GIT binary patch literal 12340 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 a$RL#*-imB{N0fwjBfW{v1lh7o=>K0BY!pQR literal 0 HcmV?d00001 diff --git a/form/src/assets/font/MMTextBook-Italic.otf b/form/src/assets/font/MMTextBook-Italic.otf new file mode 100644 index 0000000000000000000000000000000000000000..05e5aaa409dc78ee5c98167653a7ed18eab92b49 GIT binary patch literal 12148 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/font/MMTextBook.otf b/form/src/assets/font/MMTextBook.otf new file mode 100644 index 0000000000000000000000000000000000000000..f8ca9b645c27bcd4bfe1f351f4ff30f4558e302f GIT binary patch literal 11172 zcmc(FcU%-#*Z-Yeb_d(4;25(TXRt?6ioL{Gun>E1v7us#3J6Hu3fpMgShj(HJ;o&Z z#7d;7V2{RViczD<V@;ybBqn$Ez4-W^S$Lwq=gsf^{rTJZ%+Abhr`&VT`JOv7ea@We zs3p=OF$x<yX7>0|E2e*nP<RqTXkg5Q31I{8>>vn98xZQ&efsRk{wrc9)*wW+gZkww zH^wFXRMuuOLXzcBHg;`%+$#UzQW?~J2<PCnP(T-pp&s3Zv-{eOsTt=ZUz>zb?}yOd zyfH2#39Xy~Ra7wiNfY8W#+RqfRKhdR7e7u)Oi6ul6!nLy9Z(;JDEJq@?wuZa;>fbL zZ~cM9Vi*UZ3$r=#%j=8z;&ky)p(PRtrSOA(;#n`=LubWS;Ypkx7%5QI{1=B1@Uaq} zM50cV4N2f8U$g+8CpTTGrKmsE7fO*t93)%>ief<x|Nc#wKY2D9jl#aCnrV$fd!SC> z8BxzfS5O!n!mlGG`-}c)cn-9H|CZ3Z>0X3rG^zPsj2JYt`9A2CHWD-ft!^%tzEV!3 zzG!Q6c?;AQU2MK@g<eNDo9|_TdoiMdS^#}50!;?)Db#`5+<Y%WGAgh6UX1!s?&kZT zSK3HW8g-(%T>45mjTVT8G?%wPtjOAY-wO2?ebjs}6YkRnL`3%ui%Cq%OkTHUZEDz_ zu>Mg|gZuT5itZowPQvQMDT!;=t?Uc8D<i_jY}gPsOK6o6HY+|QJ~=IZRm9Y(bK)~n z$0jDOpB2Am^M<%&7%wVngfJB&Ue?WvPfl5vm=M-fIb(KMR8(|C6tr8Ln7T4CAuSA^ zA_fc{u`zCad}8YAhz;vjL`Mvc7&L5f)XPD_)}@5Sg{3CPt%~0mm%KhKarJ+4_#X_f zO-)T29vPXQo*uC=E_Ln3I1nXbW#Yz2l!gYN2owzy6^3F^B1%G;C>gCoYtUMh3T1oX z?2n@07>xP_?xNv8484OAV9FEG6gbyF`;~zagwmBTUKkpKHoy^vX8ko*O5iCTrJ#7A zkOu#&pygCJ=D>XhP#X(lC8G7vCmzP!4E^JvWfOk_2P4n~G#^byv*GUV`ppZBoB|XR zfse5Nqvs6h6&8>q8mJ1R3FEDWmZ`w8&^`_7o9ZH<=TNBK2=v#(m_nP?&}##XyduzM zFgy)H!$2odf6GZ2v=roxgEJLmhyz*U1LGybh+#0|YWV-(b@;#63bT_6vo#z=!jT?0 zA_5drK`Mdsrdf#yNVgH%1bzWe0n0q3dG);^tbo9?6#WS;T7VkhIq>`UwfXV?a-jnL zCkVWh6g)*RjL;IbLak97B!d;-4z))iC=_)7&(RURhC0D&mm>vw19e6$;y?*qP*>Cq zbw@o=Pt*&&iF%_xC>)HbAE-DI)GL_V05lNPJs1svX&DA0k3essk?3tS3cS=9Fq;@O z4vh!nn22IQsguA&rogmJL({>L&IEIs4JI}h%>(0EfEJ=f=v}lJEkR4sG86<95O5tF z@Xu=W&G*!c7f=!gcj(277eBnn3yb?pBZ3M94Z`omA>iw8eiRB4A&R0}y<DxrV^6*< z;yY73E8<x(|5{K18TntW{8uHoS34Zu7LRHFk2kvhD+C2ml%z$>)Me2_2f#V#Z=6xo zu>V}@{|{#blS_pyr4S_ryFe|5AP8w=JEQjzWunkZ;1zTr1>HHR80x+#U))DLSL_jA z4@wED3-U`?$y<^H$uY@y(qYo0bSFBG{v~)o@P!tGTC8tzp(WQcuH}(dU0OYDJ)`xN zHhtTu+FX^%WiHvRwxYIgw=Hhl&@Q5#s@>)GUE9AO(lf*x@_FcMq02(AcbMLxw8K4y zWo9vj%s0%B9Xoeab-e#t%xil)1$SEB>Duc(UtjY2A$d!AxO|KJp`yRSsrc=Ufp5Iu z8FilA*~NBXE$k0mI9JG3hKa+bh8^!Rpo@uLDvOhm<ah5;IOGd4X7THcw$NpCD_m}y zi*xZsl0te{mM1eSQ?-fBr*Ay($m~e3OioTuOHQuH*s-Icd<P5t`9au6eR=ry2{B&5 zPhwPsPQ6p%bUM6+oD0WGis<remoihM$}D6_3lbk_P!eeHN_~nkQ&q^yp5d`4@%$6i zMShEz7jI_Nu3VSPUF<7jcj9@H-=!YA*XuEO)m*rAC!R0)N$R$HJzj%H!wr;f$Kxdy z+N~+pYIO!>9-B-iO2}C0jzF<TQ>@Wx_07fIr5b};rM9cw+#_icnJ?)B1uC^lD7Y)# zMCM3Lw7MkM-9&l^kj7&J#UJ4U2FBb4wDB0J?2@{Me{zg^SdZVR#*xRx_@8P9cX3?2 zQFu2P%X=LmXb+3G(l^bui)@pFGYUO9ZiU<JEUjLHDH87F>VRFFMy)Yw*!lEGJ&`UV zGC67ec+-#XvE<V{diuoLFS0m~IlDxy(CGA8i!PHO+$o1!Mr+(gkK1i?vwX{-FO$DZ z>?x03IIpXLU4)-7i#`1hUX`D(I(^T<%J4rI*WleX${M_@CgkcFJpT-Cbp|gu9g0G4 z`};0tp4Q*}<(JuadiI(*;LSHr^?$;J)-_JVjm(o%cYb+1^KP$Rv-<abvths!&Oxp+ zd8T}mNv`y1eNLyf#Ln_ke~hHaT4=G#z1bz%Il1N>BYW!kFlJ23wX<C4?X%mz`Rc3f zqo%Q;b<<Mb9>WGk9-H#@IjH#Z>usZ^O-&s=nv>y?@7DNb)ghnO?`*&e8*pe1aCeg@ z>lwYnk>^nOJRYCj>@YaE-oHrR|L6nU?vmU>mupJY8nrHi&7YIfEp;PF!l|9UIr7=z z+wx~44!k{T<chF&Kbl=Tn+<L3|L(}iBv?+`KZ(KNKixj?`7w6&erER4ajV8Cx<=PN z{`q3<^}}4~&C>JC;@S;IK9OIk*;P~XY0|hk8<YCa2OHlGHeO0SJ0r%ye{12D$`WN_ zUaAh74ko?*FR1Tp#P}o9o3U9ec59x)VCN#9%)@=~AUPg%9QS$ngta@0>^8a0Y&B(( zSm^aW*^VcW;ah|u{A<!FoLMctNy3?OJOK~K+wpEP5f9EXn$1R|#bDQS4|<&-eaIj= z890}ONA_Y3db7bOH(5+pRyL7ugU?bp9{8>1-(d8%V!cb@+*VRvY<3uJoYph{M0VL$ z>sOvKYj8;sEH8P9aa*d<RFG$4vkmXOm#Pc){aIkM$vwHHshjoLYD1yX+l5UjnfhUt zJ-E<pEHo)Hw3#ZUTj$Q>%1mFWx0;k$^X6*R!6uVQpDS1Svddh~Vuy__@qKjBRpH9m z7h9|hmf=PC)=>&SJu3G1z_%EW-Q{)}TxyP#;Vn{6zRs>uXkld*a%2nHLTmI|t;V5s zb9f6WlWOwaAcecc;V$HG87(6vD}SQ!ln=!Codl*xUue+FS0`*-VPFmUc}9a=Z`BuD zesn)Qvw2S(z|+(eU+V6XGAppu%*6$s{|_!2uSowQDI=e(yifgj7u@1XW=BQE4#D%K z1Uz5*c1{+#z`uvOgd4<PXqh}iK4@N9oLf@tw0o>9_WCzSERI5$USEz=mjmn8z{(aK z_s5)|o;C1HgBbs5Wk}>|91Al$d_RuCkvM8Ui6O(u@YP@pQQW*B9Qy?xjCEKu9uI_~ z*a>7H(GcBbG8o5lvW5PG6s|oj#<huz(x>-%eGVV%&!fFchf1l`t616cQ~u#6DBSui zzJ6NFUs%p~?OvbH;8k&rtn}d3KXB_m9|r&U-O)>r<$sL)k#r$62^vbe2!r`bi%W6K zJ2lsSIX8L8nDui8j$*q+lJR8jOnGWq)*e>&Zasc-2Jf#6;WJMspMj<NkeBlvnb4>A zc3wDpPmY;Br@_%j%<Gb!RhnH|Tx<hRQNQQn-Uh|J&t{E?=r(s0w*)k;R4N@xH&-Qn zfMs(@n|>2Uk~ZPf8ZK|*N=&)dTt!y8GRyo48HD5TsIPy;p}5tM%UyloEw~1Xk8BY0 ze_)Pr+q^!n(W~J|7kpFdRe}5}ke}QnE*h8c&cD2qOO=yj(ivIeY4k|+YO_`=PuY^a zi^cDgVN#_Rbm#>g;$gIG$w|J`ah!dM!u?L*ug{42t^SdW+YU-L2y}jsre$WQaO4`D z;ms_y*@~<-_M-!J<yDH`?@l8fN&CJrQBwvUIF-b?jCv3w8-AO=AW}R)5aB)^gx@0V zzai2&3)M;S9NtdLme=qR_0*qd`F1c>ZTOAM`a$N|^SP_I--VmsUJmxU?d}q}N9$D0 zBv$edvYmuKBNXn5-+cNIkHB1CEF}sHOX5ihgInCbjS+5fC6WY@pz-}+9)jO~fN56d zAA6kotzL{jvoq%0{9J>4vp2`%_BaHCP4h346xj<M4tc5Gm(DguO4nwo)^cPdo$l3n zz21^a77yh`v}|szfBMOgN9PkSV1Gkk;;Z;i7^STQB0j|7%IcB07n#6?UL!60O(rd4 zuFd^&6&L#Ot?6Bcc9RdhP1@nN@y0`V%x4&p;BN_C#U9!7=-T_`!PZ6zGkj!U(k`O+ z^_vf{^yaxw*@J34ZY*gb-^34L;t~iNxL|cKjNI;`;lKy-D;JJEU_&4Na(2ct!6XW5 z`7X5-mN(!#_r>^UT+0lOz4;Wke|+zU?=Oz%6*hv1x^uh95kYpn9%NU0T`otdjm2~L ztCAu|p~Eh(RJ&CMgV|(Y?<S2tAEh8N(v}31ND_LlC#H`c_U+uy$;gMAd-%pZ>W6z` zJdU6HKLJtWprC()q?C$u07(_wg#eQA<J2@h`d-N0yQ;mQxV3n2E>j3j%OH<W+7zb~ zoEF?0z-h6e@9+9z&#lwxdsZZ6rlh3!Ht*&_*E)URy13A!QhrH*W|J$**xm%f>aXy% z)Twh~-taYJwpsJ73QuuKiNoZ`v2l%EafU?eFj%c}o89VypxqTGNSrn+Om|6ciP~t) zHyhbTmaLN`C{^j{@^oMN``H06nQ#P;J4#&^9AzJfdw;p>R~;pPg(L|zu7D$NuF(o! zTNdDoHvwB-T*K@s^;T5KD^wK;KA?uzNi0TVp;4jE)#<=jJB=LQl_W^q2Ac`On9-!s zvyELzh9t*mf(g?(b#5!*4Dj9t!#)1zBOw=Rf4lq6G2G(>X!8*^;F(O8OYe4jic8ts z^cDQ>K0H8<TSZ(3#}+Y_NMkZQIxzQ=3ih+YFTc5?xN&V^I0vhB?%HU1=(9?4FyQ33 z3-C50EhV`;eFs?84&$*uY8M{CXAfhlI^<k67S-Wp)dlsqMRh0w{4|<R!Yi0{AE)m9 z?J2Cfes~;sp%!E+SxTb8ZWfTG_;nJAv+%;FxKFu9?NaOY=3E0icxJyvy%b~?tcTa| zcnAWo<IZ>@?twcFhK{mv(c{xK)?F@3skMR&tvy}?6KJJ9DyLebF(}QfF+p-ZwSPgb zVszL<GA!);oUZ}2jlQt|z_wDMISI;O-d%q1#{EM--~Z7zJtbiinNMgCr>#A0TN++l z9kQ2y23p(Ce{W+{HkYA9;qkc2toiml8%G@eUXq=<OizX)Gef;e2PQ}C&$~*@`h2}n zp6SW)xLkI(mHkq{#Q!BtuV%;<aBchmiR@s0Ek0U}%WFfvYQQ&6CDa3rXZ!&?jk&Yr z8xmB;hVnOxYj0kYV`=`IXL~5feCehP<wmaY1)b=FxPsS7L!aTEpFO(6HHH&8W6mqG zaQFa@rtf0W3L@?`X(egFk+Jwk2775sQIUnk(b7=<!Iw$B`VCz=h?8B{9`iHR)M<zf z_waP4ROwP_H2O?4J478jkst+`I2Vt>;W+#R=zQYi%QK=YIIYE<3!vOpTz+H*?nx$) z89hipvW{%{l|<ngc-1~UY8U8^$*<#ot)m_`@MBJiab#^1cl?89K3FN9_M{tGL>Be# zN@j5LgYYuk<#%ku#U$b}nZ=PvX+m~pk|67bGSzNYwzZ%RAFRRUb<`c;*51)&_jo)8 zkCr1u+9dcse1ith?{N#+4Y`56(k79gNZmGQYlPB9*mDhx`Y$@koB07NE5&ze@%B3E zr+P8J4&Q;O<rYST{#S5$bN^pn_9y>p>i_%=TJ6<?qjz{%e3h2r5KT4SQ;R>Vrp`3* zQ%;Ea6Qzs>(k!pX?q=~BdVBhoWR^^pY7KzE?P?c?-<Dbm^UYiqO-98IhIJJ?1&<aq zeG)W1;n}5_w@cY<i$~D3+gW*G0PaBg3YzXq-XrUA5Q)Y!o_tevp^}sR<W9rC*HNE0 z@Cs0j$IYk&&U_9p>mNsZvmGjx+Mr~~=|%-UO?%Y>-pN(7&<82r(QaxWy{~9#*;1 z{F~CL$EU@QJxq2JNGfIhqv<lG6FTK&v9h-e5HondV?0h_2pu;idgPp{TUxd}50XfQ zMw64hcrQ`lftag(fID-10_{^4D^+SexX0baY1BpFFwG1}O0l_EQ3_nz&33@ojR^mW z@8T+n&1SLL<sOYknVW0Q&0)#+<gf&P7+_nKEwDWX*ft0qf$e*=EF-^;IuCQVHXrbs z%k9ne!PGr!G6;VMZ~-8`N)P?Q=%mt2FeB`CrEN{yofdMsfxj+9<OTj|<xGY*2gWSf z!umOSPf}@O+GgEmpl)dN6C>}JY|lw6NmIb4?M5!t^PHnIe1RZe&iX^>(4n~Cd5|R4 zS*F>dC@XVsb8@)QA0&}o^`>o43prEIcNfSc@tZ1`Y-f3Hxnjq5?{3cDllG~K0ej^t z+2<{2^4uRR@#SO|XDE_WR6u6`^PaTQn+qmZ3_!ItnAn@jYJZ1g)WHVc45;MEM+})c zy~$+GfXU3nv(5q>4kzK$$Y@wUi-Pb%EW*)vJzhsdxGz}<2L<M{4$OxF^I6Erc6ifp zLmfU-M_p>bf5M>c@UIL$*}OvMNN;_$G%RfRyQ9Fzk?#RE=lHxrw7?(Yg*0yc@G4ed z1;mTi9Eq2vq`_j9;c#`ezil=3Nj;wjQ@#2#CgZ)8x_1?1<}^G~u<o;XXcMbLNqE1M z9`8)%2#woH>_%geL7`S>t4&2li<!d(WQ&l>n(Yd&%jdD@*-cii_ivJ`7e9H1L*@8A zBF251Md}k+5fq8Q3(p+)?K}dm!VQ|o4{Gp^x{$LC_|YlQzY@3PLm6DrEZj`#w^vv9 z=`&^p2xn~+Gpf>D$eHaR+!uHr{cP7N(yD|DttRi3Za0?$QUf$mV9m2~88wEzhR23m z>yOQ?2>x>K-jm<Ru`Kce31-O(X>xkTCQfG21yu0qX?!0X-)O!KgO|pBkwT>M5##3d z2p@gwYa_cQAC{Ctt;tnR{TyQ25X{}b{#zk;clEjGeeBGw<99493!YQ4rs{<J+pmw` zdw6mF7%Q7y=z??(u;rG^u}?`aBI_}-$LN|#Ujs=qtlWOEGIL=Lb6t!QJeV)w06O92 zG^}v9NAH0=CSIz_QK=w7Eah;VRCYh-Q~#KB>YEe%8z;qlIo2@~mVhJbM!HSM^lg@3 zDJ(m+N|mc(8&}b}R-(muICVFkbe`qoA#*BLsntT}^bb!ORmtxY<HIKy@}8fSxXe16 zR-w$+W#<)`3t=`lJ?|&Uuvh9T6%~~w<#s6Whf4}A1s03ERO!yv>5M8PE8`_@SehZF zeggBg+|Qn7NMC;|Nu^O(d}*7t=|+x(KW|MY`d<eU8oNLuCqN>P!_%MllB75))fI}$ z3il2m5e{8LD{=VqmXc&grAi>}+3Dc$41aG)VNpR*ksKsYs?`RKnUx)ML!b}Y!tVyk zmAui$=p0T{G0eN$XUn&nAj)UpA8-QxLQ-TY1YGD*xdjiU)3am=IR>cZn50CXYspn8 zRT`DK&{PCMCy*<W(B&k9d@nH@^Nf)2dbPgdVvEzx!lJw+k?jDzVJkROs~4tB57}n1 zm&NroPUC|DbSwcnkcDZ1&T{e{S%z;*N(?!WBMEejuvCm3P9`rTGIc>6|4SY90iPn~ zbsb;EyG~NRJ%2}HcUnrE@^W?Q2DY)gRAta;)WwiV@~x$f9UAXT3_0eUTzQ69xebuF zopd<hKXa7&XEhiT=>Q3%(+QTR<GTCL{07^Hu)Sz-ftPJ1%~a;D=bm4oQ`|aXUvuWW z{xZsfZ;0{!^^Df)G&+UY<pXdnz@**&brPp3*OsGDffa&TfML8OhDX5uPb^T|;V#+E z`LED>vx~D>prJ8nHCj7><6obj=^@p@21kx92cWWw@65+gAM*3W{3N~)lVbzyE}*hf zTfWT<<YMs)Nm-7{nGNZrE<?wWNrXt6cH>kYt+&`|D}h{Q0{&ehvky2$74S#I{E-37 zsm3ESAryYde~edA2k;w0&Qiq`jmM+&Ev(m|h5eSyOm&9Rss5dG=gdXce2c>2u-ReR ztB>;0N2%&Me7jDJEA}#^T^ttw{L>*U_|>+Dh`4Wf91)YY93GazXuW!m2fzl)&w(Ii zhahE8vvcUGq_O{)rXW#MA(84pm~*5pj{4)+<#HD%%hpz<r|}DqhMW{AfSn%2J3a;? zE3oM2pAI$=IV=!aPDDT?G=pqR7oY$@5P$-qN6*pIt4=1KQ{bp`z)uI<VJdD*qNYt= zyI>86t6xS++4|h0e0UXAbzDG1otQ!}crZk5i6$qoOs6C-UNTrg+AhWD=bw%Oh;Mtl zYRU9%oYG!ma4KMn)oa;+yF(0$h$U@6hz^%X8ytay>*{ZR^okTUe@RgRQnZZ|q!3iq z7Po6wm58(hDe%x&r0~bQ<dam>wQDAQENE+5KwBNof+vkSSHJsA6(`%QtHN`R;ut{= z{NSYcDc;H4cb&Zbo8sBYfdh)U50)}Mr_0CTmc~g~M*1m8_*fE3+LMs4NC@mM#e9e( zEnbzd2Vzv4xOdX#&jX?9*^hoQg4M3^rtvds@kDUBZBGKvUPkT9^?C$F^CKPyKxhC& z_P!@QZr^vM#G7ySu=z!W1w{&XF+kCrvWY|2%^%A39YVwAomy?zxVhU>**oN|Dm?HY zFFHi+s>bJP#W?LcLqsbd{d0!}B6;+KGb0K0_VOO26^92bVfxOT9?^f{p%Xf`)C~Ef zLZi;fUi5hss4(*611#bA5wr`2)(D&B^XL;BCheT5AU&paC9O#7)7@~deD2)&kB<UY zpUY1=LDkjcPXI`<#mq}&dyKxZ1i(V)*y$@5u4i%0OYJ|O_zD1a(pNA1dWU_Ge`xAk zav8bpm)xVSHHfddK`qT7nU8x3J$K{2f0H}H2IjD%e*LWwEWZ^i*!TB%oWC`*ZOfKz z+cL{jQ!_GBQ_C~AaiNztJ&#}}Z{GY~M!KUco3$AYMUWJ0HJY?fH+*_^-=RAk@21@V zvIXDH%DTDJsFNU=ERQi-Az@Q^;Drc;a<i2qdTht<;o%Z{0Cu|79?0$U%qEr;kl7Nx z_sf;}eEcioR)T~05q!5GV!(5IU;_})_Nah*U^h(-FjLRZsHQH}W5|82^<w`pJE#?K zt5?9S$7$TX-{G-u&09Jpi9MG&r)rF1_RI})lezN(-|$ui_->4E0=j_?KKk<EKkt0^ z(WD_PIrK{TPWoKUZ#Qr4pEa13E#s$GQw>d%*zMIxtf6a@@f&1N?7WmI@$6@`2UG)? z7)Y#mMJO+Q<;-vQ9~_=IhLz<Qs`#j*)R8*KE5vyF0a%~&h4oq2v_9(uFEby!OgnB# z5RSUq<W6D)cS0g#n%3e~Sc{RIY}U3ze8?f{P#vy6CO$;^Ku)Chy4`{j9Q53ePbD=d zaQ6mG<CeJPEKHNGT%L6D)K$wjac5|k#tylXLCfN$jXfD6U5Q(M;d4RO-xCM@quam% ztGW{@Cz}BjS|6hJSK|x7tKl<-1TBAZ=buNO0{CrnfKa10W|2Xp8;7Id<;Y*udH>7d zr_xm^)Ao&1kZx083$P{W_xNorKKc3H>fORh=O-PbuGNdLy*hte>2s%_e(5OA&vUT( zmZAcS!s~Rqiwi1dPh7A#P6^ZKg+Kwo3CwRW=rZD{Ffkr@-S?aiV$_xrV+lmYV(-r7 zk4V_yq3=aZt6o*7;_B3gRQt8Tr?Pf#h?7r>**rCN(#IDyFBi9RT@}2{>h{~c{lA}H zT0NzVTj^TqUF8g(;Yr-NPhNBEgEJrB(vI5-kvJj$7~i{w!Xm(fBCKHE+_(DXmv(QN zTklqz^9u4|M?|g3*D1yswq4@z=Z{{d&3#~l;IE{KL=S~m3Tm~+uJLfUq_V}jT3AZ> z6F`gI${8)ZRs_iGV)-RtQ#Q3q31&;Y^oZI0A|jTZ{g!<-s*n@(sDrQv%bxpu`}vPq z*)V$@wT&Mv#*09)Hm|{_@PVb<I6RhL`fqra<x=W$j9L?$n@oB&h84(31V2pTGU=>3 z1*D^D0bJ%m&XHhGqqh3jiuw94m;%xfH>wV>UL$0F3P?PaMlN$EBtAbu_c!^z&^^bR zBVbeLo(J9W$i~GIr48aFKx;>-mBStQC`kcsNB%6I!76Ql%K%n5e85^{6Kj?tfMrgl zR%_IlSXpl&o#bulmFXed_}<{Q7Vzx~;RTYz3~%9Jhu4-L@HE443IxGb5=+yoKb1$7 z8`#(av^_@>`abE3=SUnzy+sd_snw=JlaK^OkX2+DNs*XM`9_mm<yCnd4yyy;V<cW9 zk%f_A{vMQ*j}YTF<TWPWoNqP*#?*P7#nuwoqqgvW0LB)Aw^v=FhB&5yz5MXTAkv?w zBrao)O(!5RrGQpV9FA@53q!)LFjGry=R1q}t{q|P0ul#d2mgW;pW<6f><)|5Dc_<g z+swiqmQt@#tBciM4j+_~`o>_19$seZ<QbmKN-)7)q))m3Ulr6J)#5+gOxU40_Z(K6 z)n>BgPRhD+i^W~&Z_RZJyzKFk!sFNFxGR0zed+UJtIY;Y^aGdA?#hzaY0@e$V}cU4 zdf_FR++;P`^Vy3UTNY^#QRa^!em&%^0Ir5Ge*LWHdhp8sCW>1Ec5S(h8Jab2Qm)Bp zG+B*~dxuW`$>L5lZf`5Q=w==83f3xzxzQK06MT8)xRo5gPCr{-KTr=Hj8<duB~L84 z+phFmh4YT<*aa%{{E>25HJ*Ihb2j8FetsZAEyBf2Xl4Gfo8!Jzd{z71&SHZNI-7IN z+?tdP$`y;FznY{7{eINE5sA4VmleW{h5N94-<HD)c&B!QKSVv^4~zMKU1uOggP>$H zTR6zFghL~-Sc+^`xm)Aaz=&ouOSHm)wGxZjSY(1|uhujt%UYrlsw8G}9@vS-qjuY@ zMHblX3k)SxSgdB-|0j|^Ji@(>V)-KqfBi`8k9hSZX5-zLuMcqzp2+Onx^>si&0CW; zZQh);Y3t@)T;qtK|4}AW`gn5zPAQO*kp(ncIc(*N)-7sVHnciwZ{51i*1C;<MhAGu zB77-HJ%e*JN`-Tr$b`m<;?NxN1{5nggCeQ6XdR_QbK#ssT}RVJchP97GkPy@MQAB? z62*wB(K=Bz)u-u-7Q%HAoXK#mhjR^_ac~;pvzK`=-h9zKG#vVmhwB1SCp20df!-E* zQJ82Vnk3qYMu;lV645}Yi$KdnW#}!D3ce}wqZQQWh!YJ5{#v0?;x5o`HPn5Adc!w` zF``4L7xWn^>Vn=BDNrj>CYmA|hZy*>vmJ~Z0&O~p+9QtYg630kNDS9VQ9IN{)E#7( zLZ2=uS|me5sDGgdxb_zXqX=p;VyK%)K|O?Tp01*i6a#G!!<SFz&{VMu#ZbSYVIl_g zrS8FZkatiIXg`%Yhx$?DP%!lb#`+AsCgS0{&T8};bpW-1vlG=CzPhS`zO8|u=^*c2 z_&h8Q#uUEr625i~f^W4%>sG}lCMRx8K-7k~)C4G(20m{RzV8Z#@42WK^Mv;Q4YCFF Aga7~l literal 0 HcmV?d00001 diff --git a/form/src/assets/libs/audio-recorder/lame.min.js b/form/src/assets/libs/audio-recorder/lame.min.js new file mode 100644 index 0000000..32bfe8c --- /dev/null +++ b/form/src/assets/libs/audio-recorder/lame.min.js @@ -0,0 +1,308 @@ +function lamejs(){function Y(d){return new Int32Array(d)}function H(d){return new Float32Array(d)}function ra(d){if(1==d.length)return H(d[0]);var k=d[0];d=d.slice(1);for(var q=[],C=0;C<k;C++)q.push(ra(d));return q}function db(d){if(1==d.length)return Y(d[0]);var k=d[0];d=d.slice(1);for(var q=[],C=0;C<k;C++)q.push(db(d));return q}function vc(d){if(1==d.length)return new Int16Array(d[0]);var k=d[0];d=d.slice(1);for(var q=[],C=0;C<k;C++)q.push(vc(d));return q}function Zb(d){if(1==d.length)return Array(d[0]); +var k=d[0];d=d.slice(1);for(var q=[],C=0;C<k;C++)q.push(Zb(d));return q}function sa(d){this.ordinal=d}function M(d){this.ordinal=d}function ka(d){this.ordinal=function(){return d}}function Fc(){this.getLameVersion=function(){return"3.98.4"};this.getLameShortVersion=function(){return"3.98.4"};this.getLameVeryShortVersion=function(){return"LAME3.98r"};this.getPsyVersion=function(){return"0.93"};this.getLameUrl=function(){return"http://www.mp3dev.org/"};this.getLameOsBitness=function(){return"32bits"}} +function Gc(){function d(b,g,a,h,k,e,n,c,f,E,z,w,A,v,p){this.vbr_q=b;this.quant_comp=g;this.quant_comp_s=a;this.expY=h;this.st_lrm=k;this.st_s=e;this.masking_adj=n;this.masking_adj_short=c;this.ath_lower=f;this.ath_curve=E;this.ath_sensitivity=z;this.interch=w;this.safejoint=A;this.sfb21mod=v;this.msfix=p}function k(b,g,a,d,k,e,n,c,f,E,z,w,A,v){this.quant_comp=g;this.quant_comp_s=a;this.safejoint=d;this.nsmsfix=k;this.st_lrm=e;this.st_s=n;this.nsbass=c;this.scale=f;this.masking_adj=E;this.ath_lower= +z;this.ath_curve=w;this.interch=A;this.sfscale=v}function q(b,g,a){var d=b.VBR==M.vbr_rh?t:r,k=b.VBR_q_frac,e=d[g],d=d[g+1];e.st_lrm+=k*(d.st_lrm-e.st_lrm);e.st_s+=k*(d.st_s-e.st_s);e.masking_adj+=k*(d.masking_adj-e.masking_adj);e.masking_adj_short+=k*(d.masking_adj_short-e.masking_adj_short);e.ath_lower+=k*(d.ath_lower-e.ath_lower);e.ath_curve+=k*(d.ath_curve-e.ath_curve);e.ath_sensitivity+=k*(d.ath_sensitivity-e.ath_sensitivity);e.interch+=k*(d.interch-e.interch);e.msfix+=k*(d.msfix-e.msfix);d= +e.vbr_q;0>d&&(d=0);9<d&&(d=9);b.VBR_q=d;b.VBR_q_frac=0;0!=a?b.quant_comp=e.quant_comp:0<Math.abs(b.quant_comp- -1)||(b.quant_comp=e.quant_comp);0!=a?b.quant_comp_short=e.quant_comp_s:0<Math.abs(b.quant_comp_short- -1)||(b.quant_comp_short=e.quant_comp_s);0!=e.expY&&(b.experimentalY=0!=e.expY);0!=a?b.internal_flags.nsPsy.attackthre=e.st_lrm:0<Math.abs(b.internal_flags.nsPsy.attackthre- -1)||(b.internal_flags.nsPsy.attackthre=e.st_lrm);0!=a?b.internal_flags.nsPsy.attackthre_s=e.st_s:0<Math.abs(b.internal_flags.nsPsy.attackthre_s- +-1)||(b.internal_flags.nsPsy.attackthre_s=e.st_s);0!=a?b.maskingadjust=e.masking_adj:0<Math.abs(b.maskingadjust-0)||(b.maskingadjust=e.masking_adj);0!=a?b.maskingadjust_short=e.masking_adj_short:0<Math.abs(b.maskingadjust_short-0)||(b.maskingadjust_short=e.masking_adj_short);0!=a?b.ATHlower=-e.ath_lower/10:0<Math.abs(10*-b.ATHlower-0)||(b.ATHlower=-e.ath_lower/10);0!=a?b.ATHcurve=e.ath_curve:0<Math.abs(b.ATHcurve- -1)||(b.ATHcurve=e.ath_curve);0!=a?b.athaa_sensitivity=e.ath_sensitivity:0<Math.abs(b.athaa_sensitivity- +-1)||(b.athaa_sensitivity=e.ath_sensitivity);0<e.interch&&(0!=a?b.interChRatio=e.interch:0<Math.abs(b.interChRatio- -1)||(b.interChRatio=e.interch));0<e.safejoint&&(b.exp_nspsytune|=e.safejoint);0<e.sfb21mod&&(b.exp_nspsytune|=e.sfb21mod<<20);0!=a?b.msfix=e.msfix:0<Math.abs(b.msfix- -1)||(b.msfix=e.msfix);0==a&&(b.VBR_q=g,b.VBR_q_frac=k)}function C(b,d,a){var h=B.nearestBitrateFullIndex(d);b.VBR=M.vbr_abr;b.VBR_mean_bitrate_kbps=d;b.VBR_mean_bitrate_kbps=Math.min(b.VBR_mean_bitrate_kbps,320);b.VBR_mean_bitrate_kbps= +Math.max(b.VBR_mean_bitrate_kbps,8);b.brate=b.VBR_mean_bitrate_kbps;320<b.VBR_mean_bitrate_kbps&&(b.disable_reservoir=!0);0<g[h].safejoint&&(b.exp_nspsytune|=2);0<g[h].sfscale&&(b.internal_flags.noise_shaping=2);if(0<Math.abs(g[h].nsbass)){var k=int(4*g[h].nsbass);0>k&&(k+=64);b.exp_nspsytune|=k<<2}0!=a?b.quant_comp=g[h].quant_comp:0<Math.abs(b.quant_comp- -1)||(b.quant_comp=g[h].quant_comp);0!=a?b.quant_comp_short=g[h].quant_comp_s:0<Math.abs(b.quant_comp_short- -1)||(b.quant_comp_short=g[h].quant_comp_s); +0!=a?b.msfix=g[h].nsmsfix:0<Math.abs(b.msfix- -1)||(b.msfix=g[h].nsmsfix);0!=a?b.internal_flags.nsPsy.attackthre=g[h].st_lrm:0<Math.abs(b.internal_flags.nsPsy.attackthre- -1)||(b.internal_flags.nsPsy.attackthre=g[h].st_lrm);0!=a?b.internal_flags.nsPsy.attackthre_s=g[h].st_s:0<Math.abs(b.internal_flags.nsPsy.attackthre_s- -1)||(b.internal_flags.nsPsy.attackthre_s=g[h].st_s);0!=a?b.scale=g[h].scale:0<Math.abs(b.scale- -1)||(b.scale=g[h].scale);0!=a?b.maskingadjust=g[h].masking_adj:0<Math.abs(b.maskingadjust- +0)||(b.maskingadjust=g[h].masking_adj);0<g[h].masking_adj?0!=a?b.maskingadjust_short=.9*g[h].masking_adj:0<Math.abs(b.maskingadjust_short-0)||(b.maskingadjust_short=.9*g[h].masking_adj):0!=a?b.maskingadjust_short=1.1*g[h].masking_adj:0<Math.abs(b.maskingadjust_short-0)||(b.maskingadjust_short=1.1*g[h].masking_adj);0!=a?b.ATHlower=-g[h].ath_lower/10:0<Math.abs(10*-b.ATHlower-0)||(b.ATHlower=-g[h].ath_lower/10);0!=a?b.ATHcurve=g[h].ath_curve:0<Math.abs(b.ATHcurve- -1)||(b.ATHcurve=g[h].ath_curve);0!= +a?b.interChRatio=g[h].interch:0<Math.abs(b.interChRatio- -1)||(b.interChRatio=g[h].interch);return d}var B;this.setModules=function(b){B=b};var t=[new d(0,9,9,0,5.2,125,-4.2,-6.3,4.8,1,0,0,2,21,.97),new d(1,9,9,0,5.3,125,-3.6,-5.6,4.5,1.5,0,0,2,21,1.35),new d(2,9,9,0,5.6,125,-2.2,-3.5,2.8,2,0,0,2,21,1.49),new d(3,9,9,1,5.8,130,-1.8,-2.8,2.6,3,-4,0,2,20,1.64),new d(4,9,9,1,6,135,-.7,-1.1,1.1,3.5,-8,0,2,0,1.79),new d(5,9,9,1,6.4,140,.5,.4,-7.5,4,-12,2E-4,0,0,1.95),new d(6,9,9,1,6.6,145,.67,.65,-14.7, +6.5,-19,4E-4,0,0,2.3),new d(7,9,9,1,6.6,145,.8,.75,-19.7,8,-22,6E-4,0,0,2.7),new d(8,9,9,1,6.6,145,1.2,1.15,-27.5,10,-23,7E-4,0,0,0),new d(9,9,9,1,6.6,145,1.6,1.6,-36,11,-25,8E-4,0,0,0),new d(10,9,9,1,6.6,145,2,2,-36,12,-25,8E-4,0,0,0)],r=[new d(0,9,9,0,4.2,25,-7,-4,7.5,1,0,0,2,26,.97),new d(1,9,9,0,4.2,25,-5.6,-3.6,4.5,1.5,0,0,2,21,1.35),new d(2,9,9,0,4.2,25,-4.4,-1.8,2,2,0,0,2,18,1.49),new d(3,9,9,1,4.2,25,-3.4,-1.25,1.1,3,-4,0,2,15,1.64),new d(4,9,9,1,4.2,25,-2.2,.1,0,3.5,-8,0,2,0,1.79),new d(5, +9,9,1,4.2,25,-1,1.65,-7.7,4,-12,2E-4,0,0,1.95),new d(6,9,9,1,4.2,25,-0,2.47,-7.7,6.5,-19,4E-4,0,0,2),new d(7,9,9,1,4.2,25,.5,2,-14.5,8,-22,6E-4,0,0,2),new d(8,9,9,1,4.2,25,1,2.4,-22,10,-23,7E-4,0,0,2),new d(9,9,9,1,4.2,25,1.5,2.95,-30,11,-25,8E-4,0,0,2),new d(10,9,9,1,4.2,25,2,2.95,-36,12,-30,8E-4,0,0,2)],g=[new k(8,9,9,0,0,6.6,145,0,.95,0,-30,11,.0012,1),new k(16,9,9,0,0,6.6,145,0,.95,0,-25,11,.001,1),new k(24,9,9,0,0,6.6,145,0,.95,0,-20,11,.001,1),new k(32,9,9,0,0,6.6,145,0,.95,0,-15,11,.001,1), +new k(40,9,9,0,0,6.6,145,0,.95,0,-10,11,9E-4,1),new k(48,9,9,0,0,6.6,145,0,.95,0,-10,11,9E-4,1),new k(56,9,9,0,0,6.6,145,0,.95,0,-6,11,8E-4,1),new k(64,9,9,0,0,6.6,145,0,.95,0,-2,11,8E-4,1),new k(80,9,9,0,0,6.6,145,0,.95,0,0,8,7E-4,1),new k(96,9,9,0,2.5,6.6,145,0,.95,0,1,5.5,6E-4,1),new k(112,9,9,0,2.25,6.6,145,0,.95,0,2,4.5,5E-4,1),new k(128,9,9,0,1.95,6.4,140,0,.95,0,3,4,2E-4,1),new k(160,9,9,1,1.79,6,135,0,.95,-2,5,3.5,0,1),new k(192,9,9,1,1.49,5.6,125,0,.97,-4,7,3,0,0),new k(224,9,9,1,1.25,5.2, +125,0,.98,-6,9,2,0,0),new k(256,9,9,1,.97,5.2,125,0,1,-8,10,1,0,0),new k(320,9,9,1,.9,5.2,125,0,1,-10,12,0,0,0)];this.apply_preset=function(b,d,a){switch(d){case V.R3MIX:d=V.V3;b.VBR=M.vbr_mtrh;break;case V.MEDIUM:d=V.V4;b.VBR=M.vbr_rh;break;case V.MEDIUM_FAST:d=V.V4;b.VBR=M.vbr_mtrh;break;case V.STANDARD:d=V.V2;b.VBR=M.vbr_rh;break;case V.STANDARD_FAST:d=V.V2;b.VBR=M.vbr_mtrh;break;case V.EXTREME:d=V.V0;b.VBR=M.vbr_rh;break;case V.EXTREME_FAST:d=V.V0;b.VBR=M.vbr_mtrh;break;case V.INSANE:return d= +320,b.preset=d,C(b,d,a),b.VBR=M.vbr_off,d}b.preset=d;switch(d){case V.V9:return q(b,9,a),d;case V.V8:return q(b,8,a),d;case V.V7:return q(b,7,a),d;case V.V6:return q(b,6,a),d;case V.V5:return q(b,5,a),d;case V.V4:return q(b,4,a),d;case V.V3:return q(b,3,a),d;case V.V2:return q(b,2,a),d;case V.V1:return q(b,1,a),d;case V.V0:return q(b,0,a),d}if(8<=d&&320>=d)return C(b,d,a);b.preset=0;return d}}function O(){function d(g,b,l,a,h,k){for(;0!=h--;)l[a]=1E-10+g[b+0]*k[0]-l[a-1]*k[1]+g[b-1]*k[2]-l[a-2]*k[3]+ +g[b-2]*k[4]-l[a-3]*k[5]+g[b-3]*k[6]-l[a-4]*k[7]+g[b-4]*k[8]-l[a-5]*k[9]+g[b-5]*k[10]-l[a-6]*k[11]+g[b-6]*k[12]-l[a-7]*k[13]+g[b-7]*k[14]-l[a-8]*k[15]+g[b-8]*k[16]-l[a-9]*k[17]+g[b-9]*k[18]-l[a-10]*k[19]+g[b-10]*k[20],++a,++b}function k(d,b,l,a,h,k){for(;0!=h--;)l[a]=d[b+0]*k[0]-l[a-1]*k[1]+d[b-1]*k[2]-l[a-2]*k[3]+d[b-2]*k[4],++a,++b}function q(d){return d*d}var C=O.RMS_WINDOW_TIME_NUMERATOR,B=O.RMS_WINDOW_TIME_DENOMINATOR,t=[[.038575994352,-3.84664617118067,-.02160367184185,7.81501653005538,-.00123395316851, +-11.34170355132042,-9.291677959E-5,13.05504219327545,-.01655260341619,-12.28759895145294,.02161526843274,9.4829380631979,-.02074045215285,-5.87257861775999,.00594298065125,2.75465861874613,.00306428023191,-.86984376593551,1.2025322027E-4,.13919314567432,.00288463683916],[.0541865640643,-3.47845948550071,-.02911007808948,6.36317777566148,-.00848709379851,-8.54751527471874,-.00851165645469,9.4769360780128,-.00834990904936,-8.81498681370155,.02245293253339,6.85401540936998,-.02596338512915,-4.39470996079559, +.01624864962975,2.19611684890774,-.00240879051584,-.75104302451432,.00674613682247,.13149317958808,-.00187763777362],[.15457299681924,-2.37898834973084,-.09331049056315,2.84868151156327,-.06247880153653,-2.64577170229825,.02163541888798,2.23697657451713,-.05588393329856,-1.67148153367602,.04781476674921,1.00595954808547,.00222312597743,-.45953458054983,.03174092540049,.16378164858596,-.01390589421898,-.05032077717131,.00651420667831,.0234789740702,-.00881362733839],[.30296907319327,-1.61273165137247, +-.22613988682123,1.0797749225997,-.08587323730772,-.2565625775407,.03282930172664,-.1627671912044,-.00915702933434,-.22638893773906,-.02364141202522,.39120800788284,-.00584456039913,-.22138138954925,.06276101321749,.04500235387352,-8.28086748E-6,.02005851806501,.00205861885564,.00302439095741,-.02950134983287],[.33642304856132,-1.49858979367799,-.2557224142557,.87350271418188,-.11828570177555,.12205022308084,.11921148675203,-.80774944671438,-.07834489609479,.47854794562326,-.0046997791438,-.12453458140019, +-.0058950022444,-.04067510197014,.05724228140351,.08333755284107,.00832043980773,-.04237348025746,-.0163538138454,.02977207319925,-.0176017656815],[.4491525660845,-.62820619233671,-.14351757464547,.29661783706366,-.22784394429749,-.372563729424,-.01419140100551,.00213767857124,.04078262797139,-.42029820170918,-.12398163381748,.22199650564824,.04097565135648,.00613424350682,.10478503600251,.06747620744683,-.01863887810927,.05784820375801,-.03193428438915,.03222754072173,.00541907748707],[.56619470757641, +-1.04800335126349,-.75464456939302,.29156311971249,.1624213774223,-.26806001042947,.16744243493672,.00819999645858,-.18901604199609,.45054734505008,.3093178284183,-.33032403314006,-.27562961986224,.0673936833311,.00647310677246,-.04784254229033,.08647503780351,.01639907836189,-.0378898455484,.01807364323573,-.00588215443421],[.58100494960553,-.51035327095184,-.53174909058578,-.31863563325245,-.14289799034253,-.20256413484477,.17520704835522,.1472815413433,.02377945217615,.38952639978999,.15558449135573, +-.23313271880868,-.25344790059353,-.05246019024463,.01628462406333,-.02505961724053,.06920467763959,.02442357316099,-.03721611395801,.01818801111503,-.00749618797172],[.53648789255105,-.2504987195602,-.42163034350696,-.43193942311114,-.00275953611929,-.03424681017675,.04267842219415,-.04678328784242,-.10214864179676,.26408300200955,.14590772289388,.15113130533216,-.02459864859345,-.17556493366449,-.11202315195388,-.18823009262115,-.04060034127,.05477720428674,.0478866554818,.0470440968812,-.02217936801134]], +r=[[.98621192462708,-1.97223372919527,-1.97242384925416,.97261396931306,.98621192462708],[.98500175787242,-1.96977855582618,-1.97000351574484,.9702284756635,.98500175787242],[.97938932735214,-1.95835380975398,-1.95877865470428,.95920349965459,.97938932735214],[.97531843204928,-1.95002759149878,-1.95063686409857,.95124613669835,.97531843204928],[.97316523498161,-1.94561023566527,-1.94633046996323,.94705070426118,.97316523498161],[.96454515552826,-1.92783286977036,-1.92909031105652,.93034775234268, +.96454515552826],[.96009142950541,-1.91858953033784,-1.92018285901082,.92177618768381,.96009142950541],[.95856916599601,-1.9154210807478,-1.91713833199203,.91885558323625,.95856916599601],[.94597685600279,-1.88903307939452,-1.89195371200558,.89487434461664,.94597685600279]];this.InitGainAnalysis=function(d,b){var l;a:{for(l=0;l<MAX_ORDER;l++)d.linprebuf[l]=d.lstepbuf[l]=d.loutbuf[l]=d.rinprebuf[l]=d.rstepbuf[l]=d.routbuf[l]=0;switch(0|b){case 48E3:d.reqindex=0;break;case 44100:d.reqindex=1;break; +case 32E3:d.reqindex=2;break;case 24E3:d.reqindex=3;break;case 22050:d.reqindex=4;break;case 16E3:d.reqindex=5;break;case 12E3:d.reqindex=6;break;case 11025:d.reqindex=7;break;case 8E3:d.reqindex=8;break;default:l=INIT_GAIN_ANALYSIS_ERROR;break a}d.sampleWindow=0|(b*C+B-1)/B;d.lsum=0;d.rsum=0;d.totsamp=0;Ia.ill(d.A,0);l=INIT_GAIN_ANALYSIS_OK}if(l!=INIT_GAIN_ANALYSIS_OK)return INIT_GAIN_ANALYSIS_ERROR;d.linpre=MAX_ORDER;d.rinpre=MAX_ORDER;d.lstep=MAX_ORDER;d.rstep=MAX_ORDER;d.lout=MAX_ORDER;d.rout= +MAX_ORDER;Ia.fill(d.B,0);return INIT_GAIN_ANALYSIS_OK};this.AnalyzeSamples=function(g,b,l,a,h,D,e){var n,c,f,E,z,w;if(0==D)return GAIN_ANALYSIS_OK;w=0;E=D;switch(e){case 1:a=b;h=l;break;case 2:break;default:return GAIN_ANALYSIS_ERROR}D<MAX_ORDER?(K.arraycopy(b,l,g.linprebuf,MAX_ORDER,D),K.arraycopy(a,h,g.rinprebuf,MAX_ORDER,D)):(K.arraycopy(b,l,g.linprebuf,MAX_ORDER,MAX_ORDER),K.arraycopy(a,h,g.rinprebuf,MAX_ORDER,MAX_ORDER));for(;0<E;){z=E>g.sampleWindow-g.totsamp?g.sampleWindow-g.totsamp:E;w<MAX_ORDER? +(e=g.linpre+w,n=g.linprebuf,c=g.rinpre+w,f=g.rinprebuf,z>MAX_ORDER-w&&(z=MAX_ORDER-w)):(e=l+w,n=b,c=h+w,f=a);d(n,e,g.lstepbuf,g.lstep+g.totsamp,z,t[g.reqindex]);d(f,c,g.rstepbuf,g.rstep+g.totsamp,z,t[g.reqindex]);k(g.lstepbuf,g.lstep+g.totsamp,g.loutbuf,g.lout+g.totsamp,z,r[g.reqindex]);k(g.rstepbuf,g.rstep+g.totsamp,g.routbuf,g.rout+g.totsamp,z,r[g.reqindex]);e=g.lout+g.totsamp;n=g.loutbuf;c=g.rout+g.totsamp;f=g.routbuf;for(var A=z%8;0!=A--;)g.lsum+=q(n[e++]),g.rsum+=q(f[c++]);for(A=z/8;0!=A--;)g.lsum+= +q(n[e+0])+q(n[e+1])+q(n[e+2])+q(n[e+3])+q(n[e+4])+q(n[e+5])+q(n[e+6])+q(n[e+7]),e+=8,g.rsum+=q(f[c+0])+q(f[c+1])+q(f[c+2])+q(f[c+3])+q(f[c+4])+q(f[c+5])+q(f[c+6])+q(f[c+7]),c+=8;E-=z;w+=z;g.totsamp+=z;g.totsamp==g.sampleWindow&&(e=10*O.STEPS_per_dB*Math.log10((g.lsum+g.rsum)/g.totsamp*.5+1E-37),e=0>=e?0:0|e,e>=g.A.length&&(e=g.A.length-1),g.A[e]++,g.lsum=g.rsum=0,K.arraycopy(g.loutbuf,g.totsamp,g.loutbuf,0,MAX_ORDER),K.arraycopy(g.routbuf,g.totsamp,g.routbuf,0,MAX_ORDER),K.arraycopy(g.lstepbuf,g.totsamp, +g.lstepbuf,0,MAX_ORDER),K.arraycopy(g.rstepbuf,g.totsamp,g.rstepbuf,0,MAX_ORDER),g.totsamp=0);if(g.totsamp>g.sampleWindow)return GAIN_ANALYSIS_ERROR}D<MAX_ORDER?(K.arraycopy(g.linprebuf,D,g.linprebuf,0,MAX_ORDER-D),K.arraycopy(g.rinprebuf,D,g.rinprebuf,0,MAX_ORDER-D),K.arraycopy(b,l,g.linprebuf,MAX_ORDER-D,D),K.arraycopy(a,h,g.rinprebuf,MAX_ORDER-D,D)):(K.arraycopy(b,l+D-MAX_ORDER,g.linprebuf,0,MAX_ORDER),K.arraycopy(a,h+D-MAX_ORDER,g.rinprebuf,0,MAX_ORDER));return GAIN_ANALYSIS_OK};this.GetTitleGain= +function(d){var b;b=d.A;var l=d.A.length,a,h=0;for(a=0;a<l;a++)h+=b[a];if(0==h)b=GAIN_NOT_ENOUGH_SAMPLES;else{h=0|Math.ceil(h*(1-.95));for(a=l;0<a--&&!(0>=(h-=b[a])););b=64.82-a/O.STEPS_per_dB}for(l=0;l<d.A.length;l++)d.B[l]+=d.A[l],d.A[l]=0;for(l=0;l<MAX_ORDER;l++)d.linprebuf[l]=d.lstepbuf[l]=d.loutbuf[l]=d.rinprebuf[l]=d.rstepbuf[l]=d.routbuf[l]=0;d.totsamp=0;d.lsum=d.rsum=0;return b}}function tb(){function J(a){this.bits=0|a}function k(a,c,b,d,e,p){c=.5946/c;for(a>>=1;0!=a--;)e[p++]=c>b[d++]?0: +1,e[p++]=c>b[d++]?0:1}function q(a,c,b,d,e,p){a>>=1;var m=a%2;for(a>>=1;0!=a--;){var f,n,g,u,h,l,k;f=b[d++]*c;n=b[d++]*c;h=0|f;g=b[d++]*c;l=0|n;u=b[d++]*c;k=0|g;f+=t.adj43[h];h=0|u;n+=t.adj43[l];e[p++]=0|f;g+=t.adj43[k];e[p++]=0|n;u+=t.adj43[h];e[p++]=0|g;e[p++]=0|u}0!=m&&(f=b[d++]*c,n=b[d++]*c,f+=t.adj43[0|f],n+=t.adj43[0|n],e[p++]=0|f,e[p++]=0|n)}function C(a,c,b,d){var e,p=c,m=e=0;do{var f=a[p++],n=a[p++];e<f&&(e=f);m<n&&(m=n)}while(p<b);e<m&&(e=m);switch(e){case 0:return e;case 1:p=c;c=0;e=r.ht[1].hlen; +do m=2*a[p+0]+a[p+1],p+=2,c+=e[m];while(p<b);d.bits+=c;return 1;case 2:case 3:p=c;c=g[e-1];e=0;m=r.ht[c].xlen;f=2==c?r.table23:r.table56;do n=a[p+0]*m+a[p+1],p+=2,e+=f[n];while(p<b);a=e&65535;e>>=16;e>a&&(e=a,c++);d.bits+=e;return c;case 4:case 5:case 6:case 7:case 8:case 9:case 10:case 11:case 12:case 13:case 14:case 15:p=c;c=g[e-1];var f=m=e=0,n=r.ht[c].xlen,h=r.ht[c].hlen,u=r.ht[c+1].hlen,l=r.ht[c+2].hlen;do{var k=a[p+0]*n+a[p+1],p=p+2;e+=h[k];m+=u[k];f+=l[k]}while(p<b);a=c;e>m&&(e=m,a++);e>f&& +(e=f,a=c+2);d.bits+=e;return a;default:if(e>ma.IXMAX_VAL)return d.bits=ma.LARGE_BITS,-1;e-=15;for(p=24;32>p&&!(r.ht[p].linmax>=e);p++);for(m=p-8;24>m&&!(r.ht[m].linmax>=e);m++);e=m;f=65536*r.ht[e].xlen+r.ht[p].xlen;m=0;do n=a[c++],h=a[c++],0!=n&&(14<n&&(n=15,m+=f),n*=16),0!=h&&(14<h&&(h=15,m+=f),n+=h),m+=r.largetbl[n];while(c<b);a=m&65535;m>>=16;m>a&&(m=a,e=p);d.bits+=m;return e}}function B(a,c,e,b,f,p,m,n){for(var y=c.big_values,g=2;g<d.SBMAX_l+1;g++){var h=a.scalefac_band.l[g];if(h>=y)break;var l= +f[g-2]+c.count1bits;if(e.part2_3_length<=l)break;l=new J(l);h=C(b,h,y,l);l=l.bits;e.part2_3_length<=l||(e.assign(c),e.part2_3_length=l,e.region0_count=p[g-2],e.region1_count=g-2-p[g-2],e.table_select[0]=m[g-2],e.table_select[1]=n[g-2],e.table_select[2]=h)}}var t=null;this.qupvt=null;this.setModules=function(a){t=this.qupvt=a};var ta=[[0,0],[0,0],[0,0],[0,0],[0,0],[0,1],[1,1],[1,1],[1,2],[2,2],[2,3],[2,3],[3,4],[3,4],[3,4],[4,5],[4,5],[4,6],[5,6],[5,6],[5,7],[6,7],[6,7]],g=[1,2,5,7,7,10,10,13,13,13, +13,13,13,13,13];this.noquant_count_bits=function(a,c,e){var b=c.l3_enc,f=Math.min(576,c.max_nonzero_coeff+2>>1<<1);null!=e&&(e.sfb_count1=0);for(;1<f&&0==(b[f-1]|b[f-2]);f-=2);c.count1=f;for(var p=0,m=0;3<f;f-=4){var n;if(1<((b[f-1]|b[f-2]|b[f-3]|b[f-4])&2147483647))break;n=2*(2*(2*b[f-4]+b[f-3])+b[f-2])+b[f-1];p+=r.t32l[n];m+=r.t33l[n]}n=p;c.count1table_select=0;p>m&&(n=m,c.count1table_select=1);c.count1bits=n;c.big_values=f;if(0==f)return n;c.block_type==d.SHORT_TYPE?(p=3*a.scalefac_band.s[3],p> +c.big_values&&(p=c.big_values),m=c.big_values):c.block_type==d.NORM_TYPE?(p=c.region0_count=a.bv_scf[f-2],m=c.region1_count=a.bv_scf[f-1],m=a.scalefac_band.l[p+m+2],p=a.scalefac_band.l[p+1],m<f&&(n=new J(n),c.table_select[2]=C(b,m,f,n),n=n.bits)):(c.region0_count=7,c.region1_count=d.SBMAX_l-1-7-1,p=a.scalefac_band.l[8],m=f,p>m&&(p=m));p=Math.min(p,f);m=Math.min(m,f);0<p&&(n=new J(n),c.table_select[0]=C(b,0,p,n),n=n.bits);p<m&&(n=new J(n),c.table_select[1]=C(b,p,m,n),n=n.bits);2==a.use_best_huffman&& +(c.part2_3_length=n,best_huffman_divide(a,c),n=c.part2_3_length);if(null!=e&&c.block_type==d.NORM_TYPE){for(b=0;a.scalefac_band.l[b]<c.big_values;)b++;e.sfb_count1=b}return n};this.count_bits=function(a,c,e,b){var f=e.l3_enc,n=ma.IXMAX_VAL/t.IPOW20(e.global_gain);if(e.xrpow_max>n)return ma.LARGE_BITS;var n=t.IPOW20(e.global_gain),m,g,y=0,h,u=0,l=0,la=0,F=0,G=f,I=0,T=c,U=0;h=null!=b&&e.global_gain==b.global_gain;g=e.block_type==d.SHORT_TYPE?38:21;for(m=0;m<=g;m++){var D=-1;if(h||e.block_type==d.NORM_TYPE)D= +e.global_gain-(e.scalefac[m]+(0!=e.preflag?t.pretab[m]:0)<<e.scalefac_scale+1)-8*e.subblock_gain[e.window[m]];if(h&&b.step[m]==D)0!=u&&(q(u,n,T,U,G,I),u=0),0!=l&&(k(l,n,T,U,G,I),l=0);else{var ia=e.width[m];y+e.width[m]>e.max_nonzero_coeff&&(m=e.max_nonzero_coeff-y+1,Ia.fill(f,e.max_nonzero_coeff,576,0),ia=m,0>ia&&(ia=0),m=g+1);0==u&&0==l&&(G=f,I=F,T=c,U=la);null!=b&&0<b.sfb_count1&&m>=b.sfb_count1&&0<b.step[m]&&D>=b.step[m]?(0!=u&&(q(u,n,T,U,G,I),u=0,G=f,I=F,T=c,U=la),l+=ia):(0!=l&&(k(l,n,T,U,G,I), +l=0,G=f,I=F,T=c,U=la),u+=ia);if(0>=ia){0!=l&&(k(l,n,T,U,G,I),l=0);0!=u&&(q(u,n,T,U,G,I),u=0);break}}m<=g&&(F+=e.width[m],la+=e.width[m],y+=e.width[m])}0!=u&&q(u,n,T,U,G,I);0!=l&&k(l,n,T,U,G,I);if(0!=(a.substep_shaping&2))for(n=0,g=.634521682242439/t.IPOW20(e.global_gain+e.scalefac_scale),y=0;y<e.sfbmax;y++)if(h=e.width[y],0==a.pseudohalf[y])n+=h;else for(u=n,n+=h;u<n;++u)f[u]=c[u]>=g?f[u]:0;return this.noquant_count_bits(a,e,b)};this.best_huffman_divide=function(a,c){var e=new Ab,b=c.l3_enc,f=Y(23), +n=Y(23),m=Y(23),g=Y(23);if(c.block_type!=d.SHORT_TYPE||1!=a.mode_gr){e.assign(c);if(c.block_type==d.NORM_TYPE){for(var y=c.big_values,h=0;22>=h;h++)f[h]=ma.LARGE_BITS;for(h=0;16>h;h++){var l=a.scalefac_band.l[h+1];if(l>=y)break;for(var k=0,q=new J(k),F=C(b,0,l,q),k=q.bits,G=0;8>G;G++){var I=a.scalefac_band.l[h+G+2];if(I>=y)break;q=k;q=new J(q);I=C(b,l,I,q);q=q.bits;f[h+G]>q&&(f[h+G]=q,n[h+G]=h,m[h+G]=F,g[h+G]=I)}}B(a,e,c,b,f,n,m,g)}y=e.big_values;if(!(0==y||1<(b[y-2]|b[y-1])||(y=c.count1+2,576<y))){e.assign(c); +e.count1=y;for(l=h=0;y>e.big_values;y-=4)k=2*(2*(2*b[y-4]+b[y-3])+b[y-2])+b[y-1],h+=r.t32l[k],l+=r.t33l[k];e.big_values=y;e.count1table_select=0;h>l&&(h=l,e.count1table_select=1);e.count1bits=h;e.block_type==d.NORM_TYPE?B(a,e,c,b,f,n,m,g):(e.part2_3_length=h,h=a.scalefac_band.l[8],h>y&&(h=y),0<h&&(f=new J(e.part2_3_length),e.table_select[0]=C(b,0,h,f),e.part2_3_length=f.bits),y>h&&(f=new J(e.part2_3_length),e.table_select[1]=C(b,h,y,f),e.part2_3_length=f.bits),c.part2_3_length>e.part2_3_length&&c.assign(e))}}}; +var b=[1,1,1,1,8,2,2,2,4,4,4,8,8,8,16,16],l=[1,2,4,8,1,2,4,8,2,4,8,2,4,8,4,8],a=[0,0,0,0,3,1,1,1,2,2,2,3,3,3,4,4],h=[0,1,2,3,0,1,2,3,1,2,3,1,2,3,2,3];tb.slen1_tab=a;tb.slen2_tab=h;this.best_scalefac_store=function(c,e,f,n){var g=n.tt[e][f],p,m,x,y=0;for(p=m=0;p<g.sfbmax;p++){x=g.width[p];m+=x;for(x=-x;0>x&&0==g.l3_enc[x+m];x++);0==x&&(g.scalefac[p]=y=-2)}if(0==g.scalefac_scale&&0==g.preflag){for(p=m=0;p<g.sfbmax;p++)0<g.scalefac[p]&&(m|=g.scalefac[p]);if(0==(m&1)&&0!=m){for(p=0;p<g.sfbmax;p++)0<g.scalefac[p]&& +(g.scalefac[p]>>=1);g.scalefac_scale=y=1}}if(0==g.preflag&&g.block_type!=d.SHORT_TYPE&&2==c.mode_gr){for(p=11;p<d.SBPSY_l&&!(g.scalefac[p]<t.pretab[p]&&-2!=g.scalefac[p]);p++);if(p==d.SBPSY_l){for(p=11;p<d.SBPSY_l;p++)0<g.scalefac[p]&&(g.scalefac[p]-=t.pretab[p]);g.preflag=y=1}}for(p=0;4>p;p++)n.scfsi[f][p]=0;if(2==c.mode_gr&&1==e&&n.tt[0][f].block_type!=d.SHORT_TYPE&&n.tt[1][f].block_type!=d.SHORT_TYPE){e=n.tt[1][f];m=n.tt[0][f];for(y=0;y<r.scfsi_band.length-1;y++){for(p=r.scfsi_band[y];p<r.scfsi_band[y+ +1]&&!(m.scalefac[p]!=e.scalefac[p]&&0<=e.scalefac[p]);p++);if(p==r.scfsi_band[y+1]){for(p=r.scfsi_band[y];p<r.scfsi_band[y+1];p++)e.scalefac[p]=-1;n.scfsi[f][y]=1}}for(p=n=f=0;11>p;p++)-1!=e.scalefac[p]&&(n++,f<e.scalefac[p]&&(f=e.scalefac[p]));for(x=m=0;p<d.SBPSY_l;p++)-1!=e.scalefac[p]&&(x++,m<e.scalefac[p]&&(m=e.scalefac[p]));for(y=0;16>y;y++)f<b[y]&&m<l[y]&&(p=a[y]*n+h[y]*x,e.part2_length>p&&(e.part2_length=p,e.scalefac_compress=y));y=0}for(p=0;p<g.sfbmax;p++)-2==g.scalefac[p]&&(g.scalefac[p]= +0);0!=y&&(2==c.mode_gr?this.scale_bitcount(g):this.scale_bitcount_lsf(c,g))};var D=[0,18,36,54,54,36,54,72,54,72,90,72,90,108,108,126],e=[0,18,36,54,51,35,53,71,52,70,88,69,87,105,104,122],n=[0,10,20,30,33,21,31,41,32,42,52,43,53,63,64,74];this.scale_bitcount=function(a){var c,f=0,g=0,h,p=a.scalefac;if(a.block_type==d.SHORT_TYPE)h=D,0!=a.mixed_block_flag&&(h=e);else if(h=n,0==a.preflag){for(c=11;c<d.SBPSY_l&&!(p[c]<t.pretab[c]);c++);if(c==d.SBPSY_l)for(a.preflag=1,c=11;c<d.SBPSY_l;c++)p[c]-=t.pretab[c]}for(c= +0;c<a.sfbdivide;c++)f<p[c]&&(f=p[c]);for(;c<a.sfbmax;c++)g<p[c]&&(g=p[c]);a.part2_length=ma.LARGE_BITS;for(c=0;16>c;c++)f<b[c]&&g<l[c]&&a.part2_length>h[c]&&(a.part2_length=h[c],a.scalefac_compress=c);return a.part2_length==ma.LARGE_BITS};var c=[[15,15,7,7],[15,15,7,0],[7,3,0,0],[15,31,31,0],[7,7,7,0],[3,3,0,0]];this.scale_bitcount_lsf=function(a,e){var b,n,g,p,m,h,y,l=Y(4),u=e.scalefac;b=0!=e.preflag?2:0;for(h=0;4>h;h++)l[h]=0;if(e.block_type==d.SHORT_TYPE){n=1;var k=t.nr_of_sfb_block[b][n];for(g= +y=0;4>g;g++)for(p=k[g]/3,h=0;h<p;h++,y++)for(m=0;3>m;m++)u[3*y+m]>l[g]&&(l[g]=u[3*y+m])}else for(n=0,k=t.nr_of_sfb_block[b][n],g=y=0;4>g;g++)for(p=k[g],h=0;h<p;h++,y++)u[y]>l[g]&&(l[g]=u[y]);p=!1;for(g=0;4>g;g++)l[g]>c[b][g]&&(p=!0);if(!p){e.sfb_partition_table=t.nr_of_sfb_block[b][n];for(g=0;4>g;g++)e.slen[g]=f[l[g]];n=e.slen[0];g=e.slen[1];l=e.slen[2];m=e.slen[3];switch(b){case 0:e.scalefac_compress=(5*n+g<<4)+(l<<2)+m;break;case 1:e.scalefac_compress=400+(5*n+g<<2)+l;break;case 2:e.scalefac_compress= +500+3*n+g;break;default:K.err.printf("intensity stereo not implemented yet\n")}}if(!p)for(g=e.part2_length=0;4>g;g++)e.part2_length+=e.slen[g]*e.sfb_partition_table[g];return p};var f=[0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4];this.huffman_init=function(a){for(var c=2;576>=c;c+=2){for(var e=0,b;a.scalefac_band.l[++e]<c;);for(b=ta[e][0];a.scalefac_band.l[b+1]>c;)b--;0>b&&(b=ta[e][0]);a.bv_scf[c-2]=b;for(b=ta[e][1];a.scalefac_band.l[b+a.bv_scf[c-2]+2]>c;)b--;0>b&&(b=ta[e][1]);a.bv_scf[c-1]=b}}}function Hc(){var d; +this.setModules=function(k){d=k};this.ResvFrameBegin=function(k,q){var C=k.internal_flags,B,t=C.l3_side,r=d.getframebits(k);q.bits=(r-8*C.sideinfo_len)/C.mode_gr;var g=2048*C.mode_gr-8;320<k.brate?B=8*int(1E3*k.brate/(k.out_samplerate/1152)/8+.5):(B=11520,k.strict_ISO&&(B=8*int(32E4/(k.out_samplerate/1152)/8+.5)));C.ResvMax=B-r;C.ResvMax>g&&(C.ResvMax=g);if(0>C.ResvMax||k.disable_reservoir)C.ResvMax=0;r=q.bits*C.mode_gr+Math.min(C.ResvSize,C.ResvMax);r>B&&(r=B);t.resvDrain_pre=0;null!=C.pinfo&&(C.pinfo.mean_bits= +q.bits/2,C.pinfo.resvsize=C.ResvSize);return r};this.ResvMaxBits=function(d,q,J,B){var t=d.internal_flags,r=t.ResvSize,g=t.ResvMax;0!=B&&(r+=q);0!=(t.substep_shaping&1)&&(g*=.9);J.bits=q;10*r>9*g?(B=r-9*g/10,J.bits+=B,t.substep_shaping|=128):(B=0,t.substep_shaping&=127,d.disable_reservoir||0!=(t.substep_shaping&1)||(J.bits-=.1*q));d=r<6*t.ResvMax/10?r:6*t.ResvMax/10;d-=B;0>d&&(d=0);return d};this.ResvAdjust=function(d,q){d.ResvSize-=q.part2_3_length+q.part2_length};this.ResvFrameEnd=function(d,q){var J, +B=d.l3_side;d.ResvSize+=q*d.mode_gr;var t=0;B.resvDrain_post=0;B.resvDrain_pre=0;0!=(J=d.ResvSize%8)&&(t+=J);J=d.ResvSize-t-d.ResvMax;0<J&&(t+=J);J=Math.min(8*B.main_data_begin,t)/8;B.resvDrain_pre+=8*J;t-=8*J;d.ResvSize-=8*J;B.main_data_begin-=J;B.resvDrain_post+=t;d.ResvSize-=t}}function ua(){function J(a,e,b){for(;0<b;){var d;0==z&&(z=8,E++,a.header[a.w_ptr].write_timing==f&&(d=a,K.arraycopy(d.header[d.w_ptr].buf,0,c,E,d.sideinfo_len),E+=d.sideinfo_len,f+=8*d.sideinfo_len,d.w_ptr=d.w_ptr+1&da.MAX_HEADER_BUF- +1),c[E]=0);d=Math.min(b,z);b-=d;z-=d;c[E]|=e>>b<<z;f+=d}}function k(a,c){var b=a.internal_flags,d;8<=c&&(J(b,76,8),c-=8);8<=c&&(J(b,65,8),c-=8);8<=c&&(J(b,77,8),c-=8);8<=c&&(J(b,69,8),c-=8);if(32<=c){var m=e.getLameShortVersion();if(32<=c)for(d=0;d<m.length&&8<=c;++d)c-=8,J(b,m.charAt(d),8)}for(;1<=c;--c)J(b,b.ancillary_flag,1),b.ancillary_flag^=a.disable_reservoir?0:1}function q(a,c,e){for(var b=a.header[a.h_ptr].ptr;0<e;){var m=Math.min(e,8-(b&7));e-=m;a.header[a.h_ptr].buf[b>>3]|=c>>e<<8-(b&7)- +m;b+=m}a.header[a.h_ptr].ptr=b}function C(a,c){a<<=8;for(var e=0;8>e;e++)a<<=1,c<<=1,0!=((c^a)&65536)&&(c^=32773);return c}function B(a,c){var e=r.ht[c.count1table_select+32],b,m=0,d=c.big_values,f=c.big_values;for(b=(c.count1-c.big_values)/4;0<b;--b){var n=0,g=0,h;h=c.l3_enc[d+0];0!=h&&(g+=8,0>c.xr[f+0]&&n++);h=c.l3_enc[d+1];0!=h&&(g+=4,n*=2,0>c.xr[f+1]&&n++);h=c.l3_enc[d+2];0!=h&&(g+=2,n*=2,0>c.xr[f+2]&&n++);h=c.l3_enc[d+3];0!=h&&(g++,n*=2,0>c.xr[f+3]&&n++);d+=4;f+=4;J(a,n+e.table[g],e.hlen[g]); +m+=e.hlen[g]}return m}function t(c,a,e,b,m){var d=r.ht[a],f=0;if(0==a)return f;for(;e<b;e+=2){var n=0,g=0,h=d.xlen,l=d.xlen,k=0,G=m.l3_enc[e],I=m.l3_enc[e+1];0!=G&&(0>m.xr[e]&&k++,n--);15<a&&(14<G&&(k|=G-15<<1,g=h,G=15),14<I&&(l=I-15,k<<=h,k|=l,g+=h,I=15),l=16);0!=I&&(k<<=1,0>m.xr[e+1]&&k++,n--);G=G*l+I;g-=n;n+=d.hlen[G];J(c,d.table[G],n);J(c,k,g);f+=n+g}return f}function H(c,a){var e=3*c.scalefac_band.s[3];e>a.big_values&&(e=a.big_values);var b=t(c,a.table_select[0],0,e,a);return b+=t(c,a.table_select[1], +e,a.big_values,a)}function g(c,a){var e,b,m,d;e=a.big_values;b=a.region0_count+1;m=c.scalefac_band.l[b];b+=a.region1_count+1;d=c.scalefac_band.l[b];m>e&&(m=e);d>e&&(d=e);b=t(c,a.table_select[0],0,m,a);b+=t(c,a.table_select[1],m,d,a);return b+=t(c,a.table_select[2],d,e,a)}function b(){this.total=0}function l(c,e){var b=c.internal_flags,d,m,n,g;g=b.w_ptr;n=b.h_ptr-1;-1==n&&(n=da.MAX_HEADER_BUF-1);d=b.header[n].write_timing-f;e.total=d;0<=d&&(m=1+n-g,n<g&&(m=1+n-g+da.MAX_HEADER_BUF),d-=8*m*b.sideinfo_len); +b=a.getframebits(c);d+=b;e.total+=b;e.total=0!=e.total%8?1+e.total/8:e.total/8;e.total+=E+1;0>d&&K.err.println("strange error flushing buffer ... \n");return d}var a=this,h=null,D=null,e=null,n=null;this.setModules=function(a,c,b,d){h=a;D=c;e=b;n=d};var c=null,f=0,E=0,z=0;this.getframebits=function(a){var c=a.internal_flags;return 8*(0|72E3*(a.version+1)*(0!=c.bitrate_index?r.bitrate_table[a.version][c.bitrate_index]:a.brate)/a.out_samplerate+c.padding)};this.CRC_writeheader=function(a,c){var e;e= +C(c[2]&255,65535);e=C(c[3]&255,e);for(var b=6;b<a.sideinfo_len;b++)e=C(c[b]&255,e);c[4]=byte(e>>8);c[5]=byte(e&255)};this.flush_bitstream=function(c){var a=c.internal_flags,e,d;e=a.l3_side;0>(d=l(c,new b))||(k(c,d),a.ResvSize=0,e.main_data_begin=0,a.findReplayGain&&(e=h.GetTitleGain(a.rgdata),a.RadioGain=Math.floor(10*e+.5)|0),a.findPeakSample&&(a.noclipGainChange=Math.ceil(200*Math.log10(a.PeakSample/32767))|0,0<a.noclipGainChange?EQ(c.scale,1)||EQ(c.scale,0)?a.noclipScale=Math.floor(32767/a.PeakSample* +100)/100:a.noclipScale=-1:a.noclipScale=-1))};this.add_dummy_byte=function(a,e,b){a=a.internal_flags;for(var d;0<b--;){d=e;for(var m=8;0<m;){var n;0==z&&(z=8,E++,c[E]=0);n=Math.min(m,z);m-=n;z-=n;c[E]|=d>>m<<z;f+=n}for(d=0;d<da.MAX_HEADER_BUF;++d)a.header[d].write_timing+=8}};this.format_bitstream=function(a){var c=a.internal_flags,e;e=c.l3_side;var n=this.getframebits(a);k(a,e.resvDrain_pre);var m=a.internal_flags,h,y,E;h=m.l3_side;m.header[m.h_ptr].ptr=0;Ia.fill(m.header[m.h_ptr].buf,0,m.sideinfo_len, +0);16E3>a.out_samplerate?q(m,4094,12):q(m,4095,12);q(m,a.version,1);q(m,1,2);q(m,a.error_protection?0:1,1);q(m,m.bitrate_index,4);q(m,m.samplerate_index,2);q(m,m.padding,1);q(m,a.extension,1);q(m,a.mode.ordinal(),2);q(m,m.mode_ext,2);q(m,a.copyright,1);q(m,a.original,1);q(m,a.emphasis,2);a.error_protection&&q(m,0,16);if(1==a.version){q(m,h.main_data_begin,9);2==m.channels_out?q(m,h.private_bits,3):q(m,h.private_bits,5);for(E=0;E<m.channels_out;E++)for(y=0;4>y;y++)q(m,h.scfsi[E][y],1);for(y=0;2>y;y++)for(E= +0;E<m.channels_out;E++){var u=h.tt[y][E];q(m,u.part2_3_length+u.part2_length,12);q(m,u.big_values/2,9);q(m,u.global_gain,8);q(m,u.scalefac_compress,4);u.block_type!=d.NORM_TYPE?(q(m,1,1),q(m,u.block_type,2),q(m,u.mixed_block_flag,1),14==u.table_select[0]&&(u.table_select[0]=16),q(m,u.table_select[0],5),14==u.table_select[1]&&(u.table_select[1]=16),q(m,u.table_select[1],5),q(m,u.subblock_gain[0],3),q(m,u.subblock_gain[1],3),q(m,u.subblock_gain[2],3)):(q(m,0,1),14==u.table_select[0]&&(u.table_select[0]= +16),q(m,u.table_select[0],5),14==u.table_select[1]&&(u.table_select[1]=16),q(m,u.table_select[1],5),14==u.table_select[2]&&(u.table_select[2]=16),q(m,u.table_select[2],5),q(m,u.region0_count,4),q(m,u.region1_count,3));q(m,u.preflag,1);q(m,u.scalefac_scale,1);q(m,u.count1table_select,1)}}else for(q(m,h.main_data_begin,8),q(m,h.private_bits,m.channels_out),E=y=0;E<m.channels_out;E++)u=h.tt[y][E],q(m,u.part2_3_length+u.part2_length,12),q(m,u.big_values/2,9),q(m,u.global_gain,8),q(m,u.scalefac_compress, +9),u.block_type!=d.NORM_TYPE?(q(m,1,1),q(m,u.block_type,2),q(m,u.mixed_block_flag,1),14==u.table_select[0]&&(u.table_select[0]=16),q(m,u.table_select[0],5),14==u.table_select[1]&&(u.table_select[1]=16),q(m,u.table_select[1],5),q(m,u.subblock_gain[0],3),q(m,u.subblock_gain[1],3),q(m,u.subblock_gain[2],3)):(q(m,0,1),14==u.table_select[0]&&(u.table_select[0]=16),q(m,u.table_select[0],5),14==u.table_select[1]&&(u.table_select[1]=16),q(m,u.table_select[1],5),14==u.table_select[2]&&(u.table_select[2]=16), +q(m,u.table_select[2],5),q(m,u.region0_count,4),q(m,u.region1_count,3)),q(m,u.scalefac_scale,1),q(m,u.count1table_select,1);a.error_protection&&CRC_writeheader(m,m.header[m.h_ptr].buf);h=m.h_ptr;m.h_ptr=h+1&da.MAX_HEADER_BUF-1;m.header[m.h_ptr].write_timing=m.header[h].write_timing+n;m.h_ptr==m.w_ptr&&K.err.println("Error: MAX_HEADER_BUF too small in bitstream.c \n");var m=8*c.sideinfo_len,z=0,t=a.internal_flags,F=t.l3_side;if(1==a.version)for(h=0;2>h;h++)for(E=0;E<t.channels_out;E++){var G=F.tt[h][E], +I=tb.slen1_tab[G.scalefac_compress],T=tb.slen2_tab[G.scalefac_compress];for(y=u=0;y<G.sfbdivide;y++)-1!=G.scalefac[y]&&(J(t,G.scalefac[y],I),u+=I);for(;y<G.sfbmax;y++)-1!=G.scalefac[y]&&(J(t,G.scalefac[y],T),u+=T);u=G.block_type==d.SHORT_TYPE?u+H(t,G):u+g(t,G);u+=B(t,G);z+=u}else for(E=h=0;E<t.channels_out;E++){var G=F.tt[h][E],U=0,T=y=u=0;if(G.block_type==d.SHORT_TYPE){for(;4>T;T++)for(var D=G.sfb_partition_table[T]/3,ia=G.slen[T],I=0;I<D;I++,y++)J(t,Math.max(G.scalefac[3*y+0],0),ia),J(t,Math.max(G.scalefac[3* +y+1],0),ia),J(t,Math.max(G.scalefac[3*y+2],0),ia),U+=3*ia;u+=H(t,G)}else{for(;4>T;T++)for(D=G.sfb_partition_table[T],ia=G.slen[T],I=0;I<D;I++,y++)J(t,Math.max(G.scalefac[y],0),ia),U+=ia;u+=g(t,G)}u+=B(t,G);z+=U+u}m+=z;k(a,e.resvDrain_post);m+=e.resvDrain_post;e.main_data_begin+=(n-m)/8;l(a,new b)!=c.ResvSize&&K.err.println("Internal buffer inconsistency. flushbits <> ResvSize");8*e.main_data_begin!=c.ResvSize&&(K.err.printf("bit reservoir error: \nl3_side.main_data_begin: %d \nResvoir size: %d \nresv drain (post) %d \nresv drain (pre) %d \nheader and sideinfo: %d \ndata bits: %d \ntotal bits: %d (remainder: %d) \nbitsperframe: %d \n", +8*e.main_data_begin,c.ResvSize,e.resvDrain_post,e.resvDrain_pre,8*c.sideinfo_len,m-e.resvDrain_post-8*c.sideinfo_len,m,m%8,n),K.err.println("This is a fatal error. It has several possible causes:"),K.err.println("90%% LAME compiled with buggy version of gcc using advanced optimizations"),K.err.println(" 9%% Your system is overclocked"),K.err.println(" 1%% bug in LAME encoding library"),c.ResvSize=8*e.main_data_begin);if(1E9<f){for(a=0;a<da.MAX_HEADER_BUF;++a)c.header[a].write_timing-=f;f=0}return 0}; +this.copy_buffer=function(a,e,b,d,m){var f=E+1;if(0>=f)return 0;if(0!=d&&f>d)return-1;K.arraycopy(c,0,e,b,f);E=-1;z=0;if(0!=m&&(d=Y(1),d[0]=a.nMusicCRC,n.updateMusicCRC(d,e,b,f),a.nMusicCRC=d[0],0<f&&(a.VBR_seek_table.nBytesWritten+=f),a.decode_on_the_fly)){d=ra([2,1152]);m=f;for(var g=-1,l;0!=g;)if(g=D.hip_decode1_unclipped(a.hip,e,b,m,d[0],d[1]),m=0,-1==g&&(g=0),0<g){if(a.findPeakSample){for(l=0;l<g;l++)d[0][l]>a.PeakSample?a.PeakSample=d[0][l]:-d[0][l]>a.PeakSample&&(a.PeakSample=-d[0][l]);if(1< +a.channels_out)for(l=0;l<g;l++)d[1][l]>a.PeakSample?a.PeakSample=d[1][l]:-d[1][l]>a.PeakSample&&(a.PeakSample=-d[1][l])}if(a.findReplayGain&&h.AnalyzeSamples(a.rgdata,d[0],0,d[1],0,g,a.channels_out)==O.GAIN_ANALYSIS_ERROR)return-6}}return f};this.init_bit_stream_w=function(a){c=new Int8Array(V.LAME_MAXMP3BUFFER);a.h_ptr=a.w_ptr=0;a.header[a.h_ptr].write_timing=0;E=-1;f=z=0}}function ub(){function d(a,b){var c=a[b+0]&255,c=c<<8|a[b+1]&255,c=c<<8,c=c|a[b+2]&255,c=c<<8;return c|=a[b+3]&255}function k(a, +b,c){a[b+0]=c>>24&255;a[b+1]=c>>16&255;a[b+2]=c>>8&255;a[b+3]=c&255}function q(a,b,c){a[b+0]=c>>8&255;a[b+1]=c&255}function C(a,b,c){return 255&(a<<b|c&~(-1<<b))}function B(a,b){var c=a.internal_flags;b[0]=C(b[0],8,255);b[1]=C(b[1],3,7);b[1]=C(b[1],1,16E3>a.out_samplerate?0:1);b[1]=C(b[1],1,a.version);b[1]=C(b[1],2,1);b[1]=C(b[1],1,a.error_protection?0:1);b[2]=C(b[2],4,c.bitrate_index);b[2]=C(b[2],2,c.samplerate_index);b[2]=C(b[2],1,0);b[2]=C(b[2],1,a.extension);b[3]=C(b[3],2,a.mode.ordinal());b[3]= +C(b[3],2,c.mode_ext);b[3]=C(b[3],1,a.copyright);b[3]=C(b[3],1,a.original);b[3]=C(b[3],2,a.emphasis);b[0]=255;var c=b[1]&241,d;d=1==a.version?128:16E3>a.out_samplerate?32:64;a.VBR==M.vbr_off&&(d=a.brate);d=a.free_format?0:255&16*H.BitrateIndex(d,a.version,a.out_samplerate);b[1]=1==a.version?255&(c|10):255&(c|2);c=b[2]&13;b[2]=255&(d|c)}function t(a,b){return b=b>>8^D[(b^a)&255]}var H,g,b;this.setModules=function(a,d,c){H=a;g=d;b=c};var l=ub.NUMTOCENTRIES,a=ub.MAXFRAMESIZE,h=l+4+4+4+4+4+9+1+1+8+1+1+ +3+1+1+2+4+2+2,D=[0,49345,49537,320,49921,960,640,49729,50689,1728,1920,51009,1280,50625,50305,1088,52225,3264,3456,52545,3840,53185,52865,3648,2560,51905,52097,2880,51457,2496,2176,51265,55297,6336,6528,55617,6912,56257,55937,6720,7680,57025,57217,8E3,56577,7616,7296,56385,5120,54465,54657,5440,55041,6080,5760,54849,53761,4800,4992,54081,4352,53697,53377,4160,61441,12480,12672,61761,13056,62401,62081,12864,13824,63169,63361,14144,62721,13760,13440,62529,15360,64705,64897,15680,65281,16320,16E3,65089, +64001,15040,15232,64321,14592,63937,63617,14400,10240,59585,59777,10560,60161,11200,10880,59969,60929,11968,12160,61249,11520,60865,60545,11328,58369,9408,9600,58689,9984,59329,59009,9792,8704,58049,58241,9024,57601,8640,8320,57409,40961,24768,24960,41281,25344,41921,41601,25152,26112,42689,42881,26432,42241,26048,25728,42049,27648,44225,44417,27968,44801,28608,28288,44609,43521,27328,27520,43841,26880,43457,43137,26688,30720,47297,47489,31040,47873,31680,31360,47681,48641,32448,32640,48961,32E3, +48577,48257,31808,46081,29888,30080,46401,30464,47041,46721,30272,29184,45761,45953,29504,45313,29120,28800,45121,20480,37057,37249,20800,37633,21440,21120,37441,38401,22208,22400,38721,21760,38337,38017,21568,39937,23744,23936,40257,24320,40897,40577,24128,23040,39617,39809,23360,39169,22976,22656,38977,34817,18624,18816,35137,19200,35777,35457,19008,19968,36545,36737,20288,36097,19904,19584,35905,17408,33985,34177,17728,34561,18368,18048,34369,33281,17088,17280,33601,16640,33217,32897,16448];this.addVbrFrame= +function(a){var b=a.internal_flags;var c=b.VBR_seek_table;a=r.bitrate_table[a.version][b.bitrate_index];c.nVbrNumFrames++;c.sum+=a;c.seen++;if(!(c.seen<c.want)&&(c.pos<c.size&&(c.bag[c.pos]=c.sum,c.pos++,c.seen=0),c.pos==c.size)){for(a=1;a<c.size;a+=2)c.bag[a/2]=c.bag[a];c.want*=2;c.pos/=2}};this.getVbrTag=function(a){var b=new VBRTagData,c=0;b.flags=0;var f=a[c+1]>>3&1,g=a[c+2]>>2&3,h=a[c+3]>>6&3,k=a[c+2]>>4&15,k=r.bitrate_table[f][k];b.samprate=14==a[c+1]>>4?r.samplerate_table[2][g]:r.samplerate_table[f][g]; +g=c=0!=f?3!=h?c+36:c+21:3!=h?c+21:c+13;if(!(new String(a,g,4(),null)).equals("Xing")&&!(new String(a,g,4(),null)).equals("Info"))return null;c+=4;b.hId=f;g=b.flags=d(a,c);c+=4;0!=(g&1)&&(b.frames=d(a,c),c+=4);0!=(g&2)&&(b.bytes=d(a,c),c+=4);if(0!=(g&4)){if(null!=b.toc)for(h=0;h<l;h++)b.toc[h]=a[c+h];c+=l}b.vbrScale=-1;0!=(g&8)&&(b.vbrScale=d(a,c),c+=4);b.headersize=72E3*(f+1)*k/b.samprate;c+=21;f=a[c+0]<<4;f+=a[c+1]>>4;k=(a[c+1]&15)<<8;k+=a[c+2]&255;if(0>f||3E3<f)f=-1;if(0>k||3E3<k)k=-1;b.encDelay= +f;b.encPadding=k;return b};this.InitVbrTag=function(b){var d=b.internal_flags,c;c=1==b.version?128:16E3>b.out_samplerate?32:64;b.VBR==M.vbr_off&&(c=b.brate);c=72E3*(b.version+1)*c/b.out_samplerate;var f=d.sideinfo_len+h;d.VBR_seek_table.TotalFrameSize=c;if(c<f||c>a)b.bWriteVbrTag=!1;else for(d.VBR_seek_table.nVbrNumFrames=0,d.VBR_seek_table.nBytesWritten=0,d.VBR_seek_table.sum=0,d.VBR_seek_table.seen=0,d.VBR_seek_table.want=1,d.VBR_seek_table.pos=0,null==d.VBR_seek_table.bag&&(d.VBR_seek_table.bag= +new int[400],d.VBR_seek_table.size=400),c=new Int8Array(a),B(b,c),d=d.VBR_seek_table.TotalFrameSize,f=0;f<d;++f)g.add_dummy_byte(b,c[f]&255,1)};this.updateMusicCRC=function(a,b,c,d){for(var g=0;g<d;++g)a[0]=t(b[c+g],a[0])};this.getLameTagFrame=function(a,d){var c=a.internal_flags;if(!a.bWriteVbrTag||c.Class_ID!=V.LAME_ID||0>=c.VBR_seek_table.pos)return 0;if(d.length<c.VBR_seek_table.TotalFrameSize)return c.VBR_seek_table.TotalFrameSize;Ia.fill(d,0,c.VBR_seek_table.TotalFrameSize,0);B(a,d);var f=new Int8Array(l); +if(a.free_format)for(var h=1;h<l;++h)f[h]=255&255*h/100;else{var z=c.VBR_seek_table;if(!(0>=z.pos))for(h=1;h<l;++h){var w=0|Math.floor(h/l*z.pos);w>z.pos-1&&(w=z.pos-1);w=0|256*z.bag[w]/z.sum;255<w&&(w=255);f[h]=255&w}}w=c.sideinfo_len;a.error_protection&&(w-=2);d[w++]=0;d[w++]=0;d[w++]=0;d[w++]=0;k(d,w,15);w+=4;k(d,w,c.VBR_seek_table.nVbrNumFrames);w+=4;z=c.VBR_seek_table.nBytesWritten+c.VBR_seek_table.TotalFrameSize;k(d,w,0|z);w+=4;K.arraycopy(f,0,d,w,f.length);w+=f.length;a.error_protection&&g.CRC_writeheader(c, +d);for(var A=0,h=0;h<w;h++)A=t(d[h],A);var f=w,h=A,v=a.internal_flags,w=0,A=a.encoder_delay,p=a.encoder_padding,m=100-10*a.VBR_q-a.quality,x=b.getLameVeryShortVersion(),y;y=[1,5,3,2,4,0,3];var W=0|(255<a.lowpassfreq/100+.5?255:a.lowpassfreq/100+.5),u=0,D=0,J=a.internal_flags.noise_shaping,F=0,G=0,I=0,T=0,F=0,F=0!=(a.exp_nspsytune&1),I=0!=(a.exp_nspsytune&2),U=!1,qa=!1,ia=a.internal_flags.nogap_total,ya=a.internal_flags.nogap_current,T=a.ATHtype,r=0,C;switch(a.VBR){case vbr_abr:C=a.VBR_mean_bitrate_kbps; +break;case vbr_off:C=a.brate;break;default:C=a.VBR_min_bitrate_kbps}y=0+(a.VBR.ordinal()<y.length?y[a.VBR.ordinal()]:0);v.findReplayGain&&(510<v.RadioGain&&(v.RadioGain=510),-510>v.RadioGain&&(v.RadioGain=-510),D=11264,D=0<=v.RadioGain?D|v.RadioGain:D|512|-v.RadioGain);v.findPeakSample&&(u=Math.abs(0|v.PeakSample/32767*Math.pow(2,23)+.5));-1!=ia&&(0<ya&&(qa=!0),ya<ia-1&&(U=!0));r=T+((F?1:0)<<4)+((I?1:0)<<5)+((U?1:0)<<6)+((qa?1:0)<<7);0>m&&(m=0);switch(a.mode){case MONO:F=0;break;case STEREO:F=1;break; +case DUAL_CHANNEL:F=2;break;case JOINT_STEREO:F=a.force_ms?4:3;break;default:F=7}I=32E3>=a.in_samplerate?0:48E3==a.in_samplerate?2:48E3<a.in_samplerate?3:1;if(a.short_blocks==sa.short_block_forced||a.short_blocks==sa.short_block_dispensed||-1==a.lowpassfreq&&-1==a.highpassfreq||a.scale_left<a.scale_right||a.scale_left>a.scale_right||a.disable_reservoir&&320>a.brate||a.noATH||a.ATHonly||0==T||32E3>=a.in_samplerate)G=1;T=J+(F<<2)+(G<<5)+(I<<6);F=v.nMusicCRC;k(d,f+w,m);w+=4;for(v=0;9>v;v++)d[f+w+v]= +255&x.charAt(v);w+=9;d[f+w]=255&y;w++;d[f+w]=255&W;w++;k(d,f+w,u);w+=4;q(d,f+w,D);w+=2;q(d,f+w,0);w+=2;d[f+w]=255&r;w++;d[f+w]=255<=C?255:255&C;w++;d[f+w]=255&A>>4;d[f+w+1]=255&(A<<4)+(p>>8);d[f+w+2]=255&p;w+=3;d[f+w]=255&T;w++;d[f+w++]=0;q(d,f+w,a.preset);w+=2;k(d,f+w,z);w+=4;q(d,f+w,F);w+=2;for(z=0;z<w;z++)h=t(d[f+z],h);q(d,f+w,h);return c.VBR_seek_table.TotalFrameSize};this.putVbrTag=function(b,d){if(0>=b.internal_flags.VBR_seek_table.pos)return-1;d.seek(d.length());if(0==d.length())return-1;d.seek(0); +var c=new Int8Array(10);d.readFully(c);c=(new String(c,"ISO-8859-1")).startsWith("ID3")?0:((c[6]&127)<<21|(c[7]&127)<<14|(c[8]&127)<<7|c[9]&127)+c.length;d.seek(c);var c=new Int8Array(a),f=getLameTagFrame(b,c);if(f>c.length)return-1;if(1>f)return 0;d.write(c,0,f);return 0}}function Q(d,k,q,r){this.xlen=d;this.linmax=k;this.table=q;this.hlen=r}function eb(d){this.bits=d}function Ic(){this.setModules=function(d,k){}}function $b(){this.bits=this.over_SSD=this.over_count=this.max_noise=this.tot_noise= +this.over_noise=0}function Jc(){this.scale_right=this.scale_left=this.scale=this.out_samplerate=this.in_samplerate=this.num_channels=this.num_samples=this.class_id=0;this.decode_only=this.bWriteVbrTag=this.analysis=!1;this.quality=0;this.mode=ka.STEREO;this.write_id3tag_automatic=this.decode_on_the_fly=this.findReplayGain=this.free_format=this.force_ms=!1;this.error_protection=this.emphasis=this.extension=this.original=this.copyright=this.compression_ratio=this.brate=0;this.disable_reservoir=this.strict_ISO= +!1;this.quant_comp_short=this.quant_comp=0;this.experimentalY=!1;this.preset=this.exp_nspsytune=this.experimentalZ=0;this.VBR=null;this.maskingadjust_short=this.maskingadjust=this.highpasswidth=this.lowpasswidth=this.highpassfreq=this.lowpassfreq=this.VBR_hard_min=this.VBR_max_bitrate_kbps=this.VBR_min_bitrate_kbps=this.VBR_mean_bitrate_kbps=this.VBR_q=this.VBR_q_frac=0;this.noATH=this.ATHshort=this.ATHonly=!1;this.athaa_sensitivity=this.athaa_loudapprox=this.athaa_type=this.ATHlower=this.ATHcurve= +this.ATHtype=0;this.short_blocks=null;this.useTemporal=!1;this.msfix=this.interChRatio=0;this.tune=!1;this.lame_allocated_gfp=this.frameNum=this.framesize=this.encoder_padding=this.encoder_delay=this.version=this.tune_value_a=0;this.internal_flags=null}function Kc(){this.linprebuf=H(2*O.MAX_ORDER);this.linpre=0;this.lstepbuf=H(O.MAX_SAMPLES_PER_WINDOW+O.MAX_ORDER);this.lstep=0;this.loutbuf=H(O.MAX_SAMPLES_PER_WINDOW+O.MAX_ORDER);this.lout=0;this.rinprebuf=H(2*O.MAX_ORDER);this.rinpre=0;this.rstepbuf= +H(O.MAX_SAMPLES_PER_WINDOW+O.MAX_ORDER);this.rstep=0;this.routbuf=H(O.MAX_SAMPLES_PER_WINDOW+O.MAX_ORDER);this.first=this.freqindex=this.rsum=this.lsum=this.totsamp=this.sampleWindow=this.rout=0;this.A=Y(0|O.STEPS_per_dB*O.MAX_dB);this.B=Y(0|O.STEPS_per_dB*O.MAX_dB)}function Lc(){this.floor=this.decay=this.adjustLimit=this.adjust=this.aaSensitivityP=this.useAdjust=0;this.l=H(d.SBMAX_l);this.s=H(d.SBMAX_s);this.psfb21=H(d.PSFB21);this.psfb12=H(d.PSFB12);this.cb_l=H(d.CBANDS);this.cb_s=H(d.CBANDS); +this.eql_w=H(d.BLKSIZE/2)}function Mc(J){this.quantize=J;this.iteration_loop=function(k,q,J,B){var t=k.internal_flags,r=H(na.SFBMAX),g=H(576),b=Y(2),l,a,h=t.l3_side;l=new eb(0);this.quantize.rv.ResvFrameBegin(k,l);l=l.bits;for(var D=0;D<t.mode_gr;D++)for(a=this.quantize.qupvt.on_pe(k,q,b,l,D,D),t.mode_ext==d.MPG_MD_MS_LR&&(this.quantize.ms_convert(t.l3_side,D),this.quantize.qupvt.reduce_side(b,J[D],l,a)),a=0;a<t.channels_out;a++){var e,n=h.tt[D][a];n.block_type!=d.SHORT_TYPE?(e=0,e=t.PSY.mask_adjust- +e):(e=0,e=t.PSY.mask_adjust_short-e);t.masking_lower=Math.pow(10,.1*e);this.quantize.init_outer_loop(t,n);this.quantize.init_xrpow(t,n,g)&&(this.quantize.qupvt.calc_xmin(k,B[D][a],n,r),this.quantize.outer_loop(k,n,r,g,a,b[a]));this.quantize.iteration_finish_one(t,D,a)}this.quantize.rv.ResvFrameEnd(t,l)}}function ha(J,k,q,r){this.l=Y(1+d.SBMAX_l);this.s=Y(1+d.SBMAX_s);this.psfb21=Y(1+d.PSFB21);this.psfb12=Y(1+d.PSFB12);var B=this.l,t=this.s;4==arguments.length&&(this.arrL=arguments[0],this.arrS=arguments[1], +this.arr21=arguments[2],this.arr12=arguments[3],K.arraycopy(this.arrL,0,B,0,Math.min(this.arrL.length,this.l.length)),K.arraycopy(this.arrS,0,t,0,Math.min(this.arrS.length,this.s.length)),K.arraycopy(this.arr21,0,this.psfb21,0,Math.min(this.arr21.length,this.psfb21.length)),K.arraycopy(this.arr12,0,this.psfb12,0,Math.min(this.arr12.length,this.psfb12.length)))}function ma(){function J(a,b){var c=B.ATHformula(b,a);return c=Math.pow(10,(c-100)/10+a.ATHlower)}function k(a){this.s=a}var q=null,r=null, +B=null;this.setModules=function(a,b,c){q=a;r=b;B=c};this.IPOW20=function(b){return a[b]};var t=ma.IXMAX_VAL+2,ta=ma.Q_MAX,g=ma.Q_MAX2;this.nr_of_sfb_block=[[[6,5,5,5],[9,9,9,9],[6,9,9,9]],[[6,5,7,3],[9,9,12,6],[6,9,12,6]],[[11,10,0,0],[18,18,0,0],[15,18,0,0]],[[7,7,7,0],[12,12,12,0],[6,15,12,0]],[[6,6,6,3],[12,9,9,6],[6,12,9,6]],[[8,8,5,0],[15,12,9,0],[6,18,9,0]]];var b=[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0];this.pretab=b;this.sfBandIndex=[new ha([0,6,12,18,24,30,36,44,54,66,80,96,116,140, +168,200,238,284,336,396,464,522,576],[0,4,8,12,18,24,32,42,56,74,100,132,174,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new ha([0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,332,394,464,540,576],[0,4,8,12,18,26,36,48,62,80,104,136,180,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new ha([0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576],[0,4,8,12,18,26,36,48,62,80,104,134,174,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new ha([0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162, +196,238,288,342,418,576],[0,4,8,12,16,22,30,40,52,66,84,106,136,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new ha([0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576],[0,4,8,12,16,22,28,38,50,64,80,100,126,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new ha([0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576],[0,4,8,12,16,22,30,42,58,78,104,138,180,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new ha([0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464, +522,576],[0,4,8,12,18,26,36,48,62,80,104,134,174,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new ha([0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576],[0,4,8,12,18,26,36,48,62,80,104,134,174,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new ha([0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576],[0,8,16,24,36,52,72,96,124,160,162,164,166,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0])];var l=H(ta+g+1),a=H(ta),h=H(t),D=H(t);this.adj43=D;this.iteration_init=function(b){var n= +b.internal_flags,c=n.l3_side;if(0==n.iteration_init_init){n.iteration_init_init=1;c.main_data_begin=0;for(var c=b.internal_flags.ATH.l,f=b.internal_flags.ATH.psfb21,k=b.internal_flags.ATH.s,z=b.internal_flags.ATH.psfb12,w=b.internal_flags,A=b.out_samplerate,v=0;v<d.SBMAX_l;v++){var p=w.scalefac_band.l[v],m=w.scalefac_band.l[v+1];for(c[v]=vb.MAX_VALUE;p<m;p++){var x=p*A/1152,x=J(b,x);c[v]=Math.min(c[v],x)}}for(v=0;v<d.PSFB21;v++)for(p=w.scalefac_band.psfb21[v],m=w.scalefac_band.psfb21[v+1],f[v]=vb.MAX_VALUE;p< +m;p++)x=p*A/1152,x=J(b,x),f[v]=Math.min(f[v],x);for(v=0;v<d.SBMAX_s;v++){p=w.scalefac_band.s[v];m=w.scalefac_band.s[v+1];for(k[v]=vb.MAX_VALUE;p<m;p++)x=p*A/384,x=J(b,x),k[v]=Math.min(k[v],x);k[v]*=w.scalefac_band.s[v+1]-w.scalefac_band.s[v]}for(v=0;v<d.PSFB12;v++){p=w.scalefac_band.psfb12[v];m=w.scalefac_band.psfb12[v+1];for(z[v]=vb.MAX_VALUE;p<m;p++)x=p*A/384,x=J(b,x),z[v]=Math.min(z[v],x);z[v]*=w.scalefac_band.s[13]-w.scalefac_band.s[12]}if(b.noATH){for(v=0;v<d.SBMAX_l;v++)c[v]=1E-20;for(v=0;v< +d.PSFB21;v++)f[v]=1E-20;for(v=0;v<d.SBMAX_s;v++)k[v]=1E-20;for(v=0;v<d.PSFB12;v++)z[v]=1E-20}w.ATH.floor=10*Math.log10(J(b,-1));h[0]=0;for(c=1;c<t;c++)h[c]=Math.pow(c,4/3);for(c=0;c<t-1;c++)D[c]=c+1-Math.pow(.5*(h[c]+h[c+1]),.75);D[c]=.5;for(c=0;c<ta;c++)a[c]=Math.pow(2,-.1875*(c-210));for(c=0;c<=ta+g;c++)l[c]=Math.pow(2,.25*(c-210-g));q.huffman_init(n);c=b.exp_nspsytune>>2&63;32<=c&&(c-=64);f=Math.pow(10,c/4/10);c=b.exp_nspsytune>>8&63;32<=c&&(c-=64);k=Math.pow(10,c/4/10);c=b.exp_nspsytune>>14&63; +32<=c&&(c-=64);z=Math.pow(10,c/4/10);c=b.exp_nspsytune>>20&63;32<=c&&(c-=64);b=z*Math.pow(10,c/4/10);for(c=0;c<d.SBMAX_l;c++)w=6>=c?f:13>=c?k:20>=c?z:b,n.nsPsy.longfact[c]=w;for(c=0;c<d.SBMAX_s;c++)w=5>=c?f:10>=c?k:11>=c?z:b,n.nsPsy.shortfact[c]=w}};this.on_pe=function(a,b,c,d,g,h){var l=a.internal_flags,k=0,v=Y(2),p,k=new eb(k);a=r.ResvMaxBits(a,d,k,h);var k=k.bits,m=k+a;m>da.MAX_BITS_PER_GRANULE&&(m=da.MAX_BITS_PER_GRANULE);for(p=h=0;p<l.channels_out;++p)c[p]=Math.min(da.MAX_BITS_PER_CHANNEL,k/ +l.channels_out),v[p]=0|c[p]*b[g][p]/700-c[p],v[p]>3*d/4&&(v[p]=3*d/4),0>v[p]&&(v[p]=0),v[p]+c[p]>da.MAX_BITS_PER_CHANNEL&&(v[p]=Math.max(0,da.MAX_BITS_PER_CHANNEL-c[p])),h+=v[p];if(h>a)for(p=0;p<l.channels_out;++p)v[p]=a*v[p]/h;for(p=0;p<l.channels_out;++p)c[p]+=v[p],a-=v[p];for(p=h=0;p<l.channels_out;++p)h+=c[p];if(h>da.MAX_BITS_PER_GRANULE)for(p=0;p<l.channels_out;++p)c[p]*=da.MAX_BITS_PER_GRANULE,c[p]/=h;return m};this.reduce_side=function(a,b,c,d){b=.33*(.5-b)/.5;0>b&&(b=0);.5<b&&(b=.5);b=0|.5* +b*(a[0]+a[1]);b>da.MAX_BITS_PER_CHANNEL-a[0]&&(b=da.MAX_BITS_PER_CHANNEL-a[0]);0>b&&(b=0);125<=a[1]&&(125<a[1]-b?(a[0]<c&&(a[0]+=b),a[1]-=b):(a[0]+=a[1]-125,a[1]=125));b=a[0]+a[1];b>d&&(a[0]=d*a[0]/b,a[1]=d*a[1]/b)};this.athAdjust=function(a,b,c){b=X.FAST_LOG10_X(b,10);a*=a;var d=0;b-=c;1E-20<a&&(d=1+X.FAST_LOG10_X(a,10/90.30873362));0>d&&(d=0);b=b*d+(c+90.30873362-94.82444863);return Math.pow(10,.1*b)};this.calc_xmin=function(a,b,c,f){var g=0,h=a.internal_flags,l,k=0,v=0,p=h.ATH,m=c.xr,x=a.VBR== +M.vbr_mtrh?1:0,y=h.masking_lower;if(a.VBR==M.vbr_mtrh||a.VBR==M.vbr_mt)y=1;for(l=0;l<c.psy_lmax;l++){var q,u,t,D,F,G;u=a.VBR==M.vbr_rh||a.VBR==M.vbr_mtrh?athAdjust(p.adjust,p.l[l],p.floor):p.adjust*p.l[l];F=c.width[l];t=u/F;D=2.220446049250313E-16;G=F>>1;q=0;do{var I;I=m[k]*m[k];q+=I;D+=I<t?I:t;k++;I=m[k]*m[k];q+=I;D+=I<t?I:t;k++}while(0<--G);q>u&&v++;l==d.SBPSY_l&&(t=u*h.nsPsy.longfact[l],D<t&&(D=t));0!=x&&(u=D);a.ATHonly||(D=b.en.l[l],0<D&&(t=q*b.thm.l[l]*y/D,0!=x&&(t*=h.nsPsy.longfact[l]),u<t&& +(u=t)));0!=x?f[g++]=u:f[g++]=u*h.nsPsy.longfact[l]}q=575;if(c.block_type!=d.SHORT_TYPE)for(u=576;0!=u--&&ua.EQ(m[u],0);)q=u;c.max_nonzero_coeff=q;for(var T=c.sfb_smin;l<c.psymax;T++,l+=3){var U,J;J=a.VBR==M.vbr_rh||a.VBR==M.vbr_mtrh?athAdjust(p.adjust,p.s[T],p.floor):p.adjust*p.s[T];F=c.width[l];for(U=0;3>U;U++){q=0;G=F>>1;t=J/F;D=2.220446049250313E-16;do I=m[k]*m[k],q+=I,D+=I<t?I:t,k++,I=m[k]*m[k],q+=I,D+=I<t?I:t,k++;while(0<--G);q>J&&v++;T==d.SBPSY_s&&(t=J*h.nsPsy.shortfact[T],D<t&&(D=t));u=0!= +x?D:J;a.ATHonly||a.ATHshort||(D=b.en.s[T][U],0<D&&(t=q*b.thm.s[T][U]*y/D,0!=x&&(t*=h.nsPsy.shortfact[T]),u<t&&(u=t)));0!=x?f[g++]=u:f[g++]=u*h.nsPsy.shortfact[T]}a.useTemporal&&(f[g-3]>f[g-3+1]&&(f[g-3+1]+=(f[g-3]-f[g-3+1])*h.decay),f[g-3+1]>f[g-3+2]&&(f[g-3+2]+=(f[g-3+1]-f[g-3+2])*h.decay))}return v};this.calc_noise_core=function(a,b,c,d){var g=0,l=b.s,k=a.l3_enc;if(l>a.count1)for(;0!=c--;){var q;q=a.xr[l];l++;g+=q*q;q=a.xr[l];l++;g+=q*q}else if(l>a.big_values){var v=H(2);v[0]=0;for(v[1]=d;0!=c--;)q= +Math.abs(a.xr[l])-v[k[l]],l++,g+=q*q,q=Math.abs(a.xr[l])-v[k[l]],l++,g+=q*q}else for(;0!=c--;)q=Math.abs(a.xr[l])-h[k[l]]*d,l++,g+=q*q,q=Math.abs(a.xr[l])-h[k[l]]*d,l++,g+=q*q;b.s=l;return g};this.calc_noise=function(a,d,c,f,g){var h=0,q=0,t,v,p=0,m=0,x=0,y=-20,D=0,u=a.scalefac,J=0;for(t=f.over_SSD=0;t<a.psymax;t++){var B=a.global_gain-(u[J++]+(0!=a.preflag?b[t]:0)<<a.scalefac_scale+1)-8*a.subblock_gain[a.window[t]],F=0;null!=g&&g.step[t]==B?(F=g.noise[t],D+=a.width[t],c[h++]=F/d[q++],F=g.noise_log[t]): +(F=l[B+ma.Q_MAX2],v=a.width[t]>>1,D+a.width[t]>a.max_nonzero_coeff&&(v=a.max_nonzero_coeff-D+1,v=0<v?v>>1:0),D=new k(D),F=this.calc_noise_core(a,D,v,F),D=D.s,null!=g&&(g.step[t]=B,g.noise[t]=F),F=c[h++]=F/d[q++],F=X.FAST_LOG10(Math.max(F,1E-20)),null!=g&&(g.noise_log[t]=F));null!=g&&(g.global_gain=a.global_gain);x+=F;0<F&&(B=Math.max(0|10*F+.5,1),f.over_SSD+=B*B,p++,m+=F);y=Math.max(y,F)}f.over_count=p;f.tot_noise=x;f.over_noise=m;f.max_noise=y;return p};this.set_pinfo=function(a,g,c,f,h){var l=a.internal_flags, +k,q,t,p,m=0==g.scalefac_scale?.5:1,x=g.scalefac,y=H(na.SFBMAX),D=H(na.SFBMAX),u=new $b;calc_xmin(a,c,g,y);calc_noise(g,y,D,u,null);var J=0;q=g.sfb_lmax;g.block_type!=d.SHORT_TYPE&&0==g.mixed_block_flag&&(q=22);for(k=0;k<q;k++){var B=l.scalefac_band.l[k],F=l.scalefac_band.l[k+1],G=F-B;for(p=0;J<F;J++)p+=g.xr[J]*g.xr[J];p/=G;t=1E15;l.pinfo.en[f][h][k]=t*p;l.pinfo.xfsf[f][h][k]=t*y[k]*D[k]/G;p=0<c.en.l[k]&&!a.ATHonly?p/c.en.l[k]:0;l.pinfo.thr[f][h][k]=t*Math.max(p*c.thm.l[k],l.ATH.l[k]);l.pinfo.LAMEsfb[f][h][k]= +0;0!=g.preflag&&11<=k&&(l.pinfo.LAMEsfb[f][h][k]=-m*b[k]);k<d.SBPSY_l&&(l.pinfo.LAMEsfb[f][h][k]-=m*x[k])}if(g.block_type==d.SHORT_TYPE)for(q=k,k=g.sfb_smin;k<d.SBMAX_s;k++)for(var B=l.scalefac_band.s[k],F=l.scalefac_band.s[k+1],G=F-B,I=0;3>I;I++){p=0;for(t=B;t<F;t++)p+=g.xr[J]*g.xr[J],J++;p=Math.max(p/G,1E-20);t=1E15;l.pinfo.en_s[f][h][3*k+I]=t*p;l.pinfo.xfsf_s[f][h][3*k+I]=t*y[q]*D[q]/G;p=0<c.en.s[k][I]?p/c.en.s[k][I]:0;if(a.ATHonly||a.ATHshort)p=0;l.pinfo.thr_s[f][h][3*k+I]=t*Math.max(p*c.thm.s[k][I], +l.ATH.s[k]);l.pinfo.LAMEsfb_s[f][h][3*k+I]=-2*g.subblock_gain[I];k<d.SBPSY_s&&(l.pinfo.LAMEsfb_s[f][h][3*k+I]-=m*x[q]);q++}l.pinfo.LAMEqss[f][h]=g.global_gain;l.pinfo.LAMEmainbits[f][h]=g.part2_3_length+g.part2_length;l.pinfo.LAMEsfbits[f][h]=g.part2_length;l.pinfo.over[f][h]=u.over_count;l.pinfo.max_noise[f][h]=10*u.max_noise;l.pinfo.over_noise[f][h]=10*u.over_noise;l.pinfo.tot_noise[f][h]=10*u.tot_noise;l.pinfo.over_SSD[f][h]=u.over_SSD}}function Nc(){this.sfb_count1=this.global_gain=0;this.step= +Y(39);this.noise=H(39);this.noise_log=H(39)}function Ab(){this.xr=H(576);this.l3_enc=Y(576);this.scalefac=Y(na.SFBMAX);this.mixed_block_flag=this.block_type=this.scalefac_compress=this.global_gain=this.count1=this.big_values=this.part2_3_length=this.xrpow_max=0;this.table_select=Y(3);this.subblock_gain=Y(4);this.sfbdivide=this.psymax=this.sfbmax=this.psy_lmax=this.sfb_smin=this.sfb_lmax=this.part2_length=this.count1table_select=this.scalefac_scale=this.preflag=this.region1_count=this.region0_count= +0;this.width=Y(na.SFBMAX);this.window=Y(na.SFBMAX);this.count1bits=0;this.sfb_partition_table=null;this.slen=Y(4);this.max_nonzero_coeff=0;var d=this;this.assign=function(k){d.xr=new Float32Array(k.xr);d.l3_enc=new Int32Array(k.l3_enc);d.scalefac=new Int32Array(k.scalefac);d.xrpow_max=k.xrpow_max;d.part2_3_length=k.part2_3_length;d.big_values=k.big_values;d.count1=k.count1;d.global_gain=k.global_gain;d.scalefac_compress=k.scalefac_compress;d.block_type=k.block_type;d.mixed_block_flag=k.mixed_block_flag; +d.table_select=new Int32Array(k.table_select);d.subblock_gain=new Int32Array(k.subblock_gain);d.region0_count=k.region0_count;d.region1_count=k.region1_count;d.preflag=k.preflag;d.scalefac_scale=k.scalefac_scale;d.count1table_select=k.count1table_select;d.part2_length=k.part2_length;d.sfb_lmax=k.sfb_lmax;d.sfb_smin=k.sfb_smin;d.psy_lmax=k.psy_lmax;d.sfbmax=k.sfbmax;d.psymax=k.psymax;d.sfbdivide=k.sfbdivide;d.width=new Int32Array(k.width);d.window=new Int32Array(k.window);d.count1bits=k.count1bits; +d.sfb_partition_table=k.sfb_partition_table.slice(0);d.slen=new Int32Array(k.slen);d.max_nonzero_coeff=k.max_nonzero_coeff}}function Oc(){function J(d){this.ordinal=d}function k(d){for(var b=0;b<d.sfbmax;b++)if(0==d.scalefac[b]+d.subblock_gain[d.window[b]])return!1;return!0}var q;this.rv=null;var r;this.qupvt=null;var B,t=new Ic,ta;this.setModules=function(d,b,l,a){q=d;this.rv=r=b;this.qupvt=B=l;ta=a;t.setModules(B,ta)};this.ms_convert=function(d,b){for(var l=0;576>l;++l){var a=d.tt[b][0].xr[l],h= +d.tt[b][1].xr[l];d.tt[b][0].xr[l]=.5*(a+h)*X.SQRT2;d.tt[b][1].xr[l]=.5*(a-h)*X.SQRT2}};this.init_xrpow=function(d,b,l){var a=0,h=0|b.max_nonzero_coeff;b.xrpow_max=0;Ia.fill(l,h,576,0);for(var k=a=0;k<=h;++k){var e=Math.abs(b.xr[k]),a=a+e;l[k]=Math.sqrt(e*Math.sqrt(e));l[k]>b.xrpow_max&&(b.xrpow_max=l[k])}if(1E-20<a){l=0;0!=(d.substep_shaping&2)&&(l=1);for(h=0;h<b.psymax;h++)d.pseudohalf[h]=l;return!0}Ia.fill(b.l3_enc,0,576,0);return!1};this.init_outer_loop=function(g,b){b.part2_3_length=0;b.big_values= +0;b.count1=0;b.global_gain=210;b.scalefac_compress=0;b.table_select[0]=0;b.table_select[1]=0;b.table_select[2]=0;b.subblock_gain[0]=0;b.subblock_gain[1]=0;b.subblock_gain[2]=0;b.subblock_gain[3]=0;b.region0_count=0;b.region1_count=0;b.preflag=0;b.scalefac_scale=0;b.count1table_select=0;b.part2_length=0;b.sfb_lmax=d.SBPSY_l;b.sfb_smin=d.SBPSY_s;b.psy_lmax=g.sfb21_extra?d.SBMAX_l:d.SBPSY_l;b.psymax=b.psy_lmax;b.sfbmax=b.sfb_lmax;b.sfbdivide=11;for(var l=0;l<d.SBMAX_l;l++)b.width[l]=g.scalefac_band.l[l+ +1]-g.scalefac_band.l[l],b.window[l]=3;if(b.block_type==d.SHORT_TYPE){var a=H(576);b.sfb_smin=0;b.sfb_lmax=0;0!=b.mixed_block_flag&&(b.sfb_smin=3,b.sfb_lmax=2*g.mode_gr+4);b.psymax=b.sfb_lmax+3*((g.sfb21_extra?d.SBMAX_s:d.SBPSY_s)-b.sfb_smin);b.sfbmax=b.sfb_lmax+3*(d.SBPSY_s-b.sfb_smin);b.sfbdivide=b.sfbmax-18;b.psy_lmax=b.sfb_lmax;var h=g.scalefac_band.l[b.sfb_lmax];K.arraycopy(b.xr,0,a,0,576);for(l=b.sfb_smin;l<d.SBMAX_s;l++)for(var k=g.scalefac_band.s[l],e=g.scalefac_band.s[l+1],n=0;3>n;n++)for(var c= +k;c<e;c++)b.xr[h++]=a[3*c+n];a=b.sfb_lmax;for(l=b.sfb_smin;l<d.SBMAX_s;l++)b.width[a]=b.width[a+1]=b.width[a+2]=g.scalefac_band.s[l+1]-g.scalefac_band.s[l],b.window[a]=0,b.window[a+1]=1,b.window[a+2]=2,a+=3}b.count1bits=0;b.sfb_partition_table=B.nr_of_sfb_block[0][0];b.slen[0]=0;b.slen[1]=0;b.slen[2]=0;b.slen[3]=0;b.max_nonzero_coeff=575;Ia.fill(b.scalefac,0);l=g.ATH;a=b.xr;if(b.block_type!=d.SHORT_TYPE)for(h=!1,k=d.PSFB21-1;0<=k&&!h;k--)for(e=g.scalefac_band.psfb21[k],n=g.scalefac_band.psfb21[k+ +1],c=B.athAdjust(l.adjust,l.psfb21[k],l.floor),1E-12<g.nsPsy.longfact[21]&&(c*=g.nsPsy.longfact[21]),--n;n>=e;n--)if(Math.abs(a[n])<c)a[n]=0;else{h=!0;break}else for(c=0;3>c;c++)for(h=!1,k=d.PSFB12-1;0<=k&&!h;k--){var e=3*g.scalefac_band.s[12]+(g.scalefac_band.s[13]-g.scalefac_band.s[12])*c+(g.scalefac_band.psfb12[k]-g.scalefac_band.psfb12[0]),n=e+(g.scalefac_band.psfb12[k+1]-g.scalefac_band.psfb12[k]),f=B.athAdjust(l.adjust,l.psfb12[k],l.floor);1E-12<g.nsPsy.shortfact[12]&&(f*=g.nsPsy.shortfact[12]); +for(--n;n>=e;n--)if(Math.abs(a[n])<f)a[n]=0;else{h=!0;break}}};J.BINSEARCH_NONE=new J(0);J.BINSEARCH_UP=new J(1);J.BINSEARCH_DOWN=new J(2);this.trancate_smallspectrums=function(g,b,l,a){var h=H(na.SFBMAX);if((0!=(g.substep_shaping&4)||b.block_type!=d.SHORT_TYPE)&&0==(g.substep_shaping&128)){B.calc_noise(b,l,h,new $b,null);for(var k=0;576>k;k++){var e=0;0!=b.l3_enc[k]&&(e=Math.abs(b.xr[k]));a[k]=e}k=0;e=8;b.block_type==d.SHORT_TYPE&&(e=6);do{var n,c,f,q,t=b.width[e],k=k+t;if(!(1<=h[e]||(Ia.sort(a, +k-t,t),ua.EQ(a[k-1],0)))){n=(1-h[e])*l[e];q=c=0;do{var w;for(f=1;q+f<t&&!ua.NEQ(a[q+k-t],a[q+k+f-t]);f++);w=a[q+k-t]*a[q+k-t]*f;if(n<w){0!=q&&(c=a[q+k-t-1]);break}n-=w;q+=f}while(q<t);if(!ua.EQ(c,0)){do Math.abs(b.xr[k-t])<=c&&(b.l3_enc[k-t]=0);while(0<--t)}}}while(++e<b.psymax);b.part2_3_length=ta.noquant_count_bits(g,b,null)}};this.outer_loop=function(g,b,l,a,h,q){var e=g.internal_flags,n=new Ab,c=H(576),f=H(na.SFBMAX),t=new $b,z,w=new Nc,A=9999999,v=!1,p=!1,m=0,x,y,W=e.CurrentStep[h],u=!1,r=e.OldValue[h]; +z=J.BINSEARCH_NONE;b.global_gain=r;for(x=q-b.part2_length;;){y=ta.count_bits(e,a,b,null);if(1==W||y==x)break;y>x?(z==J.BINSEARCH_DOWN&&(u=!0),u&&(W/=2),z=J.BINSEARCH_UP,y=W):(z==J.BINSEARCH_UP&&(u=!0),u&&(W/=2),z=J.BINSEARCH_DOWN,y=-W);b.global_gain+=y;0>b.global_gain&&(b.global_gain=0,u=!0);255<b.global_gain&&(b.global_gain=255,u=!0)}for(;y>x&&255>b.global_gain;)b.global_gain++,y=ta.count_bits(e,a,b,null);e.CurrentStep[h]=4<=r-b.global_gain?4:2;e.OldValue[h]=b.global_gain;b.part2_3_length=y;if(0== +e.noise_shaping)return 100;B.calc_noise(b,l,f,t,w);t.bits=b.part2_3_length;n.assign(b);h=0;for(K.arraycopy(a,0,c,0,576);!v;){do{x=new $b;u=255;W=0!=(e.substep_shaping&2)?20:3;if(e.sfb21_extra){if(1<f[n.sfbmax])break;if(n.block_type==d.SHORT_TYPE&&(1<f[n.sfbmax+1]||1<f[n.sfbmax+2]))break}r=n;y=a;z=g.internal_flags;for(var C=r,F=f,G=y,I=g.internal_flags,T=void 0,T=0==C.scalefac_scale?1.2968395546510096:1.6817928305074292,U=0,qa=0;qa<C.sfbmax;qa++)U<F[qa]&&(U=F[qa]);qa=I.noise_shaping_amp;3==qa&&(qa= +p?2:1);switch(qa){case 2:break;case 1:U=1<U?Math.pow(U,.5):.95*U;break;default:U=1<U?1:.95*U}for(var ia=0,qa=0;qa<C.sfbmax;qa++){var ya=C.width[qa],ia=ia+ya;if(!(F[qa]<U)){if(0!=(I.substep_shaping&2)&&(I.pseudohalf[qa]=0==I.pseudohalf[qa]?1:0,0==I.pseudohalf[qa]&&2==I.noise_shaping_amp))break;C.scalefac[qa]++;for(ya=-ya;0>ya;ya++)G[ia+ya]*=T,G[ia+ya]>C.xrpow_max&&(C.xrpow_max=G[ia+ya]);if(2==I.noise_shaping_amp)break}}if(C=k(r))r=!1;else if(C=2==z.mode_gr?ta.scale_bitcount(r):ta.scale_bitcount_lsf(z, +r)){if(1<z.noise_shaping)if(Ia.fill(z.pseudohalf,0),0==r.scalefac_scale){C=r;for(G=F=0;G<C.sfbmax;G++){T=C.width[G];I=C.scalefac[G];0!=C.preflag&&(I+=B.pretab[G]);F+=T;if(0!=(I&1))for(I++,T=-T;0>T;T++)y[F+T]*=1.2968395546510096,y[F+T]>C.xrpow_max&&(C.xrpow_max=y[F+T]);C.scalefac[G]=I>>1}C.preflag=0;C.scalefac_scale=1;C=!1}else if(r.block_type==d.SHORT_TYPE&&0<z.subblock_gain){b:{C=z;F=r;G=void 0;I=F.scalefac;for(G=0;G<F.sfb_lmax;G++)if(16<=I[G]){y=!0;break b}for(T=0;3>T;T++){qa=U=0;for(G=F.sfb_lmax+ +T;G<F.sfbdivide;G+=3)U<I[G]&&(U=I[G]);for(;G<F.sfbmax;G+=3)qa<I[G]&&(qa=I[G]);if(!(16>U&&8>qa)){if(7<=F.subblock_gain[T]){y=!0;break b}F.subblock_gain[T]++;U=C.scalefac_band.l[F.sfb_lmax];for(G=F.sfb_lmax+T;G<F.sfbmax;G+=3)if(qa=F.width[G],ia=I[G],ia-=4>>F.scalefac_scale,0<=ia)I[G]=ia,U+=3*qa;else{I[G]=0;ia=B.IPOW20(210+(ia<<F.scalefac_scale+1));U+=qa*(T+1);for(ya=-qa;0>ya;ya++)y[U+ya]*=ia,y[U+ya]>F.xrpow_max&&(F.xrpow_max=y[U+ya]);U+=qa*(3-T-1)}ia=B.IPOW20(202);U+=F.width[G]*(T+1);for(ya=-F.width[G];0> +ya;ya++)y[U+ya]*=ia,y[U+ya]>F.xrpow_max&&(F.xrpow_max=y[U+ya])}}y=!1}C=y||k(r)}C||(C=2==z.mode_gr?ta.scale_bitcount(r):ta.scale_bitcount_lsf(z,r));r=!C}else r=!0;if(!r)break;0!=n.scalefac_scale&&(u=254);r=q-n.part2_length;if(0>=r)break;for(;(n.part2_3_length=ta.count_bits(e,a,n,w))>r&&n.global_gain<=u;)n.global_gain++;if(n.global_gain>u)break;if(0==t.over_count){for(;(n.part2_3_length=ta.count_bits(e,a,n,w))>A&&n.global_gain<=u;)n.global_gain++;if(n.global_gain>u)break}B.calc_noise(n,l,f,x,w);x.bits= +n.part2_3_length;z=b.block_type!=d.SHORT_TYPE?g.quant_comp:g.quant_comp_short;u=t;r=x;C=n;y=f;F=void 0;switch(z){default:case 9:0<u.over_count?(F=r.over_SSD<=u.over_SSD,r.over_SSD==u.over_SSD&&(F=r.bits<u.bits)):F=0>r.max_noise&&10*r.max_noise+r.bits<=10*u.max_noise+u.bits;break;case 0:F=r.over_count<u.over_count||r.over_count==u.over_count&&r.over_noise<u.over_noise||r.over_count==u.over_count&&ua.EQ(r.over_noise,u.over_noise)&&r.tot_noise<u.tot_noise;break;case 8:z=r;G=1E-37;for(F=0;F<C.psymax;F++)I= +y[F],I=X.FAST_LOG10(.368+.632*I*I*I),G+=I;y=Math.max(1E-20,G);z.max_noise=y;case 1:F=r.max_noise<u.max_noise;break;case 2:F=r.tot_noise<u.tot_noise;break;case 3:F=r.tot_noise<u.tot_noise&&r.max_noise<u.max_noise;break;case 4:F=0>=r.max_noise&&.2<u.max_noise||0>=r.max_noise&&0>u.max_noise&&u.max_noise>r.max_noise-.2&&r.tot_noise<u.tot_noise||0>=r.max_noise&&0<u.max_noise&&u.max_noise>r.max_noise-.2&&r.tot_noise<u.tot_noise+u.over_noise||0<r.max_noise&&-.05<u.max_noise&&u.max_noise>r.max_noise-.1&& +r.tot_noise+r.over_noise<u.tot_noise+u.over_noise||0<r.max_noise&&-.1<u.max_noise&&u.max_noise>r.max_noise-.15&&r.tot_noise+r.over_noise+r.over_noise<u.tot_noise+u.over_noise+u.over_noise;break;case 5:F=r.over_noise<u.over_noise||ua.EQ(r.over_noise,u.over_noise)&&r.tot_noise<u.tot_noise;break;case 6:F=r.over_noise<u.over_noise||ua.EQ(r.over_noise,u.over_noise)&&(r.max_noise<u.max_noise||ua.EQ(r.max_noise,u.max_noise)&&r.tot_noise<=u.tot_noise);break;case 7:F=r.over_count<u.over_count||r.over_noise< +u.over_noise}0==u.over_count&&(F=F&&r.bits<u.bits);z=F?1:0;if(0!=z)A=b.part2_3_length,t=x,b.assign(n),h=0,K.arraycopy(a,0,c,0,576);else if(0==e.full_outer_loop){if(++h>W&&0==t.over_count)break;if(3==e.noise_shaping_amp&&p&&30<h)break;if(3==e.noise_shaping_amp&&p&&15<n.global_gain-m)break}}while(255>n.global_gain+n.scalefac_scale);3==e.noise_shaping_amp?p?v=!0:(n.assign(b),K.arraycopy(c,0,a,0,576),h=0,m=n.global_gain,p=!0):v=!0}g.VBR==M.vbr_rh||g.VBR==M.vbr_mtrh?K.arraycopy(c,0,a,0,576):0!=(e.substep_shaping& +1)&&trancate_smallspectrums(e,b,l,a);return t.over_count};this.iteration_finish_one=function(d,b,l){var a=d.l3_side,h=a.tt[b][l];ta.best_scalefac_store(d,b,l,a);1==d.use_best_huffman&&ta.best_huffman_divide(d,h);r.ResvAdjust(d,h)};this.VBR_encode_granule=function(d,b,l,a,h,k,e){var n=d.internal_flags,c=new Ab,f=H(576),q=e,t=e+1,t=(e+k)/2,r,A=0,v=n.sfb21_extra;Ia.fill(c.l3_enc,0);do n.sfb21_extra=t>q-42?!1:v,r=outer_loop(d,b,l,a,h,t),0>=r?(A=1,t=b.part2_3_length,c.assign(b),K.arraycopy(a,0,f,0,576), +e=t-32,r=e-k,t=(e+k)/2):(k=t+32,r=e-k,t=(e+k)/2,0!=A&&(A=2,b.assign(c),K.arraycopy(f,0,a,0,576)));while(12<r);n.sfb21_extra=v;2==A&&K.arraycopy(c.l3_enc,0,b.l3_enc,0,576)};this.get_framebits=function(d,b){var l=d.internal_flags;l.bitrate_index=l.VBR_min_bitrate;var a=q.getframebits(d);l.bitrate_index=1;for(var a=q.getframebits(d),h=1;h<=l.VBR_max_bitrate;h++)l.bitrate_index=h,a=new eb(a),b[h]=r.ResvFrameBegin(d,a),a=a.bits};this.VBR_old_prepare=function(g,b,l,a,h,k,e,n,c){var f=g.internal_flags,q; +q=0;var t=1,w=0;f.bitrate_index=f.VBR_max_bitrate;var A=r.ResvFrameBegin(g,new eb(0))/f.mode_gr;get_framebits(g,k);for(var v=0;v<f.mode_gr;v++){var p=B.on_pe(g,b,n[v],A,v,0);f.mode_ext==d.MPG_MD_MS_LR&&(ms_convert(f.l3_side,v),B.reduce_side(n[v],l[v],A,p));for(p=0;p<f.channels_out;++p){var m=f.l3_side.tt[v][p];m.block_type!=d.SHORT_TYPE?(q=1.28/(1+Math.exp(3.5-b[v][p]/300))-.05,q=f.PSY.mask_adjust-q):(q=2.56/(1+Math.exp(3.5-b[v][p]/300))-.14,q=f.PSY.mask_adjust_short-q);f.masking_lower=Math.pow(10, +.1*q);init_outer_loop(f,m);c[v][p]=B.calc_xmin(g,a[v][p],m,h[v][p]);0!=c[v][p]&&(t=0);e[v][p]=126;w+=n[v][p]}}for(v=0;v<f.mode_gr;v++)for(p=0;p<f.channels_out;p++)w>k[f.VBR_max_bitrate]&&(n[v][p]*=k[f.VBR_max_bitrate],n[v][p]/=w),e[v][p]>n[v][p]&&(e[v][p]=n[v][p]);return t};this.bitpressure_strategy=function(g,b,l,a){for(var h=0;h<g.mode_gr;h++)for(var k=0;k<g.channels_out;k++){for(var e=g.l3_side.tt[h][k],n=b[h][k],c=0,f=0;f<e.psy_lmax;f++)n[c++]*=1+.029*f*f/d.SBMAX_l/d.SBMAX_l;if(e.block_type== +d.SHORT_TYPE)for(f=e.sfb_smin;f<d.SBMAX_s;f++)n[c++]*=1+.029*f*f/d.SBMAX_s/d.SBMAX_s,n[c++]*=1+.029*f*f/d.SBMAX_s/d.SBMAX_s,n[c++]*=1+.029*f*f/d.SBMAX_s/d.SBMAX_s;a[h][k]=0|Math.max(l[h][k],.9*a[h][k])}};this.VBR_new_prepare=function(g,b,k,a,h,q){var e=g.internal_flags,n=1,c=0,f=0,t;g.free_format?(e.bitrate_index=0,c=new eb(c),t=r.ResvFrameBegin(g,c),c=c.bits,h[0]=t):(e.bitrate_index=e.VBR_max_bitrate,c=new eb(c),r.ResvFrameBegin(g,c),c=c.bits,get_framebits(g,h),t=h[e.VBR_max_bitrate]);for(h=0;h< +e.mode_gr;h++){B.on_pe(g,b,q[h],c,h,0);e.mode_ext==d.MPG_MD_MS_LR&&ms_convert(e.l3_side,h);for(var z=0;z<e.channels_out;++z){var w=e.l3_side.tt[h][z];e.masking_lower=Math.pow(10,.1*e.PSY.mask_adjust);init_outer_loop(e,w);0!=B.calc_xmin(g,k[h][z],w,a[h][z])&&(n=0);f+=q[h][z]}}for(h=0;h<e.mode_gr;h++)for(z=0;z<e.channels_out;z++)f>t&&(q[h][z]*=t,q[h][z]/=f);return n};this.calc_target_bits=function(g,b,k,a,h,t){var e=g.internal_flags,n=e.l3_side,c,f;e.bitrate_index=e.VBR_max_bitrate;f=new eb(0);t[0]= +r.ResvFrameBegin(g,f);e.bitrate_index=1;f=q.getframebits(g)-8*e.sideinfo_len;h[0]=f/(e.mode_gr*e.channels_out);f=g.VBR_mean_bitrate_kbps*g.framesize*1E3;0!=(e.substep_shaping&1)&&(f*=1.09);f/=g.out_samplerate;f-=8*e.sideinfo_len;f/=e.mode_gr*e.channels_out;c=.93+.07*(11-g.compression_ratio)/5.5;.9>c&&(c=.9);1<c&&(c=1);for(g=0;g<e.mode_gr;g++){var E=0;for(h=0;h<e.channels_out;h++){a[g][h]=int(c*f);if(700<b[g][h]){var z=int((b[g][h]-700)/1.4),w=n.tt[g][h];a[g][h]=int(c*f);w.block_type==d.SHORT_TYPE&& +z<f/2&&(z=f/2);z>3*f/2?z=3*f/2:0>z&&(z=0);a[g][h]+=z}a[g][h]>da.MAX_BITS_PER_CHANNEL&&(a[g][h]=da.MAX_BITS_PER_CHANNEL);E+=a[g][h]}if(E>da.MAX_BITS_PER_GRANULE)for(h=0;h<e.channels_out;++h)a[g][h]*=da.MAX_BITS_PER_GRANULE,a[g][h]/=E}if(e.mode_ext==d.MPG_MD_MS_LR)for(g=0;g<e.mode_gr;g++)B.reduce_side(a[g],k[g],f*e.channels_out,da.MAX_BITS_PER_GRANULE);for(g=b=0;g<e.mode_gr;g++)for(h=0;h<e.channels_out;h++)a[g][h]>da.MAX_BITS_PER_CHANNEL&&(a[g][h]=da.MAX_BITS_PER_CHANNEL),b+=a[g][h];if(b>t[0])for(g= +0;g<e.mode_gr;g++)for(h=0;h<e.channels_out;h++)a[g][h]*=t[0],a[g][h]/=b}}function Qa(){this.thm=new ic;this.en=new ic}function Pc(){function r(b,d,a){for(var g=10,q=d+238-14-286,e=-15;0>e;e++){var n,c,f;n=k[g+-10];c=b[q+-224]*n;f=b[d+224]*n;n=k[g+-9];c+=b[q+-160]*n;f+=b[d+160]*n;n=k[g+-8];c+=b[q+-96]*n;f+=b[d+96]*n;n=k[g+-7];c+=b[q+-32]*n;f+=b[d+32]*n;n=k[g+-6];c+=b[q+32]*n;f+=b[d+-32]*n;n=k[g+-5];c+=b[q+96]*n;f+=b[d+-96]*n;n=k[g+-4];c+=b[q+160]*n;f+=b[d+-160]*n;n=k[g+-3];c+=b[q+224]*n;f+=b[d+-224]* +n;n=k[g+-2];c+=b[d+-256]*n;f-=b[q+256]*n;n=k[g+-1];c+=b[d+-192]*n;f-=b[q+192]*n;n=k[g+0];c+=b[d+-128]*n;f-=b[q+128]*n;n=k[g+1];c+=b[d+-64]*n;f-=b[q+64]*n;n=k[g+2];c+=b[d+0]*n;f-=b[q+0]*n;n=k[g+3];c+=b[d+64]*n;f-=b[q+-64]*n;n=k[g+4];c+=b[d+128]*n;f-=b[q+-128]*n;n=k[g+5];c+=b[d+192]*n;f-=b[q+-192]*n;c*=k[g+6];n=f-c;a[30+2*e]=f+c;a[31+2*e]=k[g+7]*n;g+=18;d--;q++}f=b[d+-16]*k[g+-10];c=b[d+-32]*k[g+-2];f+=(b[d+-48]-b[d+16])*k[g+-9];c+=b[d+-96]*k[g+-1];f+=(b[d+-80]+b[d+48])*k[g+-8];c+=b[d+-160]*k[g+0]; +f+=(b[d+-112]-b[d+80])*k[g+-7];c+=b[d+-224]*k[g+1];f+=(b[d+-144]+b[d+112])*k[g+-6];c-=b[d+32]*k[g+2];f+=(b[d+-176]-b[d+144])*k[g+-5];c-=b[d+96]*k[g+3];f+=(b[d+-208]+b[d+176])*k[g+-4];c-=b[d+160]*k[g+4];f+=(b[d+-240]-b[d+208])*k[g+-3];c-=b[d+224];b=c-f;d=c+f;f=a[14];c=a[15]-f;a[31]=d+f;a[30]=b+c;a[15]=b-c;a[14]=d-f;c=a[28]-a[0];a[0]+=a[28];a[28]=c*k[g+-36+7];c=a[29]-a[1];a[1]+=a[29];a[29]=c*k[g+-36+7];c=a[26]-a[2];a[2]+=a[26];a[26]=c*k[g+-72+7];c=a[27]-a[3];a[3]+=a[27];a[27]=c*k[g+-72+7];c=a[24]-a[4]; +a[4]+=a[24];a[24]=c*k[g+-108+7];c=a[25]-a[5];a[5]+=a[25];a[25]=c*k[g+-108+7];c=a[22]-a[6];a[6]+=a[22];a[22]=c*X.SQRT2;c=a[23]-a[7];a[7]+=a[23];a[23]=c*X.SQRT2-a[7];a[7]-=a[6];a[22]-=a[7];a[23]-=a[22];c=a[6];a[6]=a[31]-c;a[31]+=c;c=a[7];a[7]=a[30]-c;a[30]+=c;c=a[22];a[22]=a[15]-c;a[15]+=c;c=a[23];a[23]=a[14]-c;a[14]+=c;c=a[20]-a[8];a[8]+=a[20];a[20]=c*k[g+-180+7];c=a[21]-a[9];a[9]+=a[21];a[21]=c*k[g+-180+7];c=a[18]-a[10];a[10]+=a[18];a[18]=c*k[g+-216+7];c=a[19]-a[11];a[11]+=a[19];a[19]=c*k[g+-216+ +7];c=a[16]-a[12];a[12]+=a[16];a[16]=c*k[g+-252+7];c=a[17]-a[13];a[13]+=a[17];a[17]=c*k[g+-252+7];c=-a[20]+a[24];a[20]+=a[24];a[24]=c*k[g+-216+7];c=-a[21]+a[25];a[21]+=a[25];a[25]=c*k[g+-216+7];c=a[4]-a[8];a[4]+=a[8];a[8]=c*k[g+-216+7];c=a[5]-a[9];a[5]+=a[9];a[9]=c*k[g+-216+7];c=a[0]-a[12];a[0]+=a[12];a[12]=c*k[g+-72+7];c=a[1]-a[13];a[1]+=a[13];a[13]=c*k[g+-72+7];c=a[16]-a[28];a[16]+=a[28];a[28]=c*k[g+-72+7];c=-a[17]+a[29];a[17]+=a[29];a[29]=c*k[g+-72+7];c=X.SQRT2*(a[2]-a[10]);a[2]+=a[10];a[10]=c; +c=X.SQRT2*(a[3]-a[11]);a[3]+=a[11];a[11]=c;c=X.SQRT2*(-a[18]+a[26]);a[18]+=a[26];a[26]=c-a[18];c=X.SQRT2*(-a[19]+a[27]);a[19]+=a[27];a[27]=c-a[19];c=a[2];a[19]-=a[3];a[3]-=c;a[2]=a[31]-c;a[31]+=c;c=a[3];a[11]-=a[19];a[18]-=c;a[3]=a[30]-c;a[30]+=c;c=a[18];a[27]-=a[11];a[19]-=c;a[18]=a[15]-c;a[15]+=c;c=a[19];a[10]-=c;a[19]=a[14]-c;a[14]+=c;c=a[10];a[11]-=c;a[10]=a[23]-c;a[23]+=c;c=a[11];a[26]-=c;a[11]=a[22]-c;a[22]+=c;c=a[26];a[27]-=c;a[26]=a[7]-c;a[7]+=c;c=a[27];a[27]=a[6]-c;a[6]+=c;c=X.SQRT2*(a[0]- +a[4]);a[0]+=a[4];a[4]=c;c=X.SQRT2*(a[1]-a[5]);a[1]+=a[5];a[5]=c;c=X.SQRT2*(a[16]-a[20]);a[16]+=a[20];a[20]=c;c=X.SQRT2*(a[17]-a[21]);a[17]+=a[21];a[21]=c;c=-X.SQRT2*(a[8]-a[12]);a[8]+=a[12];a[12]=c-a[8];c=-X.SQRT2*(a[9]-a[13]);a[9]+=a[13];a[13]=c-a[9];c=-X.SQRT2*(a[25]-a[29]);a[25]+=a[29];a[29]=c-a[25];c=-X.SQRT2*(a[24]+a[28]);a[24]-=a[28];a[28]=c-a[24];c=a[24]-a[16];a[24]=c;c=a[20]-c;a[20]=c;c=a[28]-c;a[28]=c;c=a[25]-a[17];a[25]=c;c=a[21]-c;a[21]=c;c=a[29]-c;a[29]=c;c=a[17]-a[1];a[17]=c;c=a[9]-c; +a[9]=c;c=a[25]-c;a[25]=c;c=a[5]-c;a[5]=c;c=a[21]-c;a[21]=c;c=a[13]-c;a[13]=c;c=a[29]-c;a[29]=c;c=a[1]-a[0];a[1]=c;c=a[16]-c;a[16]=c;c=a[17]-c;a[17]=c;c=a[8]-c;a[8]=c;c=a[9]-c;a[9]=c;c=a[24]-c;a[24]=c;c=a[25]-c;a[25]=c;c=a[4]-c;a[4]=c;c=a[5]-c;a[5]=c;c=a[20]-c;a[20]=c;c=a[21]-c;a[21]=c;c=a[12]-c;a[12]=c;c=a[13]-c;a[13]=c;c=a[28]-c;a[28]=c;c=a[29]-c;a[29]=c;c=a[0];a[0]+=a[31];a[31]-=c;c=a[1];a[1]+=a[30];a[30]-=c;c=a[16];a[16]+=a[15];a[15]-=c;c=a[17];a[17]+=a[14];a[14]-=c;c=a[8];a[8]+=a[23];a[23]-=c; +c=a[9];a[9]+=a[22];a[22]-=c;c=a[24];a[24]+=a[7];a[7]-=c;c=a[25];a[25]+=a[6];a[6]-=c;c=a[4];a[4]+=a[27];a[27]-=c;c=a[5];a[5]+=a[26];a[26]-=c;c=a[20];a[20]+=a[11];a[11]-=c;c=a[21];a[21]+=a[10];a[10]-=c;c=a[12];a[12]+=a[19];a[19]-=c;c=a[13];a[13]+=a[18];a[18]-=c;c=a[28];a[28]+=a[3];a[3]-=c;c=a[29];a[29]+=a[2];a[2]-=c}var k=[-.1482523854003001,32.308141959636465,296.40344946382766,883.1344870032432,11113.947376231741,1057.2713659324597,305.7402417275812,30.825928907280012,3.8533188138216365,59.42900443849514, +709.5899960123345,5281.91112291017,-5829.66483675846,-817.6293103748613,-76.91656988279972,-4.594269939176596,.9063471690191471,.1960342806591213,-.15466694054279598,34.324387823855965,301.8067566458425,817.599602898885,11573.795901679885,1181.2520595540152,321.59731579894424,31.232021761053772,3.7107095756221318,53.650946155329365,684.167428119626,5224.56624370173,-6366.391851890084,-908.9766368219582,-89.83068876699639,-5.411397422890401,.8206787908286602,.3901806440322567,-.16070888947830023,36.147034243915876, +304.11815768187864,732.7429163887613,11989.60988270091,1300.012278487897,335.28490093152146,31.48816102859945,3.373875931311736,47.232241542899175,652.7371796173471,5132.414255594984,-6909.087078780055,-1001.9990371107289,-103.62185754286375,-6.104916304710272,.7416505462720353,.5805693545089249,-.16636367662261495,37.751650073343995,303.01103387567713,627.9747488785183,12358.763425278165,1412.2779918482834,346.7496836825721,31.598286663170416,3.1598635433980946,40.57878626349686,616.1671130880391, +5007.833007176154,-7454.040671756168,-1095.7960341867115,-118.24411666465777,-6.818469345853504,.6681786379192989,.7653668647301797,-.1716176790982088,39.11551877123304,298.3413246578966,503.5259106886539,12679.589408408976,1516.5821921214542,355.9850766329023,31.395241710249053,2.9164211881972335,33.79716964664243,574.8943997801362,4853.234992253242,-7997.57021486075,-1189.7624067269965,-133.6444792601766,-7.7202770609839915,.5993769336819237,.9427934736519954,-.17645823955292173,40.21879108166477, +289.9982036694474,359.3226160751053,12950.259102786438,1612.1013903507662,362.85067106591504,31.045922092242872,2.822222032597987,26.988862316190684,529.8996541764288,4671.371946949588,-8535.899136645805,-1282.5898586244496,-149.58553632943463,-8.643494270763135,.5345111359507916,1.111140466039205,-.36174739330527045,41.04429910497807,277.5463268268618,195.6386023135583,13169.43812144731,1697.6433561479398,367.40983966190305,30.557037410382826,2.531473372857427,20.070154905927314,481.50208566532336, +4464.970341588308,-9065.36882077239,-1373.62841526722,-166.1660487028118,-9.58289321133207,.4729647758913199,1.268786568327291,-.36970682634889585,41.393213350082036,261.2935935556502,12.935476055240873,13336.131683328815,1772.508612059496,369.76534388639965,29.751323653701338,2.4023193045459172,13.304795348228817,430.5615775526625,4237.0568611071185,-9581.931701634761,-1461.6913552409758,-183.12733958476446,-10.718010163869403,.41421356237309503,1.414213562373095,-.37677560326535325,41.619486213528496, +241.05423794991074,-187.94665032361226,13450.063605744153,1836.153896465782,369.4908799925761,29.001847876923147,2.0714759319987186,6.779591200894186,377.7767837205709,3990.386575512536,-10081.709459700915,-1545.947424837898,-200.3762958015653,-11.864482073055006,.3578057213145241,1.546020906725474,-.3829366947518991,41.1516456456653,216.47684307105183,-406.1569483347166,13511.136535077321,1887.8076599260432,367.3025214564151,28.136213436723654,1.913880671464418,.3829366947518991,323.85365704338597, +3728.1472257487526,-10561.233882199509,-1625.2025997821418,-217.62525175416,-13.015432208941645,.3033466836073424,1.66293922460509,-.5822628872992417,40.35639251440489,188.20071124269245,-640.2706748618148,13519.21490106562,1927.6022433578062,362.8197642637487,26.968821921868447,1.7463817695935329,-5.62650678237171,269.3016715297017,3453.386536448852,-11016.145278780888,-1698.6569643425091,-234.7658734267683,-14.16351421663124,.2504869601913055,1.76384252869671,-.5887180101749253,39.23429103868072, +155.76096234403798,-889.2492977967378,13475.470561874661,1955.0535223723712,356.4450994756727,25.894952980042156,1.5695032905781554,-11.181939564328772,214.80884394039484,3169.1640829158237,-11443.321309975563,-1765.1588461316153,-251.68908574481912,-15.49755935939164,.198912367379658,1.847759065022573,-.7912582233652842,37.39369355329111,119.699486012458,-1151.0956593239027,13380.446257078214,1970.3952110853447,348.01959814116185,24.731487364283044,1.3850130831637748,-16.421408865300393,161.05030052864092, +2878.3322807850063,-11838.991423510031,-1823.985884688674,-268.2854986386903,-16.81724543849939,.1483359875383474,1.913880671464418,-.7960642926861912,35.2322109610459,80.01928065061526,-1424.0212633405113,13235.794061869668,1973.804052543835,337.9908651258184,23.289159354463873,1.3934255946442087,-21.099669467133474,108.48348407242611,2583.700758091299,-12199.726194855148,-1874.2780658979746,-284.2467154529415,-18.11369784385905,.09849140335716425,1.961570560806461,-.998795456205172,32.56307803611191, +36.958364584370486,-1706.075448829146,13043.287458812016,1965.3831106103316,326.43182772364605,22.175018750622293,1.198638339011324,-25.371248002043963,57.53505923036915,2288.41886619975,-12522.674544337233,-1914.8400385312243,-299.26241273417224,-19.37805630698734,.04912684976946725,1.990369453344394,.0178904535*X.SQRT2/2.384E-6,.008938074*X.SQRT2/2.384E-6,.0015673635*X.SQRT2/2.384E-6,.001228571*X.SQRT2/2.384E-6,4.856585E-4*X.SQRT2/2.384E-6,1.09434E-4*X.SQRT2/2.384E-6,5.0783E-5*X.SQRT2/2.384E-6, +6.914E-6*X.SQRT2/2.384E-6,12804.797818791945,1945.5515939597317,313.4244966442953,20.801593959731544,1995.1556208053692,9.000838926174497,-29.20218120805369],q=[[2.382191739347913E-13,6.423305872147834E-13,9.400849094049688E-13,1.122435026096556E-12,1.183840321267481E-12,1.122435026096556E-12,9.40084909404969E-13,6.423305872147839E-13,2.382191739347918E-13,5.456116108943412E-12,4.878985199565852E-12,4.240448995017367E-12,3.559909094758252E-12,2.858043359288075E-12,2.156177623817898E-12,1.475637723558783E-12, +8.371015190102974E-13,2.599706096327376E-13,-5.456116108943412E-12,-4.878985199565852E-12,-4.240448995017367E-12,-3.559909094758252E-12,-2.858043359288076E-12,-2.156177623817898E-12,-1.475637723558783E-12,-8.371015190102975E-13,-2.599706096327376E-13,-2.382191739347923E-13,-6.423305872147843E-13,-9.400849094049696E-13,-1.122435026096556E-12,-1.183840321267481E-12,-1.122435026096556E-12,-9.400849094049694E-13,-6.42330587214784E-13,-2.382191739347918E-13],[2.382191739347913E-13,6.423305872147834E-13, +9.400849094049688E-13,1.122435026096556E-12,1.183840321267481E-12,1.122435026096556E-12,9.400849094049688E-13,6.423305872147841E-13,2.382191739347918E-13,5.456116108943413E-12,4.878985199565852E-12,4.240448995017367E-12,3.559909094758253E-12,2.858043359288075E-12,2.156177623817898E-12,1.475637723558782E-12,8.371015190102975E-13,2.599706096327376E-13,-5.461314069809755E-12,-4.921085770524055E-12,-4.343405037091838E-12,-3.732668368707687E-12,-3.093523840190885E-12,-2.430835727329465E-12,-1.734679010007751E-12, +-9.74825365660928E-13,-2.797435120168326E-13,0,0,0,0,0,0,-2.283748241799531E-13,-4.037858874020686E-13,-2.146547464825323E-13],[.1316524975873958,.414213562373095,.7673269879789602,1.091308501069271,1.303225372841206,1.56968557711749,1.920982126971166,2.414213562373094,3.171594802363212,4.510708503662055,7.595754112725146,22.90376554843115,.984807753012208,.6427876096865394,.3420201433256688,.9396926207859084,-.1736481776669303,-.7660444431189779,.8660254037844387,.5,-.5144957554275265,-.4717319685649723, +-.3133774542039019,-.1819131996109812,-.09457419252642064,-.04096558288530405,-.01419856857247115,-.003699974673760037,.8574929257125442,.8817419973177052,.9496286491027329,.9833145924917901,.9955178160675857,.9991605581781475,.999899195244447,.9999931550702802],[0,0,0,0,0,0,2.283748241799531E-13,4.037858874020686E-13,2.146547464825323E-13,5.461314069809755E-12,4.921085770524055E-12,4.343405037091838E-12,3.732668368707687E-12,3.093523840190885E-12,2.430835727329466E-12,1.734679010007751E-12,9.74825365660928E-13, +2.797435120168326E-13,-5.456116108943413E-12,-4.878985199565852E-12,-4.240448995017367E-12,-3.559909094758253E-12,-2.858043359288075E-12,-2.156177623817898E-12,-1.475637723558782E-12,-8.371015190102975E-13,-2.599706096327376E-13,-2.382191739347913E-13,-6.423305872147834E-13,-9.400849094049688E-13,-1.122435026096556E-12,-1.183840321267481E-12,-1.122435026096556E-12,-9.400849094049688E-13,-6.423305872147841E-13,-2.382191739347918E-13]],C=q[d.SHORT_TYPE],B=q[d.SHORT_TYPE],t=q[d.SHORT_TYPE],M=q[d.SHORT_TYPE], +g=[0,1,16,17,8,9,24,25,4,5,20,21,12,13,28,29,2,3,18,19,10,11,26,27,6,7,22,23,14,15,30,31];this.mdct_sub48=function(b,k,a){for(var h=286,D=0;D<b.channels_out;D++){for(var e=0;e<b.mode_gr;e++){for(var n,c=b.l3_side.tt[e][D],f=c.xr,E=0,z=b.sb_sample[D][1-e],w=0,A=0;9>A;A++)for(r(k,h,z[w]),r(k,h+32,z[w+1]),w+=2,h+=64,n=1;32>n;n+=2)z[w-1][n]*=-1;for(n=0;32>n;n++,E+=18){var z=c.block_type,w=b.sb_sample[D][e],v=b.sb_sample[D][1-e];0!=c.mixed_block_flag&&2>n&&(z=0);if(1E-12>b.amp_filter[n])Ia.fill(f,E+0, +E+18,0);else{if(1>b.amp_filter[n])for(A=0;18>A;A++)v[A][g[n]]*=b.amp_filter[n];if(z==d.SHORT_TYPE){for(A=-3;0>A;A++){var p=q[d.SHORT_TYPE][A+3];f[E+3*A+9]=w[9+A][g[n]]*p-w[8-A][g[n]];f[E+3*A+18]=w[14-A][g[n]]*p+w[15+A][g[n]];f[E+3*A+10]=w[15+A][g[n]]*p-w[14-A][g[n]];f[E+3*A+19]=v[2-A][g[n]]*p+v[3+A][g[n]];f[E+3*A+11]=v[3+A][g[n]]*p-v[2-A][g[n]];f[E+3*A+20]=v[8-A][g[n]]*p+v[9+A][g[n]]}A=f;w=E;for(p=0;3>p;p++){var m,x,y,W,u;y=A[w+6]*q[d.SHORT_TYPE][0]-A[w+15];v=A[w+0]*q[d.SHORT_TYPE][2]-A[w+9];m=y+ +v;x=y-v;y=A[w+15]*q[d.SHORT_TYPE][0]+A[w+6];v=A[w+9]*q[d.SHORT_TYPE][2]+A[w+0];W=y+v;u=-y+v;v=2.069978111953089E-11*(A[w+3]*q[d.SHORT_TYPE][1]-A[w+12]);y=2.069978111953089E-11*(A[w+12]*q[d.SHORT_TYPE][1]+A[w+3]);A[w+0]=1.90752519173728E-11*m+v;A[w+15]=1.90752519173728E-11*-W+y;x*=1.6519652744032674E-11;W=9.537625958686404E-12*W+y;A[w+3]=x-W;A[w+6]=x+W;m=9.537625958686404E-12*m-v;u*=1.6519652744032674E-11;A[w+9]=m+u;A[w+12]=m-u;w++}}else{p=H(18);for(A=-9;0>A;A++)m=q[z][A+27]*v[A+9][g[n]]+q[z][A+36]* +v[8-A][g[n]],x=q[z][A+9]*w[A+9][g[n]]-q[z][A+18]*w[8-A][g[n]],p[A+9]=m-x*C[3+A+9],p[A+18]=m*C[3+A+9]+x;var A=f,w=E,pa=u=W=y=x=m=v=void 0,la=void 0,F=void 0,G=void 0;x=p[17]-p[9];W=p[15]-p[11];u=p[14]-p[12];pa=p[0]+p[8];la=p[1]+p[7];F=p[2]+p[6];G=p[3]+p[5];A[w+17]=pa+F-G-(la-p[4]);m=(pa+F-G)*B[19]+(la-p[4]);v=(x-W-u)*B[18];A[w+5]=v+m;A[w+6]=v-m;y=(p[16]-p[10])*B[18];la=la*B[19]+p[4];v=x*B[12]+y+W*B[13]+u*B[14];m=-pa*B[16]+la-F*B[17]+G*B[15];A[w+1]=v+m;A[w+2]=v-m;v=x*B[13]-y-W*B[14]+u*B[12];m=-pa*B[17]+ +la-F*B[15]+G*B[16];A[w+9]=v+m;A[w+10]=v-m;v=x*B[14]-y+W*B[12]-u*B[13];m=pa*B[15]-la+F*B[16]-G*B[17];A[w+13]=v+m;A[w+14]=v-m;G=F=la=pa=u=W=y=x=void 0;x=p[8]-p[0];W=p[6]-p[2];u=p[5]-p[3];pa=p[17]+p[9];la=p[16]+p[10];F=p[15]+p[11];G=p[14]+p[12];A[w+0]=pa+F+G+(la+p[13]);v=(pa+F+G)*B[19]-(la+p[13]);m=(x-W+u)*B[18];A[w+11]=v+m;A[w+12]=v-m;y=(p[7]-p[1])*B[18];la=p[13]-la*B[19];v=pa*B[15]-la+F*B[16]+G*B[17];m=x*B[14]+y+W*B[12]+u*B[13];A[w+3]=v+m;A[w+4]=v-m;v=-pa*B[17]+la-F*B[15]-G*B[16];m=x*B[13]+y-W*B[14]- +u*B[12];A[w+7]=v+m;A[w+8]=v-m;v=-pa*B[16]+la-F*B[17]-G*B[15];m=x*B[12]-y+W*B[13]-u*B[14];A[w+15]=v+m;A[w+16]=v-m}}if(z!=d.SHORT_TYPE&&0!=n)for(A=7;0<=A;--A)z=f[E+A]*t[20+A]+f[E+-1-A]*M[28+A],w=f[E+A]*M[28+A]-f[E+-1-A]*t[20+A],f[E+-1-A]=z,f[E+A]=w}}k=a;h=286;if(1==b.mode_gr)for(e=0;18>e;e++)K.arraycopy(b.sb_sample[D][1][e],0,b.sb_sample[D][0][e],0,32)}}}function d(){var r=d.FFTOFFSET,k=d.MPG_MD_MS_LR,q=null,C=this.psy=null,B=null,t=null;this.setModules=function(d,b,k,a){q=d;C=this.psy=b;B=a;t=k};var ta= +new Pc;this.lame_encode_mp3_frame=function(g,b,l,a,h,D){var e=Zb([2,2]);e[0][0]=new Qa;e[0][1]=new Qa;e[1][0]=new Qa;e[1][1]=new Qa;var n=Zb([2,2]);n[0][0]=new Qa;n[0][1]=new Qa;n[1][0]=new Qa;n[1][1]=new Qa;var c=[null,null],f=g.internal_flags,E=ra([2,4]),z=[.5,.5],w=[[0,0],[0,0]],A=[[0,0],[0,0]];c[0]=b;c[1]=l;if(0==f.lame_encode_frame_init){b=g.internal_flags;var v,p;if(0==b.lame_encode_frame_init){l=H(2014);var m=H(2014);b.lame_encode_frame_init=1;for(p=v=0;v<286+576*(1+b.mode_gr);++v)v<576*b.mode_gr? +(l[v]=0,2==b.channels_out&&(m[v]=0)):(l[v]=c[0][p],2==b.channels_out&&(m[v]=c[1][p]),++p);for(p=0;p<b.mode_gr;p++)for(v=0;v<b.channels_out;v++)b.l3_side.tt[p][v].block_type=d.SHORT_TYPE;ta.mdct_sub48(b,l,m)}}f.padding=0;0>(f.slot_lag-=f.frac_SpF)&&(f.slot_lag+=g.out_samplerate,f.padding=1);if(0!=f.psymodel)for(m=[null,null],v=0,p=Y(2),l=0;l<f.mode_gr;l++){for(b=0;b<f.channels_out;b++)m[b]=c[b],v=576+576*l-d.FFTOFFSET;b=g.VBR==M.vbr_mtrh||g.VBR==M.vbr_mt?C.L3psycho_anal_vbr(g,m,v,l,e,n,w[l],A[l],E[l], +p):C.L3psycho_anal_ns(g,m,v,l,e,n,w[l],A[l],E[l],p);if(0!=b)return-4;g.mode==ka.JOINT_STEREO&&(z[l]=E[l][2]+E[l][3],0<z[l]&&(z[l]=E[l][3]/z[l]));for(b=0;b<f.channels_out;b++){var x=f.l3_side.tt[l][b];x.block_type=p[b];x.mixed_block_flag=0}}else for(l=0;l<f.mode_gr;l++)for(b=0;b<f.channels_out;b++)f.l3_side.tt[l][b].block_type=d.NORM_TYPE,f.l3_side.tt[l][b].mixed_block_flag=0,A[l][b]=w[l][b]=700;0==f.ATH.useAdjust?f.ATH.adjust=1:(b=f.loudness_sq[0][0],E=f.loudness_sq[1][0],2==f.channels_out?(b+=f.loudness_sq[0][1], +E+=f.loudness_sq[1][1]):(b+=b,E+=E),2==f.mode_gr&&(b=Math.max(b,E)),b=.5*b*f.ATH.aaSensitivityP,.03125<b?(1<=f.ATH.adjust?f.ATH.adjust=1:f.ATH.adjust<f.ATH.adjustLimit&&(f.ATH.adjust=f.ATH.adjustLimit),f.ATH.adjustLimit=1):(E=31.98*b+6.25E-4,f.ATH.adjust>=E?(f.ATH.adjust*=.075*E+.925,f.ATH.adjust<E&&(f.ATH.adjust=E)):f.ATH.adjustLimit>=E?f.ATH.adjust=E:f.ATH.adjust<f.ATH.adjustLimit&&(f.ATH.adjust=f.ATH.adjustLimit),f.ATH.adjustLimit=E));ta.mdct_sub48(f,c[0],c[1]);f.mode_ext=d.MPG_MD_LR_LR;if(g.force_ms)f.mode_ext= +d.MPG_MD_MS_LR;else if(g.mode==ka.JOINT_STEREO){for(l=m=E=0;l<f.mode_gr;l++)for(b=0;b<f.channels_out;b++)E+=A[l][b],m+=w[l][b];E<=1*m&&(E=f.l3_side.tt[0],b=f.l3_side.tt[f.mode_gr-1],E[0].block_type==E[1].block_type&&b[0].block_type==b[1].block_type&&(f.mode_ext=d.MPG_MD_MS_LR))}f.mode_ext==k&&(e=n,w=A);if(g.analysis&&null!=f.pinfo)for(l=0;l<f.mode_gr;l++)for(b=0;b<f.channels_out;b++)f.pinfo.ms_ratio[l]=f.ms_ratio[l],f.pinfo.ms_ener_ratio[l]=z[l],f.pinfo.blocktype[l][b]=f.l3_side.tt[l][b].block_type, +f.pinfo.pe[l][b]=w[l][b],K.arraycopy(f.l3_side.tt[l][b].xr,0,f.pinfo.xr[l][b],0,576),f.mode_ext==k&&(f.pinfo.ers[l][b]=f.pinfo.ers[l][b+2],K.arraycopy(f.pinfo.energy[l][b+2],0,f.pinfo.energy[l][b],0,f.pinfo.energy[l][b].length));if(g.VBR==M.vbr_off||g.VBR==M.vbr_abr){for(n=0;18>n;n++)f.nsPsy.pefirbuf[n]=f.nsPsy.pefirbuf[n+1];for(l=A=0;l<f.mode_gr;l++)for(b=0;b<f.channels_out;b++)A+=w[l][b];f.nsPsy.pefirbuf[18]=A;A=f.nsPsy.pefirbuf[9];for(n=0;9>n;n++)A+=(f.nsPsy.pefirbuf[n]+f.nsPsy.pefirbuf[18-n])* +d.fircoef[n];A=3350*f.mode_gr*f.channels_out/A;for(l=0;l<f.mode_gr;l++)for(b=0;b<f.channels_out;b++)w[l][b]*=A}f.iteration_loop.iteration_loop(g,w,z,e);q.format_bitstream(g);a=q.copy_buffer(f,a,h,D,1);g.bWriteVbrTag&&B.addVbrFrame(g);if(g.analysis&&null!=f.pinfo){for(b=0;b<f.channels_out;b++){for(h=0;h<r;h++)f.pinfo.pcmdata[b][h]=f.pinfo.pcmdata[b][h+g.framesize];for(h=r;1600>h;h++)f.pinfo.pcmdata[b][h]=c[b][h-r]}t.set_frame_pinfo(g,e)}f.bitrate_stereoMode_Hist[f.bitrate_index][4]++;f.bitrate_stereoMode_Hist[15][4]++; +2==f.channels_out&&(f.bitrate_stereoMode_Hist[f.bitrate_index][f.mode_ext]++,f.bitrate_stereoMode_Hist[15][f.mode_ext]++);for(g=0;g<f.mode_gr;++g)for(c=0;c<f.channels_out;++c)h=f.l3_side.tt[g][c].block_type|0,0!=f.l3_side.tt[g][c].mixed_block_flag&&(h=4),f.bitrate_blockType_Hist[f.bitrate_index][h]++,f.bitrate_blockType_Hist[f.bitrate_index][5]++,f.bitrate_blockType_Hist[15][h]++,f.bitrate_blockType_Hist[15][5]++;return a}}function Qc(){this.size=this.pos=this.want=this.seen=this.sum=0;this.bag=null; +this.TotalFrameSize=this.nBytesWritten=this.nVbrNumFrames=0}function Rc(){this.tt=[[null,null],[null,null]];this.resvDrain_post=this.resvDrain_pre=this.private_bits=this.main_data_begin=0;this.scfsi=[Y(4),Y(4)];for(var d=0;2>d;d++)for(var k=0;2>k;k++)this.tt[d][k]=new Ab}function Sc(){this.last_en_subshort=ra([4,9]);this.lastAttacks=Y(4);this.pefirbuf=H(19);this.longfact=H(d.SBMAX_l);this.shortfact=H(d.SBMAX_s);this.attackthre_s=this.attackthre=0}function ic(){this.l=H(d.SBMAX_l);this.s=ra([d.SBMAX_s, +3]);var r=this;this.assign=function(k){K.arraycopy(k.l,0,r.l,0,d.SBMAX_l);for(var q=0;q<d.SBMAX_s;q++)for(var C=0;3>C;C++)r.s[q][C]=k.s[q][C]}}function da(){function r(){this.ptr=this.write_timing=0;this.buf=new Int8Array(40)}this.fill_buffer_resample_init=this.iteration_init_init=this.lame_encode_frame_init=this.Class_ID=0;this.mfbuf=ra([2,da.MFSIZE]);this.full_outer_loop=this.use_best_huffman=this.subblock_gain=this.noise_shaping_stop=this.psymodel=this.substep_shaping=this.noise_shaping_amp=this.noise_shaping= +this.highpass2=this.highpass1=this.lowpass2=this.lowpass1=this.mode_ext=this.samplerate_index=this.bitrate_index=this.VBR_max_bitrate=this.VBR_min_bitrate=this.mf_size=this.mf_samples_to_encode=this.resample_ratio=this.channels_out=this.channels_in=this.mode_gr=0;this.l3_side=new Rc;this.ms_ratio=H(2);this.slot_lag=this.frac_SpF=this.padding=0;this.tag_spec=null;this.nMusicCRC=0;this.OldValue=Y(2);this.CurrentStep=Y(2);this.masking_lower=0;this.bv_scf=Y(576);this.pseudohalf=Y(na.SFBMAX);this.sfb21_extra= +!1;this.inbuf_old=Array(2);this.blackfilt=Array(2*da.BPC+1);this.itime=new Float64Array(2);this.sideinfo_len=0;this.sb_sample=ra([2,2,18,d.SBLIMIT]);this.amp_filter=H(32);this.header=Array(da.MAX_HEADER_BUF);this.ResvMax=this.ResvSize=this.ancillary_flag=this.w_ptr=this.h_ptr=0;this.scalefac_band=new ha;this.minval_l=H(d.CBANDS);this.minval_s=H(d.CBANDS);this.nb_1=ra([4,d.CBANDS]);this.nb_2=ra([4,d.CBANDS]);this.nb_s1=ra([4,d.CBANDS]);this.nb_s2=ra([4,d.CBANDS]);this.s3_ll=this.s3_ss=null;this.decay= +0;this.thm=Array(4);this.en=Array(4);this.tot_ener=H(4);this.loudness_sq=ra([2,2]);this.loudness_sq_save=H(2);this.mld_l=H(d.SBMAX_l);this.mld_s=H(d.SBMAX_s);this.bm_l=Y(d.SBMAX_l);this.bo_l=Y(d.SBMAX_l);this.bm_s=Y(d.SBMAX_s);this.bo_s=Y(d.SBMAX_s);this.npart_s=this.npart_l=0;this.s3ind=db([d.CBANDS,2]);this.s3ind_s=db([d.CBANDS,2]);this.numlines_s=Y(d.CBANDS);this.numlines_l=Y(d.CBANDS);this.rnumlines_l=H(d.CBANDS);this.mld_cb_l=H(d.CBANDS);this.mld_cb_s=H(d.CBANDS);this.numlines_l_num1=this.numlines_s_num1= +0;this.pe=H(4);this.ms_ener_ratio_old=this.ms_ratio_l_old=this.ms_ratio_s_old=0;this.blocktype_old=Y(2);this.nsPsy=new Sc;this.VBR_seek_table=new Qc;this.PSY=this.ATH=null;this.nogap_current=this.nogap_total=0;this.findPeakSample=this.findReplayGain=this.decode_on_the_fly=!0;this.AudiophileGain=this.RadioGain=this.PeakSample=0;this.rgdata=null;this.noclipScale=this.noclipGainChange=0;this.bitrate_stereoMode_Hist=db([16,5]);this.bitrate_blockType_Hist=db([16,6]);this.hip=this.pinfo=null;this.in_buffer_nsamples= +0;this.iteration_loop=this.in_buffer_1=this.in_buffer_0=null;for(var k=0;k<this.en.length;k++)this.en[k]=new ic;for(k=0;k<this.thm.length;k++)this.thm[k]=new ic;for(k=0;k<this.header.length;k++)this.header[k]=new r}function Tc(){function r(d,k,g){var b=0,l,a,h;g<<=1;var q=k+g;l=4;do{var e,n,c,f,B,z,w;w=l>>1;f=l;B=l<<1;z=B+f;l=B<<1;a=k;h=a+w;do{var A,v,p,m;v=d[a+0]-d[a+f];A=d[a+0]+d[a+f];m=d[a+B]-d[a+z];p=d[a+B]+d[a+z];d[a+B]=A-p;d[a+0]=A+p;d[a+z]=v-m;d[a+f]=v+m;v=d[h+0]-d[h+f];A=d[h+0]+d[h+f];m=X.SQRT2* +d[h+z];p=X.SQRT2*d[h+B];d[h+B]=A-p;d[h+0]=A+p;d[h+z]=v-m;d[h+f]=v+m;h+=l;a+=l}while(a<q);n=C[b+0];e=C[b+1];for(c=1;c<w;c++){var x,y;x=1-2*e*e;y=2*e*n;a=k+c;h=k+f-c;do{var W,u,J,H,F;W=y*d[a+f]-x*d[h+f];p=x*d[a+f]+y*d[h+f];v=d[a+0]-p;A=d[a+0]+p;J=d[h+0]-W;u=d[h+0]+W;W=y*d[a+z]-x*d[h+z];p=x*d[a+z]+y*d[h+z];m=d[a+B]-p;p=d[a+B]+p;F=d[h+B]-W;H=d[h+B]+W;W=e*p-n*F;p=n*p+e*F;d[a+B]=A-p;d[a+0]=A+p;d[h+z]=J-W;d[h+f]=J+W;W=n*H-e*m;p=e*H+n*m;d[h+B]=u-p;d[h+0]=u+p;d[a+z]=v-W;d[a+f]=v+W;h+=l;a+=l}while(a<q);x=n; +n=x*C[b+0]-e*C[b+1];e=x*C[b+1]+e*C[b+0]}b+=2}while(l<g)}var k=H(d.BLKSIZE),q=H(d.BLKSIZE_s/2),C=[.9238795325112867,.3826834323650898,.9951847266721969,.0980171403295606,.9996988186962042,.02454122852291229,.9999811752826011,.006135884649154475],B=[0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,240,8,136,72,200,40,168,104,232,24,152,88,216,56,184,120,248,4,132,68,196,36,164,100,228,20,148,84,212,52,180,116,244,12,140,76,204,44,172,108,236,28,156,92,220,60,188,124,252,2,130,66,194,34,162,98,226, +18,146,82,210,50,178,114,242,10,138,74,202,42,170,106,234,26,154,90,218,58,186,122,250,6,134,70,198,38,166,102,230,22,150,86,214,54,182,118,246,14,142,78,206,46,174,110,238,30,158,94,222,62,190,126,254];this.fft_short=function(k,C,g,b,l){for(k=0;3>k;k++){var a=d.BLKSIZE_s/2,h=65535&192*(k+1),D=d.BLKSIZE_s/8-1;do{var e,n,c,f,E,z=B[D<<2]&255;e=q[z]*b[g][l+z+h];E=q[127-z]*b[g][l+z+h+128];n=e-E;e+=E;c=q[z+64]*b[g][l+z+h+64];E=q[63-z]*b[g][l+z+h+192];f=c-E;c+=E;a-=4;C[k][a+0]=e+c;C[k][a+2]=e-c;C[k][a+ +1]=n+f;C[k][a+3]=n-f;e=q[z+1]*b[g][l+z+h+1];E=q[126-z]*b[g][l+z+h+129];n=e-E;e+=E;c=q[z+65]*b[g][l+z+h+65];E=q[62-z]*b[g][l+z+h+193];f=c-E;c+=E;C[k][a+d.BLKSIZE_s/2+0]=e+c;C[k][a+d.BLKSIZE_s/2+2]=e-c;C[k][a+d.BLKSIZE_s/2+1]=n+f;C[k][a+d.BLKSIZE_s/2+3]=n-f}while(0<=--D);r(C[k],a,d.BLKSIZE_s/2)}};this.fft_long=function(q,C,g,b,l){q=d.BLKSIZE/8-1;var a=d.BLKSIZE/2;do{var h,D,e,n,c,f=B[q]&255;h=k[f]*b[g][l+f];c=k[f+512]*b[g][l+f+512];D=h-c;h+=c;e=k[f+256]*b[g][l+f+256];c=k[f+768]*b[g][l+f+768];n=e-c; +e+=c;a-=4;C[a+0]=h+e;C[a+2]=h-e;C[a+1]=D+n;C[a+3]=D-n;h=k[f+1]*b[g][l+f+1];c=k[f+513]*b[g][l+f+513];D=h-c;h+=c;e=k[f+257]*b[g][l+f+257];c=k[f+769]*b[g][l+f+769];n=e-c;e+=c;C[a+d.BLKSIZE/2+0]=h+e;C[a+d.BLKSIZE/2+2]=h-e;C[a+d.BLKSIZE/2+1]=D+n;C[a+d.BLKSIZE/2+3]=D-n}while(0<=--q);r(C,a,d.BLKSIZE/2)};this.init_fft=function(r){for(r=0;r<d.BLKSIZE;r++)k[r]=.42-.5*Math.cos(2*Math.PI*(r+.5)/d.BLKSIZE)+.08*Math.cos(4*Math.PI*(r+.5)/d.BLKSIZE);for(r=0;r<d.BLKSIZE_s/2;r++)q[r]=.5*(1-Math.cos(2*Math.PI*(r+.5)/ +d.BLKSIZE_s))}}function jc(){function r(a,c){for(var b=0,m=0;m<d.BLKSIZE/2;++m)b+=a[m]*c.ATH.eql_w[m];return b*=z}function k(a,d,c,b,g,f){var e;if(d>a)if(d<a*A)e=d/a;else return a+d;else{if(a>=d*A)return a+d;e=a/d}a+=d;if(6>=b+3){if(e>=w)return a;b=0|X.FAST_LOG10_X(e,16);return a*x[b]}b=0|X.FAST_LOG10_X(e,16);d=0!=f?g.ATH.cb_s[c]*g.ATH.adjust:g.ATH.cb_l[c]*g.ATH.adjust;return a<v*d?a>d?(c=1,13>=b&&(c=y[b]),d=X.FAST_LOG10_X(a/d,10/15),a*((m[b]-c)*d+c)):13<b?a:a*y[b]:a*m[b]}function q(a,d,c){var b; +0>a&&(a=0);0>d&&(d=0);if(0>=a)return d;if(0>=d)return a;b=d>a?d/a:a/d;if(-2<=c&&2>=c){if(b>=w)return a+d;c=0|X.FAST_LOG10_X(b,16);return(a+d)*W[c]}if(b<A)return a+d;a<d&&(a=d);return a}function C(a,c,b,m,g){var f,e,k=0,h=0;for(f=e=0;f<d.SBMAX_s;++e,++f){for(var l=a.bo_s[f],n=a.npart_s,l=l<n?l:n;e<l;)k+=c[e],h+=b[e],e++;a.en[m].s[f][g]=k;a.thm[m].s[f][g]=h;if(e>=n){++f;break}h=a.PSY.bo_s_weight[f];n=1-h;k=h*c[e];h*=b[e];a.en[m].s[f][g]+=k;a.thm[m].s[f][g]+=h;k=n*c[e];h=n*b[e]}for(;f<d.SBMAX_s;++f)a.en[m].s[f][g]= +0,a.thm[m].s[f][g]=0}function B(a,c,b,m){var g,f,e=0,k=0;for(g=f=0;g<d.SBMAX_l;++f,++g){for(var h=a.bo_l[g],l=a.npart_l,h=h<l?h:l;f<h;)e+=c[f],k+=b[f],f++;a.en[m].l[g]=e;a.thm[m].l[g]=k;if(f>=l){++g;break}k=a.PSY.bo_l_weight[g];l=1-k;e=k*c[f];k*=b[f];a.en[m].l[g]+=e;a.thm[m].l[g]+=k;e=l*c[f];k=l*b[f]}for(;g<d.SBMAX_l;++g)a.en[m].l[g]=0,a.thm[m].l[g]=0}function t(a,d,c){return 1<=c?a:0>=c?d:0<d?Math.pow(a/d,c)*d:0}function V(a,c){for(var b=309.07,m=0;m<d.SBMAX_s-1;m++)for(var g=0;3>g;g++){var f=a.thm.s[m][g]; +if(0<f){var f=f*c,e=a.en.s[m][g];e>f&&(b=e>1E10*f?b+23.02585092994046*u[m]:b+u[m]*X.FAST_LOG10(e/f))}}return b}function g(a,c){for(var b=281.0575,m=0;m<d.SBMAX_l-1;m++){var g=a.thm.l[m];if(0<g){var g=g*c,f=a.en.l[m];f>g&&(b=f>1E10*g?b+23.02585092994046*pa[m]:b+pa[m]*X.FAST_LOG10(f/g))}}return b}function b(a,d,c,b,m){var g,f;for(g=f=0;g<a.npart_l;++g){var e=0,k=0,h;for(h=0;h<a.numlines_l[g];++h,++f){var l=d[f],e=e+l;k<l&&(k=l)}c[g]=e;b[g]=k;m[g]=e*a.rnumlines_l[g]}}function l(a,d,c,b){var m=p.length- +1,g=0,f=c[g]+c[g+1];if(0<f){var e=d[g];e<d[g+1]&&(e=d[g+1]);f=20*(2*e-f)/(f*(a.numlines_l[g]+a.numlines_l[g+1]-1));f|=0;f>m&&(f=m);b[g]=f}else b[g]=0;for(g=1;g<a.npart_l-1;g++)f=c[g-1]+c[g]+c[g+1],0<f?(e=d[g-1],e<d[g]&&(e=d[g]),e<d[g+1]&&(e=d[g+1]),f=20*(3*e-f)/(f*(a.numlines_l[g-1]+a.numlines_l[g]+a.numlines_l[g+1]-1)),f|=0,f>m&&(f=m),b[g]=f):b[g]=0;f=c[g-1]+c[g];0<f?(e=d[g-1],e<d[g]&&(e=d[g]),f=20*(2*e-f)/(f*(a.numlines_l[g-1]+a.numlines_l[g]-1)),f|=0,f>m&&(f=m),b[g]=f):b[g]=0}function a(a,d,c, +b,m,g,f){var e=2*g;m=0<g?Math.pow(10,m):1;for(var k,h,l=0;l<f;++l){var n=a[2][l],p=a[3][l],y=d[0][l],q=d[1][l],u=d[2][l],x=d[3][l];y<=1.58*q&&q<=1.58*y?(k=c[l]*n,h=Math.max(u,Math.min(x,c[l]*p)),k=Math.max(x,Math.min(u,k))):(h=u,k=x);0<g&&(x=b[l]*m,y=Math.min(Math.max(y,x),Math.max(q,x)),u=Math.max(h,x),x=Math.max(k,x),q=u+x,0<q&&y*e<q&&(y=y*e/q,u*=y,x*=y),h=Math.min(u,h),k=Math.min(x,k));h>n&&(h=n);k>p&&(k=p);d[2][l]=h;d[3][l]=k}}function h(a,d){var c;c=0<=a?27*-a:a*d;return-72>=c?0:Math.exp(.2302585093* +c)}function D(a){0>a&&(a=0);a*=.001;return 13*Math.atan(.76*a)+3.5*Math.atan(a*a/56.25)}function e(a,c,b,m,g,f,e,k,h,l,n,p){var y=H(d.CBANDS+1),q=k/(15<p?1152:384),u=Y(d.HBLKSIZE),x;k/=h;var r=0,v=0;for(x=0;x<d.CBANDS;x++){var t,w;t=D(k*r);y[x]=k*r;for(w=r;.34>D(k*w)-t&&w<=h/2;w++);a[x]=w-r;for(v=x+1;r<w;)u[r++]=x;if(r>h/2){r=h/2;++x;break}}y[x]=k*r;for(r=0;r<p;r++)x=l[r],t=l[r+1],x=0|Math.floor(.5+n*(x-.5)),0>x&&(x=0),w=0|Math.floor(.5+n*(t-.5)),w>h/2&&(w=h/2),b[r]=(u[x]+u[w])/2,c[r]=u[w],e[r]=(q* +t-y[c[r]])/(y[c[r]+1]-y[c[r]]),0>e[r]?e[r]=0:1<e[r]&&(e[r]=1),t=D(k*l[r]*n),t=Math.min(t,15.5)/15.5,f[r]=Math.pow(10,1.25*(1-Math.cos(Math.PI*t))-2.5);for(c=r=0;c<v;c++)b=a[c],t=D(k*r),f=D(k*(r+b-1)),m[c]=.5*(t+f),t=D(k*(r-.5)),f=D(k*(r+b-.5)),g[c]=f-t,r+=b;return v}function n(a,c,b,m,g,f){var e=ra([d.CBANDS,d.CBANDS]),k=0;if(f)for(var l=0;l<c;l++)for(f=0;f<c;f++){var n;var y=n=void 0,y=n=void 0;n=b[l]-b[f];n=0<=n?3*n:1.5*n;.5<=n&&2.5>=n?(y=n-.5,y=8*(y*y-2*y)):y=0;n+=.474;n=15.811389+7.5*n-17.5*Math.sqrt(1+ +n*n);-60>=n?n=0:(n=Math.exp(.2302585093*(y+n)),n/=.6609193);y=n*m[f];e[l][f]=y*g[l]}else for(f=0;f<c;f++){n=15+Math.min(21/b[f],12);var p;var l=n,q=y=0;p=0;var u=q=void 0;for(p=0;1E-20<h(p,l);--p);q=p;for(u=0;1E-12<Math.abs(u-q);)p=(u+q)/2,0<h(p,l)?u=p:q=p;y=q;for(p=0;1E-20<h(p,l);p+=1);q=0;for(u=p;1E-12<Math.abs(u-q);)p=(u+q)/2,0<h(p,l)?q=p:u=p;for(var q=u,u=0,x=void 0,x=0;1E3>=x;++x)p=y+x*(q-y)/1E3,p=h(p,l),u+=p;p=1001/(u*(q-y));for(l=0;l<c;l++)y=p*h(b[l]-b[f],n)*m[f],e[l][f]=y*g[l]}for(l=0;l<c;l++){for(f= +0;f<c&&!(0<e[l][f]);f++);a[l][0]=f;for(f=c-1;0<f&&!(0<e[l][f]);f--);a[l][1]=f;k+=a[l][1]-a[l][0]+1}b=H(k);for(l=m=0;l<c;l++)for(f=a[l][0];f<=a[l][1];f++)b[m++]=e[l][f];return b}function c(a){a=D(a);a=Math.min(a,15.5)/15.5;return Math.pow(10,1.25*(1-Math.cos(Math.PI*a))-2.5)}function f(a,c){-.3>a&&(a=3410);a=Math.max(.1,a/1E3);return 3.64*Math.pow(a,-.8)-6.8*Math.exp(-.6*Math.pow(a-3.4,2))+6*Math.exp(-.15*Math.pow(a-8.7,2))+.001*(.6+.04*c)*Math.pow(a,4)}var E=new Tc,z=1/217621504/(d.BLKSIZE/2),w,A, +v,p=[1,.79433,.63096,.63096,.63096,.63096,.63096,.25119,.11749],m=[3.3246*3.3246,3.23837*3.23837,9.9500500969,9.0247369744,8.1854926609,7.0440875649,2.46209*2.46209,2.284*2.284,4.4892710641,1.96552*1.96552,1.82335*1.82335,1.69146*1.69146,2.4621061921,2.1508568964,1.37074*1.37074,1.31036*1.31036,1.5691069696,1.4555939904,1.16203*1.16203,1.2715945225,1.09428*1.09428,1.0659*1.0659,1.0779838276,1.0382591025,1],x=[1.7782755904,1.35879*1.35879,1.38454*1.38454,1.39497*1.39497,1.40548*1.40548,1.3537*1.3537, +1.6999465924,1.22321*1.22321,1.3169398564,1],y=[5.5396212496,2.29259*2.29259,4.9868695969,2.12675*2.12675,2.02545*2.02545,1.87894*1.87894,1.74303*1.74303,1.61695*1.61695,2.2499700001,1.39148*1.39148,1.29083*1.29083,1.19746*1.19746,1.2339655056,1.0779838276],W=[1.7782755904,1.35879*1.35879,1.38454*1.38454,1.39497*1.39497,1.40548*1.40548,1.3537*1.3537,1.6999465924,1.22321*1.22321,1.3169398564,1],u=[11.8,13.6,17.2,32,46.5,51.3,57.5,67.1,71.5,84.6,97.6,130],pa=[6.8,5.8,5.8,6.4,6.5,9.9,12.1,14.4,15,18.9, +21.6,26.9,34.2,40.2,46.8,56.5,60.7,73.9,85.7,93.4,126.1],la=[-1.730326E-17,-.01703172,-1.349528E-17,.0418072,-6.73278E-17,-.0876324,-3.0835E-17,.1863476,-1.104424E-16,-.627638];this.L3psycho_anal_ns=function(a,c,m,f,e,h,n,y,q,u){var x=a.internal_flags,v=ra([2,d.BLKSIZE]),w=ra([2,3,d.BLKSIZE_s]),F=H(d.CBANDS+1),z=H(d.CBANDS+1),A=H(d.CBANDS+2),W=Y(2),D=Y(2),pa,R,Fa,L,K,Z,Da,O,Q=ra([2,576]),P,da=Y(d.CBANDS+2),N=Y(d.CBANDS+2);Ia.fill(N,0);pa=x.channels_out;a.mode==ka.JOINT_STEREO&&(pa=4);P=a.VBR==M.vbr_off? +0==x.ResvMax?0:x.ResvSize/x.ResvMax*.5:a.VBR==M.vbr_rh||a.VBR==M.vbr_mtrh||a.VBR==M.vbr_mt?.6:1;for(R=0;R<x.channels_out;R++){var ua=c[R],ma=m+576-350-21+192;for(L=0;576>L;L++){var Ga,Sa;Ga=ua[ma+L+10];for(K=Sa=0;9>K;K+=2)Ga+=la[K]*(ua[ma+L+K]+ua[ma+L+21-K]),Sa+=la[K+1]*(ua[ma+L+K+1]+ua[ma+L+21-K-1]);Q[R][L]=Ga+Sa}e[f][R].en.assign(x.en[R]);e[f][R].thm.assign(x.thm[R]);2<pa&&(h[f][R].en.assign(x.en[R+2]),h[f][R].thm.assign(x.thm[R+2]))}for(R=0;R<pa;R++){var ea=H(12),Oa=[0,0,0,0],kc=H(12),na=1,Ca, +ha=H(d.CBANDS),Qa=H(d.CBANDS),va=[0,0,0,0],db=H(d.HBLKSIZE),fb=ra([3,d.HBLKSIZE_s]);for(L=0;3>L;L++)ea[L]=x.nsPsy.last_en_subshort[R][L+6],kc[L]=ea[L]/x.nsPsy.last_en_subshort[R][L+4],Oa[0]+=ea[L];if(2==R)for(L=0;576>L;L++){var eb,Gb;eb=Q[0][L];Gb=Q[1][L];Q[0][L]=eb+Gb;Q[1][L]=eb-Gb}var vb=Q[R&1],Hb=0;for(L=0;9>L;L++){for(var tb=Hb+64,Ta=1;Hb<tb;Hb++)Ta<Math.abs(vb[Hb])&&(Ta=Math.abs(vb[Hb]));x.nsPsy.last_en_subshort[R][L]=ea[L+3]=Ta;Oa[1+L/3]+=Ta;Ta=Ta>ea[L+3-2]?Ta/ea[L+3-2]:ea[L+3-2]>10*Ta?ea[L+ +3-2]/(10*Ta):0;kc[L+3]=Ta}if(a.analysis){var Pb=kc[0];for(L=1;12>L;L++)Pb<kc[L]&&(Pb=kc[L]);x.pinfo.ers[f][R]=x.pinfo.ers_save[R];x.pinfo.ers_save[R]=Pb}Ca=3==R?x.nsPsy.attackthre_s:x.nsPsy.attackthre;for(L=0;12>L;L++)0==va[L/3]&&kc[L]>Ca&&(va[L/3]=L%3+1);for(L=1;4>L;L++)1.7>(Oa[L-1]>Oa[L]?Oa[L-1]/Oa[L]:Oa[L]/Oa[L-1])&&(va[L]=0,1==L&&(va[0]=0));0!=va[0]&&0!=x.nsPsy.lastAttacks[R]&&(va[0]=0);if(3==x.nsPsy.lastAttacks[R]||0!=va[0]+va[1]+va[2]+va[3])na=0,0!=va[1]&&0!=va[0]&&(va[1]=0),0!=va[2]&&0!=va[1]&& +(va[2]=0),0!=va[3]&&0!=va[2]&&(va[3]=0);2>R?D[R]=na:0==na&&(D[0]=D[1]=0);q[R]=x.tot_ener[R];var S=a,Pa=db,Qb=fb,Ua=v,wb=R&1,Ya=w,Va=R&1,mb=f,Ja=R,za=c,ub=m,$a=S.internal_flags;if(2>Ja)E.fft_long($a,Ua[wb],Ja,za,ub),E.fft_short($a,Ya[Va],Ja,za,ub);else if(2==Ja){for(var fa=d.BLKSIZE-1;0<=fa;--fa){var Rb=Ua[wb+0][fa],Ib=Ua[wb+1][fa];Ua[wb+0][fa]=(Rb+Ib)*X.SQRT2*.5;Ua[wb+1][fa]=(Rb-Ib)*X.SQRT2*.5}for(var Ka=2;0<=Ka;--Ka)for(fa=d.BLKSIZE_s-1;0<=fa;--fa)Rb=Ya[Va+0][Ka][fa],Ib=Ya[Va+1][Ka][fa],Ya[Va+0][Ka][fa]= +(Rb+Ib)*X.SQRT2*.5,Ya[Va+1][Ka][fa]=(Rb-Ib)*X.SQRT2*.5}Pa[0]=Ua[wb+0][0];Pa[0]*=Pa[0];for(fa=d.BLKSIZE/2-1;0<=fa;--fa){var ac=Ua[wb+0][d.BLKSIZE/2-fa],Bb=Ua[wb+0][d.BLKSIZE/2+fa];Pa[d.BLKSIZE/2-fa]=.5*(ac*ac+Bb*Bb)}for(Ka=2;0<=Ka;--Ka)for(Qb[Ka][0]=Ya[Va+0][Ka][0],Qb[Ka][0]*=Qb[Ka][0],fa=d.BLKSIZE_s/2-1;0<=fa;--fa)ac=Ya[Va+0][Ka][d.BLKSIZE_s/2-fa],Bb=Ya[Va+0][Ka][d.BLKSIZE_s/2+fa],Qb[Ka][d.BLKSIZE_s/2-fa]=.5*(ac*ac+Bb*Bb);for(var Ea=0,fa=11;fa<d.HBLKSIZE;fa++)Ea+=Pa[fa];$a.tot_ener[Ja]=Ea;if(S.analysis){for(fa= +0;fa<d.HBLKSIZE;fa++)$a.pinfo.energy[mb][Ja][fa]=$a.pinfo.energy_save[Ja][fa],$a.pinfo.energy_save[Ja][fa]=Pa[fa];$a.pinfo.pe[mb][Ja]=$a.pe[Ja]}2==S.athaa_loudapprox&&2>Ja&&($a.loudness_sq[mb][Ja]=$a.loudness_sq_save[Ja],$a.loudness_sq_save[Ja]=r(Pa,$a));b(x,db,F,ha,Qa);l(x,ha,Qa,da);for(O=0;3>O;O++){for(var qc,Ba,gb=fb,hb=z,Sb=A,Jb=R,bc=O,aa=a.internal_flags,nb=void 0,oa=void 0,oa=nb=0;oa<aa.npart_s;++oa){for(var ab=0,lc=0,Ab=aa.numlines_s[oa],ib=0;ib<Ab;++ib,++nb){var rc=gb[bc][nb],ab=ab+rc;lc< +rc&&(lc=rc)}hb[oa]=ab}for(nb=oa=0;oa<aa.npart_s;oa++){var ob=aa.s3ind_s[oa][0],Cb=aa.s3_ss[nb++]*hb[ob];for(++ob;ob<=aa.s3ind_s[oa][1];)Cb+=aa.s3_ss[nb]*hb[ob],++nb,++ob;var Tb=2*aa.nb_s1[Jb][oa];Sb[oa]=Math.min(Cb,Tb);aa.blocktype_old[Jb&1]==d.SHORT_TYPE&&(Tb=16*aa.nb_s2[Jb][oa],Sb[oa]=Math.min(Tb,Sb[oa]));aa.nb_s2[Jb][oa]=aa.nb_s1[Jb][oa];aa.nb_s1[Jb][oa]=Cb}for(;oa<=d.CBANDS;++oa)hb[oa]=0,Sb[oa]=0;C(x,z,A,R,O);for(Da=0;Da<d.SBMAX_s;Da++){Ba=x.thm[R].s[Da][O];Ba*=.8;if(2<=va[O]||1==va[O+1]){var Kb= +0!=O?O-1:2,Ta=t(x.thm[R].s[Da][Kb],Ba,.6*P);Ba=Math.min(Ba,Ta)}if(1==va[O])Kb=0!=O?O-1:2,Ta=t(x.thm[R].s[Da][Kb],Ba,.3*P),Ba=Math.min(Ba,Ta);else if(0!=O&&3==va[O-1]||0==O&&3==x.nsPsy.lastAttacks[R])Kb=2!=O?O+1:0,Ta=t(x.thm[R].s[Da][Kb],Ba,.3*P),Ba=Math.min(Ba,Ta);qc=ea[3*O+3]+ea[3*O+4]+ea[3*O+5];6*ea[3*O+5]<qc&&(Ba*=.5,6*ea[3*O+4]<qc&&(Ba*=.5));x.thm[R].s[Da][O]=Ba}}x.nsPsy.lastAttacks[R]=va[2];for(Fa=Z=0;Fa<x.npart_l;Fa++){for(var pb=x.s3ind[Fa][0],Ub=F[pb]*p[da[pb]],qb=x.s3_ll[Z++]*Ub;++pb<=x.s3ind[Fa][1];)Ub= +F[pb]*p[da[pb]],qb=k(qb,x.s3_ll[Z++]*Ub,pb,pb-Fa,x,0);qb*=.158489319246111;A[Fa]=x.blocktype_old[R&1]==d.SHORT_TYPE?qb:t(Math.min(qb,Math.min(2*x.nb_1[R][Fa],16*x.nb_2[R][Fa])),qb,P);x.nb_2[R][Fa]=x.nb_1[R][Fa];x.nb_1[R][Fa]=qb}for(;Fa<=d.CBANDS;++Fa)F[Fa]=0,A[Fa]=0;B(x,F,A,R)}if((a.mode==ka.STEREO||a.mode==ka.JOINT_STEREO)&&0<a.interChRatio){var Db=a.interChRatio,ba=a.internal_flags;if(1<ba.channels_out){for(var La=0;La<d.SBMAX_l;La++){var cc=ba.thm[0].l[La],Lb=ba.thm[1].l[La];ba.thm[0].l[La]+=Lb* +Db;ba.thm[1].l[La]+=cc*Db}for(La=0;La<d.SBMAX_s;La++)for(var rb=0;3>rb;rb++)cc=ba.thm[0].s[La][rb],Lb=ba.thm[1].s[La][rb],ba.thm[0].s[La][rb]+=Lb*Db,ba.thm[1].s[La][rb]+=cc*Db}}if(a.mode==ka.JOINT_STEREO){for(var Wa,ga=0;ga<d.SBMAX_l;ga++)if(!(x.thm[0].l[ga]>1.58*x.thm[1].l[ga]||x.thm[1].l[ga]>1.58*x.thm[0].l[ga])){var Za=x.mld_l[ga]*x.en[3].l[ga],sb=Math.max(x.thm[2].l[ga],Math.min(x.thm[3].l[ga],Za)),Za=x.mld_l[ga]*x.en[2].l[ga],sc=Math.max(x.thm[3].l[ga],Math.min(x.thm[2].l[ga],Za));x.thm[2].l[ga]= +sb;x.thm[3].l[ga]=sc}for(ga=0;ga<d.SBMAX_s;ga++)for(var wa=0;3>wa;wa++)x.thm[0].s[ga][wa]>1.58*x.thm[1].s[ga][wa]||x.thm[1].s[ga][wa]>1.58*x.thm[0].s[ga][wa]||(Za=x.mld_s[ga]*x.en[3].s[ga][wa],sb=Math.max(x.thm[2].s[ga][wa],Math.min(x.thm[3].s[ga][wa],Za)),Za=x.mld_s[ga]*x.en[2].s[ga][wa],sc=Math.max(x.thm[3].s[ga][wa],Math.min(x.thm[2].s[ga][wa],Za)),x.thm[2].s[ga][wa]=sb,x.thm[3].s[ga][wa]=sc);Wa=a.msfix;if(0<Math.abs(Wa)){for(var Mb=Wa,mc=Mb,dc=Math.pow(10,a.ATHlower*x.ATH.adjust),Mb=2*Mb,mc=2* +mc,Aa=0;Aa<d.SBMAX_l;Aa++){var Vb,Ra,Ha,bb;bb=x.ATH.cb_l[x.bm_l[Aa]]*dc;Vb=Math.min(Math.max(x.thm[0].l[Aa],bb),Math.max(x.thm[1].l[Aa],bb));Ra=Math.max(x.thm[2].l[Aa],bb);Ha=Math.max(x.thm[3].l[Aa],bb);if(Vb*Mb<Ra+Ha){var ec=Vb*mc/(Ra+Ha);Ra*=ec;Ha*=ec}x.thm[2].l[Aa]=Math.min(Ra,x.thm[2].l[Aa]);x.thm[3].l[Aa]=Math.min(Ha,x.thm[3].l[Aa])}dc*=d.BLKSIZE_s/d.BLKSIZE;for(Aa=0;Aa<d.SBMAX_s;Aa++)for(var xa=0;3>xa;xa++)bb=x.ATH.cb_s[x.bm_s[Aa]]*dc,Vb=Math.min(Math.max(x.thm[0].s[Aa][xa],bb),Math.max(x.thm[1].s[Aa][xa], +bb)),Ra=Math.max(x.thm[2].s[Aa][xa],bb),Ha=Math.max(x.thm[3].s[Aa][xa],bb),Vb*Mb<Ra+Ha&&(ec=Vb*Mb/(Ra+Ha),Ra*=ec,Ha*=ec),x.thm[2].s[Aa][xa]=Math.min(x.thm[2].s[Aa][xa],Ra),x.thm[3].s[Aa][xa]=Math.min(x.thm[3].s[Aa][xa],Ha)}}var jb=a.internal_flags;a.short_blocks!=sa.short_block_coupled||0!=D[0]&&0!=D[1]||(D[0]=D[1]=0);for(var Na=0;Na<jb.channels_out;Na++)W[Na]=d.NORM_TYPE,a.short_blocks==sa.short_block_dispensed&&(D[Na]=1),a.short_blocks==sa.short_block_forced&&(D[Na]=0),0!=D[Na]?jb.blocktype_old[Na]== +d.SHORT_TYPE&&(W[Na]=d.STOP_TYPE):(W[Na]=d.SHORT_TYPE,jb.blocktype_old[Na]==d.NORM_TYPE&&(jb.blocktype_old[Na]=d.START_TYPE),jb.blocktype_old[Na]==d.STOP_TYPE&&(jb.blocktype_old[Na]=d.SHORT_TYPE)),u[Na]=jb.blocktype_old[Na],jb.blocktype_old[Na]=W[Na];for(R=0;R<pa;R++){var Wb,kb=0,ca,Eb;if(1<R){Wb=y;kb=-2;ca=d.NORM_TYPE;if(u[0]==d.SHORT_TYPE||u[1]==d.SHORT_TYPE)ca=d.SHORT_TYPE;Eb=h[f][R-2]}else Wb=n,kb=0,ca=u[R],Eb=e[f][R];Wb[kb+R]=ca==d.SHORT_TYPE?V(Eb,x.masking_lower):g(Eb,x.masking_lower);a.analysis&& +(x.pinfo.pe[f][R]=Wb[kb+R])}return 0};var F=[-1.730326E-17,-.01703172,-1.349528E-17,.0418072,-6.73278E-17,-.0876324,-3.0835E-17,.1863476,-1.104424E-16,-.627638];this.L3psycho_anal_vbr=function(c,m,f,e,k,h,n,x,y,u){for(var v=c.internal_flags,w,z,A=H(d.HBLKSIZE),W=ra([3,d.HBLKSIZE_s]),D=ra([2,d.BLKSIZE]),M=ra([2,3,d.BLKSIZE_s]),la=ra([4,d.CBANDS]),O=ra([4,d.CBANDS]),R=ra([4,3]),K=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],L=Y(2),pa=c.mode==ka.JOINT_STEREO?4:v.channels_out,Z=ra([2,576]),Q=c.internal_flags, +da=Q.channels_out,ua=c.mode==ka.JOINT_STEREO?4:da,P=0;P<da;P++){firbuf=m[P];for(var ma=f+576-350-21+192,N=0;576>N;N++){var na,Ca;na=firbuf[ma+N+10];for(var Ga=Ca=0;9>Ga;Ga+=2)na+=F[Ga]*(firbuf[ma+N+Ga]+firbuf[ma+N+21-Ga]),Ca+=F[Ga+1]*(firbuf[ma+N+Ga+1]+firbuf[ma+N+21-Ga-1]);Z[P][N]=na+Ca}k[e][P].en.assign(Q.en[P]);k[e][P].thm.assign(Q.thm[P]);2<ua&&(h[e][P].en.assign(Q.en[P+2]),h[e][P].thm.assign(Q.thm[P+2]))}for(P=0;P<ua;P++){var Sa=H(12),ea=H(12),Oa=[0,0,0,0],Ia=Z[P&1],ha=0,eb=3==P?Q.nsPsy.attackthre_s: +Q.nsPsy.attackthre,Qa=1;if(2==P)for(N=0,Ga=576;0<Ga;++N,--Ga){var db=Z[0][N],va=Z[1][N];Z[0][N]=db+va;Z[1][N]=db-va}for(N=0;3>N;N++)ea[N]=Q.nsPsy.last_en_subshort[P][N+6],Sa[N]=ea[N]/Q.nsPsy.last_en_subshort[P][N+4],Oa[0]+=ea[N];for(N=0;9>N;N++){for(var vb=ha+64,fb=1;ha<vb;ha++)fb<Math.abs(Ia[ha])&&(fb=Math.abs(Ia[ha]));Q.nsPsy.last_en_subshort[P][N]=ea[N+3]=fb;Oa[1+N/3]+=fb;fb=fb>ea[N+3-2]?fb/ea[N+3-2]:ea[N+3-2]>10*fb?ea[N+3-2]/(10*fb):0;Sa[N+3]=fb}for(N=0;3>N;++N){var ub=ea[3*N+3]+ea[3*N+4]+ea[3* +N+5],Gb=1;6*ea[3*N+5]<ub&&(Gb*=.5,6*ea[3*N+4]<ub&&(Gb*=.5));R[P][N]=Gb}if(c.analysis){for(var tb=Sa[0],N=1;12>N;N++)tb<Sa[N]&&(tb=Sa[N]);Q.pinfo.ers[e][P]=Q.pinfo.ers_save[P];Q.pinfo.ers_save[P]=tb}for(N=0;12>N;N++)0==K[P][N/3]&&Sa[N]>eb&&(K[P][N/3]=N%3+1);for(N=1;4>N;N++){var Hb=Oa[N-1],Ab=Oa[N];4E4>Math.max(Hb,Ab)&&Hb<1.7*Ab&&Ab<1.7*Hb&&(1==N&&K[P][0]<=K[P][N]&&(K[P][0]=0),K[P][N]=0)}K[P][0]<=Q.nsPsy.lastAttacks[P]&&(K[P][0]=0);if(3==Q.nsPsy.lastAttacks[P]||0!=K[P][0]+K[P][1]+K[P][2]+K[P][3])Qa= +0,0!=K[P][1]&&0!=K[P][0]&&(K[P][1]=0),0!=K[P][2]&&0!=K[P][1]&&(K[P][2]=0),0!=K[P][3]&&0!=K[P][2]&&(K[P][3]=0);2>P?L[P]=Qa:0==Qa&&(L[0]=L[1]=0);y[P]=Q.tot_ener[P]}var Ta=c.internal_flags;c.short_blocks!=sa.short_block_coupled||0!=L[0]&&0!=L[1]||(L[0]=L[1]=0);for(var Pb=0;Pb<Ta.channels_out;Pb++)c.short_blocks==sa.short_block_dispensed&&(L[Pb]=1),c.short_blocks==sa.short_block_forced&&(L[Pb]=0);for(var S=0;S<pa;S++){var Pa=S&1;w=D;var Qb=c,Ua=S,wb=e,Ya=A,Va=w,mb=Pa,Ja=Qb.internal_flags;if(2>Ua)E.fft_long(Ja, +Va[mb],Ua,m,f);else if(2==Ua)for(var za=d.BLKSIZE-1;0<=za;--za){var $b=Va[mb+0][za],$a=Va[mb+1][za];Va[mb+0][za]=($b+$a)*X.SQRT2*.5;Va[mb+1][za]=($b-$a)*X.SQRT2*.5}Ya[0]=Va[mb+0][0];Ya[0]*=Ya[0];for(za=d.BLKSIZE/2-1;0<=za;--za){var fa=Va[mb+0][d.BLKSIZE/2-za],Rb=Va[mb+0][d.BLKSIZE/2+za];Ya[d.BLKSIZE/2-za]=.5*(fa*fa+Rb*Rb)}for(var Ib=0,za=11;za<d.HBLKSIZE;za++)Ib+=Ya[za];Ja.tot_ener[Ua]=Ib;if(Qb.analysis){for(za=0;za<d.HBLKSIZE;za++)Ja.pinfo.energy[wb][Ua][za]=Ja.pinfo.energy_save[Ua][za],Ja.pinfo.energy_save[Ua][za]= +Ya[za];Ja.pinfo.pe[wb][Ua]=Ja.pe[Ua]}var Ka=S,ac=A,Bb=c.internal_flags;2==c.athaa_loudapprox&&2>Ka&&(Bb.loudness_sq[e][Ka]=Bb.loudness_sq_save[Ka],Bb.loudness_sq_save[Ka]=r(ac,Bb));if(0!=L[Pa]){var Ea=v,qc=A,Ba=la[S],gb=O[S],hb=S,Sb=H(d.CBANDS),Jb=H(d.CBANDS),bc=Y(d.CBANDS+2),aa=void 0;b(Ea,qc,Ba,Sb,Jb);l(Ea,Sb,Jb,bc);for(var nb=0,aa=0;aa<Ea.npart_l;aa++){var oa,ab,lc,ic,ib=Ea.s3ind[aa][0],rc=Ea.s3ind[aa][1],ob=0,Cb=0,ob=bc[ib],Cb=Cb+1;ab=Ea.s3_ll[nb]*Ba[ib]*p[bc[ib]];++nb;for(++ib;ib<=rc;)ob+=bc[ib], +Cb+=1,oa=Ea.s3_ll[nb]*Ba[ib]*p[bc[ib]],ab=ic=q(ab,oa,ib-aa),++nb,++ib;ob=(1+2*ob)/(2*Cb);lc=.5*p[ob];ab*=lc;if(Ea.blocktype_old[hb&1]==d.SHORT_TYPE){var Tb=2*Ea.nb_1[hb][aa];gb[aa]=0<Tb?Math.min(ab,Tb):Math.min(ab,.3*Ba[aa])}else{var Kb=16*Ea.nb_2[hb][aa],pb=2*Ea.nb_1[hb][aa];0>=Kb&&(Kb=ab);0>=pb&&(pb=ab);Tb=Ea.blocktype_old[hb&1]==d.NORM_TYPE?Math.min(pb,Kb):pb;gb[aa]=Math.min(ab,Tb)}Ea.nb_2[hb][aa]=Ea.nb_1[hb][aa];Ea.nb_1[hb][aa]=ab;oa=Sb[aa];oa*=Ea.minval_l[aa];oa*=lc;gb[aa]>oa&&(gb[aa]=oa);1< +Ea.masking_lower&&(gb[aa]*=Ea.masking_lower);gb[aa]>Ba[aa]&&(gb[aa]=Ba[aa]);1>Ea.masking_lower&&(gb[aa]*=Ea.masking_lower)}for(;aa<d.CBANDS;++aa)Ba[aa]=0,gb[aa]=0}else for(var Ub=v,qb=S,Db=0;Db<Ub.npart_l;Db++)Ub.nb_2[qb][Db]=Ub.nb_1[qb][Db],Ub.nb_1[qb][Db]=0}2==L[0]+L[1]&&c.mode==ka.JOINT_STEREO&&a(la,O,v.mld_cb_l,v.ATH.cb_l,c.ATHlower*v.ATH.adjust,c.msfix,v.npart_l);for(S=0;S<pa;S++)Pa=S&1,0!=L[Pa]&&B(v,la[S],O[S],S);for(var ba=0;3>ba;ba++){for(S=0;S<pa;++S)if(Pa=S&1,0!=L[Pa]){var La=v,cc=S;if(0== +ba)for(var Lb=0;Lb<La.npart_s;Lb++)La.nb_s2[cc][Lb]=La.nb_s1[cc][Lb],La.nb_s1[cc][Lb]=0}else{z=M;var rb=S,Wa=ba,ga=W,Za=z,sb=Pa,sc=c.internal_flags;0==Wa&&2>rb&&E.fft_short(sc,Za[sb],rb,m,f);if(2==rb)for(var wa=d.BLKSIZE_s-1;0<=wa;--wa){var Mb=Za[sb+0][Wa][wa],mc=Za[sb+1][Wa][wa];Za[sb+0][Wa][wa]=(Mb+mc)*X.SQRT2*.5;Za[sb+1][Wa][wa]=(Mb-mc)*X.SQRT2*.5}ga[Wa][0]=Za[sb+0][Wa][0];ga[Wa][0]*=ga[Wa][0];for(wa=d.BLKSIZE_s/2-1;0<=wa;--wa){var dc=Za[sb+0][Wa][d.BLKSIZE_s/2-wa],Aa=Za[sb+0][Wa][d.BLKSIZE_s/ +2+wa];ga[Wa][d.BLKSIZE_s/2-wa]=.5*(dc*dc+Aa*Aa)}for(var Vb=W,Ra=la[S],Ha=O[S],bb=S,ec=ba,xa=c.internal_flags,jb=new float[d.CBANDS],Na=H(d.CBANDS),Wb=void 0,kb=void 0,ca=void 0,Eb=new int[d.CBANDS],ca=kb=0;ca<xa.npart_s;++ca){for(var Ob=0,Zb=0,jc=xa.numlines_s[ca],Wb=0;Wb<jc;++Wb,++kb){var Bc=Vb[ec][kb],Ob=Ob+Bc;Zb<Bc&&(Zb=Bc)}Ra[ca]=Ob;jb[ca]=Zb;Na[ca]=Ob/jc}for(;ca<d.CBANDS;++ca)jb[ca]=0,Na[ca]=0;var Xb=xa,xb=jb,fc=Na,nc=Eb,oc=p.length-1,ja=0,Xa=fc[ja]+fc[ja+1];if(0<Xa){var lb=xb[ja];lb<xb[ja+1]&& +(lb=xb[ja+1]);var Xa=20*(2*lb-Xa)/(Xa*(Xb.numlines_s[ja]+Xb.numlines_s[ja+1]-1)),yb=0|Xa;yb>oc&&(yb=oc);nc[ja]=yb}else nc[ja]=0;for(ja=1;ja<Xb.npart_s-1;ja++)Xa=fc[ja-1]+fc[ja]+fc[ja+1],0<Xa?(lb=xb[ja-1],lb<xb[ja]&&(lb=xb[ja]),lb<xb[ja+1]&&(lb=xb[ja+1]),Xa=20*(3*lb-Xa)/(Xa*(Xb.numlines_s[ja-1]+Xb.numlines_s[ja]+Xb.numlines_s[ja+1]-1)),yb=0|Xa,yb>oc&&(yb=oc),nc[ja]=yb):nc[ja]=0;Xa=fc[ja-1]+fc[ja];0<Xa?(lb=xb[ja-1],lb<xb[ja]&&(lb=xb[ja]),Xa=20*(2*lb-Xa)/(Xa*(Xb.numlines_s[ja-1]+Xb.numlines_s[ja]-1)), +yb=0|Xa,yb>oc&&(yb=oc),nc[ja]=yb):nc[ja]=0;for(kb=ca=0;ca<xa.npart_s;ca++){var Fb=xa.s3ind_s[ca][0],vc=xa.s3ind_s[ca][1],pc,wc,Nb,gc,Cc;pc=Eb[Fb];wc=1;gc=xa.s3_ss[kb]*Ra[Fb]*p[Eb[Fb]];++kb;for(++Fb;Fb<=vc;)pc+=Eb[Fb],wc+=1,Nb=xa.s3_ss[kb]*Ra[Fb]*p[Eb[Fb]],gc=q(gc,Nb,Fb-ca),++kb,++Fb;pc=(1+2*pc)/(2*wc);Cc=.5*p[pc];gc*=Cc;Ha[ca]=gc;xa.nb_s2[bb][ca]=xa.nb_s1[bb][ca];xa.nb_s1[bb][ca]=gc;Nb=jb[ca];Nb*=xa.minval_s[ca];Nb*=Cc;Ha[ca]>Nb&&(Ha[ca]=Nb);1<xa.masking_lower&&(Ha[ca]*=xa.masking_lower);Ha[ca]>Ra[ca]&& +(Ha[ca]=Ra[ca]);1>xa.masking_lower&&(Ha[ca]*=xa.masking_lower)}for(;ca<d.CBANDS;++ca)Ra[ca]=0,Ha[ca]=0}0==L[0]+L[1]&&c.mode==ka.JOINT_STEREO&&a(la,O,v.mld_cb_s,v.ATH.cb_s,c.ATHlower*v.ATH.adjust,c.msfix,v.npart_s);for(S=0;S<pa;++S)Pa=S&1,0==L[Pa]&&C(v,la[S],O[S],S,ba)}for(S=0;S<pa;S++)if(Pa=S&1,0==L[Pa])for(var hc=0;hc<d.SBMAX_s;hc++){for(var Ec=H(3),ba=0;3>ba;ba++){var cb=v.thm[S].s[hc][ba],cb=.8*cb;if(2<=K[S][ba]||1==K[S][ba+1])var tc=0!=ba?ba-1:2,uc=t(v.thm[S].s[hc][tc],cb,.36),cb=Math.min(cb, +uc);else if(1==K[S][ba])tc=0!=ba?ba-1:2,uc=t(v.thm[S].s[hc][tc],cb,.18),cb=Math.min(cb,uc);else if(0!=ba&&3==K[S][ba-1]||0==ba&&3==v.nsPsy.lastAttacks[S])tc=2!=ba?ba+1:0,uc=t(v.thm[S].s[hc][tc],cb,.18),cb=Math.min(cb,uc);cb*=R[S][ba];Ec[ba]=cb}for(ba=0;3>ba;ba++)v.thm[S].s[hc][ba]=Ec[ba]}for(S=0;S<pa;S++)v.nsPsy.lastAttacks[S]=K[S][2];for(var Yb=c.internal_flags,zb=0;zb<Yb.channels_out;zb++){var Dc=d.NORM_TYPE;0!=L[zb]?Yb.blocktype_old[zb]==d.SHORT_TYPE&&(Dc=d.STOP_TYPE):(Dc=d.SHORT_TYPE,Yb.blocktype_old[zb]== +d.NORM_TYPE&&(Yb.blocktype_old[zb]=d.START_TYPE),Yb.blocktype_old[zb]==d.STOP_TYPE&&(Yb.blocktype_old[zb]=d.SHORT_TYPE));u[zb]=Yb.blocktype_old[zb];Yb.blocktype_old[zb]=Dc}for(S=0;S<pa;S++){var xc,yc,zc,Ac;if(1<S){xc=x;yc=-2;zc=d.NORM_TYPE;if(u[0]==d.SHORT_TYPE||u[1]==d.SHORT_TYPE)zc=d.SHORT_TYPE;Ac=h[e][S-2]}else xc=n,yc=0,zc=u[S],Ac=k[e][S];xc[yc+S]=zc==d.SHORT_TYPE?V(Ac,v.masking_lower):g(Ac,v.masking_lower);c.analysis&&(v.pinfo.pe[e][S]=xc[yc+S])}return 0};this.psymodel_init=function(a){var b= +a.internal_flags,m,f=!0,g=13,k=0,h=0,l=-8.25,p=-4.5,x=H(d.CBANDS),y=H(d.CBANDS),q=H(d.CBANDS),u=a.out_samplerate;switch(a.experimentalZ){default:case 0:f=!0;break;case 1:f=a.VBR==M.vbr_mtrh||a.VBR==M.vbr_mt?!1:!0;break;case 2:f=!1;break;case 3:g=8,k=-1.75,h=-.0125,l=-8.25,p=-2.25}b.ms_ener_ratio_old=.25;b.blocktype_old[0]=b.blocktype_old[1]=d.NORM_TYPE;for(m=0;4>m;++m){for(var r=0;r<d.CBANDS;++r)b.nb_1[m][r]=1E20,b.nb_2[m][r]=1E20,b.nb_s1[m][r]=b.nb_s2[m][r]=1;for(var t=0;t<d.SBMAX_l;t++)b.en[m].l[t]= +1E20,b.thm[m].l[t]=1E20;for(r=0;3>r;++r){for(t=0;t<d.SBMAX_s;t++)b.en[m].s[t][r]=1E20,b.thm[m].s[t][r]=1E20;b.nsPsy.lastAttacks[m]=0}for(r=0;9>r;r++)b.nsPsy.last_en_subshort[m][r]=10}b.loudness_sq_save[0]=b.loudness_sq_save[1]=0;b.npart_l=e(b.numlines_l,b.bo_l,b.bm_l,x,y,b.mld_l,b.PSY.bo_l_weight,u,d.BLKSIZE,b.scalefac_band.l,d.BLKSIZE/1152,d.SBMAX_l);for(m=0;m<b.npart_l;m++)t=k,x[m]>=g&&(t=h*(x[m]-g)/(24-g)+k*(24-x[m])/(24-g)),q[m]=Math.pow(10,t/10),b.rnumlines_l[m]=0<b.numlines_l[m]?1/b.numlines_l[m]: +0;b.s3_ll=n(b.s3ind,b.npart_l,x,y,q,f);for(m=r=0;m<b.npart_l;m++){h=vb.MAX_VALUE;for(t=0;t<b.numlines_l[m];t++,r++)k=u*r/(1E3*d.BLKSIZE),k=this.ATHformula(1E3*k,a)-20,k=Math.pow(10,.1*k),k*=b.numlines_l[m],h>k&&(h=k);b.ATH.cb_l[m]=h;h=-20+20*x[m]/10;6<h&&(h=100);-15>h&&(h=-15);h-=8;b.minval_l[m]=Math.pow(10,h/10)*b.numlines_l[m]}b.npart_s=e(b.numlines_s,b.bo_s,b.bm_s,x,y,b.mld_s,b.PSY.bo_s_weight,u,d.BLKSIZE_s,b.scalefac_band.s,d.BLKSIZE_s/384,d.SBMAX_s);for(m=r=0;m<b.npart_s;m++){t=l;x[m]>=g&&(t= +p*(x[m]-g)/(24-g)+l*(24-x[m])/(24-g));q[m]=Math.pow(10,t/10);h=vb.MAX_VALUE;for(t=0;t<b.numlines_s[m];t++,r++)k=u*r/(1E3*d.BLKSIZE_s),k=this.ATHformula(1E3*k,a)-20,k=Math.pow(10,.1*k),k*=b.numlines_s[m],h>k&&(h=k);b.ATH.cb_s[m]=h;h=-7+7*x[m]/12;12<x[m]&&(h*=1+3.1*Math.log(1+h));12>x[m]&&(h*=1+2.3*Math.log(1-h));-15>h&&(h=-15);h-=8;b.minval_s[m]=Math.pow(10,h/10)*b.numlines_s[m]}b.s3_ss=n(b.s3ind_s,b.npart_s,x,y,q,f);w=Math.pow(10,.5625);A=Math.pow(10,1.5);v=Math.pow(10,1.5);E.init_fft(b);b.decay= +Math.exp(-2.302585092994046/(.01*u/192));m=3.5;0!=(a.exp_nspsytune&2)&&(m=1);0<Math.abs(a.msfix)&&(m=a.msfix);a.msfix=m;for(f=0;f<b.npart_l;f++)b.s3ind[f][1]>b.npart_l-1&&(b.s3ind[f][1]=b.npart_l-1);b.ATH.decay=Math.pow(10,576*b.mode_gr/u*-1.2);b.ATH.adjust=.01;b.ATH.adjustLimit=1;if(-1!=a.ATHtype){r=a.out_samplerate/d.BLKSIZE;for(m=k=f=0;m<d.BLKSIZE/2;++m)k+=r,b.ATH.eql_w[m]=1/Math.pow(10,this.ATHformula(k,a)/10),f+=b.ATH.eql_w[m];f=1/f;for(m=d.BLKSIZE/2;0<=--m;)b.ATH.eql_w[m]*=f}for(f=r=0;f<b.npart_s;++f)for(m= +0;m<b.numlines_s[f];++m)++r;for(f=r=0;f<b.npart_l;++f)for(m=0;m<b.numlines_l[f];++m)++r;for(m=r=0;m<b.npart_l;m++)k=u*(r+b.numlines_l[m]/2)/(1*d.BLKSIZE),b.mld_cb_l[m]=c(k),r+=b.numlines_l[m];for(;m<d.CBANDS;++m)b.mld_cb_l[m]=1;for(m=r=0;m<b.npart_s;m++)k=u*(r+b.numlines_s[m]/2)/(1*d.BLKSIZE_s),b.mld_cb_s[m]=c(k),r+=b.numlines_s[m];for(;m<d.CBANDS;++m)b.mld_cb_s[m]=1;return 0};this.ATHformula=function(a,c){var b;switch(c.ATHtype){case 0:b=f(a,9);break;case 1:b=f(a,-1);break;case 2:b=f(a,0);break; +case 3:b=f(a,1)+6;break;case 4:b=f(a,c.ATHcurve);break;default:b=f(a,0)}return b}}function V(){function J(){this.mask_adjust_short=this.mask_adjust=0;this.bo_l_weight=H(d.SBMAX_l);this.bo_s_weight=H(d.SBMAX_s)}function k(){this.lowerlimit=0}function q(a,c){this.lowpass=c}function C(a){return 1<a?0:0>=a?1:Math.cos(Math.PI/2*a)}function B(a,c){switch(a){case 44100:return c.version=1,0;case 48E3:return c.version=1;case 32E3:return c.version=1,2;case 22050:return c.version=0;case 24E3:return c.version= +0,1;case 16E3:return c.version=0,2;case 11025:return c.version=0;case 12E3:return c.version=0,1;case 8E3:return c.version=0,2;default:return c.version=0,-1}}function t(a,c,b){16E3>b&&(c=2);b=r.bitrate_table[c][1];for(var d=2;14>=d;d++)0<r.bitrate_table[c][d]&&Math.abs(r.bitrate_table[c][d]-a)<Math.abs(b-a)&&(b=r.bitrate_table[c][d]);return b}function Q(a,c,b){16E3>b&&(c=2);for(b=0;14>=b;b++)if(0<r.bitrate_table[c][b]&&r.bitrate_table[c][b]==a)return b;return-1}function g(a,c){var b=[new q(8,2E3), +new q(16,3700),new q(24,3900),new q(32,5500),new q(40,7E3),new q(48,7500),new q(56,1E4),new q(64,11E3),new q(80,13500),new q(96,15100),new q(112,15600),new q(128,17E3),new q(160,17500),new q(192,18600),new q(224,19400),new q(256,19700),new q(320,20500)],d=e.nearestBitrateFullIndex(c);a.lowerlimit=b[d].lowpass}function b(a){var c=d.BLKSIZE+a.framesize-d.FFTOFFSET;return c=Math.max(c,512+a.framesize-32)}function l(m,f,g,k,l,p,q){var r=m.internal_flags,v=0,t,w,A=[null,null],z=[null,null];if(4294479419!= +r.Class_ID)return-3;if(0==k)return 0;t=c.copy_buffer(r,l,p,q,0);if(0>t)return t;p+=t;v+=t;z[0]=f;z[1]=g;if(ua.NEQ(m.scale,0)&&ua.NEQ(m.scale,1))for(t=0;t<k;++t)z[0][t]*=m.scale,2==r.channels_out&&(z[1][t]*=m.scale);if(ua.NEQ(m.scale_left,0)&&ua.NEQ(m.scale_left,1))for(t=0;t<k;++t)z[0][t]*=m.scale_left;if(ua.NEQ(m.scale_right,0)&&ua.NEQ(m.scale_right,1))for(t=0;t<k;++t)z[1][t]*=m.scale_right;if(2==m.num_channels&&1==r.channels_out)for(t=0;t<k;++t)z[0][t]=.5*(z[0][t]+z[1][t]),z[1][t]=0;f=b(m);A[0]= +r.mfbuf[0];A[1]=r.mfbuf[1];for(g=0;0<k;){var B=[null,null];t=w=0;B[0]=z[0];B[1]=z[1];t=new a;var C=m;w=A;var E=g,J=k,K=t,M=C.internal_flags;if(.9999>M.resample_ratio||1.0001<M.resample_ratio)for(var Q=0;Q<M.channels_out;Q++){var V=new h,Y=K,X=w[Q],ta=M.mf_size,ka=C.framesize,ma=B[Q],ra=E,R=J,Fa=V,L=Q,Ma=C.internal_flags,Z=void 0,Da=0,na=void 0,sa=C.out_samplerate/D(C.out_samplerate,C.in_samplerate);sa>da.BPC&&(sa=da.BPC);var P=1E-4>Math.abs(Ma.resample_ratio-Math.floor(.5+Ma.resample_ratio))?1:0, +na=1/Ma.resample_ratio;1<na&&(na=1);var ha=31;0==ha%2&&--ha;ha+=P;P=ha+1;if(0==Ma.fill_buffer_resample_init){Ma.inbuf_old[0]=H(P);Ma.inbuf_old[1]=H(P);for(Z=0;Z<=2*sa;++Z)Ma.blackfilt[Z]=H(P);Ma.itime[0]=0;for(Da=Ma.itime[1]=0;Da<=2*sa;Da++){for(var N=0,Ca=(Da-sa)/(2*sa),Z=0;Z<=ha;Z++){var Ia=Ma.blackfilt[Da],Ga=Z,Sa,ea=Z-Ca;Sa=ha;var Oa=Math.PI*na,ea=ea/Sa;0>ea&&(ea=0);1<ea&&(ea=1);var Qa=ea-.5,ea=.42-.5*Math.cos(2*ea*Math.PI)+.08*Math.cos(4*ea*Math.PI);Sa=1E-9>Math.abs(Qa)?Oa/Math.PI:ea*Math.sin(Sa* +Oa*Qa)/(Math.PI*Sa*Qa);N+=Ia[Ga]=Sa}for(Z=0;Z<=ha;Z++)Ma.blackfilt[Da][Z]/=N}Ma.fill_buffer_resample_init=1}N=Ma.inbuf_old[L];for(na=0;na<ka;na++){Z=na*Ma.resample_ratio;Da=0|Math.floor(Z-Ma.itime[L]);if(ha+Da-ha/2>=R)break;Ca=Z-Ma.itime[L]-(Da+ha%2*.5);Ca=0|Math.floor(2*Ca*sa+sa+.5);for(Z=Ia=0;Z<=ha;++Z)Ga=Z+Da-ha/2,Ia+=(0>Ga?N[P+Ga]:ma[ra+Ga])*Ma.blackfilt[Ca][Z];X[ta+na]=Ia}Fa.num_used=Math.min(R,ha+Da-ha/2);Ma.itime[L]+=Fa.num_used-na*Ma.resample_ratio;if(Fa.num_used>=P)for(Z=0;Z<P;Z++)N[Z]=ma[ra+ +Fa.num_used+Z-P];else{X=P-Fa.num_used;for(Z=0;Z<X;++Z)N[Z]=N[Z+Fa.num_used];for(Da=0;Z<P;++Z,++Da)N[Z]=ma[ra+Da]}Y.n_out=na;K.n_in=V.num_used}else for(K.n_out=Math.min(C.framesize,J),K.n_in=K.n_out,C=0;C<K.n_out;++C)w[0][M.mf_size+C]=B[0][E+C],2==M.channels_out&&(w[1][M.mf_size+C]=B[1][E+C]);w=t.n_in;t=t.n_out;if(r.findReplayGain&&!r.decode_on_the_fly&&n.AnalyzeSamples(r.rgdata,A[0],r.mf_size,A[1],r.mf_size,t,r.channels_out)==O.GAIN_ANALYSIS_ERROR)return-6;k-=w;g+=w;r.mf_size+=t;1>r.mf_samples_to_encode&& +(r.mf_samples_to_encode=d.ENCDELAY+d.POSTDELAY);r.mf_samples_to_encode+=t;if(r.mf_size>=f){w=q-v;0==q&&(w=0);t=m;w=e.enc.lame_encode_mp3_frame(t,A[0],A[1],l,p,w);t.frameNum++;t=w;if(0>t)return t;p+=t;v+=t;r.mf_size-=m.framesize;r.mf_samples_to_encode-=m.framesize;for(w=0;w<r.channels_out;w++)for(t=0;t<r.mf_size;t++)A[w][t]=A[w][t+m.framesize]}}return v}function a(){this.n_out=this.n_in=0}function h(){this.num_used=0}function D(a,c){return 0!=c?D(c,a%c):a}var e=this;V.V9=410;V.V8=420;V.V7=430;V.V6= +440;V.V5=450;V.V4=460;V.V3=470;V.V2=480;V.V1=490;V.V0=500;V.R3MIX=1E3;V.STANDARD=1001;V.EXTREME=1002;V.INSANE=1003;V.STANDARD_FAST=1004;V.EXTREME_FAST=1005;V.MEDIUM=1006;V.MEDIUM_FAST=1007;V.LAME_MAXMP3BUFFER=147456;var n,c,f,E,z,w=new jc,A,v,p;this.enc=new d;this.setModules=function(a,b,d,g,e,k,h,l,q){n=a;c=b;f=d;E=g;z=e;A=k;v=l;p=q;this.enc.setModules(c,w,E,A)};this.lame_init=function(){var a=new Jc,c;a.class_id=4294479419;c=a.internal_flags=new da;a.mode=ka.NOT_SET;a.original=1;a.in_samplerate= +44100;a.num_channels=2;a.num_samples=-1;a.bWriteVbrTag=!0;a.quality=-1;a.short_blocks=null;c.subblock_gain=-1;a.lowpassfreq=0;a.highpassfreq=0;a.lowpasswidth=-1;a.highpasswidth=-1;a.VBR=M.vbr_off;a.VBR_q=4;a.ATHcurve=-1;a.VBR_mean_bitrate_kbps=128;a.VBR_min_bitrate_kbps=0;a.VBR_max_bitrate_kbps=0;a.VBR_hard_min=0;c.VBR_min_bitrate=1;c.VBR_max_bitrate=13;a.quant_comp=-1;a.quant_comp_short=-1;a.msfix=-1;c.resample_ratio=1;c.OldValue[0]=180;c.OldValue[1]=180;c.CurrentStep[0]=4;c.CurrentStep[1]=4;c.masking_lower= +1;c.nsPsy.attackthre=-1;c.nsPsy.attackthre_s=-1;a.scale=-1;a.athaa_type=-1;a.ATHtype=-1;a.athaa_loudapprox=-1;a.athaa_sensitivity=0;a.useTemporal=null;a.interChRatio=-1;c.mf_samples_to_encode=d.ENCDELAY+d.POSTDELAY;a.encoder_padding=0;c.mf_size=d.ENCDELAY-d.MDCTDELAY;a.findReplayGain=!1;a.decode_on_the_fly=!1;c.decode_on_the_fly=!1;c.findReplayGain=!1;c.findPeakSample=!1;c.RadioGain=0;c.AudiophileGain=0;c.noclipGainChange=0;c.noclipScale=-1;a.preset=0;a.write_id3tag_automatic=!0;a.lame_allocated_gfp= +1;return a};this.nearestBitrateFullIndex=function(a){for(var c=[8,16,24,32,40,48,56,64,80,96,112,128,160,192,224,256,320],b=0,d=0,f=0,g=0,g=c[16],f=16,d=c[16],b=16,e=0;16>e;e++)if(Math.max(a,c[e+1])!=a){g=c[e+1];f=e+1;d=c[e];b=e;break}return g-a>a-d?b:f};this.lame_init_params=function(a){var b=a.internal_flags;b.Class_ID=0;null==b.ATH&&(b.ATH=new Lc);null==b.PSY&&(b.PSY=new J);null==b.rgdata&&(b.rgdata=new Kc);b.channels_in=a.num_channels;1==b.channels_in&&(a.mode=ka.MONO);b.channels_out=a.mode== +ka.MONO?1:2;b.mode_ext=d.MPG_MD_MS_LR;a.mode==ka.MONO&&(a.force_ms=!1);a.VBR==M.vbr_off&&128!=a.VBR_mean_bitrate_kbps&&0==a.brate&&(a.brate=a.VBR_mean_bitrate_kbps);a.VBR!=M.vbr_off&&a.VBR!=M.vbr_mtrh&&a.VBR!=M.vbr_mt&&(a.free_format=!1);a.VBR==M.vbr_off&&0==a.brate&&ua.EQ(a.compression_ratio,0)&&(a.compression_ratio=11.025);a.VBR==M.vbr_off&&0<a.compression_ratio&&(0==a.out_samplerate&&(a.out_samplerate=map2MP3Frequency(int(.97*a.in_samplerate))),a.brate=0|16*a.out_samplerate*b.channels_out/(1E3* +a.compression_ratio),b.samplerate_index=B(a.out_samplerate,a),a.free_format||(a.brate=t(a.brate,a.version,a.out_samplerate)));0!=a.out_samplerate&&(16E3>a.out_samplerate?(a.VBR_mean_bitrate_kbps=Math.max(a.VBR_mean_bitrate_kbps,8),a.VBR_mean_bitrate_kbps=Math.min(a.VBR_mean_bitrate_kbps,64)):32E3>a.out_samplerate?(a.VBR_mean_bitrate_kbps=Math.max(a.VBR_mean_bitrate_kbps,8),a.VBR_mean_bitrate_kbps=Math.min(a.VBR_mean_bitrate_kbps,160)):(a.VBR_mean_bitrate_kbps=Math.max(a.VBR_mean_bitrate_kbps,32), +a.VBR_mean_bitrate_kbps=Math.min(a.VBR_mean_bitrate_kbps,320)));if(0==a.lowpassfreq){var e=16E3;switch(a.VBR){case M.vbr_off:e=new k;g(e,a.brate);e=e.lowerlimit;break;case M.vbr_abr:e=new k;g(e,a.VBR_mean_bitrate_kbps);e=e.lowerlimit;break;case M.vbr_rh:var h=[19500,19E3,18600,18E3,17500,16E3,15600,14900,12500,1E4,3950];if(0<=a.VBR_q&&9>=a.VBR_q)var e=h[a.VBR_q],h=h[a.VBR_q+1],l=a.VBR_q_frac,e=linear_int(e,h,l);else e=19500;break;default:h=[19500,19E3,18500,18E3,17500,16500,15500,14500,12500,9500, +3950],0<=a.VBR_q&&9>=a.VBR_q?(e=h[a.VBR_q],h=h[a.VBR_q+1],l=a.VBR_q_frac,e=linear_int(e,h,l)):e=19500}a.mode!=ka.MONO||a.VBR!=M.vbr_off&&a.VBR!=M.vbr_abr||(e*=1.5);a.lowpassfreq=e|0}0==a.out_samplerate&&(2*a.lowpassfreq>a.in_samplerate&&(a.lowpassfreq=a.in_samplerate/2),e=a.lowpassfreq|0,h=a.in_samplerate,l=44100,48E3<=h?l=48E3:44100<=h?l=44100:32E3<=h?l=32E3:24E3<=h?l=24E3:22050<=h?l=22050:16E3<=h?l=16E3:12E3<=h?l=12E3:11025<=h?l=11025:8E3<=h&&(l=8E3),-1==e?e=l:(15960>=e&&(l=44100),15250>=e&&(l= +32E3),11220>=e&&(l=24E3),9970>=e&&(l=22050),7230>=e&&(l=16E3),5420>=e&&(l=12E3),4510>=e&&(l=11025),3970>=e&&(l=8E3),e=h<l?44100<h?48E3:32E3<h?44100:24E3<h?32E3:22050<h?24E3:16E3<h?22050:12E3<h?16E3:11025<h?12E3:8E3<h?11025:8E3:l),a.out_samplerate=e);a.lowpassfreq=Math.min(20500,a.lowpassfreq);a.lowpassfreq=Math.min(a.out_samplerate/2,a.lowpassfreq);a.VBR==M.vbr_off&&(a.compression_ratio=16*a.out_samplerate*b.channels_out/(1E3*a.brate));a.VBR==M.vbr_abr&&(a.compression_ratio=16*a.out_samplerate*b.channels_out/ +(1E3*a.VBR_mean_bitrate_kbps));a.bWriteVbrTag||(a.findReplayGain=!1,a.decode_on_the_fly=!1,b.findPeakSample=!1);b.findReplayGain=a.findReplayGain;b.decode_on_the_fly=a.decode_on_the_fly;b.decode_on_the_fly&&(b.findPeakSample=!0);if(b.findReplayGain&&n.InitGainAnalysis(b.rgdata,a.out_samplerate)==O.INIT_GAIN_ANALYSIS_ERROR)return a.internal_flags=null,-6;b.decode_on_the_fly&&!a.decode_only&&(null!=b.hip&&p.hip_decode_exit(b.hip),b.hip=p.hip_decode_init());b.mode_gr=24E3>=a.out_samplerate?1:2;a.framesize= +576*b.mode_gr;a.encoder_delay=d.ENCDELAY;b.resample_ratio=a.in_samplerate/a.out_samplerate;switch(a.VBR){case M.vbr_mt:case M.vbr_rh:case M.vbr_mtrh:a.compression_ratio=[5.7,6.5,7.3,8.2,10,11.9,13,14,15,16.5][a.VBR_q];break;case M.vbr_abr:a.compression_ratio=16*a.out_samplerate*b.channels_out/(1E3*a.VBR_mean_bitrate_kbps);break;default:a.compression_ratio=16*a.out_samplerate*b.channels_out/(1E3*a.brate)}a.mode==ka.NOT_SET&&(a.mode=ka.JOINT_STEREO);0<a.highpassfreq?(b.highpass1=2*a.highpassfreq,b.highpass2= +0<=a.highpasswidth?2*(a.highpassfreq+a.highpasswidth):2*a.highpassfreq,b.highpass1/=a.out_samplerate,b.highpass2/=a.out_samplerate):(b.highpass1=0,b.highpass2=0);0<a.lowpassfreq?(b.lowpass2=2*a.lowpassfreq,0<=a.lowpasswidth?(b.lowpass1=2*(a.lowpassfreq-a.lowpasswidth),0>b.lowpass1&&(b.lowpass1=0)):b.lowpass1=2*a.lowpassfreq,b.lowpass1/=a.out_samplerate,b.lowpass2/=a.out_samplerate):(b.lowpass1=0,b.lowpass2=0);var e=a.internal_flags,q=32,D=-1;if(0<e.lowpass1){for(var F=999,h=0;31>=h;h++)l=h/31,l>= +e.lowpass2&&(q=Math.min(q,h)),e.lowpass1<l&&l<e.lowpass2&&(F=Math.min(F,h));e.lowpass1=999==F?(q-.75)/31:(F-.75)/31;e.lowpass2=q/31}0<e.highpass2&&e.highpass2<.75/31*.9&&(e.highpass1=0,e.highpass2=0,K.err.println("Warning: highpass filter disabled. highpass frequency too small\n"));if(0<e.highpass2){q=-1;for(h=0;31>=h;h++)l=h/31,l<=e.highpass1&&(D=Math.max(D,h)),e.highpass1<l&&l<e.highpass2&&(q=Math.max(q,h));e.highpass1=D/31;e.highpass2=-1==q?(D+.75)/31:(q+.75)/31}for(h=0;32>h;h++)l=h/31,D=e.highpass2> +e.highpass1?C((e.highpass2-l)/(e.highpass2-e.highpass1+1E-20)):1,l=e.lowpass2>e.lowpass1?C((l-e.lowpass1)/(e.lowpass2-e.lowpass1+1E-20)):1,e.amp_filter[h]=D*l;b.samplerate_index=B(a.out_samplerate,a);if(0>b.samplerate_index)return a.internal_flags=null,-1;if(a.VBR==M.vbr_off)if(a.free_format)b.bitrate_index=0;else{if(a.brate=t(a.brate,a.version,a.out_samplerate),b.bitrate_index=Q(a.brate,a.version,a.out_samplerate),0>=b.bitrate_index)return a.internal_flags=null,-1}else b.bitrate_index=1;a.analysis&& +(a.bWriteVbrTag=!1);null!=b.pinfo&&(a.bWriteVbrTag=!1);c.init_bit_stream_w(b);e=b.samplerate_index+3*a.version+6*(16E3>a.out_samplerate?1:0);for(h=0;h<d.SBMAX_l+1;h++)b.scalefac_band.l[h]=E.sfBandIndex[e].l[h];for(h=0;h<d.PSFB21+1;h++)l=(b.scalefac_band.l[22]-b.scalefac_band.l[21])/d.PSFB21,l=b.scalefac_band.l[21]+h*l,b.scalefac_band.psfb21[h]=l;b.scalefac_band.psfb21[d.PSFB21]=576;for(h=0;h<d.SBMAX_s+1;h++)b.scalefac_band.s[h]=E.sfBandIndex[e].s[h];for(h=0;h<d.PSFB12+1;h++)l=(b.scalefac_band.s[13]- +b.scalefac_band.s[12])/d.PSFB12,l=b.scalefac_band.s[12]+h*l,b.scalefac_band.psfb12[h]=l;b.scalefac_band.psfb12[d.PSFB12]=192;b.sideinfo_len=1==a.version?1==b.channels_out?21:36:1==b.channels_out?13:21;a.error_protection&&(b.sideinfo_len+=2);e=a.internal_flags;a.frameNum=0;a.write_id3tag_automatic&&v.id3tag_write_v2(a);e.bitrate_stereoMode_Hist=db([16,5]);e.bitrate_blockType_Hist=db([16,6]);e.PeakSample=0;a.bWriteVbrTag&&A.InitVbrTag(a);b.Class_ID=4294479419;for(e=0;19>e;e++)b.nsPsy.pefirbuf[e]=700* +b.mode_gr*b.channels_out;-1==a.ATHtype&&(a.ATHtype=4);switch(a.VBR){case M.vbr_mt:a.VBR=M.vbr_mtrh;case M.vbr_mtrh:null==a.useTemporal&&(a.useTemporal=!1);f.apply_preset(a,500-10*a.VBR_q,0);0>a.quality&&(a.quality=LAME_DEFAULT_QUALITY);5>a.quality&&(a.quality=0);5<a.quality&&(a.quality=5);b.PSY.mask_adjust=a.maskingadjust;b.PSY.mask_adjust_short=a.maskingadjust_short;b.sfb21_extra=a.experimentalY?!1:44E3<a.out_samplerate;b.iteration_loop=new VBRNewIterationLoop(z);break;case M.vbr_rh:f.apply_preset(a, +500-10*a.VBR_q,0);b.PSY.mask_adjust=a.maskingadjust;b.PSY.mask_adjust_short=a.maskingadjust_short;b.sfb21_extra=a.experimentalY?!1:44E3<a.out_samplerate;6<a.quality&&(a.quality=6);0>a.quality&&(a.quality=LAME_DEFAULT_QUALITY);b.iteration_loop=new VBROldIterationLoop(z);break;default:b.sfb21_extra=!1,0>a.quality&&(a.quality=LAME_DEFAULT_QUALITY),e=a.VBR,e==M.vbr_off&&(a.VBR_mean_bitrate_kbps=a.brate),f.apply_preset(a,a.VBR_mean_bitrate_kbps,0),a.VBR=e,b.PSY.mask_adjust=a.maskingadjust,b.PSY.mask_adjust_short= +a.maskingadjust_short,b.iteration_loop=e==M.vbr_off?new Mc(z):new ABRIterationLoop(z)}if(a.VBR!=M.vbr_off){b.VBR_min_bitrate=1;b.VBR_max_bitrate=14;16E3>a.out_samplerate&&(b.VBR_max_bitrate=8);if(0!=a.VBR_min_bitrate_kbps&&(a.VBR_min_bitrate_kbps=t(a.VBR_min_bitrate_kbps,a.version,a.out_samplerate),b.VBR_min_bitrate=Q(a.VBR_min_bitrate_kbps,a.version,a.out_samplerate),0>b.VBR_min_bitrate)||0!=a.VBR_max_bitrate_kbps&&(a.VBR_max_bitrate_kbps=t(a.VBR_max_bitrate_kbps,a.version,a.out_samplerate),b.VBR_max_bitrate= +Q(a.VBR_max_bitrate_kbps,a.version,a.out_samplerate),0>b.VBR_max_bitrate))return-1;a.VBR_min_bitrate_kbps=r.bitrate_table[a.version][b.VBR_min_bitrate];a.VBR_max_bitrate_kbps=r.bitrate_table[a.version][b.VBR_max_bitrate];a.VBR_mean_bitrate_kbps=Math.min(r.bitrate_table[a.version][b.VBR_max_bitrate],a.VBR_mean_bitrate_kbps);a.VBR_mean_bitrate_kbps=Math.max(r.bitrate_table[a.version][b.VBR_min_bitrate],a.VBR_mean_bitrate_kbps)}a.tune&&(b.PSY.mask_adjust+=a.tune_value_a,b.PSY.mask_adjust_short+=a.tune_value_a); +e=a.internal_flags;switch(a.quality){default:case 9:e.psymodel=0;e.noise_shaping=0;e.noise_shaping_amp=0;e.noise_shaping_stop=0;e.use_best_huffman=0;e.full_outer_loop=0;break;case 8:a.quality=7;case 7:e.psymodel=1;e.noise_shaping=0;e.noise_shaping_amp=0;e.noise_shaping_stop=0;e.use_best_huffman=0;e.full_outer_loop=0;break;case 6:e.psymodel=1;0==e.noise_shaping&&(e.noise_shaping=1);e.noise_shaping_amp=0;e.noise_shaping_stop=0;-1==e.subblock_gain&&(e.subblock_gain=1);e.use_best_huffman=0;e.full_outer_loop= +0;break;case 5:e.psymodel=1;0==e.noise_shaping&&(e.noise_shaping=1);e.noise_shaping_amp=0;e.noise_shaping_stop=0;-1==e.subblock_gain&&(e.subblock_gain=1);e.use_best_huffman=0;e.full_outer_loop=0;break;case 4:e.psymodel=1;0==e.noise_shaping&&(e.noise_shaping=1);e.noise_shaping_amp=0;e.noise_shaping_stop=0;-1==e.subblock_gain&&(e.subblock_gain=1);e.use_best_huffman=1;e.full_outer_loop=0;break;case 3:e.psymodel=1;0==e.noise_shaping&&(e.noise_shaping=1);e.noise_shaping_amp=1;e.noise_shaping_stop=1;-1== +e.subblock_gain&&(e.subblock_gain=1);e.use_best_huffman=1;e.full_outer_loop=0;break;case 2:e.psymodel=1;0==e.noise_shaping&&(e.noise_shaping=1);0==e.substep_shaping&&(e.substep_shaping=2);e.noise_shaping_amp=1;e.noise_shaping_stop=1;-1==e.subblock_gain&&(e.subblock_gain=1);e.use_best_huffman=1;e.full_outer_loop=0;break;case 1:e.psymodel=1;0==e.noise_shaping&&(e.noise_shaping=1);0==e.substep_shaping&&(e.substep_shaping=2);e.noise_shaping_amp=2;e.noise_shaping_stop=1;-1==e.subblock_gain&&(e.subblock_gain= +1);e.use_best_huffman=1;e.full_outer_loop=0;break;case 0:e.psymodel=1,0==e.noise_shaping&&(e.noise_shaping=1),0==e.substep_shaping&&(e.substep_shaping=2),e.noise_shaping_amp=2,e.noise_shaping_stop=1,-1==e.subblock_gain&&(e.subblock_gain=1),e.use_best_huffman=1,e.full_outer_loop=0}b.ATH.useAdjust=0>a.athaa_type?3:a.athaa_type;b.ATH.aaSensitivityP=Math.pow(10,a.athaa_sensitivity/-10);null==a.short_blocks&&(a.short_blocks=sa.short_block_allowed);a.short_blocks!=sa.short_block_allowed||a.mode!=ka.JOINT_STEREO&& +a.mode!=ka.STEREO||(a.short_blocks=sa.short_block_coupled);0>a.quant_comp&&(a.quant_comp=1);0>a.quant_comp_short&&(a.quant_comp_short=0);0>a.msfix&&(a.msfix=0);a.exp_nspsytune|=1;0>a.internal_flags.nsPsy.attackthre&&(a.internal_flags.nsPsy.attackthre=jc.NSATTACKTHRE);0>a.internal_flags.nsPsy.attackthre_s&&(a.internal_flags.nsPsy.attackthre_s=jc.NSATTACKTHRE_S);0>a.scale&&(a.scale=1);0>a.ATHtype&&(a.ATHtype=4);0>a.ATHcurve&&(a.ATHcurve=4);0>a.athaa_loudapprox&&(a.athaa_loudapprox=2);0>a.interChRatio&& +(a.interChRatio=0);null==a.useTemporal&&(a.useTemporal=!0);b.slot_lag=b.frac_SpF=0;a.VBR==M.vbr_off&&(b.slot_lag=b.frac_SpF=72E3*(a.version+1)*a.brate%a.out_samplerate|0);E.iteration_init(a);w.psymodel_init(a);return 0};this.lame_encode_flush=function(a,e,f,g){var h=a.internal_flags,k=vc([2,1152]),l=0,n,p,q=h.mf_samples_to_encode-d.POSTDELAY,r=b(a);if(1>h.mf_samples_to_encode)return 0;n=0;a.in_samplerate!=a.out_samplerate&&(q+=16*a.out_samplerate/a.in_samplerate);p=a.framesize-q%a.framesize;576>p&& +(p+=a.framesize);a.encoder_padding=p;for(p=(q+p)/a.framesize;0<p&&0<=l;){var t=r-h.mf_size,q=a.frameNum,t=t*a.in_samplerate,t=t/a.out_samplerate;1152<t&&(t=1152);1>t&&(t=1);l=g-n;0==g&&(l=0);l=this.lame_encode_buffer(a,k[0],k[1],t,e,f,l);f+=l;n+=l;p-=q!=a.frameNum?1:0}h.mf_samples_to_encode=0;if(0>l)return l;l=g-n;0==g&&(l=0);c.flush_bitstream(a);l=c.copy_buffer(h,e,f,l,1);if(0>l)return l;f+=l;n+=l;l=g-n;0==g&&(l=0);if(a.write_id3tag_automatic){v.id3tag_write_v1(a);l=c.copy_buffer(h,e,f,l,0);if(0> +l)return l;n+=l}return n};this.lame_encode_buffer=function(a,b,c,d,e,f,g){var h=a.internal_flags,k=[null,null];if(4294479419!=h.Class_ID)return-3;if(0==d)return 0;if(null==h.in_buffer_0||h.in_buffer_nsamples<d)h.in_buffer_0=H(d),h.in_buffer_1=H(d),h.in_buffer_nsamples=d;k[0]=h.in_buffer_0;k[1]=h.in_buffer_1;for(var n=0;n<d;n++)k[0][n]=b[n],1<h.channels_in&&(k[1][n]=c[n]);return l(a,k[0],k[1],d,e,f,g)}}function Uc(){this.setModules=function(d,k){}}function Vc(){this.setModules=function(d,k,q){}}function Wc(){} +function Xc(){this.setModules=function(d,k){}}function Ca(){this.sampleRate=this.channels=this.dataLen=this.dataOffset=0}function Ob(d){return d.charCodeAt(0)<<24|d.charCodeAt(1)<<16|d.charCodeAt(2)<<8|d.charCodeAt(3)}var Ia={fill:function(d,k,q,r){if(2==arguments.length)for(var B=0;B<d.length;B++)d[B]=arguments[1];else for(B=k;B<q;B++)d[B]=r}},K={arraycopy:function(d,k,q,r,B){for(B=k+B;k<B;)q[r++]=d[k++]}},X={SQRT2:1.4142135623730951,FAST_LOG10:function(d){return Math.log10(d)},FAST_LOG10_X:function(d, +k){return Math.log10(d)*k}};sa.short_block_allowed=new sa(0);sa.short_block_coupled=new sa(1);sa.short_block_dispensed=new sa(2);sa.short_block_forced=new sa(3);var vb={MAX_VALUE:3.4028235E38};M.vbr_off=new M(0);M.vbr_mt=new M(1);M.vbr_rh=new M(2);M.vbr_abr=new M(3);M.vbr_mtrh=new M(4);M.vbr_default=M.vbr_mtrh;ka.STEREO=new ka(0);ka.JOINT_STEREO=new ka(1);ka.DUAL_CHANNEL=new ka(2);ka.MONO=new ka(3);ka.NOT_SET=new ka(4);O.STEPS_per_dB=100;O.MAX_dB=120;O.GAIN_NOT_ENOUGH_SAMPLES=-24601;O.GAIN_ANALYSIS_ERROR= +0;O.GAIN_ANALYSIS_OK=1;O.INIT_GAIN_ANALYSIS_ERROR=0;O.INIT_GAIN_ANALYSIS_OK=1;O.YULE_ORDER=10;O.MAX_ORDER=O.YULE_ORDER;O.MAX_SAMP_FREQ=48E3;O.RMS_WINDOW_TIME_NUMERATOR=1;O.RMS_WINDOW_TIME_DENOMINATOR=20;O.MAX_SAMPLES_PER_WINDOW=O.MAX_SAMP_FREQ*O.RMS_WINDOW_TIME_NUMERATOR/O.RMS_WINDOW_TIME_DENOMINATOR+1;ua.EQ=function(d,k){return Math.abs(d)>Math.abs(k)?Math.abs(d-k)<=1E-6*Math.abs(d):Math.abs(d-k)<=1E-6*Math.abs(k)};ua.NEQ=function(d,k){return!ua.EQ(d,k)};ub.NUMTOCENTRIES=100;ub.MAXFRAMESIZE=2880; +var r={t1HB:[1,1,1,0],t2HB:[1,2,1,3,1,1,3,2,0],t3HB:[3,2,1,1,1,1,3,2,0],t5HB:[1,2,6,5,3,1,4,4,7,5,7,1,6,1,1,0],t6HB:[7,3,5,1,6,2,3,2,5,4,4,1,3,3,2,0],t7HB:[1,2,10,19,16,10,3,3,7,10,5,3,11,4,13,17,8,4,12,11,18,15,11,2,7,6,9,14,3,1,6,4,5,3,2,0],t8HB:[3,4,6,18,12,5,5,1,2,16,9,3,7,3,5,14,7,3,19,17,15,13,10,4,13,5,8,11,5,1,12,4,4,1,1,0],t9HB:[7,5,9,14,15,7,6,4,5,5,6,7,7,6,8,8,8,5,15,6,9,10,5,1,11,7,9,6,4,1,14,4,6,2,6,0],t10HB:[1,2,10,23,35,30,12,17,3,3,8,12,18,21,12,7,11,9,15,21,32,40,19,6,14,13,22,34, +46,23,18,7,20,19,33,47,27,22,9,3,31,22,41,26,21,20,5,3,14,13,10,11,16,6,5,1,9,8,7,8,4,4,2,0],t11HB:[3,4,10,24,34,33,21,15,5,3,4,10,32,17,11,10,11,7,13,18,30,31,20,5,25,11,19,59,27,18,12,5,35,33,31,58,30,16,7,5,28,26,32,19,17,15,8,14,14,12,9,13,14,9,4,1,11,4,6,6,6,3,2,0],t12HB:[9,6,16,33,41,39,38,26,7,5,6,9,23,16,26,11,17,7,11,14,21,30,10,7,17,10,15,12,18,28,14,5,32,13,22,19,18,16,9,5,40,17,31,29,17,13,4,2,27,12,11,15,10,7,4,1,27,12,8,12,6,3,1,0],t13HB:[1,5,14,21,34,51,46,71,42,52,68,52,67,44,43,19, +3,4,12,19,31,26,44,33,31,24,32,24,31,35,22,14,15,13,23,36,59,49,77,65,29,40,30,40,27,33,42,16,22,20,37,61,56,79,73,64,43,76,56,37,26,31,25,14,35,16,60,57,97,75,114,91,54,73,55,41,48,53,23,24,58,27,50,96,76,70,93,84,77,58,79,29,74,49,41,17,47,45,78,74,115,94,90,79,69,83,71,50,59,38,36,15,72,34,56,95,92,85,91,90,86,73,77,65,51,44,43,42,43,20,30,44,55,78,72,87,78,61,46,54,37,30,20,16,53,25,41,37,44,59,54,81,66,76,57,54,37,18,39,11,35,33,31,57,42,82,72,80,47,58,55,21,22,26,38,22,53,25,23,38,70,60,51, +36,55,26,34,23,27,14,9,7,34,32,28,39,49,75,30,52,48,40,52,28,18,17,9,5,45,21,34,64,56,50,49,45,31,19,12,15,10,7,6,3,48,23,20,39,36,35,53,21,16,23,13,10,6,1,4,2,16,15,17,27,25,20,29,11,17,12,16,8,1,1,0,1],t15HB:[7,12,18,53,47,76,124,108,89,123,108,119,107,81,122,63,13,5,16,27,46,36,61,51,42,70,52,83,65,41,59,36,19,17,15,24,41,34,59,48,40,64,50,78,62,80,56,33,29,28,25,43,39,63,55,93,76,59,93,72,54,75,50,29,52,22,42,40,67,57,95,79,72,57,89,69,49,66,46,27,77,37,35,66,58,52,91,74,62,48,79,63,90,62,40, +38,125,32,60,56,50,92,78,65,55,87,71,51,73,51,70,30,109,53,49,94,88,75,66,122,91,73,56,42,64,44,21,25,90,43,41,77,73,63,56,92,77,66,47,67,48,53,36,20,71,34,67,60,58,49,88,76,67,106,71,54,38,39,23,15,109,53,51,47,90,82,58,57,48,72,57,41,23,27,62,9,86,42,40,37,70,64,52,43,70,55,42,25,29,18,11,11,118,68,30,55,50,46,74,65,49,39,24,16,22,13,14,7,91,44,39,38,34,63,52,45,31,52,28,19,14,8,9,3,123,60,58,53,47,43,32,22,37,24,17,12,15,10,2,1,71,37,34,30,28,20,17,26,21,16,10,6,8,6,2,0],t16HB:[1,5,14,44,74,63, +110,93,172,149,138,242,225,195,376,17,3,4,12,20,35,62,53,47,83,75,68,119,201,107,207,9,15,13,23,38,67,58,103,90,161,72,127,117,110,209,206,16,45,21,39,69,64,114,99,87,158,140,252,212,199,387,365,26,75,36,68,65,115,101,179,164,155,264,246,226,395,382,362,9,66,30,59,56,102,185,173,265,142,253,232,400,388,378,445,16,111,54,52,100,184,178,160,133,257,244,228,217,385,366,715,10,98,48,91,88,165,157,148,261,248,407,397,372,380,889,884,8,85,84,81,159,156,143,260,249,427,401,392,383,727,713,708,7,154,76,73, +141,131,256,245,426,406,394,384,735,359,710,352,11,139,129,67,125,247,233,229,219,393,743,737,720,885,882,439,4,243,120,118,115,227,223,396,746,742,736,721,712,706,223,436,6,202,224,222,218,216,389,386,381,364,888,443,707,440,437,1728,4,747,211,210,208,370,379,734,723,714,1735,883,877,876,3459,865,2,377,369,102,187,726,722,358,711,709,866,1734,871,3458,870,434,0,12,10,7,11,10,17,11,9,13,12,10,7,5,3,1,3],t24HB:[15,13,46,80,146,262,248,434,426,669,653,649,621,517,1032,88,14,12,21,38,71,130,122,216, +209,198,327,345,319,297,279,42,47,22,41,74,68,128,120,221,207,194,182,340,315,295,541,18,81,39,75,70,134,125,116,220,204,190,178,325,311,293,271,16,147,72,69,135,127,118,112,210,200,188,352,323,306,285,540,14,263,66,129,126,119,114,214,202,192,180,341,317,301,281,262,12,249,123,121,117,113,215,206,195,185,347,330,308,291,272,520,10,435,115,111,109,211,203,196,187,353,332,313,298,283,531,381,17,427,212,208,205,201,193,186,177,169,320,303,286,268,514,377,16,335,199,197,191,189,181,174,333,321,305,289, +275,521,379,371,11,668,184,183,179,175,344,331,314,304,290,277,530,383,373,366,10,652,346,171,168,164,318,309,299,287,276,263,513,375,368,362,6,648,322,316,312,307,302,292,284,269,261,512,376,370,364,359,4,620,300,296,294,288,282,273,266,515,380,374,369,365,361,357,2,1033,280,278,274,267,264,259,382,378,372,367,363,360,358,356,0,43,20,19,17,15,13,11,9,7,6,4,7,5,3,1,3],t32HB:[1,10,8,20,12,20,16,32,14,12,24,0,28,16,24,16],t33HB:[15,28,26,48,22,40,36,64,14,24,20,32,12,16,8,0],t1l:[1,4,3,5],t2l:[1,4, +7,4,5,7,6,7,8],t3l:[2,3,7,4,4,7,6,7,8],t5l:[1,4,7,8,4,5,8,9,7,8,9,10,8,8,9,10],t6l:[3,4,6,8,4,4,6,7,5,6,7,8,7,7,8,9],t7l:[1,4,7,9,9,10,4,6,8,9,9,10,7,7,9,10,10,11,8,9,10,11,11,11,8,9,10,11,11,12,9,10,11,12,12,12],t8l:[2,4,7,9,9,10,4,4,6,10,10,10,7,6,8,10,10,11,9,10,10,11,11,12,9,9,10,11,12,12,10,10,11,11,13,13],t9l:[3,4,6,7,9,10,4,5,6,7,8,10,5,6,7,8,9,10,7,7,8,9,9,10,8,8,9,9,10,11,9,9,10,10,11,11],t10l:[1,4,7,9,10,10,10,11,4,6,8,9,10,11,10,10,7,8,9,10,11,12,11,11,8,9,10,11,12,12,11,12,9,10,11,12, +12,12,12,12,10,11,12,12,13,13,12,13,9,10,11,12,12,12,13,13,10,10,11,12,12,13,13,13],t11l:[2,4,6,8,9,10,9,10,4,5,6,8,10,10,9,10,6,7,8,9,10,11,10,10,8,8,9,11,10,12,10,11,9,10,10,11,11,12,11,12,9,10,11,12,12,13,12,13,9,9,9,10,11,12,12,12,9,9,10,11,12,12,12,12],t12l:[4,4,6,8,9,10,10,10,4,5,6,7,9,9,10,10,6,6,7,8,9,10,9,10,7,7,8,8,9,10,10,10,8,8,9,9,10,10,10,11,9,9,10,10,10,11,10,11,9,9,9,10,10,11,11,12,10,10,10,11,11,11,11,12],t13l:[1,5,7,8,9,10,10,11,10,11,12,12,13,13,14,14,4,6,8,9,10,10,11,11,11,11, +12,12,13,14,14,14,7,8,9,10,11,11,12,12,11,12,12,13,13,14,15,15,8,9,10,11,11,12,12,12,12,13,13,13,13,14,15,15,9,9,11,11,12,12,13,13,12,13,13,14,14,15,15,16,10,10,11,12,12,12,13,13,13,13,14,13,15,15,16,16,10,11,12,12,13,13,13,13,13,14,14,14,15,15,16,16,11,11,12,13,13,13,14,14,14,14,15,15,15,16,18,18,10,10,11,12,12,13,13,14,14,14,14,15,15,16,17,17,11,11,12,12,13,13,13,15,14,15,15,16,16,16,18,17,11,12,12,13,13,14,14,15,14,15,16,15,16,17,18,19,12,12,12,13,14,14,14,14,15,15,15,16,17,17,17,18,12,13,13,14, +14,15,14,15,16,16,17,17,17,18,18,18,13,13,14,15,15,15,16,16,16,16,16,17,18,17,18,18,14,14,14,15,15,15,17,16,16,19,17,17,17,19,18,18,13,14,15,16,16,16,17,16,17,17,18,18,21,20,21,18],t15l:[3,5,6,8,8,9,10,10,10,11,11,12,12,12,13,14,5,5,7,8,9,9,10,10,10,11,11,12,12,12,13,13,6,7,7,8,9,9,10,10,10,11,11,12,12,13,13,13,7,8,8,9,9,10,10,11,11,11,12,12,12,13,13,13,8,8,9,9,10,10,11,11,11,11,12,12,12,13,13,13,9,9,9,10,10,10,11,11,11,11,12,12,13,13,13,14,10,9,10,10,10,11,11,11,11,12,12,12,13,13,14,14,10,10,10, +11,11,11,11,12,12,12,12,12,13,13,13,14,10,10,10,11,11,11,11,12,12,12,12,13,13,14,14,14,10,10,11,11,11,11,12,12,12,13,13,13,13,14,14,14,11,11,11,11,12,12,12,12,12,13,13,13,13,14,15,14,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,15,12,12,11,12,12,12,13,13,13,13,13,13,14,14,15,15,12,12,12,12,12,13,13,13,13,14,14,14,14,14,15,15,13,13,13,13,13,13,13,13,14,14,14,14,15,15,14,15,13,13,13,13,13,13,13,14,14,14,14,14,15,15,15,15],t16_5l:[1,5,7,9,10,10,11,11,12,12,12,13,13,13,14,11,4,6,8,9,10,11,11,11,12,12, +12,13,14,13,14,11,7,8,9,10,11,11,12,12,13,12,13,13,13,14,14,12,9,9,10,11,11,12,12,12,13,13,14,14,14,15,15,13,10,10,11,11,12,12,13,13,13,14,14,14,15,15,15,12,10,10,11,11,12,13,13,14,13,14,14,15,15,15,16,13,11,11,11,12,13,13,13,13,14,14,14,14,15,15,16,13,11,11,12,12,13,13,13,14,14,15,15,15,15,17,17,13,11,12,12,13,13,13,14,14,15,15,15,15,16,16,16,13,12,12,12,13,13,14,14,15,15,15,15,16,15,16,15,14,12,13,12,13,14,14,14,14,15,16,16,16,17,17,16,13,13,13,13,13,14,14,15,16,16,16,16,16,16,15,16,14,13,14,14, +14,14,15,15,15,15,17,16,16,16,16,18,14,15,14,14,14,15,15,16,16,16,18,17,17,17,19,17,14,14,15,13,14,16,16,15,16,16,17,18,17,19,17,16,14,11,11,11,12,12,13,13,13,14,14,14,14,14,14,14,12],t16l:[1,5,7,9,10,10,11,11,12,12,12,13,13,13,14,10,4,6,8,9,10,11,11,11,12,12,12,13,14,13,14,10,7,8,9,10,11,11,12,12,13,12,13,13,13,14,14,11,9,9,10,11,11,12,12,12,13,13,14,14,14,15,15,12,10,10,11,11,12,12,13,13,13,14,14,14,15,15,15,11,10,10,11,11,12,13,13,14,13,14,14,15,15,15,16,12,11,11,11,12,13,13,13,13,14,14,14,14, +15,15,16,12,11,11,12,12,13,13,13,14,14,15,15,15,15,17,17,12,11,12,12,13,13,13,14,14,15,15,15,15,16,16,16,12,12,12,12,13,13,14,14,15,15,15,15,16,15,16,15,13,12,13,12,13,14,14,14,14,15,16,16,16,17,17,16,12,13,13,13,13,14,14,15,16,16,16,16,16,16,15,16,13,13,14,14,14,14,15,15,15,15,17,16,16,16,16,18,13,15,14,14,14,15,15,16,16,16,18,17,17,17,19,17,13,14,15,13,14,16,16,15,16,16,17,18,17,19,17,16,13,10,10,10,11,11,12,12,12,13,13,13,13,13,13,13,10],t24l:[4,5,7,8,9,10,10,11,11,12,12,12,12,12,13,10,5,6,7,8, +9,10,10,11,11,11,12,12,12,12,12,10,7,7,8,9,9,10,10,11,11,11,11,12,12,12,13,9,8,8,9,9,10,10,10,11,11,11,11,12,12,12,12,9,9,9,9,10,10,10,10,11,11,11,12,12,12,12,13,9,10,9,10,10,10,10,11,11,11,11,12,12,12,12,12,9,10,10,10,10,10,11,11,11,11,12,12,12,12,12,13,9,11,10,10,10,11,11,11,11,12,12,12,12,12,13,13,10,11,11,11,11,11,11,11,11,11,12,12,12,12,13,13,10,11,11,11,11,11,11,11,12,12,12,12,12,13,13,13,10,12,11,11,11,11,12,12,12,12,12,12,13,13,13,13,10,12,12,11,11,11,12,12,12,12,12,12,13,13,13,13,10,12,12, +12,12,12,12,12,12,12,12,13,13,13,13,13,10,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,10,13,12,12,12,12,12,12,13,13,13,13,13,13,13,13,10,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,6],t32l:[1,5,5,7,5,8,7,9,5,7,7,9,7,9,9,10],t33l:[4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8]};r.ht=[new Q(0,0,null,null),new Q(2,0,r.t1HB,r.t1l),new Q(3,0,r.t2HB,r.t2l),new Q(3,0,r.t3HB,r.t3l),new Q(0,0,null,null),new Q(4,0,r.t5HB,r.t5l),new Q(4,0,r.t6HB,r.t6l),new Q(6,0,r.t7HB,r.t7l),new Q(6,0,r.t8HB,r.t8l),new Q(6,0,r.t9HB,r.t9l),new Q(8, +0,r.t10HB,r.t10l),new Q(8,0,r.t11HB,r.t11l),new Q(8,0,r.t12HB,r.t12l),new Q(16,0,r.t13HB,r.t13l),new Q(0,0,null,r.t16_5l),new Q(16,0,r.t15HB,r.t15l),new Q(1,1,r.t16HB,r.t16l),new Q(2,3,r.t16HB,r.t16l),new Q(3,7,r.t16HB,r.t16l),new Q(4,15,r.t16HB,r.t16l),new Q(6,63,r.t16HB,r.t16l),new Q(8,255,r.t16HB,r.t16l),new Q(10,1023,r.t16HB,r.t16l),new Q(13,8191,r.t16HB,r.t16l),new Q(4,15,r.t24HB,r.t24l),new Q(5,31,r.t24HB,r.t24l),new Q(6,63,r.t24HB,r.t24l),new Q(7,127,r.t24HB,r.t24l),new Q(8,255,r.t24HB,r.t24l), +new Q(9,511,r.t24HB,r.t24l),new Q(11,2047,r.t24HB,r.t24l),new Q(13,8191,r.t24HB,r.t24l),new Q(0,0,r.t32HB,r.t32l),new Q(0,0,r.t33HB,r.t33l)];r.largetbl=[65540,327685,458759,589832,655369,655370,720906,720907,786443,786444,786444,851980,851980,851980,917517,655370,262149,393222,524295,589832,655369,720906,720906,720907,786443,786443,786444,851980,917516,851980,917516,655370,458759,524295,589832,655369,720905,720906,786442,786443,851979,786443,851979,851980,851980,917516,917517,720905,589832,589832, +655369,720905,720906,786442,786442,786443,851979,851979,917515,917516,917516,983052,983052,786441,655369,655369,720905,720906,786442,786442,851978,851979,851979,917515,917516,917516,983052,983052,983053,720905,655370,655369,720906,720906,786442,851978,851979,917515,851979,917515,917516,983052,983052,983052,1048588,786441,720906,720906,720906,786442,851978,851979,851979,851979,917515,917516,917516,917516,983052,983052,1048589,786441,720907,720906,786442,786442,851979,851979,851979,917515,917516,983052, +983052,983052,983052,1114125,1114125,786442,720907,786443,786443,851979,851979,851979,917515,917515,983051,983052,983052,983052,1048588,1048589,1048589,786442,786443,786443,786443,851979,851979,917515,917515,983052,983052,983052,983052,1048588,983053,1048589,983053,851978,786444,851979,786443,851979,917515,917516,917516,917516,983052,1048588,1048588,1048589,1114125,1114125,1048589,786442,851980,851980,851979,851979,917515,917516,983052,1048588,1048588,1048588,1048588,1048589,1048589,983053,1048589, +851978,851980,917516,917516,917516,917516,983052,983052,983052,983052,1114124,1048589,1048589,1048589,1048589,1179661,851978,983052,917516,917516,917516,983052,983052,1048588,1048588,1048589,1179661,1114125,1114125,1114125,1245197,1114125,851978,917517,983052,851980,917516,1048588,1048588,983052,1048589,1048589,1114125,1179661,1114125,1245197,1114125,1048589,851978,655369,655369,655369,720905,720905,786441,786441,786441,851977,851977,851977,851978,851978,851978,851978,655366];r.table23=[65538,262147, +458759,262148,327684,458759,393222,458759,524296];r.table56=[65539,262148,458758,524296,262148,327684,524294,589831,458757,524294,589831,655368,524295,524295,589832,655369];r.bitrate_table=[[0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,-1],[0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,-1],[0,8,16,24,32,40,48,56,64,-1,-1,-1,-1,-1,-1,-1]];r.samplerate_table=[[22050,24E3,16E3,-1],[44100,48E3,32E3,-1],[11025,12E3,8E3,-1]];r.scfsi_band=[0,6,11,16,21];ma.Q_MAX=257;ma.Q_MAX2=116;ma.LARGE_BITS=1E5; +ma.IXMAX_VAL=8206;var na={};na.SFBMAX=3*d.SBMAX_s;d.ENCDELAY=576;d.POSTDELAY=1152;d.MDCTDELAY=48;d.FFTOFFSET=224+d.MDCTDELAY;d.DECDELAY=528;d.SBLIMIT=32;d.CBANDS=64;d.SBPSY_l=21;d.SBPSY_s=12;d.SBMAX_l=22;d.SBMAX_s=13;d.PSFB21=6;d.PSFB12=6;d.BLKSIZE=1024;d.HBLKSIZE=d.BLKSIZE/2+1;d.BLKSIZE_s=256;d.HBLKSIZE_s=d.BLKSIZE_s/2+1;d.NORM_TYPE=0;d.START_TYPE=1;d.SHORT_TYPE=2;d.STOP_TYPE=3;d.MPG_MD_LR_LR=0;d.MPG_MD_LR_I=1;d.MPG_MD_MS_LR=2;d.MPG_MD_MS_I=3;d.fircoef=[-.1039435,-.1892065,-.0432472*5,-.155915,3.898045E-17, +.0467745*5,.50455,.756825,.187098*5];da.MFSIZE=3456+d.ENCDELAY-d.MDCTDELAY;da.MAX_HEADER_BUF=256;da.MAX_BITS_PER_CHANNEL=4095;da.MAX_BITS_PER_GRANULE=7680;da.BPC=320;Ca.RIFF=Ob("RIFF");Ca.WAVE=Ob("WAVE");Ca.fmt_=Ob("fmt ");Ca.data=Ob("data");Ca.readHeader=function(d){var k=new Ca,q=d.getUint32(0,!1);if(Ca.RIFF==q&&(d.getUint32(4,!0),Ca.WAVE==d.getUint32(8,!1)&&Ca.fmt_==d.getUint32(12,!1))){var r=d.getUint32(16,!0),B=20;switch(r){case 16:case 18:k.channels=d.getUint16(B+2,!0);k.sampleRate=d.getUint32(B+ +4,!0);break;default:throw"extended fmt chunk not implemented";}for(var B=B+r,r=Ca.data,t=0;r!=q;){q=d.getUint32(B,!1);t=d.getUint32(B+4,!0);if(r==q)break;B+=t+8}k.dataLen=t;k.dataOffset=B+8;return k}};na.SFBMAX=3*d.SBMAX_s;this.Mp3Encoder=function(d,k,q){3!=arguments.length&&(console.error("WARN: Mp3Encoder(channels, samplerate, kbps) not specified"),d=1,k=44100,q=128);var r=new V,B=new Uc,t=new O,H=new ua,g=new Gc,b=new ma,l=new Oc,a=new ub,h=new Fc,D=new Xc,e=new Hc,n=new tb,c=new Vc,f=new Wc;r.setModules(t, +H,g,b,l,a,h,D,f);H.setModules(t,f,h,a);D.setModules(H,h);g.setModules(r);l.setModules(H,e,b,n);b.setModules(n,e,r.enc.psy);e.setModules(H);n.setModules(b);a.setModules(r,H,h);B.setModules(c,f);c.setModules(h,D,g);var E=r.lame_init();E.num_channels=d;E.in_samplerate=k;E.brate=q;E.mode=ka.STEREO;E.quality=3;E.bWriteVbrTag=!1;E.disable_reservoir=!0;E.write_id3tag_automatic=!1;r.lame_init_params(E);var z=1152,w=0|1.25*z+7200,A=new Int8Array(w);this.encodeBuffer=function(a,b){1==d&&(b=a);a.length>z&&(z= +a.length,w=0|1.25*z+7200,A=new Int8Array(w));var c=r.lame_encode_buffer(E,a,b,a.length,A,0,w);return new Int8Array(A.subarray(0,c))};this.flush=function(){var a=r.lame_encode_flush(E,A,0,w);return new Int8Array(A.subarray(0,a))}};this.WavHeader=Ca}; diff --git a/form/src/assets/libs/audio-recorder/recorder.js b/form/src/assets/libs/audio-recorder/recorder.js new file mode 100644 index 0000000..fba7241 --- /dev/null +++ b/form/src/assets/libs/audio-recorder/recorder.js @@ -0,0 +1,141 @@ +(function (exports) { + //公共方法 + var Util = { + //åˆå§‹åŒ– + init: function () { + navigator.getUserMedia = navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia; + + window.AudioContext = window.AudioContext || + window.webkitAudioContext; + }, + //日志 + log: function () { + console.log.apply(console, arguments); + } + }; + //æž„é€ å‡½æ•° + var Recorder = function (config) { + + var _this = this; + config = config || {}; //åˆå§‹åŒ–é…置对象 + config.sampleRate = config.sampleRate || 44100; //é‡‡æ ·é¢‘çŽ‡ï¼Œé»˜è®¤ä¸º44100Hz(æ ‡å‡†MP3é‡‡æ ·çŽ‡) + config.bitRate = config.bitRate || 128; //比特率,默认为128kbps(æ ‡å‡†MP3è´¨é‡) + + Util.init(); + + if (navigator.getUserMedia) { + navigator.getUserMedia({ + audio: true //é…置对象 + }, + function (stream) { //æˆåŠŸå›žè°ƒ + var context = new AudioContext(), + microphone = context.createMediaStreamSource(stream), //媒体æµéŸ³é¢‘æº + processor = context.createScriptProcessor(16384, 1, 1), //js音频处ç†å™¨ + successCallback, errorCallback; + + config.sampleRate = context.sampleRate; + + processor.onaudioprocess = function (event) { + //监å¬éŸ³é¢‘录制过程 + var array = event.inputBuffer.getChannelData(0); + realTimeWorker.postMessage({cmd: 'encode', buf: array}); + }; + + var realTimeWorker = new Worker('assets/libs/audio-recorder/worker.js'); //å¼€å¯åŽå°çº¿ç¨‹ + _this.worker = realTimeWorker; + realTimeWorker.onmessage = function (e) { //主线程监å¬åŽå°çº¿ç¨‹ï¼Œå®žæ—¶é€šä¿¡ + switch (e.data.cmd) { + case 'init': + Util.log('åˆå§‹åŒ–æˆåŠŸ'); + if (config.success) { + config.success(); + } + break; + case 'end': + if (successCallback) { + var blob = new Blob(e.data.buf, {type: 'audio/mp3'}); + successCallback(blob); + Util.log('MP3大å°ï¼š' + blob.size + '%cB', 'color:#0000EE'); + } + break; + case 'error': + Util.log('错误信æ¯ï¼š' + e.data.error); + if (errorCallback) { + errorCallback(e.data.error); + } + break; + default: + Util.log('未知信æ¯ï¼š' + e.data); + } + }; + //接å£åˆ—表 + //开始录音 + _this.start = function () { + if (processor && microphone) { + microphone.connect(processor); + processor.connect(context.destination); + Util.log('开始录音'); + } + }; + //结æŸå½•音 + _this.stop = function () { + if (processor && microphone) { + microphone.disconnect(); + processor.disconnect(); + Util.log('录音结æŸ'); + } + }; + //获å–blobæ ¼å¼å½•音文件 + _this.getBlob = function (onSuccess, onError) { + successCallback = onSuccess; + errorCallback = onError; + realTimeWorker.postMessage({cmd: 'finish'}); + }; + + realTimeWorker.postMessage({ + cmd: 'init', + config: { + sampleRate: config.sampleRate, + bitRate: config.bitRate + } + }); + }, + function (error) { //失败回调 + var msg; + switch (error.code || error.name) { + case 'PermissionDeniedError': + case 'PERMISSION_DENIED': + case 'NotAllowedError': + msg = '用户拒ç»è®¿é—®éº¦å…‹é£Ž'; + break; + case 'NOT_SUPPORTED_ERROR': + case 'NotSupportedError': + msg = 'æµè§ˆå™¨ä¸æ”¯æŒéº¦å…‹é£Ž'; + break; + case 'MANDATORY_UNSATISFIED_ERROR': + case 'MandatoryUnsatisfiedError': + msg = '找ä¸åˆ°éº¦å…‹é£Žè®¾å¤‡'; + break; + default: + msg = 'æ— æ³•æ‰“å¼€éº¦å…‹é£Žï¼Œå¼‚å¸¸ä¿¡æ¯:' + (error.code || error.name); + break; + } + Util.log(msg); + if (config.error) { + config.error(msg); + } + }); + } else { + Util.log('当剿µè§ˆå™¨ä¸æ”¯æŒå½•音功能'); + if (config.fix) { + config.fix('当剿µè§ˆå™¨ä¸æ”¯æŒå½•音功能'); + } + } + + }; + //æ¨¡å—æŽ¥å£ + exports.Recorder = Recorder; +})(window); diff --git a/form/src/assets/libs/audio-recorder/worker.js b/form/src/assets/libs/audio-recorder/worker.js new file mode 100644 index 0000000..41e7c93 --- /dev/null +++ b/form/src/assets/libs/audio-recorder/worker.js @@ -0,0 +1,108 @@ +(function () { + 'use strict'; + if (!importScripts) { + var importScripts = (function (globalEval) { + var xhr = new XMLHttpRequest; + return function importScripts() { + var + args = Array.prototype.slice.call(arguments) + , len = args.length + , i = 0 + , meta + , data + , content + ; + for (; i < len; i++) { + if (args[i].substr(0, 5).toLowerCase() === "data:") { + data = args[i]; + content = data.indexOf(","); + meta = data.substr(5, content).toLowerCase(); + data = decodeURIComponent(data.substr(content + 1)); + if (/;\s*base64\s*[;,]/.test(meta)) { + data = atob(data); + } + if (/;\s*charset=[uU][tT][fF]-?8\s*[;,]/.test(meta)) { + data = decodeURIComponent(escape(data)); + } + } else { + xhr.open("GET", args[i], false); + xhr.send(null); + data = xhr.responseText; + } + globalEval(data); + } + }; + }(eval)); + } + + + importScripts('assets/libs/audio-recorder/lame.min.js'); + + var mp3Encoder, maxSamples = 1152, samplesMono, lame, config, dataBuffer; + + var clearBuffer = function () { + dataBuffer = []; + }; + + var appendToBuffer = function (mp3Buf) { + dataBuffer.push(new Int8Array(mp3Buf)); + }; + + var init = function (prefConfig) { + config = prefConfig || {}; + lame = new lamejs(); + mp3Encoder = new lame.Mp3Encoder(1, config.sampleRate || 44100, config.bitRate || 128); + clearBuffer(); + self.postMessage({ + cmd: 'init' + }); + }; + + var floatTo16BitPCM = function (input, output) { + for (var i = 0; i < input.length; i++) { + var s = Math.max(-1, Math.min(1, input[i])); + output[i] = (s < 0 ? s * 0x8000 : s * 0x7FFF); + } + }; + + var convertBuffer = function (arrayBuffer) { + var data = new Float32Array(arrayBuffer); + var out = new Int16Array(arrayBuffer.length); + floatTo16BitPCM(data, out); + return out; + }; + + var encode = function (arrayBuffer) { + samplesMono = convertBuffer(arrayBuffer); + var remaining = samplesMono.length; + for (var i = 0; remaining >= 0; i += maxSamples) { + var left = samplesMono.subarray(i, i + maxSamples); + var mp3buf = mp3Encoder.encodeBuffer(left); + appendToBuffer(mp3buf); + remaining -= maxSamples; + } + }; + + var finish = function () { + appendToBuffer(mp3Encoder.flush()); + self.postMessage({ + cmd: 'end', + buf: dataBuffer + }); + clearBuffer(); + }; + + self.onmessage = function (e) { + switch (e.data.cmd) { + case 'init': + init(e.data.config); + break; + case 'encode': + encode(e.data.buf); + break; + case 'finish': + finish(); + break; + } + }; +})(); diff --git a/form/src/assets/libs/service-worker/cache-service.js b/form/src/assets/libs/service-worker/cache-service.js new file mode 100644 index 0000000..d9111ae --- /dev/null +++ b/form/src/assets/libs/service-worker/cache-service.js @@ -0,0 +1,535 @@ +/* + Copyright 2014 Google Inc. All Rights Reserved. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +// While overkill for this specific sample in which there is only one cache, +// this is one best practice that can be followed in general to keep track of +// multiple caches used by a given service worker, and keep them all versioned. +// It maps a shorthand identifier for a cache to a specific, versioned cache name. + +// Note that since global state is discarded in between service worker restarts, these +// variables will be reinitialized each time the service worker handles an event, and you +// should not attempt to change their values inside an event handler. (Treat them as constants.) + +// If at any point you want to force pages that use this service worker to start using a fresh +// cache, then increment the CACHE_VERSION value. It will kick off the service worker update +// flow and the old cache(s) will be purged as part of the activate event handler when the +// updated service worker is activated. +var CACHE_SID = 0; +var CACHE_VER = ''; +var isPlayerPage = false; +// var CURRENT_CACHES = {}; +// var CURRENT_CACHES = null; + +async function progressDownloader(urlOrRequest, port, sid) { + let url = urlOrRequest; + let response = await fetch(url); + if (urlOrRequest instanceof Request) { + url = urlOrRequest.url; + } + let isBin = false; + if (url.endsWith('.mp4') + || url.endsWith('.mp3') + || url.endsWith('.jpg') + || url.endsWith('.png')){ + isBin = true; + } + + const reader = response.body.getReader(); + const contentLength = +response.headers.get('Content-Length'); + port.postMessage({ + len: contentLength, + status: 'init', + sid + }); + let receivedLength = 0; + let mb = 0; + let timeS = new Date().getTime(); + let timeD = 0; + let speed = 0; + let chunks = []; // array of received binary chunks (comprises the body) + while(true) { + const {done, value} = await reader.read(); + if (done) { + break; + } + chunks.push(value); + receivedLength += value.length; + /*mb += value.length; + if(mb > 1000 * 1000) { + timeD = new Date().getTime() - timeS; + // timeD = timeD /1000; + speed = mb / timeD; + mb = 0; + timeS = new Date().getTime(); + }*/ + // console.log(`Received ${receivedLength} of ${contentLength}`) + // cb && cb(receivedLength , contentLength) + port.postMessage({ + loaded: value.length, + status: 'downloading', + sid + }); + } + + if (isBin) { + return new Blob(chunks); + } else { + let chunksAll = new Uint8Array(receivedLength); + let position = 0; + for(let chunk of chunks) { + chunksAll.set(chunk, position); + position += chunk.length; + } + return chunksAll; //new TextDecoder("utf-8").decode(chunksAll); + } + +} +self.addEventListener('install', function(event) { + event.waitUntil(self.skipWaiting()); // Activate worker immediately +}); + +self.addEventListener('activate', function(event) { + event.waitUntil(self.clients.claim({ + includeUncontrolled: true + }).then(function() { + // After the activation and claiming is complete, send a message to each of the controlled + // pages letting it know that it's active. + // This will trigger navigator.serviceWorker.onmessage in each client. + return self.clients.matchAll().then(function(clients) { + return Promise.all(clients.map(function(client) { + // return client.postMessage('The service worker has activated and ' + + // 'taken control.'); + return client.postMessage({ + name: 'initOk', + }); + + })); + }); + })); // Become available to all pages +}); +/* +self.addEventListener('activate', function(event) { + // Delete all caches that aren't named in CURRENT_CACHES. + // While there is only one cache in this example, the same logic will handle the case where + // there are multiple versioned caches. + // var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function(key) { + // return CURRENT_CACHES[key]; + // }); + + event.waitUntil( + caches.keys().then(function(cacheNames) { + // return Promise.all( + // cacheNames.map(function(cacheName) { + // if (expectedCacheNames.indexOf(cacheName) === -1) { + // // If this cache name isn't present in the array of "expected" cache names, then delete it. + // console.log('Deleting out of date cache:', cacheName); + // return caches.delete(cacheName); + // } + // }) + // ); + }).then(function() { + return clients.claim(); + }).then(function() { + // After the activation and claiming is complete, send a message to each of the controlled + // pages letting it know that it's active. + // This will trigger navigator.serviceWorker.onmessage in each client. + return self.clients.matchAll().then(function(clients) { + return Promise.all(clients.map(function(client) { + return client.postMessage('The service worker has activated and ' + + 'taken control.'); + })); + }); + }) + ); +});*/ + +self.addEventListener('message', function(event) { + // console.log('Handling message event:', event); + if (event.data.command === 'remove') { + if (!event.data.key) { + return; + } + caches.delete(event.data.key) + /*caches.keys().then(function(cacheNames) { + console.log('clear', cacheNames); + // return caches.delete(event.data.ver); + // CACHE_VER = event.data.newVer; + // CACHE_SID = event.data.sid; + if (!event.data.key) { + return; + } + return caches.delete(event.data.key); + return Promise.all( + cacheNames.map(function(cacheName) { + if ( cache_ver === cacheName) { + // If this cache name isn't present in the array of "expected" cache names, then delete it. + console.log('Deleting out of date cache:', cacheName); + // localStorage.removeItem('item-cache-'+event.data.sid); + // self.clients.matchAll().then(function(clients) { + // clients.forEach(function(client) { + // client.postMessage({ + // + // }); + // }); + // }); + console.log('delete', cacheName) + return caches.delete(cacheName); + } + }) + ); + })*/ + /*.then(function() { + return clients.claim(); + })*/ + /*.then(function() { + // After the activation and claiming is complete, send a message to each of the controlled + // pages letting it know that it's active. + // This will trigger navigator.serviceWorker.onmessage in each client. + return self.clients.matchAll().then(function(clients) { + return Promise.all(clients.map(function(client) { + return client.postMessage('The service worker has activated and ' + + 'taken control.'); + })); + }); + })*/ + .then(function() { + console.log('delete finished') + event.ports[0].postMessage({ + error: null + }); + }); + return; + } + if (event.data.command === 'clearAll') { + event.waitUntil( + caches.keys().then(function(cacheNames) { + return Promise.all( + cacheNames.map(function(cacheName) { + return caches.delete(cacheName); + }) + ); + }).then(function() { + event.ports[0].postMessage({ + error: null + }); + }).catch(err => { + event.ports[0].postMessage({ + error: err, + }); + }) + ); + return; + } + if (event.data.command === 'listCachedCoursewares') { + var cacheData = {} + // caches.open('item-cache-c965d3a0630911e994fa058136a96bb1-1556518161000').then(r=>{console.log(r.keys().then(items=>console.log(items[0])))}) + caches.keys().then((cacheNames) => { + cacheNames.map((cacheName) => { + if (cacheName.indexOf('item-cache') > -1) { + var size = 0; + caches.open(cacheName).then((cache) => { + console.log(cacheName) + cache.keys().then((requests) => { + console.log(requests[0]) + for(var req of requests) { + console.log(req) + cache.match(req.url).then(resp => { + console.log(resp.headers.entries()) + }) + // cache.match(req.url).then((resp) => { + // console.log(req.url, resp.length) + // size += parseInt(resp.headers['Content-Length']) + // }).catch(err => { + // console.log(err) + // }); + } + }).then(() => { + cacheData.cacheName = size; + }) + }); + + } + }); + }).then(function(result) { + // event.ports[0].postMessage({ + // error: null, + // urls: urls + // }); + }); + return; + } + + // var key = 'item-cache-' + event.data.sid + '-'+ event.data.ver; + var key = event.data.key; + var p = caches.open(key).then(function(cache) { + // throw {name: 'QuotaExceededError'} + switch (event.data.command) { + // This command returns a list of the URLs corresponding to the Request objects + // that serve as keys for the current cache. + case 'keys': + return cache.keys().then(function(requests) { + var urls = requests.map(function(request) { + return request.url; + }); + + return urls.sort(); + }).then(function(urls) { + // event.ports[0] corresponds to the MessagePort that was transferred as part of the controlled page's + // call to controller.postMessage(). Therefore, event.ports[0].postMessage() will trigger the onmessage + // handler from the controlled page. + // It's up to you how to structure the messages that you send back; this is just one example. + event.ports[0].postMessage({ + error: null, + urls: urls + }); + }); + + // This command adds a new request/response pair to the cache. + case 'add': + // If event.data.url isn't a valid URL, new Request() will throw a TypeError which will be handled + // by the outer .catch(). + // Hardcode {mode: 'no-cors} since the default for new Requests constructed from strings is to require + // CORS, and we don't have any way of knowing whether an arbitrary URL that a user entered supports CORS. + var request = new Request(event.data.url, {mode: 'cors', cache: 'reload'}); // {mode: 'no-cors'} + // console.log('start', event.data.url); + // return fetch(request) + // .then(function(res){ + // return res.arrayBuffer(); + // }) + const startTime = new Date().getTime(); + let len = 0; + return progressDownloader(request, event.ports[0], event.data.sid).then((ab) => { + var cl = ab.size ? ab.size : ab.byteLength; + len = cl; + return cache.put(event.data.url, new Response(ab, { + // url: event.data.url, + // type: 'cors', + status: 200, + statusText: 'OK', + headers: [ + ['Content-Length', cl+''], + ] + })); + }).then(function(r) { + event.ports[0].postMessage({ + error: null, + status: 'finished', + len: len, + time: new Date().getTime() - startTime + }); + }); + + // This command removes a request/response pair from the cache (assuming it exists). + case 'delete': + return cache.delete(event.data.url).then(function(success) { + event.ports[0].postMessage({ + error: success ? null : 'Item was not found in the cache.' + }); + }); + + default: + // This will be handled by the outer .catch(). + throw Error('Unknown command: ' + event.data.command); + } + }).catch(function(error) { + // If the promise rejects, handle it by returning a standardized error message to the controlled page. + console.log('Message handling failed:', event.data.url, error); + // if (error.name == 'QuotaExceededError') { + event.ports[0].postMessage({ + //error: {name: 'QuotaExceededError'} + error: {name: error.name, message: error.message}, + status: 'error' + }); + // } + }); + + // Beginning in Chrome 51, event is an ExtendableMessageEvent, which supports + // the waitUntil() method for extending the lifetime of the event handler + // until the promise is resolved. + if ('waitUntil' in event) { + event.waitUntil(p); + } + + // Without support for waitUntil(), there's a chance that if the promise chain + // takes "too long" to execute, the service worker might be automatically + // stopped before it's complete. +}); + + +self.addEventListener('fetch', function(event) { + + // console.log('Handling fetch event for', event.request.method, event.request.url); + // if (event.request.method !== 'GET' || !CACHE_SID || !CACHE_VER) { + // event.respondWith(function(){ + // return fetch(request).then(networkResponse => { + // return networkResponse; + // }).catch(_ => { + // console.error('direct Fetching failed:', error); + // + // throw error; + // }) + // }); + // + // return; + // } + + /*if (!CACHE_SID || !CACHE_VER) { + event.request.mode = 'no-cors'; + return fetch(event.request).then(function(response) { + // console.log('Response from network is:', response); + console.log(999) + return response; + }).catch(function(error) { + // This catch() will handle exceptions thrown from the fetch() operation. + // Note that a HTTP error response (e.g. 404) will NOT trigger an exception. + // It will return a normal response object that has the appropriate error code set. + console.error('Fetching failed 9:', error); + + throw error; + }); + }*/ + // var isNormReq = !CACHE_SID || !CACHE_VER; + // var key = 'item-cache-' + CACHE_SID + '-'+ CACHE_VER; + if (event.request.method == 'GET' ) { + if (event.request.headers.get('range')) { + var pos = + Number(/^bytes\=(\d+)\-$/g.exec(event.request.headers.get('range'))[1]); + // console.log('Range request for', event.request.url, + // ', starting position:', pos); + event.respondWith( + caches.match(event.request.url, { + ignoreSearch: true, + ignoreVary: true + }).then(function(response) { + if (response) { + console.log('Found response in cache:', event.request.url); + return response.arrayBuffer().then(ab => { + return new Response( + ab.slice(pos), + { + status: 206, + statusText: 'Partial Content', + headers: [ + ['Content-Length', ab.byteLength+''], + ['Content-Range', 'bytes ' + pos + '-' + + (ab.byteLength - 1) + '/' + ab.byteLength]] + }); + }); + + // return response; + } + // event.request.mode = 'cors'; + // event.request.cache = 'reload'; + var request = new Request(event.request.url, + { + method: event.request.method, + mode: 'cors', + cache: 'reload', + headers: event.request.headers + }); + return fetch(request).then(function(response) { + console.log('Response from network is:', event.request.url); + return response; + })/*.then(res => { + return res.arrayBuffer(); + }).then(ab => { + return new Response( + ab.slice(pos), + { + status: 206, + statusText: 'Partial Content', + headers: [ + ['Content-Length', ab.byteLength+''], + ['Content-Range', 'bytes ' + pos + '-' + + (ab.byteLength - 1) + '/' + (pos + ab.byteLength)]] + }); + })*/ + }) + /*caches.open(key) + .then(function(cache) { + return cache.match(event.request.url); + }).then(function(res) { + if (!res) { + return fetch(event.request) + .then(res => { + return res.arrayBuffer(); + }); + } + return res.arrayBuffer(); + }).then(function(ab) { + return new Response( + ab.slice(pos), + { + status: 206, + statusText: 'Partial Content', + headers: [ + ['Content-Length', ab.byteLength+''], + ['Content-Range', 'bytes ' + pos + '-' + + (ab.byteLength - 1) + '/' + ab.byteLength]] + }); + })*/ + ); + } else { + // console.log('Non-range request for', event.request.url); + event.respondWith( + // caches.match() will look for a cache entry in all of the caches available to the service worker. + // It's an alternative to first opening a specific named cache and then matching on that. + caches.match(event.request, { + ignoreSearch: true, + ignoreVary: true + }).then(function(response) { + if (response) { + // console.log('%c Response in cache:', 'color:DodgerBlue;', response); + return response; + } + + // event.request will always have the proper mode set ('cors, 'no-cors', etc.) so we don't + // have to hardcode 'no-cors' like we do when fetch()ing in the install handler. + // event.request.mode = 'cors'; + // cache: 'reload' + if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') { + return; + } + // console.log('No response found in cache.', event.request.url); + return fetch(event.request).then(function(response) { + // console.log('%c Response from network is:', 'color:#bada55', response); + + return response; + }).catch(function(error) { + // This catch() will handle exceptions thrown from the fetch() operation. + // Note that a HTTP error response (e.g. 404) will NOT trigger an exception. + // It will return a normal response object that has the appropriate error code set. + console.error('Fetching failed:', error); + + // throw error; + }); + }) + ); + } + } else { + event.respondWith( + fetch(event.request).then(function(response) { + // console.log('not get from network:', response); + // console.log(888) + return response; + }).catch(function(error) { + // This catch() will handle exceptions thrown from the fetch() operation. + // Note that a HTTP error response (e.g. 404) will NOT trigger an exception. + // It will return a normal response object that has the appropriate error code set. + console.error('Fetching failed 8:', error); + throw error; + }) + ); + } +}); + diff --git a/form/src/assets/libs/video-js-7.0.0/video-js.css b/form/src/assets/libs/video-js-7.0.0/video-js.css new file mode 100644 index 0000000..aff41ca --- /dev/null +++ b/form/src/assets/libs/video-js-7.0.0/video-js.css @@ -0,0 +1,1699 @@ +.video-js .vjs-big-play-button .vjs-icon-placeholder:before, .vjs-button > .vjs-icon-placeholder:before, .video-js .vjs-modal-dialog, .vjs-modal-dialog .vjs-modal-dialog-content { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.video-js .vjs-big-play-button .vjs-icon-placeholder:before, .vjs-button > .vjs-icon-placeholder:before { + text-align: center; +} + +@font-face { + font-family: VideoJS; + src: url(data:application/font-woff;charset=utf-8;base64,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) format("woff"); + font-weight: normal; + font-style: normal; +} + +.vjs-icon-play, .video-js .vjs-big-play-button .vjs-icon-placeholder:before, .video-js .vjs-play-control .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-play:before, .video-js .vjs-big-play-button .vjs-icon-placeholder:before, .video-js .vjs-play-control .vjs-icon-placeholder:before { + content: "\f101"; +} + +.vjs-icon-play-circle { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-play-circle:before { + content: "\f102"; +} + +.vjs-icon-pause, .video-js .vjs-play-control.vjs-playing .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-pause:before, .video-js .vjs-play-control.vjs-playing .vjs-icon-placeholder:before { + content: "\f103"; +} + +.vjs-icon-volume-mute, .video-js .vjs-mute-control.vjs-vol-0 .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-volume-mute:before, .video-js .vjs-mute-control.vjs-vol-0 .vjs-icon-placeholder:before { + content: "\f104"; +} + +.vjs-icon-volume-low, .video-js .vjs-mute-control.vjs-vol-1 .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-volume-low:before, .video-js .vjs-mute-control.vjs-vol-1 .vjs-icon-placeholder:before { + content: "\f105"; +} + +.vjs-icon-volume-mid, .video-js .vjs-mute-control.vjs-vol-2 .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-volume-mid:before, .video-js .vjs-mute-control.vjs-vol-2 .vjs-icon-placeholder:before { + content: "\f106"; +} + +.vjs-icon-volume-high, .video-js .vjs-mute-control .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-volume-high:before, .video-js .vjs-mute-control .vjs-icon-placeholder:before { + content: "\f107"; +} + +.vjs-icon-fullscreen-enter, .video-js .vjs-fullscreen-control .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-fullscreen-enter:before, .video-js .vjs-fullscreen-control .vjs-icon-placeholder:before { + content: "\f108"; +} + +.vjs-icon-fullscreen-exit, .video-js.vjs-fullscreen .vjs-fullscreen-control .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-fullscreen-exit:before, .video-js.vjs-fullscreen .vjs-fullscreen-control .vjs-icon-placeholder:before { + content: "\f109"; +} + +.vjs-icon-square { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-square:before { + content: "\f10a"; +} + +.vjs-icon-spinner { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-spinner:before { + content: "\f10b"; +} + +.vjs-icon-subtitles, .video-js .vjs-subtitles-button .vjs-icon-placeholder, .video-js .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js.video-js:lang(en-GB) .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js.video-js:lang(en-IE) .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js.video-js:lang(en-AU) .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js.video-js:lang(en-NZ) .vjs-subs-caps-button .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-subtitles:before, .video-js .vjs-subtitles-button .vjs-icon-placeholder:before, .video-js .vjs-subs-caps-button .vjs-icon-placeholder:before, +.video-js.video-js:lang(en-GB) .vjs-subs-caps-button .vjs-icon-placeholder:before, +.video-js.video-js:lang(en-IE) .vjs-subs-caps-button .vjs-icon-placeholder:before, +.video-js.video-js:lang(en-AU) .vjs-subs-caps-button .vjs-icon-placeholder:before, +.video-js.video-js:lang(en-NZ) .vjs-subs-caps-button .vjs-icon-placeholder:before { + content: "\f10c"; +} + +.vjs-icon-captions, .video-js .vjs-captions-button .vjs-icon-placeholder, .video-js:lang(en) .vjs-subs-caps-button .vjs-icon-placeholder, +.video-js:lang(fr-CA) .vjs-subs-caps-button .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-captions:before, .video-js .vjs-captions-button .vjs-icon-placeholder:before, .video-js:lang(en) .vjs-subs-caps-button .vjs-icon-placeholder:before, +.video-js:lang(fr-CA) .vjs-subs-caps-button .vjs-icon-placeholder:before { + content: "\f10d"; +} + +.vjs-icon-chapters, .video-js .vjs-chapters-button .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-chapters:before, .video-js .vjs-chapters-button .vjs-icon-placeholder:before { + content: "\f10e"; +} + +.vjs-icon-share { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-share:before { + content: "\f10f"; +} + +.vjs-icon-cog { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-cog:before { + content: "\f110"; +} + +.vjs-icon-circle, .video-js .vjs-play-progress, .video-js .vjs-volume-level { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-circle:before, .video-js .vjs-play-progress:before, .video-js .vjs-volume-level:before { + content: "\f111"; +} + +.vjs-icon-circle-outline { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-circle-outline:before { + content: "\f112"; +} + +.vjs-icon-circle-inner-circle { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-circle-inner-circle:before { + content: "\f113"; +} + +.vjs-icon-hd { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-hd:before { + content: "\f114"; +} + +.vjs-icon-cancel, .video-js .vjs-control.vjs-close-button .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-cancel:before, .video-js .vjs-control.vjs-close-button .vjs-icon-placeholder:before { + content: "\f115"; +} + +.vjs-icon-replay, .video-js .vjs-play-control.vjs-ended .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-replay:before, .video-js .vjs-play-control.vjs-ended .vjs-icon-placeholder:before { + content: "\f116"; +} + +.vjs-icon-facebook { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-facebook:before { + content: "\f117"; +} + +.vjs-icon-gplus { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-gplus:before { + content: "\f118"; +} + +.vjs-icon-linkedin { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-linkedin:before { + content: "\f119"; +} + +.vjs-icon-twitter { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-twitter:before { + content: "\f11a"; +} + +.vjs-icon-tumblr { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-tumblr:before { + content: "\f11b"; +} + +.vjs-icon-pinterest { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-pinterest:before { + content: "\f11c"; +} + +.vjs-icon-audio-description, .video-js .vjs-descriptions-button .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-audio-description:before, .video-js .vjs-descriptions-button .vjs-icon-placeholder:before { + content: "\f11d"; +} + +.vjs-icon-audio, .video-js .vjs-audio-button .vjs-icon-placeholder { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-audio:before, .video-js .vjs-audio-button .vjs-icon-placeholder:before { + content: "\f11e"; +} + +.vjs-icon-next-item { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-next-item:before { + content: "\f11f"; +} + +.vjs-icon-previous-item { + font-family: VideoJS; + font-weight: normal; + font-style: normal; +} + +.vjs-icon-previous-item:before { + content: "\f120"; +} + +.video-js { + display: block; + vertical-align: top; + box-sizing: border-box; + color: #fff; + background-color: #000; + position: relative; + padding: 0; + font-size: 10px; + line-height: 1; + font-weight: normal; + font-style: normal; + font-family: Arial, Helvetica, sans-serif; + word-break: initial; +} + +.video-js:-moz-full-screen { + position: absolute; +} + +.video-js:-webkit-full-screen { + width: 100% !important; + height: 100% !important; +} + +.video-js[tabindex="-1"] { + outline: none; +} + +.video-js *, +.video-js *:before, +.video-js *:after { + box-sizing: inherit; +} + +.video-js ul { + font-family: inherit; + font-size: inherit; + line-height: inherit; + list-style-position: outside; + margin-left: 0; + margin-right: 0; + margin-top: 0; + margin-bottom: 0; +} + +.video-js.vjs-fluid, +.video-js.vjs-16-9, +.video-js.vjs-4-3 { + width: 100%; + max-width: 100%; + height: 0; +} + +.video-js.vjs-16-9 { + padding-top: 56.25%; +} + +.video-js.vjs-4-3 { + padding-top: 75%; +} + +.video-js.vjs-fill { + width: 100%; + height: 100%; +} + +.video-js .vjs-tech { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +body.vjs-full-window { + padding: 0; + margin: 0; + height: 100%; +} + +.vjs-full-window .video-js.vjs-fullscreen { + position: fixed; + overflow: hidden; + z-index: 1000; + left: 0; + top: 0; + bottom: 0; + right: 0; +} + +.video-js.vjs-fullscreen { + width: 100% !important; + height: 100% !important; + padding-top: 0 !important; +} + +.video-js.vjs-fullscreen.vjs-user-inactive { + cursor: none; +} + +.vjs-hidden { + display: none !important; +} + +.vjs-disabled { + opacity: 0.5; + cursor: default; +} + +.video-js .vjs-offscreen { + height: 1px; + left: -9999px; + position: absolute; + top: 0; + width: 1px; +} + +.vjs-lock-showing { + display: block !important; + opacity: 1; + visibility: visible; +} + +.vjs-no-js { + padding: 20px; + color: #fff; + background-color: #000; + font-size: 18px; + font-family: Arial, Helvetica, sans-serif; + text-align: center; + width: 300px; + height: 150px; + margin: 0px auto; +} + +.vjs-no-js a, +.vjs-no-js a:visited { + color: #66A8CC; +} + +.video-js .vjs-big-play-button { + font-size: 3em; + line-height: 1.5em; + height: 1.5em; + width: 3em; + display: block; + position: absolute; + top: 10px; + left: 10px; + padding: 0; + cursor: pointer; + opacity: 1; + border: 0.06666em solid #fff; + background-color: #2B333F; + background-color: rgba(43, 51, 63, 0.7); + -webkit-border-radius: 0.3em; + -moz-border-radius: 0.3em; + border-radius: 0.3em; + -webkit-transition: all 0.4s; + -moz-transition: all 0.4s; + -ms-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; +} + +.vjs-big-play-centered .vjs-big-play-button { + top: 50%; + left: 50%; + margin-top: -0.75em; + margin-left: -1.5em; +} + +.video-js:hover .vjs-big-play-button, +.video-js .vjs-big-play-button:focus { + border-color: #fff; + background-color: #73859f; + background-color: rgba(115, 133, 159, 0.5); + -webkit-transition: all 0s; + -moz-transition: all 0s; + -ms-transition: all 0s; + -o-transition: all 0s; + transition: all 0s; +} + +.vjs-controls-disabled .vjs-big-play-button, +.vjs-has-started .vjs-big-play-button, +.vjs-using-native-controls .vjs-big-play-button, +.vjs-error .vjs-big-play-button { + display: none; +} + +.vjs-has-started.vjs-paused.vjs-show-big-play-button-on-pause .vjs-big-play-button { + display: block; +} + +.video-js button { + background: none; + border: none; + color: inherit; + display: inline-block; + font-size: inherit; + line-height: inherit; + text-transform: none; + text-decoration: none; + transition: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.vjs-control .vjs-button { + width: 100%; + height: 100%; +} + +.video-js .vjs-control.vjs-close-button { + cursor: pointer; + height: 3em; + position: absolute; + right: 0; + top: 0.5em; + z-index: 2; +} + +.video-js .vjs-modal-dialog { + background: rgba(0, 0, 0, 0.8); + background: -webkit-linear-gradient(-90deg, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0)); + background: linear-gradient(180deg, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0)); + overflow: auto; +} + +.video-js .vjs-modal-dialog > * { + box-sizing: border-box; +} + +.vjs-modal-dialog .vjs-modal-dialog-content { + font-size: 1.2em; + line-height: 1.5; + padding: 20px 24px; + z-index: 1; +} + +.vjs-menu-button { + cursor: pointer; +} + +.vjs-menu-button.vjs-disabled { + cursor: default; +} + +.vjs-workinghover .vjs-menu-button.vjs-disabled:hover .vjs-menu { + display: none; +} + +.vjs-menu .vjs-menu-content { + display: block; + padding: 0; + margin: 0; + font-family: Arial, Helvetica, sans-serif; + overflow: auto; +} + +.vjs-menu .vjs-menu-content > * { + box-sizing: border-box; +} + +.vjs-scrubbing .vjs-control.vjs-menu-button:hover .vjs-menu { + display: none; +} + +.vjs-menu li { + list-style: none; + margin: 0; + padding: 0.2em 0; + line-height: 1.4em; + font-size: 1.2em; + text-align: center; + text-transform: lowercase; +} + +.vjs-menu li.vjs-menu-item:focus, +.vjs-menu li.vjs-menu-item:hover { + background-color: #73859f; + background-color: rgba(115, 133, 159, 0.5); +} + +.vjs-menu li.vjs-selected, +.vjs-menu li.vjs-selected:focus, +.vjs-menu li.vjs-selected:hover { + background-color: #fff; + color: #2B333F; +} + +.vjs-menu li.vjs-menu-title { + text-align: center; + text-transform: uppercase; + font-size: 1em; + line-height: 2em; + padding: 0; + margin: 0 0 0.3em 0; + font-weight: bold; + cursor: default; +} + +.vjs-menu-button-popup .vjs-menu { + display: none; + position: absolute; + bottom: 0; + width: 10em; + left: -3em; + height: 0em; + margin-bottom: 1.5em; + border-top-color: rgba(43, 51, 63, 0.7); +} + +.vjs-menu-button-popup .vjs-menu .vjs-menu-content { + background-color: #2B333F; + background-color: rgba(43, 51, 63, 0.7); + position: absolute; + width: 100%; + bottom: 1.5em; + max-height: 15em; +} + +.vjs-workinghover .vjs-menu-button-popup:hover .vjs-menu, +.vjs-menu-button-popup .vjs-menu.vjs-lock-showing { + display: block; +} + +.video-js .vjs-menu-button-inline { + -webkit-transition: all 0.4s; + -moz-transition: all 0.4s; + -ms-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; + overflow: hidden; +} + +.video-js .vjs-menu-button-inline:before { + width: 2.222222222em; +} + +.video-js .vjs-menu-button-inline:hover, +.video-js .vjs-menu-button-inline:focus, +.video-js .vjs-menu-button-inline.vjs-slider-active, +.video-js.vjs-no-flex .vjs-menu-button-inline { + width: 12em; +} + +.vjs-menu-button-inline .vjs-menu { + opacity: 0; + height: 100%; + width: auto; + position: absolute; + left: 4em; + top: 0; + padding: 0; + margin: 0; + -webkit-transition: all 0.4s; + -moz-transition: all 0.4s; + -ms-transition: all 0.4s; + -o-transition: all 0.4s; + transition: all 0.4s; +} + +.vjs-menu-button-inline:hover .vjs-menu, +.vjs-menu-button-inline:focus .vjs-menu, +.vjs-menu-button-inline.vjs-slider-active .vjs-menu { + display: block; + opacity: 1; +} + +.vjs-no-flex .vjs-menu-button-inline .vjs-menu { + display: block; + opacity: 1; + position: relative; + width: auto; +} + +.vjs-no-flex .vjs-menu-button-inline:hover .vjs-menu, +.vjs-no-flex .vjs-menu-button-inline:focus .vjs-menu, +.vjs-no-flex .vjs-menu-button-inline.vjs-slider-active .vjs-menu { + width: auto; +} + +.vjs-menu-button-inline .vjs-menu-content { + width: auto; + height: 100%; + margin: 0; + overflow: hidden; +} + +.video-js .vjs-control-bar { + display: none; + width: 100%; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 3.0em; + background-color: #2B333F; + background-color: rgba(43, 51, 63, 0.7); +} + +.vjs-has-started .vjs-control-bar { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + visibility: visible; + opacity: 1; + -webkit-transition: visibility 0.1s, opacity 0.1s; + -moz-transition: visibility 0.1s, opacity 0.1s; + -ms-transition: visibility 0.1s, opacity 0.1s; + -o-transition: visibility 0.1s, opacity 0.1s; + transition: visibility 0.1s, opacity 0.1s; +} + +.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar { + visibility: visible; + opacity: 0; + -webkit-transition: visibility 1s, opacity 1s; + -moz-transition: visibility 1s, opacity 1s; + -ms-transition: visibility 1s, opacity 1s; + -o-transition: visibility 1s, opacity 1s; + transition: visibility 1s, opacity 1s; +} + +.vjs-controls-disabled .vjs-control-bar, +.vjs-using-native-controls .vjs-control-bar, +.vjs-error .vjs-control-bar { + display: none !important; +} + +.vjs-audio.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar { + opacity: 1; + visibility: visible; +} + +.vjs-has-started.vjs-no-flex .vjs-control-bar { + display: table; +} + +.video-js .vjs-control { + position: relative; + text-align: center; + margin: 0; + padding: 0; + height: 100%; + width: 4em; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; +} + +.vjs-button > .vjs-icon-placeholder:before { + font-size: 1.8em; + line-height: 1.67; +} + +.video-js .vjs-control:focus:before, +.video-js .vjs-control:hover:before, +.video-js .vjs-control:focus { + text-shadow: 0em 0em 1em white; +} + +.video-js .vjs-control-text { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +.vjs-no-flex .vjs-control { + display: table-cell; + vertical-align: middle; +} + +.video-js .vjs-custom-control-spacer { + display: none; +} + +.video-js .vjs-progress-control { + cursor: pointer; + -webkit-box-flex: auto; + -moz-box-flex: auto; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + min-width: 4em; +} + +.video-js .vjs-progress-control.disabled { + cursor: default; +} + +.vjs-live .vjs-progress-control { + display: none; +} + +.vjs-no-flex .vjs-progress-control { + width: auto; +} + +.video-js .vjs-progress-holder { + -webkit-box-flex: auto; + -moz-box-flex: auto; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + -ms-transition: all 0.2s; + -o-transition: all 0.2s; + transition: all 0.2s; + height: 0.3em; +} + +.video-js .vjs-progress-control .vjs-progress-holder { + margin: 0 10px; +} + +.video-js .vjs-progress-control:hover .vjs-progress-holder { + font-size: 1.666666666666666666em; +} + +.video-js .vjs-progress-control:hover .vjs-progress-holder.disabled { + font-size: 1em; +} + +.video-js .vjs-progress-holder .vjs-play-progress, +.video-js .vjs-progress-holder .vjs-load-progress, +.video-js .vjs-progress-holder .vjs-load-progress div { + position: absolute; + display: block; + height: 100%; + margin: 0; + padding: 0; + width: 0; +} + +.video-js .vjs-play-progress { + background-color: #fff; +} + +.video-js .vjs-play-progress:before { + font-size: 0.9em; + position: absolute; + right: -0.5em; + top: -0.333333333333333em; + z-index: 1; +} + +.video-js .vjs-load-progress { + background: rgba(115, 133, 159, 0.5); +} + +.video-js .vjs-load-progress div { + background: rgba(115, 133, 159, 0.75); +} + +.video-js .vjs-time-tooltip { + background-color: #fff; + background-color: rgba(255, 255, 255, 0.8); + -webkit-border-radius: 0.3em; + -moz-border-radius: 0.3em; + border-radius: 0.3em; + color: #000; + float: right; + font-family: Arial, Helvetica, sans-serif; + font-size: 1em; + padding: 6px 8px 8px 8px; + pointer-events: none; + position: relative; + top: -3.4em; + visibility: hidden; + z-index: 1; +} + +.video-js .vjs-progress-holder:focus .vjs-time-tooltip { + display: none; +} + +.video-js .vjs-progress-control:hover .vjs-time-tooltip, +.video-js .vjs-progress-control:hover .vjs-progress-holder:focus .vjs-time-tooltip { + display: block; + font-size: 0.6em; + visibility: visible; +} + +.video-js .vjs-progress-control.disabled:hover .vjs-time-tooltip { + font-size: 1em; +} + +.video-js .vjs-progress-control .vjs-mouse-display { + display: none; + position: absolute; + width: 1px; + height: 100%; + background-color: #000; + z-index: 1; +} + +.vjs-no-flex .vjs-progress-control .vjs-mouse-display { + z-index: 0; +} + +.video-js .vjs-progress-control:hover .vjs-mouse-display { + display: block; +} + +.video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display { + visibility: hidden; + opacity: 0; + -webkit-transition: visibility 1s, opacity 1s; + -moz-transition: visibility 1s, opacity 1s; + -ms-transition: visibility 1s, opacity 1s; + -o-transition: visibility 1s, opacity 1s; + transition: visibility 1s, opacity 1s; +} + +.video-js.vjs-user-inactive.vjs-no-flex .vjs-progress-control .vjs-mouse-display { + display: none; +} + +.vjs-mouse-display .vjs-time-tooltip { + color: #fff; + background-color: #000; + background-color: rgba(0, 0, 0, 0.8); +} + +.video-js .vjs-slider { + position: relative; + cursor: pointer; + padding: 0; + margin: 0 0.45em 0 0.45em; + /* iOS Safari */ + -webkit-touch-callout: none; + /* Safari */ + -webkit-user-select: none; + /* Konqueror HTML */ + -khtml-user-select: none; + /* Firefox */ + -moz-user-select: none; + /* Internet Explorer/Edge */ + -ms-user-select: none; + /* Non-prefixed version, currently supported by Chrome and Opera */ + user-select: none; + background-color: #73859f; + background-color: rgba(115, 133, 159, 0.5); +} + +.video-js .vjs-slider.disabled { + cursor: default; +} + +.video-js .vjs-slider:focus { + text-shadow: 0em 0em 1em white; + -webkit-box-shadow: 0 0 1em #fff; + -moz-box-shadow: 0 0 1em #fff; + box-shadow: 0 0 1em #fff; +} + +.video-js .vjs-mute-control { + cursor: pointer; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; +} + +.video-js .vjs-volume-control { + cursor: pointer; + margin-right: 1em; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +.video-js .vjs-volume-control.vjs-volume-horizontal { + width: 5em; +} + +.video-js .vjs-volume-panel .vjs-volume-control { + visibility: visible; + opacity: 0; + width: 1px; + height: 1px; + margin-left: -1px; +} + +.video-js .vjs-volume-panel { + -webkit-transition: width 1s; + -moz-transition: width 1s; + -ms-transition: width 1s; + -o-transition: width 1s; + transition: width 1s; +} + +.video-js .vjs-volume-panel:hover .vjs-volume-control, +.video-js .vjs-volume-panel:active .vjs-volume-control, +.video-js .vjs-volume-panel:focus .vjs-volume-control, +.video-js .vjs-volume-panel .vjs-volume-control:hover, +.video-js .vjs-volume-panel .vjs-volume-control:active, +.video-js .vjs-volume-panel .vjs-mute-control:hover ~ .vjs-volume-control, +.video-js .vjs-volume-panel .vjs-volume-control.vjs-slider-active { + visibility: visible; + opacity: 1; + position: relative; + -webkit-transition: visibility 0.1s, opacity 0.1s, height 0.1s, width 0.1s, left 0s, top 0s; + -moz-transition: visibility 0.1s, opacity 0.1s, height 0.1s, width 0.1s, left 0s, top 0s; + -ms-transition: visibility 0.1s, opacity 0.1s, height 0.1s, width 0.1s, left 0s, top 0s; + -o-transition: visibility 0.1s, opacity 0.1s, height 0.1s, width 0.1s, left 0s, top 0s; + transition: visibility 0.1s, opacity 0.1s, height 0.1s, width 0.1s, left 0s, top 0s; +} + +.video-js .vjs-volume-panel:hover .vjs-volume-control.vjs-volume-horizontal, +.video-js .vjs-volume-panel:active .vjs-volume-control.vjs-volume-horizontal, +.video-js .vjs-volume-panel:focus .vjs-volume-control.vjs-volume-horizontal, +.video-js .vjs-volume-panel .vjs-volume-control:hover.vjs-volume-horizontal, +.video-js .vjs-volume-panel .vjs-volume-control:active.vjs-volume-horizontal, +.video-js .vjs-volume-panel .vjs-mute-control:hover ~ .vjs-volume-control.vjs-volume-horizontal, +.video-js .vjs-volume-panel .vjs-volume-control.vjs-slider-active.vjs-volume-horizontal { + width: 5em; + height: 3em; +} + +.video-js .vjs-volume-panel.vjs-volume-panel-horizontal:hover, .video-js .vjs-volume-panel.vjs-volume-panel-horizontal:active, .video-js .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-slider-active { + width: 9em; + -webkit-transition: width 0.1s; + -moz-transition: width 0.1s; + -ms-transition: width 0.1s; + -o-transition: width 0.1s; + transition: width 0.1s; +} + +.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical { + height: 8em; + width: 3em; + left: -3.5em; + -webkit-transition: visibility 1s, opacity 1s, height 1s 1s, width 1s 1s, left 1s 1s, top 1s 1s; + -moz-transition: visibility 1s, opacity 1s, height 1s 1s, width 1s 1s, left 1s 1s, top 1s 1s; + -ms-transition: visibility 1s, opacity 1s, height 1s 1s, width 1s 1s, left 1s 1s, top 1s 1s; + -o-transition: visibility 1s, opacity 1s, height 1s 1s, width 1s 1s, left 1s 1s, top 1s 1s; + transition: visibility 1s, opacity 1s, height 1s 1s, width 1s 1s, left 1s 1s, top 1s 1s; +} + +.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-horizontal { + -webkit-transition: visibility 1s, opacity 1s, height 1s 1s, width 1s, left 1s 1s, top 1s 1s; + -moz-transition: visibility 1s, opacity 1s, height 1s 1s, width 1s, left 1s 1s, top 1s 1s; + -ms-transition: visibility 1s, opacity 1s, height 1s 1s, width 1s, left 1s 1s, top 1s 1s; + -o-transition: visibility 1s, opacity 1s, height 1s 1s, width 1s, left 1s 1s, top 1s 1s; + transition: visibility 1s, opacity 1s, height 1s 1s, width 1s, left 1s 1s, top 1s 1s; +} + +.video-js.vjs-no-flex .vjs-volume-panel .vjs-volume-control.vjs-volume-horizontal { + width: 5em; + height: 3em; + visibility: visible; + opacity: 1; + position: relative; + -webkit-transition: none; + -moz-transition: none; + -ms-transition: none; + -o-transition: none; + transition: none; +} + +.video-js.vjs-no-flex .vjs-volume-control.vjs-volume-vertical, +.video-js.vjs-no-flex .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical { + position: absolute; + bottom: 3em; + left: 0.5em; +} + +.video-js .vjs-volume-panel { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +.video-js .vjs-volume-bar { + margin: 1.35em 0.45em; +} + +.vjs-volume-bar.vjs-slider-horizontal { + width: 5em; + height: 0.3em; +} + +.vjs-volume-bar.vjs-slider-vertical { + width: 0.3em; + height: 5em; + margin: 1.35em auto; +} + +.video-js .vjs-volume-level { + position: absolute; + bottom: 0; + left: 0; + background-color: #fff; +} + +.video-js .vjs-volume-level:before { + position: absolute; + font-size: 0.9em; +} + +.vjs-slider-vertical .vjs-volume-level { + width: 0.3em; +} + +.vjs-slider-vertical .vjs-volume-level:before { + top: -0.5em; + left: -0.3em; +} + +.vjs-slider-horizontal .vjs-volume-level { + height: 0.3em; +} + +.vjs-slider-horizontal .vjs-volume-level:before { + top: -0.3em; + right: -0.5em; +} + +.video-js .vjs-volume-panel.vjs-volume-panel-vertical { + width: 4em; +} + +.vjs-volume-bar.vjs-slider-vertical .vjs-volume-level { + height: 100%; +} + +.vjs-volume-bar.vjs-slider-horizontal .vjs-volume-level { + width: 100%; +} + +.video-js .vjs-volume-vertical { + width: 3em; + height: 8em; + bottom: 8em; + background-color: #2B333F; + background-color: rgba(43, 51, 63, 0.7); +} + +.video-js .vjs-volume-horizontal .vjs-menu { + left: -2em; +} + +.vjs-poster { + display: inline-block; + vertical-align: middle; + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain; + background-color: #000000; + cursor: pointer; + margin: 0; + padding: 0; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 100%; +} + +.vjs-has-started .vjs-poster { + display: none; +} + +.vjs-audio.vjs-has-started .vjs-poster { + display: block; +} + +.vjs-using-native-controls .vjs-poster { + display: none; +} + +.video-js .vjs-live-control { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: flex-start; + -webkit-align-items: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + -webkit-box-flex: auto; + -moz-box-flex: auto; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; + font-size: 1em; + line-height: 3em; +} + +.vjs-no-flex .vjs-live-control { + display: table-cell; + width: auto; + text-align: left; +} + +.video-js .vjs-time-control { + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; + font-size: 1em; + line-height: 3em; + min-width: 2em; + width: auto; + padding-left: 1em; + padding-right: 1em; +} + +.vjs-live .vjs-time-control { + display: none; +} + +.video-js .vjs-current-time, +.vjs-no-flex .vjs-current-time { + display: none; +} + +.video-js .vjs-duration, +.vjs-no-flex .vjs-duration { + display: none; +} + +.vjs-time-divider { + display: none; + line-height: 3em; +} + +.vjs-live .vjs-time-divider { + display: none; +} + +.video-js .vjs-play-control .vjs-icon-placeholder { + cursor: pointer; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; +} + +.vjs-text-track-display { + position: absolute; + bottom: 3em; + left: 0; + right: 0; + top: 0; + pointer-events: none; +} + +.video-js.vjs-user-inactive.vjs-playing .vjs-text-track-display { + bottom: 1em; +} + +.video-js .vjs-text-track { + font-size: 1.4em; + text-align: center; + margin-bottom: 0.1em; +} + +.vjs-subtitles { + color: #fff; +} + +.vjs-captions { + color: #fc6; +} + +.vjs-tt-cue { + display: block; +} + +video::-webkit-media-text-track-display { + -moz-transform: translateY(-3em); + -ms-transform: translateY(-3em); + -o-transform: translateY(-3em); + -webkit-transform: translateY(-3em); + transform: translateY(-3em); +} + +.video-js.vjs-user-inactive.vjs-playing video::-webkit-media-text-track-display { + -moz-transform: translateY(-1.5em); + -ms-transform: translateY(-1.5em); + -o-transform: translateY(-1.5em); + -webkit-transform: translateY(-1.5em); + transform: translateY(-1.5em); +} + +.video-js .vjs-fullscreen-control { + cursor: pointer; + -webkit-box-flex: none; + -moz-box-flex: none; + -webkit-flex: none; + -ms-flex: none; + flex: none; +} + +.vjs-playback-rate > .vjs-menu-button, +.vjs-playback-rate .vjs-playback-rate-value { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.vjs-playback-rate .vjs-playback-rate-value { + pointer-events: none; + font-size: 1.5em; + line-height: 2; + text-align: center; +} + +.vjs-playback-rate .vjs-menu { + width: 4em; + left: 0em; +} + +.vjs-error .vjs-error-display .vjs-modal-dialog-content { + font-size: 1.4em; + text-align: center; +} + +.vjs-error .vjs-error-display:before { + color: #fff; + content: 'X'; + font-family: Arial, Helvetica, sans-serif; + font-size: 4em; + left: 0; + line-height: 1; + margin-top: -0.5em; + position: absolute; + text-shadow: 0.05em 0.05em 0.1em #000; + text-align: center; + top: 50%; + vertical-align: middle; + width: 100%; +} + +.vjs-loading-spinner { + display: none; + position: absolute; + top: 50%; + left: 50%; + margin: -25px 0 0 -25px; + opacity: 0.85; + text-align: left; + border: 6px solid rgba(43, 51, 63, 0.7); + box-sizing: border-box; + background-clip: padding-box; + width: 50px; + height: 50px; + border-radius: 25px; + visibility: hidden; +} + +.vjs-seeking .vjs-loading-spinner, +.vjs-waiting .vjs-loading-spinner { + display: block; + animation: 0s linear 0.3s forwards vjs-spinner-show; +} + +.vjs-loading-spinner:before, +.vjs-loading-spinner:after { + content: ""; + position: absolute; + margin: -6px; + box-sizing: inherit; + width: inherit; + height: inherit; + border-radius: inherit; + opacity: 1; + border: inherit; + border-color: transparent; + border-top-color: white; +} + +.vjs-seeking .vjs-loading-spinner:before, +.vjs-seeking .vjs-loading-spinner:after, +.vjs-waiting .vjs-loading-spinner:before, +.vjs-waiting .vjs-loading-spinner:after { + -webkit-animation: vjs-spinner-spin 1.1s cubic-bezier(0.6, 0.2, 0, 0.8) infinite, vjs-spinner-fade 1.1s linear infinite; + animation: vjs-spinner-spin 1.1s cubic-bezier(0.6, 0.2, 0, 0.8) infinite, vjs-spinner-fade 1.1s linear infinite; +} + +.vjs-seeking .vjs-loading-spinner:before, +.vjs-waiting .vjs-loading-spinner:before { + border-top-color: white; +} + +.vjs-seeking .vjs-loading-spinner:after, +.vjs-waiting .vjs-loading-spinner:after { + border-top-color: white; + -webkit-animation-delay: 0.44s; + animation-delay: 0.44s; +} + +@keyframes vjs-spinner-show { + to { + visibility: visible; + } +} + +@-webkit-keyframes vjs-spinner-show { + to { + visibility: visible; + } +} + +@keyframes vjs-spinner-spin { + 100% { + transform: rotate(360deg); + } +} + +@-webkit-keyframes vjs-spinner-spin { + 100% { + -webkit-transform: rotate(360deg); + } +} + +@keyframes vjs-spinner-fade { + 0% { + border-top-color: #73859f; + } + 20% { + border-top-color: #73859f; + } + 35% { + border-top-color: white; + } + 60% { + border-top-color: #73859f; + } + 100% { + border-top-color: #73859f; + } +} + +@-webkit-keyframes vjs-spinner-fade { + 0% { + border-top-color: #73859f; + } + 20% { + border-top-color: #73859f; + } + 35% { + border-top-color: white; + } + 60% { + border-top-color: #73859f; + } + 100% { + border-top-color: #73859f; + } +} + +.vjs-chapters-button .vjs-menu ul { + width: 24em; +} + +.video-js .vjs-subs-caps-button + .vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder { + position: absolute; +} + +.video-js .vjs-subs-caps-button + .vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder:before { + font-family: VideoJS; + content: "\f10d"; + font-size: 1.5em; + line-height: inherit; +} + +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-custom-control-spacer { + -webkit-box-flex: auto; + -moz-box-flex: auto; + -webkit-flex: auto; + -ms-flex: auto; + flex: auto; +} + +.video-js.vjs-layout-tiny:not(.vjs-fullscreen).vjs-no-flex .vjs-custom-control-spacer { + width: auto; +} + +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-current-time, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-time-divider, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-duration, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-remaining-time, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-playback-rate, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-progress-control, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-mute-control, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-volume-control, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-chapters-button, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-descriptions-button, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-captions-button, +.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-subtitles-button, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-audio-button { + display: none; +} + +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-current-time, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-time-divider, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-duration, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-remaining-time, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-playback-rate, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-mute-control, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-volume-control, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-chapters-button, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-descriptions-button, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-captions-button, +.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-subtitles-button, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-audio-button { + display: none; +} + +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-current-time, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-time-divider, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-duration, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-remaining-time, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-playback-rate, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-mute-control, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-volume-control, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-chapters-button, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-descriptions-button, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-captions-button, +.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-subtitles-button .vjs-audio-button { + display: none; +} + +.vjs-modal-dialog.vjs-text-track-settings { + background-color: #2B333F; + background-color: rgba(43, 51, 63, 0.75); + color: #fff; + height: 70%; +} + +.vjs-text-track-settings .vjs-modal-dialog-content { + display: table; +} + +.vjs-text-track-settings .vjs-track-settings-colors, +.vjs-text-track-settings .vjs-track-settings-font, +.vjs-text-track-settings .vjs-track-settings-controls { + display: table-cell; +} + +.vjs-text-track-settings .vjs-track-settings-controls { + text-align: right; + vertical-align: bottom; +} + +@supports (display: grid) { + .vjs-text-track-settings .vjs-modal-dialog-content { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr auto; + } + + .vjs-text-track-settings .vjs-track-settings-colors { + display: block; + grid-column: 1; + grid-row: 1; + } + + .vjs-text-track-settings .vjs-track-settings-font { + grid-column: 2; + grid-row: 1; + } + + .vjs-text-track-settings .vjs-track-settings-controls { + grid-column: 2; + grid-row: 2; + } +} + +.vjs-track-setting > select { + margin-right: 5px; +} + +.vjs-text-track-settings fieldset { + margin: 5px; + padding: 3px; + border: none; +} + +.vjs-text-track-settings fieldset span { + display: inline-block; +} + +.vjs-text-track-settings legend { + color: #fff; + margin: 0 0 5px 0; +} + +.vjs-text-track-settings .vjs-label { + position: absolute; + clip: rect(1px 1px 1px 1px); + clip: rect(1px, 1px, 1px, 1px); + display: block; + margin: 0 0 5px 0; + padding: 0; + border: 0; + height: 1px; + width: 1px; + overflow: hidden; +} + +.vjs-track-settings-controls button:focus, +.vjs-track-settings-controls button:active { + outline-style: solid; + outline-width: medium; + background-image: linear-gradient(0deg, #fff 88%, #73859f 100%); +} + +.vjs-track-settings-controls button:hover { + color: rgba(43, 51, 63, 0.75); +} + +.vjs-track-settings-controls button { + background-color: #fff; + background-image: linear-gradient(-180deg, #fff 88%, #73859f 100%); + color: #2B333F; + cursor: pointer; + border-radius: 2px; +} + +.vjs-track-settings-controls .vjs-default-button { + margin-right: 1em; +} + +@media print { + .video-js > *:not(.vjs-tech):not(.vjs-poster) { + visibility: hidden; + } +} + +.vjs-resize-manager { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; + visibility: hidden; +} diff --git a/form/src/assets/libs/video-js-7.0.0/video-js.min.css b/form/src/assets/libs/video-js-7.0.0/video-js.min.css new file mode 100644 index 0000000..10c2521 --- /dev/null +++ b/form/src/assets/libs/video-js-7.0.0/video-js.min.css @@ -0,0 +1 @@ +.video-js .vjs-big-play-button .vjs-icon-placeholder:before,.video-js .vjs-modal-dialog,.vjs-button>.vjs-icon-placeholder:before,.vjs-modal-dialog .vjs-modal-dialog-content{position:absolute;top:0;left:0;width:100%;height:100%}.video-js .vjs-big-play-button .vjs-icon-placeholder:before,.vjs-button>.vjs-icon-placeholder:before{text-align:center}@font-face{font-family:VideoJS;src:url(data:application/font-woff;charset=utf-8;base64,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) format("woff");font-weight:400;font-style:normal}.video-js .vjs-big-play-button .vjs-icon-placeholder:before,.video-js .vjs-play-control .vjs-icon-placeholder,.vjs-icon-play{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-big-play-button .vjs-icon-placeholder:before,.video-js .vjs-play-control .vjs-icon-placeholder:before,.vjs-icon-play:before{content:"\f101"}.vjs-icon-play-circle{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-play-circle:before{content:"\f102"}.video-js .vjs-play-control.vjs-playing .vjs-icon-placeholder,.vjs-icon-pause{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-play-control.vjs-playing .vjs-icon-placeholder:before,.vjs-icon-pause:before{content:"\f103"}.video-js .vjs-mute-control.vjs-vol-0 .vjs-icon-placeholder,.vjs-icon-volume-mute{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-mute-control.vjs-vol-0 .vjs-icon-placeholder:before,.vjs-icon-volume-mute:before{content:"\f104"}.video-js .vjs-mute-control.vjs-vol-1 .vjs-icon-placeholder,.vjs-icon-volume-low{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-mute-control.vjs-vol-1 .vjs-icon-placeholder:before,.vjs-icon-volume-low:before{content:"\f105"}.video-js .vjs-mute-control.vjs-vol-2 .vjs-icon-placeholder,.vjs-icon-volume-mid{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-mute-control.vjs-vol-2 .vjs-icon-placeholder:before,.vjs-icon-volume-mid:before{content:"\f106"}.video-js .vjs-mute-control .vjs-icon-placeholder,.vjs-icon-volume-high{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-mute-control .vjs-icon-placeholder:before,.vjs-icon-volume-high:before{content:"\f107"}.video-js .vjs-fullscreen-control .vjs-icon-placeholder,.vjs-icon-fullscreen-enter{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-fullscreen-control .vjs-icon-placeholder:before,.vjs-icon-fullscreen-enter:before{content:"\f108"}.video-js.vjs-fullscreen .vjs-fullscreen-control .vjs-icon-placeholder,.vjs-icon-fullscreen-exit{font-family:VideoJS;font-weight:400;font-style:normal}.video-js.vjs-fullscreen .vjs-fullscreen-control .vjs-icon-placeholder:before,.vjs-icon-fullscreen-exit:before{content:"\f109"}.vjs-icon-square{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-square:before{content:"\f10a"}.vjs-icon-spinner{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-spinner:before{content:"\f10b"}.video-js .vjs-subs-caps-button .vjs-icon-placeholder,.video-js .vjs-subtitles-button .vjs-icon-placeholder,.video-js.video-js:lang(en-AU) .vjs-subs-caps-button .vjs-icon-placeholder,.video-js.video-js:lang(en-GB) .vjs-subs-caps-button .vjs-icon-placeholder,.video-js.video-js:lang(en-IE) .vjs-subs-caps-button .vjs-icon-placeholder,.video-js.video-js:lang(en-NZ) .vjs-subs-caps-button .vjs-icon-placeholder,.vjs-icon-subtitles{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js .vjs-subtitles-button .vjs-icon-placeholder:before,.video-js.video-js:lang(en-AU) .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js.video-js:lang(en-GB) .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js.video-js:lang(en-IE) .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js.video-js:lang(en-NZ) .vjs-subs-caps-button .vjs-icon-placeholder:before,.vjs-icon-subtitles:before{content:"\f10c"}.video-js .vjs-captions-button .vjs-icon-placeholder,.video-js:lang(en) .vjs-subs-caps-button .vjs-icon-placeholder,.video-js:lang(fr-CA) .vjs-subs-caps-button .vjs-icon-placeholder,.vjs-icon-captions{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-captions-button .vjs-icon-placeholder:before,.video-js:lang(en) .vjs-subs-caps-button .vjs-icon-placeholder:before,.video-js:lang(fr-CA) .vjs-subs-caps-button .vjs-icon-placeholder:before,.vjs-icon-captions:before{content:"\f10d"}.video-js .vjs-chapters-button .vjs-icon-placeholder,.vjs-icon-chapters{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-chapters-button .vjs-icon-placeholder:before,.vjs-icon-chapters:before{content:"\f10e"}.vjs-icon-share{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-share:before{content:"\f10f"}.vjs-icon-cog{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-cog:before{content:"\f110"}.video-js .vjs-play-progress,.video-js .vjs-volume-level,.vjs-icon-circle{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-play-progress:before,.video-js .vjs-volume-level:before,.vjs-icon-circle:before{content:"\f111"}.vjs-icon-circle-outline{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-circle-outline:before{content:"\f112"}.vjs-icon-circle-inner-circle{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-circle-inner-circle:before{content:"\f113"}.vjs-icon-hd{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-hd:before{content:"\f114"}.video-js .vjs-control.vjs-close-button .vjs-icon-placeholder,.vjs-icon-cancel{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-control.vjs-close-button .vjs-icon-placeholder:before,.vjs-icon-cancel:before{content:"\f115"}.video-js .vjs-play-control.vjs-ended .vjs-icon-placeholder,.vjs-icon-replay{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-play-control.vjs-ended .vjs-icon-placeholder:before,.vjs-icon-replay:before{content:"\f116"}.vjs-icon-facebook{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-facebook:before{content:"\f117"}.vjs-icon-gplus{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-gplus:before{content:"\f118"}.vjs-icon-linkedin{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-linkedin:before{content:"\f119"}.vjs-icon-twitter{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-twitter:before{content:"\f11a"}.vjs-icon-tumblr{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-tumblr:before{content:"\f11b"}.vjs-icon-pinterest{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-pinterest:before{content:"\f11c"}.video-js .vjs-descriptions-button .vjs-icon-placeholder,.vjs-icon-audio-description{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-descriptions-button .vjs-icon-placeholder:before,.vjs-icon-audio-description:before{content:"\f11d"}.video-js .vjs-audio-button .vjs-icon-placeholder,.vjs-icon-audio{font-family:VideoJS;font-weight:400;font-style:normal}.video-js .vjs-audio-button .vjs-icon-placeholder:before,.vjs-icon-audio:before{content:"\f11e"}.vjs-icon-next-item{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-next-item:before{content:"\f11f"}.vjs-icon-previous-item{font-family:VideoJS;font-weight:400;font-style:normal}.vjs-icon-previous-item:before{content:"\f120"}.video-js{display:block;vertical-align:top;box-sizing:border-box;color:#fff;background-color:#000;position:relative;padding:0;font-size:10px;line-height:1;font-weight:400;font-style:normal;font-family:Arial,Helvetica,sans-serif;word-break:initial}.video-js:-moz-full-screen{position:absolute}.video-js:-webkit-full-screen{width:100%!important;height:100%!important}.video-js[tabindex="-1"]{outline:0}.video-js *,.video-js :after,.video-js :before{box-sizing:inherit}.video-js ul{font-family:inherit;font-size:inherit;line-height:inherit;list-style-position:outside;margin-left:0;margin-right:0;margin-top:0;margin-bottom:0}.video-js.vjs-16-9,.video-js.vjs-4-3,.video-js.vjs-fluid{width:100%;max-width:100%;height:0}.video-js.vjs-16-9{padding-top:56.25%}.video-js.vjs-4-3{padding-top:75%}.video-js.vjs-fill{width:100%;height:100%}.video-js .vjs-tech{position:absolute;top:0;left:0;width:100%;height:100%}body.vjs-full-window{padding:0;margin:0;height:100%}.vjs-full-window .video-js.vjs-fullscreen{position:fixed;overflow:hidden;z-index:1000;left:0;top:0;bottom:0;right:0}.video-js.vjs-fullscreen{width:100%!important;height:100%!important;padding-top:0!important}.video-js.vjs-fullscreen.vjs-user-inactive{cursor:none}.vjs-hidden{display:none!important}.vjs-disabled{opacity:.5;cursor:default}.video-js .vjs-offscreen{height:1px;left:-9999px;position:absolute;top:0;width:1px}.vjs-lock-showing{display:block!important;opacity:1;visibility:visible}.vjs-no-js{padding:20px;color:#fff;background-color:#000;font-size:18px;font-family:Arial,Helvetica,sans-serif;text-align:center;width:300px;height:150px;margin:0 auto}.vjs-no-js a,.vjs-no-js a:visited{color:#66a8cc}.video-js .vjs-big-play-button{font-size:3em;line-height:1.5em;height:1.5em;width:3em;display:block;position:absolute;top:10px;left:10px;padding:0;cursor:pointer;opacity:1;border:.06666em solid #fff;background-color:#2b333f;background-color:rgba(43,51,63,.7);-webkit-border-radius:.3em;-moz-border-radius:.3em;border-radius:.3em;-webkit-transition:all .4s;-moz-transition:all .4s;-ms-transition:all .4s;-o-transition:all .4s;transition:all .4s}.vjs-big-play-centered .vjs-big-play-button{top:50%;left:50%;margin-top:-.75em;margin-left:-1.5em}.video-js .vjs-big-play-button:focus,.video-js:hover .vjs-big-play-button{border-color:#fff;background-color:#73859f;background-color:rgba(115,133,159,.5);-webkit-transition:all 0s;-moz-transition:all 0s;-ms-transition:all 0s;-o-transition:all 0s;transition:all 0s}.vjs-controls-disabled .vjs-big-play-button,.vjs-error .vjs-big-play-button,.vjs-has-started .vjs-big-play-button,.vjs-using-native-controls .vjs-big-play-button{display:none}.vjs-has-started.vjs-paused.vjs-show-big-play-button-on-pause .vjs-big-play-button{display:block}.video-js button{background:0 0;border:none;color:inherit;display:inline-block;font-size:inherit;line-height:inherit;text-transform:none;text-decoration:none;transition:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.vjs-control .vjs-button{width:100%;height:100%}.video-js .vjs-control.vjs-close-button{cursor:pointer;height:3em;position:absolute;right:0;top:.5em;z-index:2}.video-js .vjs-modal-dialog{background:rgba(0,0,0,.8);background:-webkit-linear-gradient(-90deg,rgba(0,0,0,.8),rgba(255,255,255,0));background:linear-gradient(180deg,rgba(0,0,0,.8),rgba(255,255,255,0));overflow:auto}.video-js .vjs-modal-dialog>*{box-sizing:border-box}.vjs-modal-dialog .vjs-modal-dialog-content{font-size:1.2em;line-height:1.5;padding:20px 24px;z-index:1}.vjs-menu-button{cursor:pointer}.vjs-menu-button.vjs-disabled{cursor:default}.vjs-workinghover .vjs-menu-button.vjs-disabled:hover .vjs-menu{display:none}.vjs-menu .vjs-menu-content{display:block;padding:0;margin:0;font-family:Arial,Helvetica,sans-serif;overflow:auto}.vjs-menu .vjs-menu-content>*{box-sizing:border-box}.vjs-scrubbing .vjs-control.vjs-menu-button:hover .vjs-menu{display:none}.vjs-menu li{list-style:none;margin:0;padding:.2em 0;line-height:1.4em;font-size:1.2em;text-align:center;text-transform:lowercase}.vjs-menu li.vjs-menu-item:focus,.vjs-menu li.vjs-menu-item:hover{background-color:#73859f;background-color:rgba(115,133,159,.5)}.vjs-menu li.vjs-selected,.vjs-menu li.vjs-selected:focus,.vjs-menu li.vjs-selected:hover{background-color:#fff;color:#2b333f}.vjs-menu li.vjs-menu-title{text-align:center;text-transform:uppercase;font-size:1em;line-height:2em;padding:0;margin:0 0 .3em 0;font-weight:700;cursor:default}.vjs-menu-button-popup .vjs-menu{display:none;position:absolute;bottom:0;width:10em;left:-3em;height:0;margin-bottom:1.5em;border-top-color:rgba(43,51,63,.7)}.vjs-menu-button-popup .vjs-menu .vjs-menu-content{background-color:#2b333f;background-color:rgba(43,51,63,.7);position:absolute;width:100%;bottom:1.5em;max-height:15em}.vjs-menu-button-popup .vjs-menu.vjs-lock-showing,.vjs-workinghover .vjs-menu-button-popup:hover .vjs-menu{display:block}.video-js .vjs-menu-button-inline{-webkit-transition:all .4s;-moz-transition:all .4s;-ms-transition:all .4s;-o-transition:all .4s;transition:all .4s;overflow:hidden}.video-js .vjs-menu-button-inline:before{width:2.222222222em}.video-js .vjs-menu-button-inline.vjs-slider-active,.video-js .vjs-menu-button-inline:focus,.video-js .vjs-menu-button-inline:hover,.video-js.vjs-no-flex .vjs-menu-button-inline{width:12em}.vjs-menu-button-inline .vjs-menu{opacity:0;height:100%;width:auto;position:absolute;left:4em;top:0;padding:0;margin:0;-webkit-transition:all .4s;-moz-transition:all .4s;-ms-transition:all .4s;-o-transition:all .4s;transition:all .4s}.vjs-menu-button-inline.vjs-slider-active .vjs-menu,.vjs-menu-button-inline:focus .vjs-menu,.vjs-menu-button-inline:hover .vjs-menu{display:block;opacity:1}.vjs-no-flex .vjs-menu-button-inline .vjs-menu{display:block;opacity:1;position:relative;width:auto}.vjs-no-flex .vjs-menu-button-inline.vjs-slider-active .vjs-menu,.vjs-no-flex .vjs-menu-button-inline:focus .vjs-menu,.vjs-no-flex .vjs-menu-button-inline:hover .vjs-menu{width:auto}.vjs-menu-button-inline .vjs-menu-content{width:auto;height:100%;margin:0;overflow:hidden}.video-js .vjs-control-bar{display:none;width:100%;position:absolute;bottom:0;left:0;right:0;height:3em;background-color:#2b333f;background-color:rgba(43,51,63,.7)}.vjs-has-started .vjs-control-bar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;visibility:visible;opacity:1;-webkit-transition:visibility .1s,opacity .1s;-moz-transition:visibility .1s,opacity .1s;-ms-transition:visibility .1s,opacity .1s;-o-transition:visibility .1s,opacity .1s;transition:visibility .1s,opacity .1s}.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar{visibility:visible;opacity:0;-webkit-transition:visibility 1s,opacity 1s;-moz-transition:visibility 1s,opacity 1s;-ms-transition:visibility 1s,opacity 1s;-o-transition:visibility 1s,opacity 1s;transition:visibility 1s,opacity 1s}.vjs-controls-disabled .vjs-control-bar,.vjs-error .vjs-control-bar,.vjs-using-native-controls .vjs-control-bar{display:none!important}.vjs-audio.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar{opacity:1;visibility:visible}.vjs-has-started.vjs-no-flex .vjs-control-bar{display:table}.video-js .vjs-control{position:relative;text-align:center;margin:0;padding:0;height:100%;width:4em;-webkit-box-flex:none;-moz-box-flex:none;-webkit-flex:none;-ms-flex:none;flex:none}.vjs-button>.vjs-icon-placeholder:before{font-size:1.8em;line-height:1.67}.video-js .vjs-control:focus,.video-js .vjs-control:focus:before,.video-js .vjs-control:hover:before{text-shadow:0 0 1em #fff}.video-js .vjs-control-text{border:0;clip:rect(0 0 0 0);height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.vjs-no-flex .vjs-control{display:table-cell;vertical-align:middle}.video-js .vjs-custom-control-spacer{display:none}.video-js .vjs-progress-control{cursor:pointer;-webkit-box-flex:auto;-moz-box-flex:auto;-webkit-flex:auto;-ms-flex:auto;flex:auto;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;min-width:4em}.video-js .vjs-progress-control.disabled{cursor:default}.vjs-live .vjs-progress-control{display:none}.vjs-no-flex .vjs-progress-control{width:auto}.video-js .vjs-progress-holder{-webkit-box-flex:auto;-moz-box-flex:auto;-webkit-flex:auto;-ms-flex:auto;flex:auto;-webkit-transition:all .2s;-moz-transition:all .2s;-ms-transition:all .2s;-o-transition:all .2s;transition:all .2s;height:.3em}.video-js .vjs-progress-control .vjs-progress-holder{margin:0 10px}.video-js .vjs-progress-control:hover .vjs-progress-holder{font-size:1.666666666666666666em}.video-js .vjs-progress-control:hover .vjs-progress-holder.disabled{font-size:1em}.video-js .vjs-progress-holder .vjs-load-progress,.video-js .vjs-progress-holder .vjs-load-progress div,.video-js .vjs-progress-holder .vjs-play-progress{position:absolute;display:block;height:100%;margin:0;padding:0;width:0}.video-js .vjs-play-progress{background-color:#fff}.video-js .vjs-play-progress:before{font-size:.9em;position:absolute;right:-.5em;top:-.333333333333333em;z-index:1}.video-js .vjs-load-progress{background:rgba(115,133,159,.5)}.video-js .vjs-load-progress div{background:rgba(115,133,159,.75)}.video-js .vjs-time-tooltip{background-color:#fff;background-color:rgba(255,255,255,.8);-webkit-border-radius:.3em;-moz-border-radius:.3em;border-radius:.3em;color:#000;float:right;font-family:Arial,Helvetica,sans-serif;font-size:1em;padding:6px 8px 8px 8px;pointer-events:none;position:relative;top:-3.4em;visibility:hidden;z-index:1}.video-js .vjs-progress-holder:focus .vjs-time-tooltip{display:none}.video-js .vjs-progress-control:hover .vjs-progress-holder:focus .vjs-time-tooltip,.video-js .vjs-progress-control:hover .vjs-time-tooltip{display:block;font-size:.6em;visibility:visible}.video-js .vjs-progress-control.disabled:hover .vjs-time-tooltip{font-size:1em}.video-js .vjs-progress-control .vjs-mouse-display{display:none;position:absolute;width:1px;height:100%;background-color:#000;z-index:1}.vjs-no-flex .vjs-progress-control .vjs-mouse-display{z-index:0}.video-js .vjs-progress-control:hover .vjs-mouse-display{display:block}.video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display{visibility:hidden;opacity:0;-webkit-transition:visibility 1s,opacity 1s;-moz-transition:visibility 1s,opacity 1s;-ms-transition:visibility 1s,opacity 1s;-o-transition:visibility 1s,opacity 1s;transition:visibility 1s,opacity 1s}.video-js.vjs-user-inactive.vjs-no-flex .vjs-progress-control .vjs-mouse-display{display:none}.vjs-mouse-display .vjs-time-tooltip{color:#fff;background-color:#000;background-color:rgba(0,0,0,.8)}.video-js .vjs-slider{position:relative;cursor:pointer;padding:0;margin:0 .45em 0 .45em;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#73859f;background-color:rgba(115,133,159,.5)}.video-js .vjs-slider.disabled{cursor:default}.video-js .vjs-slider:focus{text-shadow:0 0 1em #fff;-webkit-box-shadow:0 0 1em #fff;-moz-box-shadow:0 0 1em #fff;box-shadow:0 0 1em #fff}.video-js .vjs-mute-control{cursor:pointer;-webkit-box-flex:none;-moz-box-flex:none;-webkit-flex:none;-ms-flex:none;flex:none}.video-js .vjs-volume-control{cursor:pointer;margin-right:1em;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.video-js .vjs-volume-control.vjs-volume-horizontal{width:5em}.video-js .vjs-volume-panel .vjs-volume-control{visibility:visible;opacity:0;width:1px;height:1px;margin-left:-1px}.video-js .vjs-volume-panel{-webkit-transition:width 1s;-moz-transition:width 1s;-ms-transition:width 1s;-o-transition:width 1s;transition:width 1s}.video-js .vjs-volume-panel .vjs-mute-control:hover~.vjs-volume-control,.video-js .vjs-volume-panel .vjs-volume-control.vjs-slider-active,.video-js .vjs-volume-panel .vjs-volume-control:active,.video-js .vjs-volume-panel .vjs-volume-control:hover,.video-js .vjs-volume-panel:active .vjs-volume-control,.video-js .vjs-volume-panel:focus .vjs-volume-control,.video-js .vjs-volume-panel:hover .vjs-volume-control{visibility:visible;opacity:1;position:relative;-webkit-transition:visibility .1s,opacity .1s,height .1s,width .1s,left 0s,top 0s;-moz-transition:visibility .1s,opacity .1s,height .1s,width .1s,left 0s,top 0s;-ms-transition:visibility .1s,opacity .1s,height .1s,width .1s,left 0s,top 0s;-o-transition:visibility .1s,opacity .1s,height .1s,width .1s,left 0s,top 0s;transition:visibility .1s,opacity .1s,height .1s,width .1s,left 0s,top 0s}.video-js .vjs-volume-panel .vjs-mute-control:hover~.vjs-volume-control.vjs-volume-horizontal,.video-js .vjs-volume-panel .vjs-volume-control.vjs-slider-active.vjs-volume-horizontal,.video-js .vjs-volume-panel .vjs-volume-control:active.vjs-volume-horizontal,.video-js .vjs-volume-panel .vjs-volume-control:hover.vjs-volume-horizontal,.video-js .vjs-volume-panel:active .vjs-volume-control.vjs-volume-horizontal,.video-js .vjs-volume-panel:focus .vjs-volume-control.vjs-volume-horizontal,.video-js .vjs-volume-panel:hover .vjs-volume-control.vjs-volume-horizontal{width:5em;height:3em}.video-js .vjs-volume-panel.vjs-volume-panel-horizontal.vjs-slider-active,.video-js .vjs-volume-panel.vjs-volume-panel-horizontal:active,.video-js .vjs-volume-panel.vjs-volume-panel-horizontal:hover{width:9em;-webkit-transition:width .1s;-moz-transition:width .1s;-ms-transition:width .1s;-o-transition:width .1s;transition:width .1s}.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical{height:8em;width:3em;left:-3.5em;-webkit-transition:visibility 1s,opacity 1s,height 1s 1s,width 1s 1s,left 1s 1s,top 1s 1s;-moz-transition:visibility 1s,opacity 1s,height 1s 1s,width 1s 1s,left 1s 1s,top 1s 1s;-ms-transition:visibility 1s,opacity 1s,height 1s 1s,width 1s 1s,left 1s 1s,top 1s 1s;-o-transition:visibility 1s,opacity 1s,height 1s 1s,width 1s 1s,left 1s 1s,top 1s 1s;transition:visibility 1s,opacity 1s,height 1s 1s,width 1s 1s,left 1s 1s,top 1s 1s}.video-js .vjs-volume-panel .vjs-volume-control.vjs-volume-horizontal{-webkit-transition:visibility 1s,opacity 1s,height 1s 1s,width 1s,left 1s 1s,top 1s 1s;-moz-transition:visibility 1s,opacity 1s,height 1s 1s,width 1s,left 1s 1s,top 1s 1s;-ms-transition:visibility 1s,opacity 1s,height 1s 1s,width 1s,left 1s 1s,top 1s 1s;-o-transition:visibility 1s,opacity 1s,height 1s 1s,width 1s,left 1s 1s,top 1s 1s;transition:visibility 1s,opacity 1s,height 1s 1s,width 1s,left 1s 1s,top 1s 1s}.video-js.vjs-no-flex .vjs-volume-panel .vjs-volume-control.vjs-volume-horizontal{width:5em;height:3em;visibility:visible;opacity:1;position:relative;-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}.video-js.vjs-no-flex .vjs-volume-control.vjs-volume-vertical,.video-js.vjs-no-flex .vjs-volume-panel .vjs-volume-control.vjs-volume-vertical{position:absolute;bottom:3em;left:.5em}.video-js .vjs-volume-panel{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.video-js .vjs-volume-bar{margin:1.35em .45em}.vjs-volume-bar.vjs-slider-horizontal{width:5em;height:.3em}.vjs-volume-bar.vjs-slider-vertical{width:.3em;height:5em;margin:1.35em auto}.video-js .vjs-volume-level{position:absolute;bottom:0;left:0;background-color:#fff}.video-js .vjs-volume-level:before{position:absolute;font-size:.9em}.vjs-slider-vertical .vjs-volume-level{width:.3em}.vjs-slider-vertical .vjs-volume-level:before{top:-.5em;left:-.3em}.vjs-slider-horizontal .vjs-volume-level{height:.3em}.vjs-slider-horizontal .vjs-volume-level:before{top:-.3em;right:-.5em}.video-js .vjs-volume-panel.vjs-volume-panel-vertical{width:4em}.vjs-volume-bar.vjs-slider-vertical .vjs-volume-level{height:100%}.vjs-volume-bar.vjs-slider-horizontal .vjs-volume-level{width:100%}.video-js .vjs-volume-vertical{width:3em;height:8em;bottom:8em;background-color:#2b333f;background-color:rgba(43,51,63,.7)}.video-js .vjs-volume-horizontal .vjs-menu{left:-2em}.vjs-poster{display:inline-block;vertical-align:middle;background-repeat:no-repeat;background-position:50% 50%;background-size:contain;background-color:#000;cursor:pointer;margin:0;padding:0;position:absolute;top:0;right:0;bottom:0;left:0;height:100%}.vjs-has-started .vjs-poster{display:none}.vjs-audio.vjs-has-started .vjs-poster{display:block}.vjs-using-native-controls .vjs-poster{display:none}.video-js .vjs-live-control{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:flex-start;-webkit-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-box-flex:auto;-moz-box-flex:auto;-webkit-flex:auto;-ms-flex:auto;flex:auto;font-size:1em;line-height:3em}.vjs-no-flex .vjs-live-control{display:table-cell;width:auto;text-align:left}.video-js .vjs-time-control{-webkit-box-flex:none;-moz-box-flex:none;-webkit-flex:none;-ms-flex:none;flex:none;font-size:1em;line-height:3em;min-width:2em;width:auto;padding-left:1em;padding-right:1em}.vjs-live .vjs-time-control{display:none}.video-js .vjs-current-time,.vjs-no-flex .vjs-current-time{display:none}.video-js .vjs-duration,.vjs-no-flex .vjs-duration{display:none}.vjs-time-divider{display:none;line-height:3em}.vjs-live .vjs-time-divider{display:none}.video-js .vjs-play-control .vjs-icon-placeholder{cursor:pointer;-webkit-box-flex:none;-moz-box-flex:none;-webkit-flex:none;-ms-flex:none;flex:none}.vjs-text-track-display{position:absolute;bottom:3em;left:0;right:0;top:0;pointer-events:none}.video-js.vjs-user-inactive.vjs-playing .vjs-text-track-display{bottom:1em}.video-js .vjs-text-track{font-size:1.4em;text-align:center;margin-bottom:.1em}.vjs-subtitles{color:#fff}.vjs-captions{color:#fc6}.vjs-tt-cue{display:block}video::-webkit-media-text-track-display{-moz-transform:translateY(-3em);-ms-transform:translateY(-3em);-o-transform:translateY(-3em);-webkit-transform:translateY(-3em);transform:translateY(-3em)}.video-js.vjs-user-inactive.vjs-playing video::-webkit-media-text-track-display{-moz-transform:translateY(-1.5em);-ms-transform:translateY(-1.5em);-o-transform:translateY(-1.5em);-webkit-transform:translateY(-1.5em);transform:translateY(-1.5em)}.video-js .vjs-fullscreen-control{cursor:pointer;-webkit-box-flex:none;-moz-box-flex:none;-webkit-flex:none;-ms-flex:none;flex:none}.vjs-playback-rate .vjs-playback-rate-value,.vjs-playback-rate>.vjs-menu-button{position:absolute;top:0;left:0;width:100%;height:100%}.vjs-playback-rate .vjs-playback-rate-value{pointer-events:none;font-size:1.5em;line-height:2;text-align:center}.vjs-playback-rate .vjs-menu{width:4em;left:0}.vjs-error .vjs-error-display .vjs-modal-dialog-content{font-size:1.4em;text-align:center}.vjs-error .vjs-error-display:before{color:#fff;content:'X';font-family:Arial,Helvetica,sans-serif;font-size:4em;left:0;line-height:1;margin-top:-.5em;position:absolute;text-shadow:.05em .05em .1em #000;text-align:center;top:50%;vertical-align:middle;width:100%}.vjs-loading-spinner{display:none;position:absolute;top:50%;left:50%;margin:-25px 0 0 -25px;opacity:.85;text-align:left;border:6px solid rgba(43,51,63,.7);box-sizing:border-box;background-clip:padding-box;width:50px;height:50px;border-radius:25px;visibility:hidden}.vjs-seeking .vjs-loading-spinner,.vjs-waiting .vjs-loading-spinner{display:block;animation:0s linear .3s forwards vjs-spinner-show}.vjs-loading-spinner:after,.vjs-loading-spinner:before{content:"";position:absolute;margin:-6px;box-sizing:inherit;width:inherit;height:inherit;border-radius:inherit;opacity:1;border:inherit;border-color:transparent;border-top-color:#fff}.vjs-seeking .vjs-loading-spinner:after,.vjs-seeking .vjs-loading-spinner:before,.vjs-waiting .vjs-loading-spinner:after,.vjs-waiting .vjs-loading-spinner:before{-webkit-animation:vjs-spinner-spin 1.1s cubic-bezier(.6,.2,0,.8) infinite,vjs-spinner-fade 1.1s linear infinite;animation:vjs-spinner-spin 1.1s cubic-bezier(.6,.2,0,.8) infinite,vjs-spinner-fade 1.1s linear infinite}.vjs-seeking .vjs-loading-spinner:before,.vjs-waiting .vjs-loading-spinner:before{border-top-color:#fff}.vjs-seeking .vjs-loading-spinner:after,.vjs-waiting .vjs-loading-spinner:after{border-top-color:#fff;-webkit-animation-delay:.44s;animation-delay:.44s}@keyframes vjs-spinner-show{to{visibility:visible}}@-webkit-keyframes vjs-spinner-show{to{visibility:visible}}@keyframes vjs-spinner-spin{100%{transform:rotate(360deg)}}@-webkit-keyframes vjs-spinner-spin{100%{-webkit-transform:rotate(360deg)}}@keyframes vjs-spinner-fade{0%{border-top-color:#73859f}20%{border-top-color:#73859f}35%{border-top-color:#fff}60%{border-top-color:#73859f}100%{border-top-color:#73859f}}@-webkit-keyframes vjs-spinner-fade{0%{border-top-color:#73859f}20%{border-top-color:#73859f}35%{border-top-color:#fff}60%{border-top-color:#73859f}100%{border-top-color:#73859f}}.vjs-chapters-button .vjs-menu ul{width:24em}.video-js .vjs-subs-caps-button+.vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder{position:absolute}.video-js .vjs-subs-caps-button+.vjs-menu .vjs-captions-menu-item .vjs-menu-item-text .vjs-icon-placeholder:before{font-family:VideoJS;content:"\f10d";font-size:1.5em;line-height:inherit}.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-custom-control-spacer{-webkit-box-flex:auto;-moz-box-flex:auto;-webkit-flex:auto;-ms-flex:auto;flex:auto}.video-js.vjs-layout-tiny:not(.vjs-fullscreen).vjs-no-flex .vjs-custom-control-spacer{width:auto}.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-audio-button,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-captions-button,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-chapters-button,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-current-time,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-descriptions-button,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-duration,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-mute-control,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-playback-rate,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-progress-control,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-remaining-time,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-subtitles-button,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-time-divider,.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-volume-control{display:none}.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-audio-button,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-captions-button,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-chapters-button,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-current-time,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-descriptions-button,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-duration,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-mute-control,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-playback-rate,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-remaining-time,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-subtitles-button,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-time-divider,.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-volume-control{display:none}.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-captions-button,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-chapters-button,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-current-time,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-descriptions-button,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-duration,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-mute-control,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-playback-rate,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-remaining-time,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-subtitles-button .vjs-audio-button,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-time-divider,.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-volume-control{display:none}.vjs-modal-dialog.vjs-text-track-settings{background-color:#2b333f;background-color:rgba(43,51,63,.75);color:#fff;height:70%}.vjs-text-track-settings .vjs-modal-dialog-content{display:table}.vjs-text-track-settings .vjs-track-settings-colors,.vjs-text-track-settings .vjs-track-settings-controls,.vjs-text-track-settings .vjs-track-settings-font{display:table-cell}.vjs-text-track-settings .vjs-track-settings-controls{text-align:right;vertical-align:bottom}@supports (display:grid){.vjs-text-track-settings .vjs-modal-dialog-content{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr auto}.vjs-text-track-settings .vjs-track-settings-colors{display:block;grid-column:1;grid-row:1}.vjs-text-track-settings .vjs-track-settings-font{grid-column:2;grid-row:1}.vjs-text-track-settings .vjs-track-settings-controls{grid-column:2;grid-row:2}}.vjs-track-setting>select{margin-right:5px}.vjs-text-track-settings fieldset{margin:5px;padding:3px;border:none}.vjs-text-track-settings fieldset span{display:inline-block}.vjs-text-track-settings legend{color:#fff;margin:0 0 5px 0}.vjs-text-track-settings .vjs-label{position:absolute;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);display:block;margin:0 0 5px 0;padding:0;border:0;height:1px;width:1px;overflow:hidden}.vjs-track-settings-controls button:active,.vjs-track-settings-controls button:focus{outline-style:solid;outline-width:medium;background-image:linear-gradient(0deg,#fff 88%,#73859f 100%)}.vjs-track-settings-controls button:hover{color:rgba(43,51,63,.75)}.vjs-track-settings-controls button{background-color:#fff;background-image:linear-gradient(-180deg,#fff 88%,#73859f 100%);color:#2b333f;cursor:pointer;border-radius:2px}.vjs-track-settings-controls .vjs-default-button{margin-right:1em}@media print{.video-js>:not(.vjs-tech):not(.vjs-poster){visibility:hidden}}.vjs-resize-manager{position:absolute;top:0;left:0;width:100%;height:100%;border:none;visibility:hidden} diff --git a/form/src/assets/libs/video-js-7.0.0/video.js b/form/src/assets/libs/video-js-7.0.0/video.js new file mode 100644 index 0000000..7fbbd14 --- /dev/null +++ b/form/src/assets/libs/video-js-7.0.0/video.js @@ -0,0 +1,47623 @@ +/** + * @license + * Video.js 7.0.0 <http://videojs.com/> + * Copyright Brightcove, Inc. <https://www.brightcove.com/> + * Available under Apache License Version 2.0 + * <https://github.com/videojs/video.js/blob/master/LICENSE> + * + * Includes vtt.js <https://github.com/mozilla/vtt.js> + * Available under Apache License Version 2.0 + * <https://github.com/mozilla/vtt.js/blob/master/LICENSE> + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.videojs = factory()); +}(this, (function () { + + var version = "7.0.0"; + + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = {exports: {}}, fn(module, module.exports), module.exports; + } + + var win; + + if (typeof window !== "undefined") { + win = window; + } else if (typeof commonjsGlobal !== "undefined") { + win = commonjsGlobal; + } else if (typeof self !== "undefined") { + win = self; + } else { + win = {}; + } + + var window_1 = win; + + var empty = {}; + + var empty$1 = /*#__PURE__*/Object.freeze({ + default: empty + }); + + var minDoc = (empty$1 && empty) || empty$1; + + var topLevel = typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof window !== 'undefined' ? window : {}; + + var doccy; + + if (typeof document !== 'undefined') { + doccy = document; + } else { + doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; + + if (!doccy) { + doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; + } + } + + var document_1 = doccy; + + /** + * @file log.js + * @module log + */ + + var log = void 0; + + // This is the private tracking variable for logging level. + var level = 'info'; + + // This is the private tracking variable for the logging history. + var history = []; + + /** + * Log messages to the console and history based on the type of message + * + * @private + * @param {string} type + * The name of the console method to use. + * + * @param {Array} args + * The arguments to be passed to the matching console method. + */ + var logByType = function logByType(type, args) { + var lvl = log.levels[level]; + var lvlRegExp = new RegExp('^(' + lvl + ')$'); + + if (type !== 'log') { + + // Add the type to the front of the message when it's not "log". + args.unshift(type.toUpperCase() + ':'); + } + + // Add a clone of the args at this point to history. + if (history) { + history.push([].concat(args)); + } + + // Add console prefix after adding to history. + args.unshift('VIDEOJS:'); + + // If there's no console then don't try to output messages, but they will + // still be stored in history. + if (!window_1.console) { + return; + } + + // Was setting these once outside of this function, but containing them + // in the function makes it easier to test cases where console doesn't exist + // when the module is executed. + var fn = window_1.console[type]; + + if (!fn && type === 'debug') { + // Certain browsers don't have support for console.debug. For those, we + // should default to the closest comparable log. + fn = window_1.console.info || window_1.console.log; + } + + // Bail out if there's no console or if this type is not allowed by the + // current logging level. + if (!fn || !lvl || !lvlRegExp.test(type)) { + return; + } + + fn[Array.isArray(args) ? 'apply' : 'call'](window_1.console, args); + }; + + /** + * Logs plain debug messages. Similar to `console.log`. + * + * @class + * @param {Mixed[]} args + * One or more messages or objects that should be logged. + */ + log = function log() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + logByType('log', args); + }; + + /** + * Enumeration of available logging levels, where the keys are the level names + * and the values are `|`-separated strings containing logging methods allowed + * in that logging level. These strings are used to create a regular expression + * matching the function name being called. + * + * Levels provided by video.js are: + * + * - `off`: Matches no calls. Any value that can be cast to `false` will have + * this effect. The most restrictive. + * - `all`: Matches only Video.js-provided functions (`debug`, `log`, + * `log.warn`, and `log.error`). + * - `debug`: Matches `log.debug`, `log`, `log.warn`, and `log.error` calls. + * - `info` (default): Matches `log`, `log.warn`, and `log.error` calls. + * - `warn`: Matches `log.warn` and `log.error` calls. + * - `error`: Matches only `log.error` calls. + * + * @type {Object} + */ + log.levels = { + all: 'debug|log|warn|error', + off: '', + debug: 'debug|log|warn|error', + info: 'log|warn|error', + warn: 'warn|error', + error: 'error', + DEFAULT: level + }; + + /** + * Get or set the current logging level. If a string matching a key from + * {@link log.levels} is provided, acts as a setter. Regardless of argument, + * returns the current logging level. + * + * @param {string} [lvl] + * Pass to set a new logging level. + * + * @return {string} + * The current logging level. + */ + log.level = function (lvl) { + if (typeof lvl === 'string') { + if (!log.levels.hasOwnProperty(lvl)) { + throw new Error('"' + lvl + '" in not a valid log level'); + } + level = lvl; + } + return level; + }; + + /** + * Returns an array containing everything that has been logged to the history. + * + * This array is a shallow clone of the internal history record. However, its + * contents are _not_ cloned; so, mutating objects inside this array will + * mutate them in history. + * + * @return {Array} + */ + log.history = function () { + return history ? [].concat(history) : []; + }; + + /** + * Clears the internal history tracking, but does not prevent further history + * tracking. + */ + log.history.clear = function () { + if (history) { + history.length = 0; + } + }; + + /** + * Disable history tracking if it is currently enabled. + */ + log.history.disable = function () { + if (history !== null) { + history.length = 0; + history = null; + } + }; + + /** + * Enable history tracking if it is currently disabled. + */ + log.history.enable = function () { + if (history === null) { + history = []; + } + }; + + /** + * Logs error messages. Similar to `console.error`. + * + * @param {Mixed[]} args + * One or more messages or objects that should be logged as an error + */ + log.error = function () { + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + return logByType('error', args); + }; + + /** + * Logs warning messages. Similar to `console.warn`. + * + * @param {Mixed[]} args + * One or more messages or objects that should be logged as a warning. + */ + log.warn = function () { + for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + args[_key3] = arguments[_key3]; + } + + return logByType('warn', args); + }; + + /** + * Logs debug messages. Similar to `console.debug`, but may also act as a comparable + * log if `console.debug` is not available + * + * @param {Mixed[]} args + * One or more messages or objects that should be logged as debug. + */ + log.debug = function () { + for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; + } + + return logByType('debug', args); + }; + + var log$1 = log; + + function clean(s) { + return s.replace(/\n\r?\s*/g, ''); + } + + var tsml = function tsml(sa) { + var s = '', + i = 0; + + for (; i < arguments.length; i++) { + s += clean(sa[i]) + (arguments[i + 1] || ''); + } + return s; + }; + + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + + var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + }; + + var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; + }; + + var taggedTemplateLiteralLoose = function (strings, raw) { + strings.raw = raw; + return strings; + }; + + /** + * @file obj.js + * @module obj + */ + + /** + * @callback obj:EachCallback + * + * @param {Mixed} value + * The current key for the object that is being iterated over. + * + * @param {string} key + * The current key-value for object that is being iterated over + */ + + /** + * @callback obj:ReduceCallback + * + * @param {Mixed} accum + * The value that is accumulating over the reduce loop. + * + * @param {Mixed} value + * The current key for the object that is being iterated over. + * + * @param {string} key + * The current key-value for object that is being iterated over + * + * @return {Mixed} + * The new accumulated value. + */ + var toString = Object.prototype.toString; + + /** + * Get the keys of an Object + * + * @param {Object} + * The Object to get the keys from + * + * @return {string[]} + * An array of the keys from the object. Returns an empty array if the + * object passed in was invalid or had no keys. + * + * @private + */ + var keys = function keys(object) { + return isObject(object) ? Object.keys(object) : []; + }; + + /** + * Array-like iteration for objects. + * + * @param {Object} object + * The object to iterate over + * + * @param {obj:EachCallback} fn + * The callback function which is called for each key in the object. + */ + function each(object, fn) { + keys(object).forEach(function (key) { + return fn(object[key], key); + }); + } + + /** + * Array-like reduce for objects. + * + * @param {Object} object + * The Object that you want to reduce. + * + * @param {Function} fn + * A callback function which is called for each key in the object. It + * receives the accumulated value and the per-iteration value and key + * as arguments. + * + * @param {Mixed} [initial = 0] + * Starting value + * + * @return {Mixed} + * The final accumulated value. + */ + function reduce(object, fn) { + var initial = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + + return keys(object).reduce(function (accum, key) { + return fn(accum, object[key], key); + }, initial); + } + + /** + * Object.assign-style object shallow merge/extend. + * + * @param {Object} target + * @param {Object} ...sources + * @return {Object} + */ + function assign(target) { + for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + sources[_key - 1] = arguments[_key]; + } + + if (Object.assign) { + return Object.assign.apply(Object, [target].concat(sources)); + } + + sources.forEach(function (source) { + if (!source) { + return; + } + + each(source, function (value, key) { + target[key] = value; + }); + }); + + return target; + } + + /** + * Returns whether a value is an object of any kind - including DOM nodes, + * arrays, regular expressions, etc. Not functions, though. + * + * This avoids the gotcha where using `typeof` on a `null` value + * results in `'object'`. + * + * @param {Object} value + * @return {Boolean} + */ + function isObject(value) { + return !!value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object'; + } + + /** + * Returns whether an object appears to be a "plain" object - that is, a + * direct instance of `Object`. + * + * @param {Object} value + * @return {Boolean} + */ + function isPlain(value) { + return isObject(value) && toString.call(value) === '[object Object]' && value.constructor === Object; + } + + /** + * @file computed-style.js + * @module computed-style + */ + + /** + * A safe getComputedStyle. + * + * This is needed because in Firefox, if the player is loaded in an iframe with + * `display:none`, then `getComputedStyle` returns `null`, so, we do a null-check to + * make sure that the player doesn't break in these cases. + * + * @param {Element} el + * The element you want the computed style of + * + * @param {string} prop + * The property name you want + * + * @see https://bugzilla.mozilla.org/show_bug.cgi?id=548397 + * + * @static + * @const + */ + function computedStyle(el, prop) { + if (!el || !prop) { + return ''; + } + + if (typeof window_1.getComputedStyle === 'function') { + var cs = window_1.getComputedStyle(el); + + return cs ? cs[prop] : ''; + } + + return ''; + } + + var _templateObject = taggedTemplateLiteralLoose(['Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set ', ' to ', '.'], ['Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set ', ' to ', '.']); + + /** + * Detect if a value is a string with any non-whitespace characters. + * + * @param {string} str + * The string to check + * + * @return {boolean} + * - True if the string is non-blank + * - False otherwise + * + */ + function isNonBlankString(str) { + return typeof str === 'string' && /\S/.test(str); + } + + /** + * Throws an error if the passed string has whitespace. This is used by + * class methods to be relatively consistent with the classList API. + * + * @param {string} str + * The string to check for whitespace. + * + * @throws {Error} + * Throws an error if there is whitespace in the string. + * + */ + function throwIfWhitespace(str) { + if (/\s/.test(str)) { + throw new Error('class has illegal whitespace characters'); + } + } + + /** + * Produce a regular expression for matching a className within an elements className. + * + * @param {string} className + * The className to generate the RegExp for. + * + * @return {RegExp} + * The RegExp that will check for a specific `className` in an elements + * className. + */ + function classRegExp(className) { + return new RegExp('(^|\\s)' + className + '($|\\s)'); + } + + /** + * Whether the current DOM interface appears to be real. + * + * @return {Boolean} + */ + function isReal() { + // Both document and window will never be undefined thanks to `global`. + return document_1 === window_1.document; + } + + /** + * Determines, via duck typing, whether or not a value is a DOM element. + * + * @param {Mixed} value + * The thing to check + * + * @return {boolean} + * - True if it is a DOM element + * - False otherwise + */ + function isEl(value) { + return isObject(value) && value.nodeType === 1; + } + + /** + * Determines if the current DOM is embedded in an iframe. + * + * @return {boolean} + * + */ + function isInFrame() { + + // We need a try/catch here because Safari will throw errors when attempting + // to get either `parent` or `self` + try { + return window_1.parent !== window_1.self; + } catch (x) { + return true; + } + } + + /** + * Creates functions to query the DOM using a given method. + * + * @param {string} method + * The method to create the query with. + * + * @return {Function} + * The query method + */ + function createQuerier(method) { + return function (selector, context) { + if (!isNonBlankString(selector)) { + return document_1[method](null); + } + if (isNonBlankString(context)) { + context = document_1.querySelector(context); + } + + var ctx = isEl(context) ? context : document_1; + + return ctx[method] && ctx[method](selector); + }; + } + + /** + * Creates an element and applies properties. + * + * @param {string} [tagName='div'] + * Name of tag to be created. + * + * @param {Object} [properties={}] + * Element properties to be applied. + * + * @param {Object} [attributes={}] + * Element attributes to be applied. + * + * @param {String|Element|TextNode|Array|Function} [content] + * Contents for the element (see: {@link dom:normalizeContent}) + * + * @return {Element} + * The element that was created. + */ + function createEl() { + var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div'; + var properties = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var content = arguments[3]; + + var el = document_1.createElement(tagName); + + Object.getOwnPropertyNames(properties).forEach(function (propName) { + var val = properties[propName]; + + // See #2176 + // We originally were accepting both properties and attributes in the + // same object, but that doesn't work so well. + if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') { + log$1.warn(tsml(_templateObject, propName, val)); + el.setAttribute(propName, val); + + // Handle textContent since it's not supported everywhere and we have a + // method for it. + } else if (propName === 'textContent') { + textContent(el, val); + } else { + el[propName] = val; + } + }); + + Object.getOwnPropertyNames(attributes).forEach(function (attrName) { + el.setAttribute(attrName, attributes[attrName]); + }); + + if (content) { + appendContent(el, content); + } + + return el; + } + + /** + * Injects text into an element, replacing any existing contents entirely. + * + * @param {Element} el + * The element to add text content into + * + * @param {string} text + * The text content to add. + * + * @return {Element} + * The element with added text content. + */ + function textContent(el, text) { + if (typeof el.textContent === 'undefined') { + el.innerText = text; + } else { + el.textContent = text; + } + return el; + } + + /** + * Insert an element as the first child node of another + * + * @param {Element} child + * Element to insert + * + * @param {Element} parent + * Element to insert child into + */ + function prependTo(child, parent) { + if (parent.firstChild) { + parent.insertBefore(child, parent.firstChild); + } else { + parent.appendChild(child); + } + } + + /** + * Check if an element has a CSS class + * + * @param {Element} element + * Element to check + * + * @param {string} classToCheck + * Class name to check for + * + * @return {boolean} + * - True if the element had the class + * - False otherwise. + * + * @throws {Error} + * Throws an error if `classToCheck` has white space. + */ + function hasClass(element, classToCheck) { + throwIfWhitespace(classToCheck); + if (element.classList) { + return element.classList.contains(classToCheck); + } + return classRegExp(classToCheck).test(element.className); + } + + /** + * Add a CSS class name to an element + * + * @param {Element} element + * Element to add class name to. + * + * @param {string} classToAdd + * Class name to add. + * + * @return {Element} + * The dom element with the added class name. + */ + function addClass(element, classToAdd) { + if (element.classList) { + element.classList.add(classToAdd); + + // Don't need to `throwIfWhitespace` here because `hasElClass` will do it + // in the case of classList not being supported. + } else if (!hasClass(element, classToAdd)) { + element.className = (element.className + ' ' + classToAdd).trim(); + } + + return element; + } + + /** + * Remove a CSS class name from an element + * + * @param {Element} element + * Element to remove a class name from. + * + * @param {string} classToRemove + * Class name to remove + * + * @return {Element} + * The dom element with class name removed. + */ + function removeClass(element, classToRemove) { + if (element.classList) { + element.classList.remove(classToRemove); + } else { + throwIfWhitespace(classToRemove); + element.className = element.className.split(/\s+/).filter(function (c) { + return c !== classToRemove; + }).join(' '); + } + + return element; + } + + /** + * The callback definition for toggleElClass. + * + * @callback Dom~PredicateCallback + * @param {Element} element + * The DOM element of the Component. + * + * @param {string} classToToggle + * The `className` that wants to be toggled + * + * @return {boolean|undefined} + * - If true the `classToToggle` will get added to `element`. + * - If false the `classToToggle` will get removed from `element`. + * - If undefined this callback will be ignored + */ + + /** + * Adds or removes a CSS class name on an element depending on an optional + * condition or the presence/absence of the class name. + * + * @param {Element} element + * The element to toggle a class name on. + * + * @param {string} classToToggle + * The class that should be toggled + * + * @param {boolean|PredicateCallback} [predicate] + * See the return value for {@link Dom~PredicateCallback} + * + * @return {Element} + * The element with a class that has been toggled. + */ + function toggleClass(element, classToToggle, predicate) { + + // This CANNOT use `classList` internally because IE11 does not support the + // second parameter to the `classList.toggle()` method! Which is fine because + // `classList` will be used by the add/remove functions. + var has = hasClass(element, classToToggle); + + if (typeof predicate === 'function') { + predicate = predicate(element, classToToggle); + } + + if (typeof predicate !== 'boolean') { + predicate = !has; + } + + // If the necessary class operation matches the current state of the + // element, no action is required. + if (predicate === has) { + return; + } + + if (predicate) { + addClass(element, classToToggle); + } else { + removeClass(element, classToToggle); + } + + return element; + } + + /** + * Apply attributes to an HTML element. + * + * @param {Element} el + * Element to add attributes to. + * + * @param {Object} [attributes] + * Attributes to be applied. + */ + function setAttributes(el, attributes) { + Object.getOwnPropertyNames(attributes).forEach(function (attrName) { + var attrValue = attributes[attrName]; + + if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) { + el.removeAttribute(attrName); + } else { + el.setAttribute(attrName, attrValue === true ? '' : attrValue); + } + }); + } + + /** + * Get an element's attribute values, as defined on the HTML tag + * Attributes are not the same as properties. They're defined on the tag + * or with setAttribute (which shouldn't be used with HTML) + * This will return true or false for boolean attributes. + * + * @param {Element} tag + * Element from which to get tag attributes. + * + * @return {Object} + * All attributes of the element. + */ + function getAttributes(tag) { + var obj = {}; + + // known boolean attributes + // we can check for matching boolean properties, but not all browsers + // and not all tags know about these attributes, so, we still want to check them manually + var knownBooleans = ',' + 'autoplay,controls,playsinline,loop,muted,default,defaultMuted' + ','; + + if (tag && tag.attributes && tag.attributes.length > 0) { + var attrs = tag.attributes; + + for (var i = attrs.length - 1; i >= 0; i--) { + var attrName = attrs[i].name; + var attrVal = attrs[i].value; + + // check for known booleans + // the matching element property will return a value for typeof + if (typeof tag[attrName] === 'boolean' || knownBooleans.indexOf(',' + attrName + ',') !== -1) { + // the value of an included boolean attribute is typically an empty + // string ('') which would equal false if we just check for a false value. + // we also don't want support bad code like autoplay='false' + attrVal = attrVal !== null ? true : false; + } + + obj[attrName] = attrVal; + } + } + + return obj; + } + + /** + * Get the value of an element's attribute + * + * @param {Element} el + * A DOM element + * + * @param {string} attribute + * Attribute to get the value of + * + * @return {string} + * value of the attribute + */ + function getAttribute(el, attribute) { + return el.getAttribute(attribute); + } + + /** + * Set the value of an element's attribute + * + * @param {Element} el + * A DOM element + * + * @param {string} attribute + * Attribute to set + * + * @param {string} value + * Value to set the attribute to + */ + function setAttribute(el, attribute, value) { + el.setAttribute(attribute, value); + } + + /** + * Remove an element's attribute + * + * @param {Element} el + * A DOM element + * + * @param {string} attribute + * Attribute to remove + */ + function removeAttribute(el, attribute) { + el.removeAttribute(attribute); + } + + /** + * Attempt to block the ability to select text while dragging controls + */ + function blockTextSelection() { + document_1.body.focus(); + document_1.onselectstart = function () { + return false; + }; + } + + /** + * Turn off text selection blocking + */ + function unblockTextSelection() { + document_1.onselectstart = function () { + return true; + }; + } + + /** + * Identical to the native `getBoundingClientRect` function, but ensures that + * the method is supported at all (it is in all browsers we claim to support) + * and that the element is in the DOM before continuing. + * + * This wrapper function also shims properties which are not provided by some + * older browsers (namely, IE8). + * + * Additionally, some browsers do not support adding properties to a + * `ClientRect`/`DOMRect` object; so, we shallow-copy it with the standard + * properties (except `x` and `y` which are not widely supported). This helps + * avoid implementations where keys are non-enumerable. + * + * @param {Element} el + * Element whose `ClientRect` we want to calculate. + * + * @return {Object|undefined} + * Always returns a plain + */ + function getBoundingClientRect(el) { + if (el && el.getBoundingClientRect && el.parentNode) { + var rect = el.getBoundingClientRect(); + var result = {}; + + ['bottom', 'height', 'left', 'right', 'top', 'width'].forEach(function (k) { + if (rect[k] !== undefined) { + result[k] = rect[k]; + } + }); + + if (!result.height) { + result.height = parseFloat(computedStyle(el, 'height')); + } + + if (!result.width) { + result.width = parseFloat(computedStyle(el, 'width')); + } + + return result; + } + } + + /** + * The postion of a DOM element on the page. + * + * @typedef {Object} module:dom~Position + * + * @property {number} left + * Pixels to the left + * + * @property {number} top + * Pixels on top + */ + + /** + * Offset Left. + * getBoundingClientRect technique from + * John Resig + * + * @see http://ejohn.org/blog/getboundingclientrect-is-awesome/ + * + * @param {Element} el + * Element from which to get offset + * + * @return {module:dom~Position} + * The position of the element that was passed in. + */ + function findPosition(el) { + var box = void 0; + + if (el.getBoundingClientRect && el.parentNode) { + box = el.getBoundingClientRect(); + } + + if (!box) { + return { + left: 0, + top: 0 + }; + } + + var docEl = document_1.documentElement; + var body = document_1.body; + + var clientLeft = docEl.clientLeft || body.clientLeft || 0; + var scrollLeft = window_1.pageXOffset || body.scrollLeft; + var left = box.left + scrollLeft - clientLeft; + + var clientTop = docEl.clientTop || body.clientTop || 0; + var scrollTop = window_1.pageYOffset || body.scrollTop; + var top = box.top + scrollTop - clientTop; + + // Android sometimes returns slightly off decimal values, so need to round + return { + left: Math.round(left), + top: Math.round(top) + }; + } + + /** + * x and y coordinates for a dom element or mouse pointer + * + * @typedef {Object} Dom~Coordinates + * + * @property {number} x + * x coordinate in pixels + * + * @property {number} y + * y coordinate in pixels + */ + + /** + * Get pointer position in element + * Returns an object with x and y coordinates. + * The base on the coordinates are the bottom left of the element. + * + * @param {Element} el + * Element on which to get the pointer position on + * + * @param {EventTarget~Event} event + * Event object + * + * @return {Dom~Coordinates} + * A Coordinates object corresponding to the mouse position. + * + */ + function getPointerPosition(el, event) { + var position = {}; + var box = findPosition(el); + var boxW = el.offsetWidth; + var boxH = el.offsetHeight; + + var boxY = box.top; + var boxX = box.left; + var pageY = event.pageY; + var pageX = event.pageX; + + if (event.changedTouches) { + pageX = event.changedTouches[0].pageX; + pageY = event.changedTouches[0].pageY; + } + + position.y = Math.max(0, Math.min(1, (boxY - pageY + boxH) / boxH)); + position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW)); + + return position; + } + + /** + * Determines, via duck typing, whether or not a value is a text node. + * + * @param {Mixed} value + * Check if this value is a text node. + * + * @return {boolean} + * - True if it is a text node + * - False otherwise + */ + function isTextNode(value) { + return isObject(value) && value.nodeType === 3; + } + + /** + * Empties the contents of an element. + * + * @param {Element} el + * The element to empty children from + * + * @return {Element} + * The element with no children + */ + function emptyEl(el) { + while (el.firstChild) { + el.removeChild(el.firstChild); + } + return el; + } + + /** + * Normalizes content for eventual insertion into the DOM. + * + * This allows a wide range of content definition methods, but protects + * from falling into the trap of simply writing to `innerHTML`, which is + * an XSS concern. + * + * The content for an element can be passed in multiple types and + * combinations, whose behavior is as follows: + * + * @param {String|Element|TextNode|Array|Function} content + * - String: Normalized into a text node. + * - Element/TextNode: Passed through. + * - Array: A one-dimensional array of strings, elements, nodes, or functions + * (which return single strings, elements, or nodes). + * - Function: If the sole argument, is expected to produce a string, element, + * node, or array as defined above. + * + * @return {Array} + * All of the content that was passed in normalized. + */ + function normalizeContent(content) { + + // First, invoke content if it is a function. If it produces an array, + // that needs to happen before normalization. + if (typeof content === 'function') { + content = content(); + } + + // Next up, normalize to an array, so one or many items can be normalized, + // filtered, and returned. + return (Array.isArray(content) ? content : [content]).map(function (value) { + + // First, invoke value if it is a function to produce a new value, + // which will be subsequently normalized to a Node of some kind. + if (typeof value === 'function') { + value = value(); + } + + if (isEl(value) || isTextNode(value)) { + return value; + } + + if (typeof value === 'string' && /\S/.test(value)) { + return document_1.createTextNode(value); + } + }).filter(function (value) { + return value; + }); + } + + /** + * Normalizes and appends content to an element. + * + * @param {Element} el + * Element to append normalized content to. + * + * + * @param {String|Element|TextNode|Array|Function} content + * See the `content` argument of {@link dom:normalizeContent} + * + * @return {Element} + * The element with appended normalized content. + */ + function appendContent(el, content) { + normalizeContent(content).forEach(function (node) { + return el.appendChild(node); + }); + return el; + } + + /** + * Normalizes and inserts content into an element; this is identical to + * `appendContent()`, except it empties the element first. + * + * @param {Element} el + * Element to insert normalized content into. + * + * @param {String|Element|TextNode|Array|Function} content + * See the `content` argument of {@link dom:normalizeContent} + * + * @return {Element} + * The element with inserted normalized content. + * + */ + function insertContent(el, content) { + return appendContent(emptyEl(el), content); + } + + /** + * Check if event was a single left click + * + * @param {EventTarget~Event} event + * Event object + * + * @return {boolean} + * - True if a left click + * - False if not a left click + */ + function isSingleLeftClick(event) { + // Note: if you create something draggable, be sure to + // call it on both `mousedown` and `mousemove` event, + // otherwise `mousedown` should be enough for a button + + if (event.button === undefined && event.buttons === undefined) { + // Why do we need `buttons` ? + // Because, middle mouse sometimes have this: + // e.button === 0 and e.buttons === 4 + // Furthermore, we want to prevent combination click, something like + // HOLD middlemouse then left click, that would be + // e.button === 0, e.buttons === 5 + // just `button` is not gonna work + + // Alright, then what this block does ? + // this is for chrome `simulate mobile devices` + // I want to support this as well + + return true; + } + + if (event.button === 0 && event.buttons === undefined) { + // Touch screen, sometimes on some specific device, `buttons` + // doesn't have anything (safari on ios, blackberry...) + + return true; + } + + if (event.button !== 0 || event.buttons !== 1) { + // This is the reason we have those if else block above + // if any special case we can catch and let it slide + // we do it above, when get to here, this definitely + // is-not-left-click + + return false; + } + + return true; + } + + /** + * Finds a single DOM element matching `selector` within the optional + * `context` of another DOM element (defaulting to `document`). + * + * @param {string} selector + * A valid CSS selector, which will be passed to `querySelector`. + * + * @param {Element|String} [context=document] + * A DOM element within which to query. Can also be a selector + * string in which case the first matching element will be used + * as context. If missing (or no element matches selector), falls + * back to `document`. + * + * @return {Element|null} + * The element that was found or null. + */ + var $ = createQuerier('querySelector'); + + /** + * Finds a all DOM elements matching `selector` within the optional + * `context` of another DOM element (defaulting to `document`). + * + * @param {string} selector + * A valid CSS selector, which will be passed to `querySelectorAll`. + * + * @param {Element|String} [context=document] + * A DOM element within which to query. Can also be a selector + * string in which case the first matching element will be used + * as context. If missing (or no element matches selector), falls + * back to `document`. + * + * @return {NodeList} + * A element list of elements that were found. Will be empty if none were found. + * + */ + var $$ = createQuerier('querySelectorAll'); + + var Dom = /*#__PURE__*/Object.freeze({ + isReal: isReal, + isEl: isEl, + isInFrame: isInFrame, + createEl: createEl, + textContent: textContent, + prependTo: prependTo, + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + toggleClass: toggleClass, + setAttributes: setAttributes, + getAttributes: getAttributes, + getAttribute: getAttribute, + setAttribute: setAttribute, + removeAttribute: removeAttribute, + blockTextSelection: blockTextSelection, + unblockTextSelection: unblockTextSelection, + getBoundingClientRect: getBoundingClientRect, + findPosition: findPosition, + getPointerPosition: getPointerPosition, + isTextNode: isTextNode, + emptyEl: emptyEl, + normalizeContent: normalizeContent, + appendContent: appendContent, + insertContent: insertContent, + isSingleLeftClick: isSingleLeftClick, + $: $, + $$: $$ + }); + + /** + * @file guid.js + * @module guid + */ + + /** + * Unique ID for an element or function + * @type {Number} + */ + var _guid = 1; + + /** + * Get a unique auto-incrementing ID by number that has not been returned before. + * + * @return {number} + * A new unique ID. + */ + function newGUID() { + return _guid++; + } + + /** + * @file dom-data.js + * @module dom-data + */ + + /** + * Element Data Store. + * + * Allows for binding data to an element without putting it directly on the + * element. Ex. Event listeners are stored here. + * (also from jsninja.com, slightly modified and updated for closure compiler) + * + * @type {Object} + * @private + */ + var elData = {}; + + /* + * Unique attribute name to store an element's guid in + * + * @type {String} + * @constant + * @private + */ + var elIdAttr = 'vdata' + new Date().getTime(); + + /** + * Returns the cache object where data for an element is stored + * + * @param {Element} el + * Element to store data for. + * + * @return {Object} + * The cache object for that el that was passed in. + */ + function getData(el) { + var id = el[elIdAttr]; + + if (!id) { + id = el[elIdAttr] = newGUID(); + } + + if (!elData[id]) { + elData[id] = {}; + } + + return elData[id]; + } + + /** + * Returns whether or not an element has cached data + * + * @param {Element} el + * Check if this element has cached data. + * + * @return {boolean} + * - True if the DOM element has cached data. + * - False otherwise. + */ + function hasData(el) { + var id = el[elIdAttr]; + + if (!id) { + return false; + } + + return !!Object.getOwnPropertyNames(elData[id]).length; + } + + /** + * Delete data for the element from the cache and the guid attr from getElementById + * + * @param {Element} el + * Remove cached data for this element. + */ + function removeData(el) { + var id = el[elIdAttr]; + + if (!id) { + return; + } + + // Remove all stored data + delete elData[id]; + + // Remove the elIdAttr property from the DOM node + try { + delete el[elIdAttr]; + } catch (e) { + if (el.removeAttribute) { + el.removeAttribute(elIdAttr); + } else { + // IE doesn't appear to support removeAttribute on the document element + el[elIdAttr] = null; + } + } + } + + /** + * @file events.js. An Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/) + * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible) + * This should work very similarly to jQuery's events, however it's based off the book version which isn't as + * robust as jquery's, so there's probably some differences. + * + * @module events + */ + + /** + * Clean up the listener cache and dispatchers + * + * @param {Element|Object} elem + * Element to clean up + * + * @param {string} type + * Type of event to clean up + */ + function _cleanUpEvents(elem, type) { + var data = getData(elem); + + // Remove the events of a particular type if there are none left + if (data.handlers[type].length === 0) { + delete data.handlers[type]; + // data.handlers[type] = null; + // Setting to null was causing an error with data.handlers + + // Remove the meta-handler from the element + if (elem.removeEventListener) { + elem.removeEventListener(type, data.dispatcher, false); + } else if (elem.detachEvent) { + elem.detachEvent('on' + type, data.dispatcher); + } + } + + // Remove the events object if there are no types left + if (Object.getOwnPropertyNames(data.handlers).length <= 0) { + delete data.handlers; + delete data.dispatcher; + delete data.disabled; + } + + // Finally remove the element data if there is no data left + if (Object.getOwnPropertyNames(data).length === 0) { + removeData(elem); + } + } + + /** + * Loops through an array of event types and calls the requested method for each type. + * + * @param {Function} fn + * The event method we want to use. + * + * @param {Element|Object} elem + * Element or object to bind listeners to + * + * @param {string} type + * Type of event to bind to. + * + * @param {EventTarget~EventListener} callback + * Event listener. + */ + function _handleMultipleEvents(fn, elem, types, callback) { + types.forEach(function (type) { + // Call the event method for each one of the types + fn(elem, type, callback); + }); + } + + /** + * Fix a native event to have standard property values + * + * @param {Object} event + * Event object to fix. + * + * @return {Object} + * Fixed event object. + */ + function fixEvent(event) { + + function returnTrue() { + return true; + } + + function returnFalse() { + return false; + } + + // Test if fixing up is needed + // Used to check if !event.stopPropagation instead of isPropagationStopped + // But native events return true for stopPropagation, but don't have + // other expected methods like isPropagationStopped. Seems to be a problem + // with the Javascript Ninja code. So we're just overriding all events now. + if (!event || !event.isPropagationStopped) { + var old = event || window_1.event; + + event = {}; + // Clone the old object so that we can modify the values event = {}; + // IE8 Doesn't like when you mess with native event properties + // Firefox returns false for event.hasOwnProperty('type') and other props + // which makes copying more difficult. + // TODO: Probably best to create a whitelist of event props + for (var key in old) { + // Safari 6.0.3 warns you if you try to copy deprecated layerX/Y + // Chrome warns you if you try to copy deprecated keyboardEvent.keyLocation + // and webkitMovementX/Y + if (key !== 'layerX' && key !== 'layerY' && key !== 'keyLocation' && key !== 'webkitMovementX' && key !== 'webkitMovementY') { + // Chrome 32+ warns if you try to copy deprecated returnValue, but + // we still want to if preventDefault isn't supported (IE8). + if (!(key === 'returnValue' && old.preventDefault)) { + event[key] = old[key]; + } + } + } + + // The event occurred on this element + if (!event.target) { + event.target = event.srcElement || document_1; + } + + // Handle which other element the event is related to + if (!event.relatedTarget) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Stop the default browser action + event.preventDefault = function () { + if (old.preventDefault) { + old.preventDefault(); + } + event.returnValue = false; + old.returnValue = false; + event.defaultPrevented = true; + }; + + event.defaultPrevented = false; + + // Stop the event from bubbling + event.stopPropagation = function () { + if (old.stopPropagation) { + old.stopPropagation(); + } + event.cancelBubble = true; + old.cancelBubble = true; + event.isPropagationStopped = returnTrue; + }; + + event.isPropagationStopped = returnFalse; + + // Stop the event from bubbling and executing other handlers + event.stopImmediatePropagation = function () { + if (old.stopImmediatePropagation) { + old.stopImmediatePropagation(); + } + event.isImmediatePropagationStopped = returnTrue; + event.stopPropagation(); + }; + + event.isImmediatePropagationStopped = returnFalse; + + // Handle mouse position + if (event.clientX !== null && event.clientX !== undefined) { + var doc = document_1.documentElement; + var body = document_1.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Handle key presses + event.which = event.charCode || event.keyCode; + + // Fix button for mouse clicks: + // 0 == left; 1 == middle; 2 == right + if (event.button !== null && event.button !== undefined) { + + // The following is disabled because it does not pass videojs-standard + // and... yikes. + /* eslint-disable */ + event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0; + /* eslint-enable */ + } + } + + // Returns fixed-up instance + return event; + } + + /** + * Whether passive event listeners are supported + */ + var _supportsPassive = false; + + (function () { + try { + var opts = Object.defineProperty({}, 'passive', { + get: function get() { + _supportsPassive = true; + } + }); + + window_1.addEventListener('test', null, opts); + window_1.removeEventListener('test', null, opts); + } catch (e) { + // disregard + } + })(); + + /** + * Touch events Chrome expects to be passive + */ + var passiveEvents = ['touchstart', 'touchmove']; + + /** + * Add an event listener to element + * It stores the handler function in a separate cache object + * and adds a generic handler to the element's event, + * along with a unique id (guid) to the element. + * + * @param {Element|Object} elem + * Element or object to bind listeners to + * + * @param {string|string[]} type + * Type of event to bind to. + * + * @param {EventTarget~EventListener} fn + * Event listener. + */ + function on(elem, type, fn) { + if (Array.isArray(type)) { + return _handleMultipleEvents(on, elem, type, fn); + } + + var data = getData(elem); + + // We need a place to store all our handler data + if (!data.handlers) { + data.handlers = {}; + } + + if (!data.handlers[type]) { + data.handlers[type] = []; + } + + if (!fn.guid) { + fn.guid = newGUID(); + } + + data.handlers[type].push(fn); + + if (!data.dispatcher) { + data.disabled = false; + + data.dispatcher = function (event, hash) { + + if (data.disabled) { + return; + } + + event = fixEvent(event); + + var handlers = data.handlers[event.type]; + + if (handlers) { + // Copy handlers so if handlers are added/removed during the process it doesn't throw everything off. + var handlersCopy = handlers.slice(0); + + for (var m = 0, n = handlersCopy.length; m < n; m++) { + if (event.isImmediatePropagationStopped()) { + break; + } else { + try { + handlersCopy[m].call(elem, event, hash); + } catch (e) { + log$1.error(e); + } + } + } + } + }; + } + + if (data.handlers[type].length === 1) { + if (elem.addEventListener) { + var options = false; + + if (_supportsPassive && passiveEvents.indexOf(type) > -1) { + options = {passive: true}; + } + elem.addEventListener(type, data.dispatcher, options); + } else if (elem.attachEvent) { + elem.attachEvent('on' + type, data.dispatcher); + } + } + } + + /** + * Removes event listeners from an element + * + * @param {Element|Object} elem + * Object to remove listeners from. + * + * @param {string|string[]} [type] + * Type of listener to remove. Don't include to remove all events from element. + * + * @param {EventTarget~EventListener} [fn] + * Specific listener to remove. Don't include to remove listeners for an event + * type. + */ + function off(elem, type, fn) { + // Don't want to add a cache object through getElData if not needed + if (!hasData(elem)) { + return; + } + + var data = getData(elem); + + // If no events exist, nothing to unbind + if (!data.handlers) { + return; + } + + if (Array.isArray(type)) { + return _handleMultipleEvents(off, elem, type, fn); + } + + // Utility function + var removeType = function removeType(el, t) { + data.handlers[t] = []; + _cleanUpEvents(el, t); + }; + + // Are we removing all bound events? + if (type === undefined) { + for (var t in data.handlers) { + if (Object.prototype.hasOwnProperty.call(data.handlers || {}, t)) { + removeType(elem, t); + } + } + return; + } + + var handlers = data.handlers[type]; + + // If no handlers exist, nothing to unbind + if (!handlers) { + return; + } + + // If no listener was provided, remove all listeners for type + if (!fn) { + removeType(elem, type); + return; + } + + // We're only removing a single handler + if (fn.guid) { + for (var n = 0; n < handlers.length; n++) { + if (handlers[n].guid === fn.guid) { + handlers.splice(n--, 1); + } + } + } + + _cleanUpEvents(elem, type); + } + + /** + * Trigger an event for an element + * + * @param {Element|Object} elem + * Element to trigger an event on + * + * @param {EventTarget~Event|string} event + * A string (the type) or an event object with a type attribute + * + * @param {Object} [hash] + * data hash to pass along with the event + * + * @return {boolean|undefined} + * - Returns the opposite of `defaultPrevented` if default was prevented + * - Otherwise returns undefined + */ + function trigger(elem, event, hash) { + // Fetches element data and a reference to the parent (for bubbling). + // Don't want to add a data object to cache for every parent, + // so checking hasElData first. + var elemData = hasData(elem) ? getData(elem) : {}; + var parent = elem.parentNode || elem.ownerDocument; + // type = event.type || event, + // handler; + + // If an event name was passed as a string, creates an event out of it + if (typeof event === 'string') { + event = {type: event, target: elem}; + } else if (!event.target) { + event.target = elem; + } + + // Normalizes the event properties. + event = fixEvent(event); + + // If the passed element has a dispatcher, executes the established handlers. + if (elemData.dispatcher) { + elemData.dispatcher.call(elem, event, hash); + } + + // Unless explicitly stopped or the event does not bubble (e.g. media events) + // recursively calls this function to bubble the event up the DOM. + if (parent && !event.isPropagationStopped() && event.bubbles === true) { + trigger.call(null, parent, event, hash); + + // If at the top of the DOM, triggers the default action unless disabled. + } else if (!parent && !event.defaultPrevented) { + var targetData = getData(event.target); + + // Checks if the target has a default action for this event. + if (event.target[event.type]) { + // Temporarily disables event dispatching on the target as we have already executed the handler. + targetData.disabled = true; + // Executes the default action. + if (typeof event.target[event.type] === 'function') { + event.target[event.type](); + } + // Re-enables event dispatching. + targetData.disabled = false; + } + } + + // Inform the triggerer if the default was prevented by returning false + return !event.defaultPrevented; + } + + /** + * Trigger a listener only once for an event + * + * @param {Element|Object} elem + * Element or object to bind to. + * + * @param {string|string[]} type + * Name/type of event + * + * @param {Event~EventListener} fn + * Event Listener function + */ + function one(elem, type, fn) { + if (Array.isArray(type)) { + return _handleMultipleEvents(one, elem, type, fn); + } + var func = function func() { + off(elem, type, func); + fn.apply(this, arguments); + }; + + // copy the guid to the new function so it can removed using the original function's ID + func.guid = fn.guid = fn.guid || newGUID(); + on(elem, type, func); + } + + var Events = /*#__PURE__*/Object.freeze({ + fixEvent: fixEvent, + on: on, + off: off, + trigger: trigger, + one: one + }); + + /** + * @file setup.js - Functions for setting up a player without + * user interaction based on the data-setup `attribute` of the video tag. + * + * @module setup + */ + + var _windowLoaded = false; + var videojs = void 0; + + /** + * Set up any tags that have a data-setup `attribute` when the player is started. + */ + var autoSetup = function autoSetup() { + + // Protect against breakage in non-browser environments and check global autoSetup option. + if (!isReal() || videojs.options.autoSetup === false) { + return; + } + + var vids = Array.prototype.slice.call(document_1.getElementsByTagName('video')); + var audios = Array.prototype.slice.call(document_1.getElementsByTagName('audio')); + var divs = Array.prototype.slice.call(document_1.getElementsByTagName('video-js')); + var mediaEls = vids.concat(audios, divs); + + // Check if any media elements exist + if (mediaEls && mediaEls.length > 0) { + + for (var i = 0, e = mediaEls.length; i < e; i++) { + var mediaEl = mediaEls[i]; + + // Check if element exists, has getAttribute func. + if (mediaEl && mediaEl.getAttribute) { + + // Make sure this player hasn't already been set up. + if (mediaEl.player === undefined) { + var options = mediaEl.getAttribute('data-setup'); + + // Check if data-setup attr exists. + // We only auto-setup if they've added the data-setup attr. + if (options !== null) { + // Create new video.js instance. + videojs(mediaEl); + } + } + + // If getAttribute isn't defined, we need to wait for the DOM. + } else { + autoSetupTimeout(1); + break; + } + } + + // No videos were found, so keep looping unless page is finished loading. + } else if (!_windowLoaded) { + autoSetupTimeout(1); + } + }; + + /** + * Wait until the page is loaded before running autoSetup. This will be called in + * autoSetup if `hasLoaded` returns false. + * + * @param {number} wait + * How long to wait in ms + * + * @param {module:videojs} [vjs] + * The videojs library function + */ + function autoSetupTimeout(wait, vjs) { + if (vjs) { + videojs = vjs; + } + + window_1.setTimeout(autoSetup, wait); + } + + if (isReal() && document_1.readyState === 'complete') { + _windowLoaded = true; + } else { + /** + * Listen for the load event on window, and set _windowLoaded to true. + * + * @listens load + */ + one(window_1, 'load', function () { + _windowLoaded = true; + }); + } + + /** + * @file stylesheet.js + * @module stylesheet + */ + + /** + * Create a DOM syle element given a className for it. + * + * @param {string} className + * The className to add to the created style element. + * + * @return {Element} + * The element that was created. + */ + var createStyleElement = function createStyleElement(className) { + var style = document_1.createElement('style'); + + style.className = className; + + return style; + }; + + /** + * Add text to a DOM element. + * + * @param {Element} el + * The Element to add text content to. + * + * @param {string} content + * The text to add to the element. + */ + var setTextContent = function setTextContent(el, content) { + if (el.styleSheet) { + el.styleSheet.cssText = content; + } else { + el.textContent = content; + } + }; + + /** + * @file fn.js + * @module fn + */ + + /** + * Bind (a.k.a proxy or Context). A simple method for changing the context of a function + * It also stores a unique id on the function so it can be easily removed from events. + * + * @param {Mixed} context + * The object to bind as scope. + * + * @param {Function} fn + * The function to be bound to a scope. + * + * @param {number} [uid] + * An optional unique ID for the function to be set + * + * @return {Function} + * The new function that will be bound into the context given + */ + var bind = function bind(context, fn, uid) { + // Make sure the function has a unique ID + if (!fn.guid) { + fn.guid = newGUID(); + } + + // Create the new function that changes the context + var bound = function bound() { + return fn.apply(context, arguments); + }; + + // Allow for the ability to individualize this function + // Needed in the case where multiple objects might share the same prototype + // IF both items add an event listener with the same function, then you try to remove just one + // it will remove both because they both have the same guid. + // when using this, you need to use the bind method when you remove the listener as well. + // currently used in text tracks + bound.guid = uid ? uid + '_' + fn.guid : fn.guid; + + return bound; + }; + + /** + * Wraps the given function, `fn`, with a new function that only invokes `fn` + * at most once per every `wait` milliseconds. + * + * @param {Function} fn + * The function to be throttled. + * + * @param {Number} wait + * The number of milliseconds by which to throttle. + * + * @return {Function} + */ + var throttle = function throttle(fn, wait) { + var last = Date.now(); + + var throttled = function throttled() { + var now = Date.now(); + + if (now - last >= wait) { + fn.apply(undefined, arguments); + last = now; + } + }; + + return throttled; + }; + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. + * + * Inspired by lodash and underscore implementations. + * + * @param {Function} func + * The function to wrap with debounce behavior. + * + * @param {number} wait + * The number of milliseconds to wait after the last invocation. + * + * @param {boolean} [immediate] + * Whether or not to invoke the function immediately upon creation. + * + * @param {Object} [context=window] + * The "context" in which the debounced function should debounce. For + * example, if this function should be tied to a Video.js player, + * the player can be passed here. Alternatively, defaults to the + * global `window` object. + * + * @return {Function} + * A debounced function. + */ + var debounce = function debounce(func, wait, immediate) { + var context = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : window_1; + + var timeout = void 0; + + /* eslint-disable consistent-this */ + return function () { + var self = this; + var args = arguments; + + var _later = function later() { + timeout = null; + _later = null; + if (!immediate) { + func.apply(self, args); + } + }; + + if (!timeout && immediate) { + func.apply(self, args); + } + + context.clearTimeout(timeout); + timeout = context.setTimeout(_later, wait); + }; + /* eslint-enable consistent-this */ + }; + + /** + * @file src/js/event-target.js + */ + + /** + * `EventTarget` is a class that can have the same API as the DOM `EventTarget`. It + * adds shorthand functions that wrap around lengthy functions. For example: + * the `on` function is a wrapper around `addEventListener`. + * + * @see [EventTarget Spec]{@link https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget} + * @class EventTarget + */ + var EventTarget = function EventTarget() { + }; + + /** + * A Custom DOM event. + * + * @typedef {Object} EventTarget~Event + * @see [Properties]{@link https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent} + */ + + /** + * All event listeners should follow the following format. + * + * @callback EventTarget~EventListener + * @this {EventTarget} + * + * @param {EventTarget~Event} event + * the event that triggered this function + * + * @param {Object} [hash] + * hash of data sent during the event + */ + + /** + * An object containing event names as keys and booleans as values. + * + * > NOTE: If an event name is set to a true value here {@link EventTarget#trigger} + * will have extra functionality. See that function for more information. + * + * @property EventTarget.prototype.allowedEvents_ + * @private + */ + EventTarget.prototype.allowedEvents_ = {}; + + /** + * Adds an `event listener` to an instance of an `EventTarget`. An `event listener` is a + * function that will get called when an event with a certain name gets triggered. + * + * @param {string|string[]} type + * An event name or an array of event names. + * + * @param {EventTarget~EventListener} fn + * The function to call with `EventTarget`s + */ + EventTarget.prototype.on = function (type, fn) { + // Remove the addEventListener alias before calling Events.on + // so we don't get into an infinite type loop + var ael = this.addEventListener; + + this.addEventListener = function () { + }; + on(this, type, fn); + this.addEventListener = ael; + }; + + /** + * An alias of {@link EventTarget#on}. Allows `EventTarget` to mimic + * the standard DOM API. + * + * @function + * @see {@link EventTarget#on} + */ + EventTarget.prototype.addEventListener = EventTarget.prototype.on; + + /** + * Removes an `event listener` for a specific event from an instance of `EventTarget`. + * This makes it so that the `event listener` will no longer get called when the + * named event happens. + * + * @param {string|string[]} type + * An event name or an array of event names. + * + * @param {EventTarget~EventListener} fn + * The function to remove. + */ + EventTarget.prototype.off = function (type, fn) { + off(this, type, fn); + }; + + /** + * An alias of {@link EventTarget#off}. Allows `EventTarget` to mimic + * the standard DOM API. + * + * @function + * @see {@link EventTarget#off} + */ + EventTarget.prototype.removeEventListener = EventTarget.prototype.off; + + /** + * This function will add an `event listener` that gets triggered only once. After the + * first trigger it will get removed. This is like adding an `event listener` + * with {@link EventTarget#on} that calls {@link EventTarget#off} on itself. + * + * @param {string|string[]} type + * An event name or an array of event names. + * + * @param {EventTarget~EventListener} fn + * The function to be called once for each event name. + */ + EventTarget.prototype.one = function (type, fn) { + // Remove the addEventListener alialing Events.on + // so we don't get into an infinite type loop + var ael = this.addEventListener; + + this.addEventListener = function () { + }; + one(this, type, fn); + this.addEventListener = ael; + }; + + /** + * This function causes an event to happen. This will then cause any `event listeners` + * that are waiting for that event, to get called. If there are no `event listeners` + * for an event then nothing will happen. + * + * If the name of the `Event` that is being triggered is in `EventTarget.allowedEvents_`. + * Trigger will also call the `on` + `uppercaseEventName` function. + * + * Example: + * 'click' is in `EventTarget.allowedEvents_`, so, trigger will attempt to call + * `onClick` if it exists. + * + * @param {string|EventTarget~Event|Object} event + * The name of the event, an `Event`, or an object with a key of type set to + * an event name. + */ + EventTarget.prototype.trigger = function (event) { + var type = event.type || event; + + if (typeof event === 'string') { + event = {type: type}; + } + event = fixEvent(event); + + if (this.allowedEvents_[type] && this['on' + type]) { + this['on' + type](event); + } + + trigger(this, event); + }; + + /** + * An alias of {@link EventTarget#trigger}. Allows `EventTarget` to mimic + * the standard DOM API. + * + * @function + * @see {@link EventTarget#trigger} + */ + EventTarget.prototype.dispatchEvent = EventTarget.prototype.trigger; + + /** + * @file mixins/evented.js + * @module evented + */ + + /** + * Returns whether or not an object has had the evented mixin applied. + * + * @param {Object} object + * An object to test. + * + * @return {boolean} + * Whether or not the object appears to be evented. + */ + var isEvented = function isEvented(object) { + return object instanceof EventTarget || !!object.eventBusEl_ && ['on', 'one', 'off', 'trigger'].every(function (k) { + return typeof object[k] === 'function'; + }); + }; + + /** + * Whether a value is a valid event type - non-empty string or array. + * + * @private + * @param {string|Array} type + * The type value to test. + * + * @return {boolean} + * Whether or not the type is a valid event type. + */ + var isValidEventType = function isValidEventType(type) { + return ( + // The regex here verifies that the `type` contains at least one non- + // whitespace character. + typeof type === 'string' && /\S/.test(type) || Array.isArray(type) && !!type.length + ); + }; + + /** + * Validates a value to determine if it is a valid event target. Throws if not. + * + * @private + * @throws {Error} + * If the target does not appear to be a valid event target. + * + * @param {Object} target + * The object to test. + */ + var validateTarget = function validateTarget(target) { + if (!target.nodeName && !isEvented(target)) { + throw new Error('Invalid target; must be a DOM node or evented object.'); + } + }; + + /** + * Validates a value to determine if it is a valid event target. Throws if not. + * + * @private + * @throws {Error} + * If the type does not appear to be a valid event type. + * + * @param {string|Array} type + * The type to test. + */ + var validateEventType = function validateEventType(type) { + if (!isValidEventType(type)) { + throw new Error('Invalid event type; must be a non-empty string or array.'); + } + }; + + /** + * Validates a value to determine if it is a valid listener. Throws if not. + * + * @private + * @throws {Error} + * If the listener is not a function. + * + * @param {Function} listener + * The listener to test. + */ + var validateListener = function validateListener(listener) { + if (typeof listener !== 'function') { + throw new Error('Invalid listener; must be a function.'); + } + }; + + /** + * Takes an array of arguments given to `on()` or `one()`, validates them, and + * normalizes them into an object. + * + * @private + * @param {Object} self + * The evented object on which `on()` or `one()` was called. This + * object will be bound as the `this` value for the listener. + * + * @param {Array} args + * An array of arguments passed to `on()` or `one()`. + * + * @return {Object} + * An object containing useful values for `on()` or `one()` calls. + */ + var normalizeListenArgs = function normalizeListenArgs(self, args) { + + // If the number of arguments is less than 3, the target is always the + // evented object itself. + var isTargetingSelf = args.length < 3 || args[0] === self || args[0] === self.eventBusEl_; + var target = void 0; + var type = void 0; + var listener = void 0; + + if (isTargetingSelf) { + target = self.eventBusEl_; + + // Deal with cases where we got 3 arguments, but we are still listening to + // the evented object itself. + if (args.length >= 3) { + args.shift(); + } + + type = args[0]; + listener = args[1]; + } else { + target = args[0]; + type = args[1]; + listener = args[2]; + } + + validateTarget(target); + validateEventType(type); + validateListener(listener); + + listener = bind(self, listener); + + return {isTargetingSelf: isTargetingSelf, target: target, type: type, listener: listener}; + }; + + /** + * Adds the listener to the event type(s) on the target, normalizing for + * the type of target. + * + * @private + * @param {Element|Object} target + * A DOM node or evented object. + * + * @param {string} method + * The event binding method to use ("on" or "one"). + * + * @param {string|Array} type + * One or more event type(s). + * + * @param {Function} listener + * A listener function. + */ + var listen = function listen(target, method, type, listener) { + validateTarget(target); + + if (target.nodeName) { + Events[method](target, type, listener); + } else { + target[method](type, listener); + } + }; + + /** + * Contains methods that provide event capabilities to an object which is passed + * to {@link module:evented|evented}. + * + * @mixin EventedMixin + */ + var EventedMixin = { + + /** + * Add a listener to an event (or events) on this object or another evented + * object. + * + * @param {string|Array|Element|Object} targetOrType + * If this is a string or array, it represents the event type(s) + * that will trigger the listener. + * + * Another evented object can be passed here instead, which will + * cause the listener to listen for events on _that_ object. + * + * In either case, the listener's `this` value will be bound to + * this object. + * + * @param {string|Array|Function} typeOrListener + * If the first argument was a string or array, this should be the + * listener function. Otherwise, this is a string or array of event + * type(s). + * + * @param {Function} [listener] + * If the first argument was another evented object, this will be + * the listener function. + */ + on: function on$$1() { + var _this = this; + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var _normalizeListenArgs = normalizeListenArgs(this, args), + isTargetingSelf = _normalizeListenArgs.isTargetingSelf, + target = _normalizeListenArgs.target, + type = _normalizeListenArgs.type, + listener = _normalizeListenArgs.listener; + + listen(target, 'on', type, listener); + + // If this object is listening to another evented object. + if (!isTargetingSelf) { + + // If this object is disposed, remove the listener. + var removeListenerOnDispose = function removeListenerOnDispose() { + return _this.off(target, type, listener); + }; + + // Use the same function ID as the listener so we can remove it later it + // using the ID of the original listener. + removeListenerOnDispose.guid = listener.guid; + + // Add a listener to the target's dispose event as well. This ensures + // that if the target is disposed BEFORE this object, we remove the + // removal listener that was just added. Otherwise, we create a memory leak. + var removeRemoverOnTargetDispose = function removeRemoverOnTargetDispose() { + return _this.off('dispose', removeListenerOnDispose); + }; + + // Use the same function ID as the listener so we can remove it later + // it using the ID of the original listener. + removeRemoverOnTargetDispose.guid = listener.guid; + + listen(this, 'on', 'dispose', removeListenerOnDispose); + listen(target, 'on', 'dispose', removeRemoverOnTargetDispose); + } + }, + + + /** + * Add a listener to an event (or events) on this object or another evented + * object. The listener will only be called once and then removed. + * + * @param {string|Array|Element|Object} targetOrType + * If this is a string or array, it represents the event type(s) + * that will trigger the listener. + * + * Another evented object can be passed here instead, which will + * cause the listener to listen for events on _that_ object. + * + * In either case, the listener's `this` value will be bound to + * this object. + * + * @param {string|Array|Function} typeOrListener + * If the first argument was a string or array, this should be the + * listener function. Otherwise, this is a string or array of event + * type(s). + * + * @param {Function} [listener] + * If the first argument was another evented object, this will be + * the listener function. + */ + one: function one$$1() { + var _this2 = this; + + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + var _normalizeListenArgs2 = normalizeListenArgs(this, args), + isTargetingSelf = _normalizeListenArgs2.isTargetingSelf, + target = _normalizeListenArgs2.target, + type = _normalizeListenArgs2.type, + listener = _normalizeListenArgs2.listener; + + // Targeting this evented object. + + + if (isTargetingSelf) { + listen(target, 'one', type, listener); + + // Targeting another evented object. + } else { + var wrapper = function wrapper() { + for (var _len3 = arguments.length, largs = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + largs[_key3] = arguments[_key3]; + } + + _this2.off(target, type, wrapper); + listener.apply(null, largs); + }; + + // Use the same function ID as the listener so we can remove it later + // it using the ID of the original listener. + wrapper.guid = listener.guid; + listen(target, 'one', type, wrapper); + } + }, + + + /** + * Removes listener(s) from event(s) on an evented object. + * + * @param {string|Array|Element|Object} [targetOrType] + * If this is a string or array, it represents the event type(s). + * + * Another evented object can be passed here instead, in which case + * ALL 3 arguments are _required_. + * + * @param {string|Array|Function} [typeOrListener] + * If the first argument was a string or array, this may be the + * listener function. Otherwise, this is a string or array of event + * type(s). + * + * @param {Function} [listener] + * If the first argument was another evented object, this will be + * the listener function; otherwise, _all_ listeners bound to the + * event type(s) will be removed. + */ + off: function off$$1(targetOrType, typeOrListener, listener) { + + // Targeting this evented object. + if (!targetOrType || isValidEventType(targetOrType)) { + off(this.eventBusEl_, targetOrType, typeOrListener); + + // Targeting another evented object. + } else { + var target = targetOrType; + var type = typeOrListener; + + // Fail fast and in a meaningful way! + validateTarget(target); + validateEventType(type); + validateListener(listener); + + // Ensure there's at least a guid, even if the function hasn't been used + listener = bind(this, listener); + + // Remove the dispose listener on this evented object, which was given + // the same guid as the event listener in on(). + this.off('dispose', listener); + + if (target.nodeName) { + off(target, type, listener); + off(target, 'dispose', listener); + } else if (isEvented(target)) { + target.off(type, listener); + target.off('dispose', listener); + } + } + }, + + + /** + * Fire an event on this evented object, causing its listeners to be called. + * + * @param {string|Object} event + * An event type or an object with a type property. + * + * @param {Object} [hash] + * An additional object to pass along to listeners. + * + * @returns {boolean} + * Whether or not the default behavior was prevented. + */ + trigger: function trigger$$1(event, hash) { + return trigger(this.eventBusEl_, event, hash); + } + }; + + /** + * Applies {@link module:evented~EventedMixin|EventedMixin} to a target object. + * + * @param {Object} target + * The object to which to add event methods. + * + * @param {Object} [options={}] + * Options for customizing the mixin behavior. + * + * @param {String} [options.eventBusKey] + * By default, adds a `eventBusEl_` DOM element to the target object, + * which is used as an event bus. If the target object already has a + * DOM element that should be used, pass its key here. + * + * @return {Object} + * The target object. + */ + function evented(target) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var eventBusKey = options.eventBusKey; + + // Set or create the eventBusEl_. + + if (eventBusKey) { + if (!target[eventBusKey].nodeName) { + throw new Error('The eventBusKey "' + eventBusKey + '" does not refer to an element.'); + } + target.eventBusEl_ = target[eventBusKey]; + } else { + target.eventBusEl_ = createEl('span', {className: 'vjs-event-bus'}); + } + + assign(target, EventedMixin); + + // When any evented object is disposed, it removes all its listeners. + target.on('dispose', function () { + target.off(); + window_1.setTimeout(function () { + target.eventBusEl_ = null; + }, 0); + }); + + return target; + } + + /** + * @file mixins/stateful.js + * @module stateful + */ + + /** + * Contains methods that provide statefulness to an object which is passed + * to {@link module:stateful}. + * + * @mixin StatefulMixin + */ + var StatefulMixin = { + + /** + * A hash containing arbitrary keys and values representing the state of + * the object. + * + * @type {Object} + */ + state: {}, + + /** + * Set the state of an object by mutating its + * {@link module:stateful~StatefulMixin.state|state} object in place. + * + * @fires module:stateful~StatefulMixin#statechanged + * @param {Object|Function} stateUpdates + * A new set of properties to shallow-merge into the plugin state. + * Can be a plain object or a function returning a plain object. + * + * @returns {Object|undefined} + * An object containing changes that occurred. If no changes + * occurred, returns `undefined`. + */ + setState: function setState(stateUpdates) { + var _this = this; + + // Support providing the `stateUpdates` state as a function. + if (typeof stateUpdates === 'function') { + stateUpdates = stateUpdates(); + } + + var changes = void 0; + + each(stateUpdates, function (value, key) { + + // Record the change if the value is different from what's in the + // current state. + if (_this.state[key] !== value) { + changes = changes || {}; + changes[key] = { + from: _this.state[key], + to: value + }; + } + + _this.state[key] = value; + }); + + // Only trigger "statechange" if there were changes AND we have a trigger + // function. This allows us to not require that the target object be an + // evented object. + if (changes && isEvented(this)) { + + /** + * An event triggered on an object that is both + * {@link module:stateful|stateful} and {@link module:evented|evented} + * indicating that its state has changed. + * + * @event module:stateful~StatefulMixin#statechanged + * @type {Object} + * @property {Object} changes + * A hash containing the properties that were changed and + * the values they were changed `from` and `to`. + */ + this.trigger({ + changes: changes, + type: 'statechanged' + }); + } + + return changes; + } + }; + + /** + * Applies {@link module:stateful~StatefulMixin|StatefulMixin} to a target + * object. + * + * If the target object is {@link module:evented|evented} and has a + * `handleStateChanged` method, that method will be automatically bound to the + * `statechanged` event on itself. + * + * @param {Object} target + * The object to be made stateful. + * + * @param {Object} [defaultState] + * A default set of properties to populate the newly-stateful object's + * `state` property. + * + * @returns {Object} + * Returns the `target`. + */ + function stateful(target, defaultState) { + assign(target, StatefulMixin); + + // This happens after the mixing-in because we need to replace the `state` + // added in that step. + target.state = assign({}, target.state, defaultState); + + // Auto-bind the `handleStateChanged` method of the target object if it exists. + if (typeof target.handleStateChanged === 'function' && isEvented(target)) { + target.on('statechanged', target.handleStateChanged); + } + + return target; + } + + /** + * @file to-title-case.js + * @module to-title-case + */ + + /** + * Uppercase the first letter of a string. + * + * @param {string} string + * String to be uppercased + * + * @return {string} + * The string with an uppercased first letter + */ + function toTitleCase(string) { + if (typeof string !== 'string') { + return string; + } + + return string.charAt(0).toUpperCase() + string.slice(1); + } + + /** + * Compares the TitleCase versions of the two strings for equality. + * + * @param {string} str1 + * The first string to compare + * + * @param {string} str2 + * The second string to compare + * + * @return {boolean} + * Whether the TitleCase versions of the strings are equal + */ + function titleCaseEquals(str1, str2) { + return toTitleCase(str1) === toTitleCase(str2); + } + + /** + * @file merge-options.js + * @module merge-options + */ + + /** + * Deep-merge one or more options objects, recursively merging **only** plain + * object properties. + * + * @param {Object[]} sources + * One or more objects to merge into a new object. + * + * @returns {Object} + * A new object that is the merged result of all sources. + */ + function mergeOptions() { + var result = {}; + + for (var _len = arguments.length, sources = Array(_len), _key = 0; _key < _len; _key++) { + sources[_key] = arguments[_key]; + } + + sources.forEach(function (source) { + if (!source) { + return; + } + + each(source, function (value, key) { + if (!isPlain(value)) { + result[key] = value; + return; + } + + if (!isPlain(result[key])) { + result[key] = {}; + } + + result[key] = mergeOptions(result[key], value); + }); + }); + + return result; + } + + /** + * Player Component - Base class for all UI objects + * + * @file component.js + */ + + /** + * Base class for all UI Components. + * Components are UI objects which represent both a javascript object and an element + * in the DOM. They can be children of other components, and can have + * children themselves. + * + * Components can also use methods from {@link EventTarget} + */ + + var Component = function () { + + /** + * A callback that is called when a component is ready. Does not have any + * paramters and any callback value will be ignored. + * + * @callback Component~ReadyCallback + * @this Component + */ + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Object[]} [options.children] + * An array of children objects to intialize this component with. Children objects have + * a name property that will be used if more than one component of the same type needs to be + * added. + * + * @param {Component~ReadyCallback} [ready] + * Function that gets called when the `Component` is ready. + */ + function Component(player, options, ready) { + classCallCheck(this, Component); + + + // The component might be the player itself and we can't pass `this` to super + if (!player && this.play) { + this.player_ = player = this; // eslint-disable-line + } else { + this.player_ = player; + } + + // Make a copy of prototype.options_ to protect against overriding defaults + this.options_ = mergeOptions({}, this.options_); + + // Updated options with supplied options + options = this.options_ = mergeOptions(this.options_, options); + + // Get ID from options or options element if one is supplied + this.id_ = options.id || options.el && options.el.id; + + // If there was no ID from the options, generate one + if (!this.id_) { + // Don't require the player ID function in the case of mock players + var id = player && player.id && player.id() || 'no_player'; + + this.id_ = id + '_component_' + newGUID(); + } + + this.name_ = options.name || null; + + // Create element if one wasn't provided in options + if (options.el) { + this.el_ = options.el; + } else if (options.createEl !== false) { + this.el_ = this.createEl(); + } + + // if evented is anything except false, we want to mixin in evented + if (options.evented !== false) { + // Make this an evented object and use `el_`, if available, as its event bus + evented(this, {eventBusKey: this.el_ ? 'el_' : null}); + } + stateful(this, this.constructor.defaultState); + + this.children_ = []; + this.childIndex_ = {}; + this.childNameIndex_ = {}; + + // Add any child components in options + if (options.initChildren !== false) { + this.initChildren(); + } + + this.ready(ready); + // Don't want to trigger ready here or it will before init is actually + // finished for all children that run this constructor + + if (options.reportTouchActivity !== false) { + this.enableTouchActivity(); + } + } + + /** + * Dispose of the `Component` and all child components. + * + * @fires Component#dispose + */ + + + Component.prototype.dispose = function dispose() { + + /** + * Triggered when a `Component` is disposed. + * + * @event Component#dispose + * @type {EventTarget~Event} + * + * @property {boolean} [bubbles=false] + * set to false so that the close event does not + * bubble up + */ + this.trigger({type: 'dispose', bubbles: false}); + + // Dispose all children. + if (this.children_) { + for (var i = this.children_.length - 1; i >= 0; i--) { + if (this.children_[i].dispose) { + this.children_[i].dispose(); + } + } + } + + // Delete child references + this.children_ = null; + this.childIndex_ = null; + this.childNameIndex_ = null; + + if (this.el_) { + // Remove element from DOM + if (this.el_.parentNode) { + this.el_.parentNode.removeChild(this.el_); + } + + removeData(this.el_); + this.el_ = null; + } + + // remove reference to the player after disposing of the element + this.player_ = null; + }; + + /** + * Return the {@link Player} that the `Component` has attached to. + * + * @return {Player} + * The player that this `Component` has attached to. + */ + + + Component.prototype.player = function player() { + return this.player_; + }; + + /** + * Deep merge of options objects with new options. + * > Note: When both `obj` and `options` contain properties whose values are objects. + * The two properties get merged using {@link module:mergeOptions} + * + * @param {Object} obj + * The object that contains new options. + * + * @return {Object} + * A new object of `this.options_` and `obj` merged together. + * + * @deprecated since version 5 + */ + + + Component.prototype.options = function options(obj) { + log$1.warn('this.options() has been deprecated and will be moved to the constructor in 6.0'); + + if (!obj) { + return this.options_; + } + + this.options_ = mergeOptions(this.options_, obj); + return this.options_; + }; + + /** + * Get the `Component`s DOM element + * + * @return {Element} + * The DOM element for this `Component`. + */ + + + Component.prototype.el = function el() { + return this.el_; + }; + + /** + * Create the `Component`s DOM element. + * + * @param {string} [tagName] + * Element's DOM node type. e.g. 'div' + * + * @param {Object} [properties] + * An object of properties that should be set. + * + * @param {Object} [attributes] + * An object of attributes that should be set. + * + * @return {Element} + * The element that gets created. + */ + + + Component.prototype.createEl = function createEl$$1(tagName, properties, attributes) { + return createEl(tagName, properties, attributes); + }; + + /** + * Localize a string given the string in english. + * + * If tokens are provided, it'll try and run a simple token replacement on the provided string. + * The tokens it looks for look like `{1}` with the index being 1-indexed into the tokens array. + * + * If a `defaultValue` is provided, it'll use that over `string`, + * if a value isn't found in provided language files. + * This is useful if you want to have a descriptive key for token replacement + * but have a succinct localized string and not require `en.json` to be included. + * + * Currently, it is used for the progress bar timing. + * ```js + * { + * "progress bar timing: currentTime={1} duration={2}": "{1} of {2}" + * } + * ``` + * It is then used like so: + * ```js + * this.localize('progress bar timing: currentTime={1} duration{2}', + * [this.player_.currentTime(), this.player_.duration()], + * '{1} of {2}'); + * ``` + * + * Which outputs something like: `01:23 of 24:56`. + * + * + * @param {string} string + * The string to localize and the key to lookup in the language files. + * @param {string[]} [tokens] + * If the current item has token replacements, provide the tokens here. + * @param {string} [defaultValue] + * Defaults to `string`. Can be a default value to use for token replacement + * if the lookup key is needed to be separate. + * + * @return {string} + * The localized string or if no localization exists the english string. + */ + + + Component.prototype.localize = function localize(string, tokens) { + var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : string; + + var code = this.player_.language && this.player_.language(); + var languages = this.player_.languages && this.player_.languages(); + var language = languages && languages[code]; + var primaryCode = code && code.split('-')[0]; + var primaryLang = languages && languages[primaryCode]; + + var localizedString = defaultValue; + + if (language && language[string]) { + localizedString = language[string]; + } else if (primaryLang && primaryLang[string]) { + localizedString = primaryLang[string]; + } + + if (tokens) { + localizedString = localizedString.replace(/\{(\d+)\}/g, function (match, index) { + var value = tokens[index - 1]; + var ret = value; + + if (typeof value === 'undefined') { + ret = match; + } + + return ret; + }); + } + + return localizedString; + }; + + /** + * Return the `Component`s DOM element. This is where children get inserted. + * This will usually be the the same as the element returned in {@link Component#el}. + * + * @return {Element} + * The content element for this `Component`. + */ + + + Component.prototype.contentEl = function contentEl() { + return this.contentEl_ || this.el_; + }; + + /** + * Get this `Component`s ID + * + * @return {string} + * The id of this `Component` + */ + + + Component.prototype.id = function id() { + return this.id_; + }; + + /** + * Get the `Component`s name. The name gets used to reference the `Component` + * and is set during registration. + * + * @return {string} + * The name of this `Component`. + */ + + + Component.prototype.name = function name() { + return this.name_; + }; + + /** + * Get an array of all child components + * + * @return {Array} + * The children + */ + + + Component.prototype.children = function children() { + return this.children_; + }; + + /** + * Returns the child `Component` with the given `id`. + * + * @param {string} id + * The id of the child `Component` to get. + * + * @return {Component|undefined} + * The child `Component` with the given `id` or undefined. + */ + + + Component.prototype.getChildById = function getChildById(id) { + return this.childIndex_[id]; + }; + + /** + * Returns the child `Component` with the given `name`. + * + * @param {string} name + * The name of the child `Component` to get. + * + * @return {Component|undefined} + * The child `Component` with the given `name` or undefined. + */ + + + Component.prototype.getChild = function getChild(name) { + if (!name) { + return; + } + + name = toTitleCase(name); + + return this.childNameIndex_[name]; + }; + + /** + * Add a child `Component` inside the current `Component`. + * + * + * @param {string|Component} child + * The name or instance of a child to add. + * + * @param {Object} [options={}] + * The key/value store of options that will get passed to children of + * the child. + * + * @param {number} [index=this.children_.length] + * The index to attempt to add a child into. + * + * @return {Component} + * The `Component` that gets added as a child. When using a string the + * `Component` will get created by this process. + */ + + + Component.prototype.addChild = function addChild(child) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.children_.length; + + var component = void 0; + var componentName = void 0; + + // If child is a string, create component with options + if (typeof child === 'string') { + componentName = toTitleCase(child); + + var componentClassName = options.componentClass || componentName; + + // Set name through options + options.name = componentName; + + // Create a new object & element for this controls set + // If there's no .player_, this is a player + var ComponentClass = Component.getComponent(componentClassName); + + if (!ComponentClass) { + throw new Error('Component ' + componentClassName + ' does not exist'); + } + + // data stored directly on the videojs object may be + // misidentified as a component to retain + // backwards-compatibility with 4.x. check to make sure the + // component class can be instantiated. + if (typeof ComponentClass !== 'function') { + return null; + } + + component = new ComponentClass(this.player_ || this, options); + + // child is a component instance + } else { + component = child; + } + + this.children_.splice(index, 0, component); + + if (typeof component.id === 'function') { + this.childIndex_[component.id()] = component; + } + + // If a name wasn't used to create the component, check if we can use the + // name function of the component + componentName = componentName || component.name && toTitleCase(component.name()); + + if (componentName) { + this.childNameIndex_[componentName] = component; + } + + // Add the UI object's element to the container div (box) + // Having an element is not required + if (typeof component.el === 'function' && component.el()) { + var childNodes = this.contentEl().children; + var refNode = childNodes[index] || null; + + this.contentEl().insertBefore(component.el(), refNode); + } + + // Return so it can stored on parent object if desired. + return component; + }; + + /** + * Remove a child `Component` from this `Component`s list of children. Also removes + * the child `Component`s element from this `Component`s element. + * + * @param {Component} component + * The child `Component` to remove. + */ + + + Component.prototype.removeChild = function removeChild(component) { + if (typeof component === 'string') { + component = this.getChild(component); + } + + if (!component || !this.children_) { + return; + } + + var childFound = false; + + for (var i = this.children_.length - 1; i >= 0; i--) { + if (this.children_[i] === component) { + childFound = true; + this.children_.splice(i, 1); + break; + } + } + + if (!childFound) { + return; + } + + this.childIndex_[component.id()] = null; + this.childNameIndex_[component.name()] = null; + + var compEl = component.el(); + + if (compEl && compEl.parentNode === this.contentEl()) { + this.contentEl().removeChild(component.el()); + } + }; + + /** + * Add and initialize default child `Component`s based upon options. + */ + + + Component.prototype.initChildren = function initChildren() { + var _this = this; + + var children = this.options_.children; + + if (children) { + // `this` is `parent` + var parentOptions = this.options_; + + var handleAdd = function handleAdd(child) { + var name = child.name; + var opts = child.opts; + + // Allow options for children to be set at the parent options + // e.g. videojs(id, { controlBar: false }); + // instead of videojs(id, { children: { controlBar: false }); + if (parentOptions[name] !== undefined) { + opts = parentOptions[name]; + } + + // Allow for disabling default components + // e.g. options['children']['posterImage'] = false + if (opts === false) { + return; + } + + // Allow options to be passed as a simple boolean if no configuration + // is necessary. + if (opts === true) { + opts = {}; + } + + // We also want to pass the original player options + // to each component as well so they don't need to + // reach back into the player for options later. + opts.playerOptions = _this.options_.playerOptions; + + // Create and add the child component. + // Add a direct reference to the child by name on the parent instance. + // If two of the same component are used, different names should be supplied + // for each + var newChild = _this.addChild(name, opts); + + if (newChild) { + _this[name] = newChild; + } + }; + + // Allow for an array of children details to passed in the options + var workingChildren = void 0; + var Tech = Component.getComponent('Tech'); + + if (Array.isArray(children)) { + workingChildren = children; + } else { + workingChildren = Object.keys(children); + } + + workingChildren + // children that are in this.options_ but also in workingChildren would + // give us extra children we do not want. So, we want to filter them out. + .concat(Object.keys(this.options_).filter(function (child) { + return !workingChildren.some(function (wchild) { + if (typeof wchild === 'string') { + return child === wchild; + } + return child === wchild.name; + }); + })).map(function (child) { + var name = void 0; + var opts = void 0; + + if (typeof child === 'string') { + name = child; + opts = children[name] || _this.options_[name] || {}; + } else { + name = child.name; + opts = child; + } + + return {name: name, opts: opts}; + }).filter(function (child) { + // we have to make sure that child.name isn't in the techOrder since + // techs are registerd as Components but can't aren't compatible + // See https://github.com/videojs/video.js/issues/2772 + var c = Component.getComponent(child.opts.componentClass || toTitleCase(child.name)); + + return c && !Tech.isTech(c); + }).forEach(handleAdd); + } + }; + + /** + * Builds the default DOM class name. Should be overriden by sub-components. + * + * @return {string} + * The DOM class name for this object. + * + * @abstract + */ + + + Component.prototype.buildCSSClass = function buildCSSClass() { + // Child classes can include a function that does: + // return 'CLASS NAME' + this._super(); + return ''; + }; + + /** + * Bind a listener to the component's ready state. + * Different from event listeners in that if the ready event has already happened + * it will trigger the function immediately. + * + * @return {Component} + * Returns itself; method can be chained. + */ + + + Component.prototype.ready = function ready(fn) { + var sync = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!fn) { + return; + } + + if (!this.isReady_) { + this.readyQueue_ = this.readyQueue_ || []; + this.readyQueue_.push(fn); + return; + } + + if (sync) { + fn.call(this); + } else { + // Call the function asynchronously by default for consistency + this.setTimeout(fn, 1); + } + }; + + /** + * Trigger all the ready listeners for this `Component`. + * + * @fires Component#ready + */ + + + Component.prototype.triggerReady = function triggerReady() { + this.isReady_ = true; + + // Ensure ready is triggered asynchronously + this.setTimeout(function () { + var readyQueue = this.readyQueue_; + + // Reset Ready Queue + this.readyQueue_ = []; + + if (readyQueue && readyQueue.length > 0) { + readyQueue.forEach(function (fn) { + fn.call(this); + }, this); + } + + // Allow for using event listeners also + /** + * Triggered when a `Component` is ready. + * + * @event Component#ready + * @type {EventTarget~Event} + */ + this.trigger('ready'); + }, 1); + }; + + /** + * Find a single DOM element matching a `selector`. This can be within the `Component`s + * `contentEl()` or another custom context. + * + * @param {string} selector + * A valid CSS selector, which will be passed to `querySelector`. + * + * @param {Element|string} [context=this.contentEl()] + * A DOM element within which to query. Can also be a selector string in + * which case the first matching element will get used as context. If + * missing `this.contentEl()` gets used. If `this.contentEl()` returns + * nothing it falls back to `document`. + * + * @return {Element|null} + * the dom element that was found, or null + * + * @see [Information on CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_Started/Selectors) + */ + + + Component.prototype.$ = function $$$1(selector, context) { + return $(selector, context || this.contentEl()); + }; + + /** + * Finds all DOM element matching a `selector`. This can be within the `Component`s + * `contentEl()` or another custom context. + * + * @param {string} selector + * A valid CSS selector, which will be passed to `querySelectorAll`. + * + * @param {Element|string} [context=this.contentEl()] + * A DOM element within which to query. Can also be a selector string in + * which case the first matching element will get used as context. If + * missing `this.contentEl()` gets used. If `this.contentEl()` returns + * nothing it falls back to `document`. + * + * @return {NodeList} + * a list of dom elements that were found + * + * @see [Information on CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_Started/Selectors) + */ + + + Component.prototype.$$ = function $$$$1(selector, context) { + return $$(selector, context || this.contentEl()); + }; + + /** + * Check if a component's element has a CSS class name. + * + * @param {string} classToCheck + * CSS class name to check. + * + * @return {boolean} + * - True if the `Component` has the class. + * - False if the `Component` does not have the class` + */ + + + Component.prototype.hasClass = function hasClass$$1(classToCheck) { + return hasClass(this.el_, classToCheck); + }; + + /** + * Add a CSS class name to the `Component`s element. + * + * @param {string} classToAdd + * CSS class name to add + */ + + + Component.prototype.addClass = function addClass$$1(classToAdd) { + addClass(this.el_, classToAdd); + }; + + /** + * Remove a CSS class name from the `Component`s element. + * + * @param {string} classToRemove + * CSS class name to remove + */ + + + Component.prototype.removeClass = function removeClass$$1(classToRemove) { + removeClass(this.el_, classToRemove); + }; + + /** + * Add or remove a CSS class name from the component's element. + * - `classToToggle` gets added when {@link Component#hasClass} would return false. + * - `classToToggle` gets removed when {@link Component#hasClass} would return true. + * + * @param {string} classToToggle + * The class to add or remove based on (@link Component#hasClass} + * + * @param {boolean|Dom~predicate} [predicate] + * An {@link Dom~predicate} function or a boolean + */ + + + Component.prototype.toggleClass = function toggleClass$$1(classToToggle, predicate) { + toggleClass(this.el_, classToToggle, predicate); + }; + + /** + * Show the `Component`s element if it is hidden by removing the + * 'vjs-hidden' class name from it. + */ + + + Component.prototype.show = function show() { + this.removeClass('vjs-hidden'); + }; + + /** + * Hide the `Component`s element if it is currently showing by adding the + * 'vjs-hidden` class name to it. + */ + + + Component.prototype.hide = function hide() { + this.addClass('vjs-hidden'); + }; + + /** + * Lock a `Component`s element in its visible state by adding the 'vjs-lock-showing' + * class name to it. Used during fadeIn/fadeOut. + * + * @private + */ + + + Component.prototype.lockShowing = function lockShowing() { + this.addClass('vjs-lock-showing'); + }; + + /** + * Unlock a `Component`s element from its visible state by removing the 'vjs-lock-showing' + * class name from it. Used during fadeIn/fadeOut. + * + * @private + */ + + + Component.prototype.unlockShowing = function unlockShowing() { + this.removeClass('vjs-lock-showing'); + }; + + /** + * Get the value of an attribute on the `Component`s element. + * + * @param {string} attribute + * Name of the attribute to get the value from. + * + * @return {string|null} + * - The value of the attribute that was asked for. + * - Can be an empty string on some browsers if the attribute does not exist + * or has no value + * - Most browsers will return null if the attibute does not exist or has + * no value. + * + * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute} + */ + + + Component.prototype.getAttribute = function getAttribute$$1(attribute) { + return getAttribute(this.el_, attribute); + }; + + /** + * Set the value of an attribute on the `Component`'s element + * + * @param {string} attribute + * Name of the attribute to set. + * + * @param {string} value + * Value to set the attribute to. + * + * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute} + */ + + + Component.prototype.setAttribute = function setAttribute$$1(attribute, value) { + setAttribute(this.el_, attribute, value); + }; + + /** + * Remove an attribute from the `Component`s element. + * + * @param {string} attribute + * Name of the attribute to remove. + * + * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute} + */ + + + Component.prototype.removeAttribute = function removeAttribute$$1(attribute) { + removeAttribute(this.el_, attribute); + }; + + /** + * Get or set the width of the component based upon the CSS styles. + * See {@link Component#dimension} for more detailed information. + * + * @param {number|string} [num] + * The width that you want to set postfixed with '%', 'px' or nothing. + * + * @param {boolean} [skipListeners] + * Skip the componentresize event trigger + * + * @return {number|string} + * The width when getting, zero if there is no width. Can be a string + * postpixed with '%' or 'px'. + */ + + + Component.prototype.width = function width(num, skipListeners) { + return this.dimension('width', num, skipListeners); + }; + + /** + * Get or set the height of the component based upon the CSS styles. + * See {@link Component#dimension} for more detailed information. + * + * @param {number|string} [num] + * The height that you want to set postfixed with '%', 'px' or nothing. + * + * @param {boolean} [skipListeners] + * Skip the componentresize event trigger + * + * @return {number|string} + * The width when getting, zero if there is no width. Can be a string + * postpixed with '%' or 'px'. + */ + + + Component.prototype.height = function height(num, skipListeners) { + return this.dimension('height', num, skipListeners); + }; + + /** + * Set both the width and height of the `Component` element at the same time. + * + * @param {number|string} width + * Width to set the `Component`s element to. + * + * @param {number|string} height + * Height to set the `Component`s element to. + */ + + + Component.prototype.dimensions = function dimensions(width, height) { + // Skip componentresize listeners on width for optimization + this.width(width, true); + this.height(height); + }; + + /** + * Get or set width or height of the `Component` element. This is the shared code + * for the {@link Component#width} and {@link Component#height}. + * + * Things to know: + * - If the width or height in an number this will return the number postfixed with 'px'. + * - If the width/height is a percent this will return the percent postfixed with '%' + * - Hidden elements have a width of 0 with `window.getComputedStyle`. This function + * defaults to the `Component`s `style.width` and falls back to `window.getComputedStyle`. + * See [this]{@link http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/} + * for more information + * - If you want the computed style of the component, use {@link Component#currentWidth} + * and {@link {Component#currentHeight} + * + * @fires Component#componentresize + * + * @param {string} widthOrHeight + 8 'width' or 'height' + * + * @param {number|string} [num] + 8 New dimension + * + * @param {boolean} [skipListeners] + * Skip componentresize event trigger + * + * @return {number} + * The dimension when getting or 0 if unset + */ + + + Component.prototype.dimension = function dimension(widthOrHeight, num, skipListeners) { + if (num !== undefined) { + // Set to zero if null or literally NaN (NaN !== NaN) + if (num === null || num !== num) { + num = 0; + } + + // Check if using css width/height (% or px) and adjust + if (('' + num).indexOf('%') !== -1 || ('' + num).indexOf('px') !== -1) { + this.el_.style[widthOrHeight] = num; + } else if (num === 'auto') { + this.el_.style[widthOrHeight] = ''; + } else { + this.el_.style[widthOrHeight] = num + 'px'; + } + + // skipListeners allows us to avoid triggering the resize event when setting both width and height + if (!skipListeners) { + /** + * Triggered when a component is resized. + * + * @event Component#componentresize + * @type {EventTarget~Event} + */ + this.trigger('componentresize'); + } + + return; + } + + // Not setting a value, so getting it + // Make sure element exists + if (!this.el_) { + return 0; + } + + // Get dimension value from style + var val = this.el_.style[widthOrHeight]; + var pxIndex = val.indexOf('px'); + + if (pxIndex !== -1) { + // Return the pixel value with no 'px' + return parseInt(val.slice(0, pxIndex), 10); + } + + // No px so using % or no style was set, so falling back to offsetWidth/height + // If component has display:none, offset will return 0 + // TODO: handle display:none and no dimension style using px + return parseInt(this.el_['offset' + toTitleCase(widthOrHeight)], 10); + }; + + /** + * Get the width or the height of the `Component` elements computed style. Uses + * `window.getComputedStyle`. + * + * @param {string} widthOrHeight + * A string containing 'width' or 'height'. Whichever one you want to get. + * + * @return {number} + * The dimension that gets asked for or 0 if nothing was set + * for that dimension. + */ + + + Component.prototype.currentDimension = function currentDimension(widthOrHeight) { + var computedWidthOrHeight = 0; + + if (widthOrHeight !== 'width' && widthOrHeight !== 'height') { + throw new Error('currentDimension only accepts width or height value'); + } + + if (typeof window_1.getComputedStyle === 'function') { + var computedStyle = window_1.getComputedStyle(this.el_); + + computedWidthOrHeight = computedStyle.getPropertyValue(widthOrHeight) || computedStyle[widthOrHeight]; + } + + // remove 'px' from variable and parse as integer + computedWidthOrHeight = parseFloat(computedWidthOrHeight); + + // if the computed value is still 0, it's possible that the browser is lying + // and we want to check the offset values. + // This code also runs wherever getComputedStyle doesn't exist. + if (computedWidthOrHeight === 0) { + var rule = 'offset' + toTitleCase(widthOrHeight); + + computedWidthOrHeight = this.el_[rule]; + } + + return computedWidthOrHeight; + }; + + /** + * An object that contains width and height values of the `Component`s + * computed style. Uses `window.getComputedStyle`. + * + * @typedef {Object} Component~DimensionObject + * + * @property {number} width + * The width of the `Component`s computed style. + * + * @property {number} height + * The height of the `Component`s computed style. + */ + + /** + * Get an object that contains width and height values of the `Component`s + * computed style. + * + * @return {Component~DimensionObject} + * The dimensions of the components element + */ + + + Component.prototype.currentDimensions = function currentDimensions() { + return { + width: this.currentDimension('width'), + height: this.currentDimension('height') + }; + }; + + /** + * Get the width of the `Component`s computed style. Uses `window.getComputedStyle`. + * + * @return {number} width + * The width of the `Component`s computed style. + */ + + + Component.prototype.currentWidth = function currentWidth() { + return this.currentDimension('width'); + }; + + /** + * Get the height of the `Component`s computed style. Uses `window.getComputedStyle`. + * + * @return {number} height + * The height of the `Component`s computed style. + */ + + + Component.prototype.currentHeight = function currentHeight() { + return this.currentDimension('height'); + }; + + /** + * Set the focus to this component + */ + + + Component.prototype.focus = function focus() { + this.el_.focus(); + }; + + /** + * Remove the focus from this component + */ + + + Component.prototype.blur = function blur() { + this.el_.blur(); + }; + + /** + * Emit a 'tap' events when touch event support gets detected. This gets used to + * support toggling the controls through a tap on the video. They get enabled + * because every sub-component would have extra overhead otherwise. + * + * @private + * @fires Component#tap + * @listens Component#touchstart + * @listens Component#touchmove + * @listens Component#touchleave + * @listens Component#touchcancel + * @listens Component#touchend + */ + + + Component.prototype.emitTapEvents = function emitTapEvents() { + // Track the start time so we can determine how long the touch lasted + var touchStart = 0; + var firstTouch = null; + + // Maximum movement allowed during a touch event to still be considered a tap + // Other popular libs use anywhere from 2 (hammer.js) to 15, + // so 10 seems like a nice, round number. + var tapMovementThreshold = 10; + + // The maximum length a touch can be while still being considered a tap + var touchTimeThreshold = 200; + + var couldBeTap = void 0; + + this.on('touchstart', function (event) { + // If more than one finger, don't consider treating this as a click + if (event.touches.length === 1) { + // Copy pageX/pageY from the object + firstTouch = { + pageX: event.touches[0].pageX, + pageY: event.touches[0].pageY + }; + // Record start time so we can detect a tap vs. "touch and hold" + touchStart = new Date().getTime(); + // Reset couldBeTap tracking + couldBeTap = true; + } + }); + + this.on('touchmove', function (event) { + // If more than one finger, don't consider treating this as a click + if (event.touches.length > 1) { + couldBeTap = false; + } else if (firstTouch) { + // Some devices will throw touchmoves for all but the slightest of taps. + // So, if we moved only a small distance, this could still be a tap + var xdiff = event.touches[0].pageX - firstTouch.pageX; + var ydiff = event.touches[0].pageY - firstTouch.pageY; + var touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff); + + if (touchDistance > tapMovementThreshold) { + couldBeTap = false; + } + } + }); + + var noTap = function noTap() { + couldBeTap = false; + }; + + // TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s + this.on('touchleave', noTap); + this.on('touchcancel', noTap); + + // When the touch ends, measure how long it took and trigger the appropriate + // event + this.on('touchend', function (event) { + firstTouch = null; + // Proceed only if the touchmove/leave/cancel event didn't happen + if (couldBeTap === true) { + // Measure how long the touch lasted + var touchTime = new Date().getTime() - touchStart; + + // Make sure the touch was less than the threshold to be considered a tap + if (touchTime < touchTimeThreshold) { + // Don't let browser turn this into a click + event.preventDefault(); + /** + * Triggered when a `Component` is tapped. + * + * @event Component#tap + * @type {EventTarget~Event} + */ + this.trigger('tap'); + // It may be good to copy the touchend event object and change the + // type to tap, if the other event properties aren't exact after + // Events.fixEvent runs (e.g. event.target) + } + } + }); + }; + + /** + * This function reports user activity whenever touch events happen. This can get + * turned off by any sub-components that wants touch events to act another way. + * + * Report user touch activity when touch events occur. User activity gets used to + * determine when controls should show/hide. It is simple when it comes to mouse + * events, because any mouse event should show the controls. So we capture mouse + * events that bubble up to the player and report activity when that happens. + * With touch events it isn't as easy as `touchstart` and `touchend` toggle player + * controls. So touch events can't help us at the player level either. + * + * User activity gets checked asynchronously. So what could happen is a tap event + * on the video turns the controls off. Then the `touchend` event bubbles up to + * the player. Which, if it reported user activity, would turn the controls right + * back on. We also don't want to completely block touch events from bubbling up. + * Furthermore a `touchmove` event and anything other than a tap, should not turn + * controls back on. + * + * @listens Component#touchstart + * @listens Component#touchmove + * @listens Component#touchend + * @listens Component#touchcancel + */ + + + Component.prototype.enableTouchActivity = function enableTouchActivity() { + // Don't continue if the root player doesn't support reporting user activity + if (!this.player() || !this.player().reportUserActivity) { + return; + } + + // listener for reporting that the user is active + var report = bind(this.player(), this.player().reportUserActivity); + + var touchHolding = void 0; + + this.on('touchstart', function () { + report(); + // For as long as the they are touching the device or have their mouse down, + // we consider them active even if they're not moving their finger or mouse. + // So we want to continue to update that they are active + this.clearInterval(touchHolding); + // report at the same interval as activityCheck + touchHolding = this.setInterval(report, 250); + }); + + var touchEnd = function touchEnd(event) { + report(); + // stop the interval that maintains activity if the touch is holding + this.clearInterval(touchHolding); + }; + + this.on('touchmove', report); + this.on('touchend', touchEnd); + this.on('touchcancel', touchEnd); + }; + + /** + * A callback that has no parameters and is bound into `Component`s context. + * + * @callback Component~GenericCallback + * @this Component + */ + + /** + * Creates a function that runs after an `x` millisecond timeout. This function is a + * wrapper around `window.setTimeout`. There are a few reasons to use this one + * instead though: + * 1. It gets cleared via {@link Component#clearTimeout} when + * {@link Component#dispose} gets called. + * 2. The function callback will gets turned into a {@link Component~GenericCallback} + * + * > Note: You can use `window.clearTimeout` on the id returned by this function. This + * will cause its dispose listener not to get cleaned up! Please use + * {@link Component#clearTimeout} or {@link Component#dispose}. + * + * @param {Component~GenericCallback} fn + * The function that will be run after `timeout`. + * + * @param {number} timeout + * Timeout in milliseconds to delay before executing the specified function. + * + * @return {number} + * Returns a timeout ID that gets used to identify the timeout. It can also + * get used in {@link Component#clearTimeout} to clear the timeout that + * was set. + * + * @listens Component#dispose + * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout} + */ + + + Component.prototype.setTimeout = function setTimeout(fn, timeout) { + var _this2 = this; + + fn = bind(this, fn); + + var timeoutId = window_1.setTimeout(fn, timeout); + var disposeFn = function disposeFn() { + return _this2.clearTimeout(timeoutId); + }; + + disposeFn.guid = 'vjs-timeout-' + timeoutId; + + this.on('dispose', disposeFn); + + return timeoutId; + }; + + /** + * Clears a timeout that gets created via `window.setTimeout` or + * {@link Component#setTimeout}. If you set a timeout via {@link Component#setTimeout} + * use this function instead of `window.clearTimout`. If you don't your dispose + * listener will not get cleaned up until {@link Component#dispose}! + * + * @param {number} timeoutId + * The id of the timeout to clear. The return value of + * {@link Component#setTimeout} or `window.setTimeout`. + * + * @return {number} + * Returns the timeout id that was cleared. + * + * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearTimeout} + */ + + + Component.prototype.clearTimeout = function clearTimeout(timeoutId) { + window_1.clearTimeout(timeoutId); + + var disposeFn = function disposeFn() { + }; + + disposeFn.guid = 'vjs-timeout-' + timeoutId; + + this.off('dispose', disposeFn); + + return timeoutId; + }; + + /** + * Creates a function that gets run every `x` milliseconds. This function is a wrapper + * around `window.setInterval`. There are a few reasons to use this one instead though. + * 1. It gets cleared via {@link Component#clearInterval} when + * {@link Component#dispose} gets called. + * 2. The function callback will be a {@link Component~GenericCallback} + * + * @param {Component~GenericCallback} fn + * The function to run every `x` seconds. + * + * @param {number} interval + * Execute the specified function every `x` milliseconds. + * + * @return {number} + * Returns an id that can be used to identify the interval. It can also be be used in + * {@link Component#clearInterval} to clear the interval. + * + * @listens Component#dispose + * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval} + */ + + + Component.prototype.setInterval = function setInterval(fn, interval) { + var _this3 = this; + + fn = bind(this, fn); + + var intervalId = window_1.setInterval(fn, interval); + + var disposeFn = function disposeFn() { + return _this3.clearInterval(intervalId); + }; + + disposeFn.guid = 'vjs-interval-' + intervalId; + + this.on('dispose', disposeFn); + + return intervalId; + }; + + /** + * Clears an interval that gets created via `window.setInterval` or + * {@link Component#setInterval}. If you set an inteval via {@link Component#setInterval} + * use this function instead of `window.clearInterval`. If you don't your dispose + * listener will not get cleaned up until {@link Component#dispose}! + * + * @param {number} intervalId + * The id of the interval to clear. The return value of + * {@link Component#setInterval} or `window.setInterval`. + * + * @return {number} + * Returns the interval id that was cleared. + * + * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearInterval} + */ + + + Component.prototype.clearInterval = function clearInterval(intervalId) { + window_1.clearInterval(intervalId); + + var disposeFn = function disposeFn() { + }; + + disposeFn.guid = 'vjs-interval-' + intervalId; + + this.off('dispose', disposeFn); + + return intervalId; + }; + + /** + * Queues up a callback to be passed to requestAnimationFrame (rAF), but + * with a few extra bonuses: + * + * - Supports browsers that do not support rAF by falling back to + * {@link Component#setTimeout}. + * + * - The callback is turned into a {@link Component~GenericCallback} (i.e. + * bound to the component). + * + * - Automatic cancellation of the rAF callback is handled if the component + * is disposed before it is called. + * + * @param {Component~GenericCallback} fn + * A function that will be bound to this component and executed just + * before the browser's next repaint. + * + * @return {number} + * Returns an rAF ID that gets used to identify the timeout. It can + * also be used in {@link Component#cancelAnimationFrame} to cancel + * the animation frame callback. + * + * @listens Component#dispose + * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame} + */ + + + Component.prototype.requestAnimationFrame = function requestAnimationFrame(fn) { + var _this4 = this; + + if (this.supportsRaf_) { + fn = bind(this, fn); + + var id = window_1.requestAnimationFrame(fn); + var disposeFn = function disposeFn() { + return _this4.cancelAnimationFrame(id); + }; + + disposeFn.guid = 'vjs-raf-' + id; + this.on('dispose', disposeFn); + + return id; + } + + // Fall back to using a timer. + return this.setTimeout(fn, 1000 / 60); + }; + + /** + * Cancels a queued callback passed to {@link Component#requestAnimationFrame} + * (rAF). + * + * If you queue an rAF callback via {@link Component#requestAnimationFrame}, + * use this function instead of `window.cancelAnimationFrame`. If you don't, + * your dispose listener will not get cleaned up until {@link Component#dispose}! + * + * @param {number} id + * The rAF ID to clear. The return value of {@link Component#requestAnimationFrame}. + * + * @return {number} + * Returns the rAF ID that was cleared. + * + * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/window/cancelAnimationFrame} + */ + + + Component.prototype.cancelAnimationFrame = function cancelAnimationFrame(id) { + if (this.supportsRaf_) { + window_1.cancelAnimationFrame(id); + + var disposeFn = function disposeFn() { + }; + + disposeFn.guid = 'vjs-raf-' + id; + + this.off('dispose', disposeFn); + + return id; + } + + // Fall back to using a timer. + return this.clearTimeout(id); + }; + + /** + * Register a `Component` with `videojs` given the name and the component. + * + * > NOTE: {@link Tech}s should not be registered as a `Component`. {@link Tech}s + * should be registered using {@link Tech.registerTech} or + * {@link videojs:videojs.registerTech}. + * + * > NOTE: This function can also be seen on videojs as + * {@link videojs:videojs.registerComponent}. + * + * @param {string} name + * The name of the `Component` to register. + * + * @param {Component} ComponentToRegister + * The `Component` class to register. + * + * @return {Component} + * The `Component` that was registered. + */ + + + Component.registerComponent = function registerComponent(name, ComponentToRegister) { + if (typeof name !== 'string' || !name) { + throw new Error('Illegal component name, "' + name + '"; must be a non-empty string.'); + } + + var Tech = Component.getComponent('Tech'); + + // We need to make sure this check is only done if Tech has been registered. + var isTech = Tech && Tech.isTech(ComponentToRegister); + var isComp = Component === ComponentToRegister || Component.prototype.isPrototypeOf(ComponentToRegister.prototype); + + if (isTech || !isComp) { + var reason = void 0; + + if (isTech) { + reason = 'techs must be registered using Tech.registerTech()'; + } else { + reason = 'must be a Component subclass'; + } + + throw new Error('Illegal component, "' + name + '"; ' + reason + '.'); + } + + name = toTitleCase(name); + + if (!Component.components_) { + Component.components_ = {}; + } + + var Player = Component.getComponent('Player'); + + if (name === 'Player' && Player && Player.players) { + var players = Player.players; + var playerNames = Object.keys(players); + + // If we have players that were disposed, then their name will still be + // in Players.players. So, we must loop through and verify that the value + // for each item is not null. This allows registration of the Player component + // after all players have been disposed or before any were created. + if (players && playerNames.length > 0 && playerNames.map(function (pname) { + return players[pname]; + }).every(Boolean)) { + throw new Error('Can not register Player component after player has been created.'); + } + } + + Component.components_[name] = ComponentToRegister; + + return ComponentToRegister; + }; + + /** + * Get a `Component` based on the name it was registered with. + * + * @param {string} name + * The Name of the component to get. + * + * @return {Component} + * The `Component` that got registered under the given name. + * + * @deprecated In `videojs` 6 this will not return `Component`s that were not + * registered using {@link Component.registerComponent}. Currently we + * check the global `videojs` object for a `Component` name and + * return that if it exists. + */ + + + Component.getComponent = function getComponent(name) { + if (!name) { + return; + } + + name = toTitleCase(name); + + if (Component.components_ && Component.components_[name]) { + return Component.components_[name]; + } + }; + + return Component; + }(); + + /** + * Whether or not this component supports `requestAnimationFrame`. + * + * This is exposed primarily for testing purposes. + * + * @private + * @type {Boolean} + */ + + + Component.prototype.supportsRaf_ = typeof window_1.requestAnimationFrame === 'function' && typeof window_1.cancelAnimationFrame === 'function'; + + Component.registerComponent('Component', Component); + + /** + * @file browser.js + * @module browser + */ + + var USER_AGENT = window_1.navigator && window_1.navigator.userAgent || ''; + var webkitVersionMap = /AppleWebKit\/([\d.]+)/i.exec(USER_AGENT); + var appleWebkitVersion = webkitVersionMap ? parseFloat(webkitVersionMap.pop()) : null; + + /* + * Device is an iPhone + * + * @type {Boolean} + * @constant + * @private + */ + var IS_IPAD = /iPad/i.test(USER_AGENT); + + // The Facebook app's UIWebView identifies as both an iPhone and iPad, so + // to identify iPhones, we need to exclude iPads. + // http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/ + var IS_IPHONE = /iPhone/i.test(USER_AGENT) && !IS_IPAD; + var IS_IPOD = /iPod/i.test(USER_AGENT); + var IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD; + + var IOS_VERSION = function () { + var match = USER_AGENT.match(/OS (\d+)_/i); + + if (match && match[1]) { + return match[1]; + } + return null; + }(); + + var IS_ANDROID = /Android/i.test(USER_AGENT); + var ANDROID_VERSION = function () { + // This matches Android Major.Minor.Patch versions + // ANDROID_VERSION is Major.Minor as a Number, if Minor isn't available, then only Major is returned + var match = USER_AGENT.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i); + + if (!match) { + return null; + } + + var major = match[1] && parseFloat(match[1]); + var minor = match[2] && parseFloat(match[2]); + + if (major && minor) { + return parseFloat(match[1] + '.' + match[2]); + } else if (major) { + return major; + } + return null; + }(); + + var IS_NATIVE_ANDROID = IS_ANDROID && ANDROID_VERSION < 5 && appleWebkitVersion < 537; + + var IS_FIREFOX = /Firefox/i.test(USER_AGENT); + var IS_EDGE = /Edge/i.test(USER_AGENT); + var IS_CHROME = !IS_EDGE && /Chrome/i.test(USER_AGENT); + var CHROME_VERSION = function () { + var match = USER_AGENT.match(/Chrome\/(\d+)/); + + if (match && match[1]) { + return parseFloat(match[1]); + } + return null; + }(); + var IE_VERSION = function () { + var result = /MSIE\s(\d+)\.\d/.exec(USER_AGENT); + var version = result && parseFloat(result[1]); + + if (!version && /Trident\/7.0/i.test(USER_AGENT) && /rv:11.0/.test(USER_AGENT)) { + // IE 11 has a different user agent string than other IE versions + version = 11.0; + } + + return version; + }(); + + var IS_SAFARI = /Safari/i.test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE; + var IS_ANY_SAFARI = IS_SAFARI || IS_IOS; + + var TOUCH_ENABLED = isReal() && ('ontouchstart' in window_1 || window_1.DocumentTouch && window_1.document instanceof window_1.DocumentTouch); + + var browser = /*#__PURE__*/Object.freeze({ + IS_IPAD: IS_IPAD, + IS_IPHONE: IS_IPHONE, + IS_IPOD: IS_IPOD, + IS_IOS: IS_IOS, + IOS_VERSION: IOS_VERSION, + IS_ANDROID: IS_ANDROID, + ANDROID_VERSION: ANDROID_VERSION, + IS_NATIVE_ANDROID: IS_NATIVE_ANDROID, + IS_FIREFOX: IS_FIREFOX, + IS_EDGE: IS_EDGE, + IS_CHROME: IS_CHROME, + CHROME_VERSION: CHROME_VERSION, + IE_VERSION: IE_VERSION, + IS_SAFARI: IS_SAFARI, + IS_ANY_SAFARI: IS_ANY_SAFARI, + TOUCH_ENABLED: TOUCH_ENABLED + }); + + /** + * @file time-ranges.js + * @module time-ranges + */ + + /** + * Returns the time for the specified index at the start or end + * of a TimeRange object. + * + * @function time-ranges:indexFunction + * + * @param {number} [index=0] + * The range number to return the time for. + * + * @return {number} + * The time that offset at the specified index. + * + * @depricated index must be set to a value, in the future this will throw an error. + */ + + /** + * An object that contains ranges of time for various reasons. + * + * @typedef {Object} TimeRange + * + * @property {number} length + * The number of time ranges represented by this Object + * + * @property {time-ranges:indexFunction} start + * Returns the time offset at which a specified time range begins. + * + * @property {time-ranges:indexFunction} end + * Returns the time offset at which a specified time range ends. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges + */ + + /** + * Check if any of the time ranges are over the maximum index. + * + * @param {string} fnName + * The function name to use for logging + * + * @param {number} index + * The index to check + * + * @param {number} maxIndex + * The maximum possible index + * + * @throws {Error} if the timeRanges provided are over the maxIndex + */ + function rangeCheck(fnName, index, maxIndex) { + if (typeof index !== 'number' || index < 0 || index > maxIndex) { + throw new Error('Failed to execute \'' + fnName + '\' on \'TimeRanges\': The index provided (' + index + ') is non-numeric or out of bounds (0-' + maxIndex + ').'); + } + } + + /** + * Get the time for the specified index at the start or end + * of a TimeRange object. + * + * @param {string} fnName + * The function name to use for logging + * + * @param {string} valueIndex + * The property that should be used to get the time. should be 'start' or 'end' + * + * @param {Array} ranges + * An array of time ranges + * + * @param {Array} [rangeIndex=0] + * The index to start the search at + * + * @return {number} + * The time that offset at the specified index. + * + * + * @depricated rangeIndex must be set to a value, in the future this will throw an error. + * @throws {Error} if rangeIndex is more than the length of ranges + */ + function getRange(fnName, valueIndex, ranges, rangeIndex) { + rangeCheck(fnName, rangeIndex, ranges.length - 1); + return ranges[rangeIndex][valueIndex]; + } + + /** + * Create a time range object given ranges of time. + * + * @param {Array} [ranges] + * An array of time ranges. + */ + function createTimeRangesObj(ranges) { + if (ranges === undefined || ranges.length === 0) { + return { + length: 0, + start: function start() { + throw new Error('This TimeRanges object is empty'); + }, + end: function end() { + throw new Error('This TimeRanges object is empty'); + } + }; + } + return { + length: ranges.length, + start: getRange.bind(null, 'start', 0, ranges), + end: getRange.bind(null, 'end', 1, ranges) + }; + } + + /** + * Should create a fake `TimeRange` object which mimics an HTML5 time range instance. + * + * @param {number|Array} start + * The start of a single range or an array of ranges + * + * @param {number} end + * The end of a single range. + * + * @private + */ + function createTimeRanges(start, end) { + if (Array.isArray(start)) { + return createTimeRangesObj(start); + } else if (start === undefined || end === undefined) { + return createTimeRangesObj(); + } + return createTimeRangesObj([[start, end]]); + } + + /** + * @file buffer.js + * @module buffer + */ + + /** + * Compute the percentage of the media that has been buffered. + * + * @param {TimeRange} buffered + * The current `TimeRange` object representing buffered time ranges + * + * @param {number} duration + * Total duration of the media + * + * @return {number} + * Percent buffered of the total duration in decimal form. + */ + function bufferedPercent(buffered, duration) { + var bufferedDuration = 0; + var start = void 0; + var end = void 0; + + if (!duration) { + return 0; + } + + if (!buffered || !buffered.length) { + buffered = createTimeRanges(0, 0); + } + + for (var i = 0; i < buffered.length; i++) { + start = buffered.start(i); + end = buffered.end(i); + + // buffered end can be bigger than duration by a very small fraction + if (end > duration) { + end = duration; + } + + bufferedDuration += end - start; + } + + return bufferedDuration / duration; + } + + /** + * @file fullscreen-api.js + * @module fullscreen-api + * @private + */ + + /** + * Store the browser-specific methods for the fullscreen API. + * + * @type {Object} + * @see [Specification]{@link https://fullscreen.spec.whatwg.org} + * @see [Map Approach From Screenfull.js]{@link https://github.com/sindresorhus/screenfull.js} + */ + var FullscreenApi = {}; + + // browser API methods + var apiMap = [['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'], + // WebKit + ['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror'], + // Old WebKit (Safari 5.1) + ['webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror'], + // Mozilla + ['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'], + // Microsoft + ['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']]; + + var specApi = apiMap[0]; + var browserApi = void 0; + + // determine the supported set of functions + for (var i = 0; i < apiMap.length; i++) { + // check for exitFullscreen function + if (apiMap[i][1] in document_1) { + browserApi = apiMap[i]; + break; + } + } + + // map the browser API names to the spec API names + if (browserApi) { + for (var _i = 0; _i < browserApi.length; _i++) { + FullscreenApi[specApi[_i]] = browserApi[_i]; + } + } + + /** + * @file media-error.js + */ + + /** + * A Custom `MediaError` class which mimics the standard HTML5 `MediaError` class. + * + * @param {number|string|Object|MediaError} value + * This can be of multiple types: + * - number: should be a standard error code + * - string: an error message (the code will be 0) + * - Object: arbitrary properties + * - `MediaError` (native): used to populate a video.js `MediaError` object + * - `MediaError` (video.js): will return itself if it's already a + * video.js `MediaError` object. + * + * @see [MediaError Spec]{@link https://dev.w3.org/html5/spec-author-view/video.html#mediaerror} + * @see [Encrypted MediaError Spec]{@link https://www.w3.org/TR/2013/WD-encrypted-media-20130510/#error-codes} + * + * @class MediaError + */ + function MediaError(value) { + + // Allow redundant calls to this constructor to avoid having `instanceof` + // checks peppered around the code. + if (value instanceof MediaError) { + return value; + } + + if (typeof value === 'number') { + this.code = value; + } else if (typeof value === 'string') { + // default code is zero, so this is a custom error + this.message = value; + } else if (isObject(value)) { + + // We assign the `code` property manually because native `MediaError` objects + // do not expose it as an own/enumerable property of the object. + if (typeof value.code === 'number') { + this.code = value.code; + } + + assign(this, value); + } + + if (!this.message) { + this.message = MediaError.defaultMessages[this.code] || ''; + } + } + + /** + * The error code that refers two one of the defined `MediaError` types + * + * @type {Number} + */ + MediaError.prototype.code = 0; + + /** + * An optional message that to show with the error. Message is not part of the HTML5 + * video spec but allows for more informative custom errors. + * + * @type {String} + */ + MediaError.prototype.message = ''; + + /** + * An optional status code that can be set by plugins to allow even more detail about + * the error. For example a plugin might provide a specific HTTP status code and an + * error message for that code. Then when the plugin gets that error this class will + * know how to display an error message for it. This allows a custom message to show + * up on the `Player` error overlay. + * + * @type {Array} + */ + MediaError.prototype.status = null; + + /** + * Errors indexed by the W3C standard. The order **CANNOT CHANGE**! See the + * specification listed under {@link MediaError} for more information. + * + * @enum {array} + * @readonly + * @property {string} 0 - MEDIA_ERR_CUSTOM + * @property {string} 1 - MEDIA_ERR_CUSTOM + * @property {string} 2 - MEDIA_ERR_ABORTED + * @property {string} 3 - MEDIA_ERR_NETWORK + * @property {string} 4 - MEDIA_ERR_SRC_NOT_SUPPORTED + * @property {string} 5 - MEDIA_ERR_ENCRYPTED + */ + MediaError.errorTypes = ['MEDIA_ERR_CUSTOM', 'MEDIA_ERR_ABORTED', 'MEDIA_ERR_NETWORK', 'MEDIA_ERR_DECODE', 'MEDIA_ERR_SRC_NOT_SUPPORTED', 'MEDIA_ERR_ENCRYPTED']; + + /** + * The default `MediaError` messages based on the {@link MediaError.errorTypes}. + * + * @type {Array} + * @constant + */ + MediaError.defaultMessages = { + 1: 'You aborted the media playback', + 2: 'A network error caused the media download to fail part-way.', + 3: 'The media playback was aborted due to a corruption problem or because the media used features your browser did not support.', + 4: 'The media could not be loaded, either because the server or network failed or because the format is not supported.', + 5: 'The media is encrypted and we do not have the keys to decrypt it.' + }; + + // Add types as properties on MediaError + // e.g. MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = 4; + for (var errNum = 0; errNum < MediaError.errorTypes.length; errNum++) { + MediaError[MediaError.errorTypes[errNum]] = errNum; + // values should be accessible on both the class and instance + MediaError.prototype[MediaError.errorTypes[errNum]] = errNum; + } + + var tuple = SafeParseTuple; + + function SafeParseTuple(obj, reviver) { + var json; + var error = null; + + try { + json = JSON.parse(obj, reviver); + } catch (err) { + error = err; + } + + return [error, json]; + } + + /** + * Returns whether an object is `Promise`-like (i.e. has a `then` method). + * + * @param {Object} value + * An object that may or may not be `Promise`-like. + * + * @return {Boolean} + * Whether or not the object is `Promise`-like. + */ + function isPromise(value) { + return value !== undefined && value !== null && typeof value.then === 'function'; + } + + /** + * Silence a Promise-like object. + * + * This is useful for avoiding non-harmful, but potentially confusing "uncaught + * playOld promise" rejection error messages. + * + * @param {Object} value + * An object that may or may not be `Promise`-like. + */ + function silencePromise(value) { + if (isPromise(value)) { + value.then(null, function (e) { + }); + } + } + + /** + * @file text-track-list-converter.js Utilities for capturing text track state and + * re-creating tracks based on a capture. + * + * @module text-track-list-converter + */ + + /** + * Examine a single {@link TextTrack} and return a JSON-compatible javascript object that + * represents the {@link TextTrack}'s state. + * + * @param {TextTrack} track + * The text track to query. + * + * @return {Object} + * A serializable javascript representation of the TextTrack. + * @private + */ + var trackToJson_ = function trackToJson_(track) { + var ret = ['kind', 'label', 'language', 'id', 'inBandMetadataTrackDispatchType', 'mode', 'src'].reduce(function (acc, prop, i) { + + if (track[prop]) { + acc[prop] = track[prop]; + } + + return acc; + }, { + cues: track.cues && Array.prototype.map.call(track.cues, function (cue) { + return { + startTime: cue.startTime, + endTime: cue.endTime, + text: cue.text, + id: cue.id + }; + }) + }); + + return ret; + }; + + /** + * Examine a {@link Tech} and return a JSON-compatible javascript array that represents the + * state of all {@link TextTrack}s currently configured. The return array is compatible with + * {@link text-track-list-converter:jsonToTextTracks}. + * + * @param {Tech} tech + * The tech object to query + * + * @return {Array} + * A serializable javascript representation of the {@link Tech}s + * {@link TextTrackList}. + */ + var textTracksToJson = function textTracksToJson(tech) { + + var trackEls = tech.$$('track'); + + var trackObjs = Array.prototype.map.call(trackEls, function (t) { + return t.track; + }); + var tracks = Array.prototype.map.call(trackEls, function (trackEl) { + var json = trackToJson_(trackEl.track); + + if (trackEl.src) { + json.src = trackEl.src; + } + return json; + }); + + return tracks.concat(Array.prototype.filter.call(tech.textTracks(), function (track) { + return trackObjs.indexOf(track) === -1; + }).map(trackToJson_)); + }; + + /** + * Create a set of remote {@link TextTrack}s on a {@link Tech} based on an array of javascript + * object {@link TextTrack} representations. + * + * @param {Array} json + * An array of `TextTrack` representation objects, like those that would be + * produced by `textTracksToJson`. + * + * @param {Tech} tech + * The `Tech` to create the `TextTrack`s on. + */ + var jsonToTextTracks = function jsonToTextTracks(json, tech) { + json.forEach(function (track) { + var addedTrack = tech.addRemoteTextTrack(track).track; + + if (!track.src && track.cues) { + track.cues.forEach(function (cue) { + return addedTrack.addCue(cue); + }); + } + }); + + return tech.textTracks(); + }; + + var textTrackConverter = { + textTracksToJson: textTracksToJson, + jsonToTextTracks: jsonToTextTracks, + trackToJson_: trackToJson_ + }; + + /** + * @file modal-dialog.js + */ + + var MODAL_CLASS_NAME = 'vjs-modal-dialog'; + var ESC = 27; + + /** + * The `ModalDialog` displays over the video and its controls, which blocks + * interaction with the player until it is closed. + * + * Modal dialogs include a "Close" button and will close when that button + * is activated - or when ESC is pressed anywhere. + * + * @extends Component + */ + + var ModalDialog = function (_Component) { + inherits(ModalDialog, _Component); + + /** + * Create an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Mixed} [options.content=undefined] + * Provide customized content for this modal. + * + * @param {string} [options.description] + * A text description for the modal, primarily for accessibility. + * + * @param {boolean} [options.fillAlways=false] + * Normally, modals are automatically filled only the first time + * they open. This tells the modal to refresh its content + * every time it opens. + * + * @param {string} [options.label] + * A text label for the modal, primarily for accessibility. + * + * @param {boolean} [options.temporary=true] + * If `true`, the modal can only be opened once; it will be + * disposed as soon as it's closed. + * + * @param {boolean} [options.uncloseable=false] + * If `true`, the user will not be able to close the modal + * through the UI in the normal ways. Programmatic closing is + * still possible. + */ + function ModalDialog(player, options) { + classCallCheck(this, ModalDialog); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.opened_ = _this.hasBeenOpened_ = _this.hasBeenFilled_ = false; + + _this.closeable(!_this.options_.uncloseable); + _this.content(_this.options_.content); + + // Make sure the contentEl is defined AFTER any children are initialized + // because we only want the contents of the modal in the contentEl + // (not the UI elements like the close button). + _this.contentEl_ = createEl('div', { + className: MODAL_CLASS_NAME + '-content' + }, { + role: 'document' + }); + + _this.descEl_ = createEl('p', { + className: MODAL_CLASS_NAME + '-description vjs-control-text', + id: _this.el().getAttribute('aria-describedby') + }); + + textContent(_this.descEl_, _this.description()); + _this.el_.appendChild(_this.descEl_); + _this.el_.appendChild(_this.contentEl_); + return _this; + } + + /** + * Create the `ModalDialog`'s DOM element + * + * @return {Element} + * The DOM element that gets created. + */ + + + ModalDialog.prototype.createEl = function createEl$$1() { + return _Component.prototype.createEl.call(this, 'div', { + className: this.buildCSSClass(), + tabIndex: -1 + }, { + 'aria-describedby': this.id() + '_description', + 'aria-hidden': 'true', + 'aria-label': this.label(), + 'role': 'dialog' + }); + }; + + ModalDialog.prototype.dispose = function dispose() { + this.contentEl_ = null; + this.descEl_ = null; + this.previouslyActiveEl_ = null; + + _Component.prototype.dispose.call(this); + }; + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + ModalDialog.prototype.buildCSSClass = function buildCSSClass() { + return MODAL_CLASS_NAME + ' vjs-hidden ' + _Component.prototype.buildCSSClass.call(this); + }; + + /** + * Handles `keydown` events on the document, looking for ESC, which closes + * the modal. + * + * @param {EventTarget~Event} e + * The keypress that triggered this event. + * + * @listens keydown + */ + + + ModalDialog.prototype.handleKeyPress = function handleKeyPress(e) { + if (e.which === ESC && this.closeable()) { + this.close(); + } + }; + + /** + * Returns the label string for this modal. Primarily used for accessibility. + * + * @return {string} + * the localized or raw label of this modal. + */ + + + ModalDialog.prototype.label = function label() { + return this.localize(this.options_.label || 'Modal Window'); + }; + + /** + * Returns the description string for this modal. Primarily used for + * accessibility. + * + * @return {string} + * The localized or raw description of this modal. + */ + + + ModalDialog.prototype.description = function description() { + var desc = this.options_.description || this.localize('This is a modal window.'); + + // Append a universal closeability message if the modal is closeable. + if (this.closeable()) { + desc += ' ' + this.localize('This modal can be closed by pressing the Escape key or activating the close button.'); + } + + return desc; + }; + + /** + * Opens the modal. + * + * @fires ModalDialog#beforemodalopen + * @fires ModalDialog#modalopen + */ + + + ModalDialog.prototype.open = function open() { + if (!this.opened_) { + var player = this.player(); + + /** + * Fired just before a `ModalDialog` is opened. + * + * @event ModalDialog#beforemodalopen + * @type {EventTarget~Event} + */ + this.trigger('beforemodalopen'); + this.opened_ = true; + + // Fill content if the modal has never opened before and + // never been filled. + if (this.options_.fillAlways || !this.hasBeenOpened_ && !this.hasBeenFilled_) { + this.fill(); + } + + // If the player was playing, pause it and take note of its previously + // playing state. + this.wasPlaying_ = !player.paused(); + + if (this.options_.pauseOnOpen && this.wasPlaying_) { + player.pause(); + } + + if (this.closeable()) { + this.on(this.el_.ownerDocument, 'keydown', bind(this, this.handleKeyPress)); + } + + // Hide controls and note if they were enabled. + this.hadControls_ = player.controls(); + player.controls(false); + + this.show(); + this.conditionalFocus_(); + this.el().setAttribute('aria-hidden', 'false'); + + /** + * Fired just after a `ModalDialog` is opened. + * + * @event ModalDialog#modalopen + * @type {EventTarget~Event} + */ + this.trigger('modalopen'); + this.hasBeenOpened_ = true; + } + }; + + /** + * If the `ModalDialog` is currently open or closed. + * + * @param {boolean} [value] + * If given, it will open (`true`) or close (`false`) the modal. + * + * @return {boolean} + * the current open state of the modaldialog + */ + + + ModalDialog.prototype.opened = function opened(value) { + if (typeof value === 'boolean') { + this[value ? 'open' : 'close'](); + } + return this.opened_; + }; + + /** + * Closes the modal, does nothing if the `ModalDialog` is + * not open. + * + * @fires ModalDialog#beforemodalclose + * @fires ModalDialog#modalclose + */ + + + ModalDialog.prototype.close = function close() { + if (!this.opened_) { + return; + } + var player = this.player(); + + /** + * Fired just before a `ModalDialog` is closed. + * + * @event ModalDialog#beforemodalclose + * @type {EventTarget~Event} + */ + this.trigger('beforemodalclose'); + this.opened_ = false; + + if (this.wasPlaying_ && this.options_.pauseOnOpen) { + player.play(); + } + + if (this.closeable()) { + this.off(this.el_.ownerDocument, 'keydown', bind(this, this.handleKeyPress)); + } + + if (this.hadControls_) { + player.controls(true); + } + + this.hide(); + this.el().setAttribute('aria-hidden', 'true'); + + /** + * Fired just after a `ModalDialog` is closed. + * + * @event ModalDialog#modalclose + * @type {EventTarget~Event} + */ + this.trigger('modalclose'); + this.conditionalBlur_(); + + if (this.options_.temporary) { + this.dispose(); + } + }; + + /** + * Check to see if the `ModalDialog` is closeable via the UI. + * + * @param {boolean} [value] + * If given as a boolean, it will set the `closeable` option. + * + * @return {boolean} + * Returns the final value of the closable option. + */ + + + ModalDialog.prototype.closeable = function closeable(value) { + if (typeof value === 'boolean') { + var closeable = this.closeable_ = !!value; + var close = this.getChild('closeButton'); + + // If this is being made closeable and has no close button, add one. + if (closeable && !close) { + + // The close button should be a child of the modal - not its + // content element, so temporarily change the content element. + var temp = this.contentEl_; + + this.contentEl_ = this.el_; + close = this.addChild('closeButton', {controlText: 'Close Modal Dialog'}); + this.contentEl_ = temp; + this.on(close, 'close', this.close); + } + + // If this is being made uncloseable and has a close button, remove it. + if (!closeable && close) { + this.off(close, 'close', this.close); + this.removeChild(close); + close.dispose(); + } + } + return this.closeable_; + }; + + /** + * Fill the modal's content element with the modal's "content" option. + * The content element will be emptied before this change takes place. + */ + + + ModalDialog.prototype.fill = function fill() { + this.fillWith(this.content()); + }; + + /** + * Fill the modal's content element with arbitrary content. + * The content element will be emptied before this change takes place. + * + * @fires ModalDialog#beforemodalfill + * @fires ModalDialog#modalfill + * + * @param {Mixed} [content] + * The same rules apply to this as apply to the `content` option. + */ + + + ModalDialog.prototype.fillWith = function fillWith(content) { + var contentEl = this.contentEl(); + var parentEl = contentEl.parentNode; + var nextSiblingEl = contentEl.nextSibling; + + /** + * Fired just before a `ModalDialog` is filled with content. + * + * @event ModalDialog#beforemodalfill + * @type {EventTarget~Event} + */ + this.trigger('beforemodalfill'); + this.hasBeenFilled_ = true; + + // Detach the content element from the DOM before performing + // manipulation to avoid modifying the live DOM multiple times. + parentEl.removeChild(contentEl); + this.empty(); + insertContent(contentEl, content); + /** + * Fired just after a `ModalDialog` is filled with content. + * + * @event ModalDialog#modalfill + * @type {EventTarget~Event} + */ + this.trigger('modalfill'); + + // Re-inject the re-filled content element. + if (nextSiblingEl) { + parentEl.insertBefore(contentEl, nextSiblingEl); + } else { + parentEl.appendChild(contentEl); + } + + // make sure that the close button is last in the dialog DOM + var closeButton = this.getChild('closeButton'); + + if (closeButton) { + parentEl.appendChild(closeButton.el_); + } + }; + + /** + * Empties the content element. This happens anytime the modal is filled. + * + * @fires ModalDialog#beforemodalempty + * @fires ModalDialog#modalempty + */ + + + ModalDialog.prototype.empty = function empty() { + /** + * Fired just before a `ModalDialog` is emptied. + * + * @event ModalDialog#beforemodalempty + * @type {EventTarget~Event} + */ + this.trigger('beforemodalempty'); + emptyEl(this.contentEl()); + + /** + * Fired just after a `ModalDialog` is emptied. + * + * @event ModalDialog#modalempty + * @type {EventTarget~Event} + */ + this.trigger('modalempty'); + }; + + /** + * Gets or sets the modal content, which gets normalized before being + * rendered into the DOM. + * + * This does not update the DOM or fill the modal, but it is called during + * that process. + * + * @param {Mixed} [value] + * If defined, sets the internal content value to be used on the + * next call(s) to `fill`. This value is normalized before being + * inserted. To "clear" the internal content value, pass `null`. + * + * @return {Mixed} + * The current content of the modal dialog + */ + + + ModalDialog.prototype.content = function content(value) { + if (typeof value !== 'undefined') { + this.content_ = value; + } + return this.content_; + }; + + /** + * conditionally focus the modal dialog if focus was previously on the player. + * + * @private + */ + + + ModalDialog.prototype.conditionalFocus_ = function conditionalFocus_() { + var activeEl = document_1.activeElement; + var playerEl = this.player_.el_; + + this.previouslyActiveEl_ = null; + + if (playerEl.contains(activeEl) || playerEl === activeEl) { + this.previouslyActiveEl_ = activeEl; + + this.focus(); + + this.on(document_1, 'keydown', this.handleKeyDown); + } + }; + + /** + * conditionally blur the element and refocus the last focused element + * + * @private + */ + + + ModalDialog.prototype.conditionalBlur_ = function conditionalBlur_() { + if (this.previouslyActiveEl_) { + this.previouslyActiveEl_.focus(); + this.previouslyActiveEl_ = null; + } + + this.off(document_1, 'keydown', this.handleKeyDown); + }; + + /** + * Keydown handler. Attached when modal is focused. + * + * @listens keydown + */ + + + ModalDialog.prototype.handleKeyDown = function handleKeyDown(event) { + // exit early if it isn't a tab key + if (event.which !== 9) { + return; + } + + var focusableEls = this.focusableEls_(); + var activeEl = this.el_.querySelector(':focus'); + var focusIndex = void 0; + + for (var i = 0; i < focusableEls.length; i++) { + if (activeEl === focusableEls[i]) { + focusIndex = i; + break; + } + } + + if (document_1.activeElement === this.el_) { + focusIndex = 0; + } + + if (event.shiftKey && focusIndex === 0) { + focusableEls[focusableEls.length - 1].focus(); + event.preventDefault(); + } else if (!event.shiftKey && focusIndex === focusableEls.length - 1) { + focusableEls[0].focus(); + event.preventDefault(); + } + }; + + /** + * get all focusable elements + * + * @private + */ + + + ModalDialog.prototype.focusableEls_ = function focusableEls_() { + var allChildren = this.el_.querySelectorAll('*'); + + return Array.prototype.filter.call(allChildren, function (child) { + return (child instanceof window_1.HTMLAnchorElement || child instanceof window_1.HTMLAreaElement) && child.hasAttribute('href') || (child instanceof window_1.HTMLInputElement || child instanceof window_1.HTMLSelectElement || child instanceof window_1.HTMLTextAreaElement || child instanceof window_1.HTMLButtonElement) && !child.hasAttribute('disabled') || child instanceof window_1.HTMLIFrameElement || child instanceof window_1.HTMLObjectElement || child instanceof window_1.HTMLEmbedElement || child.hasAttribute('tabindex') && child.getAttribute('tabindex') !== -1 || child.hasAttribute('contenteditable'); + }); + }; + + return ModalDialog; + }(Component); + + /** + * Default options for `ModalDialog` default options. + * + * @type {Object} + * @private + */ + + + ModalDialog.prototype.options_ = { + pauseOnOpen: true, + temporary: true + }; + + Component.registerComponent('ModalDialog', ModalDialog); + + /** + * @file track-list.js + */ + + /** + * Common functionaliy between {@link TextTrackList}, {@link AudioTrackList}, and + * {@link VideoTrackList} + * + * @extends EventTarget + */ + + var TrackList = function (_EventTarget) { + inherits(TrackList, _EventTarget); + + /** + * Create an instance of this class + * + * @param {Track[]} tracks + * A list of tracks to initialize the list with. + * + * @abstract + */ + function TrackList() { + var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + classCallCheck(this, TrackList); + + var _this = possibleConstructorReturn(this, _EventTarget.call(this)); + + _this.tracks_ = []; + + /** + * @memberof TrackList + * @member {number} length + * The current number of `Track`s in the this Trackist. + * @instance + */ + Object.defineProperty(_this, 'length', { + get: function get$$1() { + return this.tracks_.length; + } + }); + + for (var i = 0; i < tracks.length; i++) { + _this.addTrack(tracks[i]); + } + return _this; + } + + /** + * Add a {@link Track} to the `TrackList` + * + * @param {Track} track + * The audio, video, or text track to add to the list. + * + * @fires TrackList#addtrack + */ + + + TrackList.prototype.addTrack = function addTrack(track) { + var index = this.tracks_.length; + + if (!('' + index in this)) { + Object.defineProperty(this, index, { + get: function get$$1() { + return this.tracks_[index]; + } + }); + } + + // Do not add duplicate tracks + if (this.tracks_.indexOf(track) === -1) { + this.tracks_.push(track); + /** + * Triggered when a track is added to a track list. + * + * @event TrackList#addtrack + * @type {EventTarget~Event} + * @property {Track} track + * A reference to track that was added. + */ + this.trigger({ + track: track, + type: 'addtrack' + }); + } + }; + + /** + * Remove a {@link Track} from the `TrackList` + * + * @param {Track} rtrack + * The audio, video, or text track to remove from the list. + * + * @fires TrackList#removetrack + */ + + + TrackList.prototype.removeTrack = function removeTrack(rtrack) { + var track = void 0; + + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === rtrack) { + track = this[i]; + if (track.off) { + track.off(); + } + + this.tracks_.splice(i, 1); + + break; + } + } + + if (!track) { + return; + } + + /** + * Triggered when a track is removed from track list. + * + * @event TrackList#removetrack + * @type {EventTarget~Event} + * @property {Track} track + * A reference to track that was removed. + */ + this.trigger({ + track: track, + type: 'removetrack' + }); + }; + + /** + * Get a Track from the TrackList by a tracks id + * + * @param {String} id - the id of the track to get + * @method getTrackById + * @return {Track} + * @private + */ + + + TrackList.prototype.getTrackById = function getTrackById(id) { + var result = null; + + for (var i = 0, l = this.length; i < l; i++) { + var track = this[i]; + + if (track.id === id) { + result = track; + break; + } + } + + return result; + }; + + return TrackList; + }(EventTarget); + + /** + * Triggered when a different track is selected/enabled. + * + * @event TrackList#change + * @type {EventTarget~Event} + */ + + /** + * Events that can be called with on + eventName. See {@link EventHandler}. + * + * @property {Object} TrackList#allowedEvents_ + * @private + */ + + + TrackList.prototype.allowedEvents_ = { + change: 'change', + addtrack: 'addtrack', + removetrack: 'removetrack' + }; + + // emulate attribute EventHandler support to allow for feature detection + for (var event in TrackList.prototype.allowedEvents_) { + TrackList.prototype['on' + event] = null; + } + + /** + * @file audio-track-list.js + */ + + /** + * Anywhere we call this function we diverge from the spec + * as we only support one enabled audiotrack at a time + * + * @param {AudioTrackList} list + * list to work on + * + * @param {AudioTrack} track + * The track to skip + * + * @private + */ + var disableOthers = function disableOthers(list, track) { + for (var i = 0; i < list.length; i++) { + if (!Object.keys(list[i]).length || track.id === list[i].id) { + continue; + } + // another audio track is enabled, disable it + list[i].enabled = false; + } + }; + + /** + * The current list of {@link AudioTrack} for a media file. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist} + * @extends TrackList + */ + + var AudioTrackList = function (_TrackList) { + inherits(AudioTrackList, _TrackList); + + /** + * Create an instance of this class. + * + * @param {AudioTrack[]} [tracks=[]] + * A list of `AudioTrack` to instantiate the list with. + */ + function AudioTrackList() { + var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + classCallCheck(this, AudioTrackList); + + // make sure only 1 track is enabled + // sorted from last index to first index + for (var i = tracks.length - 1; i >= 0; i--) { + if (tracks[i].enabled) { + disableOthers(tracks, tracks[i]); + break; + } + } + + var _this = possibleConstructorReturn(this, _TrackList.call(this, tracks)); + + _this.changing_ = false; + return _this; + } + + /** + * Add an {@link AudioTrack} to the `AudioTrackList`. + * + * @param {AudioTrack} track + * The AudioTrack to add to the list + * + * @fires TrackList#addtrack + */ + + + AudioTrackList.prototype.addTrack = function addTrack(track) { + var _this2 = this; + + if (track.enabled) { + disableOthers(this, track); + } + + _TrackList.prototype.addTrack.call(this, track); + // native tracks don't have this + if (!track.addEventListener) { + return; + } + + /** + * @listens AudioTrack#enabledchange + * @fires TrackList#change + */ + track.addEventListener('enabledchange', function () { + // when we are disabling other tracks (since we don't support + // more than one track at a time) we will set changing_ + // to true so that we don't trigger additional change events + if (_this2.changing_) { + return; + } + _this2.changing_ = true; + disableOthers(_this2, track); + _this2.changing_ = false; + _this2.trigger('change'); + }); + }; + + return AudioTrackList; + }(TrackList); + + /** + * @file video-track-list.js + */ + + /** + * Un-select all other {@link VideoTrack}s that are selected. + * + * @param {VideoTrackList} list + * list to work on + * + * @param {VideoTrack} track + * The track to skip + * + * @private + */ + var disableOthers$1 = function disableOthers(list, track) { + for (var i = 0; i < list.length; i++) { + if (!Object.keys(list[i]).length || track.id === list[i].id) { + continue; + } + // another video track is enabled, disable it + list[i].selected = false; + } + }; + + /** + * The current list of {@link VideoTrack} for a video. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist} + * @extends TrackList + */ + + var VideoTrackList = function (_TrackList) { + inherits(VideoTrackList, _TrackList); + + /** + * Create an instance of this class. + * + * @param {VideoTrack[]} [tracks=[]] + * A list of `VideoTrack` to instantiate the list with. + */ + function VideoTrackList() { + var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + classCallCheck(this, VideoTrackList); + + // make sure only 1 track is enabled + // sorted from last index to first index + for (var i = tracks.length - 1; i >= 0; i--) { + if (tracks[i].selected) { + disableOthers$1(tracks, tracks[i]); + break; + } + } + + var _this = possibleConstructorReturn(this, _TrackList.call(this, tracks)); + + _this.changing_ = false; + + /** + * @member {number} VideoTrackList#selectedIndex + * The current index of the selected {@link VideoTrack`}. + */ + Object.defineProperty(_this, 'selectedIndex', { + get: function get$$1() { + for (var _i = 0; _i < this.length; _i++) { + if (this[_i].selected) { + return _i; + } + } + return -1; + }, + set: function set$$1() { + } + }); + return _this; + } + + /** + * Add a {@link VideoTrack} to the `VideoTrackList`. + * + * @param {VideoTrack} track + * The VideoTrack to add to the list + * + * @fires TrackList#addtrack + */ + + + VideoTrackList.prototype.addTrack = function addTrack(track) { + var _this2 = this; + + if (track.selected) { + disableOthers$1(this, track); + } + + _TrackList.prototype.addTrack.call(this, track); + // native tracks don't have this + if (!track.addEventListener) { + return; + } + + /** + * @listens VideoTrack#selectedchange + * @fires TrackList#change + */ + track.addEventListener('selectedchange', function () { + if (_this2.changing_) { + return; + } + _this2.changing_ = true; + disableOthers$1(_this2, track); + _this2.changing_ = false; + _this2.trigger('change'); + }); + }; + + return VideoTrackList; + }(TrackList); + + /** + * @file text-track-list.js + */ + + /** + * The current list of {@link TextTrack} for a media file. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttracklist} + * @extends TrackList + */ + + var TextTrackList = function (_TrackList) { + inherits(TextTrackList, _TrackList); + + function TextTrackList() { + classCallCheck(this, TextTrackList); + return possibleConstructorReturn(this, _TrackList.apply(this, arguments)); + } + + /** + * Add a {@link TextTrack} to the `TextTrackList` + * + * @param {TextTrack} track + * The text track to add to the list. + * + * @fires TrackList#addtrack + */ + TextTrackList.prototype.addTrack = function addTrack(track) { + _TrackList.prototype.addTrack.call(this, track); + + /** + * @listens TextTrack#modechange + * @fires TrackList#change + */ + track.addEventListener('modechange', bind(this, function () { + this.trigger('change'); + })); + + var nonLanguageTextTrackKind = ['metadata', 'chapters']; + + if (nonLanguageTextTrackKind.indexOf(track.kind) === -1) { + track.addEventListener('modechange', bind(this, function () { + this.trigger('selectedlanguagechange'); + })); + } + }; + + return TextTrackList; + }(TrackList); + + /** + * @file html-track-element-list.js + */ + + /** + * The current list of {@link HtmlTrackElement}s. + */ + var HtmlTrackElementList = function () { + + /** + * Create an instance of this class. + * + * @param {HtmlTrackElement[]} [tracks=[]] + * A list of `HtmlTrackElement` to instantiate the list with. + */ + function HtmlTrackElementList() { + var trackElements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + classCallCheck(this, HtmlTrackElementList); + + this.trackElements_ = []; + + /** + * @memberof HtmlTrackElementList + * @member {number} length + * The current number of `Track`s in the this Trackist. + * @instance + */ + Object.defineProperty(this, 'length', { + get: function get$$1() { + return this.trackElements_.length; + } + }); + + for (var i = 0, length = trackElements.length; i < length; i++) { + this.addTrackElement_(trackElements[i]); + } + } + + /** + * Add an {@link HtmlTrackElement} to the `HtmlTrackElementList` + * + * @param {HtmlTrackElement} trackElement + * The track element to add to the list. + * + * @private + */ + + + HtmlTrackElementList.prototype.addTrackElement_ = function addTrackElement_(trackElement) { + var index = this.trackElements_.length; + + if (!('' + index in this)) { + Object.defineProperty(this, index, { + get: function get$$1() { + return this.trackElements_[index]; + } + }); + } + + // Do not add duplicate elements + if (this.trackElements_.indexOf(trackElement) === -1) { + this.trackElements_.push(trackElement); + } + }; + + /** + * Get an {@link HtmlTrackElement} from the `HtmlTrackElementList` given an + * {@link TextTrack}. + * + * @param {TextTrack} track + * The track associated with a track element. + * + * @return {HtmlTrackElement|undefined} + * The track element that was found or undefined. + * + * @private + */ + + + HtmlTrackElementList.prototype.getTrackElementByTrack_ = function getTrackElementByTrack_(track) { + var trackElement_ = void 0; + + for (var i = 0, length = this.trackElements_.length; i < length; i++) { + if (track === this.trackElements_[i].track) { + trackElement_ = this.trackElements_[i]; + + break; + } + } + + return trackElement_; + }; + + /** + * Remove a {@link HtmlTrackElement} from the `HtmlTrackElementList` + * + * @param {HtmlTrackElement} trackElement + * The track element to remove from the list. + * + * @private + */ + + + HtmlTrackElementList.prototype.removeTrackElement_ = function removeTrackElement_(trackElement) { + for (var i = 0, length = this.trackElements_.length; i < length; i++) { + if (trackElement === this.trackElements_[i]) { + this.trackElements_.splice(i, 1); + + break; + } + } + }; + + return HtmlTrackElementList; + }(); + + /** + * @file text-track-cue-list.js + */ + + /** + * @typedef {Object} TextTrackCueList~TextTrackCue + * + * @property {string} id + * The unique id for this text track cue + * + * @property {number} startTime + * The start time for this text track cue + * + * @property {number} endTime + * The end time for this text track cue + * + * @property {boolean} pauseOnExit + * Pause when the end time is reached if true. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcue} + */ + + /** + * A List of TextTrackCues. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist} + */ + var TextTrackCueList = function () { + + /** + * Create an instance of this class.. + * + * @param {Array} cues + * A list of cues to be initialized with + */ + function TextTrackCueList(cues) { + classCallCheck(this, TextTrackCueList); + + TextTrackCueList.prototype.setCues_.call(this, cues); + + /** + * @memberof TextTrackCueList + * @member {number} length + * The current number of `TextTrackCue`s in the TextTrackCueList. + * @instance + */ + Object.defineProperty(this, 'length', { + get: function get$$1() { + return this.length_; + } + }); + } + + /** + * A setter for cues in this list. Creates getters + * an an index for the cues. + * + * @param {Array} cues + * An array of cues to set + * + * @private + */ + + + TextTrackCueList.prototype.setCues_ = function setCues_(cues) { + var oldLength = this.length || 0; + var i = 0; + var l = cues.length; + + this.cues_ = cues; + this.length_ = cues.length; + + var defineProp = function defineProp(index) { + if (!('' + index in this)) { + Object.defineProperty(this, '' + index, { + get: function get$$1() { + return this.cues_[index]; + } + }); + } + }; + + if (oldLength < l) { + i = oldLength; + + for (; i < l; i++) { + defineProp.call(this, i); + } + } + }; + + /** + * Get a `TextTrackCue` that is currently in the `TextTrackCueList` by id. + * + * @param {string} id + * The id of the cue that should be searched for. + * + * @return {TextTrackCueList~TextTrackCue|null} + * A single cue or null if none was found. + */ + + + TextTrackCueList.prototype.getCueById = function getCueById(id) { + var result = null; + + for (var i = 0, l = this.length; i < l; i++) { + var cue = this[i]; + + if (cue.id === id) { + result = cue; + break; + } + } + + return result; + }; + + return TextTrackCueList; + }(); + + /** + * @file track-kinds.js + */ + + /** + * All possible `VideoTrackKind`s + * + * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-videotrack-kind + * @typedef VideoTrack~Kind + * @enum + */ + var VideoTrackKind = { + alternative: 'alternative', + captions: 'captions', + main: 'main', + sign: 'sign', + subtitles: 'subtitles', + commentary: 'commentary' + }; + + /** + * All possible `AudioTrackKind`s + * + * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-audiotrack-kind + * @typedef AudioTrack~Kind + * @enum + */ + var AudioTrackKind = { + 'alternative': 'alternative', + 'descriptions': 'descriptions', + 'main': 'main', + 'main-desc': 'main-desc', + 'translation': 'translation', + 'commentary': 'commentary' + }; + + /** + * All possible `TextTrackKind`s + * + * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-texttrack-kind + * @typedef TextTrack~Kind + * @enum + */ + var TextTrackKind = { + subtitles: 'subtitles', + captions: 'captions', + descriptions: 'descriptions', + chapters: 'chapters', + metadata: 'metadata' + }; + + /** + * All possible `TextTrackMode`s + * + * @see https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackmode + * @typedef TextTrack~Mode + * @enum + */ + var TextTrackMode = { + disabled: 'disabled', + hidden: 'hidden', + showing: 'showing' + }; + + /** + * @file track.js + */ + + /** + * A Track class that contains all of the common functionality for {@link AudioTrack}, + * {@link VideoTrack}, and {@link TextTrack}. + * + * > Note: This class should not be used directly + * + * @see {@link https://html.spec.whatwg.org/multipage/embedded-content.html} + * @extends EventTarget + * @abstract + */ + + var Track = function (_EventTarget) { + inherits(Track, _EventTarget); + + /** + * Create an instance of this class. + * + * @param {Object} [options={}] + * Object of option names and values + * + * @param {string} [options.kind=''] + * A valid kind for the track type you are creating. + * + * @param {string} [options.id='vjs_track_' + Guid.newGUID()] + * A unique id for this AudioTrack. + * + * @param {string} [options.label=''] + * The menu label for this track. + * + * @param {string} [options.language=''] + * A valid two character language code. + * + * @abstract + */ + function Track() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + classCallCheck(this, Track); + + var _this = possibleConstructorReturn(this, _EventTarget.call(this)); + + var trackProps = { + id: options.id || 'vjs_track_' + newGUID(), + kind: options.kind || '', + label: options.label || '', + language: options.language || '' + }; + + /** + * @memberof Track + * @member {string} id + * The id of this track. Cannot be changed after creation. + * @instance + * + * @readonly + */ + + /** + * @memberof Track + * @member {string} kind + * The kind of track that this is. Cannot be changed after creation. + * @instance + * + * @readonly + */ + + /** + * @memberof Track + * @member {string} label + * The label of this track. Cannot be changed after creation. + * @instance + * + * @readonly + */ + + /** + * @memberof Track + * @member {string} language + * The two letter language code for this track. Cannot be changed after + * creation. + * @instance + * + * @readonly + */ + + var _loop = function _loop(key) { + Object.defineProperty(_this, key, { + get: function get$$1() { + return trackProps[key]; + }, + set: function set$$1() { + } + }); + }; + + for (var key in trackProps) { + _loop(key); + } + return _this; + } + + return Track; + }(EventTarget); + + /** + * @file url.js + * @module url + */ + + /** + * @typedef {Object} url:URLObject + * + * @property {string} protocol + * The protocol of the url that was parsed. + * + * @property {string} hostname + * The hostname of the url that was parsed. + * + * @property {string} port + * The port of the url that was parsed. + * + * @property {string} pathname + * The pathname of the url that was parsed. + * + * @property {string} search + * The search query of the url that was parsed. + * + * @property {string} hash + * The hash of the url that was parsed. + * + * @property {string} host + * The host of the url that was parsed. + */ + + /** + * Resolve and parse the elements of a URL. + * + * @param {String} url + * The url to parse + * + * @return {url:URLObject} + * An object of url details + */ + var parseUrl = function parseUrl(url) { + var props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host']; + + // add the url to an anchor and let the browser parse the URL + var a = document_1.createElement('a'); + + a.href = url; + + // IE8 (and 9?) Fix + // ie8 doesn't parse the URL correctly until the anchor is actually + // added to the body, and an innerHTML is needed to trigger the parsing + var addToBody = a.host === '' && a.protocol !== 'file:'; + var div = void 0; + + if (addToBody) { + div = document_1.createElement('div'); + div.innerHTML = '<a href="' + url + '"></a>'; + a = div.firstChild; + // prevent the div from affecting layout + div.setAttribute('style', 'display:none; position:absolute;'); + document_1.body.appendChild(div); + } + + // Copy the specific URL properties to a new object + // This is also needed for IE8 because the anchor loses its + // properties when it's removed from the dom + var details = {}; + + for (var i = 0; i < props.length; i++) { + details[props[i]] = a[props[i]]; + } + + // IE9 adds the port to the host property unlike everyone else. If + // a port identifier is added for standard ports, strip it. + if (details.protocol === 'http:') { + details.host = details.host.replace(/:80$/, ''); + } + + if (details.protocol === 'https:') { + details.host = details.host.replace(/:443$/, ''); + } + + if (!details.protocol) { + details.protocol = window_1.location.protocol; + } + + if (addToBody) { + document_1.body.removeChild(div); + } + + return details; + }; + + /** + * Get absolute version of relative URL. Used to tell flash correct URL. + * + * + * @param {string} url + * URL to make absolute + * + * @return {string} + * Absolute URL + * + * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue + */ + var getAbsoluteURL = function getAbsoluteURL(url) { + // Check if absolute URL + if (!url.match(/^https?:\/\//)) { + // Convert to absolute URL. Flash hosted off-site needs an absolute URL. + var div = document_1.createElement('div'); + + div.innerHTML = '<a href="' + url + '">x</a>'; + url = div.firstChild.href; + } + + return url; + }; + + /** + * Returns the extension of the passed file name. It will return an empty string + * if passed an invalid path. + * + * @param {string} path + * The fileName path like '/path/to/file.mp4' + * + * @returns {string} + * The extension in lower case or an empty string if no + * extension could be found. + */ + var getFileExtension = function getFileExtension(path) { + if (typeof path === 'string') { + var splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i; + var pathParts = splitPathRe.exec(path); + + if (pathParts) { + return pathParts.pop().toLowerCase(); + } + } + + return ''; + }; + + /** + * Returns whether the url passed is a cross domain request or not. + * + * @param {string} url + * The url to check. + * + * @return {boolean} + * Whether it is a cross domain request or not. + */ + var isCrossOrigin = function isCrossOrigin(url) { + var winLoc = window_1.location; + var urlInfo = parseUrl(url); + + // IE8 protocol relative urls will return ':' for protocol + var srcProtocol = urlInfo.protocol === ':' ? winLoc.protocol : urlInfo.protocol; + + // Check if url is for another domain/origin + // IE8 doesn't know location.origin, so we won't rely on it here + var crossOrigin = srcProtocol + urlInfo.host !== winLoc.protocol + winLoc.host; + + return crossOrigin; + }; + + var Url = /*#__PURE__*/Object.freeze({ + parseUrl: parseUrl, + getAbsoluteURL: getAbsoluteURL, + getFileExtension: getFileExtension, + isCrossOrigin: isCrossOrigin + }); + + var isFunction_1 = isFunction; + + var toString$1 = Object.prototype.toString; + + function isFunction(fn) { + var string = toString$1.call(fn); + return string === '[object Function]' || typeof fn === 'function' && string !== '[object RegExp]' || typeof window !== 'undefined' && ( + // IE8 and below + fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt); + } + + var isFunction$1 = /*#__PURE__*/Object.freeze({ + default: isFunction_1, + __moduleExports: isFunction_1 + }); + + var trim_1 = createCommonjsModule(function (module, exports) { + exports = module.exports = trim; + + function trim(str) { + return str.replace(/^\s*|\s*$/g, ''); + } + + exports.left = function (str) { + return str.replace(/^\s*/, ''); + }; + + exports.right = function (str) { + return str.replace(/\s*$/, ''); + }; + }); + var trim_2 = trim_1.left; + var trim_3 = trim_1.right; + + var trim = /*#__PURE__*/Object.freeze({ + default: trim_1, + __moduleExports: trim_1, + left: trim_2, + right: trim_3 + }); + + var isFunction$2 = (isFunction$1 && isFunction_1) || isFunction$1; + + var forEach_1 = forEach; + + var toString$2 = Object.prototype.toString; + var hasOwnProperty = Object.prototype.hasOwnProperty; + + function forEach(list, iterator, context) { + if (!isFunction$2(iterator)) { + throw new TypeError('iterator must be a function'); + } + + if (arguments.length < 3) { + context = this; + } + + if (toString$2.call(list) === '[object Array]') forEachArray(list, iterator, context); else if (typeof list === 'string') forEachString(list, iterator, context); else forEachObject(list, iterator, context); + } + + function forEachArray(array, iterator, context) { + for (var i = 0, len = array.length; i < len; i++) { + if (hasOwnProperty.call(array, i)) { + iterator.call(context, array[i], i, array); + } + } + } + + function forEachString(string, iterator, context) { + for (var i = 0, len = string.length; i < len; i++) { + // no such thing as a sparse string. + iterator.call(context, string.charAt(i), i, string); + } + } + + function forEachObject(object, iterator, context) { + for (var k in object) { + if (hasOwnProperty.call(object, k)) { + iterator.call(context, object[k], k, object); + } + } + } + + var forEach$1 = /*#__PURE__*/Object.freeze({ + default: forEach_1, + __moduleExports: forEach_1 + }); + + var trim$1 = (trim && trim_1) || trim; + + var forEach$2 = (forEach$1 && forEach_1) || forEach$1; + + var isArray = function isArray(arg) { + return Object.prototype.toString.call(arg) === '[object Array]'; + }; + + var parseHeaders = function parseHeaders(headers) { + if (!headers) return {}; + + var result = {}; + + forEach$2(trim$1(headers).split('\n'), function (row) { + var index = row.indexOf(':'), + key = trim$1(row.slice(0, index)).toLowerCase(), + value = trim$1(row.slice(index + 1)); + + if (typeof result[key] === 'undefined') { + result[key] = value; + } else if (isArray(result[key])) { + result[key].push(value); + } else { + result[key] = [result[key], value]; + } + }); + + return result; + }; + + var parseHeaders$1 = /*#__PURE__*/Object.freeze({ + default: parseHeaders, + __moduleExports: parseHeaders + }); + + var immutable = extend; + + var hasOwnProperty$1 = Object.prototype.hasOwnProperty; + + function extend() { + var target = {}; + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (hasOwnProperty$1.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + } + + var immutable$1 = /*#__PURE__*/Object.freeze({ + default: immutable, + __moduleExports: immutable + }); + + var parseHeaders$2 = (parseHeaders$1 && parseHeaders) || parseHeaders$1; + + var xtend = (immutable$1 && immutable) || immutable$1; + + var xhr = createXHR; + createXHR.XMLHttpRequest = window_1.XMLHttpRequest || noop; + createXHR.XDomainRequest = "withCredentials" in new createXHR.XMLHttpRequest() ? createXHR.XMLHttpRequest : window_1.XDomainRequest; + + forEachArray$1(["get", "put", "post", "patch", "head", "delete"], function (method) { + createXHR[method === "delete" ? "del" : method] = function (uri, options, callback) { + options = initParams(uri, options, callback); + options.method = method.toUpperCase(); + return _createXHR(options); + }; + }); + + function forEachArray$1(array, iterator) { + for (var i = 0; i < array.length; i++) { + iterator(array[i]); + } + } + + function isEmpty(obj) { + for (var i in obj) { + if (obj.hasOwnProperty(i)) return false; + } + return true; + } + + function initParams(uri, options, callback) { + var params = uri; + + if (isFunction$2(options)) { + callback = options; + if (typeof uri === "string") { + params = {uri: uri}; + } + } else { + params = xtend(options, {uri: uri}); + } + + params.callback = callback; + return params; + } + + function createXHR(uri, options, callback) { + options = initParams(uri, options, callback); + return _createXHR(options); + } + + function _createXHR(options) { + if (typeof options.callback === "undefined") { + throw new Error("callback argument missing"); + } + + var called = false; + var callback = function cbOnce(err, response, body) { + if (!called) { + called = true; + options.callback(err, response, body); + } + }; + + function readystatechange() { + if (xhr.readyState === 4) { + setTimeout(loadFunc, 0); + } + } + + function getBody() { + // Chrome with requestType=blob throws errors arround when even testing access to responseText + var body = undefined; + + if (xhr.response) { + body = xhr.response; + } else { + body = xhr.responseText || getXml(xhr); + } + + if (isJson) { + try { + body = JSON.parse(body); + } catch (e) { + } + } + + return body; + } + + function errorFunc(evt) { + clearTimeout(timeoutTimer); + if (!(evt instanceof Error)) { + evt = new Error("" + (evt || "Unknown XMLHttpRequest Error")); + } + evt.statusCode = 0; + return callback(evt, failureResponse); + } + + // will load the data & process the response in a special response object + function loadFunc() { + if (aborted) return; + var status; + clearTimeout(timeoutTimer); + if (options.useXDR && xhr.status === undefined) { + //IE8 CORS GET successful response doesn't have a status field, but body is fine + status = 200; + } else { + status = xhr.status === 1223 ? 204 : xhr.status; + } + var response = failureResponse; + var err = null; + + if (status !== 0) { + response = { + body: getBody(), + statusCode: status, + method: method, + headers: {}, + url: uri, + rawRequest: xhr + }; + if (xhr.getAllResponseHeaders) { + //remember xhr can in fact be XDR for CORS in IE + response.headers = parseHeaders$2(xhr.getAllResponseHeaders()); + } + } else { + err = new Error("Internal XMLHttpRequest Error"); + } + return callback(err, response, response.body); + } + + var xhr = options.xhr || null; + + if (!xhr) { + if (options.cors || options.useXDR) { + xhr = new createXHR.XDomainRequest(); + } else { + xhr = new createXHR.XMLHttpRequest(); + } + } + + var key; + var aborted; + var uri = xhr.url = options.uri || options.url; + var method = xhr.method = options.method || "GET"; + var body = options.body || options.data; + var headers = xhr.headers = options.headers || {}; + var sync = !!options.sync; + var isJson = false; + var timeoutTimer; + var failureResponse = { + body: undefined, + headers: {}, + statusCode: 0, + method: method, + url: uri, + rawRequest: xhr + }; + + if ("json" in options && options.json !== false) { + isJson = true; + headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json"); //Don't override existing accept header declared by user + if (method !== "GET" && method !== "HEAD") { + headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json"); //Don't override existing accept header declared by user + body = JSON.stringify(options.json === true ? body : options.json); + } + } + + xhr.onreadystatechange = readystatechange; + xhr.onload = loadFunc; + xhr.onerror = errorFunc; + // IE9 must have onprogress be set to a unique function. + xhr.onprogress = function () { + // IE must die + }; + xhr.onabort = function () { + aborted = true; + }; + xhr.ontimeout = errorFunc; + xhr.open(method, uri, !sync, options.username, options.password); + //has to be after open + if (!sync) { + xhr.withCredentials = !!options.withCredentials; + } + // Cannot set timeout with sync request + // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly + // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent + if (!sync && options.timeout > 0) { + timeoutTimer = setTimeout(function () { + if (aborted) return; + aborted = true; //IE9 may still call readystatechange + xhr.abort("timeout"); + var e = new Error("XMLHttpRequest timeout"); + e.code = "ETIMEDOUT"; + errorFunc(e); + }, options.timeout); + } + + if (xhr.setRequestHeader) { + for (key in headers) { + if (headers.hasOwnProperty(key)) { + xhr.setRequestHeader(key, headers[key]); + } + } + } else if (options.headers && !isEmpty(options.headers)) { + throw new Error("Headers cannot be set on an XDomainRequest object"); + } + + if ("responseType" in options) { + xhr.responseType = options.responseType; + } + + if ("beforeSend" in options && typeof options.beforeSend === "function") { + options.beforeSend(xhr); + } + + // Microsoft Edge browser sends "undefined" when send is called with undefined value. + // XMLHttpRequest spec says to pass null as body to indicate no body + // See https://github.com/naugtur/xhr/issues/100. + xhr.send(body || null); + + return xhr; + } + + function getXml(xhr) { + if (xhr.responseType === "document") { + return xhr.responseXML; + } + var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"; + if (xhr.responseType === "" && !firefoxBugTakenEffect) { + return xhr.responseXML; + } + + return null; + } + + function noop() { + } + + /** + * @file text-track.js + */ + + /** + * Takes a webvtt file contents and parses it into cues + * + * @param {string} srcContent + * webVTT file contents + * + * @param {TextTrack} track + * TextTrack to add cues to. Cues come from the srcContent. + * + * @private + */ + var parseCues = function parseCues(srcContent, track) { + var parser = new window_1.WebVTT.Parser(window_1, window_1.vttjs, window_1.WebVTT.StringDecoder()); + var errors = []; + + parser.oncue = function (cue) { + track.addCue(cue); + }; + + parser.onparsingerror = function (error) { + errors.push(error); + }; + + parser.onflush = function () { + track.trigger({ + type: 'loadeddata', + target: track + }); + }; + + parser.parse(srcContent); + if (errors.length > 0) { + if (window_1.console && window_1.console.groupCollapsed) { + window_1.console.groupCollapsed('Text Track parsing errors for ' + track.src); + } + errors.forEach(function (error) { + return log$1.error(error); + }); + if (window_1.console && window_1.console.groupEnd) { + window_1.console.groupEnd(); + } + } + + parser.flush(); + }; + + /** + * Load a `TextTrack` from a specified url. + * + * @param {string} src + * Url to load track from. + * + * @param {TextTrack} track + * Track to add cues to. Comes from the content at the end of `url`. + * + * @private + */ + var loadTrack = function loadTrack(src, track) { + var opts = { + uri: src + }; + var crossOrigin = isCrossOrigin(src); + + if (crossOrigin) { + opts.cors = crossOrigin; + } + + xhr(opts, bind(this, function (err, response, responseBody) { + if (err) { + return log$1.error(err, response); + } + + track.loaded_ = true; + + // Make sure that vttjs has loaded, otherwise, wait till it finished loading + // NOTE: this is only used for the alt/video.novtt.js build + if (typeof window_1.WebVTT !== 'function') { + if (track.tech_) { + var loadHandler = function loadHandler() { + return parseCues(responseBody, track); + }; + + track.tech_.on('vttjsloaded', loadHandler); + track.tech_.on('vttjserror', function () { + log$1.error('vttjs failed to load, stopping trying to process ' + track.src); + track.tech_.off('vttjsloaded', loadHandler); + }); + } + } else { + parseCues(responseBody, track); + } + })); + }; + + /** + * A representation of a single `TextTrack`. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack} + * @extends Track + */ + + var TextTrack = function (_Track) { + inherits(TextTrack, _Track); + + /** + * Create an instance of this class. + * + * @param {Object} options={} + * Object of option names and values + * + * @param {Tech} options.tech + * A reference to the tech that owns this TextTrack. + * + * @param {TextTrack~Kind} [options.kind='subtitles'] + * A valid text track kind. + * + * @param {TextTrack~Mode} [options.mode='disabled'] + * A valid text track mode. + * + * @param {string} [options.id='vjs_track_' + Guid.newGUID()] + * A unique id for this TextTrack. + * + * @param {string} [options.label=''] + * The menu label for this track. + * + * @param {string} [options.language=''] + * A valid two character language code. + * + * @param {string} [options.srclang=''] + * A valid two character language code. An alternative, but deprioritized + * version of `options.language` + * + * @param {string} [options.src] + * A url to TextTrack cues. + * + * @param {boolean} [options.default] + * If this track should default to on or off. + */ + function TextTrack() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + classCallCheck(this, TextTrack); + + if (!options.tech) { + throw new Error('A tech was not provided.'); + } + + var settings = mergeOptions(options, { + kind: TextTrackKind[options.kind] || 'subtitles', + language: options.language || options.srclang || '' + }); + var mode = TextTrackMode[settings.mode] || 'disabled'; + var default_ = settings.default; + + if (settings.kind === 'metadata' || settings.kind === 'chapters') { + mode = 'hidden'; + } + + var _this = possibleConstructorReturn(this, _Track.call(this, settings)); + + _this.tech_ = settings.tech; + + _this.cues_ = []; + _this.activeCues_ = []; + + var cues = new TextTrackCueList(_this.cues_); + var activeCues = new TextTrackCueList(_this.activeCues_); + var changed = false; + var timeupdateHandler = bind(_this, function () { + + // Accessing this.activeCues for the side-effects of updating itself + // due to it's nature as a getter function. Do not remove or cues will + // stop updating! + /* eslint-disable no-unused-expressions */ + this.activeCues; + /* eslint-enable no-unused-expressions */ + if (changed) { + this.trigger('cuechange'); + changed = false; + } + }); + + if (mode !== 'disabled') { + _this.tech_.ready(function () { + _this.tech_.on('timeupdate', timeupdateHandler); + }, true); + } + + Object.defineProperties(_this, { + /** + * @memberof TextTrack + * @member {boolean} default + * If this track was set to be on or off by default. Cannot be changed after + * creation. + * @instance + * + * @readonly + */ + default: { + get: function get$$1() { + return default_; + }, + set: function set$$1() { + } + }, + + /** + * @memberof TextTrack + * @member {string} mode + * Set the mode of this TextTrack to a valid {@link TextTrack~Mode}. Will + * not be set if setting to an invalid mode. + * @instance + * + * @fires TextTrack#modechange + */ + mode: { + get: function get$$1() { + return mode; + }, + set: function set$$1(newMode) { + var _this2 = this; + + if (!TextTrackMode[newMode]) { + return; + } + mode = newMode; + if (mode === 'showing') { + + this.tech_.ready(function () { + _this2.tech_.on('timeupdate', timeupdateHandler); + }, true); + } + /** + * An event that fires when mode changes on this track. This allows + * the TextTrackList that holds this track to act accordingly. + * + * > Note: This is not part of the spec! + * + * @event TextTrack#modechange + * @type {EventTarget~Event} + */ + this.trigger('modechange'); + } + }, + + /** + * @memberof TextTrack + * @member {TextTrackCueList} cues + * The text track cue list for this TextTrack. + * @instance + */ + cues: { + get: function get$$1() { + if (!this.loaded_) { + return null; + } + + return cues; + }, + set: function set$$1() { + } + }, + + /** + * @memberof TextTrack + * @member {TextTrackCueList} activeCues + * The list text track cues that are currently active for this TextTrack. + * @instance + */ + activeCues: { + get: function get$$1() { + if (!this.loaded_) { + return null; + } + + // nothing to do + if (this.cues.length === 0) { + return activeCues; + } + + var ct = this.tech_.currentTime(); + var active = []; + + for (var i = 0, l = this.cues.length; i < l; i++) { + var cue = this.cues[i]; + + if (cue.startTime <= ct && cue.endTime >= ct) { + active.push(cue); + } else if (cue.startTime === cue.endTime && cue.startTime <= ct && cue.startTime + 0.5 >= ct) { + active.push(cue); + } + } + + changed = false; + + if (active.length !== this.activeCues_.length) { + changed = true; + } else { + for (var _i = 0; _i < active.length; _i++) { + if (this.activeCues_.indexOf(active[_i]) === -1) { + changed = true; + } + } + } + + this.activeCues_ = active; + activeCues.setCues_(this.activeCues_); + + return activeCues; + }, + set: function set$$1() { + } + } + }); + + if (settings.src) { + _this.src = settings.src; + loadTrack(settings.src, _this); + } else { + _this.loaded_ = true; + } + return _this; + } + + /** + * Add a cue to the internal list of cues. + * + * @param {TextTrack~Cue} cue + * The cue to add to our internal list + */ + + + TextTrack.prototype.addCue = function addCue(originalCue) { + var cue = originalCue; + + if (window_1.vttjs && !(originalCue instanceof window_1.vttjs.VTTCue)) { + cue = new window_1.vttjs.VTTCue(originalCue.startTime, originalCue.endTime, originalCue.text); + + for (var prop in originalCue) { + if (!(prop in cue)) { + cue[prop] = originalCue[prop]; + } + } + + // make sure that `id` is copied over + cue.id = originalCue.id; + cue.originalCue_ = originalCue; + } + + var tracks = this.tech_.textTracks(); + + for (var i = 0; i < tracks.length; i++) { + if (tracks[i] !== this) { + tracks[i].removeCue(cue); + } + } + + this.cues_.push(cue); + this.cues.setCues_(this.cues_); + }; + + /** + * Remove a cue from our internal list + * + * @param {TextTrack~Cue} removeCue + * The cue to remove from our internal list + */ + + + TextTrack.prototype.removeCue = function removeCue(_removeCue) { + var i = this.cues_.length; + + while (i--) { + var cue = this.cues_[i]; + + if (cue === _removeCue || cue.originalCue_ && cue.originalCue_ === _removeCue) { + this.cues_.splice(i, 1); + this.cues.setCues_(this.cues_); + break; + } + } + }; + + return TextTrack; + }(Track); + + /** + * cuechange - One or more cues in the track have become active or stopped being active. + */ + + + TextTrack.prototype.allowedEvents_ = { + cuechange: 'cuechange' + }; + + /** + * A representation of a single `AudioTrack`. If it is part of an {@link AudioTrackList} + * only one `AudioTrack` in the list will be enabled at a time. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotrack} + * @extends Track + */ + + var AudioTrack = function (_Track) { + inherits(AudioTrack, _Track); + + /** + * Create an instance of this class. + * + * @param {Object} [options={}] + * Object of option names and values + * + * @param {AudioTrack~Kind} [options.kind=''] + * A valid audio track kind + * + * @param {string} [options.id='vjs_track_' + Guid.newGUID()] + * A unique id for this AudioTrack. + * + * @param {string} [options.label=''] + * The menu label for this track. + * + * @param {string} [options.language=''] + * A valid two character language code. + * + * @param {boolean} [options.enabled] + * If this track is the one that is currently playing. If this track is part of + * an {@link AudioTrackList}, only one {@link AudioTrack} will be enabled. + */ + function AudioTrack() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + classCallCheck(this, AudioTrack); + + var settings = mergeOptions(options, { + kind: AudioTrackKind[options.kind] || '' + }); + + var _this = possibleConstructorReturn(this, _Track.call(this, settings)); + + var enabled = false; + + /** + * @memberof AudioTrack + * @member {boolean} enabled + * If this `AudioTrack` is enabled or not. When setting this will + * fire {@link AudioTrack#enabledchange} if the state of enabled is changed. + * @instance + * + * @fires VideoTrack#selectedchange + */ + Object.defineProperty(_this, 'enabled', { + get: function get$$1() { + return enabled; + }, + set: function set$$1(newEnabled) { + // an invalid or unchanged value + if (typeof newEnabled !== 'boolean' || newEnabled === enabled) { + return; + } + enabled = newEnabled; + + /** + * An event that fires when enabled changes on this track. This allows + * the AudioTrackList that holds this track to act accordingly. + * + * > Note: This is not part of the spec! Native tracks will do + * this internally without an event. + * + * @event AudioTrack#enabledchange + * @type {EventTarget~Event} + */ + this.trigger('enabledchange'); + } + }); + + // if the user sets this track to selected then + // set selected to that true value otherwise + // we keep it false + if (settings.enabled) { + _this.enabled = settings.enabled; + } + _this.loaded_ = true; + return _this; + } + + return AudioTrack; + }(Track); + + /** + * A representation of a single `VideoTrack`. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#videotrack} + * @extends Track + */ + + var VideoTrack = function (_Track) { + inherits(VideoTrack, _Track); + + /** + * Create an instance of this class. + * + * @param {Object} [options={}] + * Object of option names and values + * + * @param {string} [options.kind=''] + * A valid {@link VideoTrack~Kind} + * + * @param {string} [options.id='vjs_track_' + Guid.newGUID()] + * A unique id for this AudioTrack. + * + * @param {string} [options.label=''] + * The menu label for this track. + * + * @param {string} [options.language=''] + * A valid two character language code. + * + * @param {boolean} [options.selected] + * If this track is the one that is currently playing. + */ + function VideoTrack() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + classCallCheck(this, VideoTrack); + + var settings = mergeOptions(options, { + kind: VideoTrackKind[options.kind] || '' + }); + + var _this = possibleConstructorReturn(this, _Track.call(this, settings)); + + var selected = false; + + /** + * @memberof VideoTrack + * @member {boolean} selected + * If this `VideoTrack` is selected or not. When setting this will + * fire {@link VideoTrack#selectedchange} if the state of selected changed. + * @instance + * + * @fires VideoTrack#selectedchange + */ + Object.defineProperty(_this, 'selected', { + get: function get$$1() { + return selected; + }, + set: function set$$1(newSelected) { + // an invalid or unchanged value + if (typeof newSelected !== 'boolean' || newSelected === selected) { + return; + } + selected = newSelected; + + /** + * An event that fires when selected changes on this track. This allows + * the VideoTrackList that holds this track to act accordingly. + * + * > Note: This is not part of the spec! Native tracks will do + * this internally without an event. + * + * @event VideoTrack#selectedchange + * @type {EventTarget~Event} + */ + this.trigger('selectedchange'); + } + }); + + // if the user sets this track to selected then + // set selected to that true value otherwise + // we keep it false + if (settings.selected) { + _this.selected = settings.selected; + } + return _this; + } + + return VideoTrack; + }(Track); + + /** + * @file html-track-element.js + */ + + /** + * @memberof HTMLTrackElement + * @typedef {HTMLTrackElement~ReadyState} + * @enum {number} + */ + var NONE = 0; + var LOADING = 1; + var LOADED = 2; + var ERROR = 3; + + /** + * A single track represented in the DOM. + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#htmltrackelement} + * @extends EventTarget + */ + + var HTMLTrackElement = function (_EventTarget) { + inherits(HTMLTrackElement, _EventTarget); + + /** + * Create an instance of this class. + * + * @param {Object} options={} + * Object of option names and values + * + * @param {Tech} options.tech + * A reference to the tech that owns this HTMLTrackElement. + * + * @param {TextTrack~Kind} [options.kind='subtitles'] + * A valid text track kind. + * + * @param {TextTrack~Mode} [options.mode='disabled'] + * A valid text track mode. + * + * @param {string} [options.id='vjs_track_' + Guid.newGUID()] + * A unique id for this TextTrack. + * + * @param {string} [options.label=''] + * The menu label for this track. + * + * @param {string} [options.language=''] + * A valid two character language code. + * + * @param {string} [options.srclang=''] + * A valid two character language code. An alternative, but deprioritized + * vesion of `options.language` + * + * @param {string} [options.src] + * A url to TextTrack cues. + * + * @param {boolean} [options.default] + * If this track should default to on or off. + */ + function HTMLTrackElement() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + classCallCheck(this, HTMLTrackElement); + + var _this = possibleConstructorReturn(this, _EventTarget.call(this)); + + var readyState = void 0; + + var track = new TextTrack(options); + + _this.kind = track.kind; + _this.src = track.src; + _this.srclang = track.language; + _this.label = track.label; + _this.default = track.default; + + Object.defineProperties(_this, { + + /** + * @memberof HTMLTrackElement + * @member {HTMLTrackElement~ReadyState} readyState + * The current ready state of the track element. + * @instance + */ + readyState: { + get: function get$$1() { + return readyState; + } + }, + + /** + * @memberof HTMLTrackElement + * @member {TextTrack} track + * The underlying TextTrack object. + * @instance + * + */ + track: { + get: function get$$1() { + return track; + } + } + }); + + readyState = NONE; + + /** + * @listens TextTrack#loadeddata + * @fires HTMLTrackElement#load + */ + track.addEventListener('loadeddata', function () { + readyState = LOADED; + + _this.trigger({ + type: 'load', + target: _this + }); + }); + return _this; + } + + return HTMLTrackElement; + }(EventTarget); + + HTMLTrackElement.prototype.allowedEvents_ = { + load: 'load' + }; + + HTMLTrackElement.NONE = NONE; + HTMLTrackElement.LOADING = LOADING; + HTMLTrackElement.LOADED = LOADED; + HTMLTrackElement.ERROR = ERROR; + + /* + * This file contains all track properties that are used in + * player.js, tech.js, html5.js and possibly other techs in the future. + */ + + var NORMAL = { + audio: { + ListClass: AudioTrackList, + TrackClass: AudioTrack, + capitalName: 'Audio' + }, + video: { + ListClass: VideoTrackList, + TrackClass: VideoTrack, + capitalName: 'Video' + }, + text: { + ListClass: TextTrackList, + TrackClass: TextTrack, + capitalName: 'Text' + } + }; + + Object.keys(NORMAL).forEach(function (type) { + NORMAL[type].getterName = type + 'Tracks'; + NORMAL[type].privateName = type + 'Tracks_'; + }); + + var REMOTE = { + remoteText: { + ListClass: TextTrackList, + TrackClass: TextTrack, + capitalName: 'RemoteText', + getterName: 'remoteTextTracks', + privateName: 'remoteTextTracks_' + }, + remoteTextEl: { + ListClass: HtmlTrackElementList, + TrackClass: HTMLTrackElement, + capitalName: 'RemoteTextTrackEls', + getterName: 'remoteTextTrackEls', + privateName: 'remoteTextTrackEls_' + } + }; + + var ALL = mergeOptions(NORMAL, REMOTE); + + REMOTE.names = Object.keys(REMOTE); + NORMAL.names = Object.keys(NORMAL); + ALL.names = [].concat(REMOTE.names).concat(NORMAL.names); + + /** + * Copyright 2013 vtt.js Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + var _objCreate = Object.create || function () { + function F() { + } + + return function (o) { + if (arguments.length !== 1) { + throw new Error('Object.create shim only accepts one parameter.'); + } + F.prototype = o; + return new F(); + }; + }(); + + // Creates a new ParserError object from an errorData object. The errorData + // object should have default code and message properties. The default message + // property can be overriden by passing in a message parameter. + // See ParsingError.Errors below for acceptable errors. + function ParsingError(errorData, message) { + this.name = "ParsingError"; + this.code = errorData.code; + this.message = message || errorData.message; + } + + ParsingError.prototype = _objCreate(Error.prototype); + ParsingError.prototype.constructor = ParsingError; + + // ParsingError metadata for acceptable ParsingErrors. + ParsingError.Errors = { + BadSignature: { + code: 0, + message: "Malformed WebVTT signature." + }, + BadTimeStamp: { + code: 1, + message: "Malformed time stamp." + } + }; + + // Try to parse input as a time stamp. + function parseTimeStamp(input) { + + function computeSeconds(h, m, s, f) { + return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000; + } + + var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/); + if (!m) { + return null; + } + + if (m[3]) { + // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds] + return computeSeconds(m[1], m[2], m[3].replace(":", ""), m[4]); + } else if (m[1] > 59) { + // Timestamp takes the form of [hours]:[minutes].[milliseconds] + // First position is hours as it's over 59. + return computeSeconds(m[1], m[2], 0, m[4]); + } else { + // Timestamp takes the form of [minutes]:[seconds].[milliseconds] + return computeSeconds(0, m[1], m[2], m[4]); + } + } + + // A settings object holds key/value pairs and will ignore anything but the first + // assignment to a specific key. + function Settings() { + this.values = _objCreate(null); + } + + Settings.prototype = { + // Only accept the first assignment to any key. + set: function set(k, v) { + if (!this.get(k) && v !== "") { + this.values[k] = v; + } + }, + // Return the value for a key, or a default value. + // If 'defaultKey' is passed then 'dflt' is assumed to be an object with + // a number of possible default values as properties where 'defaultKey' is + // the key of the property that will be chosen; otherwise it's assumed to be + // a single value. + get: function get(k, dflt, defaultKey) { + if (defaultKey) { + return this.has(k) ? this.values[k] : dflt[defaultKey]; + } + return this.has(k) ? this.values[k] : dflt; + }, + // Check whether we have a value for a key. + has: function has(k) { + return k in this.values; + }, + // Accept a setting if its one of the given alternatives. + alt: function alt(k, v, a) { + for (var n = 0; n < a.length; ++n) { + if (v === a[n]) { + this.set(k, v); + break; + } + } + }, + // Accept a setting if its a valid (signed) integer. + integer: function integer(k, v) { + if (/^-?\d+$/.test(v)) { + // integer + this.set(k, parseInt(v, 10)); + } + }, + // Accept a setting if its a valid percentage. + percent: function percent(k, v) { + var m; + if (m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/)) { + v = parseFloat(v); + if (v >= 0 && v <= 100) { + this.set(k, v); + return true; + } + } + return false; + } + }; + + // Helper function to parse input into groups separated by 'groupDelim', and + // interprete each group as a key/value pair separated by 'keyValueDelim'. + function parseOptions(input, callback, keyValueDelim, groupDelim) { + var groups = groupDelim ? input.split(groupDelim) : [input]; + for (var i in groups) { + if (typeof groups[i] !== "string") { + continue; + } + var kv = groups[i].split(keyValueDelim); + if (kv.length !== 2) { + continue; + } + var k = kv[0]; + var v = kv[1]; + callback(k, v); + } + } + + function parseCue(input, cue, regionList) { + // Remember the original input if we need to throw an error. + var oInput = input; + + // 4.1 WebVTT timestamp + function consumeTimeStamp() { + var ts = parseTimeStamp(input); + if (ts === null) { + throw new ParsingError(ParsingError.Errors.BadTimeStamp, "Malformed timestamp: " + oInput); + } + // Remove time stamp from input. + input = input.replace(/^[^\sa-zA-Z-]+/, ""); + return ts; + } + + // 4.4.2 WebVTT cue settings + function consumeCueSettings(input, cue) { + var settings = new Settings(); + + parseOptions(input, function (k, v) { + switch (k) { + case "region": + // Find the last region we parsed with the same region id. + for (var i = regionList.length - 1; i >= 0; i--) { + if (regionList[i].id === v) { + settings.set(k, regionList[i].region); + break; + } + } + break; + case "vertical": + settings.alt(k, v, ["rl", "lr"]); + break; + case "line": + var vals = v.split(","), + vals0 = vals[0]; + settings.integer(k, vals0); + settings.percent(k, vals0) ? settings.set("snapToLines", false) : null; + settings.alt(k, vals0, ["auto"]); + if (vals.length === 2) { + settings.alt("lineAlign", vals[1], ["start", "middle", "end"]); + } + break; + case "position": + vals = v.split(","); + settings.percent(k, vals[0]); + if (vals.length === 2) { + settings.alt("positionAlign", vals[1], ["start", "middle", "end"]); + } + break; + case "size": + settings.percent(k, v); + break; + case "align": + settings.alt(k, v, ["start", "middle", "end", "left", "right"]); + break; + } + }, /:/, /\s/); + + // Apply default values for any missing fields. + cue.region = settings.get("region", null); + cue.vertical = settings.get("vertical", ""); + cue.line = settings.get("line", "auto"); + cue.lineAlign = settings.get("lineAlign", "start"); + cue.snapToLines = settings.get("snapToLines", true); + cue.size = settings.get("size", 100); + cue.align = settings.get("align", "middle"); + cue.position = settings.get("position", { + start: 0, + left: 0, + middle: 50, + end: 100, + right: 100 + }, cue.align); + cue.positionAlign = settings.get("positionAlign", { + start: "start", + left: "start", + middle: "middle", + end: "end", + right: "end" + }, cue.align); + } + + function skipWhitespace() { + input = input.replace(/^\s+/, ""); + } + + // 4.1 WebVTT cue timings. + skipWhitespace(); + cue.startTime = consumeTimeStamp(); // (1) collect cue start time + skipWhitespace(); + if (input.substr(0, 3) !== "-->") { + // (3) next characters must match "-->" + throw new ParsingError(ParsingError.Errors.BadTimeStamp, "Malformed time stamp (time stamps must be separated by '-->'): " + oInput); + } + input = input.substr(3); + skipWhitespace(); + cue.endTime = consumeTimeStamp(); // (5) collect cue end time + + // 4.1 WebVTT cue settings list. + skipWhitespace(); + consumeCueSettings(input, cue); + } + + var ESCAPE = { + "&": "&", + "<": "<", + ">": ">", + "‎": "\u200E", + "‏": "\u200F", + " ": "\xA0" + }; + + var TAG_NAME = { + c: "span", + i: "i", + b: "b", + u: "u", + ruby: "ruby", + rt: "rt", + v: "span", + lang: "span" + }; + + var TAG_ANNOTATION = { + v: "title", + lang: "lang" + }; + + var NEEDS_PARENT = { + rt: "ruby" + }; + + // Parse content into a document fragment. + function parseContent(window, input) { + function nextToken() { + // Check for end-of-string. + if (!input) { + return null; + } + + // Consume 'n' characters from the input. + function consume(result) { + input = input.substr(result.length); + return result; + } + + var m = input.match(/^([^<]*)(<[^>]*>?)?/); + // If there is some text before the next tag, return it, otherwise return + // the tag. + return consume(m[1] ? m[1] : m[2]); + } + + // Unescape a string 's'. + function unescape1(e) { + return ESCAPE[e]; + } + + function unescape(s) { + while (m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/)) { + s = s.replace(m[0], unescape1); + } + return s; + } + + function shouldAdd(current, element) { + return !NEEDS_PARENT[element.localName] || NEEDS_PARENT[element.localName] === current.localName; + } + + // Create an element for this tag. + function createElement(type, annotation) { + var tagName = TAG_NAME[type]; + if (!tagName) { + return null; + } + var element = window.document.createElement(tagName); + element.localName = tagName; + var name = TAG_ANNOTATION[type]; + if (name && annotation) { + element[name] = annotation.trim(); + } + return element; + } + + var rootDiv = window.document.createElement("div"), + current = rootDiv, + t, + tagStack = []; + + while ((t = nextToken()) !== null) { + if (t[0] === '<') { + if (t[1] === "/") { + // If the closing tag matches, move back up to the parent node. + if (tagStack.length && tagStack[tagStack.length - 1] === t.substr(2).replace(">", "")) { + tagStack.pop(); + current = current.parentNode; + } + // Otherwise just ignore the end tag. + continue; + } + var ts = parseTimeStamp(t.substr(1, t.length - 2)); + var node; + if (ts) { + // Timestamps are lead nodes as well. + node = window.document.createProcessingInstruction("timestamp", ts); + current.appendChild(node); + continue; + } + var m = t.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/); + // If we can't parse the tag, skip to the next tag. + if (!m) { + continue; + } + // Try to construct an element, and ignore the tag if we couldn't. + node = createElement(m[1], m[3]); + if (!node) { + continue; + } + // Determine if the tag should be added based on the context of where it + // is placed in the cuetext. + if (!shouldAdd(current, node)) { + continue; + } + // Set the class list (as a list of classes, separated by space). + if (m[2]) { + node.className = m[2].substr(1).replace('.', ' '); + } + // Append the node to the current node, and enter the scope of the new + // node. + tagStack.push(m[1]); + current.appendChild(node); + current = node; + continue; + } + + // Text nodes are leaf nodes. + current.appendChild(window.document.createTextNode(unescape(t))); + } + + return rootDiv; + } + + // This is a list of all the Unicode characters that have a strong + // right-to-left category. What this means is that these characters are + // written right-to-left for sure. It was generated by pulling all the strong + // right-to-left characters out of the Unicode data table. That table can + // found at: http://www.unicode.org/Public/UNIDATA/UnicodeData.txt + var strongRTLRanges = [[0x5be, 0x5be], [0x5c0, 0x5c0], [0x5c3, 0x5c3], [0x5c6, 0x5c6], [0x5d0, 0x5ea], [0x5f0, 0x5f4], [0x608, 0x608], [0x60b, 0x60b], [0x60d, 0x60d], [0x61b, 0x61b], [0x61e, 0x64a], [0x66d, 0x66f], [0x671, 0x6d5], [0x6e5, 0x6e6], [0x6ee, 0x6ef], [0x6fa, 0x70d], [0x70f, 0x710], [0x712, 0x72f], [0x74d, 0x7a5], [0x7b1, 0x7b1], [0x7c0, 0x7ea], [0x7f4, 0x7f5], [0x7fa, 0x7fa], [0x800, 0x815], [0x81a, 0x81a], [0x824, 0x824], [0x828, 0x828], [0x830, 0x83e], [0x840, 0x858], [0x85e, 0x85e], [0x8a0, 0x8a0], [0x8a2, 0x8ac], [0x200f, 0x200f], [0xfb1d, 0xfb1d], [0xfb1f, 0xfb28], [0xfb2a, 0xfb36], [0xfb38, 0xfb3c], [0xfb3e, 0xfb3e], [0xfb40, 0xfb41], [0xfb43, 0xfb44], [0xfb46, 0xfbc1], [0xfbd3, 0xfd3d], [0xfd50, 0xfd8f], [0xfd92, 0xfdc7], [0xfdf0, 0xfdfc], [0xfe70, 0xfe74], [0xfe76, 0xfefc], [0x10800, 0x10805], [0x10808, 0x10808], [0x1080a, 0x10835], [0x10837, 0x10838], [0x1083c, 0x1083c], [0x1083f, 0x10855], [0x10857, 0x1085f], [0x10900, 0x1091b], [0x10920, 0x10939], [0x1093f, 0x1093f], [0x10980, 0x109b7], [0x109be, 0x109bf], [0x10a00, 0x10a00], [0x10a10, 0x10a13], [0x10a15, 0x10a17], [0x10a19, 0x10a33], [0x10a40, 0x10a47], [0x10a50, 0x10a58], [0x10a60, 0x10a7f], [0x10b00, 0x10b35], [0x10b40, 0x10b55], [0x10b58, 0x10b72], [0x10b78, 0x10b7f], [0x10c00, 0x10c48], [0x1ee00, 0x1ee03], [0x1ee05, 0x1ee1f], [0x1ee21, 0x1ee22], [0x1ee24, 0x1ee24], [0x1ee27, 0x1ee27], [0x1ee29, 0x1ee32], [0x1ee34, 0x1ee37], [0x1ee39, 0x1ee39], [0x1ee3b, 0x1ee3b], [0x1ee42, 0x1ee42], [0x1ee47, 0x1ee47], [0x1ee49, 0x1ee49], [0x1ee4b, 0x1ee4b], [0x1ee4d, 0x1ee4f], [0x1ee51, 0x1ee52], [0x1ee54, 0x1ee54], [0x1ee57, 0x1ee57], [0x1ee59, 0x1ee59], [0x1ee5b, 0x1ee5b], [0x1ee5d, 0x1ee5d], [0x1ee5f, 0x1ee5f], [0x1ee61, 0x1ee62], [0x1ee64, 0x1ee64], [0x1ee67, 0x1ee6a], [0x1ee6c, 0x1ee72], [0x1ee74, 0x1ee77], [0x1ee79, 0x1ee7c], [0x1ee7e, 0x1ee7e], [0x1ee80, 0x1ee89], [0x1ee8b, 0x1ee9b], [0x1eea1, 0x1eea3], [0x1eea5, 0x1eea9], [0x1eeab, 0x1eebb], [0x10fffd, 0x10fffd]]; + + function isStrongRTLChar(charCode) { + for (var i = 0; i < strongRTLRanges.length; i++) { + var currentRange = strongRTLRanges[i]; + if (charCode >= currentRange[0] && charCode <= currentRange[1]) { + return true; + } + } + + return false; + } + + function determineBidi(cueDiv) { + var nodeStack = [], + text = "", + charCode; + + if (!cueDiv || !cueDiv.childNodes) { + return "ltr"; + } + + function pushNodes(nodeStack, node) { + for (var i = node.childNodes.length - 1; i >= 0; i--) { + nodeStack.push(node.childNodes[i]); + } + } + + function nextTextNode(nodeStack) { + if (!nodeStack || !nodeStack.length) { + return null; + } + + var node = nodeStack.pop(), + text = node.textContent || node.innerText; + if (text) { + // TODO: This should match all unicode type B characters (paragraph + // separator characters). See issue #115. + var m = text.match(/^.*(\n|\r)/); + if (m) { + nodeStack.length = 0; + return m[0]; + } + return text; + } + if (node.tagName === "ruby") { + return nextTextNode(nodeStack); + } + if (node.childNodes) { + pushNodes(nodeStack, node); + return nextTextNode(nodeStack); + } + } + + pushNodes(nodeStack, cueDiv); + while (text = nextTextNode(nodeStack)) { + for (var i = 0; i < text.length; i++) { + charCode = text.charCodeAt(i); + if (isStrongRTLChar(charCode)) { + return "rtl"; + } + } + } + return "ltr"; + } + + function computeLinePos(cue) { + if (typeof cue.line === "number" && (cue.snapToLines || cue.line >= 0 && cue.line <= 100)) { + return cue.line; + } + if (!cue.track || !cue.track.textTrackList || !cue.track.textTrackList.mediaElement) { + return -1; + } + var track = cue.track, + trackList = track.textTrackList, + count = 0; + for (var i = 0; i < trackList.length && trackList[i] !== track; i++) { + if (trackList[i].mode === "showing") { + count++; + } + } + return ++count * -1; + } + + function StyleBox() { + } + + // Apply styles to a div. If there is no div passed then it defaults to the + // div on 'this'. + StyleBox.prototype.applyStyles = function (styles, div) { + div = div || this.div; + for (var prop in styles) { + if (styles.hasOwnProperty(prop)) { + div.style[prop] = styles[prop]; + } + } + }; + + StyleBox.prototype.formatStyle = function (val, unit) { + return val === 0 ? 0 : val + unit; + }; + + // Constructs the computed display state of the cue (a div). Places the div + // into the overlay which should be a block level element (usually a div). + function CueStyleBox(window, cue, styleOptions) { + StyleBox.call(this); + this.cue = cue; + + // Parse our cue's text into a DOM tree rooted at 'cueDiv'. This div will + // have inline positioning and will function as the cue background box. + this.cueDiv = parseContent(window, cue.text); + var styles = { + color: "rgba(255, 255, 255, 1)", + backgroundColor: "rgba(0, 0, 0, 0.8)", + position: "relative", + left: 0, + right: 0, + top: 0, + bottom: 0, + display: "inline", + writingMode: cue.vertical === "" ? "horizontal-tb" : cue.vertical === "lr" ? "vertical-lr" : "vertical-rl", + unicodeBidi: "plaintext" + }; + + this.applyStyles(styles, this.cueDiv); + + // Create an absolutely positioned div that will be used to position the cue + // div. Note, all WebVTT cue-setting alignments are equivalent to the CSS + // mirrors of them except "middle" which is "center" in CSS. + this.div = window.document.createElement("div"); + styles = { + direction: determineBidi(this.cueDiv), + writingMode: cue.vertical === "" ? "horizontal-tb" : cue.vertical === "lr" ? "vertical-lr" : "vertical-rl", + unicodeBidi: "plaintext", + textAlign: cue.align === "middle" ? "center" : cue.align, + font: styleOptions.font, + whiteSpace: "pre-line", + position: "absolute" + }; + + this.applyStyles(styles); + this.div.appendChild(this.cueDiv); + + // Calculate the distance from the reference edge of the viewport to the text + // position of the cue box. The reference edge will be resolved later when + // the box orientation styles are applied. + var textPos = 0; + switch (cue.positionAlign) { + case "start": + textPos = cue.position; + break; + case "middle": + textPos = cue.position - cue.size / 2; + break; + case "end": + textPos = cue.position - cue.size; + break; + } + + // Horizontal box orientation; textPos is the distance from the left edge of the + // area to the left edge of the box and cue.size is the distance extending to + // the right from there. + if (cue.vertical === "") { + this.applyStyles({ + left: this.formatStyle(textPos, "%"), + width: this.formatStyle(cue.size, "%") + }); + // Vertical box orientation; textPos is the distance from the top edge of the + // area to the top edge of the box and cue.size is the height extending + // downwards from there. + } else { + this.applyStyles({ + top: this.formatStyle(textPos, "%"), + height: this.formatStyle(cue.size, "%") + }); + } + + this.move = function (box) { + this.applyStyles({ + top: this.formatStyle(box.top, "px"), + bottom: this.formatStyle(box.bottom, "px"), + left: this.formatStyle(box.left, "px"), + right: this.formatStyle(box.right, "px"), + height: this.formatStyle(box.height, "px"), + width: this.formatStyle(box.width, "px") + }); + }; + } + + CueStyleBox.prototype = _objCreate(StyleBox.prototype); + CueStyleBox.prototype.constructor = CueStyleBox; + + // Represents the co-ordinates of an Element in a way that we can easily + // compute things with such as if it overlaps or intersects with another Element. + // Can initialize it with either a StyleBox or another BoxPosition. + function BoxPosition(obj) { + // Either a BoxPosition was passed in and we need to copy it, or a StyleBox + // was passed in and we need to copy the results of 'getBoundingClientRect' + // as the object returned is readonly. All co-ordinate values are in reference + // to the viewport origin (top left). + var lh, height, width, top; + if (obj.div) { + height = obj.div.offsetHeight; + width = obj.div.offsetWidth; + top = obj.div.offsetTop; + + var rects = (rects = obj.div.childNodes) && (rects = rects[0]) && rects.getClientRects && rects.getClientRects(); + obj = obj.div.getBoundingClientRect(); + // In certain cases the outter div will be slightly larger then the sum of + // the inner div's lines. This could be due to bold text, etc, on some platforms. + // In this case we should get the average line height and use that. This will + // result in the desired behaviour. + lh = rects ? Math.max(rects[0] && rects[0].height || 0, obj.height / rects.length) : 0; + } + this.left = obj.left; + this.right = obj.right; + this.top = obj.top || top; + this.height = obj.height || height; + this.bottom = obj.bottom || top + (obj.height || height); + this.width = obj.width || width; + this.lineHeight = lh !== undefined ? lh : obj.lineHeight; + } + + // Move the box along a particular axis. Optionally pass in an amount to move + // the box. If no amount is passed then the default is the line height of the + // box. + BoxPosition.prototype.move = function (axis, toMove) { + toMove = toMove !== undefined ? toMove : this.lineHeight; + switch (axis) { + case "+x": + this.left += toMove; + this.right += toMove; + break; + case "-x": + this.left -= toMove; + this.right -= toMove; + break; + case "+y": + this.top += toMove; + this.bottom += toMove; + break; + case "-y": + this.top -= toMove; + this.bottom -= toMove; + break; + } + }; + + // Check if this box overlaps another box, b2. + BoxPosition.prototype.overlaps = function (b2) { + return this.left < b2.right && this.right > b2.left && this.top < b2.bottom && this.bottom > b2.top; + }; + + // Check if this box overlaps any other boxes in boxes. + BoxPosition.prototype.overlapsAny = function (boxes) { + for (var i = 0; i < boxes.length; i++) { + if (this.overlaps(boxes[i])) { + return true; + } + } + return false; + }; + + // Check if this box is within another box. + BoxPosition.prototype.within = function (container) { + return this.top >= container.top && this.bottom <= container.bottom && this.left >= container.left && this.right <= container.right; + }; + + // Check if this box is entirely within the container or it is overlapping + // on the edge opposite of the axis direction passed. For example, if "+x" is + // passed and the box is overlapping on the left edge of the container, then + // return true. + BoxPosition.prototype.overlapsOppositeAxis = function (container, axis) { + switch (axis) { + case "+x": + return this.left < container.left; + case "-x": + return this.right > container.right; + case "+y": + return this.top < container.top; + case "-y": + return this.bottom > container.bottom; + } + }; + + // Find the percentage of the area that this box is overlapping with another + // box. + BoxPosition.prototype.intersectPercentage = function (b2) { + var x = Math.max(0, Math.min(this.right, b2.right) - Math.max(this.left, b2.left)), + y = Math.max(0, Math.min(this.bottom, b2.bottom) - Math.max(this.top, b2.top)), + intersectArea = x * y; + return intersectArea / (this.height * this.width); + }; + + // Convert the positions from this box to CSS compatible positions using + // the reference container's positions. This has to be done because this + // box's positions are in reference to the viewport origin, whereas, CSS + // values are in referecne to their respective edges. + BoxPosition.prototype.toCSSCompatValues = function (reference) { + return { + top: this.top - reference.top, + bottom: reference.bottom - this.bottom, + left: this.left - reference.left, + right: reference.right - this.right, + height: this.height, + width: this.width + }; + }; + + // Get an object that represents the box's position without anything extra. + // Can pass a StyleBox, HTMLElement, or another BoxPositon. + BoxPosition.getSimpleBoxPosition = function (obj) { + var height = obj.div ? obj.div.offsetHeight : obj.tagName ? obj.offsetHeight : 0; + var width = obj.div ? obj.div.offsetWidth : obj.tagName ? obj.offsetWidth : 0; + var top = obj.div ? obj.div.offsetTop : obj.tagName ? obj.offsetTop : 0; + + obj = obj.div ? obj.div.getBoundingClientRect() : obj.tagName ? obj.getBoundingClientRect() : obj; + var ret = { + left: obj.left, + right: obj.right, + top: obj.top || top, + height: obj.height || height, + bottom: obj.bottom || top + (obj.height || height), + width: obj.width || width + }; + return ret; + }; + + // Move a StyleBox to its specified, or next best, position. The containerBox + // is the box that contains the StyleBox, such as a div. boxPositions are + // a list of other boxes that the styleBox can't overlap with. + function moveBoxToLinePosition(window, styleBox, containerBox, boxPositions) { + + // Find the best position for a cue box, b, on the video. The axis parameter + // is a list of axis, the order of which, it will move the box along. For example: + // Passing ["+x", "-x"] will move the box first along the x axis in the positive + // direction. If it doesn't find a good position for it there it will then move + // it along the x axis in the negative direction. + function findBestPosition(b, axis) { + var bestPosition, + specifiedPosition = new BoxPosition(b), + percentage = 1; // Highest possible so the first thing we get is better. + + for (var i = 0; i < axis.length; i++) { + while (b.overlapsOppositeAxis(containerBox, axis[i]) || b.within(containerBox) && b.overlapsAny(boxPositions)) { + b.move(axis[i]); + } + // We found a spot where we aren't overlapping anything. This is our + // best position. + if (b.within(containerBox)) { + return b; + } + var p = b.intersectPercentage(containerBox); + // If we're outside the container box less then we were on our last try + // then remember this position as the best position. + if (percentage > p) { + bestPosition = new BoxPosition(b); + percentage = p; + } + // Reset the box position to the specified position. + b = new BoxPosition(specifiedPosition); + } + return bestPosition || specifiedPosition; + } + + var boxPosition = new BoxPosition(styleBox), + cue = styleBox.cue, + linePos = computeLinePos(cue), + axis = []; + + // If we have a line number to align the cue to. + if (cue.snapToLines) { + var size; + switch (cue.vertical) { + case "": + axis = ["+y", "-y"]; + size = "height"; + break; + case "rl": + axis = ["+x", "-x"]; + size = "width"; + break; + case "lr": + axis = ["-x", "+x"]; + size = "width"; + break; + } + + var step = boxPosition.lineHeight, + position = step * Math.round(linePos), + maxPosition = containerBox[size] + step, + initialAxis = axis[0]; + + // If the specified intial position is greater then the max position then + // clamp the box to the amount of steps it would take for the box to + // reach the max position. + if (Math.abs(position) > maxPosition) { + position = position < 0 ? -1 : 1; + position *= Math.ceil(maxPosition / step) * step; + } + + // If computed line position returns negative then line numbers are + // relative to the bottom of the video instead of the top. Therefore, we + // need to increase our initial position by the length or width of the + // video, depending on the writing direction, and reverse our axis directions. + if (linePos < 0) { + position += cue.vertical === "" ? containerBox.height : containerBox.width; + axis = axis.reverse(); + } + + // Move the box to the specified position. This may not be its best + // position. + boxPosition.move(initialAxis, position); + } else { + // If we have a percentage line value for the cue. + var calculatedPercentage = boxPosition.lineHeight / containerBox.height * 100; + + switch (cue.lineAlign) { + case "middle": + linePos -= calculatedPercentage / 2; + break; + case "end": + linePos -= calculatedPercentage; + break; + } + + // Apply initial line position to the cue box. + switch (cue.vertical) { + case "": + styleBox.applyStyles({ + top: styleBox.formatStyle(linePos, "%") + }); + break; + case "rl": + styleBox.applyStyles({ + left: styleBox.formatStyle(linePos, "%") + }); + break; + case "lr": + styleBox.applyStyles({ + right: styleBox.formatStyle(linePos, "%") + }); + break; + } + + axis = ["+y", "-x", "+x", "-y"]; + + // Get the box position again after we've applied the specified positioning + // to it. + boxPosition = new BoxPosition(styleBox); + } + + var bestPosition = findBestPosition(boxPosition, axis); + styleBox.move(bestPosition.toCSSCompatValues(containerBox)); + } + + function WebVTT$1() { + } + + // Nothing + + + // Helper to allow strings to be decoded instead of the default binary utf8 data. + WebVTT$1.StringDecoder = function () { + return { + decode: function decode(data) { + if (!data) { + return ""; + } + if (typeof data !== "string") { + throw new Error("Error - expected string data."); + } + return decodeURIComponent(encodeURIComponent(data)); + } + }; + }; + + WebVTT$1.convertCueToDOMTree = function (window, cuetext) { + if (!window || !cuetext) { + return null; + } + return parseContent(window, cuetext); + }; + + var FONT_SIZE_PERCENT = 0.05; + var FONT_STYLE = "sans-serif"; + var CUE_BACKGROUND_PADDING = "1.5%"; + + // Runs the processing model over the cues and regions passed to it. + // @param overlay A block level element (usually a div) that the computed cues + // and regions will be placed into. + WebVTT$1.processCues = function (window, cues, overlay) { + if (!window || !cues || !overlay) { + return null; + } + + // Remove all previous children. + while (overlay.firstChild) { + overlay.removeChild(overlay.firstChild); + } + + var paddedOverlay = window.document.createElement("div"); + paddedOverlay.style.position = "absolute"; + paddedOverlay.style.left = "0"; + paddedOverlay.style.right = "0"; + paddedOverlay.style.top = "0"; + paddedOverlay.style.bottom = "0"; + paddedOverlay.style.margin = CUE_BACKGROUND_PADDING; + overlay.appendChild(paddedOverlay); + + // Determine if we need to compute the display states of the cues. This could + // be the case if a cue's state has been changed since the last computation or + // if it has not been computed yet. + function shouldCompute(cues) { + for (var i = 0; i < cues.length; i++) { + if (cues[i].hasBeenReset || !cues[i].displayState) { + return true; + } + } + return false; + } + + // We don't need to recompute the cues' display states. Just reuse them. + if (!shouldCompute(cues)) { + for (var i = 0; i < cues.length; i++) { + paddedOverlay.appendChild(cues[i].displayState); + } + return; + } + + var boxPositions = [], + containerBox = BoxPosition.getSimpleBoxPosition(paddedOverlay), + fontSize = Math.round(containerBox.height * FONT_SIZE_PERCENT * 100) / 100; + var styleOptions = { + font: fontSize + "px " + FONT_STYLE + }; + + (function () { + var styleBox, cue; + + for (var i = 0; i < cues.length; i++) { + cue = cues[i]; + + // Compute the intial position and styles of the cue div. + styleBox = new CueStyleBox(window, cue, styleOptions); + paddedOverlay.appendChild(styleBox.div); + + // Move the cue div to it's correct line position. + moveBoxToLinePosition(window, styleBox, containerBox, boxPositions); + + // Remember the computed div so that we don't have to recompute it later + // if we don't have too. + cue.displayState = styleBox.div; + + boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox)); + } + })(); + }; + + WebVTT$1.Parser = function (window, vttjs, decoder) { + if (!decoder) { + decoder = vttjs; + vttjs = {}; + } + if (!vttjs) { + vttjs = {}; + } + + this.window = window; + this.vttjs = vttjs; + this.state = "INITIAL"; + this.buffer = ""; + this.decoder = decoder || new TextDecoder("utf8"); + this.regionList = []; + }; + + WebVTT$1.Parser.prototype = { + // If the error is a ParsingError then report it to the consumer if + // possible. If it's not a ParsingError then throw it like normal. + reportOrThrowError: function reportOrThrowError(e) { + if (e instanceof ParsingError) { + this.onparsingerror && this.onparsingerror(e); + } else { + throw e; + } + }, + parse: function parse(data) { + var self = this; + + // If there is no data then we won't decode it, but will just try to parse + // whatever is in buffer already. This may occur in circumstances, for + // example when flush() is called. + if (data) { + // Try to decode the data that we received. + self.buffer += self.decoder.decode(data, {stream: true}); + } + + function collectNextLine() { + var buffer = self.buffer; + var pos = 0; + while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') { + ++pos; + } + var line = buffer.substr(0, pos); + // Advance the buffer early in case we fail below. + if (buffer[pos] === '\r') { + ++pos; + } + if (buffer[pos] === '\n') { + ++pos; + } + self.buffer = buffer.substr(pos); + return line; + } + + // 3.4 WebVTT region and WebVTT region settings syntax + function parseRegion(input) { + var settings = new Settings(); + + parseOptions(input, function (k, v) { + switch (k) { + case "id": + settings.set(k, v); + break; + case "width": + settings.percent(k, v); + break; + case "lines": + settings.integer(k, v); + break; + case "regionanchor": + case "viewportanchor": + var xy = v.split(','); + if (xy.length !== 2) { + break; + } + // We have to make sure both x and y parse, so use a temporary + // settings object here. + var anchor = new Settings(); + anchor.percent("x", xy[0]); + anchor.percent("y", xy[1]); + if (!anchor.has("x") || !anchor.has("y")) { + break; + } + settings.set(k + "X", anchor.get("x")); + settings.set(k + "Y", anchor.get("y")); + break; + case "scroll": + settings.alt(k, v, ["up"]); + break; + } + }, /=/, /\s/); + + // Create the region, using default values for any values that were not + // specified. + if (settings.has("id")) { + var region = new (self.vttjs.VTTRegion || self.window.VTTRegion)(); + region.width = settings.get("width", 100); + region.lines = settings.get("lines", 3); + region.regionAnchorX = settings.get("regionanchorX", 0); + region.regionAnchorY = settings.get("regionanchorY", 100); + region.viewportAnchorX = settings.get("viewportanchorX", 0); + region.viewportAnchorY = settings.get("viewportanchorY", 100); + region.scroll = settings.get("scroll", ""); + // Register the region. + self.onregion && self.onregion(region); + // Remember the VTTRegion for later in case we parse any VTTCues that + // reference it. + self.regionList.push({ + id: settings.get("id"), + region: region + }); + } + } + + // draft-pantos-http-live-streaming-20 + // https://tools.ietf.org/html/draft-pantos-http-live-streaming-20#section-3.5 + // 3.5 WebVTT + function parseTimestampMap(input) { + var settings = new Settings(); + + parseOptions(input, function (k, v) { + switch (k) { + case "MPEGT": + settings.integer(k + 'S', v); + break; + case "LOCA": + settings.set(k + 'L', parseTimeStamp(v)); + break; + } + }, /[^\d]:/, /,/); + + self.ontimestampmap && self.ontimestampmap({ + "MPEGTS": settings.get("MPEGTS"), + "LOCAL": settings.get("LOCAL") + }); + } + + // 3.2 WebVTT metadata header syntax + function parseHeader(input) { + if (input.match(/X-TIMESTAMP-MAP/)) { + // This line contains HLS X-TIMESTAMP-MAP metadata + parseOptions(input, function (k, v) { + switch (k) { + case "X-TIMESTAMP-MAP": + parseTimestampMap(v); + break; + } + }, /=/); + } else { + parseOptions(input, function (k, v) { + switch (k) { + case "Region": + // 3.3 WebVTT region metadata header syntax + parseRegion(v); + break; + } + }, /:/); + } + } + + // 5.1 WebVTT file parsing. + try { + var line; + if (self.state === "INITIAL") { + // We can't start parsing until we have the first line. + if (!/\r\n|\n/.test(self.buffer)) { + return this; + } + + line = collectNextLine(); + + var m = line.match(/^WEBVTT([ \t].*)?$/); + if (!m || !m[0]) { + throw new ParsingError(ParsingError.Errors.BadSignature); + } + + self.state = "HEADER"; + } + + var alreadyCollectedLine = false; + while (self.buffer) { + // We can't parse a line until we have the full line. + if (!/\r\n|\n/.test(self.buffer)) { + return this; + } + + if (!alreadyCollectedLine) { + line = collectNextLine(); + } else { + alreadyCollectedLine = false; + } + + switch (self.state) { + case "HEADER": + // 13-18 - Allow a header (metadata) under the WEBVTT line. + if (/:/.test(line)) { + parseHeader(line); + } else if (!line) { + // An empty line terminates the header and starts the body (cues). + self.state = "ID"; + } + continue; + case "NOTE": + // Ignore NOTE blocks. + if (!line) { + self.state = "ID"; + } + continue; + case "ID": + // Check for the start of NOTE blocks. + if (/^NOTE($|[ \t])/.test(line)) { + self.state = "NOTE"; + break; + } + // 19-29 - Allow any number of line terminators, then initialize new cue values. + if (!line) { + continue; + } + self.cue = new (self.vttjs.VTTCue || self.window.VTTCue)(0, 0, ""); + self.state = "CUE"; + // 30-39 - Check if self line contains an optional identifier or timing data. + if (line.indexOf("-->") === -1) { + self.cue.id = line; + continue; + } + // Process line as start of a cue. + /*falls through*/ + case "CUE": + // 40 - Collect cue timings and settings. + try { + parseCue(line, self.cue, self.regionList); + } catch (e) { + self.reportOrThrowError(e); + // In case of an error ignore rest of the cue. + self.cue = null; + self.state = "BADCUE"; + continue; + } + self.state = "CUETEXT"; + continue; + case "CUETEXT": + var hasSubstring = line.indexOf("-->") !== -1; + // 34 - If we have an empty line then report the cue. + // 35 - If we have the special substring '-->' then report the cue, + // but do not collect the line as we need to process the current + // one as a new cue. + if (!line || hasSubstring && (alreadyCollectedLine = true)) { + // We are done parsing self cue. + self.oncue && self.oncue(self.cue); + self.cue = null; + self.state = "ID"; + continue; + } + if (self.cue.text) { + self.cue.text += "\n"; + } + self.cue.text += line; + continue; + case "BADCUE": + // BADCUE + // 54-62 - Collect and discard the remaining cue. + if (!line) { + self.state = "ID"; + } + continue; + } + } + } catch (e) { + self.reportOrThrowError(e); + + // If we are currently parsing a cue, report what we have. + if (self.state === "CUETEXT" && self.cue && self.oncue) { + self.oncue(self.cue); + } + self.cue = null; + // Enter BADWEBVTT state if header was not parsed correctly otherwise + // another exception occurred so enter BADCUE state. + self.state = self.state === "INITIAL" ? "BADWEBVTT" : "BADCUE"; + } + return this; + }, + flush: function flush() { + var self = this; + try { + // Finish decoding the stream. + self.buffer += self.decoder.decode(); + // Synthesize the end of the current cue or region. + if (self.cue || self.state === "HEADER") { + self.buffer += "\n\n"; + self.parse(); + } + // If we've flushed, parsed, and we're still on the INITIAL state then + // that means we don't have enough of the stream to parse the first + // line. + if (self.state === "INITIAL") { + throw new ParsingError(ParsingError.Errors.BadSignature); + } + } catch (e) { + self.reportOrThrowError(e); + } + self.onflush && self.onflush(); + return this; + } + }; + + var vtt = WebVTT$1; + + var vtt$1 = /*#__PURE__*/Object.freeze({ + default: vtt, + __moduleExports: vtt + }); + + /** + * Copyright 2013 vtt.js Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var autoKeyword = "auto"; + var directionSetting = { + "": 1, + "lr": 1, + "rl": 1 + }; + var alignSetting = { + "start": 1, + "middle": 1, + "end": 1, + "left": 1, + "right": 1 + }; + + function findDirectionSetting(value) { + if (typeof value !== "string") { + return false; + } + var dir = directionSetting[value.toLowerCase()]; + return dir ? value.toLowerCase() : false; + } + + function findAlignSetting(value) { + if (typeof value !== "string") { + return false; + } + var align = alignSetting[value.toLowerCase()]; + return align ? value.toLowerCase() : false; + } + + function VTTCue(startTime, endTime, text) { + /** + * Shim implementation specific properties. These properties are not in + * the spec. + */ + + // Lets us know when the VTTCue's data has changed in such a way that we need + // to recompute its display state. This lets us compute its display state + // lazily. + this.hasBeenReset = false; + + /** + * VTTCue and TextTrackCue properties + * http://dev.w3.org/html5/webvtt/#vttcue-interface + */ + + var _id = ""; + var _pauseOnExit = false; + var _startTime = startTime; + var _endTime = endTime; + var _text = text; + var _region = null; + var _vertical = ""; + var _snapToLines = true; + var _line = "auto"; + var _lineAlign = "start"; + var _position = 50; + var _positionAlign = "middle"; + var _size = 50; + var _align = "middle"; + + Object.defineProperties(this, { + "id": { + enumerable: true, + get: function get() { + return _id; + }, + set: function set(value) { + _id = "" + value; + } + }, + + "pauseOnExit": { + enumerable: true, + get: function get() { + return _pauseOnExit; + }, + set: function set(value) { + _pauseOnExit = !!value; + } + }, + + "startTime": { + enumerable: true, + get: function get() { + return _startTime; + }, + set: function set(value) { + if (typeof value !== "number") { + throw new TypeError("Start time must be set to a number."); + } + _startTime = value; + this.hasBeenReset = true; + } + }, + + "endTime": { + enumerable: true, + get: function get() { + return _endTime; + }, + set: function set(value) { + if (typeof value !== "number") { + throw new TypeError("End time must be set to a number."); + } + _endTime = value; + this.hasBeenReset = true; + } + }, + + "text": { + enumerable: true, + get: function get() { + return _text; + }, + set: function set(value) { + _text = "" + value; + this.hasBeenReset = true; + } + }, + + "region": { + enumerable: true, + get: function get() { + return _region; + }, + set: function set(value) { + _region = value; + this.hasBeenReset = true; + } + }, + + "vertical": { + enumerable: true, + get: function get() { + return _vertical; + }, + set: function set(value) { + var setting = findDirectionSetting(value); + // Have to check for false because the setting an be an empty string. + if (setting === false) { + throw new SyntaxError("An invalid or illegal string was specified."); + } + _vertical = setting; + this.hasBeenReset = true; + } + }, + + "snapToLines": { + enumerable: true, + get: function get() { + return _snapToLines; + }, + set: function set(value) { + _snapToLines = !!value; + this.hasBeenReset = true; + } + }, + + "line": { + enumerable: true, + get: function get() { + return _line; + }, + set: function set(value) { + if (typeof value !== "number" && value !== autoKeyword) { + throw new SyntaxError("An invalid number or illegal string was specified."); + } + _line = value; + this.hasBeenReset = true; + } + }, + + "lineAlign": { + enumerable: true, + get: function get() { + return _lineAlign; + }, + set: function set(value) { + var setting = findAlignSetting(value); + if (!setting) { + throw new SyntaxError("An invalid or illegal string was specified."); + } + _lineAlign = setting; + this.hasBeenReset = true; + } + }, + + "position": { + enumerable: true, + get: function get() { + return _position; + }, + set: function set(value) { + if (value < 0 || value > 100) { + throw new Error("Position must be between 0 and 100."); + } + _position = value; + this.hasBeenReset = true; + } + }, + + "positionAlign": { + enumerable: true, + get: function get() { + return _positionAlign; + }, + set: function set(value) { + var setting = findAlignSetting(value); + if (!setting) { + throw new SyntaxError("An invalid or illegal string was specified."); + } + _positionAlign = setting; + this.hasBeenReset = true; + } + }, + + "size": { + enumerable: true, + get: function get() { + return _size; + }, + set: function set(value) { + if (value < 0 || value > 100) { + throw new Error("Size must be between 0 and 100."); + } + _size = value; + this.hasBeenReset = true; + } + }, + + "align": { + enumerable: true, + get: function get() { + return _align; + }, + set: function set(value) { + var setting = findAlignSetting(value); + if (!setting) { + throw new SyntaxError("An invalid or illegal string was specified."); + } + _align = setting; + this.hasBeenReset = true; + } + } + }); + + /** + * Other <track> spec defined properties + */ + + // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state + this.displayState = undefined; + } + + /** + * VTTCue methods + */ + + VTTCue.prototype.getCueAsHTML = function () { + // Assume WebVTT.convertCueToDOMTree is on the global. + return WebVTT.convertCueToDOMTree(window, this.text); + }; + + var vttcue = VTTCue; + + var vttcue$1 = /*#__PURE__*/Object.freeze({ + default: vttcue, + __moduleExports: vttcue + }); + + /** + * Copyright 2013 vtt.js Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + var scrollSetting = { + "": true, + "up": true + }; + + function findScrollSetting(value) { + if (typeof value !== "string") { + return false; + } + var scroll = scrollSetting[value.toLowerCase()]; + return scroll ? value.toLowerCase() : false; + } + + function isValidPercentValue(value) { + return typeof value === "number" && value >= 0 && value <= 100; + } + + // VTTRegion shim http://dev.w3.org/html5/webvtt/#vttregion-interface + function VTTRegion() { + var _width = 100; + var _lines = 3; + var _regionAnchorX = 0; + var _regionAnchorY = 100; + var _viewportAnchorX = 0; + var _viewportAnchorY = 100; + var _scroll = ""; + + Object.defineProperties(this, { + "width": { + enumerable: true, + get: function get() { + return _width; + }, + set: function set(value) { + if (!isValidPercentValue(value)) { + throw new Error("Width must be between 0 and 100."); + } + _width = value; + } + }, + "lines": { + enumerable: true, + get: function get() { + return _lines; + }, + set: function set(value) { + if (typeof value !== "number") { + throw new TypeError("Lines must be set to a number."); + } + _lines = value; + } + }, + "regionAnchorY": { + enumerable: true, + get: function get() { + return _regionAnchorY; + }, + set: function set(value) { + if (!isValidPercentValue(value)) { + throw new Error("RegionAnchorX must be between 0 and 100."); + } + _regionAnchorY = value; + } + }, + "regionAnchorX": { + enumerable: true, + get: function get() { + return _regionAnchorX; + }, + set: function set(value) { + if (!isValidPercentValue(value)) { + throw new Error("RegionAnchorY must be between 0 and 100."); + } + _regionAnchorX = value; + } + }, + "viewportAnchorY": { + enumerable: true, + get: function get() { + return _viewportAnchorY; + }, + set: function set(value) { + if (!isValidPercentValue(value)) { + throw new Error("ViewportAnchorY must be between 0 and 100."); + } + _viewportAnchorY = value; + } + }, + "viewportAnchorX": { + enumerable: true, + get: function get() { + return _viewportAnchorX; + }, + set: function set(value) { + if (!isValidPercentValue(value)) { + throw new Error("ViewportAnchorX must be between 0 and 100."); + } + _viewportAnchorX = value; + } + }, + "scroll": { + enumerable: true, + get: function get() { + return _scroll; + }, + set: function set(value) { + var setting = findScrollSetting(value); + // Have to check for false as an empty string is a legal value. + if (setting === false) { + throw new SyntaxError("An invalid or illegal string was specified."); + } + _scroll = setting; + } + } + }); + } + + var vttregion = VTTRegion; + + var vttregion$1 = /*#__PURE__*/Object.freeze({ + default: vttregion, + __moduleExports: vttregion + }); + + var require$$0 = (vtt$1 && vtt) || vtt$1; + + var require$$1 = (vttcue$1 && vttcue) || vttcue$1; + + var require$$2 = (vttregion$1 && vttregion) || vttregion$1; + + var browserIndex = createCommonjsModule(function (module) { + /** + * Copyright 2013 vtt.js Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + // Default exports for Node. Export the extended versions of VTTCue and + // VTTRegion in Node since we likely want the capability to convert back and + // forth between JSON. If we don't then it's not that big of a deal since we're + // off browser. + + + var vttjs = module.exports = { + WebVTT: require$$0, + VTTCue: require$$1, + VTTRegion: require$$2 + }; + + window_1.vttjs = vttjs; + window_1.WebVTT = vttjs.WebVTT; + + var cueShim = vttjs.VTTCue; + var regionShim = vttjs.VTTRegion; + var nativeVTTCue = window_1.VTTCue; + var nativeVTTRegion = window_1.VTTRegion; + + vttjs.shim = function () { + window_1.VTTCue = cueShim; + window_1.VTTRegion = regionShim; + }; + + vttjs.restore = function () { + window_1.VTTCue = nativeVTTCue; + window_1.VTTRegion = nativeVTTRegion; + }; + + if (!window_1.VTTCue) { + vttjs.shim(); + } + }); + var browserIndex_1 = browserIndex.WebVTT; + var browserIndex_2 = browserIndex.VTTCue; + var browserIndex_3 = browserIndex.VTTRegion; + + /** + * @file tech.js + */ + + /** + * An Object containing a structure like: `{src: 'url', type: 'mimetype'}` or string + * that just contains the src url alone. + * * `var SourceObject = {src: 'http://ex.com/video.mp4', type: 'video/mp4'};` + * `var SourceString = 'http://example.com/some-video.mp4';` + * + * @typedef {Object|string} Tech~SourceObject + * + * @property {string} src + * The url to the source + * + * @property {string} type + * The mime type of the source + */ + + /** + * A function used by {@link Tech} to create a new {@link TextTrack}. + * + * @private + * + * @param {Tech} self + * An instance of the Tech class. + * + * @param {string} kind + * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata) + * + * @param {string} [label] + * Label to identify the text track + * + * @param {string} [language] + * Two letter language abbreviation + * + * @param {Object} [options={}] + * An object with additional text track options + * + * @return {TextTrack} + * The text track that was created. + */ + function createTrackHelper(self, kind, label, language) { + var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; + + var tracks = self.textTracks(); + + options.kind = kind; + + if (label) { + options.label = label; + } + if (language) { + options.language = language; + } + options.tech = self; + + var track = new ALL.text.TrackClass(options); + + tracks.addTrack(track); + + return track; + } + + /** + * This is the base class for media playback technology controllers, such as + * {@link Flash} and {@link HTML5} + * + * @extends Component + */ + + var Tech = function (_Component) { + inherits(Tech, _Component); + + /** + * Create an instance of this Tech. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Component~ReadyCallback} ready + * Callback function to call when the `HTML5` Tech is ready. + */ + function Tech() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var ready = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () { + }; + classCallCheck(this, Tech); + + // we don't want the tech to report user activity automatically. + // This is done manually in addControlsListeners + options.reportTouchActivity = false; + + // keep track of whether the current source has played at all to + // implement a very limited played() + var _this = possibleConstructorReturn(this, _Component.call(this, null, options, ready)); + + _this.hasStarted_ = false; + _this.on('playing', function () { + this.hasStarted_ = true; + }); + _this.on('loadstart', function () { + this.hasStarted_ = false; + }); + + ALL.names.forEach(function (name) { + var props = ALL[name]; + + if (options && options[props.getterName]) { + _this[props.privateName] = options[props.getterName]; + } + }); + + // Manually track progress in cases where the browser/flash player doesn't report it. + if (!_this.featuresProgressEvents) { + _this.manualProgressOn(); + } + + // Manually track timeupdates in cases where the browser/flash player doesn't report it. + if (!_this.featuresTimeupdateEvents) { + _this.manualTimeUpdatesOn(); + } + + ['Text', 'Audio', 'Video'].forEach(function (track) { + if (options['native' + track + 'Tracks'] === false) { + _this['featuresNative' + track + 'Tracks'] = false; + } + }); + + if (options.nativeCaptions === false || options.nativeTextTracks === false) { + _this.featuresNativeTextTracks = false; + } else if (options.nativeCaptions === true || options.nativeTextTracks === true) { + _this.featuresNativeTextTracks = true; + } + + if (!_this.featuresNativeTextTracks) { + _this.emulateTextTracks(); + } + + _this.autoRemoteTextTracks_ = new ALL.text.ListClass(); + + _this.initTrackListeners(); + + // Turn on component tap events only if not using native controls + if (!options.nativeControlsForTouch) { + _this.emitTapEvents(); + } + + if (_this.constructor) { + _this.name_ = _this.constructor.name || 'Unknown Tech'; + } + return _this; + } + + /** + * A special function to trigger source set in a way that will allow player + * to re-trigger if the player or tech are not ready yet. + * + * @fires Tech#sourceset + * @param {string} src The source string at the time of the source changing. + */ + + + Tech.prototype.triggerSourceset = function triggerSourceset(src) { + var _this2 = this; + + if (!this.isReady_) { + // on initial ready we have to trigger source set + // 1ms after ready so that player can watch for it. + this.one('ready', function () { + return _this2.setTimeout(function () { + return _this2.triggerSourceset(src); + }, 1); + }); + } + + /** + * Fired when the source is set on the tech causing the media element + * to reload. + * + * @see {@link Player#event:sourceset} + * @event Tech#sourceset + * @type {EventTarget~Event} + */ + this.trigger({ + src: src, + type: 'sourceset' + }); + }; + + /* Fallbacks for unsupported event types + ================================================================================ */ + + /** + * Polyfill the `progress` event for browsers that don't support it natively. + * + * @see {@link Tech#trackProgress} + */ + + + Tech.prototype.manualProgressOn = function manualProgressOn() { + this.on('durationchange', this.onDurationChange); + + this.manualProgress = true; + + // Trigger progress watching when a source begins loading + this.one('ready', this.trackProgress); + }; + + /** + * Turn off the polyfill for `progress` events that was created in + * {@link Tech#manualProgressOn} + */ + + + Tech.prototype.manualProgressOff = function manualProgressOff() { + this.manualProgress = false; + this.stopTrackingProgress(); + + this.off('durationchange', this.onDurationChange); + }; + + /** + * This is used to trigger a `progress` event when the buffered percent changes. It + * sets an interval function that will be called every 500 milliseconds to check if the + * buffer end percent has changed. + * + * > This function is called by {@link Tech#manualProgressOn} + * + * @param {EventTarget~Event} event + * The `ready` event that caused this to run. + * + * @listens Tech#ready + * @fires Tech#progress + */ + + + Tech.prototype.trackProgress = function trackProgress(event) { + this.stopTrackingProgress(); + this.progressInterval = this.setInterval(bind(this, function () { + // Don't trigger unless buffered amount is greater than last time + + var numBufferedPercent = this.bufferedPercent(); + + if (this.bufferedPercent_ !== numBufferedPercent) { + /** + * See {@link Player#progress} + * + * @event Tech#progress + * @type {EventTarget~Event} + */ + this.trigger('progress'); + } + + this.bufferedPercent_ = numBufferedPercent; + + if (numBufferedPercent === 1) { + this.stopTrackingProgress(); + } + }), 500); + }; + + /** + * Update our internal duration on a `durationchange` event by calling + * {@link Tech#duration}. + * + * @param {EventTarget~Event} event + * The `durationchange` event that caused this to run. + * + * @listens Tech#durationchange + */ + + + Tech.prototype.onDurationChange = function onDurationChange(event) { + this.duration_ = this.duration(); + }; + + /** + * Get and create a `TimeRange` object for buffering. + * + * @return {TimeRange} + * The time range object that was created. + */ + + + Tech.prototype.buffered = function buffered() { + return createTimeRanges(0, 0); + }; + + /** + * Get the percentage of the current video that is currently buffered. + * + * @return {number} + * A number from 0 to 1 that represents the decimal percentage of the + * video that is buffered. + * + */ + + + Tech.prototype.bufferedPercent = function bufferedPercent$$1() { + return bufferedPercent(this.buffered(), this.duration_); + }; + + /** + * Turn off the polyfill for `progress` events that was created in + * {@link Tech#manualProgressOn} + * Stop manually tracking progress events by clearing the interval that was set in + * {@link Tech#trackProgress}. + */ + + + Tech.prototype.stopTrackingProgress = function stopTrackingProgress() { + this.clearInterval(this.progressInterval); + }; + + /** + * Polyfill the `timeupdate` event for browsers that don't support it. + * + * @see {@link Tech#trackCurrentTime} + */ + + + Tech.prototype.manualTimeUpdatesOn = function manualTimeUpdatesOn() { + this.manualTimeUpdates = true; + + this.on('play', this.trackCurrentTime); + this.on('pause', this.stopTrackingCurrentTime); + }; + + /** + * Turn off the polyfill for `timeupdate` events that was created in + * {@link Tech#manualTimeUpdatesOn} + */ + + + Tech.prototype.manualTimeUpdatesOff = function manualTimeUpdatesOff() { + this.manualTimeUpdates = false; + this.stopTrackingCurrentTime(); + this.off('play', this.trackCurrentTime); + this.off('pause', this.stopTrackingCurrentTime); + }; + + /** + * Sets up an interval function to track current time and trigger `timeupdate` every + * 250 milliseconds. + * + * @listens Tech#play + * @triggers Tech#timeupdate + */ + + + Tech.prototype.trackCurrentTime = function trackCurrentTime() { + if (this.currentTimeInterval) { + this.stopTrackingCurrentTime(); + } + this.currentTimeInterval = this.setInterval(function () { + /** + * Triggered at an interval of 250ms to indicated that time is passing in the video. + * + * @event Tech#timeupdate + * @type {EventTarget~Event} + */ + this.trigger({type: 'timeupdate', target: this, manuallyTriggered: true}); + + // 42 = 24 fps // 250 is what Webkit uses // FF uses 15 + }, 250); + }; + + /** + * Stop the interval function created in {@link Tech#trackCurrentTime} so that the + * `timeupdate` event is no longer triggered. + * + * @listens {Tech#pause} + */ + + + Tech.prototype.stopTrackingCurrentTime = function stopTrackingCurrentTime() { + this.clearInterval(this.currentTimeInterval); + + // #1002 - if the video ends right before the next timeupdate would happen, + // the progress bar won't make it all the way to the end + this.trigger({type: 'timeupdate', target: this, manuallyTriggered: true}); + }; + + /** + * Turn off all event polyfills, clear the `Tech`s {@link AudioTrackList}, + * {@link VideoTrackList}, and {@link TextTrackList}, and dispose of this Tech. + * + * @fires Component#dispose + */ + + + Tech.prototype.dispose = function dispose() { + + // clear out all tracks because we can't reuse them between techs + this.clearTracks(NORMAL.names); + + // Turn off any manual progress or timeupdate tracking + if (this.manualProgress) { + this.manualProgressOff(); + } + + if (this.manualTimeUpdates) { + this.manualTimeUpdatesOff(); + } + + _Component.prototype.dispose.call(this); + }; + + /** + * Clear out a single `TrackList` or an array of `TrackLists` given their names. + * + * > Note: Techs without source handlers should call this between sources for `video` + * & `audio` tracks. You don't want to use them between tracks! + * + * @param {string[]|string} types + * TrackList names to clear, valid names are `video`, `audio`, and + * `text`. + */ + + + Tech.prototype.clearTracks = function clearTracks(types) { + var _this3 = this; + + types = [].concat(types); + // clear out all tracks because we can't reuse them between techs + types.forEach(function (type) { + var list = _this3[type + 'Tracks']() || []; + var i = list.length; + + while (i--) { + var track = list[i]; + + if (type === 'text') { + _this3.removeRemoteTextTrack(track); + } + list.removeTrack(track); + } + }); + }; + + /** + * Remove any TextTracks added via addRemoteTextTrack that are + * flagged for automatic garbage collection + */ + + + Tech.prototype.cleanupAutoTextTracks = function cleanupAutoTextTracks() { + var list = this.autoRemoteTextTracks_ || []; + var i = list.length; + + while (i--) { + var track = list[i]; + + this.removeRemoteTextTrack(track); + } + }; + + /** + * Reset the tech, which will removes all sources and reset the internal readyState. + * + * @abstract + */ + + + Tech.prototype.reset = function reset() { + }; + + /** + * Get or set an error on the Tech. + * + * @param {MediaError} [err] + * Error to set on the Tech + * + * @return {MediaError|null} + * The current error object on the tech, or null if there isn't one. + */ + + + Tech.prototype.error = function error(err) { + if (err !== undefined) { + this.error_ = new MediaError(err); + this.trigger('error'); + } + return this.error_; + }; + + /** + * Returns the `TimeRange`s that have been played through for the current source. + * + * > NOTE: This implementation is incomplete. It does not track the played `TimeRange`. + * It only checks whether the source has played at all or not. + * + * @return {TimeRange} + * - A single time range if this video has played + * - An empty set of ranges if not. + */ + + + Tech.prototype.played = function played() { + if (this.hasStarted_) { + return createTimeRanges(0, 0); + } + return createTimeRanges(); + }; + + /** + * Causes a manual time update to occur if {@link Tech#manualTimeUpdatesOn} was + * previously called. + * + * @fires Tech#timeupdate + */ + + + Tech.prototype.setCurrentTime = function setCurrentTime() { + // improve the accuracy of manual timeupdates + if (this.manualTimeUpdates) { + /** + * A manual `timeupdate` event. + * + * @event Tech#timeupdate + * @type {EventTarget~Event} + */ + this.trigger({type: 'timeupdate', target: this, manuallyTriggered: true}); + } + }; + + /** + * Turn on listeners for {@link VideoTrackList}, {@link {AudioTrackList}, and + * {@link TextTrackList} events. + * + * This adds {@link EventTarget~EventListeners} for `addtrack`, and `removetrack`. + * + * @fires Tech#audiotrackchange + * @fires Tech#videotrackchange + * @fires Tech#texttrackchange + */ + + + Tech.prototype.initTrackListeners = function initTrackListeners() { + var _this4 = this; + + /** + * Triggered when tracks are added or removed on the Tech {@link AudioTrackList} + * + * @event Tech#audiotrackchange + * @type {EventTarget~Event} + */ + + /** + * Triggered when tracks are added or removed on the Tech {@link VideoTrackList} + * + * @event Tech#videotrackchange + * @type {EventTarget~Event} + */ + + /** + * Triggered when tracks are added or removed on the Tech {@link TextTrackList} + * + * @event Tech#texttrackchange + * @type {EventTarget~Event} + */ + NORMAL.names.forEach(function (name) { + var props = NORMAL[name]; + var trackListChanges = function trackListChanges() { + _this4.trigger(name + 'trackchange'); + }; + + var tracks = _this4[props.getterName](); + + tracks.addEventListener('removetrack', trackListChanges); + tracks.addEventListener('addtrack', trackListChanges); + + _this4.on('dispose', function () { + tracks.removeEventListener('removetrack', trackListChanges); + tracks.removeEventListener('addtrack', trackListChanges); + }); + }); + }; + + /** + * Emulate TextTracks using vtt.js if necessary + * + * @fires Tech#vttjsloaded + * @fires Tech#vttjserror + */ + + + Tech.prototype.addWebVttScript_ = function addWebVttScript_() { + var _this5 = this; + + if (window_1.WebVTT) { + return; + } + + // Initially, Tech.el_ is a child of a dummy-div wait until the Component system + // signals that the Tech is ready at which point Tech.el_ is part of the DOM + // before inserting the WebVTT script + if (document_1.body.contains(this.el())) { + + // load via require if available and vtt.js script location was not passed in + // as an option. novtt builds will turn the above require call into an empty object + // which will cause this if check to always fail. + if (!this.options_['vtt.js'] && isPlain(browserIndex) && Object.keys(browserIndex).length > 0) { + this.trigger('vttjsloaded'); + return; + } + + // load vtt.js via the script location option or the cdn of no location was + // passed in + var script = document_1.createElement('script'); + + script.src = this.options_['vtt.js'] || 'https://vjs.zencdn.net/vttjs/0.14.1/vtt.min.js'; + script.onload = function () { + /** + * Fired when vtt.js is loaded. + * + * @event Tech#vttjsloaded + * @type {EventTarget~Event} + */ + _this5.trigger('vttjsloaded'); + }; + script.onerror = function () { + /** + * Fired when vtt.js was not loaded due to an error + * + * @event Tech#vttjsloaded + * @type {EventTarget~Event} + */ + _this5.trigger('vttjserror'); + }; + this.on('dispose', function () { + script.onload = null; + script.onerror = null; + }); + // but have not loaded yet and we set it to true before the inject so that + // we don't overwrite the injected window.WebVTT if it loads right away + window_1.WebVTT = true; + this.el().parentNode.appendChild(script); + } else { + this.ready(this.addWebVttScript_); + } + }; + + /** + * Emulate texttracks + * + */ + + + Tech.prototype.emulateTextTracks = function emulateTextTracks() { + var _this6 = this; + + var tracks = this.textTracks(); + var remoteTracks = this.remoteTextTracks(); + var handleAddTrack = function handleAddTrack(e) { + return tracks.addTrack(e.track); + }; + var handleRemoveTrack = function handleRemoveTrack(e) { + return tracks.removeTrack(e.track); + }; + + remoteTracks.on('addtrack', handleAddTrack); + remoteTracks.on('removetrack', handleRemoveTrack); + + this.addWebVttScript_(); + + var updateDisplay = function updateDisplay() { + return _this6.trigger('texttrackchange'); + }; + + var textTracksChanges = function textTracksChanges() { + updateDisplay(); + + for (var i = 0; i < tracks.length; i++) { + var track = tracks[i]; + + track.removeEventListener('cuechange', updateDisplay); + if (track.mode === 'showing') { + track.addEventListener('cuechange', updateDisplay); + } + } + }; + + textTracksChanges(); + tracks.addEventListener('change', textTracksChanges); + tracks.addEventListener('addtrack', textTracksChanges); + tracks.addEventListener('removetrack', textTracksChanges); + + this.on('dispose', function () { + remoteTracks.off('addtrack', handleAddTrack); + remoteTracks.off('removetrack', handleRemoveTrack); + tracks.removeEventListener('change', textTracksChanges); + tracks.removeEventListener('addtrack', textTracksChanges); + tracks.removeEventListener('removetrack', textTracksChanges); + + for (var i = 0; i < tracks.length; i++) { + var track = tracks[i]; + + track.removeEventListener('cuechange', updateDisplay); + } + }); + }; + + /** + * Create and returns a remote {@link TextTrack} object. + * + * @param {string} kind + * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata) + * + * @param {string} [label] + * Label to identify the text track + * + * @param {string} [language] + * Two letter language abbreviation + * + * @return {TextTrack} + * The TextTrack that gets created. + */ + + + Tech.prototype.addTextTrack = function addTextTrack(kind, label, language) { + if (!kind) { + throw new Error('TextTrack kind is required but was not provided'); + } + + return createTrackHelper(this, kind, label, language); + }; + + /** + * Create an emulated TextTrack for use by addRemoteTextTrack + * + * This is intended to be overridden by classes that inherit from + * Tech in order to create native or custom TextTracks. + * + * @param {Object} options + * The object should contain the options to initialize the TextTrack with. + * + * @param {string} [options.kind] + * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata). + * + * @param {string} [options.label]. + * Label to identify the text track + * + * @param {string} [options.language] + * Two letter language abbreviation. + * + * @return {HTMLTrackElement} + * The track element that gets created. + */ + + + Tech.prototype.createRemoteTextTrack = function createRemoteTextTrack(options) { + var track = mergeOptions(options, { + tech: this + }); + + return new REMOTE.remoteTextEl.TrackClass(track); + }; + + /** + * Creates a remote text track object and returns an html track element. + * + * > Note: This can be an emulated {@link HTMLTrackElement} or a native one. + * + * @param {Object} options + * See {@link Tech#createRemoteTextTrack} for more detailed properties. + * + * @param {boolean} [manualCleanup=true] + * - When false: the TextTrack will be automatically removed from the video + * element whenever the source changes + * - When True: The TextTrack will have to be cleaned up manually + * + * @return {HTMLTrackElement} + * An Html Track Element. + * + * @deprecated The default functionality for this function will be equivalent + * to "manualCleanup=false" in the future. The manualCleanup parameter will + * also be removed. + */ + + + Tech.prototype.addRemoteTextTrack = function addRemoteTextTrack() { + var _this7 = this; + + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var manualCleanup = arguments[1]; + + var htmlTrackElement = this.createRemoteTextTrack(options); + + if (manualCleanup !== true && manualCleanup !== false) { + // deprecation warning + log$1.warn('Calling addRemoteTextTrack without explicitly setting the "manualCleanup" parameter to `true` is deprecated and default to `false` in future version of video.js'); + manualCleanup = true; + } + + // store HTMLTrackElement and TextTrack to remote list + this.remoteTextTrackEls().addTrackElement_(htmlTrackElement); + this.remoteTextTracks().addTrack(htmlTrackElement.track); + + if (manualCleanup !== true) { + // create the TextTrackList if it doesn't exist + this.ready(function () { + return _this7.autoRemoteTextTracks_.addTrack(htmlTrackElement.track); + }); + } + + return htmlTrackElement; + }; + + /** + * Remove a remote text track from the remote `TextTrackList`. + * + * @param {TextTrack} track + * `TextTrack` to remove from the `TextTrackList` + */ + + + Tech.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) { + var trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track); + + // remove HTMLTrackElement and TextTrack from remote list + this.remoteTextTrackEls().removeTrackElement_(trackElement); + this.remoteTextTracks().removeTrack(track); + this.autoRemoteTextTracks_.removeTrack(track); + }; + + /** + * Gets available media playback quality metrics as specified by the W3C's Media + * Playback Quality API. + * + * @see [Spec]{@link https://wicg.github.io/media-playback-quality} + * + * @return {Object} + * An object with supported media playback quality metrics + * + * @abstract + */ + + + Tech.prototype.getVideoPlaybackQuality = function getVideoPlaybackQuality() { + return {}; + }; + + /** + * A method to set a poster from a `Tech`. + * + * @abstract + */ + + + Tech.prototype.setPoster = function setPoster() { + }; + + /** + * A method to check for the presence of the 'playsinline' <video> attribute. + * + * @abstract + */ + + + Tech.prototype.playsinline = function playsinline() { + }; + + /** + * A method to set or unset the 'playsinline' <video> attribute. + * + * @abstract + */ + + + Tech.prototype.setPlaysinline = function setPlaysinline() { + }; + + /** + * Attempt to force override of native audio tracks. + * + * @param {Boolean} override - If set to true native audio will be overridden, + * otherwise native audio will potentially be used. + * + * @abstract + */ + + + Tech.prototype.overrideNativeAudioTracks = function overrideNativeAudioTracks() { + }; + + /** + * Attempt to force override of native video tracks. + * + * @param {Boolean} override - If set to true native video will be overridden, + * otherwise native video will potentially be used. + * + * @abstract + */ + + + Tech.prototype.overrideNativeVideoTracks = function overrideNativeVideoTracks() { + }; + + /* + * Check if the tech can support the given mime-type. + * + * The base tech does not support any type, but source handlers might + * overwrite this. + * + * @param {string} type + * The mimetype to check for support + * + * @return {string} + * 'probably', 'maybe', or empty string + * + * @see [Spec]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType} + * + * @abstract + */ + + + Tech.prototype.canPlayType = function canPlayType() { + return ''; + }; + + /** + * Check if the type is supported by this tech. + * + * The base tech does not support any type, but source handlers might + * overwrite this. + * + * @param {string} type + * The media type to check + * @return {string} Returns the native video element's response + */ + + + Tech.canPlayType = function canPlayType() { + return ''; + }; + + /** + * Check if the tech can support the given source + * @param {Object} srcObj + * The source object + * @param {Object} options + * The options passed to the tech + * @return {string} 'probably', 'maybe', or '' (empty string) + */ + + + Tech.canPlaySource = function canPlaySource(srcObj, options) { + return Tech.canPlayType(srcObj.type); + }; + + /* + * Return whether the argument is a Tech or not. + * Can be passed either a Class like `Html5` or a instance like `player.tech_` + * + * @param {Object} component + * The item to check + * + * @return {boolean} + * Whether it is a tech or not + * - True if it is a tech + * - False if it is not + */ + + + Tech.isTech = function isTech(component) { + return component.prototype instanceof Tech || component instanceof Tech || component === Tech; + }; + + /** + * Registers a `Tech` into a shared list for videojs. + * + * @param {string} name + * Name of the `Tech` to register. + * + * @param {Object} tech + * The `Tech` class to register. + */ + + + Tech.registerTech = function registerTech(name, tech) { + if (!Tech.techs_) { + Tech.techs_ = {}; + } + + if (!Tech.isTech(tech)) { + throw new Error('Tech ' + name + ' must be a Tech'); + } + + if (!Tech.canPlayType) { + throw new Error('Techs must have a static canPlayType method on them'); + } + if (!Tech.canPlaySource) { + throw new Error('Techs must have a static canPlaySource method on them'); + } + + name = toTitleCase(name); + + Tech.techs_[name] = tech; + if (name !== 'Tech') { + // camel case the techName for use in techOrder + Tech.defaultTechOrder_.push(name); + } + return tech; + }; + + /** + * Get a `Tech` from the shared list by name. + * + * @param {string} name + * `camelCase` or `TitleCase` name of the Tech to get + * + * @return {Tech|undefined} + * The `Tech` or undefined if there was no tech with the name requested. + */ + + + Tech.getTech = function getTech(name) { + if (!name) { + return; + } + + name = toTitleCase(name); + + if (Tech.techs_ && Tech.techs_[name]) { + return Tech.techs_[name]; + } + + if (window_1 && window_1.videojs && window_1.videojs[name]) { + log$1.warn('The ' + name + ' tech was added to the videojs object when it should be registered using videojs.registerTech(name, tech)'); + return window_1.videojs[name]; + } + }; + + return Tech; + }(Component); + + /** + * Get the {@link VideoTrackList} + * + * @returns {VideoTrackList} + * @method Tech.prototype.videoTracks + */ + + /** + * Get the {@link AudioTrackList} + * + * @returns {AudioTrackList} + * @method Tech.prototype.audioTracks + */ + + /** + * Get the {@link TextTrackList} + * + * @returns {TextTrackList} + * @method Tech.prototype.textTracks + */ + + /** + * Get the remote element {@link TextTrackList} + * + * @returns {TextTrackList} + * @method Tech.prototype.remoteTextTracks + */ + + /** + * Get the remote element {@link HtmlTrackElementList} + * + * @returns {HtmlTrackElementList} + * @method Tech.prototype.remoteTextTrackEls + */ + + ALL.names.forEach(function (name) { + var props = ALL[name]; + + Tech.prototype[props.getterName] = function () { + this[props.privateName] = this[props.privateName] || new props.ListClass(); + return this[props.privateName]; + }; + }); + + /** + * List of associated text tracks + * + * @type {TextTrackList} + * @private + * @property Tech#textTracks_ + */ + + /** + * List of associated audio tracks. + * + * @type {AudioTrackList} + * @private + * @property Tech#audioTracks_ + */ + + /** + * List of associated video tracks. + * + * @type {VideoTrackList} + * @private + * @property Tech#videoTracks_ + */ + + /** + * Boolean indicating whether the `Tech` supports volume control. + * + * @type {boolean} + * @default + */ + Tech.prototype.featuresVolumeControl = true; + + /** + * Boolean indicating whether the `Tech` supports fullscreen resize control. + * Resizing plugins using request fullscreen reloads the plugin + * + * @type {boolean} + * @default + */ + Tech.prototype.featuresFullscreenResize = false; + + /** + * Boolean indicating whether the `Tech` supports changing the speed at which the video + * plays. Examples: + * - Set player to playOld 2x (twice) as fast + * - Set player to playOld 0.5x (half) as fast + * + * @type {boolean} + * @default + */ + Tech.prototype.featuresPlaybackRate = false; + + /** + * Boolean indicating whether the `Tech` supports the `progress` event. This is currently + * not triggered by video-js-swf. This will be used to determine if + * {@link Tech#manualProgressOn} should be called. + * + * @type {boolean} + * @default + */ + Tech.prototype.featuresProgressEvents = false; + + /** + * Boolean indicating whether the `Tech` supports the `sourceset` event. + * + * A tech should set this to `true` and then use {@link Tech#triggerSourceset} + * to trigger a {@link Tech#event:sourceset} at the earliest time after getting + * a new source. + * + * @type {boolean} + * @default + */ + Tech.prototype.featuresSourceset = false; + + /** + * Boolean indicating whether the `Tech` supports the `timeupdate` event. This is currently + * not triggered by video-js-swf. This will be used to determine if + * {@link Tech#manualTimeUpdates} should be called. + * + * @type {boolean} + * @default + */ + Tech.prototype.featuresTimeupdateEvents = false; + + /** + * Boolean indicating whether the `Tech` supports the native `TextTrack`s. + * This will help us integrate with native `TextTrack`s if the browser supports them. + * + * @type {boolean} + * @default + */ + Tech.prototype.featuresNativeTextTracks = false; + + /** + * A functional mixin for techs that want to use the Source Handler pattern. + * Source handlers are scripts for handling specific formats. + * The source handler pattern is used for adaptive formats (HLS, DASH) that + * manually load video data and feed it into a Source Buffer (Media Source Extensions) + * Example: `Tech.withSourceHandlers.call(MyTech);` + * + * @param {Tech} _Tech + * The tech to add source handler functions to. + * + * @mixes Tech~SourceHandlerAdditions + */ + Tech.withSourceHandlers = function (_Tech) { + + /** + * Register a source handler + * + * @param {Function} handler + * The source handler class + * + * @param {number} [index] + * Register it at the following index + */ + _Tech.registerSourceHandler = function (handler, index) { + var handlers = _Tech.sourceHandlers; + + if (!handlers) { + handlers = _Tech.sourceHandlers = []; + } + + if (index === undefined) { + // add to the end of the list + index = handlers.length; + } + + handlers.splice(index, 0, handler); + }; + + /** + * Check if the tech can support the given type. Also checks the + * Techs sourceHandlers. + * + * @param {string} type + * The mimetype to check. + * + * @return {string} + * 'probably', 'maybe', or '' (empty string) + */ + _Tech.canPlayType = function (type) { + var handlers = _Tech.sourceHandlers || []; + var can = void 0; + + for (var i = 0; i < handlers.length; i++) { + can = handlers[i].canPlayType(type); + + if (can) { + return can; + } + } + + return ''; + }; + + /** + * Returns the first source handler that supports the source. + * + * TODO: Answer question: should 'probably' be prioritized over 'maybe' + * + * @param {Tech~SourceObject} source + * The source object + * + * @param {Object} options + * The options passed to the tech + * + * @return {SourceHandler|null} + * The first source handler that supports the source or null if + * no SourceHandler supports the source + */ + _Tech.selectSourceHandler = function (source, options) { + var handlers = _Tech.sourceHandlers || []; + var can = void 0; + + for (var i = 0; i < handlers.length; i++) { + can = handlers[i].canHandleSource(source, options); + + if (can) { + return handlers[i]; + } + } + + return null; + }; + + /** + * Check if the tech can support the given source. + * + * @param {Tech~SourceObject} srcObj + * The source object + * + * @param {Object} options + * The options passed to the tech + * + * @return {string} + * 'probably', 'maybe', or '' (empty string) + */ + _Tech.canPlaySource = function (srcObj, options) { + var sh = _Tech.selectSourceHandler(srcObj, options); + + if (sh) { + return sh.canHandleSource(srcObj, options); + } + + return ''; + }; + + /** + * When using a source handler, prefer its implementation of + * any function normally provided by the tech. + */ + var deferrable = ['seekable', 'seeking', 'duration']; + + /** + * A wrapper around {@link Tech#seekable} that will call a `SourceHandler`s seekable + * function if it exists, with a fallback to the Techs seekable function. + * + * @method _Tech.seekable + */ + + /** + * A wrapper around {@link Tech#duration} that will call a `SourceHandler`s duration + * function if it exists, otherwise it will fallback to the techs duration function. + * + * @method _Tech.duration + */ + + deferrable.forEach(function (fnName) { + var originalFn = this[fnName]; + + if (typeof originalFn !== 'function') { + return; + } + + this[fnName] = function () { + if (this.sourceHandler_ && this.sourceHandler_[fnName]) { + return this.sourceHandler_[fnName].apply(this.sourceHandler_, arguments); + } + return originalFn.apply(this, arguments); + }; + }, _Tech.prototype); + + /** + * Create a function for setting the source using a source object + * and source handlers. + * Should never be called unless a source handler was found. + * + * @param {Tech~SourceObject} source + * A source object with src and type keys + */ + _Tech.prototype.setSource = function (source) { + var sh = _Tech.selectSourceHandler(source, this.options_); + + if (!sh) { + // Fall back to a native source hander when unsupported sources are + // deliberately set + if (_Tech.nativeSourceHandler) { + sh = _Tech.nativeSourceHandler; + } else { + log$1.error('No source handler found for the current source.'); + } + } + + // Dispose any existing source handler + this.disposeSourceHandler(); + this.off('dispose', this.disposeSourceHandler); + + if (sh !== _Tech.nativeSourceHandler) { + this.currentSource_ = source; + } + + this.sourceHandler_ = sh.handleSource(source, this, this.options_); + this.on('dispose', this.disposeSourceHandler); + }; + + /** + * Clean up any existing SourceHandlers and listeners when the Tech is disposed. + * + * @listens Tech#dispose + */ + _Tech.prototype.disposeSourceHandler = function () { + // if we have a source and get another one + // then we are loading something new + // than clear all of our current tracks + if (this.currentSource_) { + this.clearTracks(['audio', 'video']); + this.currentSource_ = null; + } + + // always clean up auto-text tracks + this.cleanupAutoTextTracks(); + + if (this.sourceHandler_) { + + if (this.sourceHandler_.dispose) { + this.sourceHandler_.dispose(); + } + + this.sourceHandler_ = null; + } + }; + }; + + // The base Tech class needs to be registered as a Component. It is the only + // Tech that can be registered as a Component. + Component.registerComponent('Tech', Tech); + Tech.registerTech('Tech', Tech); + + /** + * A list of techs that should be added to techOrder on Players + * + * @private + */ + Tech.defaultTechOrder_ = []; + + var middlewares = {}; + var middlewareInstances = {}; + + var TERMINATOR = {}; + + function use(type, middleware) { + middlewares[type] = middlewares[type] || []; + middlewares[type].push(middleware); + } + + function setSource(player, src, next) { + player.setTimeout(function () { + return setSourceHelper(src, middlewares[src.type], next, player); + }, 1); + } + + function setTech(middleware, tech) { + middleware.forEach(function (mw) { + return mw.setTech && mw.setTech(tech); + }); + } + + /** + * Calls a getter on the tech first, through each middleware + * from right to left to the player. + */ + function get$1(middleware, tech, method) { + return middleware.reduceRight(middlewareIterator(method), tech[method]()); + } + + /** + * Takes the argument given to the player and calls the setter method on each + * middleware from left to right to the tech. + */ + function set$1(middleware, tech, method, arg) { + return tech[method](middleware.reduce(middlewareIterator(method), arg)); + } + + /** + * Takes the argument given to the player and calls the `call` version of the method + * on each middleware from left to right. + * Then, call the passed in method on the tech and return the result unchanged + * back to the player, through middleware, this time from right to left. + */ + function mediate(middleware, tech, method) { + var arg = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + + var callMethod = 'call' + toTitleCase(method); + var middlewareValue = middleware.reduce(middlewareIterator(callMethod), arg); + var terminated = middlewareValue === TERMINATOR; + var returnValue = terminated ? null : tech[method](middlewareValue); + + executeRight(middleware, method, returnValue, terminated); + + return returnValue; + } + + var allowedGetters = { + buffered: 1, + currentTime: 1, + duration: 1, + seekable: 1, + played: 1, + paused: 1 + }; + + var allowedSetters = { + setCurrentTime: 1 + }; + + var allowedMediators = { + play: 1, + pause: 1 + }; + + function middlewareIterator(method) { + return function (value, mw) { + // if the previous middleware terminated, pass along the termination + if (value === TERMINATOR) { + return TERMINATOR; + } + + if (mw[method]) { + return mw[method](value); + } + + return value; + }; + } + + function executeRight(mws, method, value, terminated) { + for (var i = mws.length - 1; i >= 0; i--) { + var mw = mws[i]; + + if (mw[method]) { + mw[method](terminated, value); + } + } + } + + function clearCacheForPlayer(player) { + middlewareInstances[player.id()] = null; + } + + /** + * { + * [playerId]: [[mwFactory, mwInstance], ...] + * } + */ + function getOrCreateFactory(player, mwFactory) { + var mws = middlewareInstances[player.id()]; + var mw = null; + + if (mws === undefined || mws === null) { + mw = mwFactory(player); + middlewareInstances[player.id()] = [[mwFactory, mw]]; + return mw; + } + + for (var i = 0; i < mws.length; i++) { + var _mws$i = mws[i], + mwf = _mws$i[0], + mwi = _mws$i[1]; + + + if (mwf !== mwFactory) { + continue; + } + + mw = mwi; + } + + if (mw === null) { + mw = mwFactory(player); + mws.push([mwFactory, mw]); + } + + return mw; + } + + function setSourceHelper() { + var src = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var middleware = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; + var next = arguments[2]; + var player = arguments[3]; + var acc = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : []; + var lastRun = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + var mwFactory = middleware[0], + mwrest = middleware.slice(1); + + // if mwFactory is a string, then we're at a fork in the road + + if (typeof mwFactory === 'string') { + setSourceHelper(src, middlewares[mwFactory], next, player, acc, lastRun); + + // if we have an mwFactory, call it with the player to get the mw, + // then call the mw's setSource method + } else if (mwFactory) { + var mw = getOrCreateFactory(player, mwFactory); + + mw.setSource(assign({}, src), function (err, _src) { + + // something happened, try the next middleware on the current level + // make sure to use the old src + if (err) { + return setSourceHelper(src, mwrest, next, player, acc, lastRun); + } + + // we've succeeded, now we need to go deeper + acc.push(mw); + + // if it's the same type, continue down the current chain + // otherwise, we want to go down the new chain + setSourceHelper(_src, src.type === _src.type ? mwrest : middlewares[_src.type], next, player, acc, lastRun); + }); + } else if (mwrest.length) { + setSourceHelper(src, mwrest, next, player, acc, lastRun); + } else if (lastRun) { + next(src, acc); + } else { + setSourceHelper(src, middlewares['*'], next, player, acc, true); + } + } + + /** + * Mimetypes + * + * @see http://hul.harvard.edu/ois/////systems/wax/wax-public-help/mimetypes.htm + * @typedef Mimetypes~Kind + * @enum + */ + var MimetypesKind = { + opus: 'video/ogg', + ogv: 'video/ogg', + mp4: 'video/mp4', + mov: 'video/mp4', + m4v: 'video/mp4', + mkv: 'video/x-matroska', + mp3: 'audio/mpeg', + aac: 'audio/aac', + oga: 'audio/ogg', + m3u8: 'application/x-mpegURL' + }; + + /** + * Get the mimetype of a given src url if possible + * + * @param {string} src + * The url to the src + * + * @return {string} + * return the mimetype if it was known or empty string otherwise + */ + var getMimetype = function getMimetype() { + var src = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + + var ext = getFileExtension(src); + var mimetype = MimetypesKind[ext.toLowerCase()]; + + return mimetype || ''; + }; + + /** + * Find the mime type of a given source string if possible. Uses the player + * source cache. + * + * @param {Player} player + * The player object + * + * @param {string} src + * The source string + * + * @return {string} + * The type that was found + */ + var findMimetype = function findMimetype(player, src) { + if (!src) { + return ''; + } + + // 1. check for the type in the `source` cache + if (player.cache_.source.src === src && player.cache_.source.type) { + return player.cache_.source.type; + } + + // 2. see if we have this source in our `currentSources` cache + var matchingSources = player.cache_.sources.filter(function (s) { + return s.src === src; + }); + + if (matchingSources.length) { + return matchingSources[0].type; + } + + // 3. look for the src url in source elements and use the type there + var sources = player.$$('source'); + + for (var i = 0; i < sources.length; i++) { + var s = sources[i]; + + if (s.type && s.src && s.src === src) { + return s.type; + } + } + + // 4. finally fallback to our list of mime types based on src url extension + return getMimetype(src); + }; + + /** + * @module filter-source + */ + + /** + * Filter out single bad source objects or multiple source objects in an + * array. Also flattens nested source object arrays into a 1 dimensional + * array of source objects. + * + * @param {Tech~SourceObject|Tech~SourceObject[]} src + * The src object to filter + * + * @return {Tech~SourceObject[]} + * An array of sourceobjects containing only valid sources + * + * @private + */ + var filterSource = function filterSource(src) { + // traverse array + if (Array.isArray(src)) { + var newsrc = []; + + src.forEach(function (srcobj) { + srcobj = filterSource(srcobj); + + if (Array.isArray(srcobj)) { + newsrc = newsrc.concat(srcobj); + } else if (isObject(srcobj)) { + newsrc.push(srcobj); + } + }); + + src = newsrc; + } else if (typeof src === 'string' && src.trim()) { + // convert string into object + src = [fixSource({src: src})]; + } else if (isObject(src) && typeof src.src === 'string' && src.src && src.src.trim()) { + // src is already valid + src = [fixSource(src)]; + } else { + // invalid source, turn it into an empty array + src = []; + } + + return src; + }; + + /** + * Checks src mimetype, adding it when possible + * + * @param {Tech~SourceObject} src + * The src object to check + * @return {Tech~SourceObject} + * src Object with known type + */ + function fixSource(src) { + var mimetype = getMimetype(src.src); + + if (!src.type && mimetype) { + src.type = mimetype; + } + + return src; + } + + /** + * @file loader.js + */ + + /** + * The `MediaLoader` is the `Component` that decides which playback technology to load + * when a player is initialized. + * + * @extends Component + */ + + var MediaLoader = function (_Component) { + inherits(MediaLoader, _Component); + + /** + * Create an instance of this class. + * + * @param {Player} player + * The `Player` that this class should attach to. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Component~ReadyCallback} [ready] + * The function that is run when this component is ready. + */ + function MediaLoader(player, options, ready) { + classCallCheck(this, MediaLoader); + + // MediaLoader has no element + var options_ = mergeOptions({createEl: false}, options); + + // If there are no sources when the player is initialized, + // load the first supported playback technology. + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options_, ready)); + + if (!options.playerOptions.sources || options.playerOptions.sources.length === 0) { + for (var i = 0, j = options.playerOptions.techOrder; i < j.length; i++) { + var techName = toTitleCase(j[i]); + var tech = Tech.getTech(techName); + + // Support old behavior of techs being registered as components. + // Remove once that deprecated behavior is removed. + if (!techName) { + tech = Component.getComponent(techName); + } + + // Check if the browser supports this technology + if (tech && tech.isSupported()) { + player.loadTech_(techName); + break; + } + } + } else { + // Loop through playback technologies (HTML5, Flash) and check for support. + // Then load the best source. + // A few assumptions here: + // All playback technologies respect preload false. + player.src(options.playerOptions.sources); + } + return _this; + } + + return MediaLoader; + }(Component); + + Component.registerComponent('MediaLoader', MediaLoader); + + /** + * @file clickable-component.js + */ + + /** + * Clickable Component which is clickable or keyboard actionable, + * but is not a native HTML button. + * + * @extends Component + */ + + var ClickableComponent = function (_Component) { + inherits(ClickableComponent, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function ClickableComponent(player, options) { + classCallCheck(this, ClickableComponent); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.emitTapEvents(); + + _this.enable(); + return _this; + } + + /** + * Create the `Component`s DOM element. + * + * @param {string} [tag=div] + * The element's node type. + * + * @param {Object} [props={}] + * An object of properties that should be set on the element. + * + * @param {Object} [attributes={}] + * An object of attributes that should be set on the element. + * + * @return {Element} + * The element that gets created. + */ + + + ClickableComponent.prototype.createEl = function createEl$$1() { + var tag = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div'; + var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + props = assign({ + innerHTML: '<span aria-hidden="true" class="vjs-icon-placeholder"></span>', + className: this.buildCSSClass(), + tabIndex: 0 + }, props); + + if (tag === 'button') { + log$1.error('Creating a ClickableComponent with an HTML element of ' + tag + ' is not supported; use a Button instead.'); + } + + // Add ARIA attributes for clickable element which is not a native HTML button + attributes = assign({ + role: 'button' + }, attributes); + + this.tabIndex_ = props.tabIndex; + + var el = _Component.prototype.createEl.call(this, tag, props, attributes); + + this.createControlTextEl(el); + + return el; + }; + + ClickableComponent.prototype.dispose = function dispose() { + // remove controlTextEl_ on dispose + this.controlTextEl_ = null; + + _Component.prototype.dispose.call(this); + }; + + /** + * Create a control text element on this `Component` + * + * @param {Element} [el] + * Parent element for the control text. + * + * @return {Element} + * The control text element that gets created. + */ + + + ClickableComponent.prototype.createControlTextEl = function createControlTextEl(el) { + this.controlTextEl_ = createEl('span', { + className: 'vjs-control-text' + }, { + // let the screen reader user know that the text of the element may change + 'aria-live': 'polite' + }); + + if (el) { + el.appendChild(this.controlTextEl_); + } + + this.controlText(this.controlText_, el); + + return this.controlTextEl_; + }; + + /** + * Get or set the localize text to use for the controls on the `Component`. + * + * @param {string} [text] + * Control text for element. + * + * @param {Element} [el=this.el()] + * Element to set the title on. + * + * @return {string} + * - The control text when getting + */ + + + ClickableComponent.prototype.controlText = function controlText(text) { + var el = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.el(); + + if (text === undefined) { + return this.controlText_ || 'Need Text'; + } + + var localizedText = this.localize(text); + + this.controlText_ = text; + textContent(this.controlTextEl_, localizedText); + if (!this.nonIconControl) { + // Set title attribute if only an icon is shown + el.setAttribute('title', localizedText); + } + }; + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + ClickableComponent.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-control vjs-button ' + _Component.prototype.buildCSSClass.call(this); + }; + + /** + * Enable this `Component`s element. + */ + + + ClickableComponent.prototype.enable = function enable() { + if (!this.enabled_) { + this.enabled_ = true; + this.removeClass('vjs-disabled'); + this.el_.setAttribute('aria-disabled', 'false'); + if (typeof this.tabIndex_ !== 'undefined') { + this.el_.setAttribute('tabIndex', this.tabIndex_); + } + this.on(['tap', 'click'], this.handleClick); + this.on('focus', this.handleFocus); + this.on('blur', this.handleBlur); + } + }; + + /** + * Disable this `Component`s element. + */ + + + ClickableComponent.prototype.disable = function disable() { + this.enabled_ = false; + this.addClass('vjs-disabled'); + this.el_.setAttribute('aria-disabled', 'true'); + if (typeof this.tabIndex_ !== 'undefined') { + this.el_.removeAttribute('tabIndex'); + } + this.off(['tap', 'click'], this.handleClick); + this.off('focus', this.handleFocus); + this.off('blur', this.handleBlur); + }; + + /** + * This gets called when a `ClickableComponent` gets: + * - Clicked (via the `click` event, listening starts in the constructor) + * - Tapped (via the `tap` event, listening starts in the constructor) + * - The following things happen in order: + * 1. {@link ClickableComponent#handleFocus} is called via a `focus` event on the + * `ClickableComponent`. + * 2. {@link ClickableComponent#handleFocus} adds a listener for `keydown` on using + * {@link ClickableComponent#handleKeyPress}. + * 3. `ClickableComponent` has not had a `blur` event (`blur` means that focus was lost). The user presses + * the space or enter key. + * 4. {@link ClickableComponent#handleKeyPress} calls this function with the `keydown` + * event as a parameter. + * + * @param {EventTarget~Event} event + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + * @abstract + */ + + + ClickableComponent.prototype.handleClick = function handleClick(event) { + }; + + /** + * This gets called when a `ClickableComponent` gains focus via a `focus` event. + * Turns on listening for `keydown` events. When they happen it + * calls `this.handleKeyPress`. + * + * @param {EventTarget~Event} event + * The `focus` event that caused this function to be called. + * + * @listens focus + */ + + + ClickableComponent.prototype.handleFocus = function handleFocus(event) { + on(document_1, 'keydown', bind(this, this.handleKeyPress)); + }; + + /** + * Called when this ClickableComponent has focus and a key gets pressed down. By + * default it will call `this.handleClick` when the key is space or enter. + * + * @param {EventTarget~Event} event + * The `keydown` event that caused this function to be called. + * + * @listens keydown + */ + + + ClickableComponent.prototype.handleKeyPress = function handleKeyPress(event) { + + // Support Space (32) or Enter (13) key operation to fire a click event + if (event.which === 32 || event.which === 13) { + event.preventDefault(); + this.trigger('click'); + } else if (_Component.prototype.handleKeyPress) { + + // Pass keypress handling up for unsupported keys + _Component.prototype.handleKeyPress.call(this, event); + } + }; + + /** + * Called when a `ClickableComponent` loses focus. Turns off the listener for + * `keydown` events. Which Stops `this.handleKeyPress` from getting called. + * + * @param {EventTarget~Event} event + * The `blur` event that caused this function to be called. + * + * @listens blur + */ + + + ClickableComponent.prototype.handleBlur = function handleBlur(event) { + off(document_1, 'keydown', bind(this, this.handleKeyPress)); + }; + + return ClickableComponent; + }(Component); + + Component.registerComponent('ClickableComponent', ClickableComponent); + + /** + * @file poster-image.js + */ + + /** + * A `ClickableComponent` that handles showing the poster image for the player. + * + * @extends ClickableComponent + */ + + var PosterImage = function (_ClickableComponent) { + inherits(PosterImage, _ClickableComponent); + + /** + * Create an instance of this class. + * + * @param {Player} player + * The `Player` that this class should attach to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function PosterImage(player, options) { + classCallCheck(this, PosterImage); + + var _this = possibleConstructorReturn(this, _ClickableComponent.call(this, player, options)); + + _this.update(); + player.on('posterchange', bind(_this, _this.update)); + return _this; + } + + /** + * Clean up and dispose of the `PosterImage`. + */ + + + PosterImage.prototype.dispose = function dispose() { + this.player().off('posterchange', this.update); + _ClickableComponent.prototype.dispose.call(this); + }; + + /** + * Create the `PosterImage`s DOM element. + * + * @return {Element} + * The element that gets created. + */ + + + PosterImage.prototype.createEl = function createEl$$1() { + var el = createEl('div', { + className: 'vjs-poster', + + // Don't want poster to be tabbable. + tabIndex: -1 + }); + + return el; + }; + + /** + * An {@link EventTarget~EventListener} for {@link Player#posterchange} events. + * + * @listens Player#posterchange + * + * @param {EventTarget~Event} [event] + * The `Player#posterchange` event that triggered this function. + */ + + + PosterImage.prototype.update = function update(event) { + var url = this.player().poster(); + + this.setSrc(url); + + // If there's no poster source we should display:none on this component + // so it's not still clickable or right-clickable + if (url) { + this.show(); + } else { + this.hide(); + } + }; + + /** + * Set the source of the `PosterImage` depending on the display method. + * + * @param {string} url + * The URL to the source for the `PosterImage`. + */ + + + PosterImage.prototype.setSrc = function setSrc(url) { + var backgroundImage = ''; + + // Any falsy value should stay as an empty string, otherwise + // this will throw an extra error + if (url) { + backgroundImage = 'url("' + url + '")'; + } + + this.el_.style.backgroundImage = backgroundImage; + }; + + /** + * An {@link EventTarget~EventListener} for clicks on the `PosterImage`. See + * {@link ClickableComponent#handleClick} for instances where this will be triggered. + * + * @listens tap + * @listens click + * @listens keydown + * + * @param {EventTarget~Event} event + + The `click`, `tap` or `keydown` event that caused this function to be called. + */ + + + PosterImage.prototype.handleClick = function handleClick(event) { + // We don't want a click to trigger playback when controls are disabled + if (!this.player_.controls()) { + return; + } + + if (this.player_.paused()) { + this.player_.play(); + } else { + this.player_.pause(); + } + }; + + return PosterImage; + }(ClickableComponent); + + Component.registerComponent('PosterImage', PosterImage); + + /** + * @file text-track-display.js + */ + + var darkGray = '#222'; + var lightGray = '#ccc'; + var fontMap = { + monospace: 'monospace', + sansSerif: 'sans-serif', + serif: 'serif', + monospaceSansSerif: '"Andale Mono", "Lucida Console", monospace', + monospaceSerif: '"Courier New", monospace', + proportionalSansSerif: 'sans-serif', + proportionalSerif: 'serif', + casual: '"Comic Sans MS", Impact, fantasy', + script: '"Monotype Corsiva", cursive', + smallcaps: '"Andale Mono", "Lucida Console", monospace, sans-serif' + }; + + /** + * Construct an rgba color from a given hex color code. + * + * @param {number} color + * Hex number for color, like #f0e. + * + * @param {number} opacity + * Value for opacity, 0.0 - 1.0. + * + * @return {string} + * The rgba color that was created, like 'rgba(255, 0, 0, 0.3)'. + * + * @private + */ + function constructColor(color, opacity) { + return 'rgba(' + + // color looks like "#f0e" + parseInt(color[1] + color[1], 16) + ',' + parseInt(color[2] + color[2], 16) + ',' + parseInt(color[3] + color[3], 16) + ',' + opacity + ')'; + } + + /** + * Try to update the style of a DOM element. Some style changes will throw an error, + * particularly in IE8. Those should be noops. + * + * @param {Element} el + * The DOM element to be styled. + * + * @param {string} style + * The CSS property on the element that should be styled. + * + * @param {string} rule + * The style rule that should be applied to the property. + * + * @private + */ + function tryUpdateStyle(el, style, rule) { + try { + el.style[style] = rule; + } catch (e) { + + // Satisfies linter. + return; + } + } + + /** + * The component for displaying text track cues. + * + * @extends Component + */ + + var TextTrackDisplay = function (_Component) { + inherits(TextTrackDisplay, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Component~ReadyCallback} [ready] + * The function to call when `TextTrackDisplay` is ready. + */ + function TextTrackDisplay(player, options, ready) { + classCallCheck(this, TextTrackDisplay); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options, ready)); + + player.on('loadstart', bind(_this, _this.toggleDisplay)); + player.on('texttrackchange', bind(_this, _this.updateDisplay)); + player.on('loadstart', bind(_this, _this.preselectTrack)); + + // This used to be called during player init, but was causing an error + // if a track should show by default and the display hadn't loaded yet. + // Should probably be moved to an external track loader when we support + // tracks that don't need a display. + player.ready(bind(_this, function () { + if (player.tech_ && player.tech_.featuresNativeTextTracks) { + this.hide(); + return; + } + + player.on('fullscreenchange', bind(this, this.updateDisplay)); + + var tracks = this.options_.playerOptions.tracks || []; + + for (var i = 0; i < tracks.length; i++) { + this.player_.addRemoteTextTrack(tracks[i], true); + } + + this.preselectTrack(); + })); + return _this; + } + + /** + * Preselect a track following this precedence: + * - matches the previously selected {@link TextTrack}'s language and kind + * - matches the previously selected {@link TextTrack}'s language only + * - is the first default captions track + * - is the first default descriptions track + * + * @listens Player#loadstart + */ + + + TextTrackDisplay.prototype.preselectTrack = function preselectTrack() { + var modes = {captions: 1, subtitles: 1}; + var trackList = this.player_.textTracks(); + var userPref = this.player_.cache_.selectedLanguage; + var firstDesc = void 0; + var firstCaptions = void 0; + var preferredTrack = void 0; + + for (var i = 0; i < trackList.length; i++) { + var track = trackList[i]; + + if (userPref && userPref.enabled && userPref.language === track.language) { + // Always choose the track that matches both language and kind + if (track.kind === userPref.kind) { + preferredTrack = track; + // or choose the first track that matches language + } else if (!preferredTrack) { + preferredTrack = track; + } + + // clear everything if offTextTrackMenuItem was clicked + } else if (userPref && !userPref.enabled) { + preferredTrack = null; + firstDesc = null; + firstCaptions = null; + } else if (track.default) { + if (track.kind === 'descriptions' && !firstDesc) { + firstDesc = track; + } else if (track.kind in modes && !firstCaptions) { + firstCaptions = track; + } + } + } + + // The preferredTrack matches the user preference and takes + // precedence over all the other tracks. + // So, display the preferredTrack before the first default track + // and the subtitles/captions track before the descriptions track + if (preferredTrack) { + preferredTrack.mode = 'showing'; + } else if (firstCaptions) { + firstCaptions.mode = 'showing'; + } else if (firstDesc) { + firstDesc.mode = 'showing'; + } + }; + + /** + * Turn display of {@link TextTrack}'s from the current state into the other state. + * There are only two states: + * - 'shown' + * - 'hidden' + * + * @listens Player#loadstart + */ + + + TextTrackDisplay.prototype.toggleDisplay = function toggleDisplay() { + if (this.player_.tech_ && this.player_.tech_.featuresNativeTextTracks) { + this.hide(); + } else { + this.show(); + } + }; + + /** + * Create the {@link Component}'s DOM element. + * + * @return {Element} + * The element that was created. + */ + + + TextTrackDisplay.prototype.createEl = function createEl() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-text-track-display' + }, { + 'aria-live': 'off', + 'aria-atomic': 'true' + }); + }; + + /** + * Clear all displayed {@link TextTrack}s. + */ + + + TextTrackDisplay.prototype.clearDisplay = function clearDisplay() { + if (typeof window_1.WebVTT === 'function') { + window_1.WebVTT.processCues(window_1, [], this.el_); + } + }; + + /** + * Update the displayed TextTrack when a either a {@link Player#texttrackchange} or + * a {@link Player#fullscreenchange} is fired. + * + * @listens Player#texttrackchange + * @listens Player#fullscreenchange + */ + + + TextTrackDisplay.prototype.updateDisplay = function updateDisplay() { + var tracks = this.player_.textTracks(); + + this.clearDisplay(); + + // Track display prioritization model: if multiple tracks are 'showing', + // display the first 'subtitles' or 'captions' track which is 'showing', + // otherwise display the first 'descriptions' track which is 'showing' + + var descriptionsTrack = null; + var captionsSubtitlesTrack = null; + var i = tracks.length; + + while (i--) { + var track = tracks[i]; + + if (track.mode === 'showing') { + if (track.kind === 'descriptions') { + descriptionsTrack = track; + } else { + captionsSubtitlesTrack = track; + } + } + } + + if (captionsSubtitlesTrack) { + if (this.getAttribute('aria-live') !== 'off') { + this.setAttribute('aria-live', 'off'); + } + this.updateForTrack(captionsSubtitlesTrack); + } else if (descriptionsTrack) { + if (this.getAttribute('aria-live') !== 'assertive') { + this.setAttribute('aria-live', 'assertive'); + } + this.updateForTrack(descriptionsTrack); + } + }; + + /** + * Add an {@link TextTrack} to to the {@link Tech}s {@link TextTrackList}. + * + * @param {TextTrack} track + * Text track object to be added to the list. + */ + + + TextTrackDisplay.prototype.updateForTrack = function updateForTrack(track) { + if (typeof window_1.WebVTT !== 'function' || !track.activeCues) { + return; + } + + var cues = []; + + for (var _i = 0; _i < track.activeCues.length; _i++) { + cues.push(track.activeCues[_i]); + } + + window_1.WebVTT.processCues(window_1, cues, this.el_); + + if (!this.player_.textTrackSettings) { + return; + } + + var overrides = this.player_.textTrackSettings.getValues(); + + var i = cues.length; + + while (i--) { + var cue = cues[i]; + + if (!cue) { + continue; + } + + var cueDiv = cue.displayState; + + if (overrides.color) { + cueDiv.firstChild.style.color = overrides.color; + } + if (overrides.textOpacity) { + tryUpdateStyle(cueDiv.firstChild, 'color', constructColor(overrides.color || '#fff', overrides.textOpacity)); + } + if (overrides.backgroundColor) { + cueDiv.firstChild.style.backgroundColor = overrides.backgroundColor; + } + if (overrides.backgroundOpacity) { + tryUpdateStyle(cueDiv.firstChild, 'backgroundColor', constructColor(overrides.backgroundColor || '#000', overrides.backgroundOpacity)); + } + if (overrides.windowColor) { + if (overrides.windowOpacity) { + tryUpdateStyle(cueDiv, 'backgroundColor', constructColor(overrides.windowColor, overrides.windowOpacity)); + } else { + cueDiv.style.backgroundColor = overrides.windowColor; + } + } + if (overrides.edgeStyle) { + if (overrides.edgeStyle === 'dropshadow') { + cueDiv.firstChild.style.textShadow = '2px 2px 3px ' + darkGray + ', 2px 2px 4px ' + darkGray + ', 2px 2px 5px ' + darkGray; + } else if (overrides.edgeStyle === 'raised') { + cueDiv.firstChild.style.textShadow = '1px 1px ' + darkGray + ', 2px 2px ' + darkGray + ', 3px 3px ' + darkGray; + } else if (overrides.edgeStyle === 'depressed') { + cueDiv.firstChild.style.textShadow = '1px 1px ' + lightGray + ', 0 1px ' + lightGray + ', -1px -1px ' + darkGray + ', 0 -1px ' + darkGray; + } else if (overrides.edgeStyle === 'uniform') { + cueDiv.firstChild.style.textShadow = '0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray; + } + } + if (overrides.fontPercent && overrides.fontPercent !== 1) { + var fontSize = window_1.parseFloat(cueDiv.style.fontSize); + + cueDiv.style.fontSize = fontSize * overrides.fontPercent + 'px'; + cueDiv.style.height = 'auto'; + cueDiv.style.top = 'auto'; + cueDiv.style.bottom = '2px'; + } + if (overrides.fontFamily && overrides.fontFamily !== 'default') { + if (overrides.fontFamily === 'small-caps') { + cueDiv.firstChild.style.fontVariant = 'small-caps'; + } else { + cueDiv.firstChild.style.fontFamily = fontMap[overrides.fontFamily]; + } + } + } + }; + + return TextTrackDisplay; + }(Component); + + Component.registerComponent('TextTrackDisplay', TextTrackDisplay); + + /** + * @file loading-spinner.js + */ + + /** + * A loading spinner for use during waiting/loading events. + * + * @extends Component + */ + + var LoadingSpinner = function (_Component) { + inherits(LoadingSpinner, _Component); + + function LoadingSpinner() { + classCallCheck(this, LoadingSpinner); + return possibleConstructorReturn(this, _Component.apply(this, arguments)); + } + + /** + * Create the `LoadingSpinner`s DOM element. + * + * @return {Element} + * The dom element that gets created. + */ + LoadingSpinner.prototype.createEl = function createEl$$1() { + var isAudio = this.player_.isAudio(); + var playerType = this.localize(isAudio ? 'Audio Player' : 'Video Player'); + var controlText = createEl('span', { + className: 'vjs-control-text', + innerHTML: this.localize('{1} is loading.', [playerType]) + }); + + var el = _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-loading-spinner', + dir: 'ltr' + }); + + el.appendChild(controlText); + + return el; + }; + + return LoadingSpinner; + }(Component); + + Component.registerComponent('LoadingSpinner', LoadingSpinner); + + /** + * @file button.js + */ + + /** + * Base class for all buttons. + * + * @extends ClickableComponent + */ + + var Button = function (_ClickableComponent) { + inherits(Button, _ClickableComponent); + + function Button() { + classCallCheck(this, Button); + return possibleConstructorReturn(this, _ClickableComponent.apply(this, arguments)); + } + + /** + * Create the `Button`s DOM element. + * + * @param {string} [tag="button"] + * The element's node type. This argument is IGNORED: no matter what + * is passed, it will always create a `button` element. + * + * @param {Object} [props={}] + * An object of properties that should be set on the element. + * + * @param {Object} [attributes={}] + * An object of attributes that should be set on the element. + * + * @return {Element} + * The element that gets created. + */ + Button.prototype.createEl = function createEl(tag) { + var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + tag = 'button'; + + props = assign({ + innerHTML: '<span aria-hidden="true" class="vjs-icon-placeholder"></span>', + className: this.buildCSSClass() + }, props); + + // Add attributes for button element + attributes = assign({ + + // Necessary since the default button type is "submit" + type: 'button' + }, attributes); + + var el = Component.prototype.createEl.call(this, tag, props, attributes); + + this.createControlTextEl(el); + + return el; + }; + + /** + * Add a child `Component` inside of this `Button`. + * + * @param {string|Component} child + * The name or instance of a child to add. + * + * @param {Object} [options={}] + * The key/value store of options that will get passed to children of + * the child. + * + * @return {Component} + * The `Component` that gets added as a child. When using a string the + * `Component` will get created by this process. + * + * @deprecated since version 5 + */ + + + Button.prototype.addChild = function addChild(child) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var className = this.constructor.name; + + log$1.warn('Adding an actionable (user controllable) child to a Button (' + className + ') is not supported; use a ClickableComponent instead.'); + + // Avoid the error message generated by ClickableComponent's addChild method + return Component.prototype.addChild.call(this, child, options); + }; + + /** + * Enable the `Button` element so that it can be activated or clicked. Use this with + * {@link Button#disable}. + */ + + + Button.prototype.enable = function enable() { + _ClickableComponent.prototype.enable.call(this); + this.el_.removeAttribute('disabled'); + }; + + /** + * Disable the `Button` element so that it cannot be activated or clicked. Use this with + * {@link Button#enable}. + */ + + + Button.prototype.disable = function disable() { + _ClickableComponent.prototype.disable.call(this); + this.el_.setAttribute('disabled', 'disabled'); + }; + + /** + * This gets called when a `Button` has focus and `keydown` is triggered via a key + * press. + * + * @param {EventTarget~Event} event + * The event that caused this function to get called. + * + * @listens keydown + */ + + + Button.prototype.handleKeyPress = function handleKeyPress(event) { + + // Ignore Space (32) or Enter (13) key operation, which is handled by the browser for a button. + if (event.which === 32 || event.which === 13) { + return; + } + + // Pass keypress handling up for unsupported keys + _ClickableComponent.prototype.handleKeyPress.call(this, event); + }; + + return Button; + }(ClickableComponent); + + Component.registerComponent('Button', Button); + + /** + * @file big-playOld-button.js + */ + + /** + * The initial playOld button that shows before the video has played. The hiding of the + * `BigPlayButton` get done via CSS and `Player` states. + * + * @extends Button + */ + + var BigPlayButton = function (_Button) { + inherits(BigPlayButton, _Button); + + function BigPlayButton(player, options) { + classCallCheck(this, BigPlayButton); + + var _this = possibleConstructorReturn(this, _Button.call(this, player, options)); + + _this.mouseused_ = false; + + _this.on('mousedown', _this.handleMouseDown); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. Always returns 'vjs-big-playOld-button'. + */ + + + BigPlayButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-big-playOld-button'; + }; + + /** + * This gets called when a `BigPlayButton` "clicked". See {@link ClickableComponent} + * for more detailed information on what a click can be. + * + * @param {EventTarget~Event} event + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + BigPlayButton.prototype.handleClick = function handleClick(event) { + var playPromise = this.player_.play(); + + // exit early if clicked via the mouse + if (this.mouseused_ && event.clientX && event.clientY) { + return; + } + + var cb = this.player_.getChild('controlBar'); + var playToggle = cb && cb.getChild('playToggle'); + + if (!playToggle) { + this.player_.focus(); + return; + } + + var playFocus = function playFocus() { + return playToggle.focus(); + }; + + if (isPromise(playPromise)) { + playPromise.then(playFocus, function () { + }); + } else { + this.setTimeout(playFocus, 1); + } + }; + + BigPlayButton.prototype.handleKeyPress = function handleKeyPress(event) { + this.mouseused_ = false; + + _Button.prototype.handleKeyPress.call(this, event); + }; + + BigPlayButton.prototype.handleMouseDown = function handleMouseDown(event) { + this.mouseused_ = true; + }; + + return BigPlayButton; + }(Button); + + /** + * The text that should display over the `BigPlayButton`s controls. Added to for localization. + * + * @type {string} + * @private + */ + + + BigPlayButton.prototype.controlText_ = 'Play Video'; + + Component.registerComponent('BigPlayButton', BigPlayButton); + + /** + * @file close-button.js + */ + + /** + * The `CloseButton` is a `{@link Button}` that fires a `close` event when + * it gets clicked. + * + * @extends Button + */ + + var CloseButton = function (_Button) { + inherits(CloseButton, _Button); + + /** + * Creates an instance of the this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function CloseButton(player, options) { + classCallCheck(this, CloseButton); + + var _this = possibleConstructorReturn(this, _Button.call(this, player, options)); + + _this.controlText(options && options.controlText || _this.localize('Close')); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + CloseButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-close-button ' + _Button.prototype.buildCSSClass.call(this); + }; + + /** + * This gets called when a `CloseButton` gets clicked. See + * {@link ClickableComponent#handleClick} for more information on when this will be + * triggered + * + * @param {EventTarget~Event} event + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + * @fires CloseButton#close + */ + + + CloseButton.prototype.handleClick = function handleClick(event) { + + /** + * Triggered when the a `CloseButton` is clicked. + * + * @event CloseButton#close + * @type {EventTarget~Event} + * + * @property {boolean} [bubbles=false] + * set to false so that the close event does not + * bubble up to parents if there is no listener + */ + this.trigger({type: 'close', bubbles: false}); + }; + + return CloseButton; + }(Button); + + Component.registerComponent('CloseButton', CloseButton); + + /** + * @file playOld-toggle.js + */ + + /** + * Button to toggle between playOld and pause. + * + * @extends Button + */ + + var PlayToggle = function (_Button) { + inherits(PlayToggle, _Button); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function PlayToggle(player, options) { + classCallCheck(this, PlayToggle); + + var _this = possibleConstructorReturn(this, _Button.call(this, player, options)); + + _this.on(player, 'play', _this.handlePlay); + _this.on(player, 'pause', _this.handlePause); + _this.on(player, 'ended', _this.handleEnded); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + PlayToggle.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-playOld-control ' + _Button.prototype.buildCSSClass.call(this); + }; + + /** + * This gets called when an `PlayToggle` is "clicked". See + * {@link ClickableComponent} for more detailed information on what a click can be. + * + * @param {EventTarget~Event} [event] + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + PlayToggle.prototype.handleClick = function handleClick(event) { + if (this.player_.paused()) { + this.player_.play(); + } else { + this.player_.pause(); + } + }; + + /** + * This gets called once after the video has ended and the user seeks so that + * we can change the replay button back to a playOld button. + * + * @param {EventTarget~Event} [event] + * The event that caused this function to run. + * + * @listens Player#seeked + */ + + + PlayToggle.prototype.handleSeeked = function handleSeeked(event) { + this.removeClass('vjs-ended'); + + if (this.player_.paused()) { + this.handlePause(event); + } else { + this.handlePlay(event); + } + }; + + /** + * Add the vjs-playing class to the element so it can change appearance. + * + * @param {EventTarget~Event} [event] + * The event that caused this function to run. + * + * @listens Player#play + */ + + + PlayToggle.prototype.handlePlay = function handlePlay(event) { + this.removeClass('vjs-ended'); + this.removeClass('vjs-paused'); + this.addClass('vjs-playing'); + // change the button text to "Pause" + this.controlText('Pause'); + }; + + /** + * Add the vjs-paused class to the element so it can change appearance. + * + * @param {EventTarget~Event} [event] + * The event that caused this function to run. + * + * @listens Player#pause + */ + + + PlayToggle.prototype.handlePause = function handlePause(event) { + this.removeClass('vjs-playing'); + this.addClass('vjs-paused'); + // change the button text to "Play" + this.controlText('Play'); + }; + + /** + * Add the vjs-ended class to the element so it can change appearance + * + * @param {EventTarget~Event} [event] + * The event that caused this function to run. + * + * @listens Player#ended + */ + + + PlayToggle.prototype.handleEnded = function handleEnded(event) { + this.removeClass('vjs-playing'); + this.addClass('vjs-ended'); + // change the button text to "Replay" + this.controlText('Replay'); + + // on the next seek remove the replay button + this.one(this.player_, 'seeked', this.handleSeeked); + }; + + return PlayToggle; + }(Button); + + /** + * The text that should display over the `PlayToggle`s controls. Added for localization. + * + * @type {string} + * @private + */ + + + PlayToggle.prototype.controlText_ = 'Play'; + + Component.registerComponent('PlayToggle', PlayToggle); + + /** + * @file format-time.js + * @module format-time + */ + + /** + * Format seconds as a time string, H:MM:SS or M:SS. Supplying a guide (in seconds) + * will force a number of leading zeros to cover the length of the guide. + * + * @param {number} seconds + * Number of seconds to be turned into a string + * + * @param {number} guide + * Number (in seconds) to model the string after + * + * @return {string} + * Time formatted as H:MM:SS or M:SS + */ + var defaultImplementation = function defaultImplementation(seconds, guide) { + seconds = seconds < 0 ? 0 : seconds; + var s = Math.floor(seconds % 60); + var m = Math.floor(seconds / 60 % 60); + var h = Math.floor(seconds / 3600); + var gm = Math.floor(guide / 60 % 60); + var gh = Math.floor(guide / 3600); + + // handle invalid times + if (isNaN(seconds) || seconds === Infinity) { + // '-' is false for all relational operators (e.g. <, >=) so this setting + // will add the minimum number of fields specified by the guide + h = m = s = '-'; + } + + // Check if we need to show hours + h = h > 0 || gh > 0 ? h + ':' : ''; + + // If hours are showing, we may need to add a leading zero. + // Always show at least one digit of minutes. + m = ((h || gm >= 10) && m < 10 ? '0' + m : m) + ':'; + + // Check if leading zero is need for seconds + s = s < 10 ? '0' + s : s; + + return h + m + s; + }; + + var implementation = defaultImplementation; + + /** + * Replaces the default formatTime implementation with a custom implementation. + * + * @param {Function} customImplementation + * A function which will be used in place of the default formatTime implementation. + * Will receive the current time in seconds and the guide (in seconds) as arguments. + */ + function setFormatTime(customImplementation) { + implementation = customImplementation; + } + + /** + * Resets formatTime to the default implementation. + */ + function resetFormatTime() { + implementation = defaultImplementation; + } + + function formatTime(seconds) { + var guide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : seconds; + + return implementation(seconds, guide); + } + + /** + * @file time-display.js + */ + + /** + * Displays the time left in the video + * + * @extends Component + */ + + var TimeDisplay = function (_Component) { + inherits(TimeDisplay, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function TimeDisplay(player, options) { + classCallCheck(this, TimeDisplay); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.throttledUpdateContent = throttle(bind(_this, _this.updateContent), 25); + _this.on(player, 'timeupdate', _this.throttledUpdateContent); + return _this; + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + TimeDisplay.prototype.createEl = function createEl$$1(plainName) { + var className = this.buildCSSClass(); + var el = _Component.prototype.createEl.call(this, 'div', { + className: className + ' vjs-time-control vjs-control', + innerHTML: '<span class="vjs-control-text">' + this.localize(this.labelText_) + '\xA0</span>' + }); + + this.contentEl_ = createEl('span', { + className: className + '-display' + }, { + // tell screen readers not to automatically read the time as it changes + 'aria-live': 'off' + }); + + this.updateTextNode_(); + el.appendChild(this.contentEl_); + return el; + }; + + TimeDisplay.prototype.dispose = function dispose() { + this.contentEl_ = null; + this.textNode_ = null; + + _Component.prototype.dispose.call(this); + }; + + /** + * Updates the "remaining time" text node with new content using the + * contents of the `formattedTime_` property. + * + * @private + */ + + + TimeDisplay.prototype.updateTextNode_ = function updateTextNode_() { + if (!this.contentEl_) { + return; + } + + while (this.contentEl_.firstChild) { + this.contentEl_.removeChild(this.contentEl_.firstChild); + } + + this.textNode_ = document_1.createTextNode(this.formattedTime_ || this.formatTime_(0)); + this.contentEl_.appendChild(this.textNode_); + }; + + /** + * Generates a formatted time for this component to use in display. + * + * @param {number} time + * A numeric time, in seconds. + * + * @return {string} + * A formatted time + * + * @private + */ + + + TimeDisplay.prototype.formatTime_ = function formatTime_(time) { + return formatTime(time); + }; + + /** + * Updates the time display text node if it has what was passed in changed + * the formatted time. + * + * @param {number} time + * The time to update to + * + * @private + */ + + + TimeDisplay.prototype.updateFormattedTime_ = function updateFormattedTime_(time) { + var formattedTime = this.formatTime_(time); + + if (formattedTime === this.formattedTime_) { + return; + } + + this.formattedTime_ = formattedTime; + this.requestAnimationFrame(this.updateTextNode_); + }; + + /** + * To be filled out in the child class, should update the displayed time + * in accordance with the fact that the current time has changed. + * + * @param {EventTarget~Event} [event] + * The `timeupdate` event that caused this to run. + * + * @listens Player#timeupdate + */ + + + TimeDisplay.prototype.updateContent = function updateContent(event) { + }; + + return TimeDisplay; + }(Component); + + /** + * The text that is added to the `TimeDisplay` for screen reader users. + * + * @type {string} + * @private + */ + + + TimeDisplay.prototype.labelText_ = 'Time'; + + /** + * The text that should display over the `TimeDisplay`s controls. Added to for localization. + * + * @type {string} + * @private + * + * @deprecated in v7; controlText_ is not used in non-active display Components + */ + TimeDisplay.prototype.controlText_ = 'Time'; + + Component.registerComponent('TimeDisplay', TimeDisplay); + + /** + * @file current-time-display.js + */ + + /** + * Displays the current time + * + * @extends Component + */ + + var CurrentTimeDisplay = function (_TimeDisplay) { + inherits(CurrentTimeDisplay, _TimeDisplay); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function CurrentTimeDisplay(player, options) { + classCallCheck(this, CurrentTimeDisplay); + + var _this = possibleConstructorReturn(this, _TimeDisplay.call(this, player, options)); + + _this.on(player, 'ended', _this.handleEnded); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + CurrentTimeDisplay.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-current-time'; + }; + + /** + * Update current time display + * + * @param {EventTarget~Event} [event] + * The `timeupdate` event that caused this function to run. + * + * @listens Player#timeupdate + */ + + + CurrentTimeDisplay.prototype.updateContent = function updateContent(event) { + // Allows for smooth scrubbing, when player can't keep up. + var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime(); + + this.updateFormattedTime_(time); + }; + + /** + * When the player fires ended there should be no time left. Sadly + * this is not always the case, lets make it seem like that is the case + * for users. + * + * @param {EventTarget~Event} [event] + * The `ended` event that caused this to run. + * + * @listens Player#ended + */ + + + CurrentTimeDisplay.prototype.handleEnded = function handleEnded(event) { + if (!this.player_.duration()) { + return; + } + this.updateFormattedTime_(this.player_.duration()); + }; + + return CurrentTimeDisplay; + }(TimeDisplay); + + /** + * The text that is added to the `CurrentTimeDisplay` for screen reader users. + * + * @type {string} + * @private + */ + + + CurrentTimeDisplay.prototype.labelText_ = 'Current Time'; + + /** + * The text that should display over the `CurrentTimeDisplay`s controls. Added to for localization. + * + * @type {string} + * @private + * + * @deprecated in v7; controlText_ is not used in non-active display Components + */ + CurrentTimeDisplay.prototype.controlText_ = 'Current Time'; + + Component.registerComponent('CurrentTimeDisplay', CurrentTimeDisplay); + + /** + * @file duration-display.js + */ + + /** + * Displays the duration + * + * @extends Component + */ + + var DurationDisplay = function (_TimeDisplay) { + inherits(DurationDisplay, _TimeDisplay); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function DurationDisplay(player, options) { + classCallCheck(this, DurationDisplay); + + // we do not want to/need to throttle duration changes, + // as they should always display the changed duration as + // it has changed + var _this = possibleConstructorReturn(this, _TimeDisplay.call(this, player, options)); + + _this.on(player, 'durationchange', _this.updateContent); + + // Also listen for timeupdate (in the parent) and loadedmetadata because removing those + // listeners could have broken dependent applications/libraries. These + // can likely be removed for 7.0. + _this.on(player, 'loadedmetadata', _this.throttledUpdateContent); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + DurationDisplay.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-duration'; + }; + + /** + * Update duration time display. + * + * @param {EventTarget~Event} [event] + * The `durationchange`, `timeupdate`, or `loadedmetadata` event that caused + * this function to be called. + * + * @listens Player#durationchange + * @listens Player#timeupdate + * @listens Player#loadedmetadata + */ + + + DurationDisplay.prototype.updateContent = function updateContent(event) { + var duration = this.player_.duration(); + + if (duration && this.duration_ !== duration) { + this.duration_ = duration; + this.updateFormattedTime_(duration); + } + }; + + return DurationDisplay; + }(TimeDisplay); + + /** + * The text that is added to the `DurationDisplay` for screen reader users. + * + * @type {string} + * @private + */ + + + DurationDisplay.prototype.labelText_ = 'Duration'; + + /** + * The text that should display over the `DurationDisplay`s controls. Added to for localization. + * + * @type {string} + * @private + * + * @deprecated in v7; controlText_ is not used in non-active display Components + */ + DurationDisplay.prototype.controlText_ = 'Duration'; + + Component.registerComponent('DurationDisplay', DurationDisplay); + + /** + * @file time-divider.js + */ + + /** + * The separator between the current time and duration. + * Can be hidden if it's not needed in the design. + * + * @extends Component + */ + + var TimeDivider = function (_Component) { + inherits(TimeDivider, _Component); + + function TimeDivider() { + classCallCheck(this, TimeDivider); + return possibleConstructorReturn(this, _Component.apply(this, arguments)); + } + + /** + * Create the component's DOM element + * + * @return {Element} + * The element that was created. + */ + TimeDivider.prototype.createEl = function createEl() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-time-control vjs-time-divider', + innerHTML: '<div><span>/</span></div>' + }); + }; + + return TimeDivider; + }(Component); + + Component.registerComponent('TimeDivider', TimeDivider); + + /** + * @file remaining-time-display.js + */ + /** + * Displays the time left in the video + * + * @extends Component + */ + + var RemainingTimeDisplay = function (_TimeDisplay) { + inherits(RemainingTimeDisplay, _TimeDisplay); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function RemainingTimeDisplay(player, options) { + classCallCheck(this, RemainingTimeDisplay); + + var _this = possibleConstructorReturn(this, _TimeDisplay.call(this, player, options)); + + _this.on(player, 'durationchange', _this.throttledUpdateContent); + _this.on(player, 'ended', _this.handleEnded); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + RemainingTimeDisplay.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-remaining-time'; + }; + + /** + * The remaining time display prefixes numbers with a "minus" character. + * + * @param {number} time + * A numeric time, in seconds. + * + * @return {string} + * A formatted time + * + * @private + */ + + + RemainingTimeDisplay.prototype.formatTime_ = function formatTime_(time) { + // TODO: The "-" should be decorative, and not announced by a screen reader + return '-' + _TimeDisplay.prototype.formatTime_.call(this, time); + }; + + /** + * Update remaining time display. + * + * @param {EventTarget~Event} [event] + * The `timeupdate` or `durationchange` event that caused this to run. + * + * @listens Player#timeupdate + * @listens Player#durationchange + */ + + + RemainingTimeDisplay.prototype.updateContent = function updateContent(event) { + if (!this.player_.duration()) { + return; + } + + // @deprecated We should only use remainingTimeDisplay + // as of video.js 7 + if (this.player_.remainingTimeDisplay) { + this.updateFormattedTime_(this.player_.remainingTimeDisplay()); + } else { + this.updateFormattedTime_(this.player_.remainingTime()); + } + }; + + /** + * When the player fires ended there should be no time left. Sadly + * this is not always the case, lets make it seem like that is the case + * for users. + * + * @param {EventTarget~Event} [event] + * The `ended` event that caused this to run. + * + * @listens Player#ended + */ + + + RemainingTimeDisplay.prototype.handleEnded = function handleEnded(event) { + if (!this.player_.duration()) { + return; + } + this.updateFormattedTime_(0); + }; + + return RemainingTimeDisplay; + }(TimeDisplay); + + /** + * The text that is added to the `RemainingTimeDisplay` for screen reader users. + * + * @type {string} + * @private + */ + + + RemainingTimeDisplay.prototype.labelText_ = 'Remaining Time'; + + /** + * The text that should display over the `RemainingTimeDisplay`s controls. Added to for localization. + * + * @type {string} + * @private + * + * @deprecated in v7; controlText_ is not used in non-active display Components + */ + RemainingTimeDisplay.prototype.controlText_ = 'Remaining Time'; + + Component.registerComponent('RemainingTimeDisplay', RemainingTimeDisplay); + + /** + * @file live-display.js + */ + + // TODO - Future make it click to snap to live + + /** + * Displays the live indicator when duration is Infinity. + * + * @extends Component + */ + + var LiveDisplay = function (_Component) { + inherits(LiveDisplay, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function LiveDisplay(player, options) { + classCallCheck(this, LiveDisplay); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.updateShowing(); + _this.on(_this.player(), 'durationchange', _this.updateShowing); + return _this; + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + LiveDisplay.prototype.createEl = function createEl$$1() { + var el = _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-live-control vjs-control' + }); + + this.contentEl_ = createEl('div', { + className: 'vjs-live-display', + innerHTML: '<span class="vjs-control-text">' + this.localize('Stream Type') + '\xA0</span>' + this.localize('LIVE') + }, { + 'aria-live': 'off' + }); + + el.appendChild(this.contentEl_); + return el; + }; + + LiveDisplay.prototype.dispose = function dispose() { + this.contentEl_ = null; + + _Component.prototype.dispose.call(this); + }; + + /** + * Check the duration to see if the LiveDisplay should be showing or not. Then show/hide + * it accordingly + * + * @param {EventTarget~Event} [event] + * The {@link Player#durationchange} event that caused this function to run. + * + * @listens Player#durationchange + */ + + + LiveDisplay.prototype.updateShowing = function updateShowing(event) { + if (this.player().duration() === Infinity) { + this.show(); + } else { + this.hide(); + } + }; + + return LiveDisplay; + }(Component); + + Component.registerComponent('LiveDisplay', LiveDisplay); + + /** + * @file slider.js + */ + + /** + * The base functionality for a slider. Can be vertical or horizontal. + * For instance the volume bar or the seek bar on a video is a slider. + * + * @extends Component + */ + + var Slider = function (_Component) { + inherits(Slider, _Component); + + /** + * Create an instance of this class + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function Slider(player, options) { + classCallCheck(this, Slider); + + // Set property names to bar to match with the child Slider class is looking for + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.bar = _this.getChild(_this.options_.barName); + + // Set a horizontal or vertical class on the slider depending on the slider type + _this.vertical(!!_this.options_.vertical); + + _this.enable(); + return _this; + } + + /** + * Are controls are currently enabled for this slider or not. + * + * @return {boolean} + * true if controls are enabled, false otherwise + */ + + + Slider.prototype.enabled = function enabled() { + return this.enabled_; + }; + + /** + * Enable controls for this slider if they are disabled + */ + + + Slider.prototype.enable = function enable() { + if (this.enabled()) { + return; + } + + this.on('mousedown', this.handleMouseDown); + this.on('touchstart', this.handleMouseDown); + this.on('focus', this.handleFocus); + this.on('blur', this.handleBlur); + this.on('click', this.handleClick); + + this.on(this.player_, 'controlsvisible', this.update); + + if (this.playerEvent) { + this.on(this.player_, this.playerEvent, this.update); + } + + this.removeClass('disabled'); + this.setAttribute('tabindex', 0); + + this.enabled_ = true; + }; + + /** + * Disable controls for this slider if they are enabled + */ + + + Slider.prototype.disable = function disable() { + if (!this.enabled()) { + return; + } + var doc = this.bar.el_.ownerDocument; + + this.off('mousedown', this.handleMouseDown); + this.off('touchstart', this.handleMouseDown); + this.off('focus', this.handleFocus); + this.off('blur', this.handleBlur); + this.off('click', this.handleClick); + this.off(this.player_, 'controlsvisible', this.update); + this.off(doc, 'mousemove', this.handleMouseMove); + this.off(doc, 'mouseup', this.handleMouseUp); + this.off(doc, 'touchmove', this.handleMouseMove); + this.off(doc, 'touchend', this.handleMouseUp); + this.removeAttribute('tabindex'); + + this.addClass('disabled'); + + if (this.playerEvent) { + this.off(this.player_, this.playerEvent, this.update); + } + this.enabled_ = false; + }; + + /** + * Create the `Slider`s DOM element. + * + * @param {string} type + * Type of element to create. + * + * @param {Object} [props={}] + * List of properties in Object form. + * + * @param {Object} [attributes={}] + * list of attributes in Object form. + * + * @return {Element} + * The element that gets created. + */ + + + Slider.prototype.createEl = function createEl$$1(type) { + var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + // Add the slider element class to all sub classes + props.className = props.className + ' vjs-slider'; + props = assign({ + tabIndex: 0 + }, props); + + attributes = assign({ + 'role': 'slider', + 'aria-valuenow': 0, + 'aria-valuemin': 0, + 'aria-valuemax': 100, + 'tabIndex': 0 + }, attributes); + + return _Component.prototype.createEl.call(this, type, props, attributes); + }; + + /** + * Handle `mousedown` or `touchstart` events on the `Slider`. + * + * @param {EventTarget~Event} event + * `mousedown` or `touchstart` event that triggered this function + * + * @listens mousedown + * @listens touchstart + * @fires Slider#slideractive + */ + + + Slider.prototype.handleMouseDown = function handleMouseDown(event) { + var doc = this.bar.el_.ownerDocument; + + event.preventDefault(); + blockTextSelection(); + + this.addClass('vjs-sliding'); + /** + * Triggered when the slider is in an active state + * + * @event Slider#slideractive + * @type {EventTarget~Event} + */ + this.trigger('slideractive'); + + this.on(doc, 'mousemove', this.handleMouseMove); + this.on(doc, 'mouseup', this.handleMouseUp); + this.on(doc, 'touchmove', this.handleMouseMove); + this.on(doc, 'touchend', this.handleMouseUp); + + this.handleMouseMove(event); + }; + + /** + * Handle the `mousemove`, `touchmove`, and `mousedown` events on this `Slider`. + * The `mousemove` and `touchmove` events will only only trigger this function during + * `mousedown` and `touchstart`. This is due to {@link Slider#handleMouseDown} and + * {@link Slider#handleMouseUp}. + * + * @param {EventTarget~Event} event + * `mousedown`, `mousemove`, `touchstart`, or `touchmove` event that triggered + * this function + * + * @listens mousemove + * @listens touchmove + */ + + + Slider.prototype.handleMouseMove = function handleMouseMove(event) { + }; + + /** + * Handle `mouseup` or `touchend` events on the `Slider`. + * + * @param {EventTarget~Event} event + * `mouseup` or `touchend` event that triggered this function. + * + * @listens touchend + * @listens mouseup + * @fires Slider#sliderinactive + */ + + + Slider.prototype.handleMouseUp = function handleMouseUp() { + var doc = this.bar.el_.ownerDocument; + + unblockTextSelection(); + + this.removeClass('vjs-sliding'); + /** + * Triggered when the slider is no longer in an active state. + * + * @event Slider#sliderinactive + * @type {EventTarget~Event} + */ + this.trigger('sliderinactive'); + + this.off(doc, 'mousemove', this.handleMouseMove); + this.off(doc, 'mouseup', this.handleMouseUp); + this.off(doc, 'touchmove', this.handleMouseMove); + this.off(doc, 'touchend', this.handleMouseUp); + + this.update(); + }; + + /** + * Update the progress bar of the `Slider`. + * + * @returns {number} + * The percentage of progress the progress bar represents as a + * number from 0 to 1. + */ + + + Slider.prototype.update = function update() { + + // In VolumeBar init we have a setTimeout for update that pops and update + // to the end of the execution stack. The player is destroyed before then + // update will cause an error + if (!this.el_) { + return; + } + + // If scrubbing, we could use a cached value to make the handle keep up + // with the user's mouse. On HTML5 browsers scrubbing is really smooth, but + // some flash players are slow, so we might want to utilize this later. + // var progress = (this.player_.scrubbing()) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration(); + var progress = this.getPercent(); + var bar = this.bar; + + // If there's no bar... + if (!bar) { + return; + } + + // Protect against no duration and other division issues + if (typeof progress !== 'number' || progress !== progress || progress < 0 || progress === Infinity) { + progress = 0; + } + + // Convert to a percentage for setting + var percentage = (progress * 100).toFixed(2) + '%'; + var style = bar.el().style; + + // Set the new bar width or height + if (this.vertical()) { + style.height = percentage; + } else { + style.width = percentage; + } + + return progress; + }; + + /** + * Calculate distance for slider + * + * @param {EventTarget~Event} event + * The event that caused this function to run. + * + * @return {number} + * The current position of the Slider. + * - position.x for vertical `Slider`s + * - position.y for horizontal `Slider`s + */ + + + Slider.prototype.calculateDistance = function calculateDistance(event) { + var position = getPointerPosition(this.el_, event); + + if (this.vertical()) { + return position.y; + } + return position.x; + }; + + /** + * Handle a `focus` event on this `Slider`. + * + * @param {EventTarget~Event} event + * The `focus` event that caused this function to run. + * + * @listens focus + */ + + + Slider.prototype.handleFocus = function handleFocus() { + this.on(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress); + }; + + /** + * Handle a `keydown` event on the `Slider`. Watches for left, rigth, up, and down + * arrow keys. This function will only be called when the slider has focus. See + * {@link Slider#handleFocus} and {@link Slider#handleBlur}. + * + * @param {EventTarget~Event} event + * the `keydown` event that caused this function to run. + * + * @listens keydown + */ + + + Slider.prototype.handleKeyPress = function handleKeyPress(event) { + // Left and Down Arrows + if (event.which === 37 || event.which === 40) { + event.preventDefault(); + this.stepBack(); + + // Up and Right Arrows + } else if (event.which === 38 || event.which === 39) { + event.preventDefault(); + this.stepForward(); + } + }; + + /** + * Handle a `blur` event on this `Slider`. + * + * @param {EventTarget~Event} event + * The `blur` event that caused this function to run. + * + * @listens blur + */ + + Slider.prototype.handleBlur = function handleBlur() { + this.off(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress); + }; + + /** + * Listener for click events on slider, used to prevent clicks + * from bubbling up to parent elements like button menus. + * + * @param {Object} event + * Event that caused this object to run + */ + + + Slider.prototype.handleClick = function handleClick(event) { + event.stopImmediatePropagation(); + event.preventDefault(); + }; + + /** + * Get/set if slider is horizontal for vertical + * + * @param {boolean} [bool] + * - true if slider is vertical, + * - false is horizontal + * + * @return {boolean} + * - true if slider is vertical, and getting + * - false if the slider is horizontal, and getting + */ + + + Slider.prototype.vertical = function vertical(bool) { + if (bool === undefined) { + return this.vertical_ || false; + } + + this.vertical_ = !!bool; + + if (this.vertical_) { + this.addClass('vjs-slider-vertical'); + } else { + this.addClass('vjs-slider-horizontal'); + } + }; + + return Slider; + }(Component); + + Component.registerComponent('Slider', Slider); + + /** + * @file load-progress-bar.js + */ + + /** + * Shows loading progress + * + * @extends Component + */ + + var LoadProgressBar = function (_Component) { + inherits(LoadProgressBar, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function LoadProgressBar(player, options) { + classCallCheck(this, LoadProgressBar); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.partEls_ = []; + _this.on(player, 'progress', _this.update); + return _this; + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + LoadProgressBar.prototype.createEl = function createEl$$1() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-load-progress', + innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Loaded') + '</span>: 0%</span>' + }); + }; + + LoadProgressBar.prototype.dispose = function dispose() { + this.partEls_ = null; + + _Component.prototype.dispose.call(this); + }; + + /** + * Update progress bar + * + * @param {EventTarget~Event} [event] + * The `progress` event that caused this function to run. + * + * @listens Player#progress + */ + + + LoadProgressBar.prototype.update = function update(event) { + var buffered = this.player_.buffered(); + var duration = this.player_.duration(); + var bufferedEnd = this.player_.bufferedEnd(); + var children = this.partEls_; + + // get the percent width of a time compared to the total end + var percentify = function percentify(time, end) { + // no NaN + var percent = time / end || 0; + + return (percent >= 1 ? 1 : percent) * 100 + '%'; + }; + + // update the width of the progress bar + this.el_.style.width = percentify(bufferedEnd, duration); + + // add child elements to represent the individual buffered time ranges + for (var i = 0; i < buffered.length; i++) { + var start = buffered.start(i); + var end = buffered.end(i); + var part = children[i]; + + if (!part) { + part = this.el_.appendChild(createEl()); + children[i] = part; + } + + // set the percent based on the width of the progress bar (bufferedEnd) + part.style.left = percentify(start, bufferedEnd); + part.style.width = percentify(end - start, bufferedEnd); + } + + // remove unused buffered range elements + for (var _i = children.length; _i > buffered.length; _i--) { + this.el_.removeChild(children[_i - 1]); + } + children.length = buffered.length; + }; + + return LoadProgressBar; + }(Component); + + Component.registerComponent('LoadProgressBar', LoadProgressBar); + + /** + * @file time-tooltip.js + */ + + /** + * Time tooltips display a time above the progress bar. + * + * @extends Component + */ + + var TimeTooltip = function (_Component) { + inherits(TimeTooltip, _Component); + + function TimeTooltip() { + classCallCheck(this, TimeTooltip); + return possibleConstructorReturn(this, _Component.apply(this, arguments)); + } + + /** + * Create the time tooltip DOM element + * + * @return {Element} + * The element that was created. + */ + TimeTooltip.prototype.createEl = function createEl$$1() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-time-tooltip' + }); + }; + + /** + * Updates the position of the time tooltip relative to the `SeekBar`. + * + * @param {Object} seekBarRect + * The `ClientRect` for the {@link SeekBar} element. + * + * @param {number} seekBarPoint + * A number from 0 to 1, representing a horizontal reference point + * from the left edge of the {@link SeekBar} + */ + + + TimeTooltip.prototype.update = function update(seekBarRect, seekBarPoint, content) { + var tooltipRect = getBoundingClientRect(this.el_); + var playerRect = getBoundingClientRect(this.player_.el()); + var seekBarPointPx = seekBarRect.width * seekBarPoint; + + // do nothing if either rect isn't available + // for example, if the player isn't in the DOM for testing + if (!playerRect || !tooltipRect) { + return; + } + + // This is the space left of the `seekBarPoint` available within the bounds + // of the player. We calculate any gap between the left edge of the player + // and the left edge of the `SeekBar` and add the number of pixels in the + // `SeekBar` before hitting the `seekBarPoint` + var spaceLeftOfPoint = seekBarRect.left - playerRect.left + seekBarPointPx; + + // This is the space right of the `seekBarPoint` available within the bounds + // of the player. We calculate the number of pixels from the `seekBarPoint` + // to the right edge of the `SeekBar` and add to that any gap between the + // right edge of the `SeekBar` and the player. + var spaceRightOfPoint = seekBarRect.width - seekBarPointPx + (playerRect.right - seekBarRect.right); + + // This is the number of pixels by which the tooltip will need to be pulled + // further to the right to center it over the `seekBarPoint`. + var pullTooltipBy = tooltipRect.width / 2; + + // Adjust the `pullTooltipBy` distance to the left or right depending on + // the results of the space calculations above. + if (spaceLeftOfPoint < pullTooltipBy) { + pullTooltipBy += pullTooltipBy - spaceLeftOfPoint; + } else if (spaceRightOfPoint < pullTooltipBy) { + pullTooltipBy = spaceRightOfPoint; + } + + // Due to the imprecision of decimal/ratio based calculations and varying + // rounding behaviors, there are cases where the spacing adjustment is off + // by a pixel or two. This adds insurance to these calculations. + if (pullTooltipBy < 0) { + pullTooltipBy = 0; + } else if (pullTooltipBy > tooltipRect.width) { + pullTooltipBy = tooltipRect.width; + } + + this.el_.style.right = '-' + pullTooltipBy + 'px'; + textContent(this.el_, content); + }; + + return TimeTooltip; + }(Component); + + Component.registerComponent('TimeTooltip', TimeTooltip); + + /** + * @file playOld-progress-bar.js + */ + + /** + * Used by {@link SeekBar} to display media playback progress as part of the + * {@link ProgressControl}. + * + * @extends Component + */ + + var PlayProgressBar = function (_Component) { + inherits(PlayProgressBar, _Component); + + function PlayProgressBar() { + classCallCheck(this, PlayProgressBar); + return possibleConstructorReturn(this, _Component.apply(this, arguments)); + } + + /** + * Create the the DOM element for this class. + * + * @return {Element} + * The element that was created. + */ + PlayProgressBar.prototype.createEl = function createEl() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-playOld-progress vjs-slider-bar', + innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>' + }); + }; + + /** + * Enqueues updates to its own DOM as well as the DOM of its + * {@link TimeTooltip} child. + * + * @param {Object} seekBarRect + * The `ClientRect` for the {@link SeekBar} element. + * + * @param {number} seekBarPoint + * A number from 0 to 1, representing a horizontal reference point + * from the left edge of the {@link SeekBar} + */ + + + PlayProgressBar.prototype.update = function update(seekBarRect, seekBarPoint) { + var _this2 = this; + + // If there is an existing rAF ID, cancel it so we don't over-queue. + if (this.rafId_) { + this.cancelAnimationFrame(this.rafId_); + } + + this.rafId_ = this.requestAnimationFrame(function () { + var time = _this2.player_.scrubbing() ? _this2.player_.getCache().currentTime : _this2.player_.currentTime(); + + var content = formatTime(time, _this2.player_.duration()); + var timeTooltip = _this2.getChild('timeTooltip'); + + if (timeTooltip) { + timeTooltip.update(seekBarRect, seekBarPoint, content); + } + }); + }; + + return PlayProgressBar; + }(Component); + + /** + * Default options for {@link PlayProgressBar}. + * + * @type {Object} + * @private + */ + + + PlayProgressBar.prototype.options_ = { + children: [] + }; + + // Time tooltips should not be added to a player on mobile devices + if (!IS_IOS && !IS_ANDROID) { + PlayProgressBar.prototype.options_.children.push('timeTooltip'); + } + + Component.registerComponent('PlayProgressBar', PlayProgressBar); + + /** + * @file mouse-time-display.js + */ + + /** + * The {@link MouseTimeDisplay} component tracks mouse movement over the + * {@link ProgressControl}. It displays an indicator and a {@link TimeTooltip} + * indicating the time which is represented by a given point in the + * {@link ProgressControl}. + * + * @extends Component + */ + + var MouseTimeDisplay = function (_Component) { + inherits(MouseTimeDisplay, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The {@link Player} that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function MouseTimeDisplay(player, options) { + classCallCheck(this, MouseTimeDisplay); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.update = throttle(bind(_this, _this.update), 25); + return _this; + } + + /** + * Create the DOM element for this class. + * + * @return {Element} + * The element that was created. + */ + + + MouseTimeDisplay.prototype.createEl = function createEl() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-mouse-display' + }); + }; + + /** + * Enqueues updates to its own DOM as well as the DOM of its + * {@link TimeTooltip} child. + * + * @param {Object} seekBarRect + * The `ClientRect` for the {@link SeekBar} element. + * + * @param {number} seekBarPoint + * A number from 0 to 1, representing a horizontal reference point + * from the left edge of the {@link SeekBar} + */ + + + MouseTimeDisplay.prototype.update = function update(seekBarRect, seekBarPoint) { + var _this2 = this; + + // If there is an existing rAF ID, cancel it so we don't over-queue. + if (this.rafId_) { + this.cancelAnimationFrame(this.rafId_); + } + + this.rafId_ = this.requestAnimationFrame(function () { + var duration = _this2.player_.duration(); + var content = formatTime(seekBarPoint * duration, duration); + + _this2.el_.style.left = seekBarRect.width * seekBarPoint + 'px'; + _this2.getChild('timeTooltip').update(seekBarRect, seekBarPoint, content); + }); + }; + + return MouseTimeDisplay; + }(Component); + + /** + * Default options for `MouseTimeDisplay` + * + * @type {Object} + * @private + */ + + + MouseTimeDisplay.prototype.options_ = { + children: ['timeTooltip'] + }; + + Component.registerComponent('MouseTimeDisplay', MouseTimeDisplay); + + /** + * @file seek-bar.js + */ + + // The number of seconds the `step*` functions move the timeline. + var STEP_SECONDS = 5; + + // The interval at which the bar should update as it progresses. + var UPDATE_REFRESH_INTERVAL = 30; + + /** + * Seek bar and container for the progress bars. Uses {@link PlayProgressBar} + * as its `bar`. + * + * @extends Slider + */ + + var SeekBar = function (_Slider) { + inherits(SeekBar, _Slider); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function SeekBar(player, options) { + classCallCheck(this, SeekBar); + + var _this = possibleConstructorReturn(this, _Slider.call(this, player, options)); + + _this.setEventHandlers_(); + return _this; + } + + /** + * Sets the event handlers + * + * @private + */ + + + SeekBar.prototype.setEventHandlers_ = function setEventHandlers_() { + var _this2 = this; + + this.update = throttle(bind(this, this.update), UPDATE_REFRESH_INTERVAL); + + this.on(this.player_, 'timeupdate', this.update); + this.on(this.player_, 'ended', this.handleEnded); + + // when playing, let's ensure we smoothly update the playOld progress bar + // via an interval + this.updateInterval = null; + + this.on(this.player_, ['playing'], function () { + _this2.clearInterval(_this2.updateInterval); + + _this2.updateInterval = _this2.setInterval(function () { + _this2.requestAnimationFrame(function () { + _this2.update(); + }); + }, UPDATE_REFRESH_INTERVAL); + }); + + this.on(this.player_, ['ended', 'pause', 'waiting'], function () { + _this2.clearInterval(_this2.updateInterval); + }); + + this.on(this.player_, ['timeupdate', 'ended'], this.update); + }; + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + SeekBar.prototype.createEl = function createEl$$1() { + return _Slider.prototype.createEl.call(this, 'div', { + className: 'vjs-progress-holder' + }, { + 'aria-label': this.localize('Progress Bar') + }); + }; + + /** + * This function updates the playOld progress bar and accessibility + * attributes to whatever is passed in. + * + * @param {number} currentTime + * The currentTime value that should be used for accessibility + * + * @param {number} percent + * The percentage as a decimal that the bar should be filled from 0-1. + * + * @private + */ + + + SeekBar.prototype.update_ = function update_(currentTime, percent) { + var duration = this.player_.duration(); + + // machine readable value of progress bar (percentage complete) + this.el_.setAttribute('aria-valuenow', (percent * 100).toFixed(2)); + + // human readable value of progress bar (time complete) + this.el_.setAttribute('aria-valuetext', this.localize('progress bar timing: currentTime={1} duration={2}', [formatTime(currentTime, duration), formatTime(duration, duration)], '{1} of {2}')); + + // Update the `PlayProgressBar`. + this.bar.update(getBoundingClientRect(this.el_), percent); + }; + + /** + * Update the seek bar's UI. + * + * @param {EventTarget~Event} [event] + * The `timeupdate` or `ended` event that caused this to run. + * + * @listens Player#timeupdate + * + * @returns {number} + * The current percent at a number from 0-1 + */ + + + SeekBar.prototype.update = function update(event) { + var percent = _Slider.prototype.update.call(this); + + this.update_(this.getCurrentTime_(), percent); + return percent; + }; + + /** + * Get the value of current time but allows for smooth scrubbing, + * when player can't keep up. + * + * @return {number} + * The current time value to display + * + * @private + */ + + + SeekBar.prototype.getCurrentTime_ = function getCurrentTime_() { + return this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime(); + }; + + /** + * We want the seek bar to be full on ended + * no matter what the actual internal values are. so we force it. + * + * @param {EventTarget~Event} [event] + * The `timeupdate` or `ended` event that caused this to run. + * + * @listens Player#ended + */ + + + SeekBar.prototype.handleEnded = function handleEnded(event) { + this.update_(this.player_.duration(), 1); + }; + + /** + * Get the percentage of media played so far. + * + * @return {number} + * The percentage of media played so far (0 to 1). + */ + + + SeekBar.prototype.getPercent = function getPercent() { + var percent = this.getCurrentTime_() / this.player_.duration(); + + return percent >= 1 ? 1 : percent || 0; + }; + + /** + * Handle mouse down on seek bar + * + * @param {EventTarget~Event} event + * The `mousedown` event that caused this to run. + * + * @listens mousedown + */ + + + SeekBar.prototype.handleMouseDown = function handleMouseDown(event) { + if (!isSingleLeftClick(event)) { + return; + } + + // Stop event propagation to prevent double fire in progress-control.js + event.stopPropagation(); + this.player_.scrubbing(true); + + this.videoWasPlaying = !this.player_.paused(); + this.player_.pause(); + + _Slider.prototype.handleMouseDown.call(this, event); + }; + + /** + * Handle mouse move on seek bar + * + * @param {EventTarget~Event} event + * The `mousemove` event that caused this to run. + * + * @listens mousemove + */ + + + SeekBar.prototype.handleMouseMove = function handleMouseMove(event) { + if (!isSingleLeftClick(event)) { + return; + } + + var newTime = this.calculateDistance(event) * this.player_.duration(); + + // Don't let video end while scrubbing. + if (newTime === this.player_.duration()) { + newTime = newTime - 0.1; + } + + // Set new time (tell player to seek to new time) + this.player_.currentTime(newTime); + }; + + SeekBar.prototype.enable = function enable() { + _Slider.prototype.enable.call(this); + var mouseTimeDisplay = this.getChild('mouseTimeDisplay'); + + if (!mouseTimeDisplay) { + return; + } + + mouseTimeDisplay.show(); + }; + + SeekBar.prototype.disable = function disable() { + _Slider.prototype.disable.call(this); + var mouseTimeDisplay = this.getChild('mouseTimeDisplay'); + + if (!mouseTimeDisplay) { + return; + } + + mouseTimeDisplay.hide(); + }; + + /** + * Handle mouse up on seek bar + * + * @param {EventTarget~Event} event + * The `mouseup` event that caused this to run. + * + * @listens mouseup + */ + + + SeekBar.prototype.handleMouseUp = function handleMouseUp(event) { + _Slider.prototype.handleMouseUp.call(this, event); + + // Stop event propagation to prevent double fire in progress-control.js + if (event) { + event.stopPropagation(); + } + this.player_.scrubbing(false); + + /** + * Trigger timeupdate because we're done seeking and the time has changed. + * This is particularly useful for if the player is paused to time the time displays. + * + * @event Tech#timeupdate + * @type {EventTarget~Event} + */ + this.player_.trigger({type: 'timeupdate', target: this, manuallyTriggered: true}); + if (this.videoWasPlaying) { + silencePromise(this.player_.play()); + } + }; + + /** + * Move more quickly fast forward for keyboard-only users + */ + + + SeekBar.prototype.stepForward = function stepForward() { + this.player_.currentTime(this.player_.currentTime() + STEP_SECONDS); + }; + + /** + * Move more quickly rewind for keyboard-only users + */ + + + SeekBar.prototype.stepBack = function stepBack() { + this.player_.currentTime(this.player_.currentTime() - STEP_SECONDS); + }; + + /** + * Toggles the playback state of the player + * This gets called when enter or space is used on the seekbar + * + * @param {EventTarget~Event} event + * The `keydown` event that caused this function to be called + * + */ + + + SeekBar.prototype.handleAction = function handleAction(event) { + if (this.player_.paused()) { + this.player_.play(); + } else { + this.player_.pause(); + } + }; + + /** + * Called when this SeekBar has focus and a key gets pressed down. By + * default it will call `this.handleAction` when the key is space or enter. + * + * @param {EventTarget~Event} event + * The `keydown` event that caused this function to be called. + * + * @listens keydown + */ + + + SeekBar.prototype.handleKeyPress = function handleKeyPress(event) { + + // Support Space (32) or Enter (13) key operation to fire a click event + if (event.which === 32 || event.which === 13) { + event.preventDefault(); + this.handleAction(event); + } else if (_Slider.prototype.handleKeyPress) { + + // Pass keypress handling up for unsupported keys + _Slider.prototype.handleKeyPress.call(this, event); + } + }; + + return SeekBar; + }(Slider); + + /** + * Default options for the `SeekBar` + * + * @type {Object} + * @private + */ + + + SeekBar.prototype.options_ = { + children: ['loadProgressBar', 'playProgressBar'], + barName: 'playProgressBar' + }; + + // MouseTimeDisplay tooltips should not be added to a player on mobile devices + if (!IS_IOS && !IS_ANDROID) { + SeekBar.prototype.options_.children.splice(1, 0, 'mouseTimeDisplay'); + } + + /** + * Call the update event for this Slider when this event happens on the player. + * + * @type {string} + */ + SeekBar.prototype.playerEvent = 'timeupdate'; + + Component.registerComponent('SeekBar', SeekBar); + + /** + * @file progress-control.js + */ + + /** + * The Progress Control component contains the seek bar, load progress, + * and playOld progress. + * + * @extends Component + */ + + var ProgressControl = function (_Component) { + inherits(ProgressControl, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function ProgressControl(player, options) { + classCallCheck(this, ProgressControl); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.handleMouseMove = throttle(bind(_this, _this.handleMouseMove), 25); + _this.throttledHandleMouseSeek = throttle(bind(_this, _this.handleMouseSeek), 25); + + _this.enable(); + return _this; + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + ProgressControl.prototype.createEl = function createEl$$1() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-progress-control vjs-control' + }); + }; + + /** + * When the mouse moves over the `ProgressControl`, the pointer position + * gets passed down to the `MouseTimeDisplay` component. + * + * @param {EventTarget~Event} event + * The `mousemove` event that caused this function to run. + * + * @listen mousemove + */ + + + ProgressControl.prototype.handleMouseMove = function handleMouseMove(event) { + var seekBar = this.getChild('seekBar'); + + if (seekBar) { + var mouseTimeDisplay = seekBar.getChild('mouseTimeDisplay'); + var seekBarEl = seekBar.el(); + var seekBarRect = getBoundingClientRect(seekBarEl); + var seekBarPoint = getPointerPosition(seekBarEl, event).x; + + // The default skin has a gap on either side of the `SeekBar`. This means + // that it's possible to trigger this behavior outside the boundaries of + // the `SeekBar`. This ensures we stay within it at all times. + if (seekBarPoint > 1) { + seekBarPoint = 1; + } else if (seekBarPoint < 0) { + seekBarPoint = 0; + } + + if (mouseTimeDisplay) { + mouseTimeDisplay.update(seekBarRect, seekBarPoint); + } + } + }; + + /** + * A throttled version of the {@link ProgressControl#handleMouseSeek} listener. + * + * @method ProgressControl#throttledHandleMouseSeek + * @param {EventTarget~Event} event + * The `mousemove` event that caused this function to run. + * + * @listen mousemove + * @listen touchmove + */ + + /** + * Handle `mousemove` or `touchmove` events on the `ProgressControl`. + * + * @param {EventTarget~Event} event + * `mousedown` or `touchstart` event that triggered this function + * + * @listens mousemove + * @listens touchmove + */ + + + ProgressControl.prototype.handleMouseSeek = function handleMouseSeek(event) { + var seekBar = this.getChild('seekBar'); + + if (seekBar) { + seekBar.handleMouseMove(event); + } + }; + + /** + * Are controls are currently enabled for this progress control. + * + * @return {boolean} + * true if controls are enabled, false otherwise + */ + + + ProgressControl.prototype.enabled = function enabled() { + return this.enabled_; + }; + + /** + * Disable all controls on the progress control and its children + */ + + + ProgressControl.prototype.disable = function disable() { + this.children().forEach(function (child) { + return child.disable && child.disable(); + }); + + if (!this.enabled()) { + return; + } + + this.off(['mousedown', 'touchstart'], this.handleMouseDown); + this.off(this.el_, 'mousemove', this.handleMouseMove); + this.handleMouseUp(); + + this.addClass('disabled'); + + this.enabled_ = false; + }; + + /** + * Enable all controls on the progress control and its children + */ + + + ProgressControl.prototype.enable = function enable() { + this.children().forEach(function (child) { + return child.enable && child.enable(); + }); + + if (this.enabled()) { + return; + } + + this.on(['mousedown', 'touchstart'], this.handleMouseDown); + this.on(this.el_, 'mousemove', this.handleMouseMove); + this.removeClass('disabled'); + + this.enabled_ = true; + }; + + /** + * Handle `mousedown` or `touchstart` events on the `ProgressControl`. + * + * @param {EventTarget~Event} event + * `mousedown` or `touchstart` event that triggered this function + * + * @listens mousedown + * @listens touchstart + */ + + + ProgressControl.prototype.handleMouseDown = function handleMouseDown(event) { + var doc = this.el_.ownerDocument; + var seekBar = this.getChild('seekBar'); + + if (seekBar) { + seekBar.handleMouseDown(event); + } + + this.on(doc, 'mousemove', this.throttledHandleMouseSeek); + this.on(doc, 'touchmove', this.throttledHandleMouseSeek); + this.on(doc, 'mouseup', this.handleMouseUp); + this.on(doc, 'touchend', this.handleMouseUp); + }; + + /** + * Handle `mouseup` or `touchend` events on the `ProgressControl`. + * + * @param {EventTarget~Event} event + * `mouseup` or `touchend` event that triggered this function. + * + * @listens touchend + * @listens mouseup + */ + + + ProgressControl.prototype.handleMouseUp = function handleMouseUp(event) { + var doc = this.el_.ownerDocument; + var seekBar = this.getChild('seekBar'); + + if (seekBar) { + seekBar.handleMouseUp(event); + } + + this.off(doc, 'mousemove', this.throttledHandleMouseSeek); + this.off(doc, 'touchmove', this.throttledHandleMouseSeek); + this.off(doc, 'mouseup', this.handleMouseUp); + this.off(doc, 'touchend', this.handleMouseUp); + }; + + return ProgressControl; + }(Component); + + /** + * Default options for `ProgressControl` + * + * @type {Object} + * @private + */ + + + ProgressControl.prototype.options_ = { + children: ['seekBar'] + }; + + Component.registerComponent('ProgressControl', ProgressControl); + + /** + * @file fullscreen-toggle.js + */ + + /** + * Toggle fullscreen video + * + * @extends Button + */ + + var FullscreenToggle = function (_Button) { + inherits(FullscreenToggle, _Button); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function FullscreenToggle(player, options) { + classCallCheck(this, FullscreenToggle); + + var _this = possibleConstructorReturn(this, _Button.call(this, player, options)); + + _this.on(player, 'fullscreenchange', _this.handleFullscreenChange); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + FullscreenToggle.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-fullscreen-control ' + _Button.prototype.buildCSSClass.call(this); + }; + + /** + * Handles fullscreenchange on the player and change control text accordingly. + * + * @param {EventTarget~Event} [event] + * The {@link Player#fullscreenchange} event that caused this function to be + * called. + * + * @listens Player#fullscreenchange + */ + + + FullscreenToggle.prototype.handleFullscreenChange = function handleFullscreenChange(event) { + if (this.player_.isFullscreen()) { + this.controlText('Non-Fullscreen'); + } else { + this.controlText('Fullscreen'); + } + }; + + /** + * This gets called when an `FullscreenToggle` is "clicked". See + * {@link ClickableComponent} for more detailed information on what a click can be. + * + * @param {EventTarget~Event} [event] + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + FullscreenToggle.prototype.handleClick = function handleClick(event) { + if (!this.player_.isFullscreen()) { + this.player_.requestFullscreen(); + } else { + this.player_.exitFullscreen(); + } + }; + + return FullscreenToggle; + }(Button); + + /** + * The text that should display over the `FullscreenToggle`s controls. Added for localization. + * + * @type {string} + * @private + */ + + + FullscreenToggle.prototype.controlText_ = 'Fullscreen'; + + Component.registerComponent('FullscreenToggle', FullscreenToggle); + + /** + * Check if volume control is supported and if it isn't hide the + * `Component` that was passed using the `vjs-hidden` class. + * + * @param {Component} self + * The component that should be hidden if volume is unsupported + * + * @param {Player} player + * A reference to the player + * + * @private + */ + var checkVolumeSupport = function checkVolumeSupport(self, player) { + // hide volume controls when they're not supported by the current tech + if (player.tech_ && !player.tech_.featuresVolumeControl) { + self.addClass('vjs-hidden'); + } + + self.on(player, 'loadstart', function () { + if (!player.tech_.featuresVolumeControl) { + self.addClass('vjs-hidden'); + } else { + self.removeClass('vjs-hidden'); + } + }); + }; + + /** + * @file volume-level.js + */ + + /** + * Shows volume level + * + * @extends Component + */ + + var VolumeLevel = function (_Component) { + inherits(VolumeLevel, _Component); + + function VolumeLevel() { + classCallCheck(this, VolumeLevel); + return possibleConstructorReturn(this, _Component.apply(this, arguments)); + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + VolumeLevel.prototype.createEl = function createEl() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-level', + innerHTML: '<span class="vjs-control-text"></span>' + }); + }; + + return VolumeLevel; + }(Component); + + Component.registerComponent('VolumeLevel', VolumeLevel); + + /** + * @file volume-bar.js + */ + + /** + * The bar that contains the volume level and can be clicked on to adjust the level + * + * @extends Slider + */ + + var VolumeBar = function (_Slider) { + inherits(VolumeBar, _Slider); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function VolumeBar(player, options) { + classCallCheck(this, VolumeBar); + + var _this = possibleConstructorReturn(this, _Slider.call(this, player, options)); + + _this.on('slideractive', _this.updateLastVolume_); + _this.on(player, 'volumechange', _this.updateARIAAttributes); + player.ready(function () { + return _this.updateARIAAttributes(); + }); + return _this; + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + VolumeBar.prototype.createEl = function createEl$$1() { + return _Slider.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-bar vjs-slider-bar' + }, { + 'aria-label': this.localize('Volume Level'), + 'aria-live': 'polite' + }); + }; + + /** + * Handle mouse down on volume bar + * + * @param {EventTarget~Event} event + * The `mousedown` event that caused this to run. + * + * @listens mousedown + */ + + + VolumeBar.prototype.handleMouseDown = function handleMouseDown(event) { + if (!isSingleLeftClick(event)) { + return; + } + + _Slider.prototype.handleMouseDown.call(this, event); + }; + + /** + * Handle movement events on the {@link VolumeMenuButton}. + * + * @param {EventTarget~Event} event + * The event that caused this function to run. + * + * @listens mousemove + */ + + + VolumeBar.prototype.handleMouseMove = function handleMouseMove(event) { + if (!isSingleLeftClick(event)) { + return; + } + + this.checkMuted(); + this.player_.volume(this.calculateDistance(event)); + }; + + /** + * If the player is muted unmute it. + */ + + + VolumeBar.prototype.checkMuted = function checkMuted() { + if (this.player_.muted()) { + this.player_.muted(false); + } + }; + + /** + * Get percent of volume level + * + * @return {number} + * Volume level percent as a decimal number. + */ + + + VolumeBar.prototype.getPercent = function getPercent() { + if (this.player_.muted()) { + return 0; + } + return this.player_.volume(); + }; + + /** + * Increase volume level for keyboard users + */ + + + VolumeBar.prototype.stepForward = function stepForward() { + this.checkMuted(); + this.player_.volume(this.player_.volume() + 0.1); + }; + + /** + * Decrease volume level for keyboard users + */ + + + VolumeBar.prototype.stepBack = function stepBack() { + this.checkMuted(); + this.player_.volume(this.player_.volume() - 0.1); + }; + + /** + * Update ARIA accessibility attributes + * + * @param {EventTarget~Event} [event] + * The `volumechange` event that caused this function to run. + * + * @listens Player#volumechange + */ + + + VolumeBar.prototype.updateARIAAttributes = function updateARIAAttributes(event) { + var ariaValue = this.player_.muted() ? 0 : this.volumeAsPercentage_(); + + this.el_.setAttribute('aria-valuenow', ariaValue); + this.el_.setAttribute('aria-valuetext', ariaValue + '%'); + }; + + /** + * Returns the current value of the player volume as a percentage + * + * @private + */ + + + VolumeBar.prototype.volumeAsPercentage_ = function volumeAsPercentage_() { + return Math.round(this.player_.volume() * 100); + }; + + /** + * When user starts dragging the VolumeBar, store the volume and listen for + * the end of the drag. When the drag ends, if the volume was set to zero, + * set lastVolume to the stored volume. + * + * @listens slideractive + * @private + */ + + + VolumeBar.prototype.updateLastVolume_ = function updateLastVolume_() { + var _this2 = this; + + var volumeBeforeDrag = this.player_.volume(); + + this.one('sliderinactive', function () { + if (_this2.player_.volume() === 0) { + _this2.player_.lastVolume_(volumeBeforeDrag); + } + }); + }; + + return VolumeBar; + }(Slider); + + /** + * Default options for the `VolumeBar` + * + * @type {Object} + * @private + */ + + + VolumeBar.prototype.options_ = { + children: ['volumeLevel'], + barName: 'volumeLevel' + }; + + /** + * Call the update event for this Slider when this event happens on the player. + * + * @type {string} + */ + VolumeBar.prototype.playerEvent = 'volumechange'; + + Component.registerComponent('VolumeBar', VolumeBar); + + /** + * @file volume-control.js + */ + + /** + * The component for controlling the volume level + * + * @extends Component + */ + + var VolumeControl = function (_Component) { + inherits(VolumeControl, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options={}] + * The key/value store of player options. + */ + function VolumeControl(player) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, VolumeControl); + + options.vertical = options.vertical || false; + + // Pass the vertical option down to the VolumeBar if + // the VolumeBar is turned on. + if (typeof options.volumeBar === 'undefined' || isPlain(options.volumeBar)) { + options.volumeBar = options.volumeBar || {}; + options.volumeBar.vertical = options.vertical; + } + + // hide this control if volume support is missing + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + checkVolumeSupport(_this, player); + + _this.throttledHandleMouseMove = throttle(bind(_this, _this.handleMouseMove), 25); + + _this.on('mousedown', _this.handleMouseDown); + _this.on('touchstart', _this.handleMouseDown); + + // while the slider is active (the mouse has been pressed down and + // is dragging) or in focus we do not want to hide the VolumeBar + _this.on(_this.volumeBar, ['focus', 'slideractive'], function () { + _this.volumeBar.addClass('vjs-slider-active'); + _this.addClass('vjs-slider-active'); + _this.trigger('slideractive'); + }); + + _this.on(_this.volumeBar, ['blur', 'sliderinactive'], function () { + _this.volumeBar.removeClass('vjs-slider-active'); + _this.removeClass('vjs-slider-active'); + _this.trigger('sliderinactive'); + }); + return _this; + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + VolumeControl.prototype.createEl = function createEl() { + var orientationClass = 'vjs-volume-horizontal'; + + if (this.options_.vertical) { + orientationClass = 'vjs-volume-vertical'; + } + + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-control vjs-control ' + orientationClass + }); + }; + + /** + * Handle `mousedown` or `touchstart` events on the `VolumeControl`. + * + * @param {EventTarget~Event} event + * `mousedown` or `touchstart` event that triggered this function + * + * @listens mousedown + * @listens touchstart + */ + + + VolumeControl.prototype.handleMouseDown = function handleMouseDown(event) { + var doc = this.el_.ownerDocument; + + this.on(doc, 'mousemove', this.throttledHandleMouseMove); + this.on(doc, 'touchmove', this.throttledHandleMouseMove); + this.on(doc, 'mouseup', this.handleMouseUp); + this.on(doc, 'touchend', this.handleMouseUp); + }; + + /** + * Handle `mouseup` or `touchend` events on the `VolumeControl`. + * + * @param {EventTarget~Event} event + * `mouseup` or `touchend` event that triggered this function. + * + * @listens touchend + * @listens mouseup + */ + + + VolumeControl.prototype.handleMouseUp = function handleMouseUp(event) { + var doc = this.el_.ownerDocument; + + this.off(doc, 'mousemove', this.throttledHandleMouseMove); + this.off(doc, 'touchmove', this.throttledHandleMouseMove); + this.off(doc, 'mouseup', this.handleMouseUp); + this.off(doc, 'touchend', this.handleMouseUp); + }; + + /** + * Handle `mousedown` or `touchstart` events on the `VolumeControl`. + * + * @param {EventTarget~Event} event + * `mousedown` or `touchstart` event that triggered this function + * + * @listens mousedown + * @listens touchstart + */ + + + VolumeControl.prototype.handleMouseMove = function handleMouseMove(event) { + this.volumeBar.handleMouseMove(event); + }; + + return VolumeControl; + }(Component); + + /** + * Default options for the `VolumeControl` + * + * @type {Object} + * @private + */ + + + VolumeControl.prototype.options_ = { + children: ['volumeBar'] + }; + + Component.registerComponent('VolumeControl', VolumeControl); + + /** + * @file mute-toggle.js + */ + + /** + * A button component for muting the audio. + * + * @extends Button + */ + + var MuteToggle = function (_Button) { + inherits(MuteToggle, _Button); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function MuteToggle(player, options) { + classCallCheck(this, MuteToggle); + + // hide this control if volume support is missing + var _this = possibleConstructorReturn(this, _Button.call(this, player, options)); + + checkVolumeSupport(_this, player); + + _this.on(player, ['loadstart', 'volumechange'], _this.update); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + MuteToggle.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-mute-control ' + _Button.prototype.buildCSSClass.call(this); + }; + + /** + * This gets called when an `MuteToggle` is "clicked". See + * {@link ClickableComponent} for more detailed information on what a click can be. + * + * @param {EventTarget~Event} [event] + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + MuteToggle.prototype.handleClick = function handleClick(event) { + var vol = this.player_.volume(); + var lastVolume = this.player_.lastVolume_(); + + if (vol === 0) { + var volumeToSet = lastVolume < 0.1 ? 0.1 : lastVolume; + + this.player_.volume(volumeToSet); + this.player_.muted(false); + } else { + this.player_.muted(this.player_.muted() ? false : true); + } + }; + + /** + * Update the `MuteToggle` button based on the state of `volume` and `muted` + * on the player. + * + * @param {EventTarget~Event} [event] + * The {@link Player#loadstart} event if this function was called + * through an event. + * + * @listens Player#loadstart + * @listens Player#volumechange + */ + + + MuteToggle.prototype.update = function update(event) { + this.updateIcon_(); + this.updateControlText_(); + }; + + /** + * Update the appearance of the `MuteToggle` icon. + * + * Possible states (given `level` variable below): + * - 0: crossed out + * - 1: zero bars of volume + * - 2: one bar of volume + * - 3: two bars of volume + * + * @private + */ + + + MuteToggle.prototype.updateIcon_ = function updateIcon_() { + var vol = this.player_.volume(); + var level = 3; + + if (vol === 0 || this.player_.muted()) { + level = 0; + } else if (vol < 0.33) { + level = 1; + } else if (vol < 0.67) { + level = 2; + } + + // TODO improve muted icon classes + for (var i = 0; i < 4; i++) { + removeClass(this.el_, 'vjs-vol-' + i); + } + addClass(this.el_, 'vjs-vol-' + level); + }; + + /** + * If `muted` has changed on the player, update the control text + * (`title` attribute on `vjs-mute-control` element and content of + * `vjs-control-text` element). + * + * @private + */ + + + MuteToggle.prototype.updateControlText_ = function updateControlText_() { + var soundOff = this.player_.muted() || this.player_.volume() === 0; + var text = soundOff ? 'Unmute' : 'Mute'; + + if (this.controlText() !== text) { + this.controlText(text); + } + }; + + return MuteToggle; + }(Button); + + /** + * The text that should display over the `MuteToggle`s controls. Added for localization. + * + * @type {string} + * @private + */ + + + MuteToggle.prototype.controlText_ = 'Mute'; + + Component.registerComponent('MuteToggle', MuteToggle); + + /** + * @file volume-control.js + */ + + /** + * A Component to contain the MuteToggle and VolumeControl so that + * they can work together. + * + * @extends Component + */ + + var VolumePanel = function (_Component) { + inherits(VolumePanel, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options={}] + * The key/value store of player options. + */ + function VolumePanel(player) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, VolumePanel); + + if (typeof options.inline !== 'undefined') { + options.inline = options.inline; + } else { + options.inline = true; + } + + // pass the inline option down to the VolumeControl as vertical if + // the VolumeControl is on. + if (typeof options.volumeControl === 'undefined' || isPlain(options.volumeControl)) { + options.volumeControl = options.volumeControl || {}; + options.volumeControl.vertical = !options.inline; + } + + // hide this control if volume support is missing + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + checkVolumeSupport(_this, player); + + // while the slider is active (the mouse has been pressed down and + // is dragging) we do not want to hide the VolumeBar + _this.on(_this.volumeControl, ['slideractive'], _this.sliderActive_); + + _this.on(_this.volumeControl, ['sliderinactive'], _this.sliderInactive_); + return _this; + } + + /** + * Add vjs-slider-active class to the VolumePanel + * + * @listens VolumeControl#slideractive + * @private + */ + + + VolumePanel.prototype.sliderActive_ = function sliderActive_() { + this.addClass('vjs-slider-active'); + }; + + /** + * Removes vjs-slider-active class to the VolumePanel + * + * @listens VolumeControl#sliderinactive + * @private + */ + + + VolumePanel.prototype.sliderInactive_ = function sliderInactive_() { + this.removeClass('vjs-slider-active'); + }; + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + VolumePanel.prototype.createEl = function createEl() { + var orientationClass = 'vjs-volume-panel-horizontal'; + + if (!this.options_.inline) { + orientationClass = 'vjs-volume-panel-vertical'; + } + + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-volume-panel vjs-control ' + orientationClass + }); + }; + + return VolumePanel; + }(Component); + + /** + * Default options for the `VolumeControl` + * + * @type {Object} + * @private + */ + + + VolumePanel.prototype.options_ = { + children: ['muteToggle', 'volumeControl'] + }; + + Component.registerComponent('VolumePanel', VolumePanel); + + /** + * @file menu.js + */ + + /** + * The Menu component is used to build popup menus, including subtitle and + * captions selection menus. + * + * @extends Component + */ + + var Menu = function (_Component) { + inherits(Menu, _Component); + + /** + * Create an instance of this class. + * + * @param {Player} player + * the player that this component should attach to + * + * @param {Object} [options] + * Object of option names and values + * + */ + function Menu(player, options) { + classCallCheck(this, Menu); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + if (options) { + _this.menuButton_ = options.menuButton; + } + + _this.focusedChild_ = -1; + + _this.on('keydown', _this.handleKeyPress); + return _this; + } + + /** + * Add a {@link MenuItem} to the menu. + * + * @param {Object|string} component + * The name or instance of the `MenuItem` to add. + * + */ + + + Menu.prototype.addItem = function addItem(component) { + this.addChild(component); + component.on('click', bind(this, function (event) { + // Unpress the associated MenuButton, and move focus back to it + if (this.menuButton_) { + this.menuButton_.unpressButton(); + + // don't focus menu button if item is a caption settings item + // because focus will move elsewhere + if (component.name() !== 'CaptionSettingsMenuItem') { + this.menuButton_.focus(); + } + } + })); + }; + + /** + * Create the `Menu`s DOM element. + * + * @return {Element} + * the element that was created + */ + + + Menu.prototype.createEl = function createEl$$1() { + var contentElType = this.options_.contentElType || 'ul'; + + this.contentEl_ = createEl(contentElType, { + className: 'vjs-menu-content' + }); + + this.contentEl_.setAttribute('role', 'menu'); + + var el = _Component.prototype.createEl.call(this, 'div', { + append: this.contentEl_, + className: 'vjs-menu' + }); + + el.appendChild(this.contentEl_); + + // Prevent clicks from bubbling up. Needed for Menu Buttons, + // where a click on the parent is significant + on(el, 'click', function (event) { + event.preventDefault(); + event.stopImmediatePropagation(); + }); + + return el; + }; + + Menu.prototype.dispose = function dispose() { + this.contentEl_ = null; + + _Component.prototype.dispose.call(this); + }; + + /** + * Handle a `keydown` event on this menu. This listener is added in the constructor. + * + * @param {EventTarget~Event} event + * A `keydown` event that happened on the menu. + * + * @listens keydown + */ + + + Menu.prototype.handleKeyPress = function handleKeyPress(event) { + // Left and Down Arrows + if (event.which === 37 || event.which === 40) { + event.preventDefault(); + this.stepForward(); + + // Up and Right Arrows + } else if (event.which === 38 || event.which === 39) { + event.preventDefault(); + this.stepBack(); + } + }; + + /** + * Move to next (lower) menu item for keyboard users. + */ + + + Menu.prototype.stepForward = function stepForward() { + var stepChild = 0; + + if (this.focusedChild_ !== undefined) { + stepChild = this.focusedChild_ + 1; + } + this.focus(stepChild); + }; + + /** + * Move to previous (higher) menu item for keyboard users. + */ + + + Menu.prototype.stepBack = function stepBack() { + var stepChild = 0; + + if (this.focusedChild_ !== undefined) { + stepChild = this.focusedChild_ - 1; + } + this.focus(stepChild); + }; + + /** + * Set focus on a {@link MenuItem} in the `Menu`. + * + * @param {Object|string} [item=0] + * Index of child item set focus on. + */ + + + Menu.prototype.focus = function focus() { + var item = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + + var children = this.children().slice(); + var haveTitle = children.length && children[0].className && /vjs-menu-title/.test(children[0].className); + + if (haveTitle) { + children.shift(); + } + + if (children.length > 0) { + if (item < 0) { + item = 0; + } else if (item >= children.length) { + item = children.length - 1; + } + + this.focusedChild_ = item; + + children[item].el_.focus(); + } + }; + + return Menu; + }(Component); + + Component.registerComponent('Menu', Menu); + + /** + * @file menu-button.js + */ + + /** + * A `MenuButton` class for any popup {@link Menu}. + * + * @extends Component + */ + + var MenuButton = function (_Component) { + inherits(MenuButton, _Component); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options={}] + * The key/value store of player options. + */ + function MenuButton(player) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, MenuButton); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options)); + + _this.menuButton_ = new Button(player, options); + + _this.menuButton_.controlText(_this.controlText_); + _this.menuButton_.el_.setAttribute('aria-haspopup', 'true'); + + // Add buildCSSClass values to the button, not the wrapper + var buttonClass = Button.prototype.buildCSSClass(); + + _this.menuButton_.el_.className = _this.buildCSSClass() + ' ' + buttonClass; + _this.menuButton_.removeClass('vjs-control'); + + _this.addChild(_this.menuButton_); + + _this.update(); + + _this.enabled_ = true; + + _this.on(_this.menuButton_, 'tap', _this.handleClick); + _this.on(_this.menuButton_, 'click', _this.handleClick); + _this.on(_this.menuButton_, 'focus', _this.handleFocus); + _this.on(_this.menuButton_, 'blur', _this.handleBlur); + + _this.on('keydown', _this.handleSubmenuKeyPress); + return _this; + } + + /** + * Update the menu based on the current state of its items. + */ + + + MenuButton.prototype.update = function update() { + var menu = this.createMenu(); + + if (this.menu) { + this.menu.dispose(); + this.removeChild(this.menu); + } + + this.menu = menu; + this.addChild(menu); + + /** + * Track the state of the menu button + * + * @type {Boolean} + * @private + */ + this.buttonPressed_ = false; + this.menuButton_.el_.setAttribute('aria-expanded', 'false'); + + if (this.items && this.items.length <= this.hideThreshold_) { + this.hide(); + } else { + this.show(); + } + }; + + /** + * Create the menu and add all items to it. + * + * @return {Menu} + * The constructed menu + */ + + + MenuButton.prototype.createMenu = function createMenu() { + var menu = new Menu(this.player_, {menuButton: this}); + + /** + * Hide the menu if the number of items is less than or equal to this threshold. This defaults + * to 0 and whenever we add items which can be hidden to the menu we'll increment it. We list + * it here because every time we run `createMenu` we need to reset the value. + * + * @protected + * @type {Number} + */ + this.hideThreshold_ = 0; + + // Add a title list item to the top + if (this.options_.title) { + var title = createEl('li', { + className: 'vjs-menu-title', + innerHTML: toTitleCase(this.options_.title), + tabIndex: -1 + }); + + this.hideThreshold_ += 1; + + menu.children_.unshift(title); + prependTo(title, menu.contentEl()); + } + + this.items = this.createItems(); + + if (this.items) { + // Add menu items to the menu + for (var i = 0; i < this.items.length; i++) { + menu.addItem(this.items[i]); + } + } + + return menu; + }; + + /** + * Create the list of menu items. Specific to each subclass. + * + * @abstract + */ + + + MenuButton.prototype.createItems = function createItems() { + }; + + /** + * Create the `MenuButtons`s DOM element. + * + * @return {Element} + * The element that gets created. + */ + + + MenuButton.prototype.createEl = function createEl$$1() { + return _Component.prototype.createEl.call(this, 'div', { + className: this.buildWrapperCSSClass() + }, {}); + }; + + /** + * Allow sub components to stack CSS class names for the wrapper element + * + * @return {string} + * The constructed wrapper DOM `className` + */ + + + MenuButton.prototype.buildWrapperCSSClass = function buildWrapperCSSClass() { + var menuButtonClass = 'vjs-menu-button'; + + // If the inline option is passed, we want to use different styles altogether. + if (this.options_.inline === true) { + menuButtonClass += '-inline'; + } else { + menuButtonClass += '-popup'; + } + + // TODO: Fix the CSS so that this isn't necessary + var buttonClass = Button.prototype.buildCSSClass(); + + return 'vjs-menu-button ' + menuButtonClass + ' ' + buttonClass + ' ' + _Component.prototype.buildCSSClass.call(this); + }; + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + MenuButton.prototype.buildCSSClass = function buildCSSClass() { + var menuButtonClass = 'vjs-menu-button'; + + // If the inline option is passed, we want to use different styles altogether. + if (this.options_.inline === true) { + menuButtonClass += '-inline'; + } else { + menuButtonClass += '-popup'; + } + + return 'vjs-menu-button ' + menuButtonClass + ' ' + _Component.prototype.buildCSSClass.call(this); + }; + + /** + * Get or set the localized control text that will be used for accessibility. + * + * > NOTE: This will come from the internal `menuButton_` element. + * + * @param {string} [text] + * Control text for element. + * + * @param {Element} [el=this.menuButton_.el()] + * Element to set the title on. + * + * @return {string} + * - The control text when getting + */ + + + MenuButton.prototype.controlText = function controlText(text) { + var el = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.menuButton_.el(); + + return this.menuButton_.controlText(text, el); + }; + + /** + * Handle a click on a `MenuButton`. + * See {@link ClickableComponent#handleClick} for instances where this is called. + * + * @param {EventTarget~Event} event + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + MenuButton.prototype.handleClick = function handleClick(event) { + // When you click the button it adds focus, which will show the menu. + // So we'll remove focus when the mouse leaves the button. Focus is needed + // for tab navigation. + + this.one(this.menu.contentEl(), 'mouseleave', bind(this, function (e) { + this.unpressButton(); + this.el_.blur(); + })); + if (this.buttonPressed_) { + this.unpressButton(); + } else { + this.pressButton(); + } + }; + + /** + * Set the focus to the actual button, not to this element + */ + + + MenuButton.prototype.focus = function focus() { + this.menuButton_.focus(); + }; + + /** + * Remove the focus from the actual button, not this element + */ + + + MenuButton.prototype.blur = function blur() { + this.menuButton_.blur(); + }; + + /** + * This gets called when a `MenuButton` gains focus via a `focus` event. + * Turns on listening for `keydown` events. When they happen it + * calls `this.handleKeyPress`. + * + * @param {EventTarget~Event} event + * The `focus` event that caused this function to be called. + * + * @listens focus + */ + + + MenuButton.prototype.handleFocus = function handleFocus() { + on(document_1, 'keydown', bind(this, this.handleKeyPress)); + }; + + /** + * Called when a `MenuButton` loses focus. Turns off the listener for + * `keydown` events. Which Stops `this.handleKeyPress` from getting called. + * + * @param {EventTarget~Event} event + * The `blur` event that caused this function to be called. + * + * @listens blur + */ + + + MenuButton.prototype.handleBlur = function handleBlur() { + off(document_1, 'keydown', bind(this, this.handleKeyPress)); + }; + + /** + * Handle tab, escape, down arrow, and up arrow keys for `MenuButton`. See + * {@link ClickableComponent#handleKeyPress} for instances where this is called. + * + * @param {EventTarget~Event} event + * The `keydown` event that caused this function to be called. + * + * @listens keydown + */ + + + MenuButton.prototype.handleKeyPress = function handleKeyPress(event) { + + // Escape (27) key or Tab (9) key unpress the 'button' + if (event.which === 27 || event.which === 9) { + if (this.buttonPressed_) { + this.unpressButton(); + } + // Don't preventDefault for Tab key - we still want to lose focus + if (event.which !== 9) { + event.preventDefault(); + // Set focus back to the menu button's button + this.menuButton_.el_.focus(); + } + // Up (38) key or Down (40) key press the 'button' + } else if (event.which === 38 || event.which === 40) { + if (!this.buttonPressed_) { + this.pressButton(); + event.preventDefault(); + } + } + }; + + /** + * Handle a `keydown` event on a sub-menu. The listener for this is added in + * the constructor. + * + * @param {EventTarget~Event} event + * Key press event + * + * @listens keydown + */ + + + MenuButton.prototype.handleSubmenuKeyPress = function handleSubmenuKeyPress(event) { + + // Escape (27) key or Tab (9) key unpress the 'button' + if (event.which === 27 || event.which === 9) { + if (this.buttonPressed_) { + this.unpressButton(); + } + // Don't preventDefault for Tab key - we still want to lose focus + if (event.which !== 9) { + event.preventDefault(); + // Set focus back to the menu button's button + this.menuButton_.el_.focus(); + } + } + }; + + /** + * Put the current `MenuButton` into a pressed state. + */ + + + MenuButton.prototype.pressButton = function pressButton() { + if (this.enabled_) { + this.buttonPressed_ = true; + this.menu.lockShowing(); + this.menuButton_.el_.setAttribute('aria-expanded', 'true'); + + // set the focus into the submenu, except on iOS where it is resulting in + // undesired scrolling behavior when the player is in an iframe + if (IS_IOS && isInFrame()) { + // Return early so that the menu isn't focused + return; + } + + this.menu.focus(); + } + }; + + /** + * Take the current `MenuButton` out of a pressed state. + */ + + + MenuButton.prototype.unpressButton = function unpressButton() { + if (this.enabled_) { + this.buttonPressed_ = false; + this.menu.unlockShowing(); + this.menuButton_.el_.setAttribute('aria-expanded', 'false'); + } + }; + + /** + * Disable the `MenuButton`. Don't allow it to be clicked. + */ + + + MenuButton.prototype.disable = function disable() { + this.unpressButton(); + + this.enabled_ = false; + this.addClass('vjs-disabled'); + + this.menuButton_.disable(); + }; + + /** + * Enable the `MenuButton`. Allow it to be clicked. + */ + + + MenuButton.prototype.enable = function enable() { + this.enabled_ = true; + this.removeClass('vjs-disabled'); + + this.menuButton_.enable(); + }; + + return MenuButton; + }(Component); + + Component.registerComponent('MenuButton', MenuButton); + + /** + * @file track-button.js + */ + + /** + * The base class for buttons that toggle specific track types (e.g. subtitles). + * + * @extends MenuButton + */ + + var TrackButton = function (_MenuButton) { + inherits(TrackButton, _MenuButton); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function TrackButton(player, options) { + classCallCheck(this, TrackButton); + + var tracks = options.tracks; + + var _this = possibleConstructorReturn(this, _MenuButton.call(this, player, options)); + + if (_this.items.length <= 1) { + _this.hide(); + } + + if (!tracks) { + return possibleConstructorReturn(_this); + } + + var updateHandler = bind(_this, _this.update); + + tracks.addEventListener('removetrack', updateHandler); + tracks.addEventListener('addtrack', updateHandler); + _this.player_.on('ready', updateHandler); + + _this.player_.on('dispose', function () { + tracks.removeEventListener('removetrack', updateHandler); + tracks.removeEventListener('addtrack', updateHandler); + }); + return _this; + } + + return TrackButton; + }(MenuButton); + + Component.registerComponent('TrackButton', TrackButton); + + /** + * @file menu-item.js + */ + + /** + * The component for a menu item. `<li>` + * + * @extends ClickableComponent + */ + + var MenuItem = function (_ClickableComponent) { + inherits(MenuItem, _ClickableComponent); + + /** + * Creates an instance of the this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options={}] + * The key/value store of player options. + * + */ + function MenuItem(player, options) { + classCallCheck(this, MenuItem); + + var _this = possibleConstructorReturn(this, _ClickableComponent.call(this, player, options)); + + _this.selectable = options.selectable; + _this.isSelected_ = options.selected || false; + + _this.selected(_this.isSelected_); + + if (_this.selectable) { + // TODO: May need to be either menuitemcheckbox or menuitemradio, + // and may need logical grouping of menu items. + _this.el_.setAttribute('role', 'menuitemcheckbox'); + } else { + _this.el_.setAttribute('role', 'menuitem'); + } + return _this; + } + + /** + * Create the `MenuItem's DOM element + * + * @param {string} [type=li] + * Element's node type, not actually used, always set to `li`. + * + * @param {Object} [props={}] + * An object of properties that should be set on the element + * + * @param {Object} [attrs={}] + * An object of attributes that should be set on the element + * + * @return {Element} + * The element that gets created. + */ + + + MenuItem.prototype.createEl = function createEl(type, props, attrs) { + // The control is textual, not just an icon + this.nonIconControl = true; + + return _ClickableComponent.prototype.createEl.call(this, 'li', assign({ + className: 'vjs-menu-item', + innerHTML: '<span class="vjs-menu-item-text">' + this.localize(this.options_.label) + '</span>', + tabIndex: -1 + }, props), attrs); + }; + + /** + * Any click on a `MenuItem` puts int into the selected state. + * See {@link ClickableComponent#handleClick} for instances where this is called. + * + * @param {EventTarget~Event} event + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + MenuItem.prototype.handleClick = function handleClick(event) { + this.selected(true); + }; + + /** + * Set the state for this menu item as selected or not. + * + * @param {boolean} selected + * if the menu item is selected or not + */ + + + MenuItem.prototype.selected = function selected(_selected) { + if (this.selectable) { + if (_selected) { + this.addClass('vjs-selected'); + this.el_.setAttribute('aria-checked', 'true'); + // aria-checked isn't fully supported by browsers/screen readers, + // so indicate selected state to screen reader in the control text. + this.controlText(', selected'); + this.isSelected_ = true; + } else { + this.removeClass('vjs-selected'); + this.el_.setAttribute('aria-checked', 'false'); + // Indicate un-selected state to screen reader + this.controlText(''); + this.isSelected_ = false; + } + } + }; + + return MenuItem; + }(ClickableComponent); + + Component.registerComponent('MenuItem', MenuItem); + + /** + * @file text-track-menu-item.js + */ + + /** + * The specific menu item type for selecting a language within a text track kind + * + * @extends MenuItem + */ + + var TextTrackMenuItem = function (_MenuItem) { + inherits(TextTrackMenuItem, _MenuItem); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function TextTrackMenuItem(player, options) { + classCallCheck(this, TextTrackMenuItem); + + var track = options.track; + var tracks = player.textTracks(); + + // Modify options for parent MenuItem class's init. + options.label = track.label || track.language || 'Unknown'; + options.selected = track.mode === 'showing'; + + var _this = possibleConstructorReturn(this, _MenuItem.call(this, player, options)); + + _this.track = track; + var changeHandler = function changeHandler() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + _this.handleTracksChange.apply(_this, args); + }; + var selectedLanguageChangeHandler = function selectedLanguageChangeHandler() { + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + _this.handleSelectedLanguageChange.apply(_this, args); + }; + + player.on(['loadstart', 'texttrackchange'], changeHandler); + tracks.addEventListener('change', changeHandler); + tracks.addEventListener('selectedlanguagechange', selectedLanguageChangeHandler); + _this.on('dispose', function () { + player.off(['loadstart', 'texttrackchange'], changeHandler); + tracks.removeEventListener('change', changeHandler); + tracks.removeEventListener('selectedlanguagechange', selectedLanguageChangeHandler); + }); + + // iOS7 doesn't dispatch change events to TextTrackLists when an + // associated track's mode changes. Without something like + // Object.observe() (also not present on iOS7), it's not + // possible to detect changes to the mode attribute and polyfill + // the change event. As a poor substitute, we manually dispatch + // change events whenever the controls modify the mode. + if (tracks.onchange === undefined) { + var event = void 0; + + _this.on(['tap', 'click'], function () { + if (_typeof(window_1.Event) !== 'object') { + // Android 2.3 throws an Illegal Constructor error for window.Event + try { + event = new window_1.Event('change'); + } catch (err) { + // continue regardless of error + } + } + + if (!event) { + event = document_1.createEvent('Event'); + event.initEvent('change', true, true); + } + + tracks.dispatchEvent(event); + }); + } + + // set the default state based on current tracks + _this.handleTracksChange(); + return _this; + } + + /** + * This gets called when an `TextTrackMenuItem` is "clicked". See + * {@link ClickableComponent} for more detailed information on what a click can be. + * + * @param {EventTarget~Event} event + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + TextTrackMenuItem.prototype.handleClick = function handleClick(event) { + var kind = this.track.kind; + var kinds = this.track.kinds; + var tracks = this.player_.textTracks(); + + if (!kinds) { + kinds = [kind]; + } + + _MenuItem.prototype.handleClick.call(this, event); + + if (!tracks) { + return; + } + + for (var i = 0; i < tracks.length; i++) { + var track = tracks[i]; + + if (track === this.track && kinds.indexOf(track.kind) > -1) { + if (track.mode !== 'showing') { + track.mode = 'showing'; + } + } else if (track.mode !== 'disabled') { + track.mode = 'disabled'; + } + } + }; + + /** + * Handle text track list change + * + * @param {EventTarget~Event} event + * The `change` event that caused this function to be called. + * + * @listens TextTrackList#change + */ + + + TextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) { + var shouldBeSelected = this.track.mode === 'showing'; + + // Prevent redundant selected() calls because they may cause + // screen readers to read the appended control text unnecessarily + if (shouldBeSelected !== this.isSelected_) { + this.selected(shouldBeSelected); + } + }; + + TextTrackMenuItem.prototype.handleSelectedLanguageChange = function handleSelectedLanguageChange(event) { + if (this.track.mode === 'showing') { + var selectedLanguage = this.player_.cache_.selectedLanguage; + + // Don't replace the kind of track across the same language + if (selectedLanguage && selectedLanguage.enabled && selectedLanguage.language === this.track.language && selectedLanguage.kind !== this.track.kind) { + return; + } + + this.player_.cache_.selectedLanguage = { + enabled: true, + language: this.track.language, + kind: this.track.kind + }; + } + }; + + TextTrackMenuItem.prototype.dispose = function dispose() { + // remove reference to track object on dispose + this.track = null; + + _MenuItem.prototype.dispose.call(this); + }; + + return TextTrackMenuItem; + }(MenuItem); + + Component.registerComponent('TextTrackMenuItem', TextTrackMenuItem); + + /** + * @file off-text-track-menu-item.js + */ + + /** + * A special menu item for turning of a specific type of text track + * + * @extends TextTrackMenuItem + */ + + var OffTextTrackMenuItem = function (_TextTrackMenuItem) { + inherits(OffTextTrackMenuItem, _TextTrackMenuItem); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function OffTextTrackMenuItem(player, options) { + classCallCheck(this, OffTextTrackMenuItem); + + // Create pseudo track info + // Requires options['kind'] + options.track = { + player: player, + kind: options.kind, + kinds: options.kinds, + default: false, + mode: 'disabled' + }; + + if (!options.kinds) { + options.kinds = [options.kind]; + } + + if (options.label) { + options.track.label = options.label; + } else { + options.track.label = options.kinds.join(' and ') + ' off'; + } + + // MenuItem is selectable + options.selectable = true; + + return possibleConstructorReturn(this, _TextTrackMenuItem.call(this, player, options)); + } + + /** + * Handle text track change + * + * @param {EventTarget~Event} event + * The event that caused this function to run + */ + + + OffTextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) { + var tracks = this.player().textTracks(); + var shouldBeSelected = true; + + for (var i = 0, l = tracks.length; i < l; i++) { + var track = tracks[i]; + + if (this.options_.kinds.indexOf(track.kind) > -1 && track.mode === 'showing') { + shouldBeSelected = false; + break; + } + } + + // Prevent redundant selected() calls because they may cause + // screen readers to read the appended control text unnecessarily + if (shouldBeSelected !== this.isSelected_) { + this.selected(shouldBeSelected); + } + }; + + OffTextTrackMenuItem.prototype.handleSelectedLanguageChange = function handleSelectedLanguageChange(event) { + var tracks = this.player().textTracks(); + var allHidden = true; + + for (var i = 0, l = tracks.length; i < l; i++) { + var track = tracks[i]; + + if (['captions', 'descriptions', 'subtitles'].indexOf(track.kind) > -1 && track.mode === 'showing') { + allHidden = false; + break; + } + } + + if (allHidden) { + this.player_.cache_.selectedLanguage = { + enabled: false + }; + } + }; + + return OffTextTrackMenuItem; + }(TextTrackMenuItem); + + Component.registerComponent('OffTextTrackMenuItem', OffTextTrackMenuItem); + + /** + * @file text-track-button.js + */ + + /** + * The base class for buttons that toggle specific text track types (e.g. subtitles) + * + * @extends MenuButton + */ + + var TextTrackButton = function (_TrackButton) { + inherits(TextTrackButton, _TrackButton); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options={}] + * The key/value store of player options. + */ + function TextTrackButton(player) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, TextTrackButton); + + options.tracks = player.textTracks(); + + return possibleConstructorReturn(this, _TrackButton.call(this, player, options)); + } + + /** + * Create a menu item for each text track + * + * @param {TextTrackMenuItem[]} [items=[]] + * Existing array of items to use during creation + * + * @return {TextTrackMenuItem[]} + * Array of menu items that were created + */ + + + TextTrackButton.prototype.createItems = function createItems() { + var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + var TrackMenuItem = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : TextTrackMenuItem; + + + // Label is an override for the [track] off label + // USed to localise captions/subtitles + var label = void 0; + + if (this.label_) { + label = this.label_ + ' off'; + } + // Add an OFF menu item to turn all tracks off + items.push(new OffTextTrackMenuItem(this.player_, { + kinds: this.kinds_, + kind: this.kind_, + label: label + })); + + this.hideThreshold_ += 1; + + var tracks = this.player_.textTracks(); + + if (!Array.isArray(this.kinds_)) { + this.kinds_ = [this.kind_]; + } + + for (var i = 0; i < tracks.length; i++) { + var track = tracks[i]; + + // only add tracks that are of an appropriate kind and have a label + if (this.kinds_.indexOf(track.kind) > -1) { + + var item = new TrackMenuItem(this.player_, { + track: track, + // MenuItem is selectable + selectable: true + }); + + item.addClass('vjs-' + track.kind + '-menu-item'); + items.push(item); + } + } + + return items; + }; + + return TextTrackButton; + }(TrackButton); + + Component.registerComponent('TextTrackButton', TextTrackButton); + + /** + * @file chapters-track-menu-item.js + */ + + /** + * The chapter track menu item + * + * @extends MenuItem + */ + + var ChaptersTrackMenuItem = function (_MenuItem) { + inherits(ChaptersTrackMenuItem, _MenuItem); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function ChaptersTrackMenuItem(player, options) { + classCallCheck(this, ChaptersTrackMenuItem); + + var track = options.track; + var cue = options.cue; + var currentTime = player.currentTime(); + + // Modify options for parent MenuItem class's init. + options.selectable = true; + options.label = cue.text; + options.selected = cue.startTime <= currentTime && currentTime < cue.endTime; + + var _this = possibleConstructorReturn(this, _MenuItem.call(this, player, options)); + + _this.track = track; + _this.cue = cue; + track.addEventListener('cuechange', bind(_this, _this.update)); + return _this; + } + + /** + * This gets called when an `ChaptersTrackMenuItem` is "clicked". See + * {@link ClickableComponent} for more detailed information on what a click can be. + * + * @param {EventTarget~Event} [event] + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + ChaptersTrackMenuItem.prototype.handleClick = function handleClick(event) { + _MenuItem.prototype.handleClick.call(this); + this.player_.currentTime(this.cue.startTime); + this.update(this.cue.startTime); + }; + + /** + * Update chapter menu item + * + * @param {EventTarget~Event} [event] + * The `cuechange` event that caused this function to run. + * + * @listens TextTrack#cuechange + */ + + + ChaptersTrackMenuItem.prototype.update = function update(event) { + var cue = this.cue; + var currentTime = this.player_.currentTime(); + + // vjs.log(currentTime, cue.startTime); + this.selected(cue.startTime <= currentTime && currentTime < cue.endTime); + }; + + return ChaptersTrackMenuItem; + }(MenuItem); + + Component.registerComponent('ChaptersTrackMenuItem', ChaptersTrackMenuItem); + + /** + * @file chapters-button.js + */ + + /** + * The button component for toggling and selecting chapters + * Chapters act much differently than other text tracks + * Cues are navigation vs. other tracks of alternative languages + * + * @extends TextTrackButton + */ + + var ChaptersButton = function (_TextTrackButton) { + inherits(ChaptersButton, _TextTrackButton); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Component~ReadyCallback} [ready] + * The function to call when this function is ready. + */ + function ChaptersButton(player, options, ready) { + classCallCheck(this, ChaptersButton); + return possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready)); + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + ChaptersButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-chapters-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); + }; + + ChaptersButton.prototype.buildWrapperCSSClass = function buildWrapperCSSClass() { + return 'vjs-chapters-button ' + _TextTrackButton.prototype.buildWrapperCSSClass.call(this); + }; + + /** + * Update the menu based on the current state of its items. + * + * @param {EventTarget~Event} [event] + * An event that triggered this function to run. + * + * @listens TextTrackList#addtrack + * @listens TextTrackList#removetrack + * @listens TextTrackList#change + */ + + + ChaptersButton.prototype.update = function update(event) { + if (!this.track_ || event && (event.type === 'addtrack' || event.type === 'removetrack')) { + this.setTrack(this.findChaptersTrack()); + } + _TextTrackButton.prototype.update.call(this); + }; + + /** + * Set the currently selected track for the chapters button. + * + * @param {TextTrack} track + * The new track to select. Nothing will change if this is the currently selected + * track. + */ + + + ChaptersButton.prototype.setTrack = function setTrack(track) { + if (this.track_ === track) { + return; + } + + if (!this.updateHandler_) { + this.updateHandler_ = this.update.bind(this); + } + + // here this.track_ refers to the old track instance + if (this.track_) { + var remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_); + + if (remoteTextTrackEl) { + remoteTextTrackEl.removeEventListener('load', this.updateHandler_); + } + + this.track_ = null; + } + + this.track_ = track; + + // here this.track_ refers to the new track instance + if (this.track_) { + this.track_.mode = 'hidden'; + + var _remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_); + + if (_remoteTextTrackEl) { + _remoteTextTrackEl.addEventListener('load', this.updateHandler_); + } + } + }; + + /** + * Find the track object that is currently in use by this ChaptersButton + * + * @return {TextTrack|undefined} + * The current track or undefined if none was found. + */ + + + ChaptersButton.prototype.findChaptersTrack = function findChaptersTrack() { + var tracks = this.player_.textTracks() || []; + + for (var i = tracks.length - 1; i >= 0; i--) { + // We will always choose the last track as our chaptersTrack + var track = tracks[i]; + + if (track.kind === this.kind_) { + return track; + } + } + }; + + /** + * Get the caption for the ChaptersButton based on the track label. This will also + * use the current tracks localized kind as a fallback if a label does not exist. + * + * @return {string} + * The tracks current label or the localized track kind. + */ + + + ChaptersButton.prototype.getMenuCaption = function getMenuCaption() { + if (this.track_ && this.track_.label) { + return this.track_.label; + } + return this.localize(toTitleCase(this.kind_)); + }; + + /** + * Create menu from chapter track + * + * @return {Menu} + * New menu for the chapter buttons + */ + + + ChaptersButton.prototype.createMenu = function createMenu() { + this.options_.title = this.getMenuCaption(); + return _TextTrackButton.prototype.createMenu.call(this); + }; + + /** + * Create a menu item for each text track + * + * @return {TextTrackMenuItem[]} + * Array of menu items + */ + + + ChaptersButton.prototype.createItems = function createItems() { + var items = []; + + if (!this.track_) { + return items; + } + + var cues = this.track_.cues; + + if (!cues) { + return items; + } + + for (var i = 0, l = cues.length; i < l; i++) { + var cue = cues[i]; + var mi = new ChaptersTrackMenuItem(this.player_, {track: this.track_, cue: cue}); + + items.push(mi); + } + + return items; + }; + + return ChaptersButton; + }(TextTrackButton); + + /** + * `kind` of TextTrack to look for to associate it with this menu. + * + * @type {string} + * @private + */ + + + ChaptersButton.prototype.kind_ = 'chapters'; + + /** + * The text that should display over the `ChaptersButton`s controls. Added for localization. + * + * @type {string} + * @private + */ + ChaptersButton.prototype.controlText_ = 'Chapters'; + + Component.registerComponent('ChaptersButton', ChaptersButton); + + /** + * @file descriptions-button.js + */ + + /** + * The button component for toggling and selecting descriptions + * + * @extends TextTrackButton + */ + + var DescriptionsButton = function (_TextTrackButton) { + inherits(DescriptionsButton, _TextTrackButton); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Component~ReadyCallback} [ready] + * The function to call when this component is ready. + */ + function DescriptionsButton(player, options, ready) { + classCallCheck(this, DescriptionsButton); + + var _this = possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready)); + + var tracks = player.textTracks(); + var changeHandler = bind(_this, _this.handleTracksChange); + + tracks.addEventListener('change', changeHandler); + _this.on('dispose', function () { + tracks.removeEventListener('change', changeHandler); + }); + return _this; + } + + /** + * Handle text track change + * + * @param {EventTarget~Event} event + * The event that caused this function to run + * + * @listens TextTrackList#change + */ + + + DescriptionsButton.prototype.handleTracksChange = function handleTracksChange(event) { + var tracks = this.player().textTracks(); + var disabled = false; + + // Check whether a track of a different kind is showing + for (var i = 0, l = tracks.length; i < l; i++) { + var track = tracks[i]; + + if (track.kind !== this.kind_ && track.mode === 'showing') { + disabled = true; + break; + } + } + + // If another track is showing, disable this menu button + if (disabled) { + this.disable(); + } else { + this.enable(); + } + }; + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + DescriptionsButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-descriptions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); + }; + + DescriptionsButton.prototype.buildWrapperCSSClass = function buildWrapperCSSClass() { + return 'vjs-descriptions-button ' + _TextTrackButton.prototype.buildWrapperCSSClass.call(this); + }; + + return DescriptionsButton; + }(TextTrackButton); + + /** + * `kind` of TextTrack to look for to associate it with this menu. + * + * @type {string} + * @private + */ + + + DescriptionsButton.prototype.kind_ = 'descriptions'; + + /** + * The text that should display over the `DescriptionsButton`s controls. Added for localization. + * + * @type {string} + * @private + */ + DescriptionsButton.prototype.controlText_ = 'Descriptions'; + + Component.registerComponent('DescriptionsButton', DescriptionsButton); + + /** + * @file subtitles-button.js + */ + + /** + * The button component for toggling and selecting subtitles + * + * @extends TextTrackButton + */ + + var SubtitlesButton = function (_TextTrackButton) { + inherits(SubtitlesButton, _TextTrackButton); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Component~ReadyCallback} [ready] + * The function to call when this component is ready. + */ + function SubtitlesButton(player, options, ready) { + classCallCheck(this, SubtitlesButton); + return possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready)); + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + SubtitlesButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-subtitles-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); + }; + + SubtitlesButton.prototype.buildWrapperCSSClass = function buildWrapperCSSClass() { + return 'vjs-subtitles-button ' + _TextTrackButton.prototype.buildWrapperCSSClass.call(this); + }; + + return SubtitlesButton; + }(TextTrackButton); + + /** + * `kind` of TextTrack to look for to associate it with this menu. + * + * @type {string} + * @private + */ + + + SubtitlesButton.prototype.kind_ = 'subtitles'; + + /** + * The text that should display over the `SubtitlesButton`s controls. Added for localization. + * + * @type {string} + * @private + */ + SubtitlesButton.prototype.controlText_ = 'Subtitles'; + + Component.registerComponent('SubtitlesButton', SubtitlesButton); + + /** + * @file caption-settings-menu-item.js + */ + + /** + * The menu item for caption track settings menu + * + * @extends TextTrackMenuItem + */ + + var CaptionSettingsMenuItem = function (_TextTrackMenuItem) { + inherits(CaptionSettingsMenuItem, _TextTrackMenuItem); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function CaptionSettingsMenuItem(player, options) { + classCallCheck(this, CaptionSettingsMenuItem); + + options.track = { + player: player, + kind: options.kind, + label: options.kind + ' settings', + selectable: false, + default: false, + mode: 'disabled' + }; + + // CaptionSettingsMenuItem has no concept of 'selected' + options.selectable = false; + + options.name = 'CaptionSettingsMenuItem'; + + var _this = possibleConstructorReturn(this, _TextTrackMenuItem.call(this, player, options)); + + _this.addClass('vjs-texttrack-settings'); + _this.controlText(', opens ' + options.kind + ' settings dialog'); + return _this; + } + + /** + * This gets called when an `CaptionSettingsMenuItem` is "clicked". See + * {@link ClickableComponent} for more detailed information on what a click can be. + * + * @param {EventTarget~Event} [event] + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + CaptionSettingsMenuItem.prototype.handleClick = function handleClick(event) { + this.player().getChild('textTrackSettings').open(); + }; + + return CaptionSettingsMenuItem; + }(TextTrackMenuItem); + + Component.registerComponent('CaptionSettingsMenuItem', CaptionSettingsMenuItem); + + /** + * @file captions-button.js + */ + + /** + * The button component for toggling and selecting captions + * + * @extends TextTrackButton + */ + + var CaptionsButton = function (_TextTrackButton) { + inherits(CaptionsButton, _TextTrackButton); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Component~ReadyCallback} [ready] + * The function to call when this component is ready. + */ + function CaptionsButton(player, options, ready) { + classCallCheck(this, CaptionsButton); + return possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready)); + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + CaptionsButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-captions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); + }; + + CaptionsButton.prototype.buildWrapperCSSClass = function buildWrapperCSSClass() { + return 'vjs-captions-button ' + _TextTrackButton.prototype.buildWrapperCSSClass.call(this); + }; + + /** + * Create caption menu items + * + * @return {CaptionSettingsMenuItem[]} + * The array of current menu items. + */ + + + CaptionsButton.prototype.createItems = function createItems() { + var items = []; + + if (!(this.player().tech_ && this.player().tech_.featuresNativeTextTracks) && this.player().getChild('textTrackSettings')) { + items.push(new CaptionSettingsMenuItem(this.player_, {kind: this.kind_})); + + this.hideThreshold_ += 1; + } + + return _TextTrackButton.prototype.createItems.call(this, items); + }; + + return CaptionsButton; + }(TextTrackButton); + + /** + * `kind` of TextTrack to look for to associate it with this menu. + * + * @type {string} + * @private + */ + + + CaptionsButton.prototype.kind_ = 'captions'; + + /** + * The text that should display over the `CaptionsButton`s controls. Added for localization. + * + * @type {string} + * @private + */ + CaptionsButton.prototype.controlText_ = 'Captions'; + + Component.registerComponent('CaptionsButton', CaptionsButton); + + /** + * @file subs-caps-menu-item.js + */ + + /** + * SubsCapsMenuItem has an [cc] icon to distinguish captions from subtitles + * in the SubsCapsMenu. + * + * @extends TextTrackMenuItem + */ + + var SubsCapsMenuItem = function (_TextTrackMenuItem) { + inherits(SubsCapsMenuItem, _TextTrackMenuItem); + + function SubsCapsMenuItem() { + classCallCheck(this, SubsCapsMenuItem); + return possibleConstructorReturn(this, _TextTrackMenuItem.apply(this, arguments)); + } + + SubsCapsMenuItem.prototype.createEl = function createEl(type, props, attrs) { + var innerHTML = '<span class="vjs-menu-item-text">' + this.localize(this.options_.label); + + if (this.options_.track.kind === 'captions') { + innerHTML += '\n <span aria-hidden="true" class="vjs-icon-placeholder"></span>\n <span class="vjs-control-text"> ' + this.localize('Captions') + '</span>\n '; + } + + innerHTML += '</span>'; + + var el = _TextTrackMenuItem.prototype.createEl.call(this, type, assign({ + innerHTML: innerHTML + }, props), attrs); + + return el; + }; + + return SubsCapsMenuItem; + }(TextTrackMenuItem); + + Component.registerComponent('SubsCapsMenuItem', SubsCapsMenuItem); + + /** + * @file sub-caps-button.js + */ + /** + * The button component for toggling and selecting captions and/or subtitles + * + * @extends TextTrackButton + */ + + var SubsCapsButton = function (_TextTrackButton) { + inherits(SubsCapsButton, _TextTrackButton); + + function SubsCapsButton(player) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, SubsCapsButton); + + // Although North America uses "captions" in most cases for + // "captions and subtitles" other locales use "subtitles" + var _this = possibleConstructorReturn(this, _TextTrackButton.call(this, player, options)); + + _this.label_ = 'subtitles'; + if (['en', 'en-us', 'en-ca', 'fr-ca'].indexOf(_this.player_.language_) > -1) { + _this.label_ = 'captions'; + } + _this.menuButton_.controlText(toTitleCase(_this.label_)); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + SubsCapsButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-subs-caps-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); + }; + + SubsCapsButton.prototype.buildWrapperCSSClass = function buildWrapperCSSClass() { + return 'vjs-subs-caps-button ' + _TextTrackButton.prototype.buildWrapperCSSClass.call(this); + }; + + /** + * Create caption/subtitles menu items + * + * @return {CaptionSettingsMenuItem[]} + * The array of current menu items. + */ + + + SubsCapsButton.prototype.createItems = function createItems() { + var items = []; + + if (!(this.player().tech_ && this.player().tech_.featuresNativeTextTracks) && this.player().getChild('textTrackSettings')) { + items.push(new CaptionSettingsMenuItem(this.player_, {kind: this.label_})); + + this.hideThreshold_ += 1; + } + + items = _TextTrackButton.prototype.createItems.call(this, items, SubsCapsMenuItem); + return items; + }; + + return SubsCapsButton; + }(TextTrackButton); + + /** + * `kind`s of TextTrack to look for to associate it with this menu. + * + * @type {array} + * @private + */ + + + SubsCapsButton.prototype.kinds_ = ['captions', 'subtitles']; + + /** + * The text that should display over the `SubsCapsButton`s controls. + * + * + * @type {string} + * @private + */ + SubsCapsButton.prototype.controlText_ = 'Subtitles'; + + Component.registerComponent('SubsCapsButton', SubsCapsButton); + + /** + * @file audio-track-menu-item.js + */ + + /** + * An {@link AudioTrack} {@link MenuItem} + * + * @extends MenuItem + */ + + var AudioTrackMenuItem = function (_MenuItem) { + inherits(AudioTrackMenuItem, _MenuItem); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function AudioTrackMenuItem(player, options) { + classCallCheck(this, AudioTrackMenuItem); + + var track = options.track; + var tracks = player.audioTracks(); + + // Modify options for parent MenuItem class's init. + options.label = track.label || track.language || 'Unknown'; + options.selected = track.enabled; + + var _this = possibleConstructorReturn(this, _MenuItem.call(this, player, options)); + + _this.track = track; + + var changeHandler = function changeHandler() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + _this.handleTracksChange.apply(_this, args); + }; + + tracks.addEventListener('change', changeHandler); + _this.on('dispose', function () { + tracks.removeEventListener('change', changeHandler); + }); + return _this; + } + + /** + * This gets called when an `AudioTrackMenuItem is "clicked". See {@link ClickableComponent} + * for more detailed information on what a click can be. + * + * @param {EventTarget~Event} [event] + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + AudioTrackMenuItem.prototype.handleClick = function handleClick(event) { + var tracks = this.player_.audioTracks(); + + _MenuItem.prototype.handleClick.call(this, event); + + for (var i = 0; i < tracks.length; i++) { + var track = tracks[i]; + + track.enabled = track === this.track; + } + }; + + /** + * Handle any {@link AudioTrack} change. + * + * @param {EventTarget~Event} [event] + * The {@link AudioTrackList#change} event that caused this to run. + * + * @listens AudioTrackList#change + */ + + + AudioTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) { + this.selected(this.track.enabled); + }; + + return AudioTrackMenuItem; + }(MenuItem); + + Component.registerComponent('AudioTrackMenuItem', AudioTrackMenuItem); + + /** + * @file audio-track-button.js + */ + + /** + * The base class for buttons that toggle specific {@link AudioTrack} types. + * + * @extends TrackButton + */ + + var AudioTrackButton = function (_TrackButton) { + inherits(AudioTrackButton, _TrackButton); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options={}] + * The key/value store of player options. + */ + function AudioTrackButton(player) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, AudioTrackButton); + + options.tracks = player.audioTracks(); + + return possibleConstructorReturn(this, _TrackButton.call(this, player, options)); + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + AudioTrackButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-audio-button ' + _TrackButton.prototype.buildCSSClass.call(this); + }; + + AudioTrackButton.prototype.buildWrapperCSSClass = function buildWrapperCSSClass() { + return 'vjs-audio-button ' + _TrackButton.prototype.buildWrapperCSSClass.call(this); + }; + + /** + * Create a menu item for each audio track + * + * @param {AudioTrackMenuItem[]} [items=[]] + * An array of existing menu items to use. + * + * @return {AudioTrackMenuItem[]} + * An array of menu items + */ + + + AudioTrackButton.prototype.createItems = function createItems() { + var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + + // if there's only one audio track, there no point in showing it + this.hideThreshold_ = 1; + + var tracks = this.player_.audioTracks(); + + for (var i = 0; i < tracks.length; i++) { + var track = tracks[i]; + + items.push(new AudioTrackMenuItem(this.player_, { + track: track, + // MenuItem is selectable + selectable: true + })); + } + + return items; + }; + + return AudioTrackButton; + }(TrackButton); + + /** + * The text that should display over the `AudioTrackButton`s controls. Added for localization. + * + * @type {string} + * @private + */ + + + AudioTrackButton.prototype.controlText_ = 'Audio Track'; + Component.registerComponent('AudioTrackButton', AudioTrackButton); + + /** + * @file playback-rate-menu-item.js + */ + + /** + * The specific menu item type for selecting a playback rate. + * + * @extends MenuItem + */ + + var PlaybackRateMenuItem = function (_MenuItem) { + inherits(PlaybackRateMenuItem, _MenuItem); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function PlaybackRateMenuItem(player, options) { + classCallCheck(this, PlaybackRateMenuItem); + + var label = options.rate; + var rate = parseFloat(label, 10); + + // Modify options for parent MenuItem class's init. + options.label = label; + options.selected = rate === 1; + options.selectable = true; + + var _this = possibleConstructorReturn(this, _MenuItem.call(this, player, options)); + + _this.label = label; + _this.rate = rate; + + _this.on(player, 'ratechange', _this.update); + return _this; + } + + /** + * This gets called when an `PlaybackRateMenuItem` is "clicked". See + * {@link ClickableComponent} for more detailed information on what a click can be. + * + * @param {EventTarget~Event} [event] + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + PlaybackRateMenuItem.prototype.handleClick = function handleClick(event) { + _MenuItem.prototype.handleClick.call(this); + this.player().playbackRate(this.rate); + }; + + /** + * Update the PlaybackRateMenuItem when the playbackrate changes. + * + * @param {EventTarget~Event} [event] + * The `ratechange` event that caused this function to run. + * + * @listens Player#ratechange + */ + + + PlaybackRateMenuItem.prototype.update = function update(event) { + this.selected(this.player().playbackRate() === this.rate); + }; + + return PlaybackRateMenuItem; + }(MenuItem); + + /** + * The text that should display over the `PlaybackRateMenuItem`s controls. Added for localization. + * + * @type {string} + * @private + */ + + + PlaybackRateMenuItem.prototype.contentElType = 'button'; + + Component.registerComponent('PlaybackRateMenuItem', PlaybackRateMenuItem); + + /** + * @file playback-rate-menu-button.js + */ + + /** + * The component for controlling the playback rate. + * + * @extends MenuButton + */ + + var PlaybackRateMenuButton = function (_MenuButton) { + inherits(PlaybackRateMenuButton, _MenuButton); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function PlaybackRateMenuButton(player, options) { + classCallCheck(this, PlaybackRateMenuButton); + + var _this = possibleConstructorReturn(this, _MenuButton.call(this, player, options)); + + _this.updateVisibility(); + _this.updateLabel(); + + _this.on(player, 'loadstart', _this.updateVisibility); + _this.on(player, 'ratechange', _this.updateLabel); + return _this; + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + PlaybackRateMenuButton.prototype.createEl = function createEl$$1() { + var el = _MenuButton.prototype.createEl.call(this); + + this.labelEl_ = createEl('div', { + className: 'vjs-playback-rate-value', + innerHTML: '1x' + }); + + el.appendChild(this.labelEl_); + + return el; + }; + + PlaybackRateMenuButton.prototype.dispose = function dispose() { + this.labelEl_ = null; + + _MenuButton.prototype.dispose.call(this); + }; + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + + + PlaybackRateMenuButton.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-playback-rate ' + _MenuButton.prototype.buildCSSClass.call(this); + }; + + PlaybackRateMenuButton.prototype.buildWrapperCSSClass = function buildWrapperCSSClass() { + return 'vjs-playback-rate ' + _MenuButton.prototype.buildWrapperCSSClass.call(this); + }; + + /** + * Create the playback rate menu + * + * @return {Menu} + * Menu object populated with {@link PlaybackRateMenuItem}s + */ + + + PlaybackRateMenuButton.prototype.createMenu = function createMenu() { + var menu = new Menu(this.player()); + var rates = this.playbackRates(); + + if (rates) { + for (var i = rates.length - 1; i >= 0; i--) { + menu.addChild(new PlaybackRateMenuItem(this.player(), {rate: rates[i] + 'x'})); + } + } + + return menu; + }; + + /** + * Updates ARIA accessibility attributes + */ + + + PlaybackRateMenuButton.prototype.updateARIAAttributes = function updateARIAAttributes() { + // Current playback rate + this.el().setAttribute('aria-valuenow', this.player().playbackRate()); + }; + + /** + * This gets called when an `PlaybackRateMenuButton` is "clicked". See + * {@link ClickableComponent} for more detailed information on what a click can be. + * + * @param {EventTarget~Event} [event] + * The `keydown`, `tap`, or `click` event that caused this function to be + * called. + * + * @listens tap + * @listens click + */ + + + PlaybackRateMenuButton.prototype.handleClick = function handleClick(event) { + // select next rate option + var currentRate = this.player().playbackRate(); + var rates = this.playbackRates(); + + // this will select first one if the last one currently selected + var newRate = rates[0]; + + for (var i = 0; i < rates.length; i++) { + if (rates[i] > currentRate) { + newRate = rates[i]; + break; + } + } + this.player().playbackRate(newRate); + }; + + /** + * Get possible playback rates + * + * @return {Array} + * All possible playback rates + */ + + + PlaybackRateMenuButton.prototype.playbackRates = function playbackRates() { + return this.options_.playbackRates || this.options_.playerOptions && this.options_.playerOptions.playbackRates; + }; + + /** + * Get whether playback rates is supported by the tech + * and an array of playback rates exists + * + * @return {boolean} + * Whether changing playback rate is supported + */ + + + PlaybackRateMenuButton.prototype.playbackRateSupported = function playbackRateSupported() { + return this.player().tech_ && this.player().tech_.featuresPlaybackRate && this.playbackRates() && this.playbackRates().length > 0; + }; + + /** + * Hide playback rate controls when they're no playback rate options to select + * + * @param {EventTarget~Event} [event] + * The event that caused this function to run. + * + * @listens Player#loadstart + */ + + + PlaybackRateMenuButton.prototype.updateVisibility = function updateVisibility(event) { + if (this.playbackRateSupported()) { + this.removeClass('vjs-hidden'); + } else { + this.addClass('vjs-hidden'); + } + }; + + /** + * Update button label when rate changed + * + * @param {EventTarget~Event} [event] + * The event that caused this function to run. + * + * @listens Player#ratechange + */ + + + PlaybackRateMenuButton.prototype.updateLabel = function updateLabel(event) { + if (this.playbackRateSupported()) { + this.labelEl_.innerHTML = this.player().playbackRate() + 'x'; + } + }; + + return PlaybackRateMenuButton; + }(MenuButton); + + /** + * The text that should display over the `FullscreenToggle`s controls. Added for localization. + * + * @type {string} + * @private + */ + + + PlaybackRateMenuButton.prototype.controlText_ = 'Playback Rate'; + + Component.registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton); + + /** + * @file spacer.js + */ + + /** + * Just an empty spacer element that can be used as an append point for plugins, etc. + * Also can be used to create space between elements when necessary. + * + * @extends Component + */ + + var Spacer = function (_Component) { + inherits(Spacer, _Component); + + function Spacer() { + classCallCheck(this, Spacer); + return possibleConstructorReturn(this, _Component.apply(this, arguments)); + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + Spacer.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-spacer ' + _Component.prototype.buildCSSClass.call(this); + }; + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + Spacer.prototype.createEl = function createEl() { + return _Component.prototype.createEl.call(this, 'div', { + className: this.buildCSSClass() + }); + }; + + return Spacer; + }(Component); + + Component.registerComponent('Spacer', Spacer); + + /** + * @file custom-control-spacer.js + */ + + /** + * Spacer specifically meant to be used as an insertion point for new plugins, etc. + * + * @extends Spacer + */ + + var CustomControlSpacer = function (_Spacer) { + inherits(CustomControlSpacer, _Spacer); + + function CustomControlSpacer() { + classCallCheck(this, CustomControlSpacer); + return possibleConstructorReturn(this, _Spacer.apply(this, arguments)); + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + */ + CustomControlSpacer.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-custom-control-spacer ' + _Spacer.prototype.buildCSSClass.call(this); + }; + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + + + CustomControlSpacer.prototype.createEl = function createEl() { + var el = _Spacer.prototype.createEl.call(this, { + className: this.buildCSSClass() + }); + + // No-flex/table-cell mode requires there be some content + // in the cell to fill the remaining space of the table. + el.innerHTML = '\xA0'; + return el; + }; + + return CustomControlSpacer; + }(Spacer); + + Component.registerComponent('CustomControlSpacer', CustomControlSpacer); + + /** + * @file control-bar.js + */ + + /** + * Container of main controls. + * + * @extends Component + */ + + var ControlBar = function (_Component) { + inherits(ControlBar, _Component); + + function ControlBar() { + classCallCheck(this, ControlBar); + return possibleConstructorReturn(this, _Component.apply(this, arguments)); + } + + /** + * Create the `Component`'s DOM element + * + * @return {Element} + * The element that was created. + */ + ControlBar.prototype.createEl = function createEl() { + return _Component.prototype.createEl.call(this, 'div', { + className: 'vjs-control-bar', + dir: 'ltr' + }); + }; + + return ControlBar; + }(Component); + + /** + * Default options for `ControlBar` + * + * @type {Object} + * @private + */ + + + ControlBar.prototype.options_ = { + children: ['playToggle', 'volumePanel', 'currentTimeDisplay', 'timeDivider', 'durationDisplay', 'progressControl', 'liveDisplay', 'remainingTimeDisplay', 'customControlSpacer', 'playbackRateMenuButton', 'chaptersButton', 'descriptionsButton', 'subsCapsButton', 'audioTrackButton', 'fullscreenToggle'] + }; + + Component.registerComponent('ControlBar', ControlBar); + + /** + * @file error-display.js + */ + + /** + * A display that indicates an error has occurred. This means that the video + * is unplayable. + * + * @extends ModalDialog + */ + + var ErrorDisplay = function (_ModalDialog) { + inherits(ErrorDisplay, _ModalDialog); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function ErrorDisplay(player, options) { + classCallCheck(this, ErrorDisplay); + + var _this = possibleConstructorReturn(this, _ModalDialog.call(this, player, options)); + + _this.on(player, 'error', _this.open); + return _this; + } + + /** + * Builds the default DOM `className`. + * + * @return {string} + * The DOM `className` for this object. + * + * @deprecated Since version 5. + */ + + + ErrorDisplay.prototype.buildCSSClass = function buildCSSClass() { + return 'vjs-error-display ' + _ModalDialog.prototype.buildCSSClass.call(this); + }; + + /** + * Gets the localized error message based on the `Player`s error. + * + * @return {string} + * The `Player`s error message localized or an empty string. + */ + + + ErrorDisplay.prototype.content = function content() { + var error = this.player().error(); + + return error ? this.localize(error.message) : ''; + }; + + return ErrorDisplay; + }(ModalDialog); + + /** + * The default options for an `ErrorDisplay`. + * + * @private + */ + + + ErrorDisplay.prototype.options_ = mergeOptions(ModalDialog.prototype.options_, { + pauseOnOpen: false, + fillAlways: true, + temporary: false, + uncloseable: true + }); + + Component.registerComponent('ErrorDisplay', ErrorDisplay); + + /** + * @file text-track-settings.js + */ + + var LOCAL_STORAGE_KEY = 'vjs-text-track-settings'; + + var COLOR_BLACK = ['#000', 'Black']; + var COLOR_BLUE = ['#00F', 'Blue']; + var COLOR_CYAN = ['#0FF', 'Cyan']; + var COLOR_GREEN = ['#0F0', 'Green']; + var COLOR_MAGENTA = ['#F0F', 'Magenta']; + var COLOR_RED = ['#F00', 'Red']; + var COLOR_WHITE = ['#FFF', 'White']; + var COLOR_YELLOW = ['#FF0', 'Yellow']; + + var OPACITY_OPAQUE = ['1', 'Opaque']; + var OPACITY_SEMI = ['0.5', 'Semi-Transparent']; + var OPACITY_TRANS = ['0', 'Transparent']; + + // Configuration for the various <select> elements in the DOM of this component. + // + // Possible keys include: + // + // `default`: + // The default option index. Only needs to be provided if not zero. + // `parser`: + // A function which is used to parse the value from the selected option in + // a customized way. + // `selector`: + // The selector used to find the associated <select> element. + var selectConfigs = { + backgroundColor: { + selector: '.vjs-bg-color > select', + id: 'captions-background-color-%s', + label: 'Color', + options: [COLOR_BLACK, COLOR_WHITE, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_MAGENTA, COLOR_CYAN] + }, + + backgroundOpacity: { + selector: '.vjs-bg-opacity > select', + id: 'captions-background-opacity-%s', + label: 'Transparency', + options: [OPACITY_OPAQUE, OPACITY_SEMI, OPACITY_TRANS] + }, + + color: { + selector: '.vjs-fg-color > select', + id: 'captions-foreground-color-%s', + label: 'Color', + options: [COLOR_WHITE, COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_MAGENTA, COLOR_CYAN] + }, + + edgeStyle: { + selector: '.vjs-edge-style > select', + id: '%s', + label: 'Text Edge Style', + options: [['none', 'None'], ['raised', 'Raised'], ['depressed', 'Depressed'], ['uniform', 'Uniform'], ['dropshadow', 'Dropshadow']] + }, + + fontFamily: { + selector: '.vjs-font-family > select', + id: 'captions-font-family-%s', + label: 'Font Family', + options: [['proportionalSansSerif', 'Proportional Sans-Serif'], ['monospaceSansSerif', 'Monospace Sans-Serif'], ['proportionalSerif', 'Proportional Serif'], ['monospaceSerif', 'Monospace Serif'], ['casual', 'Casual'], ['script', 'Script'], ['small-caps', 'Small Caps']] + }, + + fontPercent: { + selector: '.vjs-font-percent > select', + id: 'captions-font-size-%s', + label: 'Font Size', + options: [['0.50', '50%'], ['0.75', '75%'], ['1.00', '100%'], ['1.25', '125%'], ['1.50', '150%'], ['1.75', '175%'], ['2.00', '200%'], ['3.00', '300%'], ['4.00', '400%']], + default: 2, + parser: function parser(v) { + return v === '1.00' ? null : Number(v); + } + }, + + textOpacity: { + selector: '.vjs-text-opacity > select', + id: 'captions-foreground-opacity-%s', + label: 'Transparency', + options: [OPACITY_OPAQUE, OPACITY_SEMI] + }, + + // Options for this object are defined below. + windowColor: { + selector: '.vjs-window-color > select', + id: 'captions-window-color-%s', + label: 'Color' + }, + + // Options for this object are defined below. + windowOpacity: { + selector: '.vjs-window-opacity > select', + id: 'captions-window-opacity-%s', + label: 'Transparency', + options: [OPACITY_TRANS, OPACITY_SEMI, OPACITY_OPAQUE] + } + }; + + selectConfigs.windowColor.options = selectConfigs.backgroundColor.options; + + /** + * Get the actual value of an option. + * + * @param {string} value + * The value to get + * + * @param {Function} [parser] + * Optional function to adjust the value. + * + * @return {Mixed} + * - Will be `undefined` if no value exists + * - Will be `undefined` if the given value is "none". + * - Will be the actual value otherwise. + * + * @private + */ + function parseOptionValue(value, parser) { + if (parser) { + value = parser(value); + } + + if (value && value !== 'none') { + return value; + } + } + + /** + * Gets the value of the selected <option> element within a <select> element. + * + * @param {Element} el + * the element to look in + * + * @param {Function} [parser] + * Optional function to adjust the value. + * + * @return {Mixed} + * - Will be `undefined` if no value exists + * - Will be `undefined` if the given value is "none". + * - Will be the actual value otherwise. + * + * @private + */ + function getSelectedOptionValue(el, parser) { + var value = el.options[el.options.selectedIndex].value; + + return parseOptionValue(value, parser); + } + + /** + * Sets the selected <option> element within a <select> element based on a + * given value. + * + * @param {Element} el + * The element to look in. + * + * @param {string} value + * the property to look on. + * + * @param {Function} [parser] + * Optional function to adjust the value before comparing. + * + * @private + */ + function setSelectedOption(el, value, parser) { + if (!value) { + return; + } + + for (var i = 0; i < el.options.length; i++) { + if (parseOptionValue(el.options[i].value, parser) === value) { + el.selectedIndex = i; + break; + } + } + } + + /** + * Manipulate Text Tracks settings. + * + * @extends ModalDialog + */ + + var TextTrackSettings = function (_ModalDialog) { + inherits(TextTrackSettings, _ModalDialog); + + /** + * Creates an instance of this class. + * + * @param {Player} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of player options. + */ + function TextTrackSettings(player, options) { + classCallCheck(this, TextTrackSettings); + + options.temporary = false; + + var _this = possibleConstructorReturn(this, _ModalDialog.call(this, player, options)); + + _this.updateDisplay = bind(_this, _this.updateDisplay); + + // fill the modal and pretend we have opened it + _this.fill(); + _this.hasBeenOpened_ = _this.hasBeenFilled_ = true; + + _this.endDialog = createEl('p', { + className: 'vjs-control-text', + textContent: _this.localize('End of dialog window.') + }); + _this.el().appendChild(_this.endDialog); + + _this.setDefaults(); + + // Grab `persistTextTrackSettings` from the player options if not passed in child options + if (options.persistTextTrackSettings === undefined) { + _this.options_.persistTextTrackSettings = _this.options_.playerOptions.persistTextTrackSettings; + } + + _this.on(_this.$('.vjs-done-button'), 'click', function () { + _this.saveSettings(); + _this.close(); + }); + + _this.on(_this.$('.vjs-default-button'), 'click', function () { + _this.setDefaults(); + _this.updateDisplay(); + }); + + each(selectConfigs, function (config) { + _this.on(_this.$(config.selector), 'change', _this.updateDisplay); + }); + + if (_this.options_.persistTextTrackSettings) { + _this.restoreSettings(); + } + return _this; + } + + TextTrackSettings.prototype.dispose = function dispose() { + this.endDialog = null; + + _ModalDialog.prototype.dispose.call(this); + }; + + /** + * Create a <select> element with configured options. + * + * @param {string} key + * Configuration key to use during creation. + * + * @return {string} + * An HTML string. + * + * @private + */ + + + TextTrackSettings.prototype.createElSelect_ = function createElSelect_(key) { + var _this2 = this; + + var legendId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'label'; + + var config = selectConfigs[key]; + var id = config.id.replace('%s', this.id_); + var selectLabelledbyIds = [legendId, id].join(' ').trim(); + + return ['<' + type + ' id="' + id + '" class="' + (type === 'label' ? 'vjs-label' : '') + '">', this.localize(config.label), '</' + type + '>', '<select aria-labelledby="' + selectLabelledbyIds + '">'].concat(config.options.map(function (o) { + var optionId = id + '-' + o[1].replace(/\W+/g, ''); + + return ['<option id="' + optionId + '" value="' + o[0] + '" ', 'aria-labelledby="' + selectLabelledbyIds + ' ' + optionId + '">', _this2.localize(o[1]), '</option>'].join(''); + })).concat('</select>').join(''); + }; + + /** + * Create foreground color element for the component + * + * @return {string} + * An HTML string. + * + * @private + */ + + + TextTrackSettings.prototype.createElFgColor_ = function createElFgColor_() { + var legendId = 'captions-text-legend-' + this.id_; + + return ['<fieldset class="vjs-fg-color vjs-track-setting">', '<legend id="' + legendId + '">', this.localize('Text'), '</legend>', this.createElSelect_('color', legendId), '<span class="vjs-text-opacity vjs-opacity">', this.createElSelect_('textOpacity', legendId), '</span>', '</fieldset>'].join(''); + }; + + /** + * Create background color element for the component + * + * @return {string} + * An HTML string. + * + * @private + */ + + + TextTrackSettings.prototype.createElBgColor_ = function createElBgColor_() { + var legendId = 'captions-background-' + this.id_; + + return ['<fieldset class="vjs-bg-color vjs-track-setting">', '<legend id="' + legendId + '">', this.localize('Background'), '</legend>', this.createElSelect_('backgroundColor', legendId), '<span class="vjs-bg-opacity vjs-opacity">', this.createElSelect_('backgroundOpacity', legendId), '</span>', '</fieldset>'].join(''); + }; + + /** + * Create window color element for the component + * + * @return {string} + * An HTML string. + * + * @private + */ + + + TextTrackSettings.prototype.createElWinColor_ = function createElWinColor_() { + var legendId = 'captions-window-' + this.id_; + + return ['<fieldset class="vjs-window-color vjs-track-setting">', '<legend id="' + legendId + '">', this.localize('Window'), '</legend>', this.createElSelect_('windowColor', legendId), '<span class="vjs-window-opacity vjs-opacity">', this.createElSelect_('windowOpacity', legendId), '</span>', '</fieldset>'].join(''); + }; + + /** + * Create color elements for the component + * + * @return {Element} + * The element that was created + * + * @private + */ + + + TextTrackSettings.prototype.createElColors_ = function createElColors_() { + return createEl('div', { + className: 'vjs-track-settings-colors', + innerHTML: [this.createElFgColor_(), this.createElBgColor_(), this.createElWinColor_()].join('') + }); + }; + + /** + * Create font elements for the component + * + * @return {Element} + * The element that was created. + * + * @private + */ + + + TextTrackSettings.prototype.createElFont_ = function createElFont_() { + return createEl('div', { + className: 'vjs-track-settings-font', + innerHTML: ['<fieldset class="vjs-font-percent vjs-track-setting">', this.createElSelect_('fontPercent', '', 'legend'), '</fieldset>', '<fieldset class="vjs-edge-style vjs-track-setting">', this.createElSelect_('edgeStyle', '', 'legend'), '</fieldset>', '<fieldset class="vjs-font-family vjs-track-setting">', this.createElSelect_('fontFamily', '', 'legend'), '</fieldset>'].join('') + }); + }; + + /** + * Create controls for the component + * + * @return {Element} + * The element that was created. + * + * @private + */ + + + TextTrackSettings.prototype.createElControls_ = function createElControls_() { + var defaultsDescription = this.localize('restore all settings to the default values'); + + return createEl('div', { + className: 'vjs-track-settings-controls', + innerHTML: ['<button class="vjs-default-button" title="' + defaultsDescription + '">', this.localize('Reset'), '<span class="vjs-control-text"> ' + defaultsDescription + '</span>', '</button>', '<button class="vjs-done-button">' + this.localize('Done') + '</button>'].join('') + }); + }; + + TextTrackSettings.prototype.content = function content() { + return [this.createElColors_(), this.createElFont_(), this.createElControls_()]; + }; + + TextTrackSettings.prototype.label = function label() { + return this.localize('Caption Settings Dialog'); + }; + + TextTrackSettings.prototype.description = function description() { + return this.localize('Beginning of dialog window. Escape will cancel and close the window.'); + }; + + TextTrackSettings.prototype.buildCSSClass = function buildCSSClass() { + return _ModalDialog.prototype.buildCSSClass.call(this) + ' vjs-text-track-settings'; + }; + + /** + * Gets an object of text track settings (or null). + * + * @return {Object} + * An object with config values parsed from the DOM or localStorage. + */ + + + TextTrackSettings.prototype.getValues = function getValues() { + var _this3 = this; + + return reduce(selectConfigs, function (accum, config, key) { + var value = getSelectedOptionValue(_this3.$(config.selector), config.parser); + + if (value !== undefined) { + accum[key] = value; + } + + return accum; + }, {}); + }; + + /** + * Sets text track settings from an object of values. + * + * @param {Object} values + * An object with config values parsed from the DOM or localStorage. + */ + + + TextTrackSettings.prototype.setValues = function setValues(values) { + var _this4 = this; + + each(selectConfigs, function (config, key) { + setSelectedOption(_this4.$(config.selector), values[key], config.parser); + }); + }; + + /** + * Sets all `<select>` elements to their default values. + */ + + + TextTrackSettings.prototype.setDefaults = function setDefaults() { + var _this5 = this; + + each(selectConfigs, function (config) { + var index = config.hasOwnProperty('default') ? config.default : 0; + + _this5.$(config.selector).selectedIndex = index; + }); + }; + + /** + * Restore texttrack settings from localStorage + */ + + + TextTrackSettings.prototype.restoreSettings = function restoreSettings() { + var values = void 0; + + try { + values = JSON.parse(window_1.localStorage.getItem(LOCAL_STORAGE_KEY)); + } catch (err) { + log$1.warn(err); + } + + if (values) { + this.setValues(values); + } + }; + + /** + * Save text track settings to localStorage + */ + + + TextTrackSettings.prototype.saveSettings = function saveSettings() { + if (!this.options_.persistTextTrackSettings) { + return; + } + + var values = this.getValues(); + + try { + if (Object.keys(values).length) { + window_1.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(values)); + } else { + window_1.localStorage.removeItem(LOCAL_STORAGE_KEY); + } + } catch (err) { + log$1.warn(err); + } + }; + + /** + * Update display of text track settings + */ + + + TextTrackSettings.prototype.updateDisplay = function updateDisplay() { + var ttDisplay = this.player_.getChild('textTrackDisplay'); + + if (ttDisplay) { + ttDisplay.updateDisplay(); + } + }; + + /** + * conditionally blur the element and refocus the captions button + * + * @private + */ + + + TextTrackSettings.prototype.conditionalBlur_ = function conditionalBlur_() { + this.previouslyActiveEl_ = null; + this.off(document_1, 'keydown', this.handleKeyDown); + + var cb = this.player_.controlBar; + var subsCapsBtn = cb && cb.subsCapsButton; + var ccBtn = cb && cb.captionsButton; + + if (subsCapsBtn) { + subsCapsBtn.focus(); + } else if (ccBtn) { + ccBtn.focus(); + } + }; + + return TextTrackSettings; + }(ModalDialog); + + Component.registerComponent('TextTrackSettings', TextTrackSettings); + + /** + * @file resize-manager.js + */ + + /** + * A Resize Manager. It is in charge of triggering `playerresize` on the player in the right conditions. + * + * It'll either create an iframe and use a debounced resize handler on it or use the new {@link https://wicg.github.io/ResizeObserver/|ResizeObserver}. + * + * If the ResizeObserver is available natively, it will be used. A polyfill can be passed in as an option. + * If a `playerresize` event is not needed, the ResizeManager component can be removed from the player, see the example below. + * @example <caption>How to disable the resize manager</caption> + * const player = videojs('#vid', { + * resizeManager: false + * }); + * + * @see {@link https://wicg.github.io/ResizeObserver/|ResizeObserver specification} + * + * @extends Component + */ + + var ResizeManager = function (_Component) { + inherits(ResizeManager, _Component); + + /** + * Create the ResizeManager. + * + * @param {Object} player + * The `Player` that this class should be attached to. + * + * @param {Object} [options] + * The key/value store of ResizeManager options. + * + * @param {Object} [options.ResizeObserver] + * A polyfill for ResizeObserver can be passed in here. + * If this is set to null it will ignore the native ResizeObserver and fall back to the iframe fallback. + */ + function ResizeManager(player, options) { + classCallCheck(this, ResizeManager); + + var RESIZE_OBSERVER_AVAILABLE = options.ResizeObserver || window_1.ResizeObserver; + + // if `null` was passed, we want to disable the ResizeObserver + if (options.ResizeObserver === null) { + RESIZE_OBSERVER_AVAILABLE = false; + } + + // Only create an element when ResizeObserver isn't available + var options_ = mergeOptions({createEl: !RESIZE_OBSERVER_AVAILABLE}, options); + + var _this = possibleConstructorReturn(this, _Component.call(this, player, options_)); + + _this.ResizeObserver = options.ResizeObserver || window_1.ResizeObserver; + _this.loadListener_ = null; + _this.resizeObserver_ = null; + _this.debouncedHandler_ = debounce(function () { + _this.resizeHandler(); + }, 100, false, player); + + if (RESIZE_OBSERVER_AVAILABLE) { + _this.resizeObserver_ = new _this.ResizeObserver(_this.debouncedHandler_); + _this.resizeObserver_.observe(player.el()); + } else { + _this.loadListener_ = function () { + if (_this.el_.contentWindow) { + on(_this.el_.contentWindow, 'resize', _this.debouncedHandler_); + } + _this.off('load', _this.loadListener_); + }; + + _this.on('load', _this.loadListener_); + } + return _this; + } + + ResizeManager.prototype.createEl = function createEl() { + return _Component.prototype.createEl.call(this, 'iframe', { + className: 'vjs-resize-manager' + }); + }; + + /** + * Called when a resize is triggered on the iframe or a resize is observed via the ResizeObserver + * + * @fires Player#playerresize + */ + + + ResizeManager.prototype.resizeHandler = function resizeHandler() { + /** + * Called when the player size has changed + * + * @event Player#playerresize + * @type {EventTarget~Event} + */ + this.player_.trigger('playerresize'); + }; + + ResizeManager.prototype.dispose = function dispose() { + if (this.resizeObserver_) { + this.resizeObserver_.unobserve(this.player_.el()); + this.resizeObserver_.disconnect(); + } + + if (this.el_ && this.el_.contentWindow) { + off(this.el_.contentWindow, 'resize', this.debouncedHandler_); + } + + if (this.loadListener_) { + this.off('load', this.loadListener_); + } + + this.ResizeObserver = null; + this.resizeObserver = null; + this.debouncedHandler_ = null; + this.loadListener_ = null; + }; + + return ResizeManager; + }(Component); + + Component.registerComponent('ResizeManager', ResizeManager); + + /** + * This function is used to fire a sourceset when there is something + * similar to `mediaEl.load()` being called. It will try to find the source via + * the `src` attribute and then the `<source>` elements. It will then fire `sourceset` + * with the source that was found or empty string if we cannot know. If it cannot + * find a source then `sourceset` will not be fired. + * + * @param {Html5} tech + * The tech object that sourceset was setup on + * + * @return {boolean} + * returns false if the sourceset was not fired and true otherwise. + */ + var sourcesetLoad = function sourcesetLoad(tech) { + var el = tech.el(); + + // if `el.src` is set, that source will be loaded. + if (el.hasAttribute('src')) { + tech.triggerSourceset(el.src); + return true; + } + + /** + * Since there isn't a src property on the media element, source elements will be used for + * implementing the source selection algorithm. This happens asynchronously and + * for most cases were there is more than one source we cannot tell what source will + * be loaded, without re-implementing the source selection algorithm. At this time we are not + * going to do that. There are three special cases that we do handle here though: + * + * 1. If there are no sources, do not fire `sourceset`. + * 2. If there is only one `<source>` with a `src` property/attribute that is our `src` + * 3. If there is more than one `<source>` but all of them have the same `src` url. + * That will be our src. + */ + var sources = tech.$$('source'); + var srcUrls = []; + var src = ''; + + // if there are no sources, do not fire sourceset + if (!sources.length) { + return false; + } + + // only count valid/non-duplicate source elements + for (var i = 0; i < sources.length; i++) { + var url = sources[i].src; + + if (url && srcUrls.indexOf(url) === -1) { + srcUrls.push(url); + } + } + + // there were no valid sources + if (!srcUrls.length) { + return false; + } + + // there is only one valid source element url + // use that + if (srcUrls.length === 1) { + src = srcUrls[0]; + } + + tech.triggerSourceset(src); + return true; + }; + + /** + * our implementation of an `innerHTML` descriptor for browsers + * that do not have one. + */ + var innerHTMLDescriptorPolyfill = Object.defineProperty({}, 'innerHTML', { + get: function get() { + return this.cloneNode(true).innerHTML; + }, + set: function set(v) { + // make a dummy node to use innerHTML on + var dummy = document_1.createElement(this.nodeName.toLowerCase()); + + // set innerHTML to the value provided + dummy.innerHTML = v; + + // make a document fragment to hold the nodes from dummy + var docFrag = document_1.createDocumentFragment(); + + // copy all of the nodes created by the innerHTML on dummy + // to the document fragment + while (dummy.childNodes.length) { + docFrag.appendChild(dummy.childNodes[0]); + } + + // remove content + this.innerText = ''; + + // now we add all of that html in one by appending the + // document fragment. This is how innerHTML does it. + window_1.Element.prototype.appendChild.call(this, docFrag); + + // then return the result that innerHTML's setter would + return this.innerHTML; + } + }); + + /** + * Get a property descriptor given a list of priorities and the + * property to get. + */ + var getDescriptor = function getDescriptor(priority, prop) { + var descriptor = {}; + + for (var i = 0; i < priority.length; i++) { + descriptor = Object.getOwnPropertyDescriptor(priority[i], prop); + + if (descriptor && descriptor.set && descriptor.get) { + break; + } + } + + descriptor.enumerable = true; + descriptor.configurable = true; + + return descriptor; + }; + + var getInnerHTMLDescriptor = function getInnerHTMLDescriptor(tech) { + return getDescriptor([tech.el(), window_1.HTMLMediaElement.prototype, window_1.Element.prototype, innerHTMLDescriptorPolyfill], 'innerHTML'); + }; + + /** + * Patches browser internal functions so that we can tell synchronously + * if a `<source>` was appended to the media element. For some reason this + * causes a `sourceset` if the the media element is ready and has no source. + * This happens when: + * - The page has just loaded and the media element does not have a source. + * - The media element was emptied of all sources, then `load()` was called. + * + * It does this by patching the following functions/properties when they are supported: + * + * - `append()` - can be used to add a `<source>` element to the media element + * - `appendChild()` - can be used to add a `<source>` element to the media element + * - `insertAdjacentHTML()` - can be used to add a `<source>` element to the media element + * - `innerHTML` - can be used to add a `<source>` element to the media element + * + * @param {Html5} tech + * The tech object that sourceset is being setup on. + */ + var firstSourceWatch = function firstSourceWatch(tech) { + var el = tech.el(); + + // make sure firstSourceWatch isn't setup twice. + if (el.resetSourceWatch_) { + return; + } + + var old = {}; + var innerDescriptor = getInnerHTMLDescriptor(tech); + var appendWrapper = function appendWrapper(appendFn) { + return function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var retval = appendFn.apply(el, args); + + sourcesetLoad(tech); + + return retval; + }; + }; + + ['append', 'appendChild', 'insertAdjacentHTML'].forEach(function (k) { + if (!el[k]) { + return; + } + + // store the old function + old[k] = el[k]; + + // call the old function with a sourceset if a source + // was loaded + el[k] = appendWrapper(old[k]); + }); + + Object.defineProperty(el, 'innerHTML', mergeOptions(innerDescriptor, { + set: appendWrapper(innerDescriptor.set) + })); + + el.resetSourceWatch_ = function () { + el.resetSourceWatch_ = null; + Object.keys(old).forEach(function (k) { + el[k] = old[k]; + }); + + Object.defineProperty(el, 'innerHTML', innerDescriptor); + }; + + // on the first sourceset, we need to revert our changes + tech.one('sourceset', el.resetSourceWatch_); + }; + + /** + * our implementation of a `src` descriptor for browsers + * that do not have one. + */ + var srcDescriptorPolyfill = Object.defineProperty({}, 'src', { + get: function get() { + if (this.hasAttribute('src')) { + return getAbsoluteURL(window_1.Element.prototype.getAttribute.call(this, 'src')); + } + + return ''; + }, + set: function set(v) { + window_1.Element.prototype.setAttribute.call(this, 'src', v); + + return v; + } + }); + + var getSrcDescriptor = function getSrcDescriptor(tech) { + return getDescriptor([tech.el(), window_1.HTMLMediaElement.prototype, srcDescriptorPolyfill], 'src'); + }; + + /** + * setup `sourceset` handling on the `Html5` tech. This function + * patches the following element properties/functions: + * + * - `src` - to determine when `src` is set + * - `setAttribute()` - to determine when `src` is set + * - `load()` - this re-triggers the source selection algorithm, and can + * cause a sourceset. + * + * If there is no source when we are adding `sourceset` support or during a `load()` + * we also patch the functions listed in `firstSourceWatch`. + * + * @param {Html5} tech + * The tech to patch + */ + var setupSourceset = function setupSourceset(tech) { + if (!tech.featuresSourceset) { + return; + } + + var el = tech.el(); + + // make sure sourceset isn't setup twice. + if (el.resetSourceset_) { + return; + } + + var srcDescriptor = getSrcDescriptor(tech); + var oldSetAttribute = el.setAttribute; + var oldLoad = el.load; + + Object.defineProperty(el, 'src', mergeOptions(srcDescriptor, { + set: function set(v) { + var retval = srcDescriptor.set.call(el, v); + + // we use the getter here to get the actual value set on src + tech.triggerSourceset(el.src); + + return retval; + } + })); + + el.setAttribute = function (n, v) { + var retval = oldSetAttribute.call(el, n, v); + + if (/src/i.test(n)) { + tech.triggerSourceset(el.src); + } + + return retval; + }; + + el.load = function () { + var retval = oldLoad.call(el); + + // if load was called, but there was no source to fire + // sourceset on. We have to watch for a source append + // as that can trigger a `sourceset` when the media element + // has no source + if (!sourcesetLoad(tech)) { + tech.triggerSourceset(''); + firstSourceWatch(tech); + } + + return retval; + }; + + if (el.currentSrc) { + tech.triggerSourceset(el.currentSrc); + } else if (!sourcesetLoad(tech)) { + firstSourceWatch(tech); + } + + el.resetSourceset_ = function () { + el.resetSourceset_ = null; + el.load = oldLoad; + el.setAttribute = oldSetAttribute; + Object.defineProperty(el, 'src', srcDescriptor); + if (el.resetSourceWatch_) { + el.resetSourceWatch_(); + } + }; + }; + + var _templateObject$1 = taggedTemplateLiteralLoose(['Text Tracks are being loaded from another origin but the crossorigin attribute isn\'t used.\n This may prevent text tracks from loading.'], ['Text Tracks are being loaded from another origin but the crossorigin attribute isn\'t used.\n This may prevent text tracks from loading.']); + + /** + * HTML5 Media Controller - Wrapper for HTML5 Media API + * + * @mixes Tech~SourceHandlerAdditions + * @extends Tech + */ + + var Html5 = function (_Tech) { + inherits(Html5, _Tech); + + /** + * Create an instance of this Tech. + * + * @param {Object} [options] + * The key/value store of player options. + * + * @param {Component~ReadyCallback} ready + * Callback function to call when the `HTML5` Tech is ready. + */ + function Html5(options, ready) { + classCallCheck(this, Html5); + + var _this = possibleConstructorReturn(this, _Tech.call(this, options, ready)); + + var source = options.source; + var crossoriginTracks = false; + + // Set the source if one is provided + // 1) Check if the source is new (if not, we want to keep the original so playback isn't interrupted) + // 2) Check to see if the network state of the tag was failed at init, and if so, reset the source + // anyway so the error gets fired. + if (source && (_this.el_.currentSrc !== source.src || options.tag && options.tag.initNetworkState_ === 3)) { + _this.setSource(source); + } else { + _this.handleLateInit_(_this.el_); + } + + // setup sourceset after late sourceset/init + if (options.enableSourceset) { + _this.setupSourcesetHandling_(); + } + + if (_this.el_.hasChildNodes()) { + + var nodes = _this.el_.childNodes; + var nodesLength = nodes.length; + var removeNodes = []; + + while (nodesLength--) { + var node = nodes[nodesLength]; + var nodeName = node.nodeName.toLowerCase(); + + if (nodeName === 'track') { + if (!_this.featuresNativeTextTracks) { + // Empty video tag tracks so the built-in player doesn't use them also. + // This may not be fast enough to stop HTML5 browsers from reading the tags + // so we'll need to turn off any default tracks if we're manually doing + // captions and subtitles. videoElement.textTracks + removeNodes.push(node); + } else { + // store HTMLTrackElement and TextTrack to remote list + _this.remoteTextTrackEls().addTrackElement_(node); + _this.remoteTextTracks().addTrack(node.track); + _this.textTracks().addTrack(node.track); + if (!crossoriginTracks && !_this.el_.hasAttribute('crossorigin') && isCrossOrigin(node.src)) { + crossoriginTracks = true; + } + } + } + } + + for (var i = 0; i < removeNodes.length; i++) { + _this.el_.removeChild(removeNodes[i]); + } + } + + _this.proxyNativeTracks_(); + if (_this.featuresNativeTextTracks && crossoriginTracks) { + log$1.warn(tsml(_templateObject$1)); + } + + // prevent iOS Safari from disabling metadata text tracks during native playback + _this.restoreMetadataTracksInIOSNativePlayer_(); + + // Determine if native controls should be used + // Our goal should be to get the custom controls on mobile solid everywhere + // so we can remove this all together. Right now this will block custom + // controls on touch enabled laptops like the Chrome Pixel + if ((TOUCH_ENABLED || IS_IPHONE || IS_NATIVE_ANDROID) && options.nativeControlsForTouch === true) { + _this.setControls(true); + } + + // on iOS, we want to proxy `webkitbeginfullscreen` and `webkitendfullscreen` + // into a `fullscreenchange` event + _this.proxyWebkitFullscreen_(); + + _this.triggerReady(); + return _this; + } + + /** + * Dispose of `HTML5` media element and remove all tracks. + */ + + + Html5.prototype.dispose = function dispose() { + if (this.el_.resetSourceset_) { + this.el_.resetSourceset_(); + } + Html5.disposeMediaElement(this.el_); + this.options_ = null; + + // tech will handle clearing of the emulated track list + _Tech.prototype.dispose.call(this); + }; + + /** + * Modify the media element so that we can detect when + * the source is changed. Fires `sourceset` just after the source has changed + */ + + + Html5.prototype.setupSourcesetHandling_ = function setupSourcesetHandling_() { + setupSourceset(this); + }; + + /** + * When a captions track is enabled in the iOS Safari native player, all other + * tracks are disabled (including metadata tracks), which nulls all of their + * associated cue points. This will restore metadata tracks to their pre-fullscreen + * state in those cases so that cue points are not needlessly lost. + * + * @private + */ + + + Html5.prototype.restoreMetadataTracksInIOSNativePlayer_ = function restoreMetadataTracksInIOSNativePlayer_() { + var textTracks = this.textTracks(); + var metadataTracksPreFullscreenState = void 0; + + // captures a snapshot of every metadata track's current state + var takeMetadataTrackSnapshot = function takeMetadataTrackSnapshot() { + metadataTracksPreFullscreenState = []; + + for (var i = 0; i < textTracks.length; i++) { + var track = textTracks[i]; + + if (track.kind === 'metadata') { + metadataTracksPreFullscreenState.push({ + track: track, + storedMode: track.mode + }); + } + } + }; + + // snapshot each metadata track's initial state, and update the snapshot + // each time there is a track 'change' event + takeMetadataTrackSnapshot(); + textTracks.addEventListener('change', takeMetadataTrackSnapshot); + + this.on('dispose', function () { + return textTracks.removeEventListener('change', takeMetadataTrackSnapshot); + }); + + var restoreTrackMode = function restoreTrackMode() { + for (var i = 0; i < metadataTracksPreFullscreenState.length; i++) { + var storedTrack = metadataTracksPreFullscreenState[i]; + + if (storedTrack.track.mode === 'disabled' && storedTrack.track.mode !== storedTrack.storedMode) { + storedTrack.track.mode = storedTrack.storedMode; + } + } + // we only want this handler to be executed on the first 'change' event + textTracks.removeEventListener('change', restoreTrackMode); + }; + + // when we enter fullscreen playback, stop updating the snapshot and + // restore all track modes to their pre-fullscreen state + this.on('webkitbeginfullscreen', function () { + textTracks.removeEventListener('change', takeMetadataTrackSnapshot); + + // remove the listener before adding it just in case it wasn't previously removed + textTracks.removeEventListener('change', restoreTrackMode); + textTracks.addEventListener('change', restoreTrackMode); + }); + + // start updating the snapshot again after leaving fullscreen + this.on('webkitendfullscreen', function () { + // remove the listener before adding it just in case it wasn't previously removed + textTracks.removeEventListener('change', takeMetadataTrackSnapshot); + textTracks.addEventListener('change', takeMetadataTrackSnapshot); + + // remove the restoreTrackMode handler in case it wasn't triggered during fullscreen playback + textTracks.removeEventListener('change', restoreTrackMode); + }); + }; + + /** + * Attempt to force override of tracks for the given type + * + * @param {String} type - Track type to override, possible values include 'Audio', + * 'Video', and 'Text'. + * @param {Boolean} override - If set to true native audio/video will be overridden, + * otherwise native audio/video will potentially be used. + * @private + */ + + + Html5.prototype.overrideNative_ = function overrideNative_(type, override) { + var _this2 = this; + + // If there is no behavioral change don't add/remove listeners + if (override !== this['featuresNative' + type + 'Tracks']) { + return; + } + + var lowerCaseType = type.toLowerCase(); + + if (this[lowerCaseType + 'TracksListeners_']) { + Object.keys(this[lowerCaseType + 'TracksListeners_']).forEach(function (eventName) { + var elTracks = _this2.el()[lowerCaseType + 'Tracks']; + + elTracks.removeEventListener(eventName, _this2[lowerCaseType + 'TracksListeners_'][eventName]); + }); + } + + this['featuresNative' + type + 'Tracks'] = !override; + this[lowerCaseType + 'TracksListeners_'] = null; + + this.proxyNativeTracksForType_(lowerCaseType); + }; + + /** + * Attempt to force override of native audio tracks. + * + * @param {Boolean} override - If set to true native audio will be overridden, + * otherwise native audio will potentially be used. + */ + + + Html5.prototype.overrideNativeAudioTracks = function overrideNativeAudioTracks(override) { + this.overrideNative_('Audio', override); + }; + + /** + * Attempt to force override of native video tracks. + * + * @param {Boolean} override - If set to true native video will be overridden, + * otherwise native video will potentially be used. + */ + + + Html5.prototype.overrideNativeVideoTracks = function overrideNativeVideoTracks(override) { + this.overrideNative_('Video', override); + }; + + /** + * Proxy native track list events for the given type to our track + * lists if the browser we are playing in supports that type of track list. + * + * @param {string} name - Track type; values include 'audio', 'video', and 'text' + * @private + */ + + + Html5.prototype.proxyNativeTracksForType_ = function proxyNativeTracksForType_(name) { + var _this3 = this; + + var props = NORMAL[name]; + var elTracks = this.el()[props.getterName]; + var techTracks = this[props.getterName](); + + if (!this['featuresNative' + props.capitalName + 'Tracks'] || !elTracks || !elTracks.addEventListener) { + return; + } + var listeners = { + change: function change(e) { + techTracks.trigger({ + type: 'change', + target: techTracks, + currentTarget: techTracks, + srcElement: techTracks + }); + }, + addtrack: function addtrack(e) { + techTracks.addTrack(e.track); + }, + removetrack: function removetrack(e) { + techTracks.removeTrack(e.track); + } + }; + var removeOldTracks = function removeOldTracks() { + var removeTracks = []; + + for (var i = 0; i < techTracks.length; i++) { + var found = false; + + for (var j = 0; j < elTracks.length; j++) { + if (elTracks[j] === techTracks[i]) { + found = true; + break; + } + } + + if (!found) { + removeTracks.push(techTracks[i]); + } + } + + while (removeTracks.length) { + techTracks.removeTrack(removeTracks.shift()); + } + }; + + this[props.getterName + 'Listeners_'] = listeners; + + Object.keys(listeners).forEach(function (eventName) { + var listener = listeners[eventName]; + + elTracks.addEventListener(eventName, listener); + _this3.on('dispose', function (e) { + return elTracks.removeEventListener(eventName, listener); + }); + }); + + // Remove (native) tracks that are not used anymore + this.on('loadstart', removeOldTracks); + this.on('dispose', function (e) { + return _this3.off('loadstart', removeOldTracks); + }); + }; + + /** + * Proxy all native track list events to our track lists if the browser we are playing + * in supports that type of track list. + * + * @private + */ + + + Html5.prototype.proxyNativeTracks_ = function proxyNativeTracks_() { + var _this4 = this; + + NORMAL.names.forEach(function (name) { + _this4.proxyNativeTracksForType_(name); + }); + }; + + /** + * Create the `Html5` Tech's DOM element. + * + * @return {Element} + * The element that gets created. + */ + + + Html5.prototype.createEl = function createEl$$1() { + var el = this.options_.tag; + + // Check if this browser supports moving the element into the box. + // On the iPhone video will break if you move the element, + // So we have to create a brand new element. + // If we ingested the player div, we do not need to move the media element. + if (!el || !(this.options_.playerElIngest || this.movingMediaElementInDOM)) { + + // If the original tag is still there, clone and remove it. + if (el) { + var clone = el.cloneNode(true); + + if (el.parentNode) { + el.parentNode.insertBefore(clone, el); + } + Html5.disposeMediaElement(el); + el = clone; + } else { + el = document_1.createElement('video'); + + // determine if native controls should be used + var tagAttributes = this.options_.tag && getAttributes(this.options_.tag); + var attributes = mergeOptions({}, tagAttributes); + + if (!TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) { + delete attributes.controls; + } + + setAttributes(el, assign(attributes, { + id: this.options_.techId, + class: 'vjs-tech' + })); + } + + el.playerId = this.options_.playerId; + } + + if (typeof this.options_.preload !== 'undefined') { + setAttribute(el, 'preload', this.options_.preload); + } + + // Update specific tag settings, in case they were overridden + // `autoplay` has to be *last* so that `muted` and `playsinline` are present + // when iOS/Safari or other browsers attempt to autoplay. + var settingsAttrs = ['loop', 'muted', 'playsinline', 'autoplay']; + + for (var i = 0; i < settingsAttrs.length; i++) { + var attr = settingsAttrs[i]; + var value = this.options_[attr]; + + if (typeof value !== 'undefined') { + if (value) { + setAttribute(el, attr, attr); + } else { + removeAttribute(el, attr); + } + el[attr] = value; + } + } + + return el; + }; + + /** + * This will be triggered if the loadstart event has already fired, before videojs was + * ready. Two known examples of when this can happen are: + * 1. If we're loading the playback object after it has started loading + * 2. The media is already playing the (often with autoplay on) then + * + * This function will fire another loadstart so that videojs can catchup. + * + * @fires Tech#loadstart + * + * @return {undefined} + * returns nothing. + */ + + + Html5.prototype.handleLateInit_ = function handleLateInit_(el) { + if (el.networkState === 0 || el.networkState === 3) { + // The video element hasn't started loading the source yet + // or didn't find a source + return; + } + + if (el.readyState === 0) { + // NetworkState is set synchronously BUT loadstart is fired at the + // end of the current stack, usually before setInterval(fn, 0). + // So at this point we know loadstart may have already fired or is + // about to fire, and either way the player hasn't seen it yet. + // We don't want to fire loadstart prematurely here and cause a + // double loadstart so we'll wait and see if it happens between now + // and the next loop, and fire it if not. + // HOWEVER, we also want to make sure it fires before loadedmetadata + // which could also happen between now and the next loop, so we'll + // watch for that also. + var loadstartFired = false; + var setLoadstartFired = function setLoadstartFired() { + loadstartFired = true; + }; + + this.on('loadstart', setLoadstartFired); + + var triggerLoadstart = function triggerLoadstart() { + // We did miss the original loadstart. Make sure the player + // sees loadstart before loadedmetadata + if (!loadstartFired) { + this.trigger('loadstart'); + } + }; + + this.on('loadedmetadata', triggerLoadstart); + + this.ready(function () { + this.off('loadstart', setLoadstartFired); + this.off('loadedmetadata', triggerLoadstart); + + if (!loadstartFired) { + // We did miss the original native loadstart. Fire it now. + this.trigger('loadstart'); + } + }); + + return; + } + + // From here on we know that loadstart already fired and we missed it. + // The other readyState events aren't as much of a problem if we double + // them, so not going to go to as much trouble as loadstart to prevent + // that unless we find reason to. + var eventsToTrigger = ['loadstart']; + + // loadedmetadata: newly equal to HAVE_METADATA (1) or greater + eventsToTrigger.push('loadedmetadata'); + + // loadeddata: newly increased to HAVE_CURRENT_DATA (2) or greater + if (el.readyState >= 2) { + eventsToTrigger.push('loadeddata'); + } + + // canplay: newly increased to HAVE_FUTURE_DATA (3) or greater + if (el.readyState >= 3) { + eventsToTrigger.push('canplay'); + } + + // canplaythrough: newly equal to HAVE_ENOUGH_DATA (4) + if (el.readyState >= 4) { + eventsToTrigger.push('canplaythrough'); + } + + // We still need to give the player time to add event listeners + this.ready(function () { + eventsToTrigger.forEach(function (type) { + this.trigger(type); + }, this); + }); + }; + + /** + * Set current time for the `HTML5` tech. + * + * @param {number} seconds + * Set the current time of the media to this. + */ + + + Html5.prototype.setCurrentTime = function setCurrentTime(seconds) { + try { + this.el_.currentTime = seconds; + } catch (e) { + log$1(e, 'Video is not ready. (Video.js)'); + // this.warning(VideoJS.warnings.videoNotReady); + } + }; + + /** + * Get the current duration of the HTML5 media element. + * + * @return {number} + * The duration of the media or 0 if there is no duration. + */ + + + Html5.prototype.duration = function duration() { + var _this5 = this; + + // Android Chrome will report duration as Infinity for VOD HLS until after + // playback has started, which triggers the live display erroneously. + // Return NaN if playback has not started and trigger a durationupdate once + // the duration can be reliably known. + if (this.el_.duration === Infinity && IS_ANDROID && IS_CHROME && this.el_.currentTime === 0) { + // Wait for the first `timeupdate` with currentTime > 0 - there may be + // several with 0 + var checkProgress = function checkProgress() { + if (_this5.el_.currentTime > 0) { + // Trigger durationchange for genuinely live video + if (_this5.el_.duration === Infinity) { + _this5.trigger('durationchange'); + } + _this5.off('timeupdate', checkProgress); + } + }; + + this.on('timeupdate', checkProgress); + return NaN; + } + return this.el_.duration || NaN; + }; + + /** + * Get the current width of the HTML5 media element. + * + * @return {number} + * The width of the HTML5 media element. + */ + + + Html5.prototype.width = function width() { + return this.el_.offsetWidth; + }; + + /** + * Get the current height of the HTML5 media element. + * + * @return {number} + * The height of the HTML5 media element. + */ + + + Html5.prototype.height = function height() { + return this.el_.offsetHeight; + }; + + /** + * Proxy iOS `webkitbeginfullscreen` and `webkitendfullscreen` into + * `fullscreenchange` event. + * + * @private + * @fires fullscreenchange + * @listens webkitendfullscreen + * @listens webkitbeginfullscreen + * @listens webkitbeginfullscreen + */ + + + Html5.prototype.proxyWebkitFullscreen_ = function proxyWebkitFullscreen_() { + var _this6 = this; + + if (!('webkitDisplayingFullscreen' in this.el_)) { + return; + } + + var endFn = function endFn() { + this.trigger('fullscreenchange', {isFullscreen: false}); + }; + + var beginFn = function beginFn() { + if ('webkitPresentationMode' in this.el_ && this.el_.webkitPresentationMode !== 'picture-in-picture') { + this.one('webkitendfullscreen', endFn); + + this.trigger('fullscreenchange', {isFullscreen: true}); + } + }; + + this.on('webkitbeginfullscreen', beginFn); + this.on('dispose', function () { + _this6.off('webkitbeginfullscreen', beginFn); + _this6.off('webkitendfullscreen', endFn); + }); + }; + + /** + * Check if fullscreen is supported on the current playback device. + * + * @return {boolean} + * - True if fullscreen is supported. + * - False if fullscreen is not supported. + */ + + + Html5.prototype.supportsFullScreen = function supportsFullScreen() { + if (typeof this.el_.webkitEnterFullScreen === 'function') { + var userAgent = window_1.navigator && window_1.navigator.userAgent || ''; + + // Seems to be broken in Chromium/Chrome && Safari in Leopard + if (/Android/.test(userAgent) || !/Chrome|Mac OS X 10.5/.test(userAgent)) { + return true; + } + } + return false; + }; + + /** + * Request that the `HTML5` Tech enter fullscreen. + */ + + + Html5.prototype.enterFullScreen = function enterFullScreen() { + var video = this.el_; + + if (video.paused && video.networkState <= video.HAVE_METADATA) { + // attempt to prime the video element for programmatic access + // this isn't necessary on the desktop but shouldn't hurt + this.el_.play(); + + // playing and pausing synchronously during the transition to fullscreen + // can get iOS ~6.1 devices into a playOld/pause loop + this.setTimeout(function () { + video.pause(); + video.webkitEnterFullScreen(); + }, 0); + } else { + video.webkitEnterFullScreen(); + } + }; + + /** + * Request that the `HTML5` Tech exit fullscreen. + */ + + + Html5.prototype.exitFullScreen = function exitFullScreen() { + this.el_.webkitExitFullScreen(); + }; + + /** + * A getter/setter for the `Html5` Tech's source object. + * > Note: Please use {@link Html5#setSource} + * + * @param {Tech~SourceObject} [src] + * The source object you want to set on the `HTML5` techs element. + * + * @return {Tech~SourceObject|undefined} + * - The current source object when a source is not passed in. + * - undefined when setting + * + * @deprecated Since version 5. + */ + + + Html5.prototype.src = function src(_src) { + if (_src === undefined) { + return this.el_.src; + } + + // Setting src through `src` instead of `setSrc` will be deprecated + this.setSrc(_src); + }; + + /** + * Reset the tech by removing all sources and then calling + * {@link Html5.resetMediaElement}. + */ + + + Html5.prototype.reset = function reset() { + Html5.resetMediaElement(this.el_); + }; + + /** + * Get the current source on the `HTML5` Tech. Falls back to returning the source from + * the HTML5 media element. + * + * @return {Tech~SourceObject} + * The current source object from the HTML5 tech. With a fallback to the + * elements source. + */ + + + Html5.prototype.currentSrc = function currentSrc() { + if (this.currentSource_) { + return this.currentSource_.src; + } + return this.el_.currentSrc; + }; + + /** + * Set controls attribute for the HTML5 media Element. + * + * @param {string} val + * Value to set the controls attribute to + */ + + + Html5.prototype.setControls = function setControls(val) { + this.el_.controls = !!val; + }; + + /** + * Create and returns a remote {@link TextTrack} object. + * + * @param {string} kind + * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata) + * + * @param {string} [label] + * Label to identify the text track + * + * @param {string} [language] + * Two letter language abbreviation + * + * @return {TextTrack} + * The TextTrack that gets created. + */ + + + Html5.prototype.addTextTrack = function addTextTrack(kind, label, language) { + if (!this.featuresNativeTextTracks) { + return _Tech.prototype.addTextTrack.call(this, kind, label, language); + } + + return this.el_.addTextTrack(kind, label, language); + }; + + /** + * Creates either native TextTrack or an emulated TextTrack depending + * on the value of `featuresNativeTextTracks` + * + * @param {Object} options + * The object should contain the options to initialize the TextTrack with. + * + * @param {string} [options.kind] + * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata). + * + * @param {string} [options.label] + * Label to identify the text track + * + * @param {string} [options.language] + * Two letter language abbreviation. + * + * @param {boolean} [options.default] + * Default this track to on. + * + * @param {string} [options.id] + * The internal id to assign this track. + * + * @param {string} [options.src] + * A source url for the track. + * + * @return {HTMLTrackElement} + * The track element that gets created. + */ + + + Html5.prototype.createRemoteTextTrack = function createRemoteTextTrack(options) { + if (!this.featuresNativeTextTracks) { + return _Tech.prototype.createRemoteTextTrack.call(this, options); + } + var htmlTrackElement = document_1.createElement('track'); + + if (options.kind) { + htmlTrackElement.kind = options.kind; + } + if (options.label) { + htmlTrackElement.label = options.label; + } + if (options.language || options.srclang) { + htmlTrackElement.srclang = options.language || options.srclang; + } + if (options.default) { + htmlTrackElement.default = options.default; + } + if (options.id) { + htmlTrackElement.id = options.id; + } + if (options.src) { + htmlTrackElement.src = options.src; + } + + return htmlTrackElement; + }; + + /** + * Creates a remote text track object and returns an html track element. + * + * @param {Object} options The object should contain values for + * kind, language, label, and src (location of the WebVTT file) + * @param {Boolean} [manualCleanup=true] if set to false, the TextTrack will be + * automatically removed from the video element whenever the source changes + * @return {HTMLTrackElement} An Html Track Element. + * This can be an emulated {@link HTMLTrackElement} or a native one. + * @deprecated The default value of the "manualCleanup" parameter will default + * to "false" in upcoming versions of Video.js + */ + + + Html5.prototype.addRemoteTextTrack = function addRemoteTextTrack(options, manualCleanup) { + var htmlTrackElement = _Tech.prototype.addRemoteTextTrack.call(this, options, manualCleanup); + + if (this.featuresNativeTextTracks) { + this.el().appendChild(htmlTrackElement); + } + + return htmlTrackElement; + }; + + /** + * Remove remote `TextTrack` from `TextTrackList` object + * + * @param {TextTrack} track + * `TextTrack` object to remove + */ + + + Html5.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) { + _Tech.prototype.removeRemoteTextTrack.call(this, track); + + if (this.featuresNativeTextTracks) { + var tracks = this.$$('track'); + + var i = tracks.length; + + while (i--) { + if (track === tracks[i] || track === tracks[i].track) { + this.el().removeChild(tracks[i]); + } + } + } + }; + + /** + * Gets available media playback quality metrics as specified by the W3C's Media + * Playback Quality API. + * + * @see [Spec]{@link https://wicg.github.io/media-playback-quality} + * + * @return {Object} + * An object with supported media playback quality metrics + */ + + + Html5.prototype.getVideoPlaybackQuality = function getVideoPlaybackQuality() { + if (typeof this.el().getVideoPlaybackQuality === 'function') { + return this.el().getVideoPlaybackQuality(); + } + + var videoPlaybackQuality = {}; + + if (typeof this.el().webkitDroppedFrameCount !== 'undefined' && typeof this.el().webkitDecodedFrameCount !== 'undefined') { + videoPlaybackQuality.droppedVideoFrames = this.el().webkitDroppedFrameCount; + videoPlaybackQuality.totalVideoFrames = this.el().webkitDecodedFrameCount; + } + + if (window_1.performance && typeof window_1.performance.now === 'function') { + videoPlaybackQuality.creationTime = window_1.performance.now(); + } else if (window_1.performance && window_1.performance.timing && typeof window_1.performance.timing.navigationStart === 'number') { + videoPlaybackQuality.creationTime = window_1.Date.now() - window_1.performance.timing.navigationStart; + } + + return videoPlaybackQuality; + }; + + return Html5; + }(Tech); + + /* HTML5 Support Testing ---------------------------------------------------- */ + + if (isReal()) { + + /** + * Element for testing browser HTML5 media capabilities + * + * @type {Element} + * @constant + * @private + */ + Html5.TEST_VID = document_1.createElement('video'); + var track = document_1.createElement('track'); + + track.kind = 'captions'; + track.srclang = 'en'; + track.label = 'English'; + Html5.TEST_VID.appendChild(track); + } + + /** + * Check if HTML5 media is supported by this browser/device. + * + * @return {boolean} + * - True if HTML5 media is supported. + * - False if HTML5 media is not supported. + */ + Html5.isSupported = function () { + // IE with no Media Player is a LIAR! (#984) + try { + Html5.TEST_VID.volume = 0.5; + } catch (e) { + return false; + } + + return !!(Html5.TEST_VID && Html5.TEST_VID.canPlayType); + }; + + /** + * Check if the tech can support the given type + * + * @param {string} type + * The mimetype to check + * @return {string} 'probably', 'maybe', or '' (empty string) + */ + Html5.canPlayType = function (type) { + return Html5.TEST_VID.canPlayType(type); + }; + + /** + * Check if the tech can support the given source + * @param {Object} srcObj + * The source object + * @param {Object} options + * The options passed to the tech + * @return {string} 'probably', 'maybe', or '' (empty string) + */ + Html5.canPlaySource = function (srcObj, options) { + return Html5.canPlayType(srcObj.type); + }; + + /** + * Check if the volume can be changed in this browser/device. + * Volume cannot be changed in a lot of mobile devices. + * Specifically, it can't be changed from 1 on iOS. + * + * @return {boolean} + * - True if volume can be controlled + * - False otherwise + */ + Html5.canControlVolume = function () { + // IE will error if Windows Media Player not installed #3315 + try { + var volume = Html5.TEST_VID.volume; + + Html5.TEST_VID.volume = volume / 2 + 0.1; + return volume !== Html5.TEST_VID.volume; + } catch (e) { + return false; + } + }; + + /** + * Check if the playback rate can be changed in this browser/device. + * + * @return {boolean} + * - True if playback rate can be controlled + * - False otherwise + */ + Html5.canControlPlaybackRate = function () { + // Playback rate API is implemented in Android Chrome, but doesn't do anything + // https://github.com/videojs/video.js/issues/3180 + if (IS_ANDROID && IS_CHROME && CHROME_VERSION < 58) { + return false; + } + // IE will error if Windows Media Player not installed #3315 + try { + var playbackRate = Html5.TEST_VID.playbackRate; + + Html5.TEST_VID.playbackRate = playbackRate / 2 + 0.1; + return playbackRate !== Html5.TEST_VID.playbackRate; + } catch (e) { + return false; + } + }; + + /** + * Check if we can override a video/audio elements attributes, with + * Object.defineProperty. + * + * @return {boolean} + * - True if builtin attributes can be overridden + * - False otherwise + */ + Html5.canOverrideAttributes = function () { + // if we cannot overwrite the src/innerHTML property, there is no support + // iOS 7 safari for instance cannot do this. + try { + var noop = function noop() { + }; + + Object.defineProperty(document_1.createElement('video'), 'src', {get: noop, set: noop}); + Object.defineProperty(document_1.createElement('audio'), 'src', {get: noop, set: noop}); + Object.defineProperty(document_1.createElement('video'), 'innerHTML', {get: noop, set: noop}); + Object.defineProperty(document_1.createElement('audio'), 'innerHTML', {get: noop, set: noop}); + } catch (e) { + return false; + } + + return true; + }; + + /** + * Check to see if native `TextTrack`s are supported by this browser/device. + * + * @return {boolean} + * - True if native `TextTrack`s are supported. + * - False otherwise + */ + Html5.supportsNativeTextTracks = function () { + return IS_ANY_SAFARI; + }; + + /** + * Check to see if native `VideoTrack`s are supported by this browser/device + * + * @return {boolean} + * - True if native `VideoTrack`s are supported. + * - False otherwise + */ + Html5.supportsNativeVideoTracks = function () { + return !!(Html5.TEST_VID && Html5.TEST_VID.videoTracks); + }; + + /** + * Check to see if native `AudioTrack`s are supported by this browser/device + * + * @return {boolean} + * - True if native `AudioTrack`s are supported. + * - False otherwise + */ + Html5.supportsNativeAudioTracks = function () { + return !!(Html5.TEST_VID && Html5.TEST_VID.audioTracks); + }; + + /** + * An array of events available on the Html5 tech. + * + * @private + * @type {Array} + */ + Html5.Events = ['loadstart', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough', 'playing', 'waiting', 'seeking', 'seeked', 'ended', 'durationchange', 'timeupdate', 'progress', 'play', 'pause', 'ratechange', 'resize', 'volumechange']; + + /** + * Boolean indicating whether the `Tech` supports volume control. + * + * @type {boolean} + * @default {@link Html5.canControlVolume} + */ + Html5.prototype.featuresVolumeControl = Html5.canControlVolume(); + + /** + * Boolean indicating whether the `Tech` supports changing the speed at which the media + * plays. Examples: + * - Set player to playOld 2x (twice) as fast + * - Set player to playOld 0.5x (half) as fast + * + * @type {boolean} + * @default {@link Html5.canControlPlaybackRate} + */ + Html5.prototype.featuresPlaybackRate = Html5.canControlPlaybackRate(); + + /** + * Boolean indicating whether the `Tech` supports the `sourceset` event. + * + * @type {boolean} + * @default + */ + Html5.prototype.featuresSourceset = Html5.canOverrideAttributes(); + + /** + * Boolean indicating whether the `HTML5` tech currently supports the media element + * moving in the DOM. iOS breaks if you move the media element, so this is set this to + * false there. Everywhere else this should be true. + * + * @type {boolean} + * @default + */ + Html5.prototype.movingMediaElementInDOM = !IS_IOS; + + // TODO: Previous comment: No longer appears to be used. Can probably be removed. + // Is this true? + /** + * Boolean indicating whether the `HTML5` tech currently supports automatic media resize + * when going into fullscreen. + * + * @type {boolean} + * @default + */ + Html5.prototype.featuresFullscreenResize = true; + + /** + * Boolean indicating whether the `HTML5` tech currently supports the progress event. + * If this is false, manual `progress` events will be triggered instead. + * + * @type {boolean} + * @default + */ + Html5.prototype.featuresProgressEvents = true; + + /** + * Boolean indicating whether the `HTML5` tech currently supports the timeupdate event. + * If this is false, manual `timeupdate` events will be triggered instead. + * + * @default + */ + Html5.prototype.featuresTimeupdateEvents = true; + + /** + * Boolean indicating whether the `HTML5` tech currently supports native `TextTrack`s. + * + * @type {boolean} + * @default {@link Html5.supportsNativeTextTracks} + */ + Html5.prototype.featuresNativeTextTracks = Html5.supportsNativeTextTracks(); + + /** + * Boolean indicating whether the `HTML5` tech currently supports native `VideoTrack`s. + * + * @type {boolean} + * @default {@link Html5.supportsNativeVideoTracks} + */ + Html5.prototype.featuresNativeVideoTracks = Html5.supportsNativeVideoTracks(); + + /** + * Boolean indicating whether the `HTML5` tech currently supports native `AudioTrack`s. + * + * @type {boolean} + * @default {@link Html5.supportsNativeAudioTracks} + */ + Html5.prototype.featuresNativeAudioTracks = Html5.supportsNativeAudioTracks(); + + // HTML5 Feature detection and Device Fixes --------------------------------- // + var canPlayType = Html5.TEST_VID && Html5.TEST_VID.constructor.prototype.canPlayType; + var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i; + + Html5.patchCanPlayType = function () { + + // Android 4.0 and above can playOld HLS to some extent but it reports being unable to do so + // Firefox and Chrome report correctly + if (ANDROID_VERSION >= 4.0 && !IS_FIREFOX && !IS_CHROME) { + Html5.TEST_VID.constructor.prototype.canPlayType = function (type) { + if (type && mpegurlRE.test(type)) { + return 'maybe'; + } + return canPlayType.call(this, type); + }; + } + }; + + Html5.unpatchCanPlayType = function () { + var r = Html5.TEST_VID.constructor.prototype.canPlayType; + + Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType; + return r; + }; + + // by default, patch the media element + Html5.patchCanPlayType(); + + Html5.disposeMediaElement = function (el) { + if (!el) { + return; + } + + if (el.parentNode) { + el.parentNode.removeChild(el); + } + + // remove any child track or source nodes to prevent their loading + while (el.hasChildNodes()) { + el.removeChild(el.firstChild); + } + + // remove any src reference. not setting `src=''` because that causes a warning + // in firefox + el.removeAttribute('src'); + + // force the media element to update its loading state by calling load() + // however IE on Windows 7N has a bug that throws an error so need a try/catch (#793) + if (typeof el.load === 'function') { + // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473) + (function () { + try { + el.load(); + } catch (e) { + // not supported + } + })(); + } + }; + + Html5.resetMediaElement = function (el) { + if (!el) { + return; + } + + var sources = el.querySelectorAll('source'); + var i = sources.length; + + while (i--) { + el.removeChild(sources[i]); + } + + // remove any src reference. + // not setting `src=''` because that throws an error + el.removeAttribute('src'); + + if (typeof el.load === 'function') { + // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473) + (function () { + try { + el.load(); + } catch (e) { + // satisfy linter + } + })(); + } + }; + + /* Native HTML5 element property wrapping ----------------------------------- */ + // Wrap native boolean attributes with getters that check both property and attribute + // The list is as followed: + // muted, defaultMuted, autoplay, controls, loop, playsinline + [ + /** + * Get the value of `muted` from the media element. `muted` indicates + * that the volume for the media should be set to silent. This does not actually change + * the `volume` attribute. + * + * @method Html5#muted + * @return {boolean} + * - True if the value of `volume` should be ignored and the audio set to silent. + * - False if the value of `volume` should be used. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted} + */ + 'muted', + + /** + * Get the value of `defaultMuted` from the media element. `defaultMuted` indicates + * whether the media should start muted or not. Only changes the default state of the + * media. `muted` and `defaultMuted` can have different values. {@link Html5#muted} indicates the + * current state. + * + * @method Html5#defaultMuted + * @return {boolean} + * - The value of `defaultMuted` from the media element. + * - True indicates that the media should start muted. + * - False indicates that the media should not start muted + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted} + */ + 'defaultMuted', + + /** + * Get the value of `autoplay` from the media element. `autoplay` indicates + * that the media should start to playOld as soon as the page is ready. + * + * @method Html5#autoplay + * @return {boolean} + * - The value of `autoplay` from the media element. + * - True indicates that the media should start as soon as the page loads. + * - False indicates that the media should not start as soon as the page loads. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay} + */ + 'autoplay', + + /** + * Get the value of `controls` from the media element. `controls` indicates + * whether the native media controls should be shown or hidden. + * + * @method Html5#controls + * @return {boolean} + * - The value of `controls` from the media element. + * - True indicates that native controls should be showing. + * - False indicates that native controls should be hidden. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-controls} + */ + 'controls', + + /** + * Get the value of `loop` from the media element. `loop` indicates + * that the media should return to the start of the media and continue playing once + * it reaches the end. + * + * @method Html5#loop + * @return {boolean} + * - The value of `loop` from the media element. + * - True indicates that playback should seek back to start once + * the end of a media is reached. + * - False indicates that playback should not loop back to the start when the + * end of the media is reached. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop} + */ + 'loop', + + /** + * Get the value of `playsinline` from the media element. `playsinline` indicates + * to the browser that non-fullscreen playback is preferred when fullscreen + * playback is the native default, such as in iOS Safari. + * + * @method Html5#playsinline + * @return {boolean} + * - The value of `playsinline` from the media element. + * - True indicates that the media should playOld inline. + * - False indicates that the media should not playOld inline. + * + * @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline} + */ + 'playsinline'].forEach(function (prop) { + Html5.prototype[prop] = function () { + return this.el_[prop] || this.el_.hasAttribute(prop); + }; + }); + + // Wrap native boolean attributes with setters that set both property and attribute + // The list is as followed: + // setMuted, setDefaultMuted, setAutoplay, setLoop, setPlaysinline + // setControls is special-cased above + [ + /** + * Set the value of `muted` on the media element. `muted` indicates that the current + * audio level should be silent. + * + * @method Html5#setMuted + * @param {boolean} muted + * - True if the audio should be set to silent + * - False otherwise + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted} + */ + 'muted', + + /** + * Set the value of `defaultMuted` on the media element. `defaultMuted` indicates that the current + * audio level should be silent, but will only effect the muted level on intial playback.. + * + * @method Html5.prototype.setDefaultMuted + * @param {boolean} defaultMuted + * - True if the audio should be set to silent + * - False otherwise + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted} + */ + 'defaultMuted', + + /** + * Set the value of `autoplay` on the media element. `autoplay` indicates + * that the media should start to playOld as soon as the page is ready. + * + * @method Html5#setAutoplay + * @param {boolean} autoplay + * - True indicates that the media should start as soon as the page loads. + * - False indicates that the media should not start as soon as the page loads. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay} + */ + 'autoplay', + + /** + * Set the value of `loop` on the media element. `loop` indicates + * that the media should return to the start of the media and continue playing once + * it reaches the end. + * + * @method Html5#setLoop + * @param {boolean} loop + * - True indicates that playback should seek back to start once + * the end of a media is reached. + * - False indicates that playback should not loop back to the start when the + * end of the media is reached. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop} + */ + 'loop', + + /** + * Set the value of `playsinline` from the media element. `playsinline` indicates + * to the browser that non-fullscreen playback is preferred when fullscreen + * playback is the native default, such as in iOS Safari. + * + * @method Html5#setPlaysinline + * @param {boolean} playsinline + * - True indicates that the media should playOld inline. + * - False indicates that the media should not playOld inline. + * + * @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline} + */ + 'playsinline'].forEach(function (prop) { + Html5.prototype['set' + toTitleCase(prop)] = function (v) { + this.el_[prop] = v; + + if (v) { + this.el_.setAttribute(prop, prop); + } else { + this.el_.removeAttribute(prop); + } + }; + }); + + // Wrap native properties with a getter + // The list is as followed + // paused, currentTime, buffered, volume, poster, preload, error, seeking + // seekable, ended, playbackRate, defaultPlaybackRate, played, networkState + // readyState, videoWidth, videoHeight + [ + /** + * Get the value of `paused` from the media element. `paused` indicates whether the media element + * is currently paused or not. + * + * @method Html5#paused + * @return {boolean} + * The value of `paused` from the media element. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-paused} + */ + 'paused', + + /** + * Get the value of `currentTime` from the media element. `currentTime` indicates + * the current second that the media is at in playback. + * + * @method Html5#currentTime + * @return {number} + * The value of `currentTime` from the media element. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-currenttime} + */ + 'currentTime', + + /** + * Get the value of `buffered` from the media element. `buffered` is a `TimeRange` + * object that represents the parts of the media that are already downloaded and + * available for playback. + * + * @method Html5#buffered + * @return {TimeRange} + * The value of `buffered` from the media element. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-buffered} + */ + 'buffered', + + /** + * Get the value of `volume` from the media element. `volume` indicates + * the current playback volume of audio for a media. `volume` will be a value from 0 + * (silent) to 1 (loudest and default). + * + * @method Html5#volume + * @return {number} + * The value of `volume` from the media element. Value will be between 0-1. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-a-volume} + */ + 'volume', + + /** + * Get the value of `poster` from the media element. `poster` indicates + * that the url of an image file that can/will be shown when no media data is available. + * + * @method Html5#poster + * @return {string} + * The value of `poster` from the media element. Value will be a url to an + * image. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-video-poster} + */ + 'poster', + + /** + * Get the value of `preload` from the media element. `preload` indicates + * what should download before the media is interacted with. It can have the following + * values: + * - none: nothing should be downloaded + * - metadata: poster and the first few frames of the media may be downloaded to get + * media dimensions and other metadata + * - auto: allow the media and metadata for the media to be downloaded before + * interaction + * + * @method Html5#preload + * @return {string} + * The value of `preload` from the media element. Will be 'none', 'metadata', + * or 'auto'. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-preload} + */ + 'preload', + + /** + * Get the value of the `error` from the media element. `error` indicates any + * MediaError that may have occurred during playback. If error returns null there is no + * current error. + * + * @method Html5#error + * @return {MediaError|null} + * The value of `error` from the media element. Will be `MediaError` if there + * is a current error and null otherwise. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-error} + */ + 'error', + + /** + * Get the value of `seeking` from the media element. `seeking` indicates whether the + * media is currently seeking to a new position or not. + * + * @method Html5#seeking + * @return {boolean} + * - The value of `seeking` from the media element. + * - True indicates that the media is currently seeking to a new position. + * - False indicates that the media is not seeking to a new position at this time. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-seeking} + */ + 'seeking', + + /** + * Get the value of `seekable` from the media element. `seekable` returns a + * `TimeRange` object indicating ranges of time that can currently be `seeked` to. + * + * @method Html5#seekable + * @return {TimeRange} + * The value of `seekable` from the media element. A `TimeRange` object + * indicating the current ranges of time that can be seeked to. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-seekable} + */ + 'seekable', + + /** + * Get the value of `ended` from the media element. `ended` indicates whether + * the media has reached the end or not. + * + * @method Html5#ended + * @return {boolean} + * - The value of `ended` from the media element. + * - True indicates that the media has ended. + * - False indicates that the media has not ended. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-ended} + */ + 'ended', + + /** + * Get the value of `playbackRate` from the media element. `playbackRate` indicates + * the rate at which the media is currently playing back. Examples: + * - if playbackRate is set to 2, media will playOld twice as fast. + * - if playbackRate is set to 0.5, media will playOld half as fast. + * + * @method Html5#playbackRate + * @return {number} + * The value of `playbackRate` from the media element. A number indicating + * the current playback speed of the media, where 1 is normal speed. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate} + */ + 'playbackRate', + + /** + * Get the value of `defaultPlaybackRate` from the media element. `defaultPlaybackRate` indicates + * the rate at which the media is currently playing back. This value will not indicate the current + * `playbackRate` after playback has started, use {@link Html5#playbackRate} for that. + * + * Examples: + * - if defaultPlaybackRate is set to 2, media will playOld twice as fast. + * - if defaultPlaybackRate is set to 0.5, media will playOld half as fast. + * + * @method Html5.prototype.defaultPlaybackRate + * @return {number} + * The value of `defaultPlaybackRate` from the media element. A number indicating + * the current playback speed of the media, where 1 is normal speed. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate} + */ + 'defaultPlaybackRate', + + /** + * Get the value of `played` from the media element. `played` returns a `TimeRange` + * object representing points in the media timeline that have been played. + * + * @method Html5#played + * @return {TimeRange} + * The value of `played` from the media element. A `TimeRange` object indicating + * the ranges of time that have been played. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-played} + */ + 'played', + + /** + * Get the value of `networkState` from the media element. `networkState` indicates + * the current network state. It returns an enumeration from the following list: + * - 0: NETWORK_EMPTY + * - 1: NETWORK_IDLE + * - 2: NETWORK_LOADING + * - 3: NETWORK_NO_SOURCE + * + * @method Html5#networkState + * @return {number} + * The value of `networkState` from the media element. This will be a number + * from the list in the description. + * + * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-networkstate} + */ + 'networkState', + + /** + * Get the value of `readyState` from the media element. `readyState` indicates + * the current state of the media element. It returns an enumeration from the + * following list: + * - 0: HAVE_NOTHING + * - 1: HAVE_METADATA + * - 2: HAVE_CURRENT_DATA + * - 3: HAVE_FUTURE_DATA + * - 4: HAVE_ENOUGH_DATA + * + * @method Html5#readyState + * @return {number} + * The value of `readyState` from the media element. This will be a number + * from the list in the description. + * + * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#ready-states} + */ + 'readyState', + + /** + * Get the value of `videoWidth` from the video element. `videoWidth` indicates + * the current width of the video in css pixels. + * + * @method Html5#videoWidth + * @return {number} + * The value of `videoWidth` from the video element. This will be a number + * in css pixels. + * + * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth} + */ + 'videoWidth', + + /** + * Get the value of `videoHeight` from the video element. `videoHeight` indicates + * the current height of the video in css pixels. + * + * @method Html5#videoHeight + * @return {number} + * The value of `videoHeight` from the video element. This will be a number + * in css pixels. + * + * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth} + */ + 'videoHeight'].forEach(function (prop) { + Html5.prototype[prop] = function () { + return this.el_[prop]; + }; + }); + + // Wrap native properties with a setter in this format: + // set + toTitleCase(name) + // The list is as follows: + // setVolume, setSrc, setPoster, setPreload, setPlaybackRate, setDefaultPlaybackRate + [ + /** + * Set the value of `volume` on the media element. `volume` indicates the current + * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and + * so on. + * + * @method Html5#setVolume + * @param {number} percentAsDecimal + * The volume percent as a decimal. Valid range is from 0-1. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-a-volume} + */ + 'volume', + + /** + * Set the value of `src` on the media element. `src` indicates the current + * {@link Tech~SourceObject} for the media. + * + * @method Html5#setSrc + * @param {Tech~SourceObject} src + * The source object to set as the current source. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-src} + */ + 'src', + + /** + * Set the value of `poster` on the media element. `poster` is the url to + * an image file that can/will be shown when no media data is available. + * + * @method Html5#setPoster + * @param {string} poster + * The url to an image that should be used as the `poster` for the media + * element. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-poster} + */ + 'poster', + + /** + * Set the value of `preload` on the media element. `preload` indicates + * what should download before the media is interacted with. It can have the following + * values: + * - none: nothing should be downloaded + * - metadata: poster and the first few frames of the media may be downloaded to get + * media dimensions and other metadata + * - auto: allow the media and metadata for the media to be downloaded before + * interaction + * + * @method Html5#setPreload + * @param {string} preload + * The value of `preload` to set on the media element. Must be 'none', 'metadata', + * or 'auto'. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-preload} + */ + 'preload', + + /** + * Set the value of `playbackRate` on the media element. `playbackRate` indicates + * the rate at which the media should playOld back. Examples: + * - if playbackRate is set to 2, media will playOld twice as fast. + * - if playbackRate is set to 0.5, media will playOld half as fast. + * + * @method Html5#setPlaybackRate + * @return {number} + * The value of `playbackRate` from the media element. A number indicating + * the current playback speed of the media, where 1 is normal speed. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate} + */ + 'playbackRate', + + /** + * Set the value of `defaultPlaybackRate` on the media element. `defaultPlaybackRate` indicates + * the rate at which the media should playOld back upon initial startup. Changing this value + * after a video has started will do nothing. Instead you should used {@link Html5#setPlaybackRate}. + * + * Example Values: + * - if playbackRate is set to 2, media will playOld twice as fast. + * - if playbackRate is set to 0.5, media will playOld half as fast. + * + * @method Html5.prototype.setDefaultPlaybackRate + * @return {number} + * The value of `defaultPlaybackRate` from the media element. A number indicating + * the current playback speed of the media, where 1 is normal speed. + * + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultplaybackrate} + */ + 'defaultPlaybackRate'].forEach(function (prop) { + Html5.prototype['set' + toTitleCase(prop)] = function (v) { + this.el_[prop] = v; + }; + }); + + // wrap native functions with a function + // The list is as follows: + // pause, load, playOld + [ + /** + * A wrapper around the media elements `pause` function. This will call the `HTML5` + * media elements `pause` function. + * + * @method Html5#pause + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-pause} + */ + 'pause', + + /** + * A wrapper around the media elements `load` function. This will call the `HTML5`s + * media element `load` function. + * + * @method Html5#load + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-load} + */ + 'load', + + /** + * A wrapper around the media elements `playOld` function. This will call the `HTML5`s + * media element `playOld` function. + * + * @method Html5#playOld + * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-play} + */ + 'play'].forEach(function (prop) { + Html5.prototype[prop] = function () { + return this.el_[prop](); + }; + }); + + Tech.withSourceHandlers(Html5); + + /** + * Native source handler for Html5, simply passes the source to the media element. + * + * @property {Tech~SourceObject} source + * The source object + * + * @property {Html5} tech + * The instance of the HTML5 tech. + */ + Html5.nativeSourceHandler = {}; + + /** + * Check if the media element can playOld the given mime type. + * + * @param {string} type + * The mimetype to check + * + * @return {string} + * 'probably', 'maybe', or '' (empty string) + */ + Html5.nativeSourceHandler.canPlayType = function (type) { + // IE without MediaPlayer throws an error (#519) + try { + return Html5.TEST_VID.canPlayType(type); + } catch (e) { + return ''; + } + }; + + /** + * Check if the media element can handle a source natively. + * + * @param {Tech~SourceObject} source + * The source object + * + * @param {Object} [options] + * Options to be passed to the tech. + * + * @return {string} + * 'probably', 'maybe', or '' (empty string). + */ + Html5.nativeSourceHandler.canHandleSource = function (source, options) { + + // If a type was provided we should rely on that + if (source.type) { + return Html5.nativeSourceHandler.canPlayType(source.type); + + // If no type, fall back to checking 'video/[EXTENSION]' + } else if (source.src) { + var ext = getFileExtension(source.src); + + return Html5.nativeSourceHandler.canPlayType('video/' + ext); + } + + return ''; + }; + + /** + * Pass the source to the native media element. + * + * @param {Tech~SourceObject} source + * The source object + * + * @param {Html5} tech + * The instance of the Html5 tech + * + * @param {Object} [options] + * The options to pass to the source + */ + Html5.nativeSourceHandler.handleSource = function (source, tech, options) { + tech.setSrc(source.src); + }; + + /** + * A noop for the native dispose function, as cleanup is not needed. + */ + Html5.nativeSourceHandler.dispose = function () { + }; + + // Register the native source handler + Html5.registerSourceHandler(Html5.nativeSourceHandler); + + Tech.registerTech('Html5', Html5); + + var _templateObject$2 = taggedTemplateLiteralLoose(['\n Using the tech directly can be dangerous. I hope you know what you\'re doing.\n See https://github.com/videojs/video.js/issues/2617 for more info.\n '], ['\n Using the tech directly can be dangerous. I hope you know what you\'re doing.\n See https://github.com/videojs/video.js/issues/2617 for more info.\n ']); + + // The following tech events are simply re-triggered + // on the player when they happen + var TECH_EVENTS_RETRIGGER = [ + /** + * Fired while the user agent is downloading media data. + * + * @event Player#progress + * @type {EventTarget~Event} + */ + /** + * Retrigger the `progress` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechProgress_ + * @fires Player#progress + * @listens Tech#progress + */ + 'progress', + + /** + * Fires when the loading of an audio/video is aborted. + * + * @event Player#abort + * @type {EventTarget~Event} + */ + /** + * Retrigger the `abort` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechAbort_ + * @fires Player#abort + * @listens Tech#abort + */ + 'abort', + + /** + * Fires when the browser is intentionally not getting media data. + * + * @event Player#suspend + * @type {EventTarget~Event} + */ + /** + * Retrigger the `suspend` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechSuspend_ + * @fires Player#suspend + * @listens Tech#suspend + */ + 'suspend', + + /** + * Fires when the current playlist is empty. + * + * @event Player#emptied + * @type {EventTarget~Event} + */ + /** + * Retrigger the `emptied` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechEmptied_ + * @fires Player#emptied + * @listens Tech#emptied + */ + 'emptied', + /** + * Fires when the browser is trying to get media data, but data is not available. + * + * @event Player#stalled + * @type {EventTarget~Event} + */ + /** + * Retrigger the `stalled` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechStalled_ + * @fires Player#stalled + * @listens Tech#stalled + */ + 'stalled', + + /** + * Fires when the browser has loaded meta data for the audio/video. + * + * @event Player#loadedmetadata + * @type {EventTarget~Event} + */ + /** + * Retrigger the `stalled` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechLoadedmetadata_ + * @fires Player#loadedmetadata + * @listens Tech#loadedmetadata + */ + 'loadedmetadata', + + /** + * Fires when the browser has loaded the current frame of the audio/video. + * + * @event Player#loadeddata + * @type {event} + */ + /** + * Retrigger the `loadeddata` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechLoaddeddata_ + * @fires Player#loadeddata + * @listens Tech#loadeddata + */ + 'loadeddata', + + /** + * Fires when the current playback position has changed. + * + * @event Player#timeupdate + * @type {event} + */ + /** + * Retrigger the `timeupdate` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechTimeUpdate_ + * @fires Player#timeupdate + * @listens Tech#timeupdate + */ + 'timeupdate', + + /** + * Fires when the video's intrinsic dimensions change + * + * @event Player#resize + * @type {event} + */ + /** + * Retrigger the `resize` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechResize_ + * @fires Player#resize + * @listens Tech#resize + */ + 'resize', + + /** + * Fires when the volume has been changed + * + * @event Player#volumechange + * @type {event} + */ + /** + * Retrigger the `volumechange` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechVolumechange_ + * @fires Player#volumechange + * @listens Tech#volumechange + */ + 'volumechange', + + /** + * Fires when the text track has been changed + * + * @event Player#texttrackchange + * @type {event} + */ + /** + * Retrigger the `texttrackchange` event that was triggered by the {@link Tech}. + * + * @private + * @method Player#handleTechTexttrackchange_ + * @fires Player#texttrackchange + * @listens Tech#texttrackchange + */ + 'texttrackchange']; + + // events to queue when playback rate is zero + // this is a hash for the sole purpose of mapping non-camel-cased event names + // to camel-cased function names + var TECH_EVENTS_QUEUE = { + canplay: 'CanPlay', + canplaythrough: 'CanPlayThrough', + playing: 'Playing', + seeked: 'Seeked' + }; + + /** + * An instance of the `Player` class is created when any of the Video.js setup methods + * are used to initialize a video. + * + * After an instance has been created it can be accessed globally in two ways: + * 1. By calling `videojs('example_video_1');` + * 2. By using it directly via `videojs.players.example_video_1;` + * + * @extends Component + */ + + var Player = function (_Component) { + inherits(Player, _Component); + + /** + * Create an instance of this class. + * + * @param {Element} tag + * The original video DOM element used for configuring options. + * + * @param {Object} [options] + * Object of option names and values. + * + * @param {Component~ReadyCallback} [ready] + * Ready callback function. + */ + function Player(tag, options, ready) { + classCallCheck(this, Player); + + // Make sure tag ID exists + tag.id = tag.id || options.id || 'vjs_video_' + newGUID(); + + // Set Options + // The options argument overrides options set in the video tag + // which overrides globally set options. + // This latter part coincides with the load order + // (tag must exist before Player) + options = assign(Player.getTagSettings(tag), options); + + // Delay the initialization of children because we need to set up + // player properties first, and can't use `this` before `super()` + options.initChildren = false; + + // Same with creating the element + options.createEl = false; + + // don't auto mixin the evented mixin + options.evented = false; + + // we don't want the player to report touch activity on itself + // see enableTouchActivity in Component + options.reportTouchActivity = false; + + // If language is not set, get the closest lang attribute + if (!options.language) { + if (typeof tag.closest === 'function') { + var closest = tag.closest('[lang]'); + + if (closest && closest.getAttribute) { + options.language = closest.getAttribute('lang'); + } + } else { + var element = tag; + + while (element && element.nodeType === 1) { + if (getAttributes(element).hasOwnProperty('lang')) { + options.language = element.getAttribute('lang'); + break; + } + element = element.parentNode; + } + } + } + + // Run base component initializing with new options + + // Tracks when a tech changes the poster + var _this = possibleConstructorReturn(this, _Component.call(this, null, options, ready)); + + _this.isPosterFromTech_ = false; + + // Holds callback info that gets queued when playback rate is zero + // and a seek is happening + _this.queuedCallbacks_ = []; + + // Turn off API access because we're loading a new tech that might load asynchronously + _this.isReady_ = false; + + // Init state hasStarted_ + _this.hasStarted_ = false; + + // Init state userActive_ + _this.userActive_ = false; + + // if the global option object was accidentally blown away by + // someone, bail early with an informative error + if (!_this.options_ || !_this.options_.techOrder || !_this.options_.techOrder.length) { + throw new Error('No techOrder specified. Did you overwrite ' + 'videojs.options instead of just changing the ' + 'properties you want to override?'); + } + + // Store the original tag used to set options + _this.tag = tag; + + // Store the tag attributes used to restore html5 element + _this.tagAttributes = tag && getAttributes(tag); + + // Update current language + _this.language(_this.options_.language); + + // Update Supported Languages + if (options.languages) { + // Normalise player option languages to lowercase + var languagesToLower = {}; + + Object.getOwnPropertyNames(options.languages).forEach(function (name$$1) { + languagesToLower[name$$1.toLowerCase()] = options.languages[name$$1]; + }); + _this.languages_ = languagesToLower; + } else { + _this.languages_ = Player.prototype.options_.languages; + } + + // Cache for video property values. + _this.cache_ = {}; + + // Set poster + _this.poster_ = options.poster || ''; + + // Set controls + _this.controls_ = !!options.controls; + + // Set default values for lastVolume + _this.cache_.lastVolume = 1; + + // Original tag settings stored in options + // now remove immediately so native controls don't flash. + // May be turned back on by HTML5 tech if nativeControlsForTouch is true + tag.controls = false; + tag.removeAttribute('controls'); + + /* + * Store the internal state of scrubbing + * + * @private + * @return {Boolean} True if the user is scrubbing + */ + _this.scrubbing_ = false; + + _this.el_ = _this.createEl(); + + // Set default value for lastPlaybackRate + _this.cache_.lastPlaybackRate = _this.defaultPlaybackRate(); + + // Make this an evented object and use `el_` as its event bus. + evented(_this, {eventBusKey: 'el_'}); + + // We also want to pass the original player options to each component and plugin + // as well so they don't need to reach back into the player for options later. + // We also need to do another copy of this.options_ so we don't end up with + // an infinite loop. + var playerOptionsCopy = mergeOptions(_this.options_); + + // Load plugins + if (options.plugins) { + var plugins = options.plugins; + + Object.keys(plugins).forEach(function (name$$1) { + if (typeof this[name$$1] === 'function') { + this[name$$1](plugins[name$$1]); + } else { + throw new Error('plugin "' + name$$1 + '" does not exist'); + } + }, _this); + } + + _this.options_.playerOptions = playerOptionsCopy; + + _this.middleware_ = []; + + _this.initChildren(); + + // Set isAudio based on whether or not an audio tag was used + _this.isAudio(tag.nodeName.toLowerCase() === 'audio'); + + // Update controls className. Can't do this when the controls are initially + // set because the element doesn't exist yet. + if (_this.controls()) { + _this.addClass('vjs-controls-enabled'); + } else { + _this.addClass('vjs-controls-disabled'); + } + + // Set ARIA label and region role depending on player type + _this.el_.setAttribute('role', 'region'); + if (_this.isAudio()) { + _this.el_.setAttribute('aria-label', _this.localize('Audio Player')); + } else { + _this.el_.setAttribute('aria-label', _this.localize('Video Player')); + } + + if (_this.isAudio()) { + _this.addClass('vjs-audio'); + } + + if (_this.flexNotSupported_()) { + _this.addClass('vjs-no-flex'); + } + + // TODO: Make this smarter. Toggle user state between touching/mousing + // using events, since devices can have both touch and mouse events. + // if (browser.TOUCH_ENABLED) { + // this.addClass('vjs-touch-enabled'); + // } + + // iOS Safari has broken hover handling + if (!IS_IOS) { + _this.addClass('vjs-workinghover'); + } + + // Make player easily findable by ID + Player.players[_this.id_] = _this; + + // Add a major version class to aid css in plugins + var majorVersion = version.split('.')[0]; + + _this.addClass('vjs-v' + majorVersion); + + // When the player is first initialized, trigger activity so components + // like the control bar show themselves if needed + _this.userActive(true); + _this.reportUserActivity(); + + _this.one('play', _this.listenForUserActivity_); + _this.on('fullscreenchange', _this.handleFullscreenChange_); + _this.on('stageclick', _this.handleStageClick_); + + _this.changingSrc_ = false; + _this.playWaitingForReady_ = false; + _this.playOnLoadstart_ = null; + return _this; + } + + /** + * Destroys the video player and does any necessary cleanup. + * + * This is especially helpful if you are dynamically adding and removing videos + * to/from the DOM. + * + * @fires Player#dispose + */ + + + Player.prototype.dispose = function dispose() { + /** + * Called when the player is being disposed of. + * + * @event Player#dispose + * @type {EventTarget~Event} + */ + this.trigger('dispose'); + // prevent dispose from being called twice + this.off('dispose'); + + if (this.styleEl_ && this.styleEl_.parentNode) { + this.styleEl_.parentNode.removeChild(this.styleEl_); + this.styleEl_ = null; + } + + // Kill reference to this player + Player.players[this.id_] = null; + + if (this.tag && this.tag.player) { + this.tag.player = null; + } + + if (this.el_ && this.el_.player) { + this.el_.player = null; + } + + if (this.tech_) { + this.tech_.dispose(); + this.isPosterFromTech_ = false; + this.poster_ = ''; + } + + if (this.playerElIngest_) { + this.playerElIngest_ = null; + } + + if (this.tag) { + this.tag = null; + } + + clearCacheForPlayer(this); + + // the actual .el_ is removed here + _Component.prototype.dispose.call(this); + }; + + /** + * Create the `Player`'s DOM element. + * + * @return {Element} + * The DOM element that gets created. + */ + + + Player.prototype.createEl = function createEl$$1() { + var tag = this.tag; + var el = void 0; + var playerElIngest = this.playerElIngest_ = tag.parentNode && tag.parentNode.hasAttribute && tag.parentNode.hasAttribute('data-vjs-player'); + var divEmbed = this.tag.tagName.toLowerCase() === 'video-js'; + + if (playerElIngest) { + el = this.el_ = tag.parentNode; + } else if (!divEmbed) { + el = this.el_ = _Component.prototype.createEl.call(this, 'div'); + } + + // Copy over all the attributes from the tag, including ID and class + // ID will now reference player box, not the video tag + var attrs = getAttributes(tag); + + if (divEmbed) { + el = this.el_ = tag; + tag = this.tag = document_1.createElement('video'); + while (el.children.length) { + tag.appendChild(el.firstChild); + } + + if (!hasClass(el, 'video-js')) { + addClass(el, 'video-js'); + } + + el.appendChild(tag); + + playerElIngest = this.playerElIngest_ = el; + // move properties over from our custom `video-js` element + // to our new `video` element. This will move things like + // `src` or `controls` that were set via js before the player + // was initialized. + Object.keys(el).forEach(function (k) { + tag[k] = el[k]; + }); + } + + // set tabindex to -1 so we could focus on the player element + tag.setAttribute('tabindex', '-1'); + + // Remove width/height attrs from tag so CSS can make it 100% width/height + tag.removeAttribute('width'); + tag.removeAttribute('height'); + + Object.getOwnPropertyNames(attrs).forEach(function (attr) { + el.setAttribute(attr, attrs[attr]); + + if (divEmbed) { + tag.setAttribute(attr, attrs[attr]); + } + }); + + // Update tag id/class for use as HTML5 playback tech + // Might think we should do this after embedding in container so .vjs-tech class + // doesn't flash 100% width/height, but class only applies with .video-js parent + tag.playerId = tag.id; + tag.id += '_html5_api'; + tag.className = 'vjs-tech'; + + // Make player findable on elements + tag.player = el.player = this; + // Default state of video is paused + this.addClass('vjs-paused'); + + // Add a style element in the player that we'll use to set the width/height + // of the player in a way that's still overrideable by CSS, just like the + // video element + if (window_1.VIDEOJS_NO_DYNAMIC_STYLE !== true) { + this.styleEl_ = createStyleElement('vjs-styles-dimensions'); + var defaultsStyleEl = $('.vjs-styles-defaults'); + var head = $('head'); + + head.insertBefore(this.styleEl_, defaultsStyleEl ? defaultsStyleEl.nextSibling : head.firstChild); + } + + // Pass in the width/height/aspectRatio options which will update the style el + this.width(this.options_.width); + this.height(this.options_.height); + this.fluid(this.options_.fluid); + this.aspectRatio(this.options_.aspectRatio); + + // Hide any links within the video/audio tag, + // because IE doesn't hide them completely from screen readers. + var links = tag.getElementsByTagName('a'); + + for (var i = 0; i < links.length; i++) { + var linkEl = links.item(i); + + addClass(linkEl, 'vjs-hidden'); + linkEl.setAttribute('hidden', 'hidden'); + } + + // insertElFirst seems to cause the networkState to flicker from 3 to 2, so + // keep track of the original for later so we can know if the source originally failed + tag.initNetworkState_ = tag.networkState; + + // Wrap video tag in div (el/box) container + if (tag.parentNode && !playerElIngest) { + tag.parentNode.insertBefore(el, tag); + } + + // insert the tag as the first child of the player element + // then manually add it to the children array so that this.addChild + // will work properly for other components + // + // Breaks iPhone, fixed in HTML5 setup. + prependTo(tag, el); + this.children_.unshift(tag); + + // Set lang attr on player to ensure CSS :lang() in consistent with player + // if it's been set to something different to the doc + this.el_.setAttribute('lang', this.language_); + + this.el_ = el; + + return el; + }; + + /** + * A getter/setter for the `Player`'s width. Returns the player's configured value. + * To get the current width use `currentWidth()`. + * + * @param {number} [value] + * The value to set the `Player`'s width to. + * + * @return {number} + * The current width of the `Player` when getting. + */ + + + Player.prototype.width = function width(value) { + return this.dimension('width', value); + }; + + /** + * A getter/setter for the `Player`'s height. Returns the player's configured value. + * To get the current height use `currentheight()`. + * + * @param {number} [value] + * The value to set the `Player`'s heigth to. + * + * @return {number} + * The current height of the `Player` when getting. + */ + + + Player.prototype.height = function height(value) { + return this.dimension('height', value); + }; + + /** + * A getter/setter for the `Player`'s width & height. + * + * @param {string} dimension + * This string can be: + * - 'width' + * - 'height' + * + * @param {number} [value] + * Value for dimension specified in the first argument. + * + * @return {number} + * The dimension arguments value when getting (width/height). + */ + + + Player.prototype.dimension = function dimension(_dimension, value) { + var privDimension = _dimension + '_'; + + if (value === undefined) { + return this[privDimension] || 0; + } + + if (value === '') { + // If an empty string is given, reset the dimension to be automatic + this[privDimension] = undefined; + this.updateStyleEl_(); + return; + } + + var parsedVal = parseFloat(value); + + if (isNaN(parsedVal)) { + log$1.error('Improper value "' + value + '" supplied for for ' + _dimension); + return; + } + + this[privDimension] = parsedVal; + this.updateStyleEl_(); + }; + + /** + * A getter/setter/toggler for the vjs-fluid `className` on the `Player`. + * + * @param {boolean} [bool] + * - A value of true adds the class. + * - A value of false removes the class. + * - No value will toggle the fluid class. + * + * @return {boolean|undefined} + * - The value of fluid when getting. + * - `undefined` when setting. + */ + + + Player.prototype.fluid = function fluid(bool) { + if (bool === undefined) { + return !!this.fluid_; + } + + this.fluid_ = !!bool; + + if (bool) { + this.addClass('vjs-fluid'); + } else { + this.removeClass('vjs-fluid'); + } + + this.updateStyleEl_(); + }; + + /** + * Get/Set the aspect ratio + * + * @param {string} [ratio] + * Aspect ratio for player + * + * @return {string|undefined} + * returns the current aspect ratio when getting + */ + + /** + * A getter/setter for the `Player`'s aspect ratio. + * + * @param {string} [ratio] + * The value to set the `Player's aspect ratio to. + * + * @return {string|undefined} + * - The current aspect ratio of the `Player` when getting. + * - undefined when setting + */ + + + Player.prototype.aspectRatio = function aspectRatio(ratio) { + if (ratio === undefined) { + return this.aspectRatio_; + } + + // Check for width:height format + if (!/^\d+\:\d+$/.test(ratio)) { + throw new Error('Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.'); + } + this.aspectRatio_ = ratio; + + // We're assuming if you set an aspect ratio you want fluid mode, + // because in fixed mode you could calculate width and height yourself. + this.fluid(true); + + this.updateStyleEl_(); + }; + + /** + * Update styles of the `Player` element (height, width and aspect ratio). + * + * @private + * @listens Tech#loadedmetadata + */ + + + Player.prototype.updateStyleEl_ = function updateStyleEl_() { + if (window_1.VIDEOJS_NO_DYNAMIC_STYLE === true) { + var _width = typeof this.width_ === 'number' ? this.width_ : this.options_.width; + var _height = typeof this.height_ === 'number' ? this.height_ : this.options_.height; + var techEl = this.tech_ && this.tech_.el(); + + if (techEl) { + if (_width >= 0) { + techEl.width = _width; + } + if (_height >= 0) { + techEl.height = _height; + } + } + + return; + } + + var width = void 0; + var height = void 0; + var aspectRatio = void 0; + var idClass = void 0; + + // The aspect ratio is either used directly or to calculate width and height. + if (this.aspectRatio_ !== undefined && this.aspectRatio_ !== 'auto') { + // Use any aspectRatio that's been specifically set + aspectRatio = this.aspectRatio_; + } else if (this.videoWidth() > 0) { + // Otherwise try to get the aspect ratio from the video metadata + aspectRatio = this.videoWidth() + ':' + this.videoHeight(); + } else { + // Or use a default. The video element's is 2:1, but 16:9 is more common. + aspectRatio = '16:9'; + } + + // Get the ratio as a decimal we can use to calculate dimensions + var ratioParts = aspectRatio.split(':'); + var ratioMultiplier = ratioParts[1] / ratioParts[0]; + + if (this.width_ !== undefined) { + // Use any width that's been specifically set + width = this.width_; + } else if (this.height_ !== undefined) { + // Or calulate the width from the aspect ratio if a height has been set + width = this.height_ / ratioMultiplier; + } else { + // Or use the video's metadata, or use the video el's default of 300 + width = this.videoWidth() || 300; + } + + if (this.height_ !== undefined) { + // Use any height that's been specifically set + height = this.height_; + } else { + // Otherwise calculate the height from the ratio and the width + height = width * ratioMultiplier; + } + + // Ensure the CSS class is valid by starting with an alpha character + if (/^[^a-zA-Z]/.test(this.id())) { + idClass = 'dimensions-' + this.id(); + } else { + idClass = this.id() + '-dimensions'; + } + + // Ensure the right class is still on the player for the style element + this.addClass(idClass); + + setTextContent(this.styleEl_, '\n .' + idClass + ' {\n width: ' + width + 'px;\n height: ' + height + 'px;\n }\n\n .' + idClass + '.vjs-fluid {\n padding-top: ' + ratioMultiplier * 100 + '%;\n }\n '); + }; + + /** + * Load/Create an instance of playback {@link Tech} including element + * and API methods. Then append the `Tech` element in `Player` as a child. + * + * @param {string} techName + * name of the playback technology + * + * @param {string} source + * video source + * + * @private + */ + + + Player.prototype.loadTech_ = function loadTech_(techName, source) { + var _this2 = this; + + // Pause and remove current playback technology + if (this.tech_) { + this.unloadTech_(); + } + + var titleTechName = toTitleCase(techName); + var camelTechName = techName.charAt(0).toLowerCase() + techName.slice(1); + + // get rid of the HTML5 video tag as soon as we are using another tech + if (titleTechName !== 'Html5' && this.tag) { + Tech.getTech('Html5').disposeMediaElement(this.tag); + this.tag.player = null; + this.tag = null; + } + + this.techName_ = titleTechName; + + // Turn off API access because we're loading a new tech that might load asynchronously + this.isReady_ = false; + + // Grab tech-specific options from player options and add source and parent element to use. + var techOptions = { + source: source, + 'nativeControlsForTouch': this.options_.nativeControlsForTouch, + 'playerId': this.id(), + 'techId': this.id() + '_' + titleTechName + '_api', + 'autoplay': this.options_.autoplay, + 'playsinline': this.options_.playsinline, + 'preload': this.options_.preload, + 'loop': this.options_.loop, + 'muted': this.options_.muted, + 'poster': this.poster(), + 'language': this.language(), + 'playerElIngest': this.playerElIngest_ || false, + 'vtt.js': this.options_['vtt.js'], + 'canOverridePoster': !!this.options_.techCanOverridePoster, + 'enableSourceset': this.options_.enableSourceset + }; + + ALL.names.forEach(function (name$$1) { + var props = ALL[name$$1]; + + techOptions[props.getterName] = _this2[props.privateName]; + }); + + assign(techOptions, this.options_[titleTechName]); + assign(techOptions, this.options_[camelTechName]); + assign(techOptions, this.options_[techName.toLowerCase()]); + + if (this.tag) { + techOptions.tag = this.tag; + } + + if (source && source.src === this.cache_.src && this.cache_.currentTime > 0) { + techOptions.startTime = this.cache_.currentTime; + } + + // Initialize tech instance + var TechClass = Tech.getTech(techName); + + if (!TechClass) { + throw new Error('No Tech named \'' + titleTechName + '\' exists! \'' + titleTechName + '\' should be registered using videojs.registerTech()\''); + } + + this.tech_ = new TechClass(techOptions); + + // player.triggerReady is always async, so don't need this to be async + this.tech_.ready(bind(this, this.handleTechReady_), true); + + textTrackConverter.jsonToTextTracks(this.textTracksJson_ || [], this.tech_); + + // Listen to all HTML5-defined events and trigger them on the player + TECH_EVENTS_RETRIGGER.forEach(function (event) { + _this2.on(_this2.tech_, event, _this2['handleTech' + toTitleCase(event) + '_']); + }); + + Object.keys(TECH_EVENTS_QUEUE).forEach(function (event) { + _this2.on(_this2.tech_, event, function (eventObj) { + if (_this2.tech_.playbackRate() === 0 && _this2.tech_.seeking()) { + _this2.queuedCallbacks_.push({ + callback: _this2['handleTech' + TECH_EVENTS_QUEUE[event] + '_'].bind(_this2), + event: eventObj + }); + return; + } + _this2['handleTech' + TECH_EVENTS_QUEUE[event] + '_'](eventObj); + }); + }); + + this.on(this.tech_, 'loadstart', this.handleTechLoadStart_); + this.on(this.tech_, 'sourceset', this.handleTechSourceset_); + this.on(this.tech_, 'waiting', this.handleTechWaiting_); + this.on(this.tech_, 'ended', this.handleTechEnded_); + this.on(this.tech_, 'seeking', this.handleTechSeeking_); + this.on(this.tech_, 'play', this.handleTechPlay_); + this.on(this.tech_, 'firstplay', this.handleTechFirstPlay_); + this.on(this.tech_, 'pause', this.handleTechPause_); + this.on(this.tech_, 'durationchange', this.handleTechDurationChange_); + this.on(this.tech_, 'fullscreenchange', this.handleTechFullscreenChange_); + this.on(this.tech_, 'error', this.handleTechError_); + this.on(this.tech_, 'loadedmetadata', this.updateStyleEl_); + this.on(this.tech_, 'posterchange', this.handleTechPosterChange_); + this.on(this.tech_, 'textdata', this.handleTechTextData_); + this.on(this.tech_, 'ratechange', this.handleTechRateChange_); + + this.usingNativeControls(this.techGet_('controls')); + + if (this.controls() && !this.usingNativeControls()) { + this.addTechControlsListeners_(); + } + + // Add the tech element in the DOM if it was not already there + // Make sure to not insert the original video element if using Html5 + if (this.tech_.el().parentNode !== this.el() && (titleTechName !== 'Html5' || !this.tag)) { + prependTo(this.tech_.el(), this.el()); + } + + // Get rid of the original video tag reference after the first tech is loaded + if (this.tag) { + this.tag.player = null; + this.tag = null; + } + }; + + /** + * Unload and dispose of the current playback {@link Tech}. + * + * @private + */ + + + Player.prototype.unloadTech_ = function unloadTech_() { + var _this3 = this; + + // Save the current text tracks so that we can reuse the same text tracks with the next tech + ALL.names.forEach(function (name$$1) { + var props = ALL[name$$1]; + + _this3[props.privateName] = _this3[props.getterName](); + }); + this.textTracksJson_ = textTrackConverter.textTracksToJson(this.tech_); + + this.isReady_ = false; + + this.tech_.dispose(); + + this.tech_ = false; + + if (this.isPosterFromTech_) { + this.poster_ = ''; + this.trigger('posterchange'); + } + + this.isPosterFromTech_ = false; + }; + + /** + * Return a reference to the current {@link Tech}. + * It will print a warning by default about the danger of using the tech directly + * but any argument that is passed in will silence the warning. + * + * @param {*} [safety] + * Anything passed in to silence the warning + * + * @return {Tech} + * The Tech + */ + + + Player.prototype.tech = function tech(safety) { + if (safety === undefined) { + log$1.warn(tsml(_templateObject$2)); + } + + return this.tech_; + }; + + /** + * Set up click and touch listeners for the playback element + * + * - On desktops: a click on the video itself will toggle playback + * - On mobile devices: a click on the video toggles controls + * which is done by toggling the user state between active and + * inactive + * - A tap can signal that a user has become active or has become inactive + * e.g. a quick tap on an iPhone movie should reveal the controls. Another + * quick tap should hide them again (signaling the user is in an inactive + * viewing state) + * - In addition to this, we still want the user to be considered inactive after + * a few seconds of inactivity. + * + * > Note: the only part of iOS interaction we can't mimic with this setup + * is a touch and hold on the video element counting as activity in order to + * keep the controls showing, but that shouldn't be an issue. A touch and hold + * on any controls will still keep the user active + * + * @private + */ + + + Player.prototype.addTechControlsListeners_ = function addTechControlsListeners_() { + // Make sure to remove all the previous listeners in case we are called multiple times. + this.removeTechControlsListeners_(); + + // Some browsers (Chrome & IE) don't trigger a click on a flash swf, but do + // trigger mousedown/up. + // http://stackoverflow.com/questions/1444562/javascript-onclick-event-over-flash-object + // Any touch events are set to block the mousedown event from happening + this.on(this.tech_, 'mousedown', this.handleTechClick_); + + // If the controls were hidden we don't want that to change without a tap event + // so we'll check if the controls were already showing before reporting user + // activity + this.on(this.tech_, 'touchstart', this.handleTechTouchStart_); + this.on(this.tech_, 'touchmove', this.handleTechTouchMove_); + this.on(this.tech_, 'touchend', this.handleTechTouchEnd_); + + // The tap listener needs to come after the touchend listener because the tap + // listener cancels out any reportedUserActivity when setting userActive(false) + this.on(this.tech_, 'tap', this.handleTechTap_); + }; + + /** + * Remove the listeners used for click and tap controls. This is needed for + * toggling to controls disabled, where a tap/touch should do nothing. + * + * @private + */ + + + Player.prototype.removeTechControlsListeners_ = function removeTechControlsListeners_() { + // We don't want to just use `this.off()` because there might be other needed + // listeners added by techs that extend this. + this.off(this.tech_, 'tap', this.handleTechTap_); + this.off(this.tech_, 'touchstart', this.handleTechTouchStart_); + this.off(this.tech_, 'touchmove', this.handleTechTouchMove_); + this.off(this.tech_, 'touchend', this.handleTechTouchEnd_); + this.off(this.tech_, 'mousedown', this.handleTechClick_); + }; + + /** + * Player waits for the tech to be ready + * + * @private + */ + + + Player.prototype.handleTechReady_ = function handleTechReady_() { + this.triggerReady(); + + // Keep the same volume as before + if (this.cache_.volume) { + this.techCall_('setVolume', this.cache_.volume); + } + + // Look if the tech found a higher resolution poster while loading + this.handleTechPosterChange_(); + + // Update the duration if available + this.handleTechDurationChange_(); + + // Chrome and Safari both have issues with autoplay. + // In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work. + // In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays) + // This fixes both issues. Need to wait for API, so it updates displays correctly + if ((this.src() || this.currentSrc()) && this.tag && this.options_.autoplay && this.paused()) { + try { + // Chrome Fix. Fixed in Chrome v16. + delete this.tag.poster; + } catch (e) { + log$1('deleting tag.poster throws in some browsers', e); + } + } + }; + + /** + * Retrigger the `loadstart` event that was triggered by the {@link Tech}. This + * function will also trigger {@link Player#firstplay} if it is the first loadstart + * for a video. + * + * @fires Player#loadstart + * @fires Player#firstplay + * @listens Tech#loadstart + * @private + */ + + + Player.prototype.handleTechLoadStart_ = function handleTechLoadStart_() { + // TODO: Update to use `emptied` event instead. See #1277. + + this.removeClass('vjs-ended'); + this.removeClass('vjs-seeking'); + + // reset the error state + this.error(null); + + // If it's already playing we want to trigger a firstplay event now. + // The firstplay event relies on both the playOld and loadstart events + // which can happen in any order for a new source + if (!this.paused()) { + /** + * Fired when the user agent begins looking for media data + * + * @event Player#loadstart + * @type {EventTarget~Event} + */ + this.trigger('loadstart'); + this.trigger('firstplay'); + } else { + // reset the hasStarted state + this.hasStarted(false); + this.trigger('loadstart'); + } + }; + + /** + * Update the internal source caches so that we return the correct source from + * `src()`, `currentSource()`, and `currentSources()`. + * + * > Note: `currentSources` will not be updated if the source that is passed in exists + * in the current `currentSources` cache. + * + * + * @param {Tech~SourceObject} srcObj + * A string or object source to update our caches to. + */ + + + Player.prototype.updateSourceCaches_ = function updateSourceCaches_() { + var srcObj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + + + var src = srcObj; + var type = ''; + + if (typeof src !== 'string') { + src = srcObj.src; + type = srcObj.type; + } + // make sure all the caches are set to default values + // to prevent null checking + this.cache_.source = this.cache_.source || {}; + this.cache_.sources = this.cache_.sources || []; + + // try to get the type of the src that was passed in + if (src && !type) { + type = findMimetype(this, src); + } + + // update `currentSource` cache always + this.cache_.source = {src: src, type: type}; + + var matchingSources = this.cache_.sources.filter(function (s) { + return s.src && s.src === src; + }); + var sourceElSources = []; + var sourceEls = this.$$('source'); + var matchingSourceEls = []; + + for (var i = 0; i < sourceEls.length; i++) { + var sourceObj = getAttributes(sourceEls[i]); + + sourceElSources.push(sourceObj); + + if (sourceObj.src && sourceObj.src === src) { + matchingSourceEls.push(sourceObj.src); + } + } + + // if we have matching source els but not matching sources + // the current source cache is not up to date + if (matchingSourceEls.length && !matchingSources.length) { + this.cache_.sources = sourceElSources; + // if we don't have matching source or source els set the + // sources cache to the `currentSource` cache + } else if (!matchingSources.length) { + this.cache_.sources = [this.cache_.source]; + } + + // update the tech `src` cache + this.cache_.src = src; + }; + + /** + * *EXPERIMENTAL* Fired when the source is set or changed on the {@link Tech} + * causing the media element to reload. + * + * It will fire for the initial source and each subsequent source. + * This event is a custom event from Video.js and is triggered by the {@link Tech}. + * + * The event object for this event contains a `src` property that will contain the source + * that was available when the event was triggered. This is generally only necessary if Video.js + * is switching techs while the source was being changed. + * + * It is also fired when `load` is called on the player (or media element) + * because the {@link https://html.spec.whatwg.org/multipage/media.html#dom-media-load|specification for `load`} + * says that the resource selection algorithm needs to be aborted and restarted. + * In this case, it is very likely that the `src` property will be set to the + * empty string `""` to indicate we do not know what the source will be but + * that it is changing. + * + * *This event is currently still experimental and may change in minor releases.* + * __To use this, pass `enableSourceset` option to the player.__ + * + * @event Player#sourceset + * @type {EventTarget~Event} + * @prop {string} src + * The source url available when the `sourceset` was triggered. + * It will be an empty string if we cannot know what the source is + * but know that the source will change. + */ + /** + * Retrigger the `sourceset` event that was triggered by the {@link Tech}. + * + * @fires Player#sourceset + * @listens Tech#sourceset + * @private + */ + + + Player.prototype.handleTechSourceset_ = function handleTechSourceset_(event) { + var _this4 = this; + + // only update the source cache when the source + // was not updated using the player api + if (!this.changingSrc_) { + // update the source to the intial source right away + // in some cases this will be empty string + this.updateSourceCaches_(event.src); + + // if the `sourceset` `src` was an empty string + // wait for a `loadstart` to update the cache to `currentSrc`. + // If a sourceset happens before a `loadstart`, we reset the state + // as this function will be called again. + if (!event.src) { + var updateCache = function updateCache(e) { + if (e.type !== 'sourceset') { + _this4.updateSourceCaches_(_this4.techGet_('currentSrc')); + } + + _this4.tech_.off(['sourceset', 'loadstart'], updateCache); + }; + + this.tech_.one(['sourceset', 'loadstart'], updateCache); + } + } + + this.trigger({ + src: event.src, + type: 'sourceset' + }); + }; + + /** + * Add/remove the vjs-has-started class + * + * @fires Player#firstplay + * + * @param {boolean} request + * - true: adds the class + * - false: remove the class + * + * @return {boolean} + * the boolean value of hasStarted_ + */ + + + Player.prototype.hasStarted = function hasStarted(request) { + if (request === undefined) { + // act as getter, if we have no request to change + return this.hasStarted_; + } + + if (request === this.hasStarted_) { + return; + } + + this.hasStarted_ = request; + + if (this.hasStarted_) { + this.addClass('vjs-has-started'); + this.trigger('firstplay'); + } else { + this.removeClass('vjs-has-started'); + } + }; + + /** + * Fired whenever the media begins or resumes playback + * + * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-play} + * @fires Player#play + * @listens Tech#play + * @private + */ + + + Player.prototype.handleTechPlay_ = function handleTechPlay_() { + this.removeClass('vjs-ended'); + this.removeClass('vjs-paused'); + this.addClass('vjs-playing'); + + // hide the poster when the user hits playOld + this.hasStarted(true); + /** + * Triggered whenever an {@link Tech#play} event happens. Indicates that + * playback has started or resumed. + * + * @event Player#play + * @type {EventTarget~Event} + */ + this.trigger('play'); + }; + + /** + * Retrigger the `ratechange` event that was triggered by the {@link Tech}. + * + * If there were any events queued while the playback rate was zero, fire + * those events now. + * + * @private + * @method Player#handleTechRateChange_ + * @fires Player#ratechange + * @listens Tech#ratechange + */ + + + Player.prototype.handleTechRateChange_ = function handleTechRateChange_() { + if (this.tech_.playbackRate() > 0 && this.cache_.lastPlaybackRate === 0) { + this.queuedCallbacks_.forEach(function (queued) { + return queued.callback(queued.event); + }); + this.queuedCallbacks_ = []; + } + this.cache_.lastPlaybackRate = this.tech_.playbackRate(); + /** + * Fires when the playing speed of the audio/video is changed + * + * @event Player#ratechange + * @type {event} + */ + this.trigger('ratechange'); + }; + + /** + * Retrigger the `waiting` event that was triggered by the {@link Tech}. + * + * @fires Player#waiting + * @listens Tech#waiting + * @private + */ + + + Player.prototype.handleTechWaiting_ = function handleTechWaiting_() { + var _this5 = this; + + this.addClass('vjs-waiting'); + /** + * A readyState change on the DOM element has caused playback to stop. + * + * @event Player#waiting + * @type {EventTarget~Event} + */ + this.trigger('waiting'); + this.one('timeupdate', function () { + return _this5.removeClass('vjs-waiting'); + }); + }; + + /** + * Retrigger the `canplay` event that was triggered by the {@link Tech}. + * > Note: This is not consistent between browsers. See #1351 + * + * @fires Player#canplay + * @listens Tech#canplay + * @private + */ + + + Player.prototype.handleTechCanPlay_ = function handleTechCanPlay_() { + this.removeClass('vjs-waiting'); + /** + * The media has a readyState of HAVE_FUTURE_DATA or greater. + * + * @event Player#canplay + * @type {EventTarget~Event} + */ + this.trigger('canplay'); + }; + + /** + * Retrigger the `canplaythrough` event that was triggered by the {@link Tech}. + * + * @fires Player#canplaythrough + * @listens Tech#canplaythrough + * @private + */ + + + Player.prototype.handleTechCanPlayThrough_ = function handleTechCanPlayThrough_() { + this.removeClass('vjs-waiting'); + /** + * The media has a readyState of HAVE_ENOUGH_DATA or greater. This means that the + * entire media file can be played without buffering. + * + * @event Player#canplaythrough + * @type {EventTarget~Event} + */ + this.trigger('canplaythrough'); + }; + + /** + * Retrigger the `playing` event that was triggered by the {@link Tech}. + * + * @fires Player#playing + * @listens Tech#playing + * @private + */ + + + Player.prototype.handleTechPlaying_ = function handleTechPlaying_() { + this.removeClass('vjs-waiting'); + /** + * The media is no longer blocked from playback, and has started playing. + * + * @event Player#playing + * @type {EventTarget~Event} + */ + this.trigger('playing'); + }; + + /** + * Retrigger the `seeking` event that was triggered by the {@link Tech}. + * + * @fires Player#seeking + * @listens Tech#seeking + * @private + */ + + + Player.prototype.handleTechSeeking_ = function handleTechSeeking_() { + this.addClass('vjs-seeking'); + /** + * Fired whenever the player is jumping to a new time + * + * @event Player#seeking + * @type {EventTarget~Event} + */ + this.trigger('seeking'); + }; + + /** + * Retrigger the `seeked` event that was triggered by the {@link Tech}. + * + * @fires Player#seeked + * @listens Tech#seeked + * @private + */ + + + Player.prototype.handleTechSeeked_ = function handleTechSeeked_() { + this.removeClass('vjs-seeking'); + /** + * Fired when the player has finished jumping to a new time + * + * @event Player#seeked + * @type {EventTarget~Event} + */ + this.trigger('seeked'); + }; + + /** + * Retrigger the `firstplay` event that was triggered by the {@link Tech}. + * + * @fires Player#firstplay + * @listens Tech#firstplay + * @deprecated As of 6.0 firstplay event is deprecated. + * @deprecated As of 6.0 passing the `starttime` option to the player and the firstplay event are deprecated. + * @private + */ + + + Player.prototype.handleTechFirstPlay_ = function handleTechFirstPlay_() { + // If the first starttime attribute is specified + // then we will start at the given offset in seconds + if (this.options_.starttime) { + log$1.warn('Passing the `starttime` option to the player will be deprecated in 6.0'); + this.currentTime(this.options_.starttime); + } + + this.addClass('vjs-has-started'); + /** + * Fired the first time a video is played. Not part of the HLS spec, and this is + * probably not the best implementation yet, so use sparingly. If you don't have a + * reason to prevent playback, use `myPlayer.one('playOld');` instead. + * + * @event Player#firstplay + * @deprecated As of 6.0 firstplay event is deprecated. + * @type {EventTarget~Event} + */ + this.trigger('firstplay'); + }; + + /** + * Retrigger the `pause` event that was triggered by the {@link Tech}. + * + * @fires Player#pause + * @listens Tech#pause + * @private + */ + + + Player.prototype.handleTechPause_ = function handleTechPause_() { + this.removeClass('vjs-playing'); + this.addClass('vjs-paused'); + /** + * Fired whenever the media has been paused + * + * @event Player#pause + * @type {EventTarget~Event} + */ + this.trigger('pause'); + }; + + /** + * Retrigger the `ended` event that was triggered by the {@link Tech}. + * + * @fires Player#ended + * @listens Tech#ended + * @private + */ + + + Player.prototype.handleTechEnded_ = function handleTechEnded_() { + this.addClass('vjs-ended'); + if (this.options_.loop) { + this.currentTime(0); + this.play(); + } else if (!this.paused()) { + this.pause(); + } + + /** + * Fired when the end of the media resource is reached (currentTime == duration) + * + * @event Player#ended + * @type {EventTarget~Event} + */ + this.trigger('ended'); + }; + + /** + * Fired when the duration of the media resource is first known or changed + * + * @listens Tech#durationchange + * @private + */ + + + Player.prototype.handleTechDurationChange_ = function handleTechDurationChange_() { + this.duration(this.techGet_('duration')); + }; + + /** + * Handle a click on the media element to playOld/pause + * + * @param {EventTarget~Event} event + * the event that caused this function to trigger + * + * @listens Tech#mousedown + * @private + */ + + + Player.prototype.handleTechClick_ = function handleTechClick_(event) { + if (!isSingleLeftClick(event)) { + return; + } + + // When controls are disabled a click should not toggle playback because + // the click is considered a control + if (!this.controls_) { + return; + } + + if (this.paused()) { + this.play(); + } else { + this.pause(); + } + }; + + /** + * Handle a tap on the media element. It will toggle the user + * activity state, which hides and shows the controls. + * + * @listens Tech#tap + * @private + */ + + + Player.prototype.handleTechTap_ = function handleTechTap_() { + this.userActive(!this.userActive()); + }; + + /** + * Handle touch to start + * + * @listens Tech#touchstart + * @private + */ + + + Player.prototype.handleTechTouchStart_ = function handleTechTouchStart_() { + this.userWasActive = this.userActive(); + }; + + /** + * Handle touch to move + * + * @listens Tech#touchmove + * @private + */ + + + Player.prototype.handleTechTouchMove_ = function handleTechTouchMove_() { + if (this.userWasActive) { + this.reportUserActivity(); + } + }; + + /** + * Handle touch to end + * + * @param {EventTarget~Event} event + * the touchend event that triggered + * this function + * + * @listens Tech#touchend + * @private + */ + + + Player.prototype.handleTechTouchEnd_ = function handleTechTouchEnd_(event) { + // Stop the mouse events from also happening + event.preventDefault(); + }; + + /** + * Fired when the player switches in or out of fullscreen mode + * + * @private + * @listens Player#fullscreenchange + */ + + + Player.prototype.handleFullscreenChange_ = function handleFullscreenChange_() { + if (this.isFullscreen()) { + this.addClass('vjs-fullscreen'); + } else { + this.removeClass('vjs-fullscreen'); + } + }; + + /** + * native click events on the SWF aren't triggered on IE11, Win8.1RT + * use stageclick events triggered from inside the SWF instead + * + * @private + * @listens stageclick + */ + + + Player.prototype.handleStageClick_ = function handleStageClick_() { + this.reportUserActivity(); + }; + + /** + * Handle Tech Fullscreen Change + * + * @param {EventTarget~Event} event + * the fullscreenchange event that triggered this function + * + * @param {Object} data + * the data that was sent with the event + * + * @private + * @listens Tech#fullscreenchange + * @fires Player#fullscreenchange + */ + + + Player.prototype.handleTechFullscreenChange_ = function handleTechFullscreenChange_(event, data) { + if (data) { + this.isFullscreen(data.isFullscreen); + } + /** + * Fired when going in and out of fullscreen. + * + * @event Player#fullscreenchange + * @type {EventTarget~Event} + */ + this.trigger('fullscreenchange'); + }; + + /** + * Fires when an error occurred during the loading of an audio/video. + * + * @private + * @listens Tech#error + */ + + + Player.prototype.handleTechError_ = function handleTechError_() { + var error = this.tech_.error(); + + this.error(error); + }; + + /** + * Retrigger the `textdata` event that was triggered by the {@link Tech}. + * + * @fires Player#textdata + * @listens Tech#textdata + * @private + */ + + + Player.prototype.handleTechTextData_ = function handleTechTextData_() { + var data = null; + + if (arguments.length > 1) { + data = arguments[1]; + } + + /** + * Fires when we get a textdata event from tech + * + * @event Player#textdata + * @type {EventTarget~Event} + */ + this.trigger('textdata', data); + }; + + /** + * Get object for cached values. + * + * @return {Object} + * get the current object cache + */ + + + Player.prototype.getCache = function getCache() { + return this.cache_; + }; + + /** + * Pass values to the playback tech + * + * @param {string} [method] + * the method to call + * + * @param {Object} arg + * the argument to pass + * + * @private + */ + + + Player.prototype.techCall_ = function techCall_(method, arg) { + // If it's not ready yet, call method when it is + + this.ready(function () { + if (method in allowedSetters) { + return set$1(this.middleware_, this.tech_, method, arg); + } else if (method in allowedMediators) { + return mediate(this.middleware_, this.tech_, method, arg); + } + + try { + if (this.tech_) { + this.tech_[method](arg); + } + } catch (e) { + log$1(e); + throw e; + } + }, true); + }; + + /** + * Get calls can't wait for the tech, and sometimes don't need to. + * + * @param {string} method + * Tech method + * + * @return {Function|undefined} + * the method or undefined + * + * @private + */ + + + Player.prototype.techGet_ = function techGet_(method) { + if (!this.tech_ || !this.tech_.isReady_) { + return; + } + + if (method in allowedGetters) { + return get$1(this.middleware_, this.tech_, method); + } else if (method in allowedMediators) { + return mediate(this.middleware_, this.tech_, method); + } + + // Flash likes to die and reload when you hide or reposition it. + // In these cases the object methods go away and we get errors. + // When that happens we'll catch the errors and inform tech that it's not ready any more. + try { + return this.tech_[method](); + } catch (e) { + + // When building additional tech libs, an expected method may not be defined yet + if (this.tech_[method] === undefined) { + log$1('Video.js: ' + method + ' method not defined for ' + this.techName_ + ' playback technology.', e); + throw e; + } + + // When a method isn't available on the object it throws a TypeError + if (e.name === 'TypeError') { + log$1('Video.js: ' + method + ' unavailable on ' + this.techName_ + ' playback technology element.', e); + this.tech_.isReady_ = false; + throw e; + } + + // If error unknown, just log and throw + log$1(e); + throw e; + } + }; + + /** + * Attempt to begin playback at the first opportunity. + * + * @return {Promise|undefined} + * Returns a `Promise` only if the browser returns one and the player + * is ready to begin playback. For some browsers and all non-ready + * situations, this will return `undefined`. + */ + + + Player.prototype.play = function play() { + var _this6 = this; + + // If this is called while we have a playOld queued up on a loadstart, remove + // that listener to avoid getting in a potentially bad state. + if (this.playOnLoadstart_) { + this.off('loadstart', this.playOnLoadstart_); + } + + // If the player/tech is not ready, queue up another call to `playOld()` for + // when it is. This will loop back into this method for another attempt at + // playback when the tech is ready. + if (!this.isReady_) { + + // Bail out if we're already waiting for `ready`! + if (this.playWaitingForReady_) { + return; + } + + this.playWaitingForReady_ = true; + this.ready(function () { + _this6.playWaitingForReady_ = false; + silencePromise(_this6.play()); + }); + + // If the player/tech is ready and we have a source, we can attempt playback. + } else if (!this.changingSrc_ && (this.src() || this.currentSrc())) { + return this.techGet_('play'); + + // If the tech is ready, but we do not have a source, we'll need to wait + // for both the `ready` and a `loadstart` when the source is finally + // resolved by middleware and set on the player. + // + // This can happen if `playOld()` is called while changing sources or before + // one has been set on the player. + } else { + + this.playOnLoadstart_ = function () { + _this6.playOnLoadstart_ = null; + silencePromise(_this6.play()); + }; + + this.one('loadstart', this.playOnLoadstart_); + } + }; + + /** + * Pause the video playback + * + * @return {Player} + * A reference to the player object this function was called on + */ + + + Player.prototype.pause = function pause() { + this.techCall_('pause'); + }; + + /** + * Check if the player is paused or has yet to playOld + * + * @return {boolean} + * - false: if the media is currently playing + * - true: if media is not currently playing + */ + + + Player.prototype.paused = function paused() { + // The initial state of paused should be true (in Safari it's actually false) + return this.techGet_('paused') === false ? false : true; + }; + + /** + * Get a TimeRange object representing the current ranges of time that the user + * has played. + * + * @return {TimeRange} + * A time range object that represents all the increments of time that have + * been played. + */ + + + Player.prototype.played = function played() { + return this.techGet_('played') || createTimeRanges(0, 0); + }; + + /** + * Returns whether or not the user is "scrubbing". Scrubbing is + * when the user has clicked the progress bar handle and is + * dragging it along the progress bar. + * + * @param {boolean} [isScrubbing] + * whether the user is or is not scrubbing + * + * @return {boolean} + * The value of scrubbing when getting + */ + + + Player.prototype.scrubbing = function scrubbing(isScrubbing) { + if (typeof isScrubbing === 'undefined') { + return this.scrubbing_; + } + this.scrubbing_ = !!isScrubbing; + + if (isScrubbing) { + this.addClass('vjs-scrubbing'); + } else { + this.removeClass('vjs-scrubbing'); + } + }; + + /** + * Get or set the current time (in seconds) + * + * @param {number|string} [seconds] + * The time to seek to in seconds + * + * @return {number} + * - the current time in seconds when getting + */ + + + Player.prototype.currentTime = function currentTime(seconds) { + if (typeof seconds !== 'undefined') { + if (seconds < 0) { + seconds = 0; + } + this.techCall_('setCurrentTime', seconds); + return; + } + + // cache last currentTime and return. default to 0 seconds + // + // Caching the currentTime is meant to prevent a massive amount of reads on the tech's + // currentTime when scrubbing, but may not provide much performance benefit afterall. + // Should be tested. Also something has to read the actual current time or the cache will + // never get updated. + this.cache_.currentTime = this.techGet_('currentTime') || 0; + return this.cache_.currentTime; + }; + + /** + * Normally gets the length in time of the video in seconds; + * in all but the rarest use cases an argument will NOT be passed to the method + * + * > **NOTE**: The video must have started loading before the duration can be + * known, and in the case of Flash, may not be known until the video starts + * playing. + * + * @fires Player#durationchange + * + * @param {number} [seconds] + * The duration of the video to set in seconds + * + * @return {number} + * - The duration of the video in seconds when getting + */ + + + Player.prototype.duration = function duration(seconds) { + if (seconds === undefined) { + // return NaN if the duration is not known + return this.cache_.duration !== undefined ? this.cache_.duration : NaN; + } + + seconds = parseFloat(seconds); + + // Standardize on Infinity for signaling video is live + if (seconds < 0) { + seconds = Infinity; + } + + if (seconds !== this.cache_.duration) { + // Cache the last set value for optimized scrubbing (esp. Flash) + this.cache_.duration = seconds; + + if (seconds === Infinity) { + this.addClass('vjs-live'); + } else { + this.removeClass('vjs-live'); + } + /** + * @event Player#durationchange + * @type {EventTarget~Event} + */ + this.trigger('durationchange'); + } + }; + + /** + * Calculates how much time is left in the video. Not part + * of the native video API. + * + * @return {number} + * The time remaining in seconds + */ + + + Player.prototype.remainingTime = function remainingTime() { + return this.duration() - this.currentTime(); + }; + + /** + * A remaining time function that is intented to be used when + * the time is to be displayed directly to the user. + * + * @return {number} + * The rounded time remaining in seconds + */ + + + Player.prototype.remainingTimeDisplay = function remainingTimeDisplay() { + return Math.floor(this.duration()) - Math.floor(this.currentTime()); + }; + + // + // Kind of like an array of portions of the video that have been downloaded. + + /** + * Get a TimeRange object with an array of the times of the video + * that have been downloaded. If you just want the percent of the + * video that's been downloaded, use bufferedPercent. + * + * @see [Buffered Spec]{@link http://dev.w3.org/html5/spec/video.html#dom-media-buffered} + * + * @return {TimeRange} + * A mock TimeRange object (following HTML spec) + */ + + + Player.prototype.buffered = function buffered() { + var buffered = this.techGet_('buffered'); + + if (!buffered || !buffered.length) { + buffered = createTimeRanges(0, 0); + } + + return buffered; + }; + + /** + * Get the percent (as a decimal) of the video that's been downloaded. + * This method is not a part of the native HTML video API. + * + * @return {number} + * A decimal between 0 and 1 representing the percent + * that is buffered 0 being 0% and 1 being 100% + */ + + + Player.prototype.bufferedPercent = function bufferedPercent$$1() { + return bufferedPercent(this.buffered(), this.duration()); + }; + + /** + * Get the ending time of the last buffered time range + * This is used in the progress bar to encapsulate all time ranges. + * + * @return {number} + * The end of the last buffered time range + */ + + + Player.prototype.bufferedEnd = function bufferedEnd() { + var buffered = this.buffered(); + var duration = this.duration(); + var end = buffered.end(buffered.length - 1); + + if (end > duration) { + end = duration; + } + + return end; + }; + + /** + * Get or set the current volume of the media + * + * @param {number} [percentAsDecimal] + * The new volume as a decimal percent: + * - 0 is muted/0%/off + * - 1.0 is 100%/full + * - 0.5 is half volume or 50% + * + * @return {number} + * The current volume as a percent when getting + */ + + + Player.prototype.volume = function volume(percentAsDecimal) { + var vol = void 0; + + if (percentAsDecimal !== undefined) { + // Force value to between 0 and 1 + vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); + this.cache_.volume = vol; + this.techCall_('setVolume', vol); + + if (vol > 0) { + this.lastVolume_(vol); + } + + return; + } + + // Default to 1 when returning current volume. + vol = parseFloat(this.techGet_('volume')); + return isNaN(vol) ? 1 : vol; + }; + + /** + * Get the current muted state, or turn mute on or off + * + * @param {boolean} [muted] + * - true to mute + * - false to unmute + * + * @return {boolean} + * - true if mute is on and getting + * - false if mute is off and getting + */ + + + Player.prototype.muted = function muted(_muted) { + if (_muted !== undefined) { + this.techCall_('setMuted', _muted); + return; + } + return this.techGet_('muted') || false; + }; + + /** + * Get the current defaultMuted state, or turn defaultMuted on or off. defaultMuted + * indicates the state of muted on initial playback. + * + * ```js + * var myPlayer = videojs('some-player-id'); + * + * myPlayer.src("http://www.example.com/path/to/video.mp4"); + * + * // get, should be false + * console.log(myPlayer.defaultMuted()); + * // set to true + * myPlayer.defaultMuted(true); + * // get should be true + * console.log(myPlayer.defaultMuted()); + * ``` + * + * @param {boolean} [defaultMuted] + * - true to mute + * - false to unmute + * + * @return {boolean|Player} + * - true if defaultMuted is on and getting + * - false if defaultMuted is off and getting + * - A reference to the current player when setting + */ + + + Player.prototype.defaultMuted = function defaultMuted(_defaultMuted) { + if (_defaultMuted !== undefined) { + return this.techCall_('setDefaultMuted', _defaultMuted); + } + return this.techGet_('defaultMuted') || false; + }; + + /** + * Get the last volume, or set it + * + * @param {number} [percentAsDecimal] + * The new last volume as a decimal percent: + * - 0 is muted/0%/off + * - 1.0 is 100%/full + * - 0.5 is half volume or 50% + * + * @return {number} + * the current value of lastVolume as a percent when getting + * + * @private + */ + + + Player.prototype.lastVolume_ = function lastVolume_(percentAsDecimal) { + if (percentAsDecimal !== undefined && percentAsDecimal !== 0) { + this.cache_.lastVolume = percentAsDecimal; + return; + } + return this.cache_.lastVolume; + }; + + /** + * Check if current tech can support native fullscreen + * (e.g. with built in controls like iOS, so not our flash swf) + * + * @return {boolean} + * if native fullscreen is supported + */ + + + Player.prototype.supportsFullScreen = function supportsFullScreen() { + return this.techGet_('supportsFullScreen') || false; + }; + + /** + * Check if the player is in fullscreen mode or tell the player that it + * is or is not in fullscreen mode. + * + * > NOTE: As of the latest HTML5 spec, isFullscreen is no longer an official + * property and instead document.fullscreenElement is used. But isFullscreen is + * still a valuable property for internal player workings. + * + * @param {boolean} [isFS] + * Set the players current fullscreen state + * + * @return {boolean} + * - true if fullscreen is on and getting + * - false if fullscreen is off and getting + */ + + + Player.prototype.isFullscreen = function isFullscreen(isFS) { + if (isFS !== undefined) { + this.isFullscreen_ = !!isFS; + return; + } + return !!this.isFullscreen_; + }; + + /** + * Increase the size of the video to full screen + * In some browsers, full screen is not supported natively, so it enters + * "full window mode", where the video fills the browser window. + * In browsers and devices that support native full screen, sometimes the + * browser's default controls will be shown, and not the Video.js custom skin. + * This includes most mobile devices (iOS, Android) and older versions of + * Safari. + * + * @fires Player#fullscreenchange + */ + + + Player.prototype.requestFullscreen = function requestFullscreen() { + var fsApi = FullscreenApi; + + this.isFullscreen(true); + + if (fsApi.requestFullscreen) { + // the browser supports going fullscreen at the element level so we can + // take the controls fullscreen as well as the video + + // Trigger fullscreenchange event after change + // We have to specifically add this each time, and remove + // when canceling fullscreen. Otherwise if there's multiple + // players on a page, they would all be reacting to the same fullscreen + // events + on(document_1, fsApi.fullscreenchange, bind(this, function documentFullscreenChange(e) { + this.isFullscreen(document_1[fsApi.fullscreenElement]); + + // If cancelling fullscreen, remove event listener. + if (this.isFullscreen() === false) { + off(document_1, fsApi.fullscreenchange, documentFullscreenChange); + } + /** + * @event Player#fullscreenchange + * @type {EventTarget~Event} + */ + this.trigger('fullscreenchange'); + })); + + this.el_[fsApi.requestFullscreen](); + } else if (this.tech_.supportsFullScreen()) { + // we can't take the video.js controls fullscreen but we can go fullscreen + // with native controls + this.techCall_('enterFullScreen'); + } else { + // fullscreen isn't supported so we'll just stretch the video element to + // fill the viewport + this.enterFullWindow(); + /** + * @event Player#fullscreenchange + * @type {EventTarget~Event} + */ + this.trigger('fullscreenchange'); + } + }; + + /** + * Return the video to its normal size after having been in full screen mode + * + * @fires Player#fullscreenchange + */ + + + Player.prototype.exitFullscreen = function exitFullscreen() { + var fsApi = FullscreenApi; + + this.isFullscreen(false); + + // Check for browser element fullscreen support + if (fsApi.requestFullscreen) { + document_1[fsApi.exitFullscreen](); + } else if (this.tech_.supportsFullScreen()) { + this.techCall_('exitFullScreen'); + } else { + this.exitFullWindow(); + /** + * @event Player#fullscreenchange + * @type {EventTarget~Event} + */ + this.trigger('fullscreenchange'); + } + }; + + /** + * When fullscreen isn't supported we can stretch the + * video container to as wide as the browser will let us. + * + * @fires Player#enterFullWindow + */ + + + Player.prototype.enterFullWindow = function enterFullWindow() { + this.isFullWindow = true; + + // Storing original doc overflow value to return to when fullscreen is off + this.docOrigOverflow = document_1.documentElement.style.overflow; + + // Add listener for esc key to exit fullscreen + on(document_1, 'keydown', bind(this, this.fullWindowOnEscKey)); + + // Hide any scroll bars + document_1.documentElement.style.overflow = 'hidden'; + + // Apply fullscreen styles + addClass(document_1.body, 'vjs-full-window'); + + /** + * @event Player#enterFullWindow + * @type {EventTarget~Event} + */ + this.trigger('enterFullWindow'); + }; + + /** + * Check for call to either exit full window or + * full screen on ESC key + * + * @param {string} event + * Event to check for key press + */ + + + Player.prototype.fullWindowOnEscKey = function fullWindowOnEscKey(event) { + if (event.keyCode === 27) { + if (this.isFullscreen() === true) { + this.exitFullscreen(); + } else { + this.exitFullWindow(); + } + } + }; + + /** + * Exit full window + * + * @fires Player#exitFullWindow + */ + + + Player.prototype.exitFullWindow = function exitFullWindow() { + this.isFullWindow = false; + off(document_1, 'keydown', this.fullWindowOnEscKey); + + // Unhide scroll bars. + document_1.documentElement.style.overflow = this.docOrigOverflow; + + // Remove fullscreen styles + removeClass(document_1.body, 'vjs-full-window'); + + // Resize the box, controller, and poster to original sizes + // this.positionAll(); + /** + * @event Player#exitFullWindow + * @type {EventTarget~Event} + */ + this.trigger('exitFullWindow'); + }; + + /** + * Check whether the player can playOld a given mimetype + * + * @see https://www.w3.org/TR/2011/WD-html5-20110113/video.html#dom-navigator-canplaytype + * + * @param {string} type + * The mimetype to check + * + * @return {string} + * 'probably', 'maybe', or '' (empty string) + */ + + + Player.prototype.canPlayType = function canPlayType(type) { + var can = void 0; + + // Loop through each playback technology in the options order + for (var i = 0, j = this.options_.techOrder; i < j.length; i++) { + var techName = j[i]; + var tech = Tech.getTech(techName); + + // Support old behavior of techs being registered as components. + // Remove once that deprecated behavior is removed. + if (!tech) { + tech = Component.getComponent(techName); + } + + // Check if the current tech is defined before continuing + if (!tech) { + log$1.error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.'); + continue; + } + + // Check if the browser supports this technology + if (tech.isSupported()) { + can = tech.canPlayType(type); + + if (can) { + return can; + } + } + } + + return ''; + }; + + /** + * Select source based on tech-order or source-order + * Uses source-order selection if `options.sourceOrder` is truthy. Otherwise, + * defaults to tech-order selection + * + * @param {Array} sources + * The sources for a media asset + * + * @return {Object|boolean} + * Object of source and tech order or false + */ + + + Player.prototype.selectSource = function selectSource(sources) { + var _this7 = this; + + // Get only the techs specified in `techOrder` that exist and are supported by the + // current platform + var techs = this.options_.techOrder.map(function (techName) { + return [techName, Tech.getTech(techName)]; + }).filter(function (_ref) { + var techName = _ref[0], + tech = _ref[1]; + + // Check if the current tech is defined before continuing + if (tech) { + // Check if the browser supports this technology + return tech.isSupported(); + } + + log$1.error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.'); + return false; + }); + + // Iterate over each `innerArray` element once per `outerArray` element and execute + // `tester` with both. If `tester` returns a non-falsy value, exit early and return + // that value. + var findFirstPassingTechSourcePair = function findFirstPassingTechSourcePair(outerArray, innerArray, tester) { + var found = void 0; + + outerArray.some(function (outerChoice) { + return innerArray.some(function (innerChoice) { + found = tester(outerChoice, innerChoice); + + if (found) { + return true; + } + }); + }); + + return found; + }; + + var foundSourceAndTech = void 0; + var flip = function flip(fn) { + return function (a, b) { + return fn(b, a); + }; + }; + var finder = function finder(_ref2, source) { + var techName = _ref2[0], + tech = _ref2[1]; + + if (tech.canPlaySource(source, _this7.options_[techName.toLowerCase()])) { + return {source: source, tech: techName}; + } + }; + + // Depending on the truthiness of `options.sourceOrder`, we swap the order of techs and sources + // to select from them based on their priority. + if (this.options_.sourceOrder) { + // Source-first ordering + foundSourceAndTech = findFirstPassingTechSourcePair(sources, techs, flip(finder)); + } else { + // Tech-first ordering + foundSourceAndTech = findFirstPassingTechSourcePair(techs, sources, finder); + } + + return foundSourceAndTech || false; + }; + + /** + * Get or set the video source. + * + * @param {Tech~SourceObject|Tech~SourceObject[]|string} [source] + * A SourceObject, an array of SourceObjects, or a string referencing + * a URL to a media source. It is _highly recommended_ that an object + * or array of objects is used here, so that source selection + * algorithms can take the `type` into account. + * + * If not provided, this method acts as a getter. + * + * @return {string|undefined} + * If the `source` argument is missing, returns the current source + * URL. Otherwise, returns nothing/undefined. + */ + + + Player.prototype.src = function src(source) { + var _this8 = this; + + // getter usage + if (typeof source === 'undefined') { + return this.cache_.src || ''; + } + // filter out invalid sources and turn our source into + // an array of source objects + var sources = filterSource(source); + + // if a source was passed in then it is invalid because + // it was filtered to a zero length Array. So we have to + // show an error + if (!sources.length) { + this.setTimeout(function () { + this.error({code: 4, message: this.localize(this.options_.notSupportedMessage)}); + }, 0); + return; + } + + // intial sources + this.changingSrc_ = true; + + this.cache_.sources = sources; + this.updateSourceCaches_(sources[0]); + + // middlewareSource is the source after it has been changed by middleware + setSource(this, sources[0], function (middlewareSource, mws) { + _this8.middleware_ = mws; + + // since sourceSet is async we have to update the cache again after we select a source since + // the source that is selected could be out of order from the cache update above this callback. + _this8.cache_.sources = sources; + _this8.updateSourceCaches_(middlewareSource); + + var err = _this8.src_(middlewareSource); + + if (err) { + if (sources.length > 1) { + return _this8.src(sources.slice(1)); + } + + _this8.changingSrc_ = false; + + // We need to wrap this in a timeout to give folks a chance to add error event handlers + _this8.setTimeout(function () { + this.error({code: 4, message: this.localize(this.options_.notSupportedMessage)}); + }, 0); + + // we could not find an appropriate tech, but let's still notify the delegate that this is it + // this needs a better comment about why this is needed + _this8.triggerReady(); + + return; + } + + setTech(mws, _this8.tech_); + }); + }; + + /** + * Set the source object on the tech, returns a boolean that indicates whether + * there is a tech that can playOld the source or not + * + * @param {Tech~SourceObject} source + * The source object to set on the Tech + * + * @return {Boolean} + * - True if there is no Tech to playback this source + * - False otherwise + * + * @private + */ + + + Player.prototype.src_ = function src_(source) { + var _this9 = this; + + var sourceTech = this.selectSource([source]); + + if (!sourceTech) { + return true; + } + + if (!titleCaseEquals(sourceTech.tech, this.techName_)) { + this.changingSrc_ = true; + // load this technology with the chosen source + this.loadTech_(sourceTech.tech, sourceTech.source); + this.tech_.ready(function () { + _this9.changingSrc_ = false; + }); + return false; + } + + // wait until the tech is ready to set the source + // and set it synchronously if possible (#2326) + this.ready(function () { + + // The setSource tech method was added with source handlers + // so older techs won't support it + // We need to check the direct prototype for the case where subclasses + // of the tech do not support source handlers + if (this.tech_.constructor.prototype.hasOwnProperty('setSource')) { + this.techCall_('setSource', source); + } else { + this.techCall_('src', source.src); + } + + this.changingSrc_ = false; + }, true); + + return false; + }; + + /** + * Begin loading the src data. + */ + + + Player.prototype.load = function load() { + this.techCall_('load'); + }; + + /** + * Reset the player. Loads the first tech in the techOrder, + * and calls `reset` on the tech`. + */ + + + Player.prototype.reset = function reset() { + this.loadTech_(this.options_.techOrder[0], null); + this.techCall_('reset'); + }; + + /** + * Returns all of the current source objects. + * + * @return {Tech~SourceObject[]} + * The current source objects + */ + + + Player.prototype.currentSources = function currentSources() { + var source = this.currentSource(); + var sources = []; + + // assume `{}` or `{ src }` + if (Object.keys(source).length !== 0) { + sources.push(source); + } + + return this.cache_.sources || sources; + }; + + /** + * Returns the current source object. + * + * @return {Tech~SourceObject} + * The current source object + */ + + + Player.prototype.currentSource = function currentSource() { + return this.cache_.source || {}; + }; + + /** + * Returns the fully qualified URL of the current source value e.g. http://mysite.com/video.mp4 + * Can be used in conjunction with `currentType` to assist in rebuilding the current source object. + * + * @return {string} + * The current source + */ + + + Player.prototype.currentSrc = function currentSrc() { + return this.currentSource() && this.currentSource().src || ''; + }; + + /** + * Get the current source type e.g. video/mp4 + * This can allow you rebuild the current source object so that you could load the same + * source and tech later + * + * @return {string} + * The source MIME type + */ + + + Player.prototype.currentType = function currentType() { + return this.currentSource() && this.currentSource().type || ''; + }; + + /** + * Get or set the preload attribute + * + * @param {boolean} [value] + * - true means that we should preload + * - false means that we should not preload + * + * @return {string} + * The preload attribute value when getting + */ + + + Player.prototype.preload = function preload(value) { + if (value !== undefined) { + this.techCall_('setPreload', value); + this.options_.preload = value; + return; + } + return this.techGet_('preload'); + }; + + /** + * Get or set the autoplay attribute. + * + * @param {boolean} [value] + * - true means that we should autoplay + * - false means that we should not autoplay + * + * @return {string} + * The current value of autoplay when getting + */ + + + Player.prototype.autoplay = function autoplay(value) { + if (value !== undefined) { + this.techCall_('setAutoplay', value); + this.options_.autoplay = value; + return; + } + return this.techGet_('autoplay', value); + }; + + /** + * Set or unset the playsinline attribute. + * Playsinline tells the browser that non-fullscreen playback is preferred. + * + * @param {boolean} [value] + * - true means that we should try to playOld inline by default + * - false means that we should use the browser's default playback mode, + * which in most cases is inline. iOS Safari is a notable exception + * and plays fullscreen by default. + * + * @return {string|Player} + * - the current value of playsinline + * - the player when setting + * + * @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline} + */ + + + Player.prototype.playsinline = function playsinline(value) { + if (value !== undefined) { + this.techCall_('setPlaysinline', value); + this.options_.playsinline = value; + return this; + } + return this.techGet_('playsinline'); + }; + + /** + * Get or set the loop attribute on the video element. + * + * @param {boolean} [value] + * - true means that we should loop the video + * - false means that we should not loop the video + * + * @return {string} + * The current value of loop when getting + */ + + + Player.prototype.loop = function loop(value) { + if (value !== undefined) { + this.techCall_('setLoop', value); + this.options_.loop = value; + return; + } + return this.techGet_('loop'); + }; + + /** + * Get or set the poster image source url + * + * @fires Player#posterchange + * + * @param {string} [src] + * Poster image source URL + * + * @return {string} + * The current value of poster when getting + */ + + + Player.prototype.poster = function poster(src) { + if (src === undefined) { + return this.poster_; + } + + // The correct way to remove a poster is to set as an empty string + // other falsey values will throw errors + if (!src) { + src = ''; + } + + if (src === this.poster_) { + return; + } + + // update the internal poster variable + this.poster_ = src; + + // update the tech's poster + this.techCall_('setPoster', src); + + this.isPosterFromTech_ = false; + + // alert components that the poster has been set + /** + * This event fires when the poster image is changed on the player. + * + * @event Player#posterchange + * @type {EventTarget~Event} + */ + this.trigger('posterchange'); + }; + + /** + * Some techs (e.g. YouTube) can provide a poster source in an + * asynchronous way. We want the poster component to use this + * poster source so that it covers up the tech's controls. + * (YouTube's playOld button). However we only want to use this + * source if the player user hasn't set a poster through + * the normal APIs. + * + * @fires Player#posterchange + * @listens Tech#posterchange + * @private + */ + + + Player.prototype.handleTechPosterChange_ = function handleTechPosterChange_() { + if ((!this.poster_ || this.options_.techCanOverridePoster) && this.tech_ && this.tech_.poster) { + var newPoster = this.tech_.poster() || ''; + + if (newPoster !== this.poster_) { + this.poster_ = newPoster; + this.isPosterFromTech_ = true; + + // Let components know the poster has changed + this.trigger('posterchange'); + } + } + }; + + /** + * Get or set whether or not the controls are showing. + * + * @fires Player#controlsenabled + * + * @param {boolean} [bool] + * - true to turn controls on + * - false to turn controls off + * + * @return {boolean} + * The current value of controls when getting + */ + + + Player.prototype.controls = function controls(bool) { + if (bool === undefined) { + return !!this.controls_; + } + + bool = !!bool; + + // Don't trigger a change event unless it actually changed + if (this.controls_ === bool) { + return; + } + + this.controls_ = bool; + + if (this.usingNativeControls()) { + this.techCall_('setControls', bool); + } + + if (this.controls_) { + this.removeClass('vjs-controls-disabled'); + this.addClass('vjs-controls-enabled'); + /** + * @event Player#controlsenabled + * @type {EventTarget~Event} + */ + this.trigger('controlsenabled'); + if (!this.usingNativeControls()) { + this.addTechControlsListeners_(); + } + } else { + this.removeClass('vjs-controls-enabled'); + this.addClass('vjs-controls-disabled'); + /** + * @event Player#controlsdisabled + * @type {EventTarget~Event} + */ + this.trigger('controlsdisabled'); + if (!this.usingNativeControls()) { + this.removeTechControlsListeners_(); + } + } + }; + + /** + * Toggle native controls on/off. Native controls are the controls built into + * devices (e.g. default iPhone controls), Flash, or other techs + * (e.g. Vimeo Controls) + * **This should only be set by the current tech, because only the tech knows + * if it can support native controls** + * + * @fires Player#usingnativecontrols + * @fires Player#usingcustomcontrols + * + * @param {boolean} [bool] + * - true to turn native controls on + * - false to turn native controls off + * + * @return {boolean} + * The current value of native controls when getting + */ + + + Player.prototype.usingNativeControls = function usingNativeControls(bool) { + if (bool === undefined) { + return !!this.usingNativeControls_; + } + + bool = !!bool; + + // Don't trigger a change event unless it actually changed + if (this.usingNativeControls_ === bool) { + return; + } + + this.usingNativeControls_ = bool; + + if (this.usingNativeControls_) { + this.addClass('vjs-using-native-controls'); + + /** + * player is using the native device controls + * + * @event Player#usingnativecontrols + * @type {EventTarget~Event} + */ + this.trigger('usingnativecontrols'); + } else { + this.removeClass('vjs-using-native-controls'); + + /** + * player is using the custom HTML controls + * + * @event Player#usingcustomcontrols + * @type {EventTarget~Event} + */ + this.trigger('usingcustomcontrols'); + } + }; + + /** + * Set or get the current MediaError + * + * @fires Player#error + * + * @param {MediaError|string|number} [err] + * A MediaError or a string/number to be turned + * into a MediaError + * + * @return {MediaError|null} + * The current MediaError when getting (or null) + */ + + + Player.prototype.error = function error(err) { + if (err === undefined) { + return this.error_ || null; + } + + // restoring to default + if (err === null) { + this.error_ = err; + this.removeClass('vjs-error'); + if (this.errorDisplay) { + this.errorDisplay.close(); + } + return; + } + + this.error_ = new MediaError(err); + + // add the vjs-error classname to the player + this.addClass('vjs-error'); + + // log the name of the error type and any message + // IE11 logs "[object object]" and required you to expand message to see error object + log$1.error('(CODE:' + this.error_.code + ' ' + MediaError.errorTypes[this.error_.code] + ')', this.error_.message, this.error_); + + /** + * @event Player#error + * @type {EventTarget~Event} + */ + this.trigger('error'); + + return; + }; + + /** + * Report user activity + * + * @param {Object} event + * Event object + */ + + + Player.prototype.reportUserActivity = function reportUserActivity(event) { + this.userActivity_ = true; + }; + + /** + * Get/set if user is active + * + * @fires Player#useractive + * @fires Player#userinactive + * + * @param {boolean} [bool] + * - true if the user is active + * - false if the user is inactive + * + * @return {boolean} + * The current value of userActive when getting + */ + + + Player.prototype.userActive = function userActive(bool) { + if (bool === undefined) { + return this.userActive_; + } + + bool = !!bool; + + if (bool === this.userActive_) { + return; + } + + this.userActive_ = bool; + + if (this.userActive_) { + this.userActivity_ = true; + this.removeClass('vjs-user-inactive'); + this.addClass('vjs-user-active'); + /** + * @event Player#useractive + * @type {EventTarget~Event} + */ + this.trigger('useractive'); + return; + } + + // Chrome/Safari/IE have bugs where when you change the cursor it can + // trigger a mousemove event. This causes an issue when you're hiding + // the cursor when the user is inactive, and a mousemove signals user + // activity. Making it impossible to go into inactive mode. Specifically + // this happens in fullscreen when we really need to hide the cursor. + // + // When this gets resolved in ALL browsers it can be removed + // https://code.google.com/p/chromium/issues/detail?id=103041 + if (this.tech_) { + this.tech_.one('mousemove', function (e) { + e.stopPropagation(); + e.preventDefault(); + }); + } + + this.userActivity_ = false; + this.removeClass('vjs-user-active'); + this.addClass('vjs-user-inactive'); + /** + * @event Player#userinactive + * @type {EventTarget~Event} + */ + this.trigger('userinactive'); + }; + + /** + * Listen for user activity based on timeout value + * + * @private + */ + + + Player.prototype.listenForUserActivity_ = function listenForUserActivity_() { + var mouseInProgress = void 0; + var lastMoveX = void 0; + var lastMoveY = void 0; + var handleActivity = bind(this, this.reportUserActivity); + + var handleMouseMove = function handleMouseMove(e) { + // #1068 - Prevent mousemove spamming + // Chrome Bug: https://code.google.com/p/chromium/issues/detail?id=366970 + if (e.screenX !== lastMoveX || e.screenY !== lastMoveY) { + lastMoveX = e.screenX; + lastMoveY = e.screenY; + handleActivity(); + } + }; + + var handleMouseDown = function handleMouseDown() { + handleActivity(); + // For as long as the they are touching the device or have their mouse down, + // we consider them active even if they're not moving their finger or mouse. + // So we want to continue to update that they are active + this.clearInterval(mouseInProgress); + // Setting userActivity=true now and setting the interval to the same time + // as the activityCheck interval (250) should ensure we never miss the + // next activityCheck + mouseInProgress = this.setInterval(handleActivity, 250); + }; + + var handleMouseUp = function handleMouseUp(event) { + handleActivity(); + // Stop the interval that maintains activity if the mouse/touch is down + this.clearInterval(mouseInProgress); + }; + + // Any mouse movement will be considered user activity + this.on('mousedown', handleMouseDown); + this.on('mousemove', handleMouseMove); + this.on('mouseup', handleMouseUp); + + // Listen for keyboard navigation + // Shouldn't need to use inProgress interval because of key repeat + this.on('keydown', handleActivity); + this.on('keyup', handleActivity); + + // Run an interval every 250 milliseconds instead of stuffing everything into + // the mousemove/touchmove function itself, to prevent performance degradation. + // `this.reportUserActivity` simply sets this.userActivity_ to true, which + // then gets picked up by this loop + // http://ejohn.org/blog/learning-from-twitter/ + var inactivityTimeout = void 0; + + this.setInterval(function () { + // Check to see if mouse/touch activity has happened + if (!this.userActivity_) { + return; + } + + // Reset the activity tracker + this.userActivity_ = false; + + // If the user state was inactive, set the state to active + this.userActive(true); + + // Clear any existing inactivity timeout to start the timer over + this.clearTimeout(inactivityTimeout); + + var timeout = this.options_.inactivityTimeout; + + if (timeout <= 0) { + return; + } + + // In <timeout> milliseconds, if no more activity has occurred the + // user will be considered inactive + inactivityTimeout = this.setTimeout(function () { + // Protect against the case where the inactivityTimeout can trigger just + // before the next user activity is picked up by the activity check loop + // causing a flicker + if (!this.userActivity_) { + this.userActive(false); + } + }, timeout); + }, 250); + }; + + /** + * Gets or sets the current playback rate. A playback rate of + * 1.0 represents normal speed and 0.5 would indicate half-speed + * playback, for instance. + * + * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-playbackrate + * + * @param {number} [rate] + * New playback rate to set. + * + * @return {number} + * The current playback rate when getting or 1.0 + */ + + + Player.prototype.playbackRate = function playbackRate(rate) { + if (rate !== undefined) { + // NOTE: this.cache_.lastPlaybackRate is set from the tech handler + // that is registered above + this.techCall_('setPlaybackRate', rate); + return; + } + + if (this.tech_ && this.tech_.featuresPlaybackRate) { + return this.cache_.lastPlaybackRate || this.techGet_('playbackRate'); + } + return 1.0; + }; + + /** + * Gets or sets the current default playback rate. A default playback rate of + * 1.0 represents normal speed and 0.5 would indicate half-speed playback, for instance. + * defaultPlaybackRate will only represent what the initial playbackRate of a video was, not + * not the current playbackRate. + * + * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-defaultplaybackrate + * + * @param {number} [rate] + * New default playback rate to set. + * + * @return {number|Player} + * - The default playback rate when getting or 1.0 + * - the player when setting + */ + + + Player.prototype.defaultPlaybackRate = function defaultPlaybackRate(rate) { + if (rate !== undefined) { + return this.techCall_('setDefaultPlaybackRate', rate); + } + + if (this.tech_ && this.tech_.featuresPlaybackRate) { + return this.techGet_('defaultPlaybackRate'); + } + return 1.0; + }; + + /** + * Gets or sets the audio flag + * + * @param {boolean} bool + * - true signals that this is an audio player + * - false signals that this is not an audio player + * + * @return {boolean} + * The current value of isAudio when getting + */ + + + Player.prototype.isAudio = function isAudio(bool) { + if (bool !== undefined) { + this.isAudio_ = !!bool; + return; + } + + return !!this.isAudio_; + }; + + /** + * A helper method for adding a {@link TextTrack} to our + * {@link TextTrackList}. + * + * In addition to the W3C settings we allow adding additional info through options. + * + * @see http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-addtexttrack + * + * @param {string} [kind] + * the kind of TextTrack you are adding + * + * @param {string} [label] + * the label to give the TextTrack label + * + * @param {string} [language] + * the language to set on the TextTrack + * + * @return {TextTrack|undefined} + * the TextTrack that was added or undefined + * if there is no tech + */ + + + Player.prototype.addTextTrack = function addTextTrack(kind, label, language) { + if (this.tech_) { + return this.tech_.addTextTrack(kind, label, language); + } + }; + + /** + * Create a remote {@link TextTrack} and an {@link HTMLTrackElement}. It will + * automatically removed from the video element whenever the source changes, unless + * manualCleanup is set to false. + * + * @param {Object} options + * Options to pass to {@link HTMLTrackElement} during creation. See + * {@link HTMLTrackElement} for object properties that you should use. + * + * @param {boolean} [manualCleanup=true] if set to false, the TextTrack will be + * + * @return {HtmlTrackElement} + * the HTMLTrackElement that was created and added + * to the HtmlTrackElementList and the remote + * TextTrackList + * + * @deprecated The default value of the "manualCleanup" parameter will default + * to "false" in upcoming versions of Video.js + */ + + + Player.prototype.addRemoteTextTrack = function addRemoteTextTrack(options, manualCleanup) { + if (this.tech_) { + return this.tech_.addRemoteTextTrack(options, manualCleanup); + } + }; + + /** + * Remove a remote {@link TextTrack} from the respective + * {@link TextTrackList} and {@link HtmlTrackElementList}. + * + * @param {Object} track + * Remote {@link TextTrack} to remove + * + * @return {undefined} + * does not return anything + */ + + + Player.prototype.removeRemoteTextTrack = function removeRemoteTextTrack() { + var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref3$track = _ref3.track, + track = _ref3$track === undefined ? arguments[0] : _ref3$track; + + // destructure the input into an object with a track argument, defaulting to arguments[0] + // default the whole argument to an empty object if nothing was passed in + + if (this.tech_) { + return this.tech_.removeRemoteTextTrack(track); + } + }; + + /** + * Gets available media playback quality metrics as specified by the W3C's Media + * Playback Quality API. + * + * @see [Spec]{@link https://wicg.github.io/media-playback-quality} + * + * @return {Object|undefined} + * An object with supported media playback quality metrics or undefined if there + * is no tech or the tech does not support it. + */ + + + Player.prototype.getVideoPlaybackQuality = function getVideoPlaybackQuality() { + return this.techGet_('getVideoPlaybackQuality'); + }; + + /** + * Get video width + * + * @return {number} + * current video width + */ + + + Player.prototype.videoWidth = function videoWidth() { + return this.tech_ && this.tech_.videoWidth && this.tech_.videoWidth() || 0; + }; + + /** + * Get video height + * + * @return {number} + * current video height + */ + + + Player.prototype.videoHeight = function videoHeight() { + return this.tech_ && this.tech_.videoHeight && this.tech_.videoHeight() || 0; + }; + + /** + * The player's language code + * NOTE: The language should be set in the player options if you want the + * the controls to be built with a specific language. Changing the language + * later will not update controls text. + * + * @param {string} [code] + * the language code to set the player to + * + * @return {string} + * The current language code when getting + */ + + + Player.prototype.language = function language(code) { + if (code === undefined) { + return this.language_; + } + + this.language_ = String(code).toLowerCase(); + }; + + /** + * Get the player's language dictionary + * Merge every time, because a newly added plugin might call videojs.addLanguage() at any time + * Languages specified directly in the player options have precedence + * + * @return {Array} + * An array of of supported languages + */ + + + Player.prototype.languages = function languages() { + return mergeOptions(Player.prototype.options_.languages, this.languages_); + }; + + /** + * returns a JavaScript object reperesenting the current track + * information. **DOES not return it as JSON** + * + * @return {Object} + * Object representing the current of track info + */ + + + Player.prototype.toJSON = function toJSON() { + var options = mergeOptions(this.options_); + var tracks = options.tracks; + + options.tracks = []; + + for (var i = 0; i < tracks.length; i++) { + var track = tracks[i]; + + // deep merge tracks and null out player so no circular references + track = mergeOptions(track); + track.player = undefined; + options.tracks[i] = track; + } + + return options; + }; + + /** + * Creates a simple modal dialog (an instance of the {@link ModalDialog} + * component) that immediately overlays the player with arbitrary + * content and removes itself when closed. + * + * @param {string|Function|Element|Array|null} content + * Same as {@link ModalDialog#content}'s param of the same name. + * The most straight-forward usage is to provide a string or DOM + * element. + * + * @param {Object} [options] + * Extra options which will be passed on to the {@link ModalDialog}. + * + * @return {ModalDialog} + * the {@link ModalDialog} that was created + */ + + + Player.prototype.createModal = function createModal(content, options) { + var _this10 = this; + + options = options || {}; + options.content = content || ''; + + var modal = new ModalDialog(this, options); + + this.addChild(modal); + modal.on('dispose', function () { + _this10.removeChild(modal); + }); + + modal.open(); + return modal; + }; + + /** + * Gets tag settings + * + * @param {Element} tag + * The player tag + * + * @return {Object} + * An object containing all of the settings + * for a player tag + */ + + + Player.getTagSettings = function getTagSettings(tag) { + var baseOptions = { + sources: [], + tracks: [] + }; + + var tagOptions = getAttributes(tag); + var dataSetup = tagOptions['data-setup']; + + if (hasClass(tag, 'vjs-fluid')) { + tagOptions.fluid = true; + } + + // Check if data-setup attr exists. + if (dataSetup !== null) { + // Parse options JSON + // If empty string, make it a parsable json object. + var _safeParseTuple = tuple(dataSetup || '{}'), + err = _safeParseTuple[0], + data = _safeParseTuple[1]; + + if (err) { + log$1.error(err); + } + assign(tagOptions, data); + } + + assign(baseOptions, tagOptions); + + // Get tag children settings + if (tag.hasChildNodes()) { + var children = tag.childNodes; + + for (var i = 0, j = children.length; i < j; i++) { + var child = children[i]; + // Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/ + var childName = child.nodeName.toLowerCase(); + + if (childName === 'source') { + baseOptions.sources.push(getAttributes(child)); + } else if (childName === 'track') { + baseOptions.tracks.push(getAttributes(child)); + } + } + } + + return baseOptions; + }; + + /** + * Determine whether or not flexbox is supported + * + * @return {boolean} + * - true if flexbox is supported + * - false if flexbox is not supported + */ + + + Player.prototype.flexNotSupported_ = function flexNotSupported_() { + var elem = document_1.createElement('i'); + + // Note: We don't actually use flexBasis (or flexOrder), but it's one of the more + // common flex features that we can rely on when checking for flex support. + return !('flexBasis' in elem.style || 'webkitFlexBasis' in elem.style || 'mozFlexBasis' in elem.style || 'msFlexBasis' in elem.style || + // IE10-specific (2012 flex spec), available for completeness + 'msFlexOrder' in elem.style); + }; + + return Player; + }(Component); + + /** + * Get the {@link VideoTrackList} + * @link https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist + * + * @return {VideoTrackList} + * the current video track list + * + * @method Player.prototype.videoTracks + */ + + /** + * Get the {@link AudioTrackList} + * @link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist + * + * @return {AudioTrackList} + * the current audio track list + * + * @method Player.prototype.audioTracks + */ + + /** + * Get the {@link TextTrackList} + * + * @link http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks + * + * @return {TextTrackList} + * the current text track list + * + * @method Player.prototype.textTracks + */ + + /** + * Get the remote {@link TextTrackList} + * + * @return {TextTrackList} + * The current remote text track list + * + * @method Player.prototype.remoteTextTracks + */ + + /** + * Get the remote {@link HtmlTrackElementList} tracks. + * + * @return {HtmlTrackElementList} + * The current remote text track element list + * + * @method Player.prototype.remoteTextTrackEls + */ + + ALL.names.forEach(function (name$$1) { + var props = ALL[name$$1]; + + Player.prototype[props.getterName] = function () { + if (this.tech_) { + return this.tech_[props.getterName](); + } + + // if we have not yet loadTech_, we create {video,audio,text}Tracks_ + // these will be passed to the tech during loading + this[props.privateName] = this[props.privateName] || new props.ListClass(); + return this[props.privateName]; + }; + }); + + /** + * Global player list + * + * @type {Object} + */ + Player.players = {}; + + var navigator = window_1.navigator; + + /* + * Player instance options, surfaced using options + * options = Player.prototype.options_ + * Make changes in options, not here. + * + * @type {Object} + * @private + */ + Player.prototype.options_ = { + // Default order of fallback technology + techOrder: Tech.defaultTechOrder_, + + html5: {}, + flash: {}, + + // default inactivity timeout + inactivityTimeout: 2000, + + // default playback rates + playbackRates: [], + // Add playback rate selection by adding rates + // 'playbackRates': [0.5, 1, 1.5, 2], + + // Included control sets + children: ['mediaLoader', 'posterImage', 'textTrackDisplay', 'loadingSpinner', 'bigPlayButton', 'controlBar', 'errorDisplay', 'textTrackSettings', 'resizeManager'], + + language: navigator && (navigator.languages && navigator.languages[0] || navigator.userLanguage || navigator.language) || 'en', + + // locales and their language translations + languages: {}, + + // Default message to show when a video cannot be played. + notSupportedMessage: 'No compatible source was found for this media.' + }; + + [ + /** + * Returns whether or not the player is in the "ended" state. + * + * @return {Boolean} True if the player is in the ended state, false if not. + * @method Player#ended + */ + 'ended', + /** + * Returns whether or not the player is in the "seeking" state. + * + * @return {Boolean} True if the player is in the seeking state, false if not. + * @method Player#seeking + */ + 'seeking', + /** + * Returns the TimeRanges of the media that are currently available + * for seeking to. + * + * @return {TimeRanges} the seekable intervals of the media timeline + * @method Player#seekable + */ + 'seekable', + /** + * Returns the current state of network activity for the element, from + * the codes in the list below. + * - NETWORK_EMPTY (numeric value 0) + * The element has not yet been initialised. All attributes are in + * their initial states. + * - NETWORK_IDLE (numeric value 1) + * The element's resource selection algorithm is active and has + * selected a resource, but it is not actually using the network at + * this time. + * - NETWORK_LOADING (numeric value 2) + * The user agent is actively trying to download data. + * - NETWORK_NO_SOURCE (numeric value 3) + * The element's resource selection algorithm is active, but it has + * not yet found a resource to use. + * + * @see https://html.spec.whatwg.org/multipage/embedded-content.html#network-states + * @return {number} the current network activity state + * @method Player#networkState + */ + 'networkState', + /** + * Returns a value that expresses the current state of the element + * with respect to rendering the current playback position, from the + * codes in the list below. + * - HAVE_NOTHING (numeric value 0) + * No information regarding the media resource is available. + * - HAVE_METADATA (numeric value 1) + * Enough of the resource has been obtained that the duration of the + * resource is available. + * - HAVE_CURRENT_DATA (numeric value 2) + * Data for the immediate current playback position is available. + * - HAVE_FUTURE_DATA (numeric value 3) + * Data for the immediate current playback position is available, as + * well as enough data for the user agent to advance the current + * playback position in the direction of playback. + * - HAVE_ENOUGH_DATA (numeric value 4) + * The user agent estimates that enough data is available for + * playback to proceed uninterrupted. + * + * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-readystate + * @return {number} the current playback rendering state + * @method Player#readyState + */ + 'readyState'].forEach(function (fn) { + Player.prototype[fn] = function () { + return this.techGet_(fn); + }; + }); + + TECH_EVENTS_RETRIGGER.forEach(function (event) { + Player.prototype['handleTech' + toTitleCase(event) + '_'] = function () { + return this.trigger(event); + }; + }); + + /** + * Fired when the player has initial duration and dimension information + * + * @event Player#loadedmetadata + * @type {EventTarget~Event} + */ + + /** + * Fired when the player has downloaded data at the current playback position + * + * @event Player#loadeddata + * @type {EventTarget~Event} + */ + + /** + * Fired when the current playback position has changed * + * During playback this is fired every 15-250 milliseconds, depending on the + * playback technology in use. + * + * @event Player#timeupdate + * @type {EventTarget~Event} + */ + + /** + * Fired when the volume changes + * + * @event Player#volumechange + * @type {EventTarget~Event} + */ + + /** + * Reports whether or not a player has a plugin available. + * + * This does not report whether or not the plugin has ever been initialized + * on this player. For that, [usingPlugin]{@link Player#usingPlugin}. + * + * @method Player#hasPlugin + * @param {string} name + * The name of a plugin. + * + * @return {boolean} + * Whether or not this player has the requested plugin available. + */ + + /** + * Reports whether or not a player is using a plugin by name. + * + * For basic plugins, this only reports whether the plugin has _ever_ been + * initialized on this player. + * + * @method Player#usingPlugin + * @param {string} name + * The name of a plugin. + * + * @return {boolean} + * Whether or not this player is using the requested plugin. + */ + + Component.registerComponent('Player', Player); + + /** + * @file plugin.js + */ + + /** + * The base plugin name. + * + * @private + * @constant + * @type {string} + */ + var BASE_PLUGIN_NAME = 'plugin'; + + /** + * The key on which a player's active plugins cache is stored. + * + * @private + * @constant + * @type {string} + */ + var PLUGIN_CACHE_KEY = 'activePlugins_'; + + /** + * Stores registered plugins in a private space. + * + * @private + * @type {Object} + */ + var pluginStorage = {}; + + /** + * Reports whether or not a plugin has been registered. + * + * @private + * @param {string} name + * The name of a plugin. + * + * @returns {boolean} + * Whether or not the plugin has been registered. + */ + var pluginExists = function pluginExists(name) { + return pluginStorage.hasOwnProperty(name); + }; + + /** + * Get a single registered plugin by name. + * + * @private + * @param {string} name + * The name of a plugin. + * + * @returns {Function|undefined} + * The plugin (or undefined). + */ + var getPlugin = function getPlugin(name) { + return pluginExists(name) ? pluginStorage[name] : undefined; + }; + + /** + * Marks a plugin as "active" on a player. + * + * Also, ensures that the player has an object for tracking active plugins. + * + * @private + * @param {Player} player + * A Video.js player instance. + * + * @param {string} name + * The name of a plugin. + */ + var markPluginAsActive = function markPluginAsActive(player, name) { + player[PLUGIN_CACHE_KEY] = player[PLUGIN_CACHE_KEY] || {}; + player[PLUGIN_CACHE_KEY][name] = true; + }; + + /** + * Triggers a pair of plugin setup events. + * + * @private + * @param {Player} player + * A Video.js player instance. + * + * @param {Plugin~PluginEventHash} hash + * A plugin event hash. + * + * @param {Boolean} [before] + * If true, prefixes the event name with "before". In other words, + * use this to trigger "beforepluginsetup" instead of "pluginsetup". + */ + var triggerSetupEvent = function triggerSetupEvent(player, hash, before) { + var eventName = (before ? 'before' : '') + 'pluginsetup'; + + player.trigger(eventName, hash); + player.trigger(eventName + ':' + hash.name, hash); + }; + + /** + * Takes a basic plugin function and returns a wrapper function which marks + * on the player that the plugin has been activated. + * + * @private + * @param {string} name + * The name of the plugin. + * + * @param {Function} plugin + * The basic plugin. + * + * @returns {Function} + * A wrapper function for the given plugin. + */ + var createBasicPlugin = function createBasicPlugin(name, plugin) { + var basicPluginWrapper = function basicPluginWrapper() { + + // We trigger the "beforepluginsetup" and "pluginsetup" events on the player + // regardless, but we want the hash to be consistent with the hash provided + // for advanced plugins. + // + // The only potentially counter-intuitive thing here is the `instance` in + // the "pluginsetup" event is the value returned by the `plugin` function. + triggerSetupEvent(this, {name: name, plugin: plugin, instance: null}, true); + + var instance = plugin.apply(this, arguments); + + markPluginAsActive(this, name); + triggerSetupEvent(this, {name: name, plugin: plugin, instance: instance}); + + return instance; + }; + + Object.keys(plugin).forEach(function (prop) { + basicPluginWrapper[prop] = plugin[prop]; + }); + + return basicPluginWrapper; + }; + + /** + * Takes a plugin sub-class and returns a factory function for generating + * instances of it. + * + * This factory function will replace itself with an instance of the requested + * sub-class of Plugin. + * + * @private + * @param {string} name + * The name of the plugin. + * + * @param {Plugin} PluginSubClass + * The advanced plugin. + * + * @returns {Function} + */ + var createPluginFactory = function createPluginFactory(name, PluginSubClass) { + + // Add a `name` property to the plugin prototype so that each plugin can + // refer to itself by name. + PluginSubClass.prototype.name = name; + + return function () { + triggerSetupEvent(this, {name: name, plugin: PluginSubClass, instance: null}, true); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var instance = new (Function.prototype.bind.apply(PluginSubClass, [null].concat([this].concat(args))))(); + + // The plugin is replaced by a function that returns the current instance. + this[name] = function () { + return instance; + }; + + triggerSetupEvent(this, instance.getEventHash()); + + return instance; + }; + }; + + /** + * Parent class for all advanced plugins. + * + * @mixes module:evented~EventedMixin + * @mixes module:stateful~StatefulMixin + * @fires Player#beforepluginsetup + * @fires Player#beforepluginsetup:$name + * @fires Player#pluginsetup + * @fires Player#pluginsetup:$name + * @listens Player#dispose + * @throws {Error} + * If attempting to instantiate the base {@link Plugin} class + * directly instead of via a sub-class. + */ + + var Plugin = function () { + + /** + * Creates an instance of this class. + * + * Sub-classes should call `super` to ensure plugins are properly initialized. + * + * @param {Player} player + * A Video.js player instance. + */ + function Plugin(player) { + classCallCheck(this, Plugin); + + if (this.constructor === Plugin) { + throw new Error('Plugin must be sub-classed; not directly instantiated.'); + } + + this.player = player; + + // Make this object evented, but remove the added `trigger` method so we + // use the prototype version instead. + evented(this); + delete this.trigger; + + stateful(this, this.constructor.defaultState); + markPluginAsActive(player, this.name); + + // Auto-bind the dispose method so we can use it as a listener and unbind + // it later easily. + this.dispose = bind(this, this.dispose); + + // If the player is disposed, dispose the plugin. + player.on('dispose', this.dispose); + } + + /** + * Get the version of the plugin that was set on <pluginName>.VERSION + */ + + + Plugin.prototype.version = function version() { + return this.constructor.VERSION; + }; + + /** + * Each event triggered by plugins includes a hash of additional data with + * conventional properties. + * + * This returns that object or mutates an existing hash. + * + * @param {Object} [hash={}] + * An object to be used as event an event hash. + * + * @returns {Plugin~PluginEventHash} + * An event hash object with provided properties mixed-in. + */ + + + Plugin.prototype.getEventHash = function getEventHash() { + var hash = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + hash.name = this.name; + hash.plugin = this.constructor; + hash.instance = this; + return hash; + }; + + /** + * Triggers an event on the plugin object and overrides + * {@link module:evented~EventedMixin.trigger|EventedMixin.trigger}. + * + * @param {string|Object} event + * An event type or an object with a type property. + * + * @param {Object} [hash={}] + * Additional data hash to merge with a + * {@link Plugin~PluginEventHash|PluginEventHash}. + * + * @returns {boolean} + * Whether or not default was prevented. + */ + + + Plugin.prototype.trigger = function trigger$$1(event) { + var hash = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + return trigger(this.eventBusEl_, event, this.getEventHash(hash)); + }; + + /** + * Handles "statechanged" events on the plugin. No-op by default, override by + * subclassing. + * + * @abstract + * @param {Event} e + * An event object provided by a "statechanged" event. + * + * @param {Object} e.changes + * An object describing changes that occurred with the "statechanged" + * event. + */ + + + Plugin.prototype.handleStateChanged = function handleStateChanged(e) { + }; + + /** + * Disposes a plugin. + * + * Subclasses can override this if they want, but for the sake of safety, + * it's probably best to subscribe the "dispose" event. + * + * @fires Plugin#dispose + */ + + + Plugin.prototype.dispose = function dispose() { + var name = this.name, + player = this.player; + + /** + * Signals that a advanced plugin is about to be disposed. + * + * @event Plugin#dispose + * @type {EventTarget~Event} + */ + + this.trigger('dispose'); + this.off(); + player.off('dispose', this.dispose); + + // Eliminate any possible sources of leaking memory by clearing up + // references between the player and the plugin instance and nulling out + // the plugin's state and replacing methods with a function that throws. + player[PLUGIN_CACHE_KEY][name] = false; + this.player = this.state = null; + + // Finally, replace the plugin name on the player with a new factory + // function, so that the plugin is ready to be set up again. + player[name] = createPluginFactory(name, pluginStorage[name]); + }; + + /** + * Determines if a plugin is a basic plugin (i.e. not a sub-class of `Plugin`). + * + * @param {string|Function} plugin + * If a string, matches the name of a plugin. If a function, will be + * tested directly. + * + * @returns {boolean} + * Whether or not a plugin is a basic plugin. + */ + + + Plugin.isBasic = function isBasic(plugin) { + var p = typeof plugin === 'string' ? getPlugin(plugin) : plugin; + + return typeof p === 'function' && !Plugin.prototype.isPrototypeOf(p.prototype); + }; + + /** + * Register a Video.js plugin. + * + * @param {string} name + * The name of the plugin to be registered. Must be a string and + * must not match an existing plugin or a method on the `Player` + * prototype. + * + * @param {Function} plugin + * A sub-class of `Plugin` or a function for basic plugins. + * + * @returns {Function} + * For advanced plugins, a factory function for that plugin. For + * basic plugins, a wrapper function that initializes the plugin. + */ + + + Plugin.registerPlugin = function registerPlugin(name, plugin) { + if (typeof name !== 'string') { + throw new Error('Illegal plugin name, "' + name + '", must be a string, was ' + (typeof name === 'undefined' ? 'undefined' : _typeof(name)) + '.'); + } + + if (pluginExists(name)) { + log$1.warn('A plugin named "' + name + '" already exists. You may want to avoid re-registering plugins!'); + } else if (Player.prototype.hasOwnProperty(name)) { + throw new Error('Illegal plugin name, "' + name + '", cannot share a name with an existing player method!'); + } + + if (typeof plugin !== 'function') { + throw new Error('Illegal plugin for "' + name + '", must be a function, was ' + (typeof plugin === 'undefined' ? 'undefined' : _typeof(plugin)) + '.'); + } + + pluginStorage[name] = plugin; + + // Add a player prototype method for all sub-classed plugins (but not for + // the base Plugin class). + if (name !== BASE_PLUGIN_NAME) { + if (Plugin.isBasic(plugin)) { + Player.prototype[name] = createBasicPlugin(name, plugin); + } else { + Player.prototype[name] = createPluginFactory(name, plugin); + } + } + + return plugin; + }; + + /** + * De-register a Video.js plugin. + * + * @param {string} name + * The name of the plugin to be deregistered. + */ + + + Plugin.deregisterPlugin = function deregisterPlugin(name) { + if (name === BASE_PLUGIN_NAME) { + throw new Error('Cannot de-register base plugin.'); + } + if (pluginExists(name)) { + delete pluginStorage[name]; + delete Player.prototype[name]; + } + }; + + /** + * Gets an object containing multiple Video.js plugins. + * + * @param {Array} [names] + * If provided, should be an array of plugin names. Defaults to _all_ + * plugin names. + * + * @returns {Object|undefined} + * An object containing plugin(s) associated with their name(s) or + * `undefined` if no matching plugins exist). + */ + + + Plugin.getPlugins = function getPlugins() { + var names = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Object.keys(pluginStorage); + + var result = void 0; + + names.forEach(function (name) { + var plugin = getPlugin(name); + + if (plugin) { + result = result || {}; + result[name] = plugin; + } + }); + + return result; + }; + + /** + * Gets a plugin's version, if available + * + * @param {string} name + * The name of a plugin. + * + * @returns {string} + * The plugin's version or an empty string. + */ + + + Plugin.getPluginVersion = function getPluginVersion(name) { + var plugin = getPlugin(name); + + return plugin && plugin.VERSION || ''; + }; + + return Plugin; + }(); + + /** + * Gets a plugin by name if it exists. + * + * @static + * @method getPlugin + * @memberOf Plugin + * @param {string} name + * The name of a plugin. + * + * @returns {Function|undefined} + * The plugin (or `undefined`). + */ + + + Plugin.getPlugin = getPlugin; + + /** + * The name of the base plugin class as it is registered. + * + * @type {string} + */ + Plugin.BASE_PLUGIN_NAME = BASE_PLUGIN_NAME; + + Plugin.registerPlugin(BASE_PLUGIN_NAME, Plugin); + + /** + * Documented in player.js + * + * @ignore + */ + Player.prototype.usingPlugin = function (name) { + return !!this[PLUGIN_CACHE_KEY] && this[PLUGIN_CACHE_KEY][name] === true; + }; + + /** + * Documented in player.js + * + * @ignore + */ + Player.prototype.hasPlugin = function (name) { + return !!pluginExists(name); + }; + + /** + * @file extend.js + * @module extend + */ + + /** + * A combination of node inherits and babel's inherits (after transpile). + * Both work the same but node adds `super_` to the subClass + * and Bable adds the superClass as __proto__. Both seem useful. + * + * @param {Object} subClass + * The class to inherit to + * + * @param {Object} superClass + * The class to inherit from + * + * @private + */ + var _inherits = function _inherits(subClass, superClass) { + if (typeof superClass !== 'function' && superClass !== null) { + throw new TypeError('Super expression must either be null or a function, not ' + (typeof superClass === 'undefined' ? 'undefined' : _typeof(superClass))); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + + if (superClass) { + // node + subClass.super_ = superClass; + } + }; + + /** + * Function for subclassing using the same inheritance that + * videojs uses internally + * + * @static + * @const + * + * @param {Object} superClass + * The class to inherit from + * + * @param {Object} [subClassMethods={}] + * The class to inherit to + * + * @return {Object} + * The new object with subClassMethods that inherited superClass. + */ + var extendFn = function extendFn(superClass) { + var subClassMethods = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var subClass = function subClass() { + superClass.apply(this, arguments); + }; + + var methods = {}; + + if ((typeof subClassMethods === 'undefined' ? 'undefined' : _typeof(subClassMethods)) === 'object') { + if (subClassMethods.constructor !== Object.prototype.constructor) { + subClass = subClassMethods.constructor; + } + methods = subClassMethods; + } else if (typeof subClassMethods === 'function') { + subClass = subClassMethods; + } + + _inherits(subClass, superClass); + + // Extend subObj's prototype with functions and other properties from props + for (var name in methods) { + if (methods.hasOwnProperty(name)) { + subClass.prototype[name] = methods[name]; + } + } + + return subClass; + }; + + /** + * @file video.js + * @module videojs + */ + + /** + * Normalize an `id` value by trimming off a leading `#` + * + * @param {string} id + * A string, maybe with a leading `#`. + * + * @returns {string} + * The string, without any leading `#`. + */ + var normalizeId = function normalizeId(id) { + return id.indexOf('#') === 0 ? id.slice(1) : id; + }; + + /** + * Doubles as the main function for users to create a player instance and also + * the main library object. + * The `videojs` function can be used to initialize or retrieve a player. + * + * @param {string|Element} id + * Video element or video element ID + * + * @param {Object} [options] + * Optional options object for config/settings + * + * @param {Component~ReadyCallback} [ready] + * Optional ready callback + * + * @return {Player} + * A player instance + */ + function videojs$1(id, options, ready) { + var player = videojs$1.getPlayer(id); + + if (player) { + if (options) { + log$1.warn('Player "' + id + '" is already initialised. Options will not be applied.'); + } + if (ready) { + player.ready(ready); + } + return player; + } + + var el = typeof id === 'string' ? $('#' + normalizeId(id)) : id; + + if (!isEl(el)) { + throw new TypeError('The element or ID supplied is not valid. (videojs)'); + } + + if (!document_1.body.contains(el)) { + log$1.warn('The element supplied is not included in the DOM'); + } + + options = options || {}; + + videojs$1.hooks('beforesetup').forEach(function (hookFunction) { + var opts = hookFunction(el, mergeOptions(options)); + + if (!isObject(opts) || Array.isArray(opts)) { + log$1.error('please return an object in beforesetup hooks'); + return; + } + + options = mergeOptions(options, opts); + }); + + // We get the current "Player" component here in case an integration has + // replaced it with a custom player. + var PlayerComponent = Component.getComponent('Player'); + + player = new PlayerComponent(el, options, ready); + + videojs$1.hooks('setup').forEach(function (hookFunction) { + return hookFunction(player); + }); + + return player; + } + + /** + * An Object that contains lifecycle hooks as keys which point to an array + * of functions that are run when a lifecycle is triggered + */ + videojs$1.hooks_ = {}; + + /** + * Get a list of hooks for a specific lifecycle + * @function videojs.hooks + * + * @param {string} type + * the lifecyle to get hooks from + * + * @param {Function|Function[]} [fn] + * Optionally add a hook (or hooks) to the lifecycle that your are getting. + * + * @return {Array} + * an array of hooks, or an empty array if there are none. + */ + videojs$1.hooks = function (type, fn) { + videojs$1.hooks_[type] = videojs$1.hooks_[type] || []; + if (fn) { + videojs$1.hooks_[type] = videojs$1.hooks_[type].concat(fn); + } + return videojs$1.hooks_[type]; + }; + + /** + * Add a function hook to a specific videojs lifecycle. + * + * @param {string} type + * the lifecycle to hook the function to. + * + * @param {Function|Function[]} + * The function or array of functions to attach. + */ + videojs$1.hook = function (type, fn) { + videojs$1.hooks(type, fn); + }; + + /** + * Add a function hook that will only run once to a specific videojs lifecycle. + * + * @param {string} type + * the lifecycle to hook the function to. + * + * @param {Function|Function[]} + * The function or array of functions to attach. + */ + videojs$1.hookOnce = function (type, fn) { + videojs$1.hooks(type, [].concat(fn).map(function (original) { + var wrapper = function wrapper() { + videojs$1.removeHook(type, wrapper); + return original.apply(undefined, arguments); + }; + + return wrapper; + })); + }; + + /** + * Remove a hook from a specific videojs lifecycle. + * + * @param {string} type + * the lifecycle that the function hooked to + * + * @param {Function} fn + * The hooked function to remove + * + * @return {boolean} + * The function that was removed or undef + */ + videojs$1.removeHook = function (type, fn) { + var index = videojs$1.hooks(type).indexOf(fn); + + if (index <= -1) { + return false; + } + + videojs$1.hooks_[type] = videojs$1.hooks_[type].slice(); + videojs$1.hooks_[type].splice(index, 1); + + return true; + }; + + // Add default styles + if (window_1.VIDEOJS_NO_DYNAMIC_STYLE !== true && isReal()) { + var style$1 = $('.vjs-styles-defaults'); + + if (!style$1) { + style$1 = createStyleElement('vjs-styles-defaults'); + var head = $('head'); + + if (head) { + head.insertBefore(style$1, head.firstChild); + } + setTextContent(style$1, '\n .video-js {\n width: 300px;\n height: 150px;\n }\n\n .vjs-fluid {\n padding-top: 56.25%\n }\n '); + } + } + + // Run Auto-load players + // You have to wait at least once in case this script is loaded after your + // video in the DOM (weird behavior only with minified version) + autoSetupTimeout(1, videojs$1); + + /** + * Current software version. Follows semver. + * + * @type {string} + */ + videojs$1.VERSION = version; + + /** + * The global options object. These are the settings that take effect + * if no overrides are specified when the player is created. + * + * @type {Object} + */ + videojs$1.options = Player.prototype.options_; + + /** + * Get an object with the currently created players, keyed by player ID + * + * @return {Object} + * The created players + */ + videojs$1.getPlayers = function () { + return Player.players; + }; + + /** + * Get a single player based on an ID or DOM element. + * + * This is useful if you want to check if an element or ID has an associated + * Video.js player, but not create one if it doesn't. + * + * @param {string|Element} id + * An HTML element - `<video>`, `<audio>`, or `<video-js>` - + * or a string matching the `id` of such an element. + * + * @returns {Player|undefined} + * A player instance or `undefined` if there is no player instance + * matching the argument. + */ + videojs$1.getPlayer = function (id) { + var players = Player.players; + var tag = void 0; + + if (typeof id === 'string') { + var nId = normalizeId(id); + var player = players[nId]; + + if (player) { + return player; + } + + tag = $('#' + nId); + } else { + tag = id; + } + + if (isEl(tag)) { + var _tag = tag, + _player = _tag.player, + playerId = _tag.playerId; + + // Element may have a `player` property referring to an already created + // player instance. If so, return that. + + if (_player || players[playerId]) { + return _player || players[playerId]; + } + } + }; + + /** + * Returns an array of all current players. + * + * @return {Array} + * An array of all players. The array will be in the order that + * `Object.keys` provides, which could potentially vary between + * JavaScript engines. + * + */ + videojs$1.getAllPlayers = function () { + return ( + + // Disposed players leave a key with a `null` value, so we need to make sure + // we filter those out. + Object.keys(Player.players).map(function (k) { + return Player.players[k]; + }).filter(Boolean) + ); + }; + + /** + * Expose players object. + * + * @memberOf videojs + * @property {Object} players + */ + videojs$1.players = Player.players; + + /** + * Get a component class object by name + * + * @borrows Component.getComponent as videojs.getComponent + */ + videojs$1.getComponent = Component.getComponent; + + /** + * Register a component so it can referred to by name. Used when adding to other + * components, either through addChild `component.addChild('myComponent')` or through + * default children options `{ children: ['myComponent'] }`. + * + * > NOTE: You could also just initialize the component before adding. + * `component.addChild(new MyComponent());` + * + * @param {string} name + * The class name of the component + * + * @param {Component} comp + * The component class + * + * @return {Component} + * The newly registered component + */ + videojs$1.registerComponent = function (name$$1, comp) { + if (Tech.isTech(comp)) { + log$1.warn('The ' + name$$1 + ' tech was registered as a component. It should instead be registered using videojs.registerTech(name, tech)'); + } + + Component.registerComponent.call(Component, name$$1, comp); + }; + + /** + * Get a Tech class object by name + * + * @borrows Tech.getTech as videojs.getTech + */ + videojs$1.getTech = Tech.getTech; + + /** + * Register a Tech so it can referred to by name. + * This is used in the tech order for the player. + * + * @borrows Tech.registerTech as videojs.registerTech + */ + videojs$1.registerTech = Tech.registerTech; + + /** + * Register a middleware to a source type. + * + * @param {String} type A string representing a MIME type. + * @param {function(player):object} middleware A middleware factory that takes a player. + */ + videojs$1.use = use; + + /** + * An object that can be returned by a middleware to signify + * that the middleware is being terminated. + * + * @type {object} + * @memberOf {videojs} + * @property {object} middleware.TERMINATOR + */ + Object.defineProperty(videojs$1, 'middleware', { + value: {}, + writeable: false, + enumerable: true + }); + + Object.defineProperty(videojs$1.middleware, 'TERMINATOR', { + value: TERMINATOR, + writeable: false, + enumerable: true + }); + + /** + * A suite of browser and device tests from {@link browser}. + * + * @type {Object} + * @private + */ + videojs$1.browser = browser; + + /** + * Whether or not the browser supports touch events. Included for backward + * compatibility with 4.x, but deprecated. Use `videojs.browser.TOUCH_ENABLED` + * instead going forward. + * + * @deprecated since version 5.0 + * @type {boolean} + */ + videojs$1.TOUCH_ENABLED = TOUCH_ENABLED; + + /** + * Subclass an existing class + * Mimics ES6 subclassing with the `extend` keyword + * + * @borrows extend:extendFn as videojs.extend + */ + videojs$1.extend = extendFn; + + /** + * Merge two options objects recursively + * Performs a deep merge like lodash.merge but **only merges plain objects** + * (not arrays, elements, anything else) + * Other values will be copied directly from the second object. + * + * @borrows merge-options:mergeOptions as videojs.mergeOptions + */ + videojs$1.mergeOptions = mergeOptions; + + /** + * Change the context (this) of a function + * + * > NOTE: as of v5.0 we require an ES5 shim, so you should use the native + * `function() {}.bind(newContext);` instead of this. + * + * @borrows fn:bind as videojs.bind + */ + videojs$1.bind = bind; + + /** + * Register a Video.js plugin. + * + * @borrows plugin:registerPlugin as videojs.registerPlugin + * @method registerPlugin + * + * @param {string} name + * The name of the plugin to be registered. Must be a string and + * must not match an existing plugin or a method on the `Player` + * prototype. + * + * @param {Function} plugin + * A sub-class of `Plugin` or a function for basic plugins. + * + * @return {Function} + * For advanced plugins, a factory function for that plugin. For + * basic plugins, a wrapper function that initializes the plugin. + */ + videojs$1.registerPlugin = Plugin.registerPlugin; + + /** + * Deprecated method to register a plugin with Video.js + * + * @deprecated + * videojs.plugin() is deprecated; use videojs.registerPlugin() instead + * + * @param {string} name + * The plugin name + * + * @param {Plugin|Function} plugin + * The plugin sub-class or function + */ + videojs$1.plugin = function (name$$1, plugin) { + log$1.warn('videojs.plugin() is deprecated; use videojs.registerPlugin() instead'); + return Plugin.registerPlugin(name$$1, plugin); + }; + + /** + * Gets an object containing multiple Video.js plugins. + * + * @param {Array} [names] + * If provided, should be an array of plugin names. Defaults to _all_ + * plugin names. + * + * @return {Object|undefined} + * An object containing plugin(s) associated with their name(s) or + * `undefined` if no matching plugins exist). + */ + videojs$1.getPlugins = Plugin.getPlugins; + + /** + * Gets a plugin by name if it exists. + * + * @param {string} name + * The name of a plugin. + * + * @return {Function|undefined} + * The plugin (or `undefined`). + */ + videojs$1.getPlugin = Plugin.getPlugin; + + /** + * Gets a plugin's version, if available + * + * @param {string} name + * The name of a plugin. + * + * @return {string} + * The plugin's version or an empty string. + */ + videojs$1.getPluginVersion = Plugin.getPluginVersion; + + /** + * Adding languages so that they're available to all players. + * Example: `videojs.addLanguage('es', { 'Hello': 'Hola' });` + * + * @param {string} code + * The language code or dictionary property + * + * @param {Object} data + * The data values to be translated + * + * @return {Object} + * The resulting language dictionary object + */ + videojs$1.addLanguage = function (code, data) { + var _mergeOptions; + + code = ('' + code).toLowerCase(); + + videojs$1.options.languages = mergeOptions(videojs$1.options.languages, (_mergeOptions = {}, _mergeOptions[code] = data, _mergeOptions)); + + return videojs$1.options.languages[code]; + }; + + /** + * Log messages + * + * @borrows log:log as videojs.log + */ + videojs$1.log = log$1; + + /** + * Creates an emulated TimeRange object. + * + * @borrows time-ranges:createTimeRanges as videojs.createTimeRange + */ + /** + * @borrows time-ranges:createTimeRanges as videojs.createTimeRanges + */ + videojs$1.createTimeRange = videojs$1.createTimeRanges = createTimeRanges; + + /** + * Format seconds as a time string, H:MM:SS or M:SS + * Supplying a guide (in seconds) will force a number of leading zeros + * to cover the length of the guide + * + * @borrows format-time:formatTime as videojs.formatTime + */ + videojs$1.formatTime = formatTime; + + /** + * Replaces format-time with a custom implementation, to be used in place of the default. + * + * @borrows format-time:setFormatTime as videojs.setFormatTime + * + * @method setFormatTime + * + * @param {Function} customFn + * A custom format-time function which will be called with the current time and guide (in seconds) as arguments. + * Passed fn should return a string. + */ + videojs$1.setFormatTime = setFormatTime; + + /** + * Resets format-time to the default implementation. + * + * @borrows format-time:resetFormatTime as videojs.resetFormatTime + * + * @method resetFormatTime + */ + videojs$1.resetFormatTime = resetFormatTime; + + /** + * Resolve and parse the elements of a URL + * + * @borrows url:parseUrl as videojs.parseUrl + * + */ + videojs$1.parseUrl = parseUrl; + + /** + * Returns whether the url passed is a cross domain request or not. + * + * @borrows url:isCrossOrigin as videojs.isCrossOrigin + */ + videojs$1.isCrossOrigin = isCrossOrigin; + + /** + * Event target class. + * + * @borrows EventTarget as videojs.EventTarget + */ + videojs$1.EventTarget = EventTarget; + + /** + * Add an event listener to element + * It stores the handler function in a separate cache object + * and adds a generic handler to the element's event, + * along with a unique id (guid) to the element. + * + * @borrows events:on as videojs.on + */ + videojs$1.on = on; + + /** + * Trigger a listener only once for an event + * + * @borrows events:one as videojs.one + */ + videojs$1.one = one; + + /** + * Removes event listeners from an element + * + * @borrows events:off as videojs.off + */ + videojs$1.off = off; + + /** + * Trigger an event for an element + * + * @borrows events:trigger as videojs.trigger + */ + videojs$1.trigger = trigger; + + /** + * A cross-browser XMLHttpRequest wrapper. Here's a simple example: + * + * @param {Object} options + * settings for the request. + * + * @return {XMLHttpRequest|XDomainRequest} + * The request object. + * + * @see https://github.com/Raynos/xhr + */ + videojs$1.xhr = xhr; + + /** + * TextTrack class + * + * @borrows TextTrack as videojs.TextTrack + */ + videojs$1.TextTrack = TextTrack; + + /** + * export the AudioTrack class so that source handlers can create + * AudioTracks and then add them to the players AudioTrackList + * + * @borrows AudioTrack as videojs.AudioTrack + */ + videojs$1.AudioTrack = AudioTrack; + + /** + * export the VideoTrack class so that source handlers can create + * VideoTracks and then add them to the players VideoTrackList + * + * @borrows VideoTrack as videojs.VideoTrack + */ + videojs$1.VideoTrack = VideoTrack; + + /** + * Determines, via duck typing, whether or not a value is a DOM element. + * + * @borrows dom:isEl as videojs.isEl + * @deprecated Use videojs.dom.isEl() instead + */ + + /** + * Determines, via duck typing, whether or not a value is a text node. + * + * @borrows dom:isTextNode as videojs.isTextNode + * @deprecated Use videojs.dom.isTextNode() instead + */ + + /** + * Creates an element and applies properties. + * + * @borrows dom:createEl as videojs.createEl + * @deprecated Use videojs.dom.createEl() instead + */ + + /** + * Check if an element has a CSS class + * + * @borrows dom:hasElClass as videojs.hasClass + * @deprecated Use videojs.dom.hasClass() instead + */ + + /** + * Add a CSS class name to an element + * + * @borrows dom:addElClass as videojs.addClass + * @deprecated Use videojs.dom.addClass() instead + */ + + /** + * Remove a CSS class name from an element + * + * @borrows dom:removeElClass as videojs.removeClass + * @deprecated Use videojs.dom.removeClass() instead + */ + + /** + * Adds or removes a CSS class name on an element depending on an optional + * condition or the presence/absence of the class name. + * + * @borrows dom:toggleElClass as videojs.toggleClass + * @deprecated Use videojs.dom.toggleClass() instead + */ + + /** + * Apply attributes to an HTML element. + * + * @borrows dom:setElAttributes as videojs.setAttribute + * @deprecated Use videojs.dom.setAttributes() instead + */ + + /** + * Get an element's attribute values, as defined on the HTML tag + * Attributes are not the same as properties. They're defined on the tag + * or with setAttribute (which shouldn't be used with HTML) + * This will return true or false for boolean attributes. + * + * @borrows dom:getElAttributes as videojs.getAttributes + * @deprecated Use videojs.dom.getAttributes() instead + */ + + /** + * Empties the contents of an element. + * + * @borrows dom:emptyEl as videojs.emptyEl + * @deprecated Use videojs.dom.emptyEl() instead + */ + + /** + * Normalizes and appends content to an element. + * + * The content for an element can be passed in multiple types and + * combinations, whose behavior is as follows: + * + * - String + * Normalized into a text node. + * + * - Element, TextNode + * Passed through. + * + * - Array + * A one-dimensional array of strings, elements, nodes, or functions (which + * return single strings, elements, or nodes). + * + * - Function + * If the sole argument, is expected to produce a string, element, + * node, or array. + * + * @borrows dom:appendContents as videojs.appendContet + * @deprecated Use videojs.dom.appendContent() instead + */ + + /** + * Normalizes and inserts content into an element; this is identical to + * `appendContent()`, except it empties the element first. + * + * The content for an element can be passed in multiple types and + * combinations, whose behavior is as follows: + * + * - String + * Normalized into a text node. + * + * - Element, TextNode + * Passed through. + * + * - Array + * A one-dimensional array of strings, elements, nodes, or functions (which + * return single strings, elements, or nodes). + * + * - Function + * If the sole argument, is expected to produce a string, element, + * node, or array. + * + * @borrows dom:insertContent as videojs.insertContent + * @deprecated Use videojs.dom.insertContent() instead + */ + ['isEl', 'isTextNode', 'createEl', 'hasClass', 'addClass', 'removeClass', 'toggleClass', 'setAttributes', 'getAttributes', 'emptyEl', 'appendContent', 'insertContent'].forEach(function (k) { + videojs$1[k] = function () { + log$1.warn('videojs.' + k + '() is deprecated; use videojs.dom.' + k + '() instead'); + return Dom[k].apply(null, arguments); + }; + }); + + /** + * A safe getComputedStyle. + * + * This is because in Firefox, if the player is loaded in an iframe with `display:none`, + * then `getComputedStyle` returns `null`, so, we do a null-check to make sure + * that the player doesn't break in these cases. + * See https://bugzilla.mozilla.org/show_bug.cgi?id=548397 for more details. + * + * @borrows computed-style:computedStyle as videojs.computedStyle + */ + videojs$1.computedStyle = computedStyle; + + /** + * Export the Dom utilities for use in external plugins + * and Tech's + */ + videojs$1.dom = Dom; + + /** + * Export the Url utilities for use in external plugins + * and Tech's + */ + videojs$1.url = Url; + + var urlToolkit = createCommonjsModule(function (module, exports) { + // see https://tools.ietf.org/html/rfc1808 + + /* jshint ignore:start */ + (function (root) { + /* jshint ignore:end */ + + var URL_REGEX = /^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/\;?#]*)?(.*?)??(;.*?)?(\?.*?)?(#.*?)?$/; + var FIRST_SEGMENT_REGEX = /^([^\/;?#]*)(.*)$/; + var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g; + var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g; + + var URLToolkit = { // jshint ignore:line + // If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or // + // E.g + // With opts.alwaysNormalize = false (default, spec compliant) + // http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g + // With opts.alwaysNormalize = true (not spec compliant) + // http://a.com/b/cd + /e/f/../g => http://a.com/e/g + buildAbsoluteURL: function buildAbsoluteURL(baseURL, relativeURL, opts) { + opts = opts || {}; + // remove any remaining space and CRLF + baseURL = baseURL.trim(); + relativeURL = relativeURL.trim(); + if (!relativeURL) { + // 2a) If the embedded URL is entirely empty, it inherits the + // entire base URL (i.e., is set equal to the base URL) + // and we are done. + if (!opts.alwaysNormalize) { + return baseURL; + } + var basePartsForNormalise = URLToolkit.parseURL(baseURL); + if (!basePartsForNormalise) { + throw new Error('Error trying to parse base URL.'); + } + basePartsForNormalise.path = URLToolkit.normalizePath(basePartsForNormalise.path); + return URLToolkit.buildURLFromParts(basePartsForNormalise); + } + var relativeParts = URLToolkit.parseURL(relativeURL); + if (!relativeParts) { + throw new Error('Error trying to parse relative URL.'); + } + if (relativeParts.scheme) { + // 2b) If the embedded URL starts with a scheme name, it is + // interpreted as an absolute URL and we are done. + if (!opts.alwaysNormalize) { + return relativeURL; + } + relativeParts.path = URLToolkit.normalizePath(relativeParts.path); + return URLToolkit.buildURLFromParts(relativeParts); + } + var baseParts = URLToolkit.parseURL(baseURL); + if (!baseParts) { + throw new Error('Error trying to parse base URL.'); + } + if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') { + // If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc + // This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a' + var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path); + baseParts.netLoc = pathParts[1]; + baseParts.path = pathParts[2]; + } + if (baseParts.netLoc && !baseParts.path) { + baseParts.path = '/'; + } + var builtParts = { + // 2c) Otherwise, the embedded URL inherits the scheme of + // the base URL. + scheme: baseParts.scheme, + netLoc: relativeParts.netLoc, + path: null, + params: relativeParts.params, + query: relativeParts.query, + fragment: relativeParts.fragment + }; + if (!relativeParts.netLoc) { + // 3) If the embedded URL's <net_loc> is non-empty, we skip to + // Step 7. Otherwise, the embedded URL inherits the <net_loc> + // (if any) of the base URL. + builtParts.netLoc = baseParts.netLoc; + // 4) If the embedded URL path is preceded by a slash "/", the + // path is not relative and we skip to Step 7. + if (relativeParts.path[0] !== '/') { + if (!relativeParts.path) { + // 5) If the embedded URL path is empty (and not preceded by a + // slash), then the embedded URL inherits the base URL path + builtParts.path = baseParts.path; + // 5a) if the embedded URL's <params> is non-empty, we skip to + // step 7; otherwise, it inherits the <params> of the base + // URL (if any) and + if (!relativeParts.params) { + builtParts.params = baseParts.params; + // 5b) if the embedded URL's <query> is non-empty, we skip to + // step 7; otherwise, it inherits the <query> of the base + // URL (if any) and we skip to step 7. + if (!relativeParts.query) { + builtParts.query = baseParts.query; + } + } + } else { + // 6) The last segment of the base URL's path (anything + // following the rightmost slash "/", or the entire path if no + // slash is present) is removed and the embedded URL's path is + // appended in its place. + var baseURLPath = baseParts.path; + var newPath = baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + relativeParts.path; + builtParts.path = URLToolkit.normalizePath(newPath); + } + } + } + if (builtParts.path === null) { + builtParts.path = opts.alwaysNormalize ? URLToolkit.normalizePath(relativeParts.path) : relativeParts.path; + } + return URLToolkit.buildURLFromParts(builtParts); + }, + parseURL: function parseURL(url) { + var parts = URL_REGEX.exec(url); + if (!parts) { + return null; + } + return { + scheme: parts[1] || '', + netLoc: parts[2] || '', + path: parts[3] || '', + params: parts[4] || '', + query: parts[5] || '', + fragment: parts[6] || '' + }; + }, + normalizePath: function normalizePath(path) { + // The following operations are + // then applied, in order, to the new path: + // 6a) All occurrences of "./", where "." is a complete path + // segment, are removed. + // 6b) If the path ends with "." as a complete path segment, + // that "." is removed. + path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, ''); + // 6c) All occurrences of "<segment>/../", where <segment> is a + // complete path segment not equal to "..", are removed. + // Removal of these path segments is performed iteratively, + // removing the leftmost matching pattern on each iteration, + // until no matching pattern remains. + // 6d) If the path ends with "<segment>/..", where <segment> is a + // complete path segment not equal to "..", that + // "<segment>/.." is removed. + while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) { + } // jshint ignore:line + return path.split('').reverse().join(''); + }, + buildURLFromParts: function buildURLFromParts(parts) { + return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment; + } + }; + + /* jshint ignore:start */ + module.exports = URLToolkit; + })(commonjsGlobal); + /* jshint ignore:end */ + }); + + var classCallCheck$1 = function classCallCheck$$1(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var _extends$1 = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + var inherits$1 = function inherits$$1(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : _typeof(superClass))); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + }; + + var possibleConstructorReturn$1 = function possibleConstructorReturn$$1(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && ((typeof call === "undefined" ? "undefined" : _typeof(call)) === "object" || typeof call === "function") ? call : self; + }; + + /** + * @file stream.js + */ + /** + * A lightweight readable stream implemention that handles event dispatching. + * + * @class Stream + */ + var Stream = function () { + function Stream() { + classCallCheck$1(this, Stream); + + this.listeners = {}; + } + + /** + * Add a listener for a specified event type. + * + * @param {String} type the event name + * @param {Function} listener the callback to be invoked when an event of + * the specified type occurs + */ + + Stream.prototype.on = function on(type, listener) { + if (!this.listeners[type]) { + this.listeners[type] = []; + } + this.listeners[type].push(listener); + }; + + /** + * Remove a listener for a specified event type. + * + * @param {String} type the event name + * @param {Function} listener a function previously registered for this + * type of event through `on` + * @return {Boolean} if we could turn it off or not + */ + + Stream.prototype.off = function off(type, listener) { + if (!this.listeners[type]) { + return false; + } + + var index = this.listeners[type].indexOf(listener); + + this.listeners[type].splice(index, 1); + return index > -1; + }; + + /** + * Trigger an event of the specified type on this stream. Any additional + * arguments to this function are passed as parameters to event listeners. + * + * @param {String} type the event name + */ + + Stream.prototype.trigger = function trigger(type) { + var callbacks = this.listeners[type]; + var i = void 0; + var length = void 0; + var args = void 0; + + if (!callbacks) { + return; + } + // Slicing the arguments on every invocation of this method + // can add a significant amount of overhead. Avoid the + // intermediate object creation for the common case of a + // single callback argument + if (arguments.length === 2) { + length = callbacks.length; + for (i = 0; i < length; ++i) { + callbacks[i].call(this, arguments[1]); + } + } else { + args = Array.prototype.slice.call(arguments, 1); + length = callbacks.length; + for (i = 0; i < length; ++i) { + callbacks[i].apply(this, args); + } + } + }; + + /** + * Destroys the stream and cleans up. + */ + + Stream.prototype.dispose = function dispose() { + this.listeners = {}; + }; + /** + * Forwards all `data` events on this stream to the destination stream. The + * destination stream should provide a method `push` to receive the data + * events as they arrive. + * + * @param {Stream} destination the stream that will receive all `data` events + * @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options + */ + + Stream.prototype.pipe = function pipe(destination) { + this.on('data', function (data) { + destination.push(data); + }); + }; + + return Stream; + }(); + + /** + * @file m3u8/line-stream.js + */ + /** + * A stream that buffers string input and generates a `data` event for each + * line. + * + * @class LineStream + * @extends Stream + */ + + var LineStream = function (_Stream) { + inherits$1(LineStream, _Stream); + + function LineStream() { + classCallCheck$1(this, LineStream); + + var _this = possibleConstructorReturn$1(this, _Stream.call(this)); + + _this.buffer = ''; + return _this; + } + + /** + * Add new data to be parsed. + * + * @param {String} data the text to process + */ + + LineStream.prototype.push = function push(data) { + var nextNewline = void 0; + + this.buffer += data; + nextNewline = this.buffer.indexOf('\n'); + + for (; nextNewline > -1; nextNewline = this.buffer.indexOf('\n')) { + this.trigger('data', this.buffer.substring(0, nextNewline)); + this.buffer = this.buffer.substring(nextNewline + 1); + } + }; + + return LineStream; + }(Stream); + + /** + * @file m3u8/parse-stream.js + */ + /** + * "forgiving" attribute list psuedo-grammar: + * attributes -> keyvalue (',' keyvalue)* + * keyvalue -> key '=' value + * key -> [^=]* + * value -> '"' [^"]* '"' | [^,]* + */ + var attributeSeparator = function attributeSeparator() { + var key = '[^=]*'; + var value = '"[^"]*"|[^,]*'; + var keyvalue = '(?:' + key + ')=(?:' + value + ')'; + + return new RegExp('(?:^|,)(' + keyvalue + ')'); + }; + + /** + * Parse attributes from a line given the seperator + * + * @param {String} attributes the attibute line to parse + */ + var parseAttributes = function parseAttributes(attributes) { + // split the string using attributes as the separator + var attrs = attributes.split(attributeSeparator()); + var result = {}; + var i = attrs.length; + var attr = void 0; + + while (i--) { + // filter out unmatched portions of the string + if (attrs[i] === '') { + continue; + } + + // split the key and value + attr = /([^=]*)=(.*)/.exec(attrs[i]).slice(1); + // trim whitespace and remove optional quotes around the value + attr[0] = attr[0].replace(/^\s+|\s+$/g, ''); + attr[1] = attr[1].replace(/^\s+|\s+$/g, ''); + attr[1] = attr[1].replace(/^['"](.*)['"]$/g, '$1'); + result[attr[0]] = attr[1]; + } + return result; + }; + + /** + * A line-level M3U8 parser event stream. It expects to receive input one + * line at a time and performs a context-free parse of its contents. A stream + * interpretation of a manifest can be useful if the manifest is expected to + * be too large to fit comfortably into memory or the entirety of the input + * is not immediately available. Otherwise, it's probably much easier to work + * with a regular `Parser` object. + * + * Produces `data` events with an object that captures the parser's + * interpretation of the input. That object has a property `tag` that is one + * of `uri`, `comment`, or `tag`. URIs only have a single additional + * property, `line`, which captures the entirety of the input without + * interpretation. Comments similarly have a single additional property + * `text` which is the input without the leading `#`. + * + * Tags always have a property `tagType` which is the lower-cased version of + * the M3U8 directive without the `#EXT` or `#EXT-X-` prefix. For instance, + * `#EXT-X-MEDIA-SEQUENCE` becomes `media-sequence` when parsed. Unrecognized + * tags are given the tag type `unknown` and a single additional property + * `data` with the remainder of the input. + * + * @class ParseStream + * @extends Stream + */ + + var ParseStream = function (_Stream) { + inherits$1(ParseStream, _Stream); + + function ParseStream() { + classCallCheck$1(this, ParseStream); + + var _this = possibleConstructorReturn$1(this, _Stream.call(this)); + + _this.customParsers = []; + return _this; + } + + /** + * Parses an additional line of input. + * + * @param {String} line a single line of an M3U8 file to parse + */ + + ParseStream.prototype.push = function push(line) { + var match = void 0; + var event = void 0; + + // strip whitespace + line = line.replace(/^[\u0000\s]+|[\u0000\s]+$/g, ''); + if (line.length === 0) { + // ignore empty lines + return; + } + + // URIs + if (line[0] !== '#') { + this.trigger('data', { + type: 'uri', + uri: line + }); + return; + } + + for (var i = 0; i < this.customParsers.length; i++) { + if (this.customParsers[i].call(this, line)) { + return; + } + } + + // Comments + if (line.indexOf('#EXT') !== 0) { + this.trigger('data', { + type: 'comment', + text: line.slice(1) + }); + return; + } + + // strip off any carriage returns here so the regex matching + // doesn't have to account for them. + line = line.replace('\r', ''); + + // Tags + match = /^#EXTM3U/.exec(line); + if (match) { + this.trigger('data', { + type: 'tag', + tagType: 'm3u' + }); + return; + } + match = /^#EXTINF:?([0-9\.]*)?,?(.*)?$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'inf' + }; + if (match[1]) { + event.duration = parseFloat(match[1]); + } + if (match[2]) { + event.title = match[2]; + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-TARGETDURATION:?([0-9.]*)?/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'targetduration' + }; + if (match[1]) { + event.duration = parseInt(match[1], 10); + } + this.trigger('data', event); + return; + } + match = /^#ZEN-TOTAL-DURATION:?([0-9.]*)?/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'totalduration' + }; + if (match[1]) { + event.duration = parseInt(match[1], 10); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-VERSION:?([0-9.]*)?/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'version' + }; + if (match[1]) { + event.version = parseInt(match[1], 10); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-MEDIA-SEQUENCE:?(\-?[0-9.]*)?/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'media-sequence' + }; + if (match[1]) { + event.number = parseInt(match[1], 10); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-DISCONTINUITY-SEQUENCE:?(\-?[0-9.]*)?/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'discontinuity-sequence' + }; + if (match[1]) { + event.number = parseInt(match[1], 10); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-PLAYLIST-TYPE:?(.*)?$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'playlist-type' + }; + if (match[1]) { + event.playlistType = match[1]; + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-BYTERANGE:?([0-9.]*)?@?([0-9.]*)?/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'byterange' + }; + if (match[1]) { + event.length = parseInt(match[1], 10); + } + if (match[2]) { + event.offset = parseInt(match[2], 10); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-ALLOW-CACHE:?(YES|NO)?/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'allow-cache' + }; + if (match[1]) { + event.allowed = !/NO/.test(match[1]); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-MAP:?(.*)$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'map' + }; + + if (match[1]) { + var attributes = parseAttributes(match[1]); + + if (attributes.URI) { + event.uri = attributes.URI; + } + if (attributes.BYTERANGE) { + var _attributes$BYTERANGE = attributes.BYTERANGE.split('@'), + length = _attributes$BYTERANGE[0], + offset = _attributes$BYTERANGE[1]; + + event.byterange = {}; + if (length) { + event.byterange.length = parseInt(length, 10); + } + if (offset) { + event.byterange.offset = parseInt(offset, 10); + } + } + } + + this.trigger('data', event); + return; + } + match = /^#EXT-X-STREAM-INF:?(.*)$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'stream-inf' + }; + if (match[1]) { + event.attributes = parseAttributes(match[1]); + + if (event.attributes.RESOLUTION) { + var split = event.attributes.RESOLUTION.split('x'); + var resolution = {}; + + if (split[0]) { + resolution.width = parseInt(split[0], 10); + } + if (split[1]) { + resolution.height = parseInt(split[1], 10); + } + event.attributes.RESOLUTION = resolution; + } + if (event.attributes.BANDWIDTH) { + event.attributes.BANDWIDTH = parseInt(event.attributes.BANDWIDTH, 10); + } + if (event.attributes['PROGRAM-ID']) { + event.attributes['PROGRAM-ID'] = parseInt(event.attributes['PROGRAM-ID'], 10); + } + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-MEDIA:?(.*)$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'media' + }; + if (match[1]) { + event.attributes = parseAttributes(match[1]); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-ENDLIST/.exec(line); + if (match) { + this.trigger('data', { + type: 'tag', + tagType: 'endlist' + }); + return; + } + match = /^#EXT-X-DISCONTINUITY/.exec(line); + if (match) { + this.trigger('data', { + type: 'tag', + tagType: 'discontinuity' + }); + return; + } + match = /^#EXT-X-PROGRAM-DATE-TIME:?(.*)$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'program-date-time' + }; + if (match[1]) { + event.dateTimeString = match[1]; + event.dateTimeObject = new Date(match[1]); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-KEY:?(.*)$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'key' + }; + if (match[1]) { + event.attributes = parseAttributes(match[1]); + // parse the IV string into a Uint32Array + if (event.attributes.IV) { + if (event.attributes.IV.substring(0, 2).toLowerCase() === '0x') { + event.attributes.IV = event.attributes.IV.substring(2); + } + + event.attributes.IV = event.attributes.IV.match(/.{8}/g); + event.attributes.IV[0] = parseInt(event.attributes.IV[0], 16); + event.attributes.IV[1] = parseInt(event.attributes.IV[1], 16); + event.attributes.IV[2] = parseInt(event.attributes.IV[2], 16); + event.attributes.IV[3] = parseInt(event.attributes.IV[3], 16); + event.attributes.IV = new Uint32Array(event.attributes.IV); + } + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-START:?(.*)$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'start' + }; + if (match[1]) { + event.attributes = parseAttributes(match[1]); + + event.attributes['TIME-OFFSET'] = parseFloat(event.attributes['TIME-OFFSET']); + event.attributes.PRECISE = /YES/.test(event.attributes.PRECISE); + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-CUE-OUT-CONT:?(.*)?$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'cue-out-cont' + }; + if (match[1]) { + event.data = match[1]; + } else { + event.data = ''; + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-CUE-OUT:?(.*)?$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'cue-out' + }; + if (match[1]) { + event.data = match[1]; + } else { + event.data = ''; + } + this.trigger('data', event); + return; + } + match = /^#EXT-X-CUE-IN:?(.*)?$/.exec(line); + if (match) { + event = { + type: 'tag', + tagType: 'cue-in' + }; + if (match[1]) { + event.data = match[1]; + } else { + event.data = ''; + } + this.trigger('data', event); + return; + } + + // unknown tag type + this.trigger('data', { + type: 'tag', + data: line.slice(4) + }); + }; + + /** + * Add a parser for custom headers + * + * @param {Object} options a map of options for the added parser + * @param {RegExp} options.expression a regular expression to match the custom header + * @param {string} options.customType the custom type to register to the output + * @param {Function} [options.dataParser] function to parse the line into an object + * @param {boolean} [options.segment] should tag data be attached to the segment object + */ + + ParseStream.prototype.addParser = function addParser(_ref) { + var _this2 = this; + + var expression = _ref.expression, + customType = _ref.customType, + dataParser = _ref.dataParser, + segment = _ref.segment; + + if (typeof dataParser !== 'function') { + dataParser = function dataParser(line) { + return line; + }; + } + this.customParsers.push(function (line) { + var match = expression.exec(line); + + if (match) { + _this2.trigger('data', { + type: 'custom', + data: dataParser(line), + customType: customType, + segment: segment + }); + return true; + } + }); + }; + + return ParseStream; + }(Stream); + + /** + * @file m3u8/parser.js + */ + /** + * A parser for M3U8 files. The current interpretation of the input is + * exposed as a property `manifest` on parser objects. It's just two lines to + * create and parse a manifest once you have the contents available as a string: + * + * ```js + * var parser = new m3u8.Parser(); + * parser.push(xhr.responseText); + * ``` + * + * New input can later be applied to update the manifest object by calling + * `push` again. + * + * The parser attempts to create a usable manifest object even if the + * underlying input is somewhat nonsensical. It emits `info` and `warning` + * events during the parse if it encounters input that seems invalid or + * requires some property of the manifest object to be defaulted. + * + * @class Parser + * @extends Stream + */ + + var Parser = function (_Stream) { + inherits$1(Parser, _Stream); + + function Parser() { + classCallCheck$1(this, Parser); + + var _this = possibleConstructorReturn$1(this, _Stream.call(this)); + + _this.lineStream = new LineStream(); + _this.parseStream = new ParseStream(); + _this.lineStream.pipe(_this.parseStream); + + /* eslint-disable consistent-this */ + var self = _this; + /* eslint-enable consistent-this */ + var uris = []; + var currentUri = {}; + // if specified, the active EXT-X-MAP definition + var currentMap = void 0; + // if specified, the active decryption key + var _key = void 0; + var noop = function noop() { + }; + var defaultMediaGroups = { + 'AUDIO': {}, + 'VIDEO': {}, + 'CLOSED-CAPTIONS': {}, + 'SUBTITLES': {} + }; + // group segments into numbered timelines delineated by discontinuities + var currentTimeline = 0; + + // the manifest is empty until the parse stream begins delivering data + _this.manifest = { + allowCache: true, + discontinuityStarts: [], + segments: [] + }; + + // update the manifest with the m3u8 entry from the parse stream + _this.parseStream.on('data', function (entry) { + var mediaGroup = void 0; + var rendition = void 0; + + ({ + tag: function tag() { + // switch based on the tag type + (({ + 'allow-cache': function allowCache() { + this.manifest.allowCache = entry.allowed; + if (!('allowed' in entry)) { + this.trigger('info', { + message: 'defaulting allowCache to YES' + }); + this.manifest.allowCache = true; + } + }, + byterange: function byterange() { + var byterange = {}; + + if ('length' in entry) { + currentUri.byterange = byterange; + byterange.length = entry.length; + + if (!('offset' in entry)) { + this.trigger('info', { + message: 'defaulting offset to zero' + }); + entry.offset = 0; + } + } + if ('offset' in entry) { + currentUri.byterange = byterange; + byterange.offset = entry.offset; + } + }, + endlist: function endlist() { + this.manifest.endList = true; + }, + inf: function inf() { + if (!('mediaSequence' in this.manifest)) { + this.manifest.mediaSequence = 0; + this.trigger('info', { + message: 'defaulting media sequence to zero' + }); + } + if (!('discontinuitySequence' in this.manifest)) { + this.manifest.discontinuitySequence = 0; + this.trigger('info', { + message: 'defaulting discontinuity sequence to zero' + }); + } + if (entry.duration > 0) { + currentUri.duration = entry.duration; + } + + if (entry.duration === 0) { + currentUri.duration = 0.01; + this.trigger('info', { + message: 'updating zero segment duration to a small value' + }); + } + + this.manifest.segments = uris; + }, + key: function key() { + if (!entry.attributes) { + this.trigger('warn', { + message: 'ignoring key declaration without attribute list' + }); + return; + } + // clear the active encryption key + if (entry.attributes.METHOD === 'NONE') { + _key = null; + return; + } + if (!entry.attributes.URI) { + this.trigger('warn', { + message: 'ignoring key declaration without URI' + }); + return; + } + if (!entry.attributes.METHOD) { + this.trigger('warn', { + message: 'defaulting key method to AES-128' + }); + } + + // setup an encryption key for upcoming segments + _key = { + method: entry.attributes.METHOD || 'AES-128', + uri: entry.attributes.URI + }; + + if (typeof entry.attributes.IV !== 'undefined') { + _key.iv = entry.attributes.IV; + } + }, + 'media-sequence': function mediaSequence() { + if (!isFinite(entry.number)) { + this.trigger('warn', { + message: 'ignoring invalid media sequence: ' + entry.number + }); + return; + } + this.manifest.mediaSequence = entry.number; + }, + 'discontinuity-sequence': function discontinuitySequence() { + if (!isFinite(entry.number)) { + this.trigger('warn', { + message: 'ignoring invalid discontinuity sequence: ' + entry.number + }); + return; + } + this.manifest.discontinuitySequence = entry.number; + currentTimeline = entry.number; + }, + 'playlist-type': function playlistType() { + if (!/VOD|EVENT/.test(entry.playlistType)) { + this.trigger('warn', { + message: 'ignoring unknown playlist type: ' + entry.playlist + }); + return; + } + this.manifest.playlistType = entry.playlistType; + }, + map: function map() { + currentMap = {}; + if (entry.uri) { + currentMap.uri = entry.uri; + } + if (entry.byterange) { + currentMap.byterange = entry.byterange; + } + }, + 'stream-inf': function streamInf() { + this.manifest.playlists = uris; + this.manifest.mediaGroups = this.manifest.mediaGroups || defaultMediaGroups; + + if (!entry.attributes) { + this.trigger('warn', { + message: 'ignoring empty stream-inf attributes' + }); + return; + } + + if (!currentUri.attributes) { + currentUri.attributes = {}; + } + _extends$1(currentUri.attributes, entry.attributes); + }, + media: function media() { + this.manifest.mediaGroups = this.manifest.mediaGroups || defaultMediaGroups; + + if (!(entry.attributes && entry.attributes.TYPE && entry.attributes['GROUP-ID'] && entry.attributes.NAME)) { + this.trigger('warn', { + message: 'ignoring incomplete or missing media group' + }); + return; + } + + // find the media group, creating defaults as necessary + var mediaGroupType = this.manifest.mediaGroups[entry.attributes.TYPE]; + + mediaGroupType[entry.attributes['GROUP-ID']] = mediaGroupType[entry.attributes['GROUP-ID']] || {}; + mediaGroup = mediaGroupType[entry.attributes['GROUP-ID']]; + + // collect the rendition metadata + rendition = { + 'default': /yes/i.test(entry.attributes.DEFAULT) + }; + if (rendition['default']) { + rendition.autoselect = true; + } else { + rendition.autoselect = /yes/i.test(entry.attributes.AUTOSELECT); + } + if (entry.attributes.LANGUAGE) { + rendition.language = entry.attributes.LANGUAGE; + } + if (entry.attributes.URI) { + rendition.uri = entry.attributes.URI; + } + if (entry.attributes['INSTREAM-ID']) { + rendition.instreamId = entry.attributes['INSTREAM-ID']; + } + if (entry.attributes.CHARACTERISTICS) { + rendition.characteristics = entry.attributes.CHARACTERISTICS; + } + if (entry.attributes.FORCED) { + rendition.forced = /yes/i.test(entry.attributes.FORCED); + } + + // insert the new rendition + mediaGroup[entry.attributes.NAME] = rendition; + }, + discontinuity: function discontinuity() { + currentTimeline += 1; + currentUri.discontinuity = true; + this.manifest.discontinuityStarts.push(uris.length); + }, + 'program-date-time': function programDateTime() { + if (typeof this.manifest.dateTimeString === 'undefined') { + // PROGRAM-DATE-TIME is a media-segment tag, but for backwards + // compatibility, we add the first occurence of the PROGRAM-DATE-TIME tag + // to the manifest object + // TODO: Consider removing this in future major version + this.manifest.dateTimeString = entry.dateTimeString; + this.manifest.dateTimeObject = entry.dateTimeObject; + } + + currentUri.dateTimeString = entry.dateTimeString; + currentUri.dateTimeObject = entry.dateTimeObject; + }, + targetduration: function targetduration() { + if (!isFinite(entry.duration) || entry.duration < 0) { + this.trigger('warn', { + message: 'ignoring invalid target duration: ' + entry.duration + }); + return; + } + this.manifest.targetDuration = entry.duration; + }, + totalduration: function totalduration() { + if (!isFinite(entry.duration) || entry.duration < 0) { + this.trigger('warn', { + message: 'ignoring invalid total duration: ' + entry.duration + }); + return; + } + this.manifest.totalDuration = entry.duration; + }, + start: function start() { + if (!entry.attributes || isNaN(entry.attributes['TIME-OFFSET'])) { + this.trigger('warn', { + message: 'ignoring start declaration without appropriate attribute list' + }); + return; + } + this.manifest.start = { + timeOffset: entry.attributes['TIME-OFFSET'], + precise: entry.attributes.PRECISE + }; + }, + 'cue-out': function cueOut() { + currentUri.cueOut = entry.data; + }, + 'cue-out-cont': function cueOutCont() { + currentUri.cueOutCont = entry.data; + }, + 'cue-in': function cueIn() { + currentUri.cueIn = entry.data; + } + })[entry.tagType] || noop).call(self); + }, + uri: function uri() { + currentUri.uri = entry.uri; + uris.push(currentUri); + + // if no explicit duration was declared, use the target duration + if (this.manifest.targetDuration && !('duration' in currentUri)) { + this.trigger('warn', { + message: 'defaulting segment duration to the target duration' + }); + currentUri.duration = this.manifest.targetDuration; + } + // annotate with encryption information, if necessary + if (_key) { + currentUri.key = _key; + } + currentUri.timeline = currentTimeline; + // annotate with initialization segment information, if necessary + if (currentMap) { + currentUri.map = currentMap; + } + + // prepare for the next URI + currentUri = {}; + }, + comment: function comment() { + // comments are not important for playback + }, + custom: function custom() { + // if this is segment-level data attach the output to the segment + if (entry.segment) { + currentUri.custom = currentUri.custom || {}; + currentUri.custom[entry.customType] = entry.data; + // if this is manifest-level data attach to the top level manifest object + } else { + this.manifest.custom = this.manifest.custom || {}; + this.manifest.custom[entry.customType] = entry.data; + } + } + })[entry.type].call(self); + }); + return _this; + } + + /** + * Parse the input string and update the manifest object. + * + * @param {String} chunk a potentially incomplete portion of the manifest + */ + + Parser.prototype.push = function push(chunk) { + this.lineStream.push(chunk); + }; + + /** + * Flush any remaining input. This can be handy if the last line of an M3U8 + * manifest did not contain a trailing newline but the file has been + * completely received. + */ + + Parser.prototype.end = function end() { + // flush any buffered input + this.lineStream.push('\n'); + }; + /** + * Add an additional parser for non-standard tags + * + * @param {Object} options a map of options for the added parser + * @param {RegExp} options.expression a regular expression to match the custom header + * @param {string} options.type the type to register to the output + * @param {Function} [options.dataParser] function to parse the line into an object + * @param {boolean} [options.segment] should tag data be attached to the segment object + */ + + Parser.prototype.addParser = function addParser(options) { + this.parseStream.addParser(options); + }; + + return Parser; + }(Stream); + + /** + * mpd-parser + * @version 0.6.0 + * @copyright 2018 Brightcove, Inc + * @license Apache-2.0 + */ + + var formatAudioPlaylist = function formatAudioPlaylist(_ref) { + var _attributes; + + var attributes = _ref.attributes, + segments = _ref.segments; + + var playlist = { + attributes: (_attributes = { + NAME: attributes.id, + BANDWIDTH: attributes.bandwidth, + CODECS: attributes.codecs + }, _attributes['PROGRAM-ID'] = 1, _attributes), + uri: '', + endList: (attributes.type || 'static') === 'static', + timeline: attributes.periodIndex, + resolvedUri: '', + targetDuration: attributes.duration, + segments: segments, + mediaSequence: segments.length ? segments[0].number : 1 + }; + + if (attributes.contentProtection) { + playlist.contentProtection = attributes.contentProtection; + } + + return playlist; + }; + + var formatVttPlaylist = function formatVttPlaylist(_ref2) { + var _attributes2; + + var attributes = _ref2.attributes, + segments = _ref2.segments; + + if (typeof segments === 'undefined') { + // vtt tracks may use single file in BaseURL + segments = [{ + uri: attributes.baseUrl, + timeline: attributes.periodIndex, + resolvedUri: attributes.baseUrl || '', + duration: attributes.sourceDuration, + number: 0 + }]; + // targetDuration should be the same duration as the only segment + attributes.duration = attributes.sourceDuration; + } + return { + attributes: (_attributes2 = { + NAME: attributes.id, + BANDWIDTH: attributes.bandwidth + }, _attributes2['PROGRAM-ID'] = 1, _attributes2), + uri: '', + endList: (attributes.type || 'static') === 'static', + timeline: attributes.periodIndex, + resolvedUri: attributes.baseUrl || '', + targetDuration: attributes.duration, + segments: segments, + mediaSequence: segments.length ? segments[0].number : 1 + }; + }; + + var organizeAudioPlaylists = function organizeAudioPlaylists(playlists) { + return playlists.reduce(function (a, playlist) { + var role = playlist.attributes.role && playlist.attributes.role.value || 'main'; + var language = playlist.attributes.lang || ''; + + var label = 'main'; + + if (language) { + label = playlist.attributes.lang + ' (' + role + ')'; + } + + // skip if we already have the highest quality audio for a language + if (a[label] && a[label].playlists[0].attributes.BANDWIDTH > playlist.attributes.bandwidth) { + return a; + } + + a[label] = { + language: language, + autoselect: true, + default: role === 'main', + playlists: [formatAudioPlaylist(playlist)], + uri: '' + }; + + return a; + }, {}); + }; + + var organizeVttPlaylists = function organizeVttPlaylists(playlists) { + return playlists.reduce(function (a, playlist) { + var label = playlist.attributes.lang || 'text'; + + // skip if we already have subtitles + if (a[label]) { + return a; + } + + a[label] = { + language: label, + default: false, + autoselect: false, + playlists: [formatVttPlaylist(playlist)], + uri: '' + }; + + return a; + }, {}); + }; + + var formatVideoPlaylist = function formatVideoPlaylist(_ref3) { + var _attributes3; + + var attributes = _ref3.attributes, + segments = _ref3.segments; + + var playlist = { + attributes: (_attributes3 = { + NAME: attributes.id, + AUDIO: 'audio', + SUBTITLES: 'subs', + RESOLUTION: { + width: attributes.width, + height: attributes.height + }, + CODECS: attributes.codecs, + BANDWIDTH: attributes.bandwidth + }, _attributes3['PROGRAM-ID'] = 1, _attributes3), + uri: '', + endList: (attributes.type || 'static') === 'static', + timeline: attributes.periodIndex, + resolvedUri: '', + targetDuration: attributes.duration, + segments: segments, + mediaSequence: segments.length ? segments[0].number : 1 + }; + + if (attributes.contentProtection) { + playlist.contentProtection = attributes.contentProtection; + } + + return playlist; + }; + + var toM3u8 = function toM3u8(dashPlaylists) { + var _mediaGroups; + + if (!dashPlaylists.length) { + return {}; + } + + // grab all master attributes + var _dashPlaylists$0$attr = dashPlaylists[0].attributes, + duration = _dashPlaylists$0$attr.sourceDuration, + _dashPlaylists$0$attr2 = _dashPlaylists$0$attr.minimumUpdatePeriod, + minimumUpdatePeriod = _dashPlaylists$0$attr2 === undefined ? 0 : _dashPlaylists$0$attr2; + + + var videoOnly = function videoOnly(_ref4) { + var attributes = _ref4.attributes; + return attributes.mimeType === 'video/mp4' || attributes.contentType === 'video'; + }; + var audioOnly = function audioOnly(_ref5) { + var attributes = _ref5.attributes; + return attributes.mimeType === 'audio/mp4' || attributes.contentType === 'audio'; + }; + var vttOnly = function vttOnly(_ref6) { + var attributes = _ref6.attributes; + return attributes.mimeType === 'text/vtt' || attributes.contentType === 'text'; + }; + + var videoPlaylists = dashPlaylists.filter(videoOnly).map(formatVideoPlaylist); + var audioPlaylists = dashPlaylists.filter(audioOnly); + var vttPlaylists = dashPlaylists.filter(vttOnly); + + var master = { + allowCache: true, + discontinuityStarts: [], + segments: [], + endList: true, + mediaGroups: (_mediaGroups = { + AUDIO: {}, + VIDEO: {} + }, _mediaGroups['CLOSED-CAPTIONS'] = {}, _mediaGroups.SUBTITLES = {}, _mediaGroups), + uri: '', + duration: duration, + playlists: videoPlaylists, + minimumUpdatePeriod: minimumUpdatePeriod * 1000 + }; + + if (audioPlaylists.length) { + master.mediaGroups.AUDIO.audio = organizeAudioPlaylists(audioPlaylists); + } + + if (vttPlaylists.length) { + master.mediaGroups.SUBTITLES.subs = organizeVttPlaylists(vttPlaylists); + } + + return master; + }; + + var isObject$1 = function isObject(obj) { + return !!obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object'; + }; + + var merge = function merge() { + for (var _len = arguments.length, objects = Array(_len), _key = 0; _key < _len; _key++) { + objects[_key] = arguments[_key]; + } + + return objects.reduce(function (result, source) { + + Object.keys(source).forEach(function (key) { + + if (Array.isArray(result[key]) && Array.isArray(source[key])) { + result[key] = result[key].concat(source[key]); + } else if (isObject$1(result[key]) && isObject$1(source[key])) { + result[key] = merge(result[key], source[key]); + } else { + result[key] = source[key]; + } + }); + return result; + }, {}); + }; + + var resolveUrl = function resolveUrl(baseUrl, relativeUrl) { + // return early if we don't need to resolve + if (/^[a-z]+:/i.test(relativeUrl)) { + return relativeUrl; + } + + // if the base URL is relative then combine with the current location + if (!/\/\//i.test(baseUrl)) { + baseUrl = urlToolkit.buildAbsoluteURL(window_1.location.href, baseUrl); + } + + return urlToolkit.buildAbsoluteURL(baseUrl, relativeUrl); + }; + + /** + * @typedef {Object} SingleUri + * @property {string} uri - relative location of segment + * @property {string} resolvedUri - resolved location of segment + * @property {Object} byterange - Object containing information on how to make byte range + * requests following byte-range-spec per RFC2616. + * @property {String} byterange.length - length of range request + * @property {String} byterange.offset - byte offset of range request + * + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1 + */ + + /** + * Converts a URLType node (5.3.9.2.3 Table 13) to a segment object + * that conforms to how m3u8-parser is structured + * + * @see https://github.com/videojs/m3u8-parser + * + * @param {string} baseUrl - baseUrl provided by <BaseUrl> nodes + * @param {string} source - source url for segment + * @param {string} range - optional range used for range calls, follows + * @return {SingleUri} full segment information transformed into a format similar + * to m3u8-parser + */ + var urlTypeToSegment = function urlTypeToSegment(_ref7) { + var _ref7$baseUrl = _ref7.baseUrl, + baseUrl = _ref7$baseUrl === undefined ? '' : _ref7$baseUrl, + _ref7$source = _ref7.source, + source = _ref7$source === undefined ? '' : _ref7$source, + _ref7$range = _ref7.range, + range = _ref7$range === undefined ? '' : _ref7$range; + + var init = { + uri: source, + resolvedUri: resolveUrl(baseUrl || '', source) + }; + + if (range) { + var ranges = range.split('-'); + var startRange = parseInt(ranges[0], 10); + var endRange = parseInt(ranges[1], 10); + + init.byterange = { + length: endRange - startRange, + offset: startRange + }; + } + + return init; + }; + + /** + * Calculates the R (repetition) value for a live stream (for the final segment + * in a manifest where the r value is negative 1) + * + * @param {Object} attributes + * Object containing all inherited attributes from parent elements with attribute + * names as keys + * @param {number} time + * current time (typically the total time up until the final segment) + * @param {number} duration + * duration property for the given <S /> + * + * @return {number} + * R value to reach the end of the given period + */ + var getLiveRValue = function getLiveRValue(attributes, time, duration) { + var NOW = attributes.NOW, + clientOffset = attributes.clientOffset, + availabilityStartTime = attributes.availabilityStartTime, + _attributes$timescale = attributes.timescale, + timescale = _attributes$timescale === undefined ? 1 : _attributes$timescale, + _attributes$start = attributes.start, + start = _attributes$start === undefined ? 0 : _attributes$start, + _attributes$minimumUp = attributes.minimumUpdatePeriod, + minimumUpdatePeriod = _attributes$minimumUp === undefined ? 0 : _attributes$minimumUp; + + var now = (NOW + clientOffset) / 1000; + var periodStartWC = availabilityStartTime + start; + var periodEndWC = now + minimumUpdatePeriod; + var periodDuration = periodEndWC - periodStartWC; + + return Math.ceil((periodDuration * timescale - time) / duration); + }; + + /** + * Uses information provided by SegmentTemplate.SegmentTimeline to determine segment + * timing and duration + * + * @param {Object} attributes + * Object containing all inherited attributes from parent elements with attribute + * names as keys + * @param {Object[]} segmentTimeline + * List of objects representing the attributes of each S element contained within + * + * @return {{number: number, duration: number, time: number, timeline: number}[]} + * List of Objects with segment timing and duration info + */ + var parseByTimeline = function parseByTimeline(attributes, segmentTimeline) { + var _attributes$type = attributes.type, + type = _attributes$type === undefined ? 'static' : _attributes$type, + _attributes$minimumUp2 = attributes.minimumUpdatePeriod, + minimumUpdatePeriod = _attributes$minimumUp2 === undefined ? 0 : _attributes$minimumUp2, + _attributes$media = attributes.media, + media = _attributes$media === undefined ? '' : _attributes$media, + sourceDuration = attributes.sourceDuration, + _attributes$timescale2 = attributes.timescale, + timescale = _attributes$timescale2 === undefined ? 1 : _attributes$timescale2, + _attributes$startNumb = attributes.startNumber, + startNumber = _attributes$startNumb === undefined ? 1 : _attributes$startNumb, + timeline = attributes.periodIndex; + + var segments = []; + var time = -1; + + for (var sIndex = 0; sIndex < segmentTimeline.length; sIndex++) { + var S = segmentTimeline[sIndex]; + var duration = S.d; + var repeat = S.r || 0; + var segmentTime = S.t || 0; + + if (time < 0) { + // first segment + time = segmentTime; + } + + if (segmentTime && segmentTime > time) { + // discontinuity + + // TODO: How to handle this type of discontinuity + // timeline++ here would treat it like HLS discontuity and content would + // get appended without gap + // E.G. + // <S t="0" d="1" /> + // <S d="1" /> + // <S d="1" /> + // <S t="5" d="1" /> + // would have $Time$ values of [0, 1, 2, 5] + // should this be appened at time positions [0, 1, 2, 3],(#EXT-X-DISCONTINUITY) + // or [0, 1, 2, gap, gap, 5]? (#EXT-X-GAP) + // does the value of sourceDuration consider this when calculating arbitrary + // negative @r repeat value? + // E.G. Same elements as above with this added at the end + // <S d="1" r="-1" /> + // with a sourceDuration of 10 + // Would the 2 gaps be included in the time duration calculations resulting in + // 8 segments with $Time$ values of [0, 1, 2, 5, 6, 7, 8, 9] or 10 segments + // with $Time$ values of [0, 1, 2, 5, 6, 7, 8, 9, 10, 11] ? + + time = segmentTime; + } + + var count = void 0; + + if (repeat < 0) { + var nextS = sIndex + 1; + + if (nextS === segmentTimeline.length) { + // last segment + if (type === 'dynamic' && minimumUpdatePeriod > 0 && media.indexOf('$Number$') > 0) { + count = getLiveRValue(attributes, time, duration); + } else { + // TODO: This may be incorrect depending on conclusion of TODO above + count = (sourceDuration * timescale - time) / duration; + } + } else { + count = (segmentTimeline[nextS].t - time) / duration; + } + } else { + count = repeat + 1; + } + + var end = startNumber + segments.length + count; + var number = startNumber + segments.length; + + while (number < end) { + segments.push({number: number, duration: duration / timescale, time: time, timeline: timeline}); + time += duration; + number++; + } + } + + return segments; + }; + + var range = function range(start, end) { + var result = []; + + for (var i = start; i < end; i++) { + result.push(i); + } + + return result; + }; + + var flatten = function flatten(lists) { + return lists.reduce(function (x, y) { + return x.concat(y); + }, []); + }; + + var from = function from(list) { + if (!list.length) { + return []; + } + + var result = []; + + for (var i = 0; i < list.length; i++) { + result.push(list[i]); + } + + return result; + }; + + /** + * Functions for calculating the range of available segments in static and dynamic + * manifests. + */ + var segmentRange = { + /** + * Returns the entire range of available segments for a static MPD + * + * @param {Object} attributes + * Inheritied MPD attributes + * @return {{ start: number, end: number }} + * The start and end numbers for available segments + */ + static: function _static(attributes) { + var duration = attributes.duration, + _attributes$timescale3 = attributes.timescale, + timescale = _attributes$timescale3 === undefined ? 1 : _attributes$timescale3, + sourceDuration = attributes.sourceDuration; + + + return { + start: 0, + end: Math.ceil(sourceDuration / (duration / timescale)) + }; + }, + + + /** + * Returns the current live window range of available segments for a dynamic MPD + * + * @param {Object} attributes + * Inheritied MPD attributes + * @return {{ start: number, end: number }} + * The start and end numbers for available segments + */ + dynamic: function dynamic(attributes) { + var NOW = attributes.NOW, + clientOffset = attributes.clientOffset, + availabilityStartTime = attributes.availabilityStartTime, + _attributes$timescale4 = attributes.timescale, + timescale = _attributes$timescale4 === undefined ? 1 : _attributes$timescale4, + duration = attributes.duration, + _attributes$start2 = attributes.start, + start = _attributes$start2 === undefined ? 0 : _attributes$start2, + _attributes$minimumUp3 = attributes.minimumUpdatePeriod, + minimumUpdatePeriod = _attributes$minimumUp3 === undefined ? 0 : _attributes$minimumUp3, + _attributes$timeShift = attributes.timeShiftBufferDepth, + timeShiftBufferDepth = _attributes$timeShift === undefined ? Infinity : _attributes$timeShift; + + var now = (NOW + clientOffset) / 1000; + var periodStartWC = availabilityStartTime + start; + var periodEndWC = now + minimumUpdatePeriod; + var periodDuration = periodEndWC - periodStartWC; + var segmentCount = Math.ceil(periodDuration * timescale / duration); + var availableStart = Math.floor((now - periodStartWC - timeShiftBufferDepth) * timescale / duration); + var availableEnd = Math.floor((now - periodStartWC) * timescale / duration); + + return { + start: Math.max(0, availableStart), + end: Math.min(segmentCount, availableEnd) + }; + } + }; + + /** + * Maps a range of numbers to objects with information needed to build the corresponding + * segment list + * + * @name toSegmentsCallback + * @function + * @param {number} number + * Number of the segment + * @param {number} index + * Index of the number in the range list + * @return {{ number: Number, duration: Number, timeline: Number, time: Number }} + * Object with segment timing and duration info + */ + + /** + * Returns a callback for Array.prototype.map for mapping a range of numbers to + * information needed to build the segment list. + * + * @param {Object} attributes + * Inherited MPD attributes + * @return {toSegmentsCallback} + * Callback map function + */ + var toSegments = function toSegments(attributes) { + return function (number, index) { + var duration = attributes.duration, + _attributes$timescale5 = attributes.timescale, + timescale = _attributes$timescale5 === undefined ? 1 : _attributes$timescale5, + periodIndex = attributes.periodIndex, + _attributes$startNumb2 = attributes.startNumber, + startNumber = _attributes$startNumb2 === undefined ? 1 : _attributes$startNumb2; + + + return { + number: startNumber + number, + duration: duration / timescale, + timeline: periodIndex, + time: index * duration + }; + }; + }; + + /** + * Returns a list of objects containing segment timing and duration info used for + * building the list of segments. This uses the @duration attribute specified + * in the MPD manifest to derive the range of segments. + * + * @param {Object} attributes + * Inherited MPD attributes + * @return {{number: number, duration: number, time: number, timeline: number}[]} + * List of Objects with segment timing and duration info + */ + var parseByDuration = function parseByDuration(attributes) { + var _attributes$type2 = attributes.type, + type = _attributes$type2 === undefined ? 'static' : _attributes$type2, + duration = attributes.duration, + _attributes$timescale6 = attributes.timescale, + timescale = _attributes$timescale6 === undefined ? 1 : _attributes$timescale6, + sourceDuration = attributes.sourceDuration; + + var _segmentRange$type = segmentRange[type](attributes), + start = _segmentRange$type.start, + end = _segmentRange$type.end; + + var segments = range(start, end).map(toSegments(attributes)); + + if (type === 'static') { + var index = segments.length - 1; + + // final segment may be less than full segment duration + segments[index].duration = sourceDuration - duration / timescale * index; + } + + return segments; + }; + + var identifierPattern = /\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g; + + /** + * Replaces template identifiers with corresponding values. To be used as the callback + * for String.prototype.replace + * + * @name replaceCallback + * @function + * @param {string} match + * Entire match of identifier + * @param {string} identifier + * Name of matched identifier + * @param {string} format + * Format tag string. Its presence indicates that padding is expected + * @param {string} width + * Desired length of the replaced value. Values less than this width shall be left + * zero padded + * @return {string} + * Replacement for the matched identifier + */ + + /** + * Returns a function to be used as a callback for String.prototype.replace to replace + * template identifiers + * + * @param {Obect} values + * Object containing values that shall be used to replace known identifiers + * @param {number} values.RepresentationID + * Value of the Representation@id attribute + * @param {number} values.Number + * Number of the corresponding segment + * @param {number} values.Bandwidth + * Value of the Representation@bandwidth attribute. + * @param {number} values.Time + * Timestamp value of the corresponding segment + * @return {replaceCallback} + * Callback to be used with String.prototype.replace to replace identifiers + */ + var identifierReplacement = function identifierReplacement(values) { + return function (match, identifier, format, width) { + if (match === '$$') { + // escape sequence + return '$'; + } + + if (typeof values[identifier] === 'undefined') { + return match; + } + + var value = '' + values[identifier]; + + if (identifier === 'RepresentationID') { + // Format tag shall not be present with RepresentationID + return value; + } + + if (!format) { + width = 1; + } else { + width = parseInt(width, 10); + } + + if (value.length >= width) { + return value; + } + + return '' + new Array(width - value.length + 1).join('0') + value; + }; + }; + + /** + * Constructs a segment url from a template string + * + * @param {string} url + * Template string to construct url from + * @param {Obect} values + * Object containing values that shall be used to replace known identifiers + * @param {number} values.RepresentationID + * Value of the Representation@id attribute + * @param {number} values.Number + * Number of the corresponding segment + * @param {number} values.Bandwidth + * Value of the Representation@bandwidth attribute. + * @param {number} values.Time + * Timestamp value of the corresponding segment + * @return {string} + * Segment url with identifiers replaced + */ + var constructTemplateUrl = function constructTemplateUrl(url, values) { + return url.replace(identifierPattern, identifierReplacement(values)); + }; + + /** + * Generates a list of objects containing timing and duration information about each + * segment needed to generate segment uris and the complete segment object + * + * @param {Object} attributes + * Object containing all inherited attributes from parent elements with attribute + * names as keys + * @param {Object[]|undefined} segmentTimeline + * List of objects representing the attributes of each S element contained within + * the SegmentTimeline element + * @return {{number: number, duration: number, time: number, timeline: number}[]} + * List of Objects with segment timing and duration info + */ + var parseTemplateInfo = function parseTemplateInfo(attributes, segmentTimeline) { + if (!attributes.duration && !segmentTimeline) { + // if neither @duration or SegmentTimeline are present, then there shall be exactly + // one media segment + return [{ + number: attributes.startNumber || 1, + duration: attributes.sourceDuration, + time: 0, + timeline: attributes.periodIndex + }]; + } + + if (attributes.duration) { + return parseByDuration(attributes); + } + + return parseByTimeline(attributes, segmentTimeline); + }; + + /** + * Generates a list of segments using information provided by the SegmentTemplate element + * + * @param {Object} attributes + * Object containing all inherited attributes from parent elements with attribute + * names as keys + * @param {Object[]|undefined} segmentTimeline + * List of objects representing the attributes of each S element contained within + * the SegmentTimeline element + * @return {Object[]} + * List of segment objects + */ + var segmentsFromTemplate = function segmentsFromTemplate(attributes, segmentTimeline) { + var templateValues = { + RepresentationID: attributes.id, + Bandwidth: attributes.bandwidth || 0 + }; + + var _attributes$initializ = attributes.initialization, + initialization = _attributes$initializ === undefined ? {sourceURL: '', range: ''} : _attributes$initializ; + + + var mapSegment = urlTypeToSegment({ + baseUrl: attributes.baseUrl, + source: constructTemplateUrl(initialization.sourceURL, templateValues), + range: initialization.range + }); + + var segments = parseTemplateInfo(attributes, segmentTimeline); + + return segments.map(function (segment) { + templateValues.Number = segment.number; + templateValues.Time = segment.time; + + var uri = constructTemplateUrl(attributes.media || '', templateValues); + + return { + uri: uri, + timeline: segment.timeline, + duration: segment.duration, + resolvedUri: resolveUrl(attributes.baseUrl || '', uri), + map: mapSegment, + number: segment.number + }; + }); + }; + + var errors = { + INVALID_NUMBER_OF_PERIOD: 'INVALID_NUMBER_OF_PERIOD', + DASH_EMPTY_MANIFEST: 'DASH_EMPTY_MANIFEST', + DASH_INVALID_XML: 'DASH_INVALID_XML', + NO_BASE_URL: 'NO_BASE_URL', + MISSING_SEGMENT_INFORMATION: 'MISSING_SEGMENT_INFORMATION', + SEGMENT_TIME_UNSPECIFIED: 'SEGMENT_TIME_UNSPECIFIED', + UNSUPPORTED_UTC_TIMING_SCHEME: 'UNSUPPORTED_UTC_TIMING_SCHEME' + }; + + /** + * Converts a <SegmentUrl> (of type URLType from the DASH spec 5.3.9.2 Table 14) + * to an object that matches the output of a segment in videojs/mpd-parser + * + * @param {Object} attributes + * Object containing all inherited attributes from parent elements with attribute + * names as keys + * @param {Object} segmentUrl + * <SegmentURL> node to translate into a segment object + * @return {Object} translated segment object + */ + var SegmentURLToSegmentObject = function SegmentURLToSegmentObject(attributes, segmentUrl) { + var baseUrl = attributes.baseUrl, + _attributes$initializ2 = attributes.initialization, + initialization = _attributes$initializ2 === undefined ? {} : _attributes$initializ2; + + + var initSegment = urlTypeToSegment({ + baseUrl: baseUrl, + source: initialization.sourceURL, + range: initialization.range + }); + + var segment = urlTypeToSegment({ + baseUrl: baseUrl, + source: segmentUrl.media, + range: segmentUrl.mediaRange + }); + + segment.map = initSegment; + + return segment; + }; + + /** + * Generates a list of segments using information provided by the SegmentList element + * SegmentList (DASH SPEC Section 5.3.9.3.2) contains a set of <SegmentURL> nodes. Each + * node should be translated into segment. + * + * @param {Object} attributes + * Object containing all inherited attributes from parent elements with attribute + * names as keys + * @param {Object[]|undefined} segmentTimeline + * List of objects representing the attributes of each S element contained within + * the SegmentTimeline element + * @return {Object.<Array>} list of segments + */ + var segmentsFromList = function segmentsFromList(attributes, segmentTimeline) { + var duration = attributes.duration, + _attributes$segmentUr = attributes.segmentUrls, + segmentUrls = _attributes$segmentUr === undefined ? [] : _attributes$segmentUr; + + // Per spec (5.3.9.2.1) no way to determine segment duration OR + // if both SegmentTimeline and @duration are defined, it is outside of spec. + + if (!duration && !segmentTimeline || duration && segmentTimeline) { + throw new Error(errors.SEGMENT_TIME_UNSPECIFIED); + } + + var segmentUrlMap = segmentUrls.map(function (segmentUrlObject) { + return SegmentURLToSegmentObject(attributes, segmentUrlObject); + }); + var segmentTimeInfo = void 0; + + if (duration) { + segmentTimeInfo = parseByDuration(attributes); + } + + if (segmentTimeline) { + segmentTimeInfo = parseByTimeline(attributes, segmentTimeline); + } + + var segments = segmentTimeInfo.map(function (segmentTime, index) { + if (segmentUrlMap[index]) { + var segment = segmentUrlMap[index]; + + segment.timeline = segmentTime.timeline; + segment.duration = segmentTime.duration; + segment.number = segmentTime.number; + return segment; + } + // Since we're mapping we should get rid of any blank segments (in case + // the given SegmentTimeline is handling for more elements than we have + // SegmentURLs for). + }).filter(function (segment) { + return segment; + }); + + return segments; + }; + + /** + * Translates SegmentBase into a set of segments. + * (DASH SPEC Section 5.3.9.3.2) contains a set of <SegmentURL> nodes. Each + * node should be translated into segment. + * + * @param {Object} attributes + * Object containing all inherited attributes from parent elements with attribute + * names as keys + * @return {Object.<Array>} list of segments + */ + var segmentsFromBase = function segmentsFromBase(attributes) { + var baseUrl = attributes.baseUrl, + _attributes$initializ3 = attributes.initialization, + initialization = _attributes$initializ3 === undefined ? {} : _attributes$initializ3, + sourceDuration = attributes.sourceDuration, + _attributes$timescale7 = attributes.timescale, + timescale = _attributes$timescale7 === undefined ? 1 : _attributes$timescale7, + _attributes$indexRang = attributes.indexRange, + indexRange = _attributes$indexRang === undefined ? '' : _attributes$indexRang, + duration = attributes.duration; + + // base url is required for SegmentBase to work, per spec (Section 5.3.9.2.1) + + if (!baseUrl) { + throw new Error(errors.NO_BASE_URL); + } + + var initSegment = urlTypeToSegment({ + baseUrl: baseUrl, + source: initialization.sourceURL, + range: initialization.range + }); + var segment = urlTypeToSegment({baseUrl: baseUrl, source: baseUrl, range: indexRange}); + + segment.map = initSegment; + + // If there is a duration, use it, otherwise use the given duration of the source + // (since SegmentBase is only for one total segment) + if (duration) { + var segmentTimeInfo = parseByDuration(attributes); + + if (segmentTimeInfo.length) { + segment.duration = segmentTimeInfo[0].duration; + segment.timeline = segmentTimeInfo[0].timeline; + } + } else if (sourceDuration) { + segment.duration = sourceDuration / timescale; + segment.timeline = 0; + } + + // This is used for mediaSequence + segment.number = 0; + + return [segment]; + }; + + var generateSegments = function generateSegments(_ref8) { + var attributes = _ref8.attributes, + segmentInfo = _ref8.segmentInfo; + + var segmentAttributes = void 0; + var segmentsFn = void 0; + + if (segmentInfo.template) { + segmentsFn = segmentsFromTemplate; + segmentAttributes = merge(attributes, segmentInfo.template); + } else if (segmentInfo.base) { + segmentsFn = segmentsFromBase; + segmentAttributes = merge(attributes, segmentInfo.base); + } else if (segmentInfo.list) { + segmentsFn = segmentsFromList; + segmentAttributes = merge(attributes, segmentInfo.list); + } + + if (!segmentsFn) { + return {attributes: attributes}; + } + + var segments = segmentsFn(segmentAttributes, segmentInfo.timeline); + + // The @duration attribute will be used to determin the playlist's targetDuration which + // must be in seconds. Since we've generated the segment list, we no longer need + // @duration to be in @timescale units, so we can convert it here. + if (segmentAttributes.duration) { + var _segmentAttributes = segmentAttributes, + duration = _segmentAttributes.duration, + _segmentAttributes$ti = _segmentAttributes.timescale, + timescale = _segmentAttributes$ti === undefined ? 1 : _segmentAttributes$ti; + + + segmentAttributes.duration = duration / timescale; + } else if (segments.length) { + // if there is no @duration attribute, use the largest segment duration as + // as target duration + segmentAttributes.duration = segments.reduce(function (max, segment) { + return Math.max(max, Math.ceil(segment.duration)); + }, 0); + } else { + segmentAttributes.duration = 0; + } + + return { + attributes: segmentAttributes, + segments: segments + }; + }; + + var toPlaylists = function toPlaylists(representations) { + return representations.map(generateSegments); + }; + + var findChildren = function findChildren(element, name) { + return from(element.childNodes).filter(function (_ref9) { + var tagName = _ref9.tagName; + return tagName === name; + }); + }; + + var getContent = function getContent(element) { + return element.textContent.trim(); + }; + + var parseDuration = function parseDuration(str) { + var SECONDS_IN_YEAR = 365 * 24 * 60 * 60; + var SECONDS_IN_MONTH = 30 * 24 * 60 * 60; + var SECONDS_IN_DAY = 24 * 60 * 60; + var SECONDS_IN_HOUR = 60 * 60; + var SECONDS_IN_MIN = 60; + + // P10Y10M10DT10H10M10.1S + var durationRegex = /P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/; + var match = durationRegex.exec(str); + + if (!match) { + return 0; + } + + var _match$slice = match.slice(1), + year = _match$slice[0], + month = _match$slice[1], + day = _match$slice[2], + hour = _match$slice[3], + minute = _match$slice[4], + second = _match$slice[5]; + + return parseFloat(year || 0) * SECONDS_IN_YEAR + parseFloat(month || 0) * SECONDS_IN_MONTH + parseFloat(day || 0) * SECONDS_IN_DAY + parseFloat(hour || 0) * SECONDS_IN_HOUR + parseFloat(minute || 0) * SECONDS_IN_MIN + parseFloat(second || 0); + }; + + var parseDate = function parseDate(str) { + // Date format without timezone according to ISO 8601 + // YYY-MM-DDThh:mm:ss.ssssss + var dateRegex = /^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/; + + // If the date string does not specifiy a timezone, we must specifiy UTC. This is + // expressed by ending with 'Z' + if (dateRegex.test(str)) { + str += 'Z'; + } + + return Date.parse(str); + }; + + // TODO: maybe order these in some way that makes it easy to find specific attributes + var parsers = { + /** + * Specifies the duration of the entire Media Presentation. Format is a duration string + * as specified in ISO 8601 + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The duration in seconds + */ + mediaPresentationDuration: function mediaPresentationDuration(value) { + return parseDuration(value); + }, + + + /** + * Specifies the Segment availability start time for all Segments referred to in this + * MPD. For a dynamic manifest, it specifies the anchor for the earliest availability + * time. Format is a date string as specified in ISO 8601 + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The date as seconds from unix epoch + */ + availabilityStartTime: function availabilityStartTime(value) { + return parseDate(value) / 1000; + }, + + + /** + * Specifies the smallest period between potential changes to the MPD. Format is a + * duration string as specified in ISO 8601 + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The duration in seconds + */ + minimumUpdatePeriod: function minimumUpdatePeriod(value) { + return parseDuration(value); + }, + + + /** + * Specifies the duration of the smallest time shifting buffer for any Representation + * in the MPD. Format is a duration string as specified in ISO 8601 + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The duration in seconds + */ + timeShiftBufferDepth: function timeShiftBufferDepth(value) { + return parseDuration(value); + }, + + + /** + * Specifies the PeriodStart time of the Period relative to the availabilityStarttime. + * Format is a duration string as specified in ISO 8601 + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The duration in seconds + */ + start: function start(value) { + return parseDuration(value); + }, + + + /** + * Specifies the width of the visual presentation + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The parsed width + */ + width: function width(value) { + return parseInt(value, 10); + }, + + + /** + * Specifies the height of the visual presentation + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The parsed height + */ + height: function height(value) { + return parseInt(value, 10); + }, + + + /** + * Specifies the bitrate of the representation + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The parsed bandwidth + */ + bandwidth: function bandwidth(value) { + return parseInt(value, 10); + }, + + + /** + * Specifies the number of the first Media Segment in this Representation in the Period + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The parsed number + */ + startNumber: function startNumber(value) { + return parseInt(value, 10); + }, + + + /** + * Specifies the timescale in units per seconds + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The aprsed timescale + */ + timescale: function timescale(value) { + return parseInt(value, 10); + }, + + + /** + * Specifies the constant approximate Segment duration + * NOTE: The <Period> element also contains an @duration attribute. This duration + * specifies the duration of the Period. This attribute is currently not + * supported by the rest of the parser, however we still check for it to prevent + * errors. + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The parsed duration + */ + duration: function duration(value) { + var parsedValue = parseInt(value, 10); + + if (isNaN(parsedValue)) { + return parseDuration(value); + } + + return parsedValue; + }, + + + /** + * Specifies the Segment duration, in units of the value of the @timescale. + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The parsed duration + */ + d: function d(value) { + return parseInt(value, 10); + }, + + + /** + * Specifies the MPD start time, in @timescale units, the first Segment in the series + * starts relative to the beginning of the Period + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The parsed time + */ + t: function t(value) { + return parseInt(value, 10); + }, + + + /** + * Specifies the repeat count of the number of following contiguous Segments with the + * same duration expressed by the value of @d + * + * @param {string} value + * value of attribute as a string + * @return {number} + * The parsed number + */ + r: function r(value) { + return parseInt(value, 10); + }, + + + /** + * Default parser for all other attributes. Acts as a no-op and just returns the value + * as a string + * + * @param {string} value + * value of attribute as a string + * @return {string} + * Unparsed value + */ + DEFAULT: function DEFAULT(value) { + return value; + } + }; + + /** + * Gets all the attributes and values of the provided node, parses attributes with known + * types, and returns an object with attribute names mapped to values. + * + * @param {Node} el + * The node to parse attributes from + * @return {Object} + * Object with all attributes of el parsed + */ + var parseAttributes$1 = function parseAttributes(el) { + if (!(el && el.attributes)) { + return {}; + } + + return from(el.attributes).reduce(function (a, e) { + var parseFn = parsers[e.name] || parsers.DEFAULT; + + a[e.name] = parseFn(e.value); + + return a; + }, {}); + }; + + function decodeB64ToUint8Array(b64Text) { + var decodedString = window_1.atob(b64Text); + var array = new Uint8Array(decodedString.length); + + for (var i = 0; i < decodedString.length; i++) { + array[i] = decodedString.charCodeAt(i); + } + return array; + } + + var keySystemsMap = { + 'urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b': 'org.w3.clearkey', + 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed': 'com.widevine.alpha', + 'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95': 'com.microsoft.playready', + 'urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb': 'com.adobe.primetime' + }; + + /** + * Builds a list of urls that is the product of the reference urls and BaseURL values + * + * @param {string[]} referenceUrls + * List of reference urls to resolve to + * @param {Node[]} baseUrlElements + * List of BaseURL nodes from the mpd + * @return {string[]} + * List of resolved urls + */ + var buildBaseUrls = function buildBaseUrls(referenceUrls, baseUrlElements) { + if (!baseUrlElements.length) { + return referenceUrls; + } + + return flatten(referenceUrls.map(function (reference) { + return baseUrlElements.map(function (baseUrlElement) { + return resolveUrl(reference, getContent(baseUrlElement)); + }); + })); + }; + + /** + * Contains all Segment information for its containing AdaptationSet + * + * @typedef {Object} SegmentInformation + * @property {Object|undefined} template + * Contains the attributes for the SegmentTemplate node + * @property {Object[]|undefined} timeline + * Contains a list of atrributes for each S node within the SegmentTimeline node + * @property {Object|undefined} list + * Contains the attributes for the SegmentList node + * @property {Object|undefined} base + * Contains the attributes for the SegmentBase node + */ + + /** + * Returns all available Segment information contained within the AdaptationSet node + * + * @param {Node} adaptationSet + * The AdaptationSet node to get Segment information from + * @return {SegmentInformation} + * The Segment information contained within the provided AdaptationSet + */ + var getSegmentInformation = function getSegmentInformation(adaptationSet) { + var segmentTemplate = findChildren(adaptationSet, 'SegmentTemplate')[0]; + var segmentList = findChildren(adaptationSet, 'SegmentList')[0]; + var segmentUrls = segmentList && findChildren(segmentList, 'SegmentURL').map(function (s) { + return merge({tag: 'SegmentURL'}, parseAttributes$1(s)); + }); + var segmentBase = findChildren(adaptationSet, 'SegmentBase')[0]; + var segmentTimelineParentNode = segmentList || segmentTemplate; + var segmentTimeline = segmentTimelineParentNode && findChildren(segmentTimelineParentNode, 'SegmentTimeline')[0]; + var segmentInitializationParentNode = segmentList || segmentBase || segmentTemplate; + var segmentInitialization = segmentInitializationParentNode && findChildren(segmentInitializationParentNode, 'Initialization')[0]; + + // SegmentTemplate is handled slightly differently, since it can have both + // @initialization and an <Initialization> node. @initialization can be templated, + // while the node can have a url and range specified. If the <SegmentTemplate> has + // both @initialization and an <Initialization> subelement we opt to override with + // the node, as this interaction is not defined in the spec. + var template = segmentTemplate && parseAttributes$1(segmentTemplate); + + if (template && segmentInitialization) { + template.initialization = segmentInitialization && parseAttributes$1(segmentInitialization); + } else if (template && template.initialization) { + // If it is @initialization we convert it to an object since this is the format that + // later functions will rely on for the initialization segment. This is only valid + // for <SegmentTemplate> + template.initialization = {sourceURL: template.initialization}; + } + + var segmentInfo = { + template: template, + timeline: segmentTimeline && findChildren(segmentTimeline, 'S').map(function (s) { + return parseAttributes$1(s); + }), + list: segmentList && merge(parseAttributes$1(segmentList), { + segmentUrls: segmentUrls, + initialization: parseAttributes$1(segmentInitialization) + }), + base: segmentBase && merge(parseAttributes$1(segmentBase), { + initialization: parseAttributes$1(segmentInitialization) + }) + }; + + Object.keys(segmentInfo).forEach(function (key) { + if (!segmentInfo[key]) { + delete segmentInfo[key]; + } + }); + + return segmentInfo; + }; + + /** + * Contains Segment information and attributes needed to construct a Playlist object + * from a Representation + * + * @typedef {Object} RepresentationInformation + * @property {SegmentInformation} segmentInfo + * Segment information for this Representation + * @property {Object} attributes + * Inherited attributes for this Representation + */ + + /** + * Maps a Representation node to an object containing Segment information and attributes + * + * @name inheritBaseUrlsCallback + * @function + * @param {Node} representation + * Representation node from the mpd + * @return {RepresentationInformation} + * Representation information needed to construct a Playlist object + */ + + /** + * Returns a callback for Array.prototype.map for mapping Representation nodes to + * Segment information and attributes using inherited BaseURL nodes. + * + * @param {Object} adaptationSetAttributes + * Contains attributes inherited by the AdaptationSet + * @param {string[]} adaptationSetBaseUrls + * Contains list of resolved base urls inherited by the AdaptationSet + * @param {SegmentInformation} adaptationSetSegmentInfo + * Contains Segment information for the AdaptationSet + * @return {inheritBaseUrlsCallback} + * Callback map function + */ + var inheritBaseUrls = function inheritBaseUrls(adaptationSetAttributes, adaptationSetBaseUrls, adaptationSetSegmentInfo) { + return function (representation) { + var repBaseUrlElements = findChildren(representation, 'BaseURL'); + var repBaseUrls = buildBaseUrls(adaptationSetBaseUrls, repBaseUrlElements); + var attributes = merge(adaptationSetAttributes, parseAttributes$1(representation)); + var representationSegmentInfo = getSegmentInformation(representation); + + return repBaseUrls.map(function (baseUrl) { + return { + segmentInfo: merge(adaptationSetSegmentInfo, representationSegmentInfo), + attributes: merge(attributes, {baseUrl: baseUrl}) + }; + }); + }; + }; + + /** + * Tranforms a series of content protection nodes to + * an object containing pssh data by key system + * + * @param {Node[]} contentProtectionNodes + * Content protection nodes + * @return {Object} + * Object containing pssh data by key system + */ + var generateKeySystemInformation = function generateKeySystemInformation(contentProtectionNodes) { + return contentProtectionNodes.reduce(function (acc, node) { + var attributes = parseAttributes$1(node); + var keySystem = keySystemsMap[attributes.schemeIdUri]; + + if (keySystem) { + acc[keySystem] = {attributes: attributes}; + + var psshNode = findChildren(node, 'cenc:pssh')[0]; + + if (psshNode) { + var pssh = getContent(psshNode); + var psshBuffer = pssh && decodeB64ToUint8Array(pssh); + + acc[keySystem].pssh = psshBuffer; + } + } + + return acc; + }, {}); + }; + + /** + * Maps an AdaptationSet node to a list of Representation information objects + * + * @name toRepresentationsCallback + * @function + * @param {Node} adaptationSet + * AdaptationSet node from the mpd + * @return {RepresentationInformation[]} + * List of objects containing Representaion information + */ + + /** + * Returns a callback for Array.prototype.map for mapping AdaptationSet nodes to a list of + * Representation information objects + * + * @param {Object} periodAttributes + * Contains attributes inherited by the Period + * @param {string[]} periodBaseUrls + * Contains list of resolved base urls inherited by the Period + * @param {string[]} periodSegmentInfo + * Contains Segment Information at the period level + * @return {toRepresentationsCallback} + * Callback map function + */ + var toRepresentations = function toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo) { + return function (adaptationSet) { + var adaptationSetAttributes = parseAttributes$1(adaptationSet); + var adaptationSetBaseUrls = buildBaseUrls(periodBaseUrls, findChildren(adaptationSet, 'BaseURL')); + var role = findChildren(adaptationSet, 'Role')[0]; + var roleAttributes = {role: parseAttributes$1(role)}; + + var attrs = merge(periodAttributes, adaptationSetAttributes, roleAttributes); + + var contentProtection = generateKeySystemInformation(findChildren(adaptationSet, 'ContentProtection')); + + if (Object.keys(contentProtection).length) { + attrs = merge(attrs, {contentProtection: contentProtection}); + } + + var segmentInfo = getSegmentInformation(adaptationSet); + var representations = findChildren(adaptationSet, 'Representation'); + var adaptationSetSegmentInfo = merge(periodSegmentInfo, segmentInfo); + + return flatten(representations.map(inheritBaseUrls(attrs, adaptationSetBaseUrls, adaptationSetSegmentInfo))); + }; + }; + + /** + * Maps an Period node to a list of Representation inforamtion objects for all + * AdaptationSet nodes contained within the Period + * + * @name toAdaptationSetsCallback + * @function + * @param {Node} period + * Period node from the mpd + * @param {number} periodIndex + * Index of the Period within the mpd + * @return {RepresentationInformation[]} + * List of objects containing Representaion information + */ + + /** + * Returns a callback for Array.prototype.map for mapping Period nodes to a list of + * Representation information objects + * + * @param {Object} mpdAttributes + * Contains attributes inherited by the mpd + * @param {string[]} mpdBaseUrls + * Contains list of resolved base urls inherited by the mpd + * @return {toAdaptationSetsCallback} + * Callback map function + */ + var toAdaptationSets = function toAdaptationSets(mpdAttributes, mpdBaseUrls) { + return function (period, periodIndex) { + var periodBaseUrls = buildBaseUrls(mpdBaseUrls, findChildren(period, 'BaseURL')); + var periodAtt = parseAttributes$1(period); + var periodAttributes = merge(mpdAttributes, periodAtt, {periodIndex: periodIndex}); + var adaptationSets = findChildren(period, 'AdaptationSet'); + var periodSegmentInfo = getSegmentInformation(period); + + return flatten(adaptationSets.map(toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo))); + }; + }; + + /** + * Traverses the mpd xml tree to generate a list of Representation information objects + * that have inherited attributes from parent nodes + * + * @param {Node} mpd + * The root node of the mpd + * @param {Object} options + * Available options for inheritAttributes + * @param {string} options.manifestUri + * The uri source of the mpd + * @param {number} options.NOW + * Current time per DASH IOP. Default is current time in ms since epoch + * @param {number} options.clientOffset + * Client time difference from NOW (in milliseconds) + * @return {RepresentationInformation[]} + * List of objects containing Representation information + */ + var inheritAttributes = function inheritAttributes(mpd) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var _options$manifestUri = options.manifestUri, + manifestUri = _options$manifestUri === undefined ? '' : _options$manifestUri, + _options$NOW = options.NOW, + NOW = _options$NOW === undefined ? Date.now() : _options$NOW, + _options$clientOffset = options.clientOffset, + clientOffset = _options$clientOffset === undefined ? 0 : _options$clientOffset; + + var periods = findChildren(mpd, 'Period'); + + if (periods.length !== 1) { + // TODO add support for multiperiod + throw new Error(errors.INVALID_NUMBER_OF_PERIOD); + } + + var mpdAttributes = parseAttributes$1(mpd); + var mpdBaseUrls = buildBaseUrls([manifestUri], findChildren(mpd, 'BaseURL')); + + mpdAttributes.sourceDuration = mpdAttributes.mediaPresentationDuration || 0; + mpdAttributes.NOW = NOW; + mpdAttributes.clientOffset = clientOffset; + + return flatten(periods.map(toAdaptationSets(mpdAttributes, mpdBaseUrls))); + }; + + var stringToMpdXml = function stringToMpdXml(manifestString) { + if (manifestString === '') { + throw new Error(errors.DASH_EMPTY_MANIFEST); + } + + var parser = new window_1.DOMParser(); + var xml = parser.parseFromString(manifestString, 'application/xml'); + var mpd = xml && xml.documentElement.tagName === 'MPD' ? xml.documentElement : null; + + if (!mpd || mpd && mpd.getElementsByTagName('parsererror').length > 0) { + throw new Error(errors.DASH_INVALID_XML); + } + + return mpd; + }; + + /** + * Parses the manifest for a UTCTiming node, returning the nodes attributes if found + * + * @param {string} mpd + * XML string of the MPD manifest + * @return {Object|null} + * Attributes of UTCTiming node specified in the manifest. Null if none found + */ + var parseUTCTimingScheme = function parseUTCTimingScheme(mpd) { + var UTCTimingNode = findChildren(mpd, 'UTCTiming')[0]; + + if (!UTCTimingNode) { + return null; + } + + var attributes = parseAttributes$1(UTCTimingNode); + + switch (attributes.schemeIdUri) { + case 'urn:mpeg:dash:utc:http-head:2014': + case 'urn:mpeg:dash:utc:http-head:2012': + attributes.method = 'HEAD'; + break; + case 'urn:mpeg:dash:utc:http-xsdate:2014': + case 'urn:mpeg:dash:utc:http-iso:2014': + case 'urn:mpeg:dash:utc:http-xsdate:2012': + case 'urn:mpeg:dash:utc:http-iso:2012': + attributes.method = 'GET'; + break; + case 'urn:mpeg:dash:utc:direct:2014': + case 'urn:mpeg:dash:utc:direct:2012': + attributes.method = 'DIRECT'; + attributes.value = Date.parse(attributes.value); + break; + case 'urn:mpeg:dash:utc:http-ntp:2014': + case 'urn:mpeg:dash:utc:ntp:2014': + case 'urn:mpeg:dash:utc:sntp:2014': + default: + throw new Error(errors.UNSUPPORTED_UTC_TIMING_SCHEME); + } + + return attributes; + }; + + var parse = function parse(manifestString, options) { + return toM3u8(toPlaylists(inheritAttributes(stringToMpdXml(manifestString), options))); + }; + + /** + * Parses the manifest for a UTCTiming node, returning the nodes attributes if found + * + * @param {string} manifestString + * XML string of the MPD manifest + * @return {Object|null} + * Attributes of UTCTiming node specified in the manifest. Null if none found + */ + var parseUTCTiming = function parseUTCTiming(manifestString) { + return parseUTCTimingScheme(stringToMpdXml(manifestString)); + }; + + var toUnsigned = function toUnsigned(value) { + return value >>> 0; + }; + + var bin = { + toUnsigned: toUnsigned + }; + var bin_1 = bin.toUnsigned; + + var bin$1 = /*#__PURE__*/Object.freeze({ + default: bin, + __moduleExports: bin, + toUnsigned: bin_1 + }); + + var require$$0$1 = (bin$1 && bin) || bin$1; + + var toUnsigned$1 = require$$0$1.toUnsigned; + var _findBox, parseType, timescale, startTime; + + // Find the data for a box specified by its path + _findBox = function findBox(data, path) { + var results = [], + i, + size, + type, + end, + subresults; + + if (!path.length) { + // short-circuit the search for empty paths + return null; + } + + for (i = 0; i < data.byteLength;) { + size = toUnsigned$1(data[i] << 24 | data[i + 1] << 16 | data[i + 2] << 8 | data[i + 3]); + + type = parseType(data.subarray(i + 4, i + 8)); + + end = size > 1 ? i + size : data.byteLength; + + if (type === path[0]) { + if (path.length === 1) { + // this is the end of the path and we've found the box we were + // looking for + results.push(data.subarray(i + 8, end)); + } else { + // recursively search for the next box along the path + subresults = _findBox(data.subarray(i + 8, end), path.slice(1)); + if (subresults.length) { + results = results.concat(subresults); + } + } + } + i = end; + } + + // we've finished searching all of data + return results; + }; + + /** + * Returns the string representation of an ASCII encoded four byte buffer. + * @param buffer {Uint8Array} a four-byte buffer to translate + * @return {string} the corresponding string + */ + parseType = function parseType(buffer) { + var result = ''; + result += String.fromCharCode(buffer[0]); + result += String.fromCharCode(buffer[1]); + result += String.fromCharCode(buffer[2]); + result += String.fromCharCode(buffer[3]); + return result; + }; + + /** + * Parses an MP4 initialization segment and extracts the timescale + * values for any declared tracks. Timescale values indicate the + * number of clock ticks per second to assume for time-based values + * elsewhere in the MP4. + * + * To determine the start time of an MP4, you need two pieces of + * information: the timescale unit and the earliest base media decode + * time. Multiple timescales can be specified within an MP4 but the + * base media decode time is always expressed in the timescale from + * the media header box for the track: + * ``` + * moov > trak > mdia > mdhd.timescale + * ``` + * @param init {Uint8Array} the bytes of the init segment + * @return {object} a hash of track ids to timescale values or null if + * the init segment is malformed. + */ + timescale = function timescale(init) { + var result = {}, + traks = _findBox(init, ['moov', 'trak']); + + // mdhd timescale + return traks.reduce(function (result, trak) { + var tkhd, version, index, id, mdhd; + + tkhd = _findBox(trak, ['tkhd'])[0]; + if (!tkhd) { + return null; + } + version = tkhd[0]; + index = version === 0 ? 12 : 20; + id = toUnsigned$1(tkhd[index] << 24 | tkhd[index + 1] << 16 | tkhd[index + 2] << 8 | tkhd[index + 3]); + + mdhd = _findBox(trak, ['mdia', 'mdhd'])[0]; + if (!mdhd) { + return null; + } + version = mdhd[0]; + index = version === 0 ? 12 : 20; + result[id] = toUnsigned$1(mdhd[index] << 24 | mdhd[index + 1] << 16 | mdhd[index + 2] << 8 | mdhd[index + 3]); + return result; + }, result); + }; + + /** + * Determine the base media decode start time, in seconds, for an MP4 + * fragment. If multiple fragments are specified, the earliest time is + * returned. + * + * The base media decode time can be parsed from track fragment + * metadata: + * ``` + * moof > traf > tfdt.baseMediaDecodeTime + * ``` + * It requires the timescale value from the mdhd to interpret. + * + * @param timescale {object} a hash of track ids to timescale values. + * @return {number} the earliest base media decode start time for the + * fragment, in seconds + */ + startTime = function startTime(timescale, fragment) { + var trafs, baseTimes, result; + + // we need info from two childrend of each track fragment box + trafs = _findBox(fragment, ['moof', 'traf']); + + // determine the start times for each track + baseTimes = [].concat.apply([], trafs.map(function (traf) { + return _findBox(traf, ['tfhd']).map(function (tfhd) { + var id, scale, baseTime; + + // get the track id from the tfhd + id = toUnsigned$1(tfhd[4] << 24 | tfhd[5] << 16 | tfhd[6] << 8 | tfhd[7]); + // assume a 90kHz clock if no timescale was specified + scale = timescale[id] || 90e3; + + // get the base media decode time from the tfdt + baseTime = _findBox(traf, ['tfdt']).map(function (tfdt) { + var version, result; + + version = tfdt[0]; + result = toUnsigned$1(tfdt[4] << 24 | tfdt[5] << 16 | tfdt[6] << 8 | tfdt[7]); + if (version === 1) { + result *= Math.pow(2, 32); + result += toUnsigned$1(tfdt[8] << 24 | tfdt[9] << 16 | tfdt[10] << 8 | tfdt[11]); + } + return result; + })[0]; + baseTime = baseTime || Infinity; + + // convert base time to seconds + return baseTime / scale; + }); + })); + + // return the minimum + result = Math.min.apply(null, baseTimes); + return isFinite(result) ? result : 0; + }; + + var probe = { + parseType: parseType, + timescale: timescale, + startTime: startTime + }; + + var streamTypes = { + H264_STREAM_TYPE: 0x1B, + ADTS_STREAM_TYPE: 0x0F, + METADATA_STREAM_TYPE: 0x15 + }; + var streamTypes_1 = streamTypes.H264_STREAM_TYPE; + var streamTypes_2 = streamTypes.ADTS_STREAM_TYPE; + var streamTypes_3 = streamTypes.METADATA_STREAM_TYPE; + + var streamTypes$1 = /*#__PURE__*/Object.freeze({ + default: streamTypes, + __moduleExports: streamTypes, + H264_STREAM_TYPE: streamTypes_1, + ADTS_STREAM_TYPE: streamTypes_2, + METADATA_STREAM_TYPE: streamTypes_3 + }); + + /** + * mux.js + * + * Copyright (c) 2014 Brightcove + * All rights reserved. + * + * A lightweight readable stream implemention that handles event dispatching. + * Objects that inherit from streams should call init in their constructors. + */ + + var Stream$1 = function Stream() { + this.init = function () { + var listeners = {}; + /** + * Add a listener for a specified event type. + * @param type {string} the event name + * @param listener {function} the callback to be invoked when an event of + * the specified type occurs + */ + this.on = function (type, listener) { + if (!listeners[type]) { + listeners[type] = []; + } + listeners[type] = listeners[type].concat(listener); + }; + /** + * Remove a listener for a specified event type. + * @param type {string} the event name + * @param listener {function} a function previously registered for this + * type of event through `on` + */ + this.off = function (type, listener) { + var index; + if (!listeners[type]) { + return false; + } + index = listeners[type].indexOf(listener); + listeners[type] = listeners[type].slice(); + listeners[type].splice(index, 1); + return index > -1; + }; + /** + * Trigger an event of the specified type on this stream. Any additional + * arguments to this function are passed as parameters to event listeners. + * @param type {string} the event name + */ + this.trigger = function (type) { + var callbacks, i, length, args; + callbacks = listeners[type]; + if (!callbacks) { + return; + } + // Slicing the arguments on every invocation of this method + // can add a significant amount of overhead. Avoid the + // intermediate object creation for the common case of a + // single callback argument + if (arguments.length === 2) { + length = callbacks.length; + for (i = 0; i < length; ++i) { + callbacks[i].call(this, arguments[1]); + } + } else { + args = []; + i = arguments.length; + for (i = 1; i < arguments.length; ++i) { + args.push(arguments[i]); + } + length = callbacks.length; + for (i = 0; i < length; ++i) { + callbacks[i].apply(this, args); + } + } + }; + /** + * Destroys the stream and cleans up. + */ + this.dispose = function () { + listeners = {}; + }; + }; + }; + + /** + * Forwards all `data` events on this stream to the destination stream. The + * destination stream should provide a method `push` to receive the data + * events as they arrive. + * @param destination {stream} the stream that will receive all `data` events + * @param autoFlush {boolean} if false, we will not call `flush` on the destination + * when the current stream emits a 'done' event + * @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options + */ + Stream$1.prototype.pipe = function (destination) { + this.on('data', function (data) { + destination.push(data); + }); + + this.on('done', function (flushSource) { + destination.flush(flushSource); + }); + + return destination; + }; + + // Default stream functions that are expected to be overridden to perform + // actual work. These are provided by the prototype as a sort of no-op + // implementation so that we don't have to check for their existence in the + // `pipe` function above. + Stream$1.prototype.push = function (data) { + this.trigger('data', data); + }; + + Stream$1.prototype.flush = function (flushSource) { + this.trigger('done', flushSource); + }; + + var stream = Stream$1; + + var stream$1 = /*#__PURE__*/Object.freeze({ + default: stream, + __moduleExports: stream + }); + + var Stream$2 = (stream$1 && stream) || stream$1; + + var MAX_TS = 8589934592; + + var RO_THRESH = 4294967296; + + var handleRollover = function handleRollover(value, reference) { + var direction = 1; + + if (value > reference) { + // If the current timestamp value is greater than our reference timestamp and we detect a + // timestamp rollover, this means the roll over is happening in the opposite direction. + // Example scenario: Enter a long stream/video just after a rollover occurred. The reference + // point will be set to a small number, e.g. 1. The user then seeks backwards over the + // rollover point. In loading this segment, the timestamp values will be very large, + // e.g. 2^33 - 1. Since this comes before the data we loaded previously, we want to adjust + // the time stamp to be `value - 2^33`. + direction = -1; + } + + // Note: A seek forwards or back that is greater than the RO_THRESH (2^32, ~13 hours) will + // cause an incorrect adjustment. + while (Math.abs(reference - value) > RO_THRESH) { + value += direction * MAX_TS; + } + + return value; + }; + + var TimestampRolloverStream = function TimestampRolloverStream(type) { + var lastDTS, referenceDTS; + + TimestampRolloverStream.prototype.init.call(this); + + this.type_ = type; + + this.push = function (data) { + if (data.type !== this.type_) { + return; + } + + if (referenceDTS === undefined) { + referenceDTS = data.dts; + } + + data.dts = handleRollover(data.dts, referenceDTS); + data.pts = handleRollover(data.pts, referenceDTS); + + lastDTS = data.dts; + + this.trigger('data', data); + }; + + this.flush = function () { + referenceDTS = lastDTS; + this.trigger('done'); + }; + + this.discontinuity = function () { + referenceDTS = void 0; + lastDTS = void 0; + }; + }; + + TimestampRolloverStream.prototype = new Stream$2(); + + var timestampRolloverStream = { + TimestampRolloverStream: TimestampRolloverStream, + handleRollover: handleRollover + }; + var timestampRolloverStream_1 = timestampRolloverStream.TimestampRolloverStream; + var timestampRolloverStream_2 = timestampRolloverStream.handleRollover; + + var timestampRolloverStream$1 = /*#__PURE__*/Object.freeze({ + default: timestampRolloverStream, + __moduleExports: timestampRolloverStream, + TimestampRolloverStream: timestampRolloverStream_1, + handleRollover: timestampRolloverStream_2 + }); + + var StreamTypes = (streamTypes$1 && streamTypes) || streamTypes$1; + + var parsePid = function parsePid(packet) { + var pid = packet[1] & 0x1f; + pid <<= 8; + pid |= packet[2]; + return pid; + }; + + var parsePayloadUnitStartIndicator = function parsePayloadUnitStartIndicator(packet) { + return !!(packet[1] & 0x40); + }; + + var parseAdaptionField = function parseAdaptionField(packet) { + var offset = 0; + // if an adaption field is present, its length is specified by the + // fifth byte of the TS packet header. The adaptation field is + // used to add stuffing to PES packets that don't fill a complete + // TS packet, and to specify some forms of timing and control data + // that we do not currently use. + if ((packet[3] & 0x30) >>> 4 > 0x01) { + offset += packet[4] + 1; + } + return offset; + }; + + var parseType$1 = function parseType(packet, pmtPid) { + var pid = parsePid(packet); + if (pid === 0) { + return 'pat'; + } else if (pid === pmtPid) { + return 'pmt'; + } else if (pmtPid) { + return 'pes'; + } + return null; + }; + + var parsePat = function parsePat(packet) { + var pusi = parsePayloadUnitStartIndicator(packet); + var offset = 4 + parseAdaptionField(packet); + + if (pusi) { + offset += packet[offset] + 1; + } + + return (packet[offset + 10] & 0x1f) << 8 | packet[offset + 11]; + }; + + var parsePmt = function parsePmt(packet) { + var programMapTable = {}; + var pusi = parsePayloadUnitStartIndicator(packet); + var payloadOffset = 4 + parseAdaptionField(packet); + + if (pusi) { + payloadOffset += packet[payloadOffset] + 1; + } + + // PMTs can be sent ahead of the time when they should actually + // take effect. We don't believe this should ever be the case + // for HLS but we'll ignore "forward" PMT declarations if we see + // them. Future PMT declarations have the current_next_indicator + // set to zero. + if (!(packet[payloadOffset + 5] & 0x01)) { + return; + } + + var sectionLength, tableEnd, programInfoLength; + // the mapping table ends at the end of the current section + sectionLength = (packet[payloadOffset + 1] & 0x0f) << 8 | packet[payloadOffset + 2]; + tableEnd = 3 + sectionLength - 4; + + // to determine where the table is, we have to figure out how + // long the program info descriptors are + programInfoLength = (packet[payloadOffset + 10] & 0x0f) << 8 | packet[payloadOffset + 11]; + + // advance the offset to the first entry in the mapping table + var offset = 12 + programInfoLength; + while (offset < tableEnd) { + var i = payloadOffset + offset; + // add an entry that maps the elementary_pid to the stream_type + programMapTable[(packet[i + 1] & 0x1F) << 8 | packet[i + 2]] = packet[i]; + + // move to the next table entry + // skip past the elementary stream descriptors, if present + offset += ((packet[i + 3] & 0x0F) << 8 | packet[i + 4]) + 5; + } + return programMapTable; + }; + + var parsePesType = function parsePesType(packet, programMapTable) { + var pid = parsePid(packet); + var type = programMapTable[pid]; + switch (type) { + case StreamTypes.H264_STREAM_TYPE: + return 'video'; + case StreamTypes.ADTS_STREAM_TYPE: + return 'audio'; + case StreamTypes.METADATA_STREAM_TYPE: + return 'timed-metadata'; + default: + return null; + } + }; + + var parsePesTime = function parsePesTime(packet) { + var pusi = parsePayloadUnitStartIndicator(packet); + if (!pusi) { + return null; + } + + var offset = 4 + parseAdaptionField(packet); + + if (offset >= packet.byteLength) { + // From the H 222.0 MPEG-TS spec + // "For transport stream packets carrying PES packets, stuffing is needed when there + // is insufficient PES packet data to completely fill the transport stream packet + // payload bytes. Stuffing is accomplished by defining an adaptation field longer than + // the sum of the lengths of the data elements in it, so that the payload bytes + // remaining after the adaptation field exactly accommodates the available PES packet + // data." + // + // If the offset is >= the length of the packet, then the packet contains no data + // and instead is just adaption field stuffing bytes + return null; + } + + var pes = null; + var ptsDtsFlags; + + // PES packets may be annotated with a PTS value, or a PTS value + // and a DTS value. Determine what combination of values is + // available to work with. + ptsDtsFlags = packet[offset + 7]; + + // PTS and DTS are normally stored as a 33-bit number. Javascript + // performs all bitwise operations on 32-bit integers but javascript + // supports a much greater range (52-bits) of integer using standard + // mathematical operations. + // We construct a 31-bit value using bitwise operators over the 31 + // most significant bits and then multiply by 4 (equal to a left-shift + // of 2) before we add the final 2 least significant bits of the + // timestamp (equal to an OR.) + if (ptsDtsFlags & 0xC0) { + pes = {}; + // the PTS and DTS are not written out directly. For information + // on how they are encoded, see + // http://dvd.sourceforge.net/dvdinfo/pes-hdr.html + pes.pts = (packet[offset + 9] & 0x0E) << 27 | (packet[offset + 10] & 0xFF) << 20 | (packet[offset + 11] & 0xFE) << 12 | (packet[offset + 12] & 0xFF) << 5 | (packet[offset + 13] & 0xFE) >>> 3; + pes.pts *= 4; // Left shift by 2 + pes.pts += (packet[offset + 13] & 0x06) >>> 1; // OR by the two LSBs + pes.dts = pes.pts; + if (ptsDtsFlags & 0x40) { + pes.dts = (packet[offset + 14] & 0x0E) << 27 | (packet[offset + 15] & 0xFF) << 20 | (packet[offset + 16] & 0xFE) << 12 | (packet[offset + 17] & 0xFF) << 5 | (packet[offset + 18] & 0xFE) >>> 3; + pes.dts *= 4; // Left shift by 2 + pes.dts += (packet[offset + 18] & 0x06) >>> 1; // OR by the two LSBs + } + } + return pes; + }; + + var parseNalUnitType = function parseNalUnitType(type) { + switch (type) { + case 0x05: + return 'slice_layer_without_partitioning_rbsp_idr'; + case 0x06: + return 'sei_rbsp'; + case 0x07: + return 'seq_parameter_set_rbsp'; + case 0x08: + return 'pic_parameter_set_rbsp'; + case 0x09: + return 'access_unit_delimiter_rbsp'; + default: + return null; + } + }; + + var videoPacketContainsKeyFrame = function videoPacketContainsKeyFrame(packet) { + var offset = 4 + parseAdaptionField(packet); + var frameBuffer = packet.subarray(offset); + var frameI = 0; + var frameSyncPoint = 0; + var foundKeyFrame = false; + var nalType; + + // advance the sync point to a NAL start, if necessary + for (; frameSyncPoint < frameBuffer.byteLength - 3; frameSyncPoint++) { + if (frameBuffer[frameSyncPoint + 2] === 1) { + // the sync point is properly aligned + frameI = frameSyncPoint + 5; + break; + } + } + + while (frameI < frameBuffer.byteLength) { + // look at the current byte to determine if we've hit the end of + // a NAL unit boundary + switch (frameBuffer[frameI]) { + case 0: + // skip past non-sync sequences + if (frameBuffer[frameI - 1] !== 0) { + frameI += 2; + break; + } else if (frameBuffer[frameI - 2] !== 0) { + frameI++; + break; + } + + if (frameSyncPoint + 3 !== frameI - 2) { + nalType = parseNalUnitType(frameBuffer[frameSyncPoint + 3] & 0x1f); + if (nalType === 'slice_layer_without_partitioning_rbsp_idr') { + foundKeyFrame = true; + } + } + + // drop trailing zeroes + do { + frameI++; + } while (frameBuffer[frameI] !== 1 && frameI < frameBuffer.length); + frameSyncPoint = frameI - 2; + frameI += 3; + break; + case 1: + // skip past non-sync sequences + if (frameBuffer[frameI - 1] !== 0 || frameBuffer[frameI - 2] !== 0) { + frameI += 3; + break; + } + + nalType = parseNalUnitType(frameBuffer[frameSyncPoint + 3] & 0x1f); + if (nalType === 'slice_layer_without_partitioning_rbsp_idr') { + foundKeyFrame = true; + } + frameSyncPoint = frameI - 2; + frameI += 3; + break; + default: + // the current byte isn't a one or zero, so it cannot be part + // of a sync sequence + frameI += 3; + break; + } + } + frameBuffer = frameBuffer.subarray(frameSyncPoint); + frameI -= frameSyncPoint; + frameSyncPoint = 0; + // parse the final nal + if (frameBuffer && frameBuffer.byteLength > 3) { + nalType = parseNalUnitType(frameBuffer[frameSyncPoint + 3] & 0x1f); + if (nalType === 'slice_layer_without_partitioning_rbsp_idr') { + foundKeyFrame = true; + } + } + + return foundKeyFrame; + }; + + var probe$1 = { + parseType: parseType$1, + parsePat: parsePat, + parsePmt: parsePmt, + parsePayloadUnitStartIndicator: parsePayloadUnitStartIndicator, + parsePesType: parsePesType, + parsePesTime: parsePesTime, + videoPacketContainsKeyFrame: videoPacketContainsKeyFrame + }; + var probe_1$1 = probe$1.parseType; + var probe_2$1 = probe$1.parsePat; + var probe_3$1 = probe$1.parsePmt; + var probe_4 = probe$1.parsePayloadUnitStartIndicator; + var probe_5 = probe$1.parsePesType; + var probe_6 = probe$1.parsePesTime; + var probe_7 = probe$1.videoPacketContainsKeyFrame; + + var probe$2 = /*#__PURE__*/Object.freeze({ + default: probe$1, + __moduleExports: probe$1, + parseType: probe_1$1, + parsePat: probe_2$1, + parsePmt: probe_3$1, + parsePayloadUnitStartIndicator: probe_4, + parsePesType: probe_5, + parsePesTime: probe_6, + videoPacketContainsKeyFrame: probe_7 + }); + + /** + * mux.js + * + * Copyright (c) 2016 Brightcove + * All rights reserved. + * + * Utilities to detect basic properties and metadata about Aac data. + */ + + var ADTS_SAMPLING_FREQUENCIES = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350]; + + var parseSyncSafeInteger = function parseSyncSafeInteger(data) { + return data[0] << 21 | data[1] << 14 | data[2] << 7 | data[3]; + }; + + // return a percent-encoded representation of the specified byte range + // @see http://en.wikipedia.org/wiki/Percent-encoding + var percentEncode = function percentEncode(bytes, start, end) { + var i, + result = ''; + for (i = start; i < end; i++) { + result += '%' + ('00' + bytes[i].toString(16)).slice(-2); + } + return result; + }; + + // return the string representation of the specified byte range, + // interpreted as ISO-8859-1. + var parseIso88591 = function parseIso88591(bytes, start, end) { + return unescape(percentEncode(bytes, start, end)); // jshint ignore:line + }; + + var parseId3TagSize = function parseId3TagSize(header, byteIndex) { + var returnSize = header[byteIndex + 6] << 21 | header[byteIndex + 7] << 14 | header[byteIndex + 8] << 7 | header[byteIndex + 9], + flags = header[byteIndex + 5], + footerPresent = (flags & 16) >> 4; + + if (footerPresent) { + return returnSize + 20; + } + return returnSize + 10; + }; + + var parseAdtsSize = function parseAdtsSize(header, byteIndex) { + var lowThree = (header[byteIndex + 5] & 0xE0) >> 5, + middle = header[byteIndex + 4] << 3, + highTwo = header[byteIndex + 3] & 0x3 << 11; + + return highTwo | middle | lowThree; + }; + + var parseType$2 = function parseType(header, byteIndex) { + if (header[byteIndex] === 'I'.charCodeAt(0) && header[byteIndex + 1] === 'D'.charCodeAt(0) && header[byteIndex + 2] === '3'.charCodeAt(0)) { + return 'timed-metadata'; + } else if (header[byteIndex] & 0xff === 0xff && (header[byteIndex + 1] & 0xf0) === 0xf0) { + return 'audio'; + } + return null; + }; + + var parseSampleRate = function parseSampleRate(packet) { + var i = 0; + + while (i + 5 < packet.length) { + if (packet[i] !== 0xFF || (packet[i + 1] & 0xF6) !== 0xF0) { + // If a valid header was not found, jump one forward and attempt to + // find a valid ADTS header starting at the next byte + i++; + continue; + } + return ADTS_SAMPLING_FREQUENCIES[(packet[i + 2] & 0x3c) >>> 2]; + } + + return null; + }; + + var parseAacTimestamp = function parseAacTimestamp(packet) { + var frameStart, frameSize, frame, frameHeader; + + // find the start of the first frame and the end of the tag + frameStart = 10; + if (packet[5] & 0x40) { + // advance the frame start past the extended header + frameStart += 4; // header size field + frameStart += parseSyncSafeInteger(packet.subarray(10, 14)); + } + + // parse one or more ID3 frames + // http://id3.org/id3v2.3.0#ID3v2_frame_overview + do { + // determine the number of bytes in this frame + frameSize = parseSyncSafeInteger(packet.subarray(frameStart + 4, frameStart + 8)); + if (frameSize < 1) { + return null; + } + frameHeader = String.fromCharCode(packet[frameStart], packet[frameStart + 1], packet[frameStart + 2], packet[frameStart + 3]); + + if (frameHeader === 'PRIV') { + frame = packet.subarray(frameStart + 10, frameStart + frameSize + 10); + + for (var i = 0; i < frame.byteLength; i++) { + if (frame[i] === 0) { + var owner = parseIso88591(frame, 0, i); + if (owner === 'com.apple.streaming.transportStreamTimestamp') { + var d = frame.subarray(i + 1); + var size = (d[3] & 0x01) << 30 | d[4] << 22 | d[5] << 14 | d[6] << 6 | d[7] >>> 2; + size *= 4; + size += d[7] & 0x03; + + return size; + } + break; + } + } + } + + frameStart += 10; // advance past the frame header + frameStart += frameSize; // advance past the frame body + } while (frameStart < packet.byteLength); + return null; + }; + + var probe$3 = { + parseId3TagSize: parseId3TagSize, + parseAdtsSize: parseAdtsSize, + parseType: parseType$2, + parseSampleRate: parseSampleRate, + parseAacTimestamp: parseAacTimestamp + }; + var probe_1$2 = probe$3.parseId3TagSize; + var probe_2$2 = probe$3.parseAdtsSize; + var probe_3$2 = probe$3.parseType; + var probe_4$1 = probe$3.parseSampleRate; + var probe_5$1 = probe$3.parseAacTimestamp; + + var probe$4 = /*#__PURE__*/Object.freeze({ + default: probe$3, + __moduleExports: probe$3, + parseId3TagSize: probe_1$2, + parseAdtsSize: probe_2$2, + parseType: probe_3$2, + parseSampleRate: probe_4$1, + parseAacTimestamp: probe_5$1 + }); + + var require$$0$2 = (timestampRolloverStream$1 && timestampRolloverStream) || timestampRolloverStream$1; + + var require$$1$1 = (probe$2 && probe$1) || probe$2; + + var require$$2$1 = (probe$4 && probe$3) || probe$4; + + var handleRollover$1 = require$$0$2.handleRollover; + var probe$5 = {}; + probe$5.ts = require$$1$1; + probe$5.aac = require$$2$1; + + var PES_TIMESCALE = 90000, + MP2T_PACKET_LENGTH = 188, + // bytes + SYNC_BYTE = 0x47; + + var isLikelyAacData = function isLikelyAacData(data) { + if (data[0] === 'I'.charCodeAt(0) && data[1] === 'D'.charCodeAt(0) && data[2] === '3'.charCodeAt(0)) { + return true; + } + return false; + }; + + /** + * walks through segment data looking for pat and pmt packets to parse out + * program map table information + */ + var parsePsi_ = function parsePsi_(bytes, pmt) { + var startIndex = 0, + endIndex = MP2T_PACKET_LENGTH, + packet, + type; + + while (endIndex < bytes.byteLength) { + // Look for a pair of start and end sync bytes in the data.. + if (bytes[startIndex] === SYNC_BYTE && bytes[endIndex] === SYNC_BYTE) { + // We found a packet + packet = bytes.subarray(startIndex, endIndex); + type = probe$5.ts.parseType(packet, pmt.pid); + + switch (type) { + case 'pat': + if (!pmt.pid) { + pmt.pid = probe$5.ts.parsePat(packet); + } + break; + case 'pmt': + if (!pmt.table) { + pmt.table = probe$5.ts.parsePmt(packet); + } + break; + default: + break; + } + + // Found the pat and pmt, we can stop walking the segment + if (pmt.pid && pmt.table) { + return; + } + + startIndex += MP2T_PACKET_LENGTH; + endIndex += MP2T_PACKET_LENGTH; + continue; + } + + // If we get here, we have somehow become de-synchronized and we need to step + // forward one byte at a time until we find a pair of sync bytes that denote + // a packet + startIndex++; + endIndex++; + } + }; + + /** + * walks through the segment data from the start and end to get timing information + * for the first and last audio pes packets + */ + var parseAudioPes_ = function parseAudioPes_(bytes, pmt, result) { + var startIndex = 0, + endIndex = MP2T_PACKET_LENGTH, + packet, + type, + pesType, + pusi, + parsed; + + var endLoop = false; + + // Start walking from start of segment to get first audio packet + while (endIndex < bytes.byteLength) { + // Look for a pair of start and end sync bytes in the data.. + if (bytes[startIndex] === SYNC_BYTE && bytes[endIndex] === SYNC_BYTE) { + // We found a packet + packet = bytes.subarray(startIndex, endIndex); + type = probe$5.ts.parseType(packet, pmt.pid); + + switch (type) { + case 'pes': + pesType = probe$5.ts.parsePesType(packet, pmt.table); + pusi = probe$5.ts.parsePayloadUnitStartIndicator(packet); + if (pesType === 'audio' && pusi) { + parsed = probe$5.ts.parsePesTime(packet); + if (parsed) { + parsed.type = 'audio'; + result.audio.push(parsed); + endLoop = true; + } + } + break; + default: + break; + } + + if (endLoop) { + break; + } + + startIndex += MP2T_PACKET_LENGTH; + endIndex += MP2T_PACKET_LENGTH; + continue; + } + + // If we get here, we have somehow become de-synchronized and we need to step + // forward one byte at a time until we find a pair of sync bytes that denote + // a packet + startIndex++; + endIndex++; + } + + // Start walking from end of segment to get last audio packet + endIndex = bytes.byteLength; + startIndex = endIndex - MP2T_PACKET_LENGTH; + endLoop = false; + while (startIndex >= 0) { + // Look for a pair of start and end sync bytes in the data.. + if (bytes[startIndex] === SYNC_BYTE && bytes[endIndex] === SYNC_BYTE) { + // We found a packet + packet = bytes.subarray(startIndex, endIndex); + type = probe$5.ts.parseType(packet, pmt.pid); + + switch (type) { + case 'pes': + pesType = probe$5.ts.parsePesType(packet, pmt.table); + pusi = probe$5.ts.parsePayloadUnitStartIndicator(packet); + if (pesType === 'audio' && pusi) { + parsed = probe$5.ts.parsePesTime(packet); + if (parsed) { + parsed.type = 'audio'; + result.audio.push(parsed); + endLoop = true; + } + } + break; + default: + break; + } + + if (endLoop) { + break; + } + + startIndex -= MP2T_PACKET_LENGTH; + endIndex -= MP2T_PACKET_LENGTH; + continue; + } + + // If we get here, we have somehow become de-synchronized and we need to step + // forward one byte at a time until we find a pair of sync bytes that denote + // a packet + startIndex--; + endIndex--; + } + }; + + /** + * walks through the segment data from the start and end to get timing information + * for the first and last video pes packets as well as timing information for the first + * key frame. + */ + var parseVideoPes_ = function parseVideoPes_(bytes, pmt, result) { + var startIndex = 0, + endIndex = MP2T_PACKET_LENGTH, + packet, + type, + pesType, + pusi, + parsed, + frame, + i, + pes; + + var endLoop = false; + + var currentFrame = { + data: [], + size: 0 + }; + + // Start walking from start of segment to get first video packet + while (endIndex < bytes.byteLength) { + // Look for a pair of start and end sync bytes in the data.. + if (bytes[startIndex] === SYNC_BYTE && bytes[endIndex] === SYNC_BYTE) { + // We found a packet + packet = bytes.subarray(startIndex, endIndex); + type = probe$5.ts.parseType(packet, pmt.pid); + + switch (type) { + case 'pes': + pesType = probe$5.ts.parsePesType(packet, pmt.table); + pusi = probe$5.ts.parsePayloadUnitStartIndicator(packet); + if (pesType === 'video') { + if (pusi && !endLoop) { + parsed = probe$5.ts.parsePesTime(packet); + if (parsed) { + parsed.type = 'video'; + result.video.push(parsed); + endLoop = true; + } + } + if (!result.firstKeyFrame) { + if (pusi) { + if (currentFrame.size !== 0) { + frame = new Uint8Array(currentFrame.size); + i = 0; + while (currentFrame.data.length) { + pes = currentFrame.data.shift(); + frame.set(pes, i); + i += pes.byteLength; + } + if (probe$5.ts.videoPacketContainsKeyFrame(frame)) { + result.firstKeyFrame = probe$5.ts.parsePesTime(frame); + result.firstKeyFrame.type = 'video'; + } + currentFrame.size = 0; + } + } + currentFrame.data.push(packet); + currentFrame.size += packet.byteLength; + } + } + break; + default: + break; + } + + if (endLoop && result.firstKeyFrame) { + break; + } + + startIndex += MP2T_PACKET_LENGTH; + endIndex += MP2T_PACKET_LENGTH; + continue; + } + + // If we get here, we have somehow become de-synchronized and we need to step + // forward one byte at a time until we find a pair of sync bytes that denote + // a packet + startIndex++; + endIndex++; + } + + // Start walking from end of segment to get last video packet + endIndex = bytes.byteLength; + startIndex = endIndex - MP2T_PACKET_LENGTH; + endLoop = false; + while (startIndex >= 0) { + // Look for a pair of start and end sync bytes in the data.. + if (bytes[startIndex] === SYNC_BYTE && bytes[endIndex] === SYNC_BYTE) { + // We found a packet + packet = bytes.subarray(startIndex, endIndex); + type = probe$5.ts.parseType(packet, pmt.pid); + + switch (type) { + case 'pes': + pesType = probe$5.ts.parsePesType(packet, pmt.table); + pusi = probe$5.ts.parsePayloadUnitStartIndicator(packet); + if (pesType === 'video' && pusi) { + parsed = probe$5.ts.parsePesTime(packet); + if (parsed) { + parsed.type = 'video'; + result.video.push(parsed); + endLoop = true; + } + } + break; + default: + break; + } + + if (endLoop) { + break; + } + + startIndex -= MP2T_PACKET_LENGTH; + endIndex -= MP2T_PACKET_LENGTH; + continue; + } + + // If we get here, we have somehow become de-synchronized and we need to step + // forward one byte at a time until we find a pair of sync bytes that denote + // a packet + startIndex--; + endIndex--; + } + }; + + /** + * Adjusts the timestamp information for the segment to account for + * rollover and convert to seconds based on pes packet timescale (90khz clock) + */ + var adjustTimestamp_ = function adjustTimestamp_(segmentInfo, baseTimestamp) { + if (segmentInfo.audio && segmentInfo.audio.length) { + var audioBaseTimestamp = baseTimestamp; + if (typeof audioBaseTimestamp === 'undefined') { + audioBaseTimestamp = segmentInfo.audio[0].dts; + } + segmentInfo.audio.forEach(function (info) { + info.dts = handleRollover$1(info.dts, audioBaseTimestamp); + info.pts = handleRollover$1(info.pts, audioBaseTimestamp); + // time in seconds + info.dtsTime = info.dts / PES_TIMESCALE; + info.ptsTime = info.pts / PES_TIMESCALE; + }); + } + + if (segmentInfo.video && segmentInfo.video.length) { + var videoBaseTimestamp = baseTimestamp; + if (typeof videoBaseTimestamp === 'undefined') { + videoBaseTimestamp = segmentInfo.video[0].dts; + } + segmentInfo.video.forEach(function (info) { + info.dts = handleRollover$1(info.dts, videoBaseTimestamp); + info.pts = handleRollover$1(info.pts, videoBaseTimestamp); + // time in seconds + info.dtsTime = info.dts / PES_TIMESCALE; + info.ptsTime = info.pts / PES_TIMESCALE; + }); + if (segmentInfo.firstKeyFrame) { + var frame = segmentInfo.firstKeyFrame; + frame.dts = handleRollover$1(frame.dts, videoBaseTimestamp); + frame.pts = handleRollover$1(frame.pts, videoBaseTimestamp); + // time in seconds + frame.dtsTime = frame.dts / PES_TIMESCALE; + frame.ptsTime = frame.dts / PES_TIMESCALE; + } + } + }; + + /** + * inspects the aac data stream for start and end time information + */ + var inspectAac_ = function inspectAac_(bytes) { + var endLoop = false, + audioCount = 0, + sampleRate = null, + timestamp = null, + frameSize = 0, + byteIndex = 0, + packet; + + while (bytes.length - byteIndex >= 3) { + var type = probe$5.aac.parseType(bytes, byteIndex); + switch (type) { + case 'timed-metadata': + // Exit early because we don't have enough to parse + // the ID3 tag header + if (bytes.length - byteIndex < 10) { + endLoop = true; + break; + } + + frameSize = probe$5.aac.parseId3TagSize(bytes, byteIndex); + + // Exit early if we don't have enough in the buffer + // to emit a full packet + if (frameSize > bytes.length) { + endLoop = true; + break; + } + if (timestamp === null) { + packet = bytes.subarray(byteIndex, byteIndex + frameSize); + timestamp = probe$5.aac.parseAacTimestamp(packet); + } + byteIndex += frameSize; + break; + case 'audio': + // Exit early because we don't have enough to parse + // the ADTS frame header + if (bytes.length - byteIndex < 7) { + endLoop = true; + break; + } + + frameSize = probe$5.aac.parseAdtsSize(bytes, byteIndex); + + // Exit early if we don't have enough in the buffer + // to emit a full packet + if (frameSize > bytes.length) { + endLoop = true; + break; + } + if (sampleRate === null) { + packet = bytes.subarray(byteIndex, byteIndex + frameSize); + sampleRate = probe$5.aac.parseSampleRate(packet); + } + audioCount++; + byteIndex += frameSize; + break; + default: + byteIndex++; + break; + } + if (endLoop) { + return null; + } + } + if (sampleRate === null || timestamp === null) { + return null; + } + + var audioTimescale = PES_TIMESCALE / sampleRate; + + var result = { + audio: [{ + type: 'audio', + dts: timestamp, + pts: timestamp + }, { + type: 'audio', + dts: timestamp + audioCount * 1024 * audioTimescale, + pts: timestamp + audioCount * 1024 * audioTimescale + }] + }; + + return result; + }; + + /** + * inspects the transport stream segment data for start and end time information + * of the audio and video tracks (when present) as well as the first key frame's + * start time. + */ + var inspectTs_ = function inspectTs_(bytes) { + var pmt = { + pid: null, + table: null + }; + + var result = {}; + + parsePsi_(bytes, pmt); + + for (var pid in pmt.table) { + if (pmt.table.hasOwnProperty(pid)) { + var type = pmt.table[pid]; + switch (type) { + case StreamTypes.H264_STREAM_TYPE: + result.video = []; + parseVideoPes_(bytes, pmt, result); + if (result.video.length === 0) { + delete result.video; + } + break; + case StreamTypes.ADTS_STREAM_TYPE: + result.audio = []; + parseAudioPes_(bytes, pmt, result); + if (result.audio.length === 0) { + delete result.audio; + } + break; + default: + break; + } + } + } + return result; + }; + + /** + * Inspects segment byte data and returns an object with start and end timing information + * + * @param {Uint8Array} bytes The segment byte data + * @param {Number} baseTimestamp Relative reference timestamp used when adjusting frame + * timestamps for rollover. This value must be in 90khz clock. + * @return {Object} Object containing start and end frame timing info of segment. + */ + var inspect = function inspect(bytes, baseTimestamp) { + var isAacData = isLikelyAacData(bytes); + + var result; + + if (isAacData) { + result = inspectAac_(bytes); + } else { + result = inspectTs_(bytes); + } + + if (!result || !result.audio && !result.video) { + return null; + } + + adjustTimestamp_(result, baseTimestamp); + + return result; + }; + + var tsInspector = { + inspect: inspect + }; + + /* + * pkcs7.pad + * https://github.com/brightcove/pkcs7 + * + * Copyright (c) 2014 Brightcove + * Licensed under the apache2 license. + */ + + /** + * Returns the subarray of a Uint8Array without PKCS#7 padding. + * @param padded {Uint8Array} unencrypted bytes that have been padded + * @return {Uint8Array} the unpadded bytes + * @see http://tools.ietf.org/html/rfc5652 + */ + function unpad(padded) { + return padded.subarray(0, padded.byteLength - padded[padded.byteLength - 1]); + } + + var classCallCheck$2 = function classCallCheck$$1(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var createClass$1 = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + var inherits$2 = function inherits$$1(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : _typeof(superClass))); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + }; + + var possibleConstructorReturn$2 = function possibleConstructorReturn$$1(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && ((typeof call === "undefined" ? "undefined" : _typeof(call)) === "object" || typeof call === "function") ? call : self; + }; + + /** + * @file aes.js + * + * This file contains an adaptation of the AES decryption algorithm + * from the Standford Javascript Cryptography Library. That work is + * covered by the following copyright and permissions notice: + * + * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the authors. + */ + + /** + * Expand the S-box tables. + * + * @private + */ + var precompute = function precompute() { + var tables = [[[], [], [], [], []], [[], [], [], [], []]]; + var encTable = tables[0]; + var decTable = tables[1]; + var sbox = encTable[4]; + var sboxInv = decTable[4]; + var i = void 0; + var x = void 0; + var xInv = void 0; + var d = []; + var th = []; + var x2 = void 0; + var x4 = void 0; + var x8 = void 0; + var s = void 0; + var tEnc = void 0; + var tDec = void 0; + + // Compute double and third tables + for (i = 0; i < 256; i++) { + th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i; + } + + for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) { + // Compute sbox + s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4; + s = s >> 8 ^ s & 255 ^ 99; + sbox[x] = s; + sboxInv[s] = x; + + // Compute MixColumns + x8 = d[x4 = d[x2 = d[x]]]; + tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100; + tEnc = d[s] * 0x101 ^ s * 0x1010100; + + for (i = 0; i < 4; i++) { + encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8; + decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8; + } + } + + // Compactify. Considerable speedup on Firefox. + for (i = 0; i < 5; i++) { + encTable[i] = encTable[i].slice(0); + decTable[i] = decTable[i].slice(0); + } + return tables; + }; + var aesTables = null; + + /** + * Schedule out an AES key for both encryption and decryption. This + * is a low-level class. Use a cipher mode to do bulk encryption. + * + * @class AES + * @param key {Array} The key as an array of 4, 6 or 8 words. + */ + + var AES = function () { + function AES(key) { + classCallCheck$2(this, AES); + + /** + * The expanded S-box and inverse S-box tables. These will be computed + * on the client so that we don't have to send them down the wire. + * + * There are two tables, _tables[0] is for encryption and + * _tables[1] is for decryption. + * + * The first 4 sub-tables are the expanded S-box with MixColumns. The + * last (_tables[01][4]) is the S-box itself. + * + * @private + */ + // if we have yet to precompute the S-box tables + // do so now + if (!aesTables) { + aesTables = precompute(); + } + // then make a copy of that object for use + this._tables = [[aesTables[0][0].slice(), aesTables[0][1].slice(), aesTables[0][2].slice(), aesTables[0][3].slice(), aesTables[0][4].slice()], [aesTables[1][0].slice(), aesTables[1][1].slice(), aesTables[1][2].slice(), aesTables[1][3].slice(), aesTables[1][4].slice()]]; + var i = void 0; + var j = void 0; + var tmp = void 0; + var encKey = void 0; + var decKey = void 0; + var sbox = this._tables[0][4]; + var decTable = this._tables[1]; + var keyLen = key.length; + var rcon = 1; + + if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) { + throw new Error('Invalid aes key size'); + } + + encKey = key.slice(0); + decKey = []; + this._key = [encKey, decKey]; + + // schedule encryption keys + for (i = keyLen; i < 4 * keyLen + 28; i++) { + tmp = encKey[i - 1]; + + // apply sbox + if (i % keyLen === 0 || keyLen === 8 && i % keyLen === 4) { + tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255]; + + // shift rows and add rcon + if (i % keyLen === 0) { + tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24; + rcon = rcon << 1 ^ (rcon >> 7) * 283; + } + } + + encKey[i] = encKey[i - keyLen] ^ tmp; + } + + // schedule decryption keys + for (j = 0; i; j++, i--) { + tmp = encKey[j & 3 ? i : i - 4]; + if (i <= 4 || j < 4) { + decKey[j] = tmp; + } else { + decKey[j] = decTable[0][sbox[tmp >>> 24]] ^ decTable[1][sbox[tmp >> 16 & 255]] ^ decTable[2][sbox[tmp >> 8 & 255]] ^ decTable[3][sbox[tmp & 255]]; + } + } + } + + /** + * Decrypt 16 bytes, specified as four 32-bit words. + * + * @param {Number} encrypted0 the first word to decrypt + * @param {Number} encrypted1 the second word to decrypt + * @param {Number} encrypted2 the third word to decrypt + * @param {Number} encrypted3 the fourth word to decrypt + * @param {Int32Array} out the array to write the decrypted words + * into + * @param {Number} offset the offset into the output array to start + * writing results + * @return {Array} The plaintext. + */ + + AES.prototype.decrypt = function decrypt(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) { + var key = this._key[1]; + // state variables a,b,c,d are loaded with pre-whitened data + var a = encrypted0 ^ key[0]; + var b = encrypted3 ^ key[1]; + var c = encrypted2 ^ key[2]; + var d = encrypted1 ^ key[3]; + var a2 = void 0; + var b2 = void 0; + var c2 = void 0; + + // key.length === 2 ? + var nInnerRounds = key.length / 4 - 2; + var i = void 0; + var kIndex = 4; + var table = this._tables[1]; + + // load up the tables + var table0 = table[0]; + var table1 = table[1]; + var table2 = table[2]; + var table3 = table[3]; + var sbox = table[4]; + + // Inner rounds. Cribbed from OpenSSL. + for (i = 0; i < nInnerRounds; i++) { + a2 = table0[a >>> 24] ^ table1[b >> 16 & 255] ^ table2[c >> 8 & 255] ^ table3[d & 255] ^ key[kIndex]; + b2 = table0[b >>> 24] ^ table1[c >> 16 & 255] ^ table2[d >> 8 & 255] ^ table3[a & 255] ^ key[kIndex + 1]; + c2 = table0[c >>> 24] ^ table1[d >> 16 & 255] ^ table2[a >> 8 & 255] ^ table3[b & 255] ^ key[kIndex + 2]; + d = table0[d >>> 24] ^ table1[a >> 16 & 255] ^ table2[b >> 8 & 255] ^ table3[c & 255] ^ key[kIndex + 3]; + kIndex += 4; + a = a2; + b = b2; + c = c2; + } + + // Last round. + for (i = 0; i < 4; i++) { + out[(3 & -i) + offset] = sbox[a >>> 24] << 24 ^ sbox[b >> 16 & 255] << 16 ^ sbox[c >> 8 & 255] << 8 ^ sbox[d & 255] ^ key[kIndex++]; + a2 = a; + a = b; + b = c; + c = d; + d = a2; + } + }; + + return AES; + }(); + + /** + * @file stream.js + */ + /** + * A lightweight readable stream implemention that handles event dispatching. + * + * @class Stream + */ + var Stream$3 = function () { + function Stream() { + classCallCheck$2(this, Stream); + + this.listeners = {}; + } + + /** + * Add a listener for a specified event type. + * + * @param {String} type the event name + * @param {Function} listener the callback to be invoked when an event of + * the specified type occurs + */ + + Stream.prototype.on = function on(type, listener) { + if (!this.listeners[type]) { + this.listeners[type] = []; + } + this.listeners[type].push(listener); + }; + + /** + * Remove a listener for a specified event type. + * + * @param {String} type the event name + * @param {Function} listener a function previously registered for this + * type of event through `on` + * @return {Boolean} if we could turn it off or not + */ + + Stream.prototype.off = function off(type, listener) { + if (!this.listeners[type]) { + return false; + } + + var index = this.listeners[type].indexOf(listener); + + this.listeners[type].splice(index, 1); + return index > -1; + }; + + /** + * Trigger an event of the specified type on this stream. Any additional + * arguments to this function are passed as parameters to event listeners. + * + * @param {String} type the event name + */ + + Stream.prototype.trigger = function trigger(type) { + var callbacks = this.listeners[type]; + + if (!callbacks) { + return; + } + + // Slicing the arguments on every invocation of this method + // can add a significant amount of overhead. Avoid the + // intermediate object creation for the common case of a + // single callback argument + if (arguments.length === 2) { + var length = callbacks.length; + + for (var i = 0; i < length; ++i) { + callbacks[i].call(this, arguments[1]); + } + } else { + var args = Array.prototype.slice.call(arguments, 1); + var _length = callbacks.length; + + for (var _i = 0; _i < _length; ++_i) { + callbacks[_i].apply(this, args); + } + } + }; + + /** + * Destroys the stream and cleans up. + */ + + Stream.prototype.dispose = function dispose() { + this.listeners = {}; + }; + /** + * Forwards all `data` events on this stream to the destination stream. The + * destination stream should provide a method `push` to receive the data + * events as they arrive. + * + * @param {Stream} destination the stream that will receive all `data` events + * @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options + */ + + Stream.prototype.pipe = function pipe(destination) { + this.on('data', function (data) { + destination.push(data); + }); + }; + + return Stream; + }(); + + /** + * @file async-stream.js + */ + /** + * A wrapper around the Stream class to use setTiemout + * and run stream "jobs" Asynchronously + * + * @class AsyncStream + * @extends Stream + */ + + var AsyncStream = function (_Stream) { + inherits$2(AsyncStream, _Stream); + + function AsyncStream() { + classCallCheck$2(this, AsyncStream); + + var _this = possibleConstructorReturn$2(this, _Stream.call(this, Stream$3)); + + _this.jobs = []; + _this.delay = 1; + _this.timeout_ = null; + return _this; + } + + /** + * process an async job + * + * @private + */ + + AsyncStream.prototype.processJob_ = function processJob_() { + this.jobs.shift()(); + if (this.jobs.length) { + this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay); + } else { + this.timeout_ = null; + } + }; + + /** + * push a job into the stream + * + * @param {Function} job the job to push into the stream + */ + + AsyncStream.prototype.push = function push(job) { + this.jobs.push(job); + if (!this.timeout_) { + this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay); + } + }; + + return AsyncStream; + }(Stream$3); + + /** + * @file decrypter.js + * + * An asynchronous implementation of AES-128 CBC decryption with + * PKCS#7 padding. + */ + + /** + * Convert network-order (big-endian) bytes into their little-endian + * representation. + */ + var ntoh = function ntoh(word) { + return word << 24 | (word & 0xff00) << 8 | (word & 0xff0000) >> 8 | word >>> 24; + }; + + /** + * Decrypt bytes using AES-128 with CBC and PKCS#7 padding. + * + * @param {Uint8Array} encrypted the encrypted bytes + * @param {Uint32Array} key the bytes of the decryption key + * @param {Uint32Array} initVector the initialization vector (IV) to + * use for the first round of CBC. + * @return {Uint8Array} the decrypted bytes + * + * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard + * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29 + * @see https://tools.ietf.org/html/rfc2315 + */ + var decrypt = function decrypt(encrypted, key, initVector) { + // word-level access to the encrypted bytes + var encrypted32 = new Int32Array(encrypted.buffer, encrypted.byteOffset, encrypted.byteLength >> 2); + + var decipher = new AES(Array.prototype.slice.call(key)); + + // byte and word-level access for the decrypted output + var decrypted = new Uint8Array(encrypted.byteLength); + var decrypted32 = new Int32Array(decrypted.buffer); + + // temporary variables for working with the IV, encrypted, and + // decrypted data + var init0 = void 0; + var init1 = void 0; + var init2 = void 0; + var init3 = void 0; + var encrypted0 = void 0; + var encrypted1 = void 0; + var encrypted2 = void 0; + var encrypted3 = void 0; + + // iteration variable + var wordIx = void 0; + + // pull out the words of the IV to ensure we don't modify the + // passed-in reference and easier access + init0 = initVector[0]; + init1 = initVector[1]; + init2 = initVector[2]; + init3 = initVector[3]; + + // decrypt four word sequences, applying cipher-block chaining (CBC) + // to each decrypted block + for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) { + // convert big-endian (network order) words into little-endian + // (javascript order) + encrypted0 = ntoh(encrypted32[wordIx]); + encrypted1 = ntoh(encrypted32[wordIx + 1]); + encrypted2 = ntoh(encrypted32[wordIx + 2]); + encrypted3 = ntoh(encrypted32[wordIx + 3]); + + // decrypt the block + decipher.decrypt(encrypted0, encrypted1, encrypted2, encrypted3, decrypted32, wordIx); + + // XOR with the IV, and restore network byte-order to obtain the + // plaintext + decrypted32[wordIx] = ntoh(decrypted32[wordIx] ^ init0); + decrypted32[wordIx + 1] = ntoh(decrypted32[wordIx + 1] ^ init1); + decrypted32[wordIx + 2] = ntoh(decrypted32[wordIx + 2] ^ init2); + decrypted32[wordIx + 3] = ntoh(decrypted32[wordIx + 3] ^ init3); + + // setup the IV for the next round + init0 = encrypted0; + init1 = encrypted1; + init2 = encrypted2; + init3 = encrypted3; + } + + return decrypted; + }; + + /** + * The `Decrypter` class that manages decryption of AES + * data through `AsyncStream` objects and the `decrypt` + * function + * + * @param {Uint8Array} encrypted the encrypted bytes + * @param {Uint32Array} key the bytes of the decryption key + * @param {Uint32Array} initVector the initialization vector (IV) to + * @param {Function} done the function to run when done + * @class Decrypter + */ + + var Decrypter = function () { + function Decrypter(encrypted, key, initVector, done) { + classCallCheck$2(this, Decrypter); + + var step = Decrypter.STEP; + var encrypted32 = new Int32Array(encrypted.buffer); + var decrypted = new Uint8Array(encrypted.byteLength); + var i = 0; + + this.asyncStream_ = new AsyncStream(); + + // split up the encryption job and do the individual chunks asynchronously + this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted)); + for (i = step; i < encrypted32.length; i += step) { + initVector = new Uint32Array([ntoh(encrypted32[i - 4]), ntoh(encrypted32[i - 3]), ntoh(encrypted32[i - 2]), ntoh(encrypted32[i - 1])]); + this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted)); + } + // invoke the done() callback when everything is finished + this.asyncStream_.push(function () { + // remove pkcs#7 padding from the decrypted bytes + done(null, unpad(decrypted)); + }); + } + + /** + * a getter for step the maximum number of bytes to process at one time + * + * @return {Number} the value of step 32000 + */ + + /** + * @private + */ + Decrypter.prototype.decryptChunk_ = function decryptChunk_(encrypted, key, initVector, decrypted) { + return function () { + var bytes = decrypt(encrypted, key, initVector); + + decrypted.set(bytes, encrypted.byteOffset); + }; + }; + + createClass$1(Decrypter, null, [{ + key: 'STEP', + get: function get$$1() { + // 4 * 8000; + return 32000; + } + }]); + return Decrypter; + }(); + + /** + * @videojs/http-streaming + * @version 1.0.0 + * @copyright 2018 Brightcove, Inc + * @license Apache-2.0 + */ + + /** + * @file resolve-url.js + */ + + var resolveUrl$1 = function resolveUrl(baseURL, relativeURL) { + // return early if we don't need to resolve + if (/^[a-z]+:/i.test(relativeURL)) { + return relativeURL; + } + + // if the base URL is relative then combine with the current location + if (!/\/\//i.test(baseURL)) { + baseURL = urlToolkit.buildAbsoluteURL(window_1.location.href, baseURL); + } + + return urlToolkit.buildAbsoluteURL(baseURL, relativeURL); + }; + + /** + * @file playlist-loader.js + * + * A state machine that manages the loading, caching, and updating of + * M3U8 playlists. + * + */ + + var mergeOptions$1 = videojs$1.mergeOptions, + EventTarget$1 = videojs$1.EventTarget, + log$2 = videojs$1.log; + + /** + * Loops through all supported media groups in master and calls the provided + * callback for each group + * + * @param {Object} master + * The parsed master manifest object + * @param {Function} callback + * Callback to call for each media group + */ + + var forEachMediaGroup = function forEachMediaGroup(master, callback) { + ['AUDIO', 'SUBTITLES'].forEach(function (mediaType) { + for (var groupKey in master.mediaGroups[mediaType]) { + for (var labelKey in master.mediaGroups[mediaType][groupKey]) { + var mediaProperties = master.mediaGroups[mediaType][groupKey][labelKey]; + + callback(mediaProperties, mediaType, groupKey, labelKey); + } + } + }); + }; + + /** + * Returns a new array of segments that is the result of merging + * properties from an older list of segments onto an updated + * list. No properties on the updated playlist will be overridden. + * + * @param {Array} original the outdated list of segments + * @param {Array} update the updated list of segments + * @param {Number=} offset the index of the first update + * segment in the original segment list. For non-live playlists, + * this should always be zero and does not need to be + * specified. For live playlists, it should be the difference + * between the media sequence numbers in the original and updated + * playlists. + * @return a list of merged segment objects + */ + var updateSegments = function updateSegments(original, update, offset) { + var result = update.slice(); + + offset = offset || 0; + var length = Math.min(original.length, update.length + offset); + + for (var i = offset; i < length; i++) { + result[i - offset] = mergeOptions$1(original[i], result[i - offset]); + } + return result; + }; + + var resolveSegmentUris = function resolveSegmentUris(segment, baseUri) { + if (!segment.resolvedUri) { + segment.resolvedUri = resolveUrl$1(baseUri, segment.uri); + } + if (segment.key && !segment.key.resolvedUri) { + segment.key.resolvedUri = resolveUrl$1(baseUri, segment.key.uri); + } + if (segment.map && !segment.map.resolvedUri) { + segment.map.resolvedUri = resolveUrl$1(baseUri, segment.map.uri); + } + }; + + /** + * Returns a new master playlist that is the result of merging an + * updated media playlist into the original version. If the + * updated media playlist does not match any of the playlist + * entries in the original master playlist, null is returned. + * + * @param {Object} master a parsed master M3U8 object + * @param {Object} media a parsed media M3U8 object + * @return {Object} a new object that represents the original + * master playlist with the updated media playlist merged in, or + * null if the merge produced no change. + */ + var updateMaster = function updateMaster(master, media) { + var result = mergeOptions$1(master, {}); + var playlist = result.playlists[media.uri]; + + if (!playlist) { + return null; + } + + // consider the playlist unchanged if the number of segments is equal and the media + // sequence number is unchanged + if (playlist.segments && media.segments && playlist.segments.length === media.segments.length && playlist.mediaSequence === media.mediaSequence) { + return null; + } + + var mergedPlaylist = mergeOptions$1(playlist, media); + + // if the update could overlap existing segment information, merge the two segment lists + if (playlist.segments) { + mergedPlaylist.segments = updateSegments(playlist.segments, media.segments, media.mediaSequence - playlist.mediaSequence); + } + + // resolve any segment URIs to prevent us from having to do it later + mergedPlaylist.segments.forEach(function (segment) { + resolveSegmentUris(segment, mergedPlaylist.resolvedUri); + }); + + // TODO Right now in the playlists array there are two references to each playlist, one + // that is referenced by index, and one by URI. The index reference may no longer be + // necessary. + for (var i = 0; i < result.playlists.length; i++) { + if (result.playlists[i].uri === media.uri) { + result.playlists[i] = mergedPlaylist; + } + } + result.playlists[media.uri] = mergedPlaylist; + + return result; + }; + + var setupMediaPlaylists = function setupMediaPlaylists(master) { + // setup by-URI lookups and resolve media playlist URIs + var i = master.playlists.length; + + while (i--) { + var playlist = master.playlists[i]; + + master.playlists[playlist.uri] = playlist; + playlist.resolvedUri = resolveUrl$1(master.uri, playlist.uri); + playlist.id = i; + + if (!playlist.attributes) { + // Although the spec states an #EXT-X-STREAM-INF tag MUST have a + // BANDWIDTH attribute, we can playOld the stream without it. This means a poorly + // formatted master playlist may not have an attribute list. An attributes + // property is added here to prevent undefined references when we encounter + // this scenario. + playlist.attributes = {}; + + log$2.warn('Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute.'); + } + } + }; + + var resolveMediaGroupUris = function resolveMediaGroupUris(master) { + forEachMediaGroup(master, function (properties) { + if (properties.uri) { + properties.resolvedUri = resolveUrl$1(master.uri, properties.uri); + } + }); + }; + + /** + * Calculates the time to wait before refreshing a live playlist + * + * @param {Object} media + * The current media + * @param {Boolean} update + * True if there were any updates from the last refresh, false otherwise + * @return {Number} + * The time in ms to wait before refreshing the live playlist + */ + var refreshDelay = function refreshDelay(media, update) { + var lastSegment = media.segments[media.segments.length - 1]; + var delay = void 0; + + if (update && lastSegment && lastSegment.duration) { + delay = lastSegment.duration * 1000; + } else { + // if the playlist is unchanged since the last reload or last segment duration + // cannot be determined, try again after half the target duration + delay = (media.targetDuration || 10) * 500; + } + return delay; + }; + + /** + * Load a playlist from a remote location + * + * @class PlaylistLoader + * @extends Stream + * @param {String} srcUrl the url to start with + * @param {Boolean} withCredentials the withCredentials xhr option + * @constructor + */ + + var PlaylistLoader = function (_EventTarget) { + inherits(PlaylistLoader, _EventTarget); + + function PlaylistLoader(srcUrl, hls, withCredentials) { + classCallCheck(this, PlaylistLoader); + + var _this2 = possibleConstructorReturn(this, _EventTarget.call(this)); + + _this2.srcUrl = srcUrl; + _this2.hls_ = hls; + _this2.withCredentials = withCredentials; + + if (!_this2.srcUrl) { + throw new Error('A non-empty playlist URL is required'); + } + + // initialize the loader state + _this2.state = 'HAVE_NOTHING'; + + // live playlist staleness timeout + _this2.on('mediaupdatetimeout', function () { + if (_this2.state !== 'HAVE_METADATA') { + // only refresh the media playlist if no other activity is going on + return; + } + + _this2.state = 'HAVE_CURRENT_METADATA'; + + _this2.request = _this2.hls_.xhr({ + uri: resolveUrl$1(_this2.master.uri, _this2.media().uri), + withCredentials: _this2.withCredentials + }, function (error, req) { + // disposed + if (!_this2.request) { + return; + } + + if (error) { + return _this2.playlistRequestError(_this2.request, _this2.media().uri, 'HAVE_METADATA'); + } + + _this2.haveMetadata(_this2.request, _this2.media().uri); + }); + }); + return _this2; + } + + PlaylistLoader.prototype.playlistRequestError = function playlistRequestError(xhr, url, startingState) { + // any in-flight request is now finished + this.request = null; + + if (startingState) { + this.state = startingState; + } + + this.error = { + playlist: this.master.playlists[url], + status: xhr.status, + message: 'HLS playlist request error at URL: ' + url, + responseText: xhr.responseText, + code: xhr.status >= 500 ? 4 : 2 + }; + + this.trigger('error'); + }; + + // update the playlist loader's state in response to a new or + // updated playlist. + + + PlaylistLoader.prototype.haveMetadata = function haveMetadata(xhr, url) { + var _this3 = this; + + // any in-flight request is now finished + this.request = null; + this.state = 'HAVE_METADATA'; + + var parser = new Parser(); + + parser.push(xhr.responseText); + parser.end(); + parser.manifest.uri = url; + // m3u8-parser does not attach an attributes property to media playlists so make + // sure that the property is attached to avoid undefined reference errors + parser.manifest.attributes = parser.manifest.attributes || {}; + + // merge this playlist into the master + var update = updateMaster(this.master, parser.manifest); + + this.targetDuration = parser.manifest.targetDuration; + + if (update) { + this.master = update; + this.media_ = this.master.playlists[parser.manifest.uri]; + } else { + this.trigger('playlistunchanged'); + } + + // refresh live playlists after a target duration passes + if (!this.media().endList) { + window_1.clearTimeout(this.mediaUpdateTimeout); + this.mediaUpdateTimeout = window_1.setTimeout(function () { + _this3.trigger('mediaupdatetimeout'); + }, refreshDelay(this.media(), !!update)); + } + + this.trigger('loadedplaylist'); + }; + + /** + * Abort any outstanding work and clean up. + */ + + + PlaylistLoader.prototype.dispose = function dispose() { + this.stopRequest(); + window_1.clearTimeout(this.mediaUpdateTimeout); + }; + + PlaylistLoader.prototype.stopRequest = function stopRequest() { + if (this.request) { + var oldRequest = this.request; + + this.request = null; + oldRequest.onreadystatechange = null; + oldRequest.abort(); + } + }; + + /** + * When called without any arguments, returns the currently + * active media playlist. When called with a single argument, + * triggers the playlist loader to asynchronously switch to the + * specified media playlist. Calling this method while the + * loader is in the HAVE_NOTHING causes an error to be emitted + * but otherwise has no effect. + * + * @param {Object=} playlist the parsed media playlist + * object to switch to + * @return {Playlist} the current loaded media + */ + + + PlaylistLoader.prototype.media = function media(playlist) { + var _this4 = this; + + // getter + if (!playlist) { + return this.media_; + } + + // setter + if (this.state === 'HAVE_NOTHING') { + throw new Error('Cannot switch media playlist from ' + this.state); + } + + var startingState = this.state; + + // find the playlist object if the target playlist has been + // specified by URI + if (typeof playlist === 'string') { + if (!this.master.playlists[playlist]) { + throw new Error('Unknown playlist URI: ' + playlist); + } + playlist = this.master.playlists[playlist]; + } + + var mediaChange = !this.media_ || playlist.uri !== this.media_.uri; + + // switch to fully loaded playlists immediately + if (this.master.playlists[playlist.uri].endList) { + // abort outstanding playlist requests + if (this.request) { + this.request.onreadystatechange = null; + this.request.abort(); + this.request = null; + } + this.state = 'HAVE_METADATA'; + this.media_ = playlist; + + // trigger media change if the active media has been updated + if (mediaChange) { + this.trigger('mediachanging'); + this.trigger('mediachange'); + } + return; + } + + // switching to the active playlist is a no-op + if (!mediaChange) { + return; + } + + this.state = 'SWITCHING_MEDIA'; + + // there is already an outstanding playlist request + if (this.request) { + if (resolveUrl$1(this.master.uri, playlist.uri) === this.request.url) { + // requesting to switch to the same playlist multiple times + // has no effect after the first + return; + } + this.request.onreadystatechange = null; + this.request.abort(); + this.request = null; + } + + // request the new playlist + if (this.media_) { + this.trigger('mediachanging'); + } + + this.request = this.hls_.xhr({ + uri: resolveUrl$1(this.master.uri, playlist.uri), + withCredentials: this.withCredentials + }, function (error, req) { + // disposed + if (!_this4.request) { + return; + } + + if (error) { + return _this4.playlistRequestError(_this4.request, playlist.uri, startingState); + } + + _this4.haveMetadata(req, playlist.uri); + + // fire loadedmetadata the first time a media playlist is loaded + if (startingState === 'HAVE_MASTER') { + _this4.trigger('loadedmetadata'); + } else { + _this4.trigger('mediachange'); + } + }); + }; + + /** + * pause loading of the playlist + */ + + + PlaylistLoader.prototype.pause = function pause() { + this.stopRequest(); + window_1.clearTimeout(this.mediaUpdateTimeout); + if (this.state === 'HAVE_NOTHING') { + // If we pause the loader before any data has been retrieved, its as if we never + // started, so reset to an unstarted state. + this.started = false; + } + // Need to restore state now that no activity is happening + if (this.state === 'SWITCHING_MEDIA') { + // if the loader was in the process of switching media, it should either return to + // HAVE_MASTER or HAVE_METADATA depending on if the loader has loaded a media + // playlist yet. This is determined by the existence of loader.media_ + if (this.media_) { + this.state = 'HAVE_METADATA'; + } else { + this.state = 'HAVE_MASTER'; + } + } else if (this.state === 'HAVE_CURRENT_METADATA') { + this.state = 'HAVE_METADATA'; + } + }; + + /** + * start loading of the playlist + */ + + + PlaylistLoader.prototype.load = function load(isFinalRendition) { + var _this5 = this; + + window_1.clearTimeout(this.mediaUpdateTimeout); + + var media = this.media(); + + if (isFinalRendition) { + var delay = media ? media.targetDuration / 2 * 1000 : 5 * 1000; + + this.mediaUpdateTimeout = window_1.setTimeout(function () { + return _this5.load(); + }, delay); + return; + } + + if (!this.started) { + this.start(); + return; + } + + if (media && !media.endList) { + this.trigger('mediaupdatetimeout'); + } else { + this.trigger('loadedplaylist'); + } + }; + + /** + * start loading of the playlist + */ + + + PlaylistLoader.prototype.start = function start() { + var _this6 = this; + + this.started = true; + + // request the specified URL + this.request = this.hls_.xhr({ + uri: this.srcUrl, + withCredentials: this.withCredentials + }, function (error, req) { + // disposed + if (!_this6.request) { + return; + } + + // clear the loader's request reference + _this6.request = null; + + if (error) { + _this6.error = { + status: req.status, + message: 'HLS playlist request error at URL: ' + _this6.srcUrl, + responseText: req.responseText, + // MEDIA_ERR_NETWORK + code: 2 + }; + if (_this6.state === 'HAVE_NOTHING') { + _this6.started = false; + } + return _this6.trigger('error'); + } + + var parser = new Parser(); + + parser.push(req.responseText); + parser.end(); + + _this6.state = 'HAVE_MASTER'; + + parser.manifest.uri = _this6.srcUrl; + + // loaded a master playlist + if (parser.manifest.playlists) { + _this6.master = parser.manifest; + + setupMediaPlaylists(_this6.master); + resolveMediaGroupUris(_this6.master); + + _this6.trigger('loadedplaylist'); + if (!_this6.request) { + // no media playlist was specifically selected so start + // from the first listed one + _this6.media(parser.manifest.playlists[0]); + } + return; + } + + // loaded a media playlist + // infer a master playlist if none was previously requested + _this6.master = { + mediaGroups: { + 'AUDIO': {}, + 'VIDEO': {}, + 'CLOSED-CAPTIONS': {}, + 'SUBTITLES': {} + }, + uri: window_1.location.href, + playlists: [{ + uri: _this6.srcUrl, + id: 0 + }] + }; + _this6.master.playlists[_this6.srcUrl] = _this6.master.playlists[0]; + _this6.master.playlists[0].resolvedUri = _this6.srcUrl; + // m3u8-parser does not attach an attributes property to media playlists so make + // sure that the property is attached to avoid undefined reference errors + _this6.master.playlists[0].attributes = _this6.master.playlists[0].attributes || {}; + _this6.haveMetadata(req, _this6.srcUrl); + return _this6.trigger('loadedmetadata'); + }); + }; + + return PlaylistLoader; + }(EventTarget$1); + + /** + * @file playlist.js + * + * Playlist related utilities. + */ + + var createTimeRange = videojs$1.createTimeRange; + + /** + * walk backward until we find a duration we can use + * or return a failure + * + * @param {Playlist} playlist the playlist to walk through + * @param {Number} endSequence the mediaSequence to stop walking on + */ + + var backwardDuration = function backwardDuration(playlist, endSequence) { + var result = 0; + var i = endSequence - playlist.mediaSequence; + // if a start time is available for segment immediately following + // the interval, use it + var segment = playlist.segments[i]; + + // Walk backward until we find the latest segment with timeline + // information that is earlier than endSequence + if (segment) { + if (typeof segment.start !== 'undefined') { + return {result: segment.start, precise: true}; + } + if (typeof segment.end !== 'undefined') { + return { + result: segment.end - segment.duration, + precise: true + }; + } + } + while (i--) { + segment = playlist.segments[i]; + if (typeof segment.end !== 'undefined') { + return {result: result + segment.end, precise: true}; + } + + result += segment.duration; + + if (typeof segment.start !== 'undefined') { + return {result: result + segment.start, precise: true}; + } + } + return {result: result, precise: false}; + }; + + /** + * walk forward until we find a duration we can use + * or return a failure + * + * @param {Playlist} playlist the playlist to walk through + * @param {Number} endSequence the mediaSequence to stop walking on + */ + var forwardDuration = function forwardDuration(playlist, endSequence) { + var result = 0; + var segment = void 0; + var i = endSequence - playlist.mediaSequence; + // Walk forward until we find the earliest segment with timeline + // information + + for (; i < playlist.segments.length; i++) { + segment = playlist.segments[i]; + if (typeof segment.start !== 'undefined') { + return { + result: segment.start - result, + precise: true + }; + } + + result += segment.duration; + + if (typeof segment.end !== 'undefined') { + return { + result: segment.end - result, + precise: true + }; + } + } + // indicate we didn't find a useful duration estimate + return {result: -1, precise: false}; + }; + + /** + * Calculate the media duration from the segments associated with a + * playlist. The duration of a subinterval of the available segments + * may be calculated by specifying an end index. + * + * @param {Object} playlist a media playlist object + * @param {Number=} endSequence an exclusive upper boundary + * for the playlist. Defaults to playlist length. + * @param {Number} expired the amount of time that has dropped + * off the front of the playlist in a live scenario + * @return {Number} the duration between the first available segment + * and end index. + */ + var intervalDuration = function intervalDuration(playlist, endSequence, expired) { + var backward = void 0; + var forward = void 0; + + if (typeof endSequence === 'undefined') { + endSequence = playlist.mediaSequence + playlist.segments.length; + } + + if (endSequence < playlist.mediaSequence) { + return 0; + } + + // do a backward walk to estimate the duration + backward = backwardDuration(playlist, endSequence); + if (backward.precise) { + // if we were able to base our duration estimate on timing + // information provided directly from the Media Source, return + // it + return backward.result; + } + + // walk forward to see if a precise duration estimate can be made + // that way + forward = forwardDuration(playlist, endSequence); + if (forward.precise) { + // we found a segment that has been buffered and so it's + // position is known precisely + return forward.result; + } + + // return the less-precise, playlist-based duration estimate + return backward.result + expired; + }; + + /** + * Calculates the duration of a playlist. If a start and end index + * are specified, the duration will be for the subset of the media + * timeline between those two indices. The total duration for live + * playlists is always Infinity. + * + * @param {Object} playlist a media playlist object + * @param {Number=} endSequence an exclusive upper + * boundary for the playlist. Defaults to the playlist media + * sequence number plus its length. + * @param {Number=} expired the amount of time that has + * dropped off the front of the playlist in a live scenario + * @return {Number} the duration between the start index and end + * index. + */ + var duration = function duration(playlist, endSequence, expired) { + if (!playlist) { + return 0; + } + + if (typeof expired !== 'number') { + expired = 0; + } + + // if a slice of the total duration is not requested, use + // playlist-level duration indicators when they're present + if (typeof endSequence === 'undefined') { + // if present, use the duration specified in the playlist + if (playlist.totalDuration) { + return playlist.totalDuration; + } + + // duration should be Infinity for live playlists + if (!playlist.endList) { + return window_1.Infinity; + } + } + + // calculate the total duration based on the segment durations + return intervalDuration(playlist, endSequence, expired); + }; + + /** + * Calculate the time between two indexes in the current playlist + * neight the start- nor the end-index need to be within the current + * playlist in which case, the targetDuration of the playlist is used + * to approximate the durations of the segments + * + * @param {Object} playlist a media playlist object + * @param {Number} startIndex + * @param {Number} endIndex + * @return {Number} the number of seconds between startIndex and endIndex + */ + var sumDurations = function sumDurations(playlist, startIndex, endIndex) { + var durations = 0; + + if (startIndex > endIndex) { + var _ref = [endIndex, startIndex]; + startIndex = _ref[0]; + endIndex = _ref[1]; + } + + if (startIndex < 0) { + for (var i = startIndex; i < Math.min(0, endIndex); i++) { + durations += playlist.targetDuration; + } + startIndex = 0; + } + + for (var _i2 = startIndex; _i2 < endIndex; _i2++) { + durations += playlist.segments[_i2].duration; + } + + return durations; + }; + + /** + * Determines the media index of the segment corresponding to the safe edge of the live + * window which is the duration of the last segment plus 2 target durations from the end + * of the playlist. + * + * @param {Object} playlist + * a media playlist object + * @return {Number} + * The media index of the segment at the safe live point. 0 if there is no "safe" + * point. + * @function safeLiveIndex + */ + var safeLiveIndex = function safeLiveIndex(playlist) { + if (!playlist.segments.length) { + return 0; + } + + var i = playlist.segments.length - 1; + var distanceFromEnd = playlist.segments[i].duration || playlist.targetDuration; + var safeDistance = distanceFromEnd + playlist.targetDuration * 2; + + while (i--) { + distanceFromEnd += playlist.segments[i].duration; + + if (distanceFromEnd >= safeDistance) { + break; + } + } + + return Math.max(0, i); + }; + + /** + * Calculates the playlist end time + * + * @param {Object} playlist a media playlist object + * @param {Number=} expired the amount of time that has + * dropped off the front of the playlist in a live scenario + * @param {Boolean|false} useSafeLiveEnd a boolean value indicating whether or not the + * playlist end calculation should consider the safe live end + * (truncate the playlist end by three segments). This is normally + * used for calculating the end of the playlist's seekable range. + * @returns {Number} the end time of playlist + * @function playlistEnd + */ + var playlistEnd = function playlistEnd(playlist, expired, useSafeLiveEnd) { + if (!playlist || !playlist.segments) { + return null; + } + if (playlist.endList) { + return duration(playlist); + } + + if (expired === null) { + return null; + } + + expired = expired || 0; + + var endSequence = useSafeLiveEnd ? safeLiveIndex(playlist) : playlist.segments.length; + + return intervalDuration(playlist, playlist.mediaSequence + endSequence, expired); + }; + + /** + * Calculates the interval of time that is currently seekable in a + * playlist. The returned time ranges are relative to the earliest + * moment in the specified playlist that is still available. A full + * seekable implementation for live streams would need to offset + * these values by the duration of content that has expired from the + * stream. + * + * @param {Object} playlist a media playlist object + * dropped off the front of the playlist in a live scenario + * @param {Number=} expired the amount of time that has + * dropped off the front of the playlist in a live scenario + * @return {TimeRanges} the periods of time that are valid targets + * for seeking + */ + var seekable = function seekable(playlist, expired) { + var useSafeLiveEnd = true; + var seekableStart = expired || 0; + var seekableEnd = playlistEnd(playlist, expired, useSafeLiveEnd); + + if (seekableEnd === null) { + return createTimeRange(); + } + return createTimeRange(seekableStart, seekableEnd); + }; + + var isWholeNumber = function isWholeNumber(num) { + return num - Math.floor(num) === 0; + }; + + var roundSignificantDigit = function roundSignificantDigit(increment, num) { + // If we have a whole number, just add 1 to it + if (isWholeNumber(num)) { + return num + increment * 0.1; + } + + var numDecimalDigits = num.toString().split('.')[1].length; + + for (var i = 1; i <= numDecimalDigits; i++) { + var scale = Math.pow(10, i); + var temp = num * scale; + + if (isWholeNumber(temp) || i === numDecimalDigits) { + return (temp + increment) / scale; + } + } + }; + + var ceilLeastSignificantDigit = roundSignificantDigit.bind(null, 1); + var floorLeastSignificantDigit = roundSignificantDigit.bind(null, -1); + + /** + * Determine the index and estimated starting time of the segment that + * contains a specified playback position in a media playlist. + * + * @param {Object} playlist the media playlist to query + * @param {Number} currentTime The number of seconds since the earliest + * possible position to determine the containing segment for + * @param {Number} startIndex + * @param {Number} startTime + * @return {Object} + */ + var getMediaInfoForTime = function getMediaInfoForTime(playlist, currentTime, startIndex, startTime) { + var i = void 0; + var segment = void 0; + var numSegments = playlist.segments.length; + + var time = currentTime - startTime; + + if (time < 0) { + // Walk backward from startIndex in the playlist, adding durations + // until we find a segment that contains `time` and return it + if (startIndex > 0) { + for (i = startIndex - 1; i >= 0; i--) { + segment = playlist.segments[i]; + time += floorLeastSignificantDigit(segment.duration); + if (time > 0) { + return { + mediaIndex: i, + startTime: startTime - sumDurations(playlist, startIndex, i) + }; + } + } + } + // We were unable to find a good segment within the playlist + // so select the first segment + return { + mediaIndex: 0, + startTime: currentTime + }; + } + + // When startIndex is negative, we first walk forward to first segment + // adding target durations. If we "run out of time" before getting to + // the first segment, return the first segment + if (startIndex < 0) { + for (i = startIndex; i < 0; i++) { + time -= playlist.targetDuration; + if (time < 0) { + return { + mediaIndex: 0, + startTime: currentTime + }; + } + } + startIndex = 0; + } + + // Walk forward from startIndex in the playlist, subtracting durations + // until we find a segment that contains `time` and return it + for (i = startIndex; i < numSegments; i++) { + segment = playlist.segments[i]; + time -= ceilLeastSignificantDigit(segment.duration); + if (time < 0) { + return { + mediaIndex: i, + startTime: startTime + sumDurations(playlist, startIndex, i) + }; + } + } + + // We are out of possible candidates so load the last one... + return { + mediaIndex: numSegments - 1, + startTime: currentTime + }; + }; + + /** + * Check whether the playlist is blacklisted or not. + * + * @param {Object} playlist the media playlist object + * @return {boolean} whether the playlist is blacklisted or not + * @function isBlacklisted + */ + var isBlacklisted = function isBlacklisted(playlist) { + return playlist.excludeUntil && playlist.excludeUntil > Date.now(); + }; + + /** + * Check whether the playlist is compatible with current playback configuration or has + * been blacklisted permanently for being incompatible. + * + * @param {Object} playlist the media playlist object + * @return {boolean} whether the playlist is incompatible or not + * @function isIncompatible + */ + var isIncompatible = function isIncompatible(playlist) { + return playlist.excludeUntil && playlist.excludeUntil === Infinity; + }; + + /** + * Check whether the playlist is enabled or not. + * + * @param {Object} playlist the media playlist object + * @return {boolean} whether the playlist is enabled or not + * @function isEnabled + */ + var isEnabled = function isEnabled(playlist) { + var blacklisted = isBlacklisted(playlist); + + return !playlist.disabled && !blacklisted; + }; + + /** + * Check whether the playlist has been manually disabled through the representations api. + * + * @param {Object} playlist the media playlist object + * @return {boolean} whether the playlist is disabled manually or not + * @function isDisabled + */ + var isDisabled = function isDisabled(playlist) { + return playlist.disabled; + }; + + /** + * Returns whether the current playlist is an AES encrypted HLS stream + * + * @return {Boolean} true if it's an AES encrypted HLS stream + */ + var isAes = function isAes(media) { + for (var i = 0; i < media.segments.length; i++) { + if (media.segments[i].key) { + return true; + } + } + return false; + }; + + /** + * Returns whether the current playlist contains fMP4 + * + * @return {Boolean} true if the playlist contains fMP4 + */ + var isFmp4 = function isFmp4(media) { + for (var i = 0; i < media.segments.length; i++) { + if (media.segments[i].map) { + return true; + } + } + return false; + }; + + /** + * Checks if the playlist has a value for the specified attribute + * + * @param {String} attr + * Attribute to check for + * @param {Object} playlist + * The media playlist object + * @return {Boolean} + * Whether the playlist contains a value for the attribute or not + * @function hasAttribute + */ + var hasAttribute = function hasAttribute(attr, playlist) { + return playlist.attributes && playlist.attributes[attr]; + }; + + /** + * Estimates the time required to complete a segment download from the specified playlist + * + * @param {Number} segmentDuration + * Duration of requested segment + * @param {Number} bandwidth + * Current measured bandwidth of the player + * @param {Object} playlist + * The media playlist object + * @param {Number=} bytesReceived + * Number of bytes already received for the request. Defaults to 0 + * @return {Number|NaN} + * The estimated time to request the segment. NaN if bandwidth information for + * the given playlist is unavailable + * @function estimateSegmentRequestTime + */ + var estimateSegmentRequestTime = function estimateSegmentRequestTime(segmentDuration, bandwidth, playlist) { + var bytesReceived = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + + if (!hasAttribute('BANDWIDTH', playlist)) { + return NaN; + } + + var size = segmentDuration * playlist.attributes.BANDWIDTH; + + return (size - bytesReceived * 8) / bandwidth; + }; + + /* + * Returns whether the current playlist is the lowest rendition + * + * @return {Boolean} true if on lowest rendition + */ + var isLowestEnabledRendition = function isLowestEnabledRendition(master, media) { + if (master.playlists.length === 1) { + return true; + } + + var currentBandwidth = media.attributes.BANDWIDTH || Number.MAX_VALUE; + + return master.playlists.filter(function (playlist) { + if (!isEnabled(playlist)) { + return false; + } + + return (playlist.attributes.BANDWIDTH || 0) < currentBandwidth; + }).length === 0; + }; + + // exports + var Playlist = { + duration: duration, + seekable: seekable, + safeLiveIndex: safeLiveIndex, + getMediaInfoForTime: getMediaInfoForTime, + isEnabled: isEnabled, + isDisabled: isDisabled, + isBlacklisted: isBlacklisted, + isIncompatible: isIncompatible, + playlistEnd: playlistEnd, + isAes: isAes, + isFmp4: isFmp4, + hasAttribute: hasAttribute, + estimateSegmentRequestTime: estimateSegmentRequestTime, + isLowestEnabledRendition: isLowestEnabledRendition + }; + + /** + * @file xhr.js + */ + + var videojsXHR = videojs$1.xhr, + mergeOptions$1$1 = videojs$1.mergeOptions; + + + var xhrFactory = function xhrFactory() { + var xhr = function XhrFunction(options, callback) { + // Add a default timeout for all hls requests + options = mergeOptions$1$1({ + timeout: 45e3 + }, options); + + // Allow an optional user-specified function to modify the option + // object before we construct the xhr request + var beforeRequest = XhrFunction.beforeRequest || videojs$1.Hls.xhr.beforeRequest; + + if (beforeRequest && typeof beforeRequest === 'function') { + var newOptions = beforeRequest(options); + + if (newOptions) { + options = newOptions; + } + } + + var request = videojsXHR(options, function (error, response) { + var reqResponse = request.response; + + if (!error && reqResponse) { + request.responseTime = Date.now(); + request.roundTripTime = request.responseTime - request.requestTime; + request.bytesReceived = reqResponse.byteLength || reqResponse.length; + if (!request.bandwidth) { + request.bandwidth = Math.floor(request.bytesReceived / request.roundTripTime * 8 * 1000); + } + } + + if (response.headers) { + request.responseHeaders = response.headers; + } + + // videojs.xhr now uses a specific code on the error + // object to signal that a request has timed out instead + // of setting a boolean on the request object + if (error && error.code === 'ETIMEDOUT') { + request.timedout = true; + } + + // videojs.xhr no longer considers status codes outside of 200 and 0 + // (for file uris) to be errors, but the old XHR did, so emulate that + // behavior. Status 206 may be used in response to byterange requests. + if (!error && !request.aborted && response.statusCode !== 200 && response.statusCode !== 206 && response.statusCode !== 0) { + error = new Error('XHR Failed with a response of: ' + (request && (reqResponse || request.responseText))); + } + + callback(error, request); + }); + var originalAbort = request.abort; + + request.abort = function () { + request.aborted = true; + return originalAbort.apply(request, arguments); + }; + request.uri = options.uri; + request.requestTime = Date.now(); + return request; + }; + + return xhr; + }; + + /** + * @file bin-utils.js + */ + + /** + * convert a TimeRange to text + * + * @param {TimeRange} range the timerange to use for conversion + * @param {Number} i the iterator on the range to convert + */ + var textRange = function textRange(range, i) { + return range.start(i) + '-' + range.end(i); + }; + + /** + * format a number as hex string + * + * @param {Number} e The number + * @param {Number} i the iterator + */ + var formatHexString = function formatHexString(e, i) { + var value = e.toString(16); + + return '00'.substring(0, 2 - value.length) + value + (i % 2 ? ' ' : ''); + }; + var formatAsciiString = function formatAsciiString(e) { + if (e >= 0x20 && e < 0x7e) { + return String.fromCharCode(e); + } + return '.'; + }; + + /** + * Creates an object for sending to a web worker modifying properties that are TypedArrays + * into a new object with seperated properties for the buffer, byteOffset, and byteLength. + * + * @param {Object} message + * Object of properties and values to send to the web worker + * @return {Object} + * Modified message with TypedArray values expanded + * @function createTransferableMessage + */ + var createTransferableMessage = function createTransferableMessage(message) { + var transferable = {}; + + Object.keys(message).forEach(function (key) { + var value = message[key]; + + if (ArrayBuffer.isView(value)) { + transferable[key] = { + bytes: value.buffer, + byteOffset: value.byteOffset, + byteLength: value.byteLength + }; + } else { + transferable[key] = value; + } + }); + + return transferable; + }; + + /** + * Returns a unique string identifier for a media initialization + * segment. + */ + var initSegmentId = function initSegmentId(initSegment) { + var byterange = initSegment.byterange || { + length: Infinity, + offset: 0 + }; + + return [byterange.length, byterange.offset, initSegment.resolvedUri].join(','); + }; + + /** + * utils to help dump binary data to the console + */ + var hexDump = function hexDump(data) { + var bytes = Array.prototype.slice.call(data); + var step = 16; + var result = ''; + var hex = void 0; + var ascii = void 0; + + for (var j = 0; j < bytes.length / step; j++) { + hex = bytes.slice(j * step, j * step + step).map(formatHexString).join(''); + ascii = bytes.slice(j * step, j * step + step).map(formatAsciiString).join(''); + result += hex + ' ' + ascii + '\n'; + } + + return result; + }; + + var tagDump = function tagDump(_ref2) { + var bytes = _ref2.bytes; + return hexDump(bytes); + }; + + var textRanges = function textRanges(ranges) { + var result = ''; + var i = void 0; + + for (i = 0; i < ranges.length; i++) { + result += textRange(ranges, i) + ' '; + } + return result; + }; + + var utils = /*#__PURE__*/Object.freeze({ + createTransferableMessage: createTransferableMessage, + initSegmentId: initSegmentId, + hexDump: hexDump, + tagDump: tagDump, + textRanges: textRanges + }); + + /** + * ranges + * + * Utilities for working with TimeRanges. + * + */ + + // Fudge factor to account for TimeRanges rounding + var TIME_FUDGE_FACTOR = 1 / 30; + // Comparisons between time values such as current time and the end of the buffered range + // can be misleading because of precision differences or when the current media has poorly + // aligned audio and video, which can cause values to be slightly off from what you would + // expect. This value is what we consider to be safe to use in such comparisons to account + // for these scenarios. + var SAFE_TIME_DELTA = TIME_FUDGE_FACTOR * 3; + var filterRanges = function filterRanges(timeRanges, predicate) { + var results = []; + var i = void 0; + + if (timeRanges && timeRanges.length) { + // Search for ranges that match the predicate + for (i = 0; i < timeRanges.length; i++) { + if (predicate(timeRanges.start(i), timeRanges.end(i))) { + results.push([timeRanges.start(i), timeRanges.end(i)]); + } + } + } + + return videojs$1.createTimeRanges(results); + }; + + /** + * Attempts to find the buffered TimeRange that contains the specified + * time. + * @param {TimeRanges} buffered - the TimeRanges object to query + * @param {number} time - the time to filter on. + * @returns {TimeRanges} a new TimeRanges object + */ + var findRange = function findRange(buffered, time) { + return filterRanges(buffered, function (start, end) { + return start - TIME_FUDGE_FACTOR <= time && end + TIME_FUDGE_FACTOR >= time; + }); + }; + + /** + * Returns the TimeRanges that begin later than the specified time. + * @param {TimeRanges} timeRanges - the TimeRanges object to query + * @param {number} time - the time to filter on. + * @returns {TimeRanges} a new TimeRanges object. + */ + var findNextRange = function findNextRange(timeRanges, time) { + return filterRanges(timeRanges, function (start) { + return start - TIME_FUDGE_FACTOR >= time; + }); + }; + + /** + * Returns gaps within a list of TimeRanges + * @param {TimeRanges} buffered - the TimeRanges object + * @return {TimeRanges} a TimeRanges object of gaps + */ + var findGaps = function findGaps(buffered) { + if (buffered.length < 2) { + return videojs$1.createTimeRanges(); + } + + var ranges = []; + + for (var i = 1; i < buffered.length; i++) { + var start = buffered.end(i - 1); + var end = buffered.start(i); + + ranges.push([start, end]); + } + + return videojs$1.createTimeRanges(ranges); + }; + + /** + * Gets a human readable string for a TimeRange + * + * @param {TimeRange} range + * @returns {String} a human readable string + */ + var printableRange = function printableRange(range) { + var strArr = []; + + if (!range || !range.length) { + return ''; + } + + for (var i = 0; i < range.length; i++) { + strArr.push(range.start(i) + ' => ' + range.end(i)); + } + + return strArr.join(', '); + }; + + /** + * Calculates the amount of time left in seconds until the player hits the end of the + * buffer and causes a rebuffer + * + * @param {TimeRange} buffered + * The state of the buffer + * @param {Numnber} currentTime + * The current time of the player + * @param {Number} playbackRate + * The current playback rate of the player. Defaults to 1. + * @return {Number} + * Time until the player has to start rebuffering in seconds. + * @function timeUntilRebuffer + */ + var timeUntilRebuffer = function timeUntilRebuffer(buffered, currentTime) { + var playbackRate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + + var bufferedEnd = buffered.length ? buffered.end(buffered.length - 1) : 0; + + return (bufferedEnd - currentTime) / playbackRate; + }; + + /** + * Converts a TimeRanges object into an array representation + * @param {TimeRanges} timeRanges + * @returns {Array} + */ + var timeRangesToArray = function timeRangesToArray(timeRanges) { + var timeRangesList = []; + + for (var i = 0; i < timeRanges.length; i++) { + timeRangesList.push({ + start: timeRanges.start(i), + end: timeRanges.end(i) + }); + } + + return timeRangesList; + }; + + /** + * @file create-text-tracks-if-necessary.js + */ + + /** + * Create text tracks on video.js if they exist on a segment. + * + * @param {Object} sourceBuffer the VSB or FSB + * @param {Object} mediaSource the HTML media source + * @param {Object} segment the segment that may contain the text track + * @private + */ + var createTextTracksIfNecessary = function createTextTracksIfNecessary(sourceBuffer, mediaSource, segment) { + var player = mediaSource.player_; + + // create an in-band caption track if one is present in the segment + if (segment.captions && segment.captions.length) { + if (!sourceBuffer.inbandTextTracks_) { + sourceBuffer.inbandTextTracks_ = {}; + } + + for (var trackId in segment.captionStreams) { + if (!sourceBuffer.inbandTextTracks_[trackId]) { + player.tech_.trigger({type: 'usage', name: 'hls-608'}); + var track = player.textTracks().getTrackById(trackId); + + if (track) { + // Resuse an existing track with a CC# id because this was + // very likely created by videojs-contrib-hls from information + // in the m3u8 for us to use + sourceBuffer.inbandTextTracks_[trackId] = track; + } else { + // Otherwise, create a track with the default `CC#` label and + // without a language + sourceBuffer.inbandTextTracks_[trackId] = player.addRemoteTextTrack({ + kind: 'captions', + id: trackId, + label: trackId + }, false).track; + } + } + } + } + + if (segment.metadata && segment.metadata.length && !sourceBuffer.metadataTrack_) { + sourceBuffer.metadataTrack_ = player.addRemoteTextTrack({ + kind: 'metadata', + label: 'Timed Metadata' + }, false).track; + sourceBuffer.metadataTrack_.inBandMetadataTrackDispatchType = segment.metadata.dispatchType; + } + }; + + /** + * @file remove-cues-from-track.js + */ + + /** + * Remove cues from a track on video.js. + * + * @param {Double} start start of where we should remove the cue + * @param {Double} end end of where the we should remove the cue + * @param {Object} track the text track to remove the cues from + * @private + */ + var removeCuesFromTrack = function removeCuesFromTrack(start, end, track) { + var i = void 0; + var cue = void 0; + + if (!track) { + return; + } + + if (!track.cues) { + return; + } + + i = track.cues.length; + + while (i--) { + cue = track.cues[i]; + + // Remove any overlapping cue + if (cue.startTime <= end && cue.endTime >= start) { + track.removeCue(cue); + } + } + }; + + /** + * @file add-text-track-data.js + */ + /** + * Define properties on a cue for backwards compatability, + * but warn the user that the way that they are using it + * is depricated and will be removed at a later date. + * + * @param {Cue} cue the cue to add the properties on + * @private + */ + var deprecateOldCue = function deprecateOldCue(cue) { + Object.defineProperties(cue.frame, { + id: { + get: function get$$1() { + videojs$1.log.warn('cue.frame.id is deprecated. Use cue.value.key instead.'); + return cue.value.key; + } + }, + value: { + get: function get$$1() { + videojs$1.log.warn('cue.frame.value is deprecated. Use cue.value.data instead.'); + return cue.value.data; + } + }, + privateData: { + get: function get$$1() { + videojs$1.log.warn('cue.frame.privateData is deprecated. Use cue.value.data instead.'); + return cue.value.data; + } + } + }); + }; + + var durationOfVideo = function durationOfVideo(duration) { + var dur = void 0; + + if (isNaN(duration) || Math.abs(duration) === Infinity) { + dur = Number.MAX_VALUE; + } else { + dur = duration; + } + return dur; + }; + /** + * Add text track data to a source handler given the captions and + * metadata from the buffer. + * + * @param {Object} sourceHandler the virtual source buffer + * @param {Array} captionArray an array of caption data + * @param {Array} metadataArray an array of meta data + * @private + */ + var addTextTrackData = function addTextTrackData(sourceHandler, captionArray, metadataArray) { + var Cue = window_1.WebKitDataCue || window_1.VTTCue; + + if (captionArray) { + captionArray.forEach(function (caption) { + var track = caption.stream; + + this.inbandTextTracks_[track].addCue(new Cue(caption.startTime + this.timestampOffset, caption.endTime + this.timestampOffset, caption.text)); + }, sourceHandler); + } + + if (metadataArray) { + var videoDuration = durationOfVideo(sourceHandler.mediaSource_.duration); + + metadataArray.forEach(function (metadata) { + var time = metadata.cueTime + this.timestampOffset; + + metadata.frames.forEach(function (frame) { + var cue = new Cue(time, time, frame.value || frame.url || frame.data || ''); + + cue.frame = frame; + cue.value = frame; + deprecateOldCue(cue); + + this.metadataTrack_.addCue(cue); + }, this); + }, sourceHandler); + + // Updating the metadeta cues so that + // the endTime of each cue is the startTime of the next cue + // the endTime of last cue is the duration of the video + if (sourceHandler.metadataTrack_ && sourceHandler.metadataTrack_.cues && sourceHandler.metadataTrack_.cues.length) { + var cues = sourceHandler.metadataTrack_.cues; + var cuesArray = []; + + // Create a copy of the TextTrackCueList... + // ...disregarding cues with a falsey value + for (var i = 0; i < cues.length; i++) { + if (cues[i]) { + cuesArray.push(cues[i]); + } + } + + // Group cues by their startTime value + var cuesGroupedByStartTime = cuesArray.reduce(function (obj, cue) { + var timeSlot = obj[cue.startTime] || []; + + timeSlot.push(cue); + obj[cue.startTime] = timeSlot; + + return obj; + }, {}); + + // Sort startTimes by ascending order + var sortedStartTimes = Object.keys(cuesGroupedByStartTime).sort(function (a, b) { + return Number(a) - Number(b); + }); + + // Map each cue group's endTime to the next group's startTime + sortedStartTimes.forEach(function (startTime, idx) { + var cueGroup = cuesGroupedByStartTime[startTime]; + var nextTime = Number(sortedStartTimes[idx + 1]) || videoDuration; + + // Map each cue's endTime the next group's startTime + cueGroup.forEach(function (cue) { + cue.endTime = nextTime; + }); + }); + } + } + }; + + var win$1 = typeof window !== 'undefined' ? window : {}, + TARGET = typeof Symbol === 'undefined' ? '__target' : Symbol(), + SCRIPT_TYPE = 'application/javascript', + BlobBuilder = win$1.BlobBuilder || win$1.WebKitBlobBuilder || win$1.MozBlobBuilder || win$1.MSBlobBuilder, + URL = win$1.URL || win$1.webkitURL || URL && URL.msURL, + Worker = win$1.Worker; + + /** + * Returns a wrapper around Web Worker code that is constructible. + * + * @function shimWorker + * + * @param { String } filename The name of the file + * @param { Function } fn Function wrapping the code of the worker + */ + function shimWorker(filename, fn) { + return function ShimWorker(forceFallback) { + var o = this; + + if (!fn) { + return new Worker(filename); + } else if (Worker && !forceFallback) { + // Convert the function's inner code to a string to construct the worker + var source = fn.toString().replace(/^function.+?{/, '').slice(0, -1), + objURL = createSourceObject(source); + + this[TARGET] = new Worker(objURL); + wrapTerminate(this[TARGET], objURL); + return this[TARGET]; + } else { + var selfShim = { + postMessage: function postMessage(m) { + if (o.onmessage) { + setTimeout(function () { + o.onmessage({data: m, target: selfShim}); + }); + } + } + }; + + fn.call(selfShim); + this.postMessage = function (m) { + setTimeout(function () { + selfShim.onmessage({data: m, target: o}); + }); + }; + this.isThisThread = true; + } + }; + } + + // Test Worker capabilities + if (Worker) { + var testWorker, + objURL = createSourceObject('self.onmessage = function () {}'), + testArray = new Uint8Array(1); + + try { + testWorker = new Worker(objURL); + + // Native browser on some Samsung devices throws for transferables, let's detect it + testWorker.postMessage(testArray, [testArray.buffer]); + } catch (e) { + Worker = null; + } finally { + URL.revokeObjectURL(objURL); + if (testWorker) { + testWorker.terminate(); + } + } + } + + function createSourceObject(str) { + try { + return URL.createObjectURL(new Blob([str], {type: SCRIPT_TYPE})); + } catch (e) { + var blob = new BlobBuilder(); + blob.append(str); + return URL.createObjectURL(blob.getBlob(type)); + } + } + + function wrapTerminate(worker, objURL) { + if (!worker || !objURL) return; + var term = worker.terminate; + worker.objURL = objURL; + worker.terminate = function () { + if (worker.objURL) URL.revokeObjectURL(worker.objURL); + term.call(worker); + }; + } + + var TransmuxWorker = new shimWorker("./transmuxer-worker.worker.js", function (window, document$$1) { + var self = this; + var transmuxerWorker = function () { + + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + var win; + + if (typeof window !== "undefined") { + win = window; + } else if (typeof commonjsGlobal !== "undefined") { + win = commonjsGlobal; + } else if (typeof self !== "undefined") { + win = self; + } else { + win = {}; + } + + var window_1$$1 = win; + + /** + * mux.js + * + * Copyright (c) 2015 Brightcove + * All rights reserved. + * + * Functions that generate fragmented MP4s suitable for use with Media + * Source Extensions. + */ + + var UINT32_MAX = Math.pow(2, 32) - 1; + + var box, dinf, esds, ftyp, mdat, mfhd, minf, moof, moov, mvex, mvhd, trak, tkhd, mdia, mdhd, hdlr, sdtp, stbl, + stsd, traf, trex, trun, types, MAJOR_BRAND, MINOR_VERSION, AVC1_BRAND, VIDEO_HDLR, AUDIO_HDLR, HDLR_TYPES, VMHD, + SMHD, DREF, STCO, STSC, STSZ, STTS; + + // pre-calculate constants + (function () { + var i; + types = { + avc1: [], // codingname + avcC: [], + btrt: [], + dinf: [], + dref: [], + esds: [], + ftyp: [], + hdlr: [], + mdat: [], + mdhd: [], + mdia: [], + mfhd: [], + minf: [], + moof: [], + moov: [], + mp4a: [], // codingname + mvex: [], + mvhd: [], + sdtp: [], + smhd: [], + stbl: [], + stco: [], + stsc: [], + stsd: [], + stsz: [], + stts: [], + styp: [], + tfdt: [], + tfhd: [], + traf: [], + trak: [], + trun: [], + trex: [], + tkhd: [], + vmhd: [] + }; + + // In environments where Uint8Array is undefined (e.g., IE8), skip set up so that we + // don't throw an error + if (typeof Uint8Array === 'undefined') { + return; + } + + for (i in types) { + if (types.hasOwnProperty(i)) { + types[i] = [i.charCodeAt(0), i.charCodeAt(1), i.charCodeAt(2), i.charCodeAt(3)]; + } + } + + MAJOR_BRAND = new Uint8Array(['i'.charCodeAt(0), 's'.charCodeAt(0), 'o'.charCodeAt(0), 'm'.charCodeAt(0)]); + AVC1_BRAND = new Uint8Array(['a'.charCodeAt(0), 'v'.charCodeAt(0), 'c'.charCodeAt(0), '1'.charCodeAt(0)]); + MINOR_VERSION = new Uint8Array([0, 0, 0, 1]); + VIDEO_HDLR = new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, 0x00, 0x00, // pre_defined + 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide' + 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x00, 0x00, 0x00, // reserved + 0x56, 0x69, 0x64, 0x65, 0x6f, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler' + ]); + AUDIO_HDLR = new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, 0x00, 0x00, // pre_defined + 0x73, 0x6f, 0x75, 0x6e, // handler_type: 'soun' + 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x00, 0x00, 0x00, // reserved + 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler' + ]); + HDLR_TYPES = { + video: VIDEO_HDLR, + audio: AUDIO_HDLR + }; + DREF = new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, 0x00, 0x01, // entry_count + 0x00, 0x00, 0x00, 0x0c, // entry_size + 0x75, 0x72, 0x6c, 0x20, // 'url' type + 0x00, // version 0 + 0x00, 0x00, 0x01 // entry_flags + ]); + SMHD = new Uint8Array([0x00, // version + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, // balance, 0 means centered + 0x00, 0x00 // reserved + ]); + STCO = new Uint8Array([0x00, // version + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, 0x00, 0x00 // entry_count + ]); + STSC = STCO; + STSZ = new Uint8Array([0x00, // version + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, 0x00, 0x00, // sample_size + 0x00, 0x00, 0x00, 0x00 // sample_count + ]); + STTS = STCO; + VMHD = new Uint8Array([0x00, // version + 0x00, 0x00, 0x01, // flags + 0x00, 0x00, // graphicsmode + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // opcolor + ]); + })(); + + box = function box(type) { + var payload = [], + size = 0, + i, + result, + view; + + for (i = 1; i < arguments.length; i++) { + payload.push(arguments[i]); + } + + i = payload.length; + + // calculate the total size we need to allocate + while (i--) { + size += payload[i].byteLength; + } + result = new Uint8Array(size + 8); + view = new DataView(result.buffer, result.byteOffset, result.byteLength); + view.setUint32(0, result.byteLength); + result.set(type, 4); + + // copy the payload into the result + for (i = 0, size = 8; i < payload.length; i++) { + result.set(payload[i], size); + size += payload[i].byteLength; + } + return result; + }; + + dinf = function dinf() { + return box(types.dinf, box(types.dref, DREF)); + }; + + esds = function esds(track) { + return box(types.esds, new Uint8Array([0x00, // version + 0x00, 0x00, 0x00, // flags + + // ES_Descriptor + 0x03, // tag, ES_DescrTag + 0x19, // length + 0x00, 0x00, // ES_ID + 0x00, // streamDependenceFlag, URL_flag, reserved, streamPriority + + // DecoderConfigDescriptor + 0x04, // tag, DecoderConfigDescrTag + 0x11, // length + 0x40, // object type + 0x15, // streamType + 0x00, 0x06, 0x00, // bufferSizeDB + 0x00, 0x00, 0xda, 0xc0, // maxBitrate + 0x00, 0x00, 0xda, 0xc0, // avgBitrate + + // DecoderSpecificInfo + 0x05, // tag, DecoderSpecificInfoTag + 0x02, // length + // ISO/IEC 14496-3, AudioSpecificConfig + // for samplingFrequencyIndex see ISO/IEC 13818-7:2006, 8.1.3.2.2, Table 35 + track.audioobjecttype << 3 | track.samplingfrequencyindex >>> 1, track.samplingfrequencyindex << 7 | track.channelcount << 3, 0x06, 0x01, 0x02 // GASpecificConfig + ])); + }; + + ftyp = function ftyp() { + return box(types.ftyp, MAJOR_BRAND, MINOR_VERSION, MAJOR_BRAND, AVC1_BRAND); + }; + + hdlr = function hdlr(type) { + return box(types.hdlr, HDLR_TYPES[type]); + }; + mdat = function mdat(data) { + return box(types.mdat, data); + }; + mdhd = function mdhd(track) { + var result = new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, 0x00, 0x02, // creation_time + 0x00, 0x00, 0x00, 0x03, // modification_time + 0x00, 0x01, 0x5f, 0x90, // timescale, 90,000 "ticks" per second + + track.duration >>> 24 & 0xFF, track.duration >>> 16 & 0xFF, track.duration >>> 8 & 0xFF, track.duration & 0xFF, // duration + 0x55, 0xc4, // 'und' language (undetermined) + 0x00, 0x00]); + + // Use the sample rate from the track metadata, when it is + // defined. The sample rate can be parsed out of an ADTS header, for + // instance. + if (track.samplerate) { + result[12] = track.samplerate >>> 24 & 0xFF; + result[13] = track.samplerate >>> 16 & 0xFF; + result[14] = track.samplerate >>> 8 & 0xFF; + result[15] = track.samplerate & 0xFF; + } + + return box(types.mdhd, result); + }; + mdia = function mdia(track) { + return box(types.mdia, mdhd(track), hdlr(track.type), minf(track)); + }; + mfhd = function mfhd(sequenceNumber) { + return box(types.mfhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // flags + (sequenceNumber & 0xFF000000) >> 24, (sequenceNumber & 0xFF0000) >> 16, (sequenceNumber & 0xFF00) >> 8, sequenceNumber & 0xFF // sequence_number + ])); + }; + minf = function minf(track) { + return box(types.minf, track.type === 'video' ? box(types.vmhd, VMHD) : box(types.smhd, SMHD), dinf(), stbl(track)); + }; + moof = function moof(sequenceNumber, tracks) { + var trackFragments = [], + i = tracks.length; + // build traf boxes for each track fragment + while (i--) { + trackFragments[i] = traf(tracks[i]); + } + return box.apply(null, [types.moof, mfhd(sequenceNumber)].concat(trackFragments)); + }; + /** + * Returns a movie box. + * @param tracks {array} the tracks associated with this movie + * @see ISO/IEC 14496-12:2012(E), section 8.2.1 + */ + moov = function moov(tracks) { + var i = tracks.length, + boxes = []; + + while (i--) { + boxes[i] = trak(tracks[i]); + } + + return box.apply(null, [types.moov, mvhd(0xffffffff)].concat(boxes).concat(mvex(tracks))); + }; + mvex = function mvex(tracks) { + var i = tracks.length, + boxes = []; + + while (i--) { + boxes[i] = trex(tracks[i]); + } + return box.apply(null, [types.mvex].concat(boxes)); + }; + mvhd = function mvhd(duration) { + var bytes = new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, 0x00, 0x01, // creation_time + 0x00, 0x00, 0x00, 0x02, // modification_time + 0x00, 0x01, 0x5f, 0x90, // timescale, 90,000 "ticks" per second + (duration & 0xFF000000) >> 24, (duration & 0xFF0000) >> 16, (duration & 0xFF00) >> 8, duration & 0xFF, // duration + 0x00, 0x01, 0x00, 0x00, // 1.0 rate + 0x01, 0x00, // 1.0 volume + 0x00, 0x00, // reserved + 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined + 0xff, 0xff, 0xff, 0xff // next_track_ID + ]); + return box(types.mvhd, bytes); + }; + + sdtp = function sdtp(track) { + var samples = track.samples || [], + bytes = new Uint8Array(4 + samples.length), + flags, + i; + + // leave the full box header (4 bytes) all zero + + // write the sample table + for (i = 0; i < samples.length; i++) { + flags = samples[i].flags; + + bytes[i + 4] = flags.dependsOn << 4 | flags.isDependedOn << 2 | flags.hasRedundancy; + } + + return box(types.sdtp, bytes); + }; + + stbl = function stbl(track) { + return box(types.stbl, stsd(track), box(types.stts, STTS), box(types.stsc, STSC), box(types.stsz, STSZ), box(types.stco, STCO)); + }; + + (function () { + var videoSample, audioSample; + + stsd = function stsd(track) { + + return box(types.stsd, new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x00, // flags + 0x00, 0x00, 0x00, 0x01]), track.type === 'video' ? videoSample(track) : audioSample(track)); + }; + + videoSample = function videoSample(track) { + var sps = track.sps || [], + pps = track.pps || [], + sequenceParameterSets = [], + pictureParameterSets = [], + i; + + // assemble the SPSs + for (i = 0; i < sps.length; i++) { + sequenceParameterSets.push((sps[i].byteLength & 0xFF00) >>> 8); + sequenceParameterSets.push(sps[i].byteLength & 0xFF); // sequenceParameterSetLength + sequenceParameterSets = sequenceParameterSets.concat(Array.prototype.slice.call(sps[i])); // SPS + } + + // assemble the PPSs + for (i = 0; i < pps.length; i++) { + pictureParameterSets.push((pps[i].byteLength & 0xFF00) >>> 8); + pictureParameterSets.push(pps[i].byteLength & 0xFF); + pictureParameterSets = pictureParameterSets.concat(Array.prototype.slice.call(pps[i])); + } + + return box(types.avc1, new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x01, // data_reference_index + 0x00, 0x00, // pre_defined + 0x00, 0x00, // reserved + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined + (track.width & 0xff00) >> 8, track.width & 0xff, // width + (track.height & 0xff00) >> 8, track.height & 0xff, // height + 0x00, 0x48, 0x00, 0x00, // horizresolution + 0x00, 0x48, 0x00, 0x00, // vertresolution + 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x01, // frame_count + 0x13, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6a, 0x73, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x2d, 0x68, 0x6c, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compressorname + 0x00, 0x18, // depth = 24 + 0x11, 0x11 // pre_defined = -1 + ]), box(types.avcC, new Uint8Array([0x01, // configurationVersion + track.profileIdc, // AVCProfileIndication + track.profileCompatibility, // profile_compatibility + track.levelIdc, // AVCLevelIndication + 0xff // lengthSizeMinusOne, hard-coded to 4 bytes + ].concat([sps.length // numOfSequenceParameterSets + ]).concat(sequenceParameterSets).concat([pps.length // numOfPictureParameterSets + ]).concat(pictureParameterSets))), // "PPS" + box(types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80, // bufferSizeDB + 0x00, 0x2d, 0xc6, 0xc0, // maxBitrate + 0x00, 0x2d, 0xc6, 0xc0])) // avgBitrate + ); + }; + + audioSample = function audioSample(track) { + return box(types.mp4a, new Uint8Array([ + + // SampleEntry, ISO/IEC 14496-12 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x01, // data_reference_index + + // AudioSampleEntry, ISO/IEC 14496-12 + 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x00, 0x00, 0x00, // reserved + (track.channelcount & 0xff00) >> 8, track.channelcount & 0xff, // channelcount + + (track.samplesize & 0xff00) >> 8, track.samplesize & 0xff, // samplesize + 0x00, 0x00, // pre_defined + 0x00, 0x00, // reserved + + (track.samplerate & 0xff00) >> 8, track.samplerate & 0xff, 0x00, 0x00 // samplerate, 16.16 + + // MP4AudioSampleEntry, ISO/IEC 14496-14 + ]), esds(track)); + }; + })(); + + tkhd = function tkhd(track) { + var result = new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x07, // flags + 0x00, 0x00, 0x00, 0x00, // creation_time + 0x00, 0x00, 0x00, 0x00, // modification_time + (track.id & 0xFF000000) >> 24, (track.id & 0xFF0000) >> 16, (track.id & 0xFF00) >> 8, track.id & 0xFF, // track_ID + 0x00, 0x00, 0x00, 0x00, // reserved + (track.duration & 0xFF000000) >> 24, (track.duration & 0xFF0000) >> 16, (track.duration & 0xFF00) >> 8, track.duration & 0xFF, // duration + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved + 0x00, 0x00, // layer + 0x00, 0x00, // alternate_group + 0x01, 0x00, // non-audio track volume + 0x00, 0x00, // reserved + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix + (track.width & 0xFF00) >> 8, track.width & 0xFF, 0x00, 0x00, // width + (track.height & 0xFF00) >> 8, track.height & 0xFF, 0x00, 0x00 // height + ]); + + return box(types.tkhd, result); + }; + + /** + * Generate a track fragment (traf) box. A traf box collects metadata + * about tracks in a movie fragment (moof) box. + */ + traf = function traf(track) { + var trackFragmentHeader, trackFragmentDecodeTime, trackFragmentRun, sampleDependencyTable, dataOffset, + upperWordBaseMediaDecodeTime, lowerWordBaseMediaDecodeTime; + + trackFragmentHeader = box(types.tfhd, new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x3a, // flags + (track.id & 0xFF000000) >> 24, (track.id & 0xFF0000) >> 16, (track.id & 0xFF00) >> 8, track.id & 0xFF, // track_ID + 0x00, 0x00, 0x00, 0x01, // sample_description_index + 0x00, 0x00, 0x00, 0x00, // default_sample_duration + 0x00, 0x00, 0x00, 0x00, // default_sample_size + 0x00, 0x00, 0x00, 0x00 // default_sample_flags + ])); + + upperWordBaseMediaDecodeTime = Math.floor(track.baseMediaDecodeTime / (UINT32_MAX + 1)); + lowerWordBaseMediaDecodeTime = Math.floor(track.baseMediaDecodeTime % (UINT32_MAX + 1)); + + trackFragmentDecodeTime = box(types.tfdt, new Uint8Array([0x01, // version 1 + 0x00, 0x00, 0x00, // flags + // baseMediaDecodeTime + upperWordBaseMediaDecodeTime >>> 24 & 0xFF, upperWordBaseMediaDecodeTime >>> 16 & 0xFF, upperWordBaseMediaDecodeTime >>> 8 & 0xFF, upperWordBaseMediaDecodeTime & 0xFF, lowerWordBaseMediaDecodeTime >>> 24 & 0xFF, lowerWordBaseMediaDecodeTime >>> 16 & 0xFF, lowerWordBaseMediaDecodeTime >>> 8 & 0xFF, lowerWordBaseMediaDecodeTime & 0xFF])); + + // the data offset specifies the number of bytes from the start of + // the containing moof to the first payload byte of the associated + // mdat + dataOffset = 32 + // tfhd + 20 + // tfdt + 8 + // traf header + 16 + // mfhd + 8 + // moof header + 8; // mdat header + + // audio tracks require less metadata + if (track.type === 'audio') { + trackFragmentRun = trun(track, dataOffset); + return box(types.traf, trackFragmentHeader, trackFragmentDecodeTime, trackFragmentRun); + } + + // video tracks should contain an independent and disposable samples + // box (sdtp) + // generate one and adjust offsets to match + sampleDependencyTable = sdtp(track); + trackFragmentRun = trun(track, sampleDependencyTable.length + dataOffset); + return box(types.traf, trackFragmentHeader, trackFragmentDecodeTime, trackFragmentRun, sampleDependencyTable); + }; + + /** + * Generate a track box. + * @param track {object} a track definition + * @return {Uint8Array} the track box + */ + trak = function trak(track) { + track.duration = track.duration || 0xffffffff; + return box(types.trak, tkhd(track), mdia(track)); + }; + + trex = function trex(track) { + var result = new Uint8Array([0x00, // version 0 + 0x00, 0x00, 0x00, // flags + (track.id & 0xFF000000) >> 24, (track.id & 0xFF0000) >> 16, (track.id & 0xFF00) >> 8, track.id & 0xFF, // track_ID + 0x00, 0x00, 0x00, 0x01, // default_sample_description_index + 0x00, 0x00, 0x00, 0x00, // default_sample_duration + 0x00, 0x00, 0x00, 0x00, // default_sample_size + 0x00, 0x01, 0x00, 0x01 // default_sample_flags + ]); + // the last two bytes of default_sample_flags is the sample + // degradation priority, a hint about the importance of this sample + // relative to others. Lower the degradation priority for all sample + // types other than video. + if (track.type !== 'video') { + result[result.length - 1] = 0x00; + } + + return box(types.trex, result); + }; + + (function () { + var audioTrun, videoTrun, trunHeader; + + // This method assumes all samples are uniform. That is, if a + // duration is present for the first sample, it will be present for + // all subsequent samples. + // see ISO/IEC 14496-12:2012, Section 8.8.8.1 + trunHeader = function trunHeader(samples, offset) { + var durationPresent = 0, + sizePresent = 0, + flagsPresent = 0, + compositionTimeOffset = 0; + + // trun flag constants + if (samples.length) { + if (samples[0].duration !== undefined) { + durationPresent = 0x1; + } + if (samples[0].size !== undefined) { + sizePresent = 0x2; + } + if (samples[0].flags !== undefined) { + flagsPresent = 0x4; + } + if (samples[0].compositionTimeOffset !== undefined) { + compositionTimeOffset = 0x8; + } + } + + return [0x00, // version 0 + 0x00, durationPresent | sizePresent | flagsPresent | compositionTimeOffset, 0x01, // flags + (samples.length & 0xFF000000) >>> 24, (samples.length & 0xFF0000) >>> 16, (samples.length & 0xFF00) >>> 8, samples.length & 0xFF, // sample_count + (offset & 0xFF000000) >>> 24, (offset & 0xFF0000) >>> 16, (offset & 0xFF00) >>> 8, offset & 0xFF // data_offset + ]; + }; + + videoTrun = function videoTrun(track, offset) { + var bytes, samples, sample, i; + + samples = track.samples || []; + offset += 8 + 12 + 16 * samples.length; + + bytes = trunHeader(samples, offset); + + for (i = 0; i < samples.length; i++) { + sample = samples[i]; + bytes = bytes.concat([(sample.duration & 0xFF000000) >>> 24, (sample.duration & 0xFF0000) >>> 16, (sample.duration & 0xFF00) >>> 8, sample.duration & 0xFF, // sample_duration + (sample.size & 0xFF000000) >>> 24, (sample.size & 0xFF0000) >>> 16, (sample.size & 0xFF00) >>> 8, sample.size & 0xFF, // sample_size + sample.flags.isLeading << 2 | sample.flags.dependsOn, sample.flags.isDependedOn << 6 | sample.flags.hasRedundancy << 4 | sample.flags.paddingValue << 1 | sample.flags.isNonSyncSample, sample.flags.degradationPriority & 0xF0 << 8, sample.flags.degradationPriority & 0x0F, // sample_flags + (sample.compositionTimeOffset & 0xFF000000) >>> 24, (sample.compositionTimeOffset & 0xFF0000) >>> 16, (sample.compositionTimeOffset & 0xFF00) >>> 8, sample.compositionTimeOffset & 0xFF // sample_composition_time_offset + ]); + } + return box(types.trun, new Uint8Array(bytes)); + }; + + audioTrun = function audioTrun(track, offset) { + var bytes, samples, sample, i; + + samples = track.samples || []; + offset += 8 + 12 + 8 * samples.length; + + bytes = trunHeader(samples, offset); + + for (i = 0; i < samples.length; i++) { + sample = samples[i]; + bytes = bytes.concat([(sample.duration & 0xFF000000) >>> 24, (sample.duration & 0xFF0000) >>> 16, (sample.duration & 0xFF00) >>> 8, sample.duration & 0xFF, // sample_duration + (sample.size & 0xFF000000) >>> 24, (sample.size & 0xFF0000) >>> 16, (sample.size & 0xFF00) >>> 8, sample.size & 0xFF]); // sample_size + } + + return box(types.trun, new Uint8Array(bytes)); + }; + + trun = function trun(track, offset) { + if (track.type === 'audio') { + return audioTrun(track, offset); + } + + return videoTrun(track, offset); + }; + })(); + + var mp4Generator = { + ftyp: ftyp, + mdat: mdat, + moof: moof, + moov: moov, + initSegment: function initSegment(tracks) { + var fileType = ftyp(), + movie = moov(tracks), + result; + + result = new Uint8Array(fileType.byteLength + movie.byteLength); + result.set(fileType); + result.set(movie, fileType.byteLength); + return result; + } + }; + + /** + * mux.js + * + * Copyright (c) 2014 Brightcove + * All rights reserved. + * + * A lightweight readable stream implemention that handles event dispatching. + * Objects that inherit from streams should call init in their constructors. + */ + + var Stream = function Stream() { + this.init = function () { + var listeners = {}; + /** + * Add a listener for a specified event type. + * @param type {string} the event name + * @param listener {function} the callback to be invoked when an event of + * the specified type occurs + */ + this.on = function (type, listener) { + if (!listeners[type]) { + listeners[type] = []; + } + listeners[type] = listeners[type].concat(listener); + }; + /** + * Remove a listener for a specified event type. + * @param type {string} the event name + * @param listener {function} a function previously registered for this + * type of event through `on` + */ + this.off = function (type, listener) { + var index; + if (!listeners[type]) { + return false; + } + index = listeners[type].indexOf(listener); + listeners[type] = listeners[type].slice(); + listeners[type].splice(index, 1); + return index > -1; + }; + /** + * Trigger an event of the specified type on this stream. Any additional + * arguments to this function are passed as parameters to event listeners. + * @param type {string} the event name + */ + this.trigger = function (type) { + var callbacks, i, length, args; + callbacks = listeners[type]; + if (!callbacks) { + return; + } + // Slicing the arguments on every invocation of this method + // can add a significant amount of overhead. Avoid the + // intermediate object creation for the common case of a + // single callback argument + if (arguments.length === 2) { + length = callbacks.length; + for (i = 0; i < length; ++i) { + callbacks[i].call(this, arguments[1]); + } + } else { + args = []; + i = arguments.length; + for (i = 1; i < arguments.length; ++i) { + args.push(arguments[i]); + } + length = callbacks.length; + for (i = 0; i < length; ++i) { + callbacks[i].apply(this, args); + } + } + }; + /** + * Destroys the stream and cleans up. + */ + this.dispose = function () { + listeners = {}; + }; + }; + }; + + /** + * Forwards all `data` events on this stream to the destination stream. The + * destination stream should provide a method `push` to receive the data + * events as they arrive. + * @param destination {stream} the stream that will receive all `data` events + * @param autoFlush {boolean} if false, we will not call `flush` on the destination + * when the current stream emits a 'done' event + * @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options + */ + Stream.prototype.pipe = function (destination) { + this.on('data', function (data) { + destination.push(data); + }); + + this.on('done', function (flushSource) { + destination.flush(flushSource); + }); + + return destination; + }; + + // Default stream functions that are expected to be overridden to perform + // actual work. These are provided by the prototype as a sort of no-op + // implementation so that we don't have to check for their existence in the + // `pipe` function above. + Stream.prototype.push = function (data) { + this.trigger('data', data); + }; + + Stream.prototype.flush = function (flushSource) { + this.trigger('done', flushSource); + }; + + var stream = Stream; + + // ----------------- + // Link To Transport + // ----------------- + + // Supplemental enhancement information (SEI) NAL units have a + // payload type field to indicate how they are to be + // interpreted. CEAS-708 caption content is always transmitted with + // payload type 0x04. + var USER_DATA_REGISTERED_ITU_T_T35 = 4, + RBSP_TRAILING_BITS = 128; + + /** + * Parse a supplemental enhancement information (SEI) NAL unit. + * Stops parsing once a message of type ITU T T35 has been found. + * + * @param bytes {Uint8Array} the bytes of a SEI NAL unit + * @return {object} the parsed SEI payload + * @see Rec. ITU-T H.264, 7.3.2.3.1 + */ + var parseSei = function parseSei(bytes) { + var i = 0, + result = { + payloadType: -1, + payloadSize: 0 + }, + payloadType = 0, + payloadSize = 0; + + // go through the sei_rbsp parsing each each individual sei_message + while (i < bytes.byteLength) { + // stop once we have hit the end of the sei_rbsp + if (bytes[i] === RBSP_TRAILING_BITS) { + break; + } + + // Parse payload type + while (bytes[i] === 0xFF) { + payloadType += 255; + i++; + } + payloadType += bytes[i++]; + + // Parse payload size + while (bytes[i] === 0xFF) { + payloadSize += 255; + i++; + } + payloadSize += bytes[i++]; + + // this sei_message is a 608/708 caption so save it and break + // there can only ever be one caption message in a frame's sei + if (!result.payload && payloadType === USER_DATA_REGISTERED_ITU_T_T35) { + result.payloadType = payloadType; + result.payloadSize = payloadSize; + result.payload = bytes.subarray(i, i + payloadSize); + break; + } + + // skip the payload and parse the next message + i += payloadSize; + payloadType = 0; + payloadSize = 0; + } + + return result; + }; + + // see ANSI/SCTE 128-1 (2013), section 8.1 + var parseUserData = function parseUserData(sei) { + // itu_t_t35_contry_code must be 181 (United States) for + // captions + if (sei.payload[0] !== 181) { + return null; + } + + // itu_t_t35_provider_code should be 49 (ATSC) for captions + if ((sei.payload[1] << 8 | sei.payload[2]) !== 49) { + return null; + } + + // the user_identifier should be "GA94" to indicate ATSC1 data + if (String.fromCharCode(sei.payload[3], sei.payload[4], sei.payload[5], sei.payload[6]) !== 'GA94') { + return null; + } + + // finally, user_data_type_code should be 0x03 for caption data + if (sei.payload[7] !== 0x03) { + return null; + } + + // return the user_data_type_structure and strip the trailing + // marker bits + return sei.payload.subarray(8, sei.payload.length - 1); + }; + + // see CEA-708-D, section 4.4 + var parseCaptionPackets = function parseCaptionPackets(pts, userData) { + var results = [], + i, + count, + offset, + data; + + // if this is just filler, return immediately + if (!(userData[0] & 0x40)) { + return results; + } + + // parse out the cc_data_1 and cc_data_2 fields + count = userData[0] & 0x1f; + for (i = 0; i < count; i++) { + offset = i * 3; + data = { + type: userData[offset + 2] & 0x03, + pts: pts + }; + + // capture cc data when cc_valid is 1 + if (userData[offset + 2] & 0x04) { + data.ccData = userData[offset + 3] << 8 | userData[offset + 4]; + results.push(data); + } + } + return results; + }; + + var CaptionStream = function CaptionStream() { + + CaptionStream.prototype.init.call(this); + + this.captionPackets_ = []; + + this.ccStreams_ = [new Cea608Stream(0, 0), // eslint-disable-line no-use-before-define + new Cea608Stream(0, 1), // eslint-disable-line no-use-before-define + new Cea608Stream(1, 0), // eslint-disable-line no-use-before-define + new Cea608Stream(1, 1) // eslint-disable-line no-use-before-define + ]; + + this.reset(); + + // forward data and done events from CCs to this CaptionStream + this.ccStreams_.forEach(function (cc) { + cc.on('data', this.trigger.bind(this, 'data')); + cc.on('done', this.trigger.bind(this, 'done')); + }, this); + }; + + CaptionStream.prototype = new stream(); + CaptionStream.prototype.push = function (event) { + var sei, userData; + + // only examine SEI NALs + if (event.nalUnitType !== 'sei_rbsp') { + return; + } + + // parse the sei + sei = parseSei(event.escapedRBSP); + + // ignore everything but user_data_registered_itu_t_t35 + if (sei.payloadType !== USER_DATA_REGISTERED_ITU_T_T35) { + return; + } + + // parse out the user data payload + userData = parseUserData(sei); + + // ignore unrecognized userData + if (!userData) { + return; + } + + // Sometimes, the same segment # will be downloaded twice. To stop the + // caption data from being processed twice, we track the latest dts we've + // received and ignore everything with a dts before that. However, since + // data for a specific dts can be split across packets on either side of + // a segment boundary, we need to make sure we *don't* ignore the packets + // from the *next* segment that have dts === this.latestDts_. By constantly + // tracking the number of packets received with dts === this.latestDts_, we + // know how many should be ignored once we start receiving duplicates. + if (event.dts < this.latestDts_) { + // We've started getting older data, so set the flag. + this.ignoreNextEqualDts_ = true; + return; + } else if (event.dts === this.latestDts_ && this.ignoreNextEqualDts_) { + this.numSameDts_--; + if (!this.numSameDts_) { + // We've received the last duplicate packet, time to start processing again + this.ignoreNextEqualDts_ = false; + } + return; + } + + // parse out CC data packets and save them for later + this.captionPackets_ = this.captionPackets_.concat(parseCaptionPackets(event.pts, userData)); + if (this.latestDts_ !== event.dts) { + this.numSameDts_ = 0; + } + this.numSameDts_++; + this.latestDts_ = event.dts; + }; + + CaptionStream.prototype.flush = function () { + // make sure we actually parsed captions before proceeding + if (!this.captionPackets_.length) { + this.ccStreams_.forEach(function (cc) { + cc.flush(); + }, this); + return; + } + + // In Chrome, the Array#sort function is not stable so add a + // presortIndex that we can use to ensure we get a stable-sort + this.captionPackets_.forEach(function (elem, idx) { + elem.presortIndex = idx; + }); + + // sort caption byte-pairs based on their PTS values + this.captionPackets_.sort(function (a, b) { + if (a.pts === b.pts) { + return a.presortIndex - b.presortIndex; + } + return a.pts - b.pts; + }); + + this.captionPackets_.forEach(function (packet) { + if (packet.type < 2) { + // Dispatch packet to the right Cea608Stream + this.dispatchCea608Packet(packet); + } + // this is where an 'else' would go for a dispatching packets + // to a theoretical Cea708Stream that handles SERVICEn data + }, this); + + this.captionPackets_.length = 0; + this.ccStreams_.forEach(function (cc) { + cc.flush(); + }, this); + return; + }; + + CaptionStream.prototype.reset = function () { + this.latestDts_ = null; + this.ignoreNextEqualDts_ = false; + this.numSameDts_ = 0; + this.activeCea608Channel_ = [null, null]; + this.ccStreams_.forEach(function (ccStream) { + ccStream.reset(); + }); + }; + + CaptionStream.prototype.dispatchCea608Packet = function (packet) { + // NOTE: packet.type is the CEA608 field + if (this.setsChannel1Active(packet)) { + this.activeCea608Channel_[packet.type] = 0; + } else if (this.setsChannel2Active(packet)) { + this.activeCea608Channel_[packet.type] = 1; + } + if (this.activeCea608Channel_[packet.type] === null) { + // If we haven't received anything to set the active channel, discard the + // data; we don't want jumbled captions + return; + } + this.ccStreams_[(packet.type << 1) + this.activeCea608Channel_[packet.type]].push(packet); + }; + + CaptionStream.prototype.setsChannel1Active = function (packet) { + return (packet.ccData & 0x7800) === 0x1000; + }; + CaptionStream.prototype.setsChannel2Active = function (packet) { + return (packet.ccData & 0x7800) === 0x1800; + }; + + // ---------------------- + // Session to Application + // ---------------------- + + var CHARACTER_TRANSLATION = { + 0x2a: 0xe1, // á + 0x5c: 0xe9, // é + 0x5e: 0xed, // à + 0x5f: 0xf3, // ó + 0x60: 0xfa, // ú + 0x7b: 0xe7, // ç + 0x7c: 0xf7, // ÷ + 0x7d: 0xd1, // Ñ + 0x7e: 0xf1, // ñ + 0x7f: 0x2588, // █ + 0x0130: 0xae, // ® + 0x0131: 0xb0, // ° + 0x0132: 0xbd, // ½ + 0x0133: 0xbf, // ¿ + 0x0134: 0x2122, // ™ + 0x0135: 0xa2, // ¢ + 0x0136: 0xa3, // £ + 0x0137: 0x266a, // ♪ + 0x0138: 0xe0, // à + 0x0139: 0xa0, // + 0x013a: 0xe8, // è + 0x013b: 0xe2, // â + 0x013c: 0xea, // ê + 0x013d: 0xee, // î + 0x013e: 0xf4, // ô + 0x013f: 0xfb, // û + 0x0220: 0xc1, // à + 0x0221: 0xc9, // É + 0x0222: 0xd3, // Ó + 0x0223: 0xda, // Ú + 0x0224: 0xdc, // Ü + 0x0225: 0xfc, // ü + 0x0226: 0x2018, // ‘ + 0x0227: 0xa1, // ¡ + 0x0228: 0x2a, // * + 0x0229: 0x27, // ' + 0x022a: 0x2014, // — + 0x022b: 0xa9, // © + 0x022c: 0x2120, // ℠+ 0x022d: 0x2022, // • + 0x022e: 0x201c, // “ + 0x022f: 0x201d, // †+ 0x0230: 0xc0, // À + 0x0231: 0xc2, // Â + 0x0232: 0xc7, // Ç + 0x0233: 0xc8, // È + 0x0234: 0xca, // Ê + 0x0235: 0xcb, // Ë + 0x0236: 0xeb, // ë + 0x0237: 0xce, // Î + 0x0238: 0xcf, // à + 0x0239: 0xef, // ï + 0x023a: 0xd4, // Ô + 0x023b: 0xd9, // Ù + 0x023c: 0xf9, // ù + 0x023d: 0xdb, // Û + 0x023e: 0xab, // « + 0x023f: 0xbb, // » + 0x0320: 0xc3, // Ã + 0x0321: 0xe3, // ã + 0x0322: 0xcd, // à + 0x0323: 0xcc, // Ì + 0x0324: 0xec, // ì + 0x0325: 0xd2, // Ò + 0x0326: 0xf2, // ò + 0x0327: 0xd5, // Õ + 0x0328: 0xf5, // õ + 0x0329: 0x7b, // { + 0x032a: 0x7d, // } + 0x032b: 0x5c, // \ + 0x032c: 0x5e, // ^ + 0x032d: 0x5f, // _ + 0x032e: 0x7c, // | + 0x032f: 0x7e, // ~ + 0x0330: 0xc4, // Ä + 0x0331: 0xe4, // ä + 0x0332: 0xd6, // Ö + 0x0333: 0xf6, // ö + 0x0334: 0xdf, // ß + 0x0335: 0xa5, // ¥ + 0x0336: 0xa4, // ¤ + 0x0337: 0x2502, // │ + 0x0338: 0xc5, // Å + 0x0339: 0xe5, // å + 0x033a: 0xd8, // Ø + 0x033b: 0xf8, // ø + 0x033c: 0x250c, // ┌ + 0x033d: 0x2510, // ┠+ 0x033e: 0x2514, // └ + 0x033f: 0x2518 // ┘ + }; + + var getCharFromCode = function getCharFromCode(code) { + if (code === null) { + return ''; + } + code = CHARACTER_TRANSLATION[code] || code; + return String.fromCharCode(code); + }; + + // the index of the last row in a CEA-608 display buffer + var BOTTOM_ROW = 14; + + // This array is used for mapping PACs -> row #, since there's no way of + // getting it through bit logic. + var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620, 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420]; + + // CEA-608 captions are rendered onto a 34x15 matrix of character + // cells. The "bottom" row is the last element in the outer array. + var createDisplayBuffer = function createDisplayBuffer() { + var result = [], + i = BOTTOM_ROW + 1; + while (i--) { + result.push(''); + } + return result; + }; + + var Cea608Stream = function Cea608Stream(field, dataChannel) { + Cea608Stream.prototype.init.call(this); + + this.field_ = field || 0; + this.dataChannel_ = dataChannel || 0; + + this.name_ = 'CC' + ((this.field_ << 1 | this.dataChannel_) + 1); + + this.setConstants(); + this.reset(); + + this.push = function (packet) { + var data, swap, char0, char1, text; + // remove the parity bits + data = packet.ccData & 0x7f7f; + + // ignore duplicate control codes; the spec demands they're sent twice + if (data === this.lastControlCode_) { + this.lastControlCode_ = null; + return; + } + + // Store control codes + if ((data & 0xf000) === 0x1000) { + this.lastControlCode_ = data; + } else if (data !== this.PADDING_) { + this.lastControlCode_ = null; + } + + char0 = data >>> 8; + char1 = data & 0xff; + + if (data === this.PADDING_) { + return; + } else if (data === this.RESUME_CAPTION_LOADING_) { + this.mode_ = 'popOn'; + } else if (data === this.END_OF_CAPTION_) { + this.clearFormatting(packet.pts); + // if a caption was being displayed, it's gone now + this.flushDisplayed(packet.pts); + + // flip memory + swap = this.displayed_; + this.displayed_ = this.nonDisplayed_; + this.nonDisplayed_ = swap; + + // start measuring the time to display the caption + this.startPts_ = packet.pts; + } else if (data === this.ROLL_UP_2_ROWS_) { + this.topRow_ = BOTTOM_ROW - 1; + this.mode_ = 'rollUp'; + } else if (data === this.ROLL_UP_3_ROWS_) { + this.topRow_ = BOTTOM_ROW - 2; + this.mode_ = 'rollUp'; + } else if (data === this.ROLL_UP_4_ROWS_) { + this.topRow_ = BOTTOM_ROW - 3; + this.mode_ = 'rollUp'; + } else if (data === this.CARRIAGE_RETURN_) { + this.clearFormatting(packet.pts); + this.flushDisplayed(packet.pts); + this.shiftRowsUp_(); + this.startPts_ = packet.pts; + } else if (data === this.BACKSPACE_) { + if (this.mode_ === 'popOn') { + this.nonDisplayed_[BOTTOM_ROW] = this.nonDisplayed_[BOTTOM_ROW].slice(0, -1); + } else { + this.displayed_[BOTTOM_ROW] = this.displayed_[BOTTOM_ROW].slice(0, -1); + } + } else if (data === this.ERASE_DISPLAYED_MEMORY_) { + this.flushDisplayed(packet.pts); + this.displayed_ = createDisplayBuffer(); + } else if (data === this.ERASE_NON_DISPLAYED_MEMORY_) { + this.nonDisplayed_ = createDisplayBuffer(); + } else if (data === this.RESUME_DIRECT_CAPTIONING_) { + this.mode_ = 'paintOn'; + + // Append special characters to caption text + } else if (this.isSpecialCharacter(char0, char1)) { + // Bitmask char0 so that we can apply character transformations + // regardless of field and data channel. + // Then byte-shift to the left and OR with char1 so we can pass the + // entire character code to `getCharFromCode`. + char0 = (char0 & 0x03) << 8; + text = getCharFromCode(char0 | char1); + this[this.mode_](packet.pts, text); + this.column_++; + + // Append extended characters to caption text + } else if (this.isExtCharacter(char0, char1)) { + // Extended characters always follow their "non-extended" equivalents. + // IE if a "è" is desired, you'll always receive "eè"; non-compliant + // decoders are supposed to drop the "è", while compliant decoders + // backspace the "e" and insert "è". + + // Delete the previous character + if (this.mode_ === 'popOn') { + this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1); + } else { + this.displayed_[BOTTOM_ROW] = this.displayed_[BOTTOM_ROW].slice(0, -1); + } + + // Bitmask char0 so that we can apply character transformations + // regardless of field and data channel. + // Then byte-shift to the left and OR with char1 so we can pass the + // entire character code to `getCharFromCode`. + char0 = (char0 & 0x03) << 8; + text = getCharFromCode(char0 | char1); + this[this.mode_](packet.pts, text); + this.column_++; + + // Process mid-row codes + } else if (this.isMidRowCode(char0, char1)) { + // Attributes are not additive, so clear all formatting + this.clearFormatting(packet.pts); + + // According to the standard, mid-row codes + // should be replaced with spaces, so add one now + this[this.mode_](packet.pts, ' '); + this.column_++; + + if ((char1 & 0xe) === 0xe) { + this.addFormatting(packet.pts, ['i']); + } + + if ((char1 & 0x1) === 0x1) { + this.addFormatting(packet.pts, ['u']); + } + + // Detect offset control codes and adjust cursor + } else if (this.isOffsetControlCode(char0, char1)) { + // Cursor position is set by indent PAC (see below) in 4-column + // increments, with an additional offset code of 1-3 to reach any + // of the 32 columns specified by CEA-608. So all we need to do + // here is increment the column cursor by the given offset. + this.column_ += char1 & 0x03; + + // Detect PACs (Preamble Address Codes) + } else if (this.isPAC(char0, char1)) { + + // There's no logic for PAC -> row mapping, so we have to just + // find the row code in an array and use its index :( + var row = ROWS.indexOf(data & 0x1f20); + + if (row !== this.row_) { + // formatting is only persistent for current row + this.clearFormatting(packet.pts); + this.row_ = row; + } + // All PACs can apply underline, so detect and apply + // (All odd-numbered second bytes set underline) + if (char1 & 0x1 && this.formatting_.indexOf('u') === -1) { + this.addFormatting(packet.pts, ['u']); + } + + if ((data & 0x10) === 0x10) { + // We've got an indent level code. Each successive even number + // increments the column cursor by 4, so we can get the desired + // column position by bit-shifting to the right (to get n/2) + // and multiplying by 4. + this.column_ = ((data & 0xe) >> 1) * 4; + } + + if (this.isColorPAC(char1)) { + // it's a color code, though we only support white, which + // can be either normal or italicized. white italics can be + // either 0x4e or 0x6e depending on the row, so we just + // bitwise-and with 0xe to see if italics should be turned on + if ((char1 & 0xe) === 0xe) { + this.addFormatting(packet.pts, ['i']); + } + } + + // We have a normal character in char0, and possibly one in char1 + } else if (this.isNormalChar(char0)) { + if (char1 === 0x00) { + char1 = null; + } + text = getCharFromCode(char0); + text += getCharFromCode(char1); + this[this.mode_](packet.pts, text); + this.column_ += text.length; + } // finish data processing + }; + }; + Cea608Stream.prototype = new stream(); + // Trigger a cue point that captures the current state of the + // display buffer + Cea608Stream.prototype.flushDisplayed = function (pts) { + var content = this.displayed_ + // remove spaces from the start and end of the string + .map(function (row) { + return row.trim(); + }) + // combine all text rows to display in one cue + .join('\n') + // and remove blank rows from the start and end, but not the middle + .replace(/^\n+|\n+$/g, ''); + + if (content.length) { + this.trigger('data', { + startPts: this.startPts_, + endPts: pts, + text: content, + stream: this.name_ + }); + } + }; + + /** + * Zero out the data, used for startup and on seek + */ + Cea608Stream.prototype.reset = function () { + this.mode_ = 'popOn'; + // When in roll-up mode, the index of the last row that will + // actually display captions. If a caption is shifted to a row + // with a lower index than this, it is cleared from the display + // buffer + this.topRow_ = 0; + this.startPts_ = 0; + this.displayed_ = createDisplayBuffer(); + this.nonDisplayed_ = createDisplayBuffer(); + this.lastControlCode_ = null; + + // Track row and column for proper line-breaking and spacing + this.column_ = 0; + this.row_ = BOTTOM_ROW; + + // This variable holds currently-applied formatting + this.formatting_ = []; + }; + + /** + * Sets up control code and related constants for this instance + */ + Cea608Stream.prototype.setConstants = function () { + // The following attributes have these uses: + // ext_ : char0 for mid-row codes, and the base for extended + // chars (ext_+0, ext_+1, and ext_+2 are char0s for + // extended codes) + // control_: char0 for control codes, except byte-shifted to the + // left so that we can do this.control_ | CONTROL_CODE + // offset_: char0 for tab offset codes + // + // It's also worth noting that control codes, and _only_ control codes, + // differ between field 1 and field2. Field 2 control codes are always + // their field 1 value plus 1. That's why there's the "| field" on the + // control value. + if (this.dataChannel_ === 0) { + this.BASE_ = 0x10; + this.EXT_ = 0x11; + this.CONTROL_ = (0x14 | this.field_) << 8; + this.OFFSET_ = 0x17; + } else if (this.dataChannel_ === 1) { + this.BASE_ = 0x18; + this.EXT_ = 0x19; + this.CONTROL_ = (0x1c | this.field_) << 8; + this.OFFSET_ = 0x1f; + } + + // Constants for the LSByte command codes recognized by Cea608Stream. This + // list is not exhaustive. For a more comprehensive listing and semantics see + // http://www.gpo.gov/fdsys/pkg/CFR-2010-title47-vol1/pdf/CFR-2010-title47-vol1-sec15-119.pdf + // Padding + this.PADDING_ = 0x0000; + // Pop-on Mode + this.RESUME_CAPTION_LOADING_ = this.CONTROL_ | 0x20; + this.END_OF_CAPTION_ = this.CONTROL_ | 0x2f; + // Roll-up Mode + this.ROLL_UP_2_ROWS_ = this.CONTROL_ | 0x25; + this.ROLL_UP_3_ROWS_ = this.CONTROL_ | 0x26; + this.ROLL_UP_4_ROWS_ = this.CONTROL_ | 0x27; + this.CARRIAGE_RETURN_ = this.CONTROL_ | 0x2d; + // paint-on mode (not supported) + this.RESUME_DIRECT_CAPTIONING_ = this.CONTROL_ | 0x29; + // Erasure + this.BACKSPACE_ = this.CONTROL_ | 0x21; + this.ERASE_DISPLAYED_MEMORY_ = this.CONTROL_ | 0x2c; + this.ERASE_NON_DISPLAYED_MEMORY_ = this.CONTROL_ | 0x2e; + }; + + /** + * Detects if the 2-byte packet data is a special character + * + * Special characters have a second byte in the range 0x30 to 0x3f, + * with the first byte being 0x11 (for data channel 1) or 0x19 (for + * data channel 2). + * + * @param {Integer} char0 The first byte + * @param {Integer} char1 The second byte + * @return {Boolean} Whether the 2 bytes are an special character + */ + Cea608Stream.prototype.isSpecialCharacter = function (char0, char1) { + return char0 === this.EXT_ && char1 >= 0x30 && char1 <= 0x3f; + }; + + /** + * Detects if the 2-byte packet data is an extended character + * + * Extended characters have a second byte in the range 0x20 to 0x3f, + * with the first byte being 0x12 or 0x13 (for data channel 1) or + * 0x1a or 0x1b (for data channel 2). + * + * @param {Integer} char0 The first byte + * @param {Integer} char1 The second byte + * @return {Boolean} Whether the 2 bytes are an extended character + */ + Cea608Stream.prototype.isExtCharacter = function (char0, char1) { + return (char0 === this.EXT_ + 1 || char0 === this.EXT_ + 2) && char1 >= 0x20 && char1 <= 0x3f; + }; + + /** + * Detects if the 2-byte packet is a mid-row code + * + * Mid-row codes have a second byte in the range 0x20 to 0x2f, with + * the first byte being 0x11 (for data channel 1) or 0x19 (for data + * channel 2). + * + * @param {Integer} char0 The first byte + * @param {Integer} char1 The second byte + * @return {Boolean} Whether the 2 bytes are a mid-row code + */ + Cea608Stream.prototype.isMidRowCode = function (char0, char1) { + return char0 === this.EXT_ && char1 >= 0x20 && char1 <= 0x2f; + }; + + /** + * Detects if the 2-byte packet is an offset control code + * + * Offset control codes have a second byte in the range 0x21 to 0x23, + * with the first byte being 0x17 (for data channel 1) or 0x1f (for + * data channel 2). + * + * @param {Integer} char0 The first byte + * @param {Integer} char1 The second byte + * @return {Boolean} Whether the 2 bytes are an offset control code + */ + Cea608Stream.prototype.isOffsetControlCode = function (char0, char1) { + return char0 === this.OFFSET_ && char1 >= 0x21 && char1 <= 0x23; + }; + + /** + * Detects if the 2-byte packet is a Preamble Address Code + * + * PACs have a first byte in the range 0x10 to 0x17 (for data channel 1) + * or 0x18 to 0x1f (for data channel 2), with the second byte in the + * range 0x40 to 0x7f. + * + * @param {Integer} char0 The first byte + * @param {Integer} char1 The second byte + * @return {Boolean} Whether the 2 bytes are a PAC + */ + Cea608Stream.prototype.isPAC = function (char0, char1) { + return char0 >= this.BASE_ && char0 < this.BASE_ + 8 && char1 >= 0x40 && char1 <= 0x7f; + }; + + /** + * Detects if a packet's second byte is in the range of a PAC color code + * + * PAC color codes have the second byte be in the range 0x40 to 0x4f, or + * 0x60 to 0x6f. + * + * @param {Integer} char1 The second byte + * @return {Boolean} Whether the byte is a color PAC + */ + Cea608Stream.prototype.isColorPAC = function (char1) { + return char1 >= 0x40 && char1 <= 0x4f || char1 >= 0x60 && char1 <= 0x7f; + }; + + /** + * Detects if a single byte is in the range of a normal character + * + * Normal text bytes are in the range 0x20 to 0x7f. + * + * @param {Integer} char The byte + * @return {Boolean} Whether the byte is a normal character + */ + Cea608Stream.prototype.isNormalChar = function (char) { + return char >= 0x20 && char <= 0x7f; + }; + + // Adds the opening HTML tag for the passed character to the caption text, + // and keeps track of it for later closing + Cea608Stream.prototype.addFormatting = function (pts, format) { + this.formatting_ = this.formatting_.concat(format); + var text = format.reduce(function (text, format) { + return text + '<' + format + '>'; + }, ''); + this[this.mode_](pts, text); + }; + + // Adds HTML closing tags for current formatting to caption text and + // clears remembered formatting + Cea608Stream.prototype.clearFormatting = function (pts) { + if (!this.formatting_.length) { + return; + } + var text = this.formatting_.reverse().reduce(function (text, format) { + return text + '</' + format + '>'; + }, ''); + this.formatting_ = []; + this[this.mode_](pts, text); + }; + + // Mode Implementations + Cea608Stream.prototype.popOn = function (pts, text) { + var baseRow = this.nonDisplayed_[this.row_]; + + // buffer characters + baseRow += text; + this.nonDisplayed_[this.row_] = baseRow; + }; + + Cea608Stream.prototype.rollUp = function (pts, text) { + var baseRow = this.displayed_[BOTTOM_ROW]; + + baseRow += text; + this.displayed_[BOTTOM_ROW] = baseRow; + }; + + Cea608Stream.prototype.shiftRowsUp_ = function () { + var i; + // clear out inactive rows + for (i = 0; i < this.topRow_; i++) { + this.displayed_[i] = ''; + } + // shift displayed rows up + for (i = this.topRow_; i < BOTTOM_ROW; i++) { + this.displayed_[i] = this.displayed_[i + 1]; + } + // clear out the bottom row + this.displayed_[BOTTOM_ROW] = ''; + }; + + // paintOn mode is not implemented + Cea608Stream.prototype.paintOn = function () { + }; + + // exports + var captionStream = { + CaptionStream: CaptionStream, + Cea608Stream: Cea608Stream + }; + + var streamTypes = { + H264_STREAM_TYPE: 0x1B, + ADTS_STREAM_TYPE: 0x0F, + METADATA_STREAM_TYPE: 0x15 + }; + + var MAX_TS = 8589934592; + + var RO_THRESH = 4294967296; + + var handleRollover = function handleRollover(value, reference) { + var direction = 1; + + if (value > reference) { + // If the current timestamp value is greater than our reference timestamp and we detect a + // timestamp rollover, this means the roll over is happening in the opposite direction. + // Example scenario: Enter a long stream/video just after a rollover occurred. The reference + // point will be set to a small number, e.g. 1. The user then seeks backwards over the + // rollover point. In loading this segment, the timestamp values will be very large, + // e.g. 2^33 - 1. Since this comes before the data we loaded previously, we want to adjust + // the time stamp to be `value - 2^33`. + direction = -1; + } + + // Note: A seek forwards or back that is greater than the RO_THRESH (2^32, ~13 hours) will + // cause an incorrect adjustment. + while (Math.abs(reference - value) > RO_THRESH) { + value += direction * MAX_TS; + } + + return value; + }; + + var TimestampRolloverStream = function TimestampRolloverStream(type) { + var lastDTS, referenceDTS; + + TimestampRolloverStream.prototype.init.call(this); + + this.type_ = type; + + this.push = function (data) { + if (data.type !== this.type_) { + return; + } + + if (referenceDTS === undefined) { + referenceDTS = data.dts; + } + + data.dts = handleRollover(data.dts, referenceDTS); + data.pts = handleRollover(data.pts, referenceDTS); + + lastDTS = data.dts; + + this.trigger('data', data); + }; + + this.flush = function () { + referenceDTS = lastDTS; + this.trigger('done'); + }; + + this.discontinuity = function () { + referenceDTS = void 0; + lastDTS = void 0; + }; + }; + + TimestampRolloverStream.prototype = new stream(); + + var timestampRolloverStream = { + TimestampRolloverStream: TimestampRolloverStream, + handleRollover: handleRollover + }; + + var percentEncode = function percentEncode(bytes, start, end) { + var i, + result = ''; + for (i = start; i < end; i++) { + result += '%' + ('00' + bytes[i].toString(16)).slice(-2); + } + return result; + }, + + + // return the string representation of the specified byte range, + // interpreted as UTf-8. + parseUtf8 = function parseUtf8(bytes, start, end) { + return decodeURIComponent(percentEncode(bytes, start, end)); + }, + + + // return the string representation of the specified byte range, + // interpreted as ISO-8859-1. + parseIso88591 = function parseIso88591(bytes, start, end) { + return unescape(percentEncode(bytes, start, end)); // jshint ignore:line + }, + parseSyncSafeInteger = function parseSyncSafeInteger(data) { + return data[0] << 21 | data[1] << 14 | data[2] << 7 | data[3]; + }, + tagParsers = { + TXXX: function TXXX(tag) { + var i; + if (tag.data[0] !== 3) { + // ignore frames with unrecognized character encodings + return; + } + + for (i = 1; i < tag.data.length; i++) { + if (tag.data[i] === 0) { + // parse the text fields + tag.description = parseUtf8(tag.data, 1, i); + // do not include the null terminator in the tag value + tag.value = parseUtf8(tag.data, i + 1, tag.data.length).replace(/\0*$/, ''); + break; + } + } + tag.data = tag.value; + }, + WXXX: function WXXX(tag) { + var i; + if (tag.data[0] !== 3) { + // ignore frames with unrecognized character encodings + return; + } + + for (i = 1; i < tag.data.length; i++) { + if (tag.data[i] === 0) { + // parse the description and URL fields + tag.description = parseUtf8(tag.data, 1, i); + tag.url = parseUtf8(tag.data, i + 1, tag.data.length); + break; + } + } + }, + PRIV: function PRIV(tag) { + var i; + + for (i = 0; i < tag.data.length; i++) { + if (tag.data[i] === 0) { + // parse the description and URL fields + tag.owner = parseIso88591(tag.data, 0, i); + break; + } + } + tag.privateData = tag.data.subarray(i + 1); + tag.data = tag.privateData; + } + }, + _MetadataStream; + + _MetadataStream = function MetadataStream(options) { + var settings = { + debug: !!(options && options.debug), + + // the bytes of the program-level descriptor field in MP2T + // see ISO/IEC 13818-1:2013 (E), section 2.6 "Program and + // program element descriptors" + descriptor: options && options.descriptor + }, + + + // the total size in bytes of the ID3 tag being parsed + tagSize = 0, + + + // tag data that is not complete enough to be parsed + buffer = [], + + + // the total number of bytes currently in the buffer + bufferSize = 0, + i; + + _MetadataStream.prototype.init.call(this); + + // calculate the text track in-band metadata track dispatch type + // https://html.spec.whatwg.org/multipage/embedded-content.html#steps-to-expose-a-media-resource-specific-text-track + this.dispatchType = streamTypes.METADATA_STREAM_TYPE.toString(16); + if (settings.descriptor) { + for (i = 0; i < settings.descriptor.length; i++) { + this.dispatchType += ('00' + settings.descriptor[i].toString(16)).slice(-2); + } + } + + this.push = function (chunk) { + var tag, frameStart, frameSize, frame, i, frameHeader; + if (chunk.type !== 'timed-metadata') { + return; + } + + // if data_alignment_indicator is set in the PES header, + // we must have the start of a new ID3 tag. Assume anything + // remaining in the buffer was malformed and throw it out + if (chunk.dataAlignmentIndicator) { + bufferSize = 0; + buffer.length = 0; + } + + // ignore events that don't look like ID3 data + if (buffer.length === 0 && (chunk.data.length < 10 || chunk.data[0] !== 'I'.charCodeAt(0) || chunk.data[1] !== 'D'.charCodeAt(0) || chunk.data[2] !== '3'.charCodeAt(0))) { + if (settings.debug) { + // eslint-disable-next-line no-console + console.log('Skipping unrecognized metadata packet'); + } + return; + } + + // add this chunk to the data we've collected so far + + buffer.push(chunk); + bufferSize += chunk.data.byteLength; + + // grab the size of the entire frame from the ID3 header + if (buffer.length === 1) { + // the frame size is transmitted as a 28-bit integer in the + // last four bytes of the ID3 header. + // The most significant bit of each byte is dropped and the + // results concatenated to recover the actual value. + tagSize = parseSyncSafeInteger(chunk.data.subarray(6, 10)); + + // ID3 reports the tag size excluding the header but it's more + // convenient for our comparisons to include it + tagSize += 10; + } + + // if the entire frame has not arrived, wait for more data + if (bufferSize < tagSize) { + return; + } + + // collect the entire frame so it can be parsed + tag = { + data: new Uint8Array(tagSize), + frames: [], + pts: buffer[0].pts, + dts: buffer[0].dts + }; + for (i = 0; i < tagSize;) { + tag.data.set(buffer[0].data.subarray(0, tagSize - i), i); + i += buffer[0].data.byteLength; + bufferSize -= buffer[0].data.byteLength; + buffer.shift(); + } + + // find the start of the first frame and the end of the tag + frameStart = 10; + if (tag.data[5] & 0x40) { + // advance the frame start past the extended header + frameStart += 4; // header size field + frameStart += parseSyncSafeInteger(tag.data.subarray(10, 14)); + + // clip any padding off the end + tagSize -= parseSyncSafeInteger(tag.data.subarray(16, 20)); + } + + // parse one or more ID3 frames + // http://id3.org/id3v2.3.0#ID3v2_frame_overview + do { + // determine the number of bytes in this frame + frameSize = parseSyncSafeInteger(tag.data.subarray(frameStart + 4, frameStart + 8)); + if (frameSize < 1) { + // eslint-disable-next-line no-console + return console.log('Malformed ID3 frame encountered. Skipping metadata parsing.'); + } + frameHeader = String.fromCharCode(tag.data[frameStart], tag.data[frameStart + 1], tag.data[frameStart + 2], tag.data[frameStart + 3]); + + frame = { + id: frameHeader, + data: tag.data.subarray(frameStart + 10, frameStart + frameSize + 10) + }; + frame.key = frame.id; + if (tagParsers[frame.id]) { + tagParsers[frame.id](frame); + + // handle the special PRIV frame used to indicate the start + // time for raw AAC data + if (frame.owner === 'com.apple.streaming.transportStreamTimestamp') { + var d = frame.data, + size = (d[3] & 0x01) << 30 | d[4] << 22 | d[5] << 14 | d[6] << 6 | d[7] >>> 2; + + size *= 4; + size += d[7] & 0x03; + frame.timeStamp = size; + // in raw AAC, all subsequent data will be timestamped based + // on the value of this frame + // we couldn't have known the appropriate pts and dts before + // parsing this ID3 tag so set those values now + if (tag.pts === undefined && tag.dts === undefined) { + tag.pts = frame.timeStamp; + tag.dts = frame.timeStamp; + } + this.trigger('timestamp', frame); + } + } + tag.frames.push(frame); + + frameStart += 10; // advance past the frame header + frameStart += frameSize; // advance past the frame body + } while (frameStart < tagSize); + this.trigger('data', tag); + }; + }; + _MetadataStream.prototype = new stream(); + + var metadataStream = _MetadataStream; + + var TimestampRolloverStream$1 = timestampRolloverStream.TimestampRolloverStream; + + // object types + var _TransportPacketStream, _TransportParseStream, _ElementaryStream; + + // constants + var MP2T_PACKET_LENGTH = 188, + + // bytes + SYNC_BYTE = 0x47; + + /** + * Splits an incoming stream of binary data into MPEG-2 Transport + * Stream packets. + */ + _TransportPacketStream = function TransportPacketStream() { + var buffer = new Uint8Array(MP2T_PACKET_LENGTH), + bytesInBuffer = 0; + + _TransportPacketStream.prototype.init.call(this); + + // Deliver new bytes to the stream. + + this.push = function (bytes) { + var startIndex = 0, + endIndex = MP2T_PACKET_LENGTH, + everything; + + // If there are bytes remaining from the last segment, prepend them to the + // bytes that were pushed in + if (bytesInBuffer) { + everything = new Uint8Array(bytes.byteLength + bytesInBuffer); + everything.set(buffer.subarray(0, bytesInBuffer)); + everything.set(bytes, bytesInBuffer); + bytesInBuffer = 0; + } else { + everything = bytes; + } + + // While we have enough data for a packet + while (endIndex < everything.byteLength) { + // Look for a pair of start and end sync bytes in the data.. + if (everything[startIndex] === SYNC_BYTE && everything[endIndex] === SYNC_BYTE) { + // We found a packet so emit it and jump one whole packet forward in + // the stream + this.trigger('data', everything.subarray(startIndex, endIndex)); + startIndex += MP2T_PACKET_LENGTH; + endIndex += MP2T_PACKET_LENGTH; + continue; + } + // If we get here, we have somehow become de-synchronized and we need to step + // forward one byte at a time until we find a pair of sync bytes that denote + // a packet + startIndex++; + endIndex++; + } + + // If there was some data left over at the end of the segment that couldn't + // possibly be a whole packet, keep it because it might be the start of a packet + // that continues in the next segment + if (startIndex < everything.byteLength) { + buffer.set(everything.subarray(startIndex), 0); + bytesInBuffer = everything.byteLength - startIndex; + } + }; + + this.flush = function () { + // If the buffer contains a whole packet when we are being flushed, emit it + // and empty the buffer. Otherwise hold onto the data because it may be + // important for decoding the next segment + if (bytesInBuffer === MP2T_PACKET_LENGTH && buffer[0] === SYNC_BYTE) { + this.trigger('data', buffer); + bytesInBuffer = 0; + } + this.trigger('done'); + }; + }; + _TransportPacketStream.prototype = new stream(); + + /** + * Accepts an MP2T TransportPacketStream and emits data events with parsed + * forms of the individual transport stream packets. + */ + _TransportParseStream = function TransportParseStream() { + var parsePsi, parsePat, parsePmt, self; + _TransportParseStream.prototype.init.call(this); + self = this; + + this.packetsWaitingForPmt = []; + this.programMapTable = undefined; + + parsePsi = function parsePsi(payload, psi) { + var offset = 0; + + // PSI packets may be split into multiple sections and those + // sections may be split into multiple packets. If a PSI + // section starts in this packet, the payload_unit_start_indicator + // will be true and the first byte of the payload will indicate + // the offset from the current position to the start of the + // section. + if (psi.payloadUnitStartIndicator) { + offset += payload[offset] + 1; + } + + if (psi.type === 'pat') { + parsePat(payload.subarray(offset), psi); + } else { + parsePmt(payload.subarray(offset), psi); + } + }; + + parsePat = function parsePat(payload, pat) { + pat.section_number = payload[7]; // eslint-disable-line camelcase + pat.last_section_number = payload[8]; // eslint-disable-line camelcase + + // skip the PSI header and parse the first PMT entry + self.pmtPid = (payload[10] & 0x1F) << 8 | payload[11]; + pat.pmtPid = self.pmtPid; + }; + + /** + * Parse out the relevant fields of a Program Map Table (PMT). + * @param payload {Uint8Array} the PMT-specific portion of an MP2T + * packet. The first byte in this array should be the table_id + * field. + * @param pmt {object} the object that should be decorated with + * fields parsed from the PMT. + */ + parsePmt = function parsePmt(payload, pmt) { + var sectionLength, tableEnd, programInfoLength, offset; + + // PMTs can be sent ahead of the time when they should actually + // take effect. We don't believe this should ever be the case + // for HLS but we'll ignore "forward" PMT declarations if we see + // them. Future PMT declarations have the current_next_indicator + // set to zero. + if (!(payload[5] & 0x01)) { + return; + } + + // overwrite any existing program map table + self.programMapTable = { + video: null, + audio: null, + 'timed-metadata': {} + }; + + // the mapping table ends at the end of the current section + sectionLength = (payload[1] & 0x0f) << 8 | payload[2]; + tableEnd = 3 + sectionLength - 4; + + // to determine where the table is, we have to figure out how + // long the program info descriptors are + programInfoLength = (payload[10] & 0x0f) << 8 | payload[11]; + + // advance the offset to the first entry in the mapping table + offset = 12 + programInfoLength; + while (offset < tableEnd) { + var streamType = payload[offset]; + var pid = (payload[offset + 1] & 0x1F) << 8 | payload[offset + 2]; + + // only map a single elementary_pid for audio and video stream types + // TODO: should this be done for metadata too? for now maintain behavior of + // multiple metadata streams + if (streamType === streamTypes.H264_STREAM_TYPE && self.programMapTable.video === null) { + self.programMapTable.video = pid; + } else if (streamType === streamTypes.ADTS_STREAM_TYPE && self.programMapTable.audio === null) { + self.programMapTable.audio = pid; + } else if (streamType === streamTypes.METADATA_STREAM_TYPE) { + // map pid to stream type for metadata streams + self.programMapTable['timed-metadata'][pid] = streamType; + } + + // move to the next table entry + // skip past the elementary stream descriptors, if present + offset += ((payload[offset + 3] & 0x0F) << 8 | payload[offset + 4]) + 5; + } + + // record the map on the packet as well + pmt.programMapTable = self.programMapTable; + }; + + /** + * Deliver a new MP2T packet to the stream. + */ + this.push = function (packet) { + var result = {}, + offset = 4; + + result.payloadUnitStartIndicator = !!(packet[1] & 0x40); + + // pid is a 13-bit field starting at the last bit of packet[1] + result.pid = packet[1] & 0x1f; + result.pid <<= 8; + result.pid |= packet[2]; + + // if an adaption field is present, its length is specified by the + // fifth byte of the TS packet header. The adaptation field is + // used to add stuffing to PES packets that don't fill a complete + // TS packet, and to specify some forms of timing and control data + // that we do not currently use. + if ((packet[3] & 0x30) >>> 4 > 0x01) { + offset += packet[offset] + 1; + } + + // parse the rest of the packet based on the type + if (result.pid === 0) { + result.type = 'pat'; + parsePsi(packet.subarray(offset), result); + this.trigger('data', result); + } else if (result.pid === this.pmtPid) { + result.type = 'pmt'; + parsePsi(packet.subarray(offset), result); + this.trigger('data', result); + + // if there are any packets waiting for a PMT to be found, process them now + while (this.packetsWaitingForPmt.length) { + this.processPes_.apply(this, this.packetsWaitingForPmt.shift()); + } + } else if (this.programMapTable === undefined) { + // When we have not seen a PMT yet, defer further processing of + // PES packets until one has been parsed + this.packetsWaitingForPmt.push([packet, offset, result]); + } else { + this.processPes_(packet, offset, result); + } + }; + + this.processPes_ = function (packet, offset, result) { + // set the appropriate stream type + if (result.pid === this.programMapTable.video) { + result.streamType = streamTypes.H264_STREAM_TYPE; + } else if (result.pid === this.programMapTable.audio) { + result.streamType = streamTypes.ADTS_STREAM_TYPE; + } else { + // if not video or audio, it is timed-metadata or unknown + // if unknown, streamType will be undefined + result.streamType = this.programMapTable['timed-metadata'][result.pid]; + } + + result.type = 'pes'; + result.data = packet.subarray(offset); + + this.trigger('data', result); + }; + }; + _TransportParseStream.prototype = new stream(); + _TransportParseStream.STREAM_TYPES = { + h264: 0x1b, + adts: 0x0f + }; + + /** + * Reconsistutes program elementary stream (PES) packets from parsed + * transport stream packets. That is, if you pipe an + * mp2t.TransportParseStream into a mp2t.ElementaryStream, the output + * events will be events which capture the bytes for individual PES + * packets plus relevant metadata that has been extracted from the + * container. + */ + _ElementaryStream = function ElementaryStream() { + var self = this, + + + // PES packet fragments + video = { + data: [], + size: 0 + }, + audio = { + data: [], + size: 0 + }, + timedMetadata = { + data: [], + size: 0 + }, + parsePes = function parsePes(payload, pes) { + var ptsDtsFlags; + + // get the packet length, this will be 0 for video + pes.packetLength = 6 + (payload[4] << 8 | payload[5]); + + // find out if this packets starts a new keyframe + pes.dataAlignmentIndicator = (payload[6] & 0x04) !== 0; + // PES packets may be annotated with a PTS value, or a PTS value + // and a DTS value. Determine what combination of values is + // available to work with. + ptsDtsFlags = payload[7]; + + // PTS and DTS are normally stored as a 33-bit number. Javascript + // performs all bitwise operations on 32-bit integers but javascript + // supports a much greater range (52-bits) of integer using standard + // mathematical operations. + // We construct a 31-bit value using bitwise operators over the 31 + // most significant bits and then multiply by 4 (equal to a left-shift + // of 2) before we add the final 2 least significant bits of the + // timestamp (equal to an OR.) + if (ptsDtsFlags & 0xC0) { + // the PTS and DTS are not written out directly. For information + // on how they are encoded, see + // http://dvd.sourceforge.net/dvdinfo/pes-hdr.html + pes.pts = (payload[9] & 0x0E) << 27 | (payload[10] & 0xFF) << 20 | (payload[11] & 0xFE) << 12 | (payload[12] & 0xFF) << 5 | (payload[13] & 0xFE) >>> 3; + pes.pts *= 4; // Left shift by 2 + pes.pts += (payload[13] & 0x06) >>> 1; // OR by the two LSBs + pes.dts = pes.pts; + if (ptsDtsFlags & 0x40) { + pes.dts = (payload[14] & 0x0E) << 27 | (payload[15] & 0xFF) << 20 | (payload[16] & 0xFE) << 12 | (payload[17] & 0xFF) << 5 | (payload[18] & 0xFE) >>> 3; + pes.dts *= 4; // Left shift by 2 + pes.dts += (payload[18] & 0x06) >>> 1; // OR by the two LSBs + } + } + // the data section starts immediately after the PES header. + // pes_header_data_length specifies the number of header bytes + // that follow the last byte of the field. + pes.data = payload.subarray(9 + payload[8]); + }, + flushStream = function flushStream(stream$$1, type, forceFlush) { + var packetData = new Uint8Array(stream$$1.size), + event = { + type: type + }, + i = 0, + offset = 0, + packetFlushable = false, + fragment; + + // do nothing if there is not enough buffered data for a complete + // PES header + if (!stream$$1.data.length || stream$$1.size < 9) { + return; + } + event.trackId = stream$$1.data[0].pid; + + // reassemble the packet + for (i = 0; i < stream$$1.data.length; i++) { + fragment = stream$$1.data[i]; + + packetData.set(fragment.data, offset); + offset += fragment.data.byteLength; + } + + // parse assembled packet's PES header + parsePes(packetData, event); + + // non-video PES packets MUST have a non-zero PES_packet_length + // check that there is enough stream data to fill the packet + packetFlushable = type === 'video' || event.packetLength <= stream$$1.size; + + // flush pending packets if the conditions are right + if (forceFlush || packetFlushable) { + stream$$1.size = 0; + stream$$1.data.length = 0; + } + + // only emit packets that are complete. this is to avoid assembling + // incomplete PES packets due to poor segmentation + if (packetFlushable) { + self.trigger('data', event); + } + }; + + _ElementaryStream.prototype.init.call(this); + + this.push = function (data) { + ({ + pat: function pat() { + // we have to wait for the PMT to arrive as well before we + // have any meaningful metadata + }, + pes: function pes() { + var stream$$1, streamType; + + switch (data.streamType) { + case streamTypes.H264_STREAM_TYPE: + case streamTypes.H264_STREAM_TYPE: + stream$$1 = video; + streamType = 'video'; + break; + case streamTypes.ADTS_STREAM_TYPE: + stream$$1 = audio; + streamType = 'audio'; + break; + case streamTypes.METADATA_STREAM_TYPE: + stream$$1 = timedMetadata; + streamType = 'timed-metadata'; + break; + default: + // ignore unknown stream types + return; + } + + // if a new packet is starting, we can flush the completed + // packet + if (data.payloadUnitStartIndicator) { + flushStream(stream$$1, streamType, true); + } + + // buffer this fragment until we are sure we've received the + // complete payload + stream$$1.data.push(data); + stream$$1.size += data.data.byteLength; + }, + pmt: function pmt() { + var event = { + type: 'metadata', + tracks: [] + }, + programMapTable = data.programMapTable; + + // translate audio and video streams to tracks + if (programMapTable.video !== null) { + event.tracks.push({ + timelineStartInfo: { + baseMediaDecodeTime: 0 + }, + id: +programMapTable.video, + codec: 'avc', + type: 'video' + }); + } + if (programMapTable.audio !== null) { + event.tracks.push({ + timelineStartInfo: { + baseMediaDecodeTime: 0 + }, + id: +programMapTable.audio, + codec: 'adts', + type: 'audio' + }); + } + + self.trigger('data', event); + } + })[data.type](); + }; + + /** + * Flush any remaining input. Video PES packets may be of variable + * length. Normally, the start of a new video packet can trigger the + * finalization of the previous packet. That is not possible if no + * more video is forthcoming, however. In that case, some other + * mechanism (like the end of the file) has to be employed. When it is + * clear that no additional data is forthcoming, calling this method + * will flush the buffered packets. + */ + this.flush = function () { + // !!THIS ORDER IS IMPORTANT!! + // video first then audio + flushStream(video, 'video'); + flushStream(audio, 'audio'); + flushStream(timedMetadata, 'timed-metadata'); + this.trigger('done'); + }; + }; + _ElementaryStream.prototype = new stream(); + + var m2ts = { + PAT_PID: 0x0000, + MP2T_PACKET_LENGTH: MP2T_PACKET_LENGTH, + TransportPacketStream: _TransportPacketStream, + TransportParseStream: _TransportParseStream, + ElementaryStream: _ElementaryStream, + TimestampRolloverStream: TimestampRolloverStream$1, + CaptionStream: captionStream.CaptionStream, + Cea608Stream: captionStream.Cea608Stream, + MetadataStream: metadataStream + }; + + for (var type in streamTypes) { + if (streamTypes.hasOwnProperty(type)) { + m2ts[type] = streamTypes[type]; + } + } + + var m2ts_1 = m2ts; + + var _AdtsStream; + + var ADTS_SAMPLING_FREQUENCIES = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350]; + + /* + * Accepts a ElementaryStream and emits data events with parsed + * AAC Audio Frames of the individual packets. Input audio in ADTS + * format is unpacked and re-emitted as AAC frames. + * + * @see http://wiki.multimedia.cx/index.php?title=ADTS + * @see http://wiki.multimedia.cx/?title=Understanding_AAC + */ + _AdtsStream = function AdtsStream() { + var buffer; + + _AdtsStream.prototype.init.call(this); + + this.push = function (packet) { + var i = 0, + frameNum = 0, + frameLength, + protectionSkipBytes, + frameEnd, + oldBuffer, + sampleCount, + adtsFrameDuration; + + if (packet.type !== 'audio') { + // ignore non-audio data + return; + } + + // Prepend any data in the buffer to the input data so that we can parse + // aac frames the cross a PES packet boundary + if (buffer) { + oldBuffer = buffer; + buffer = new Uint8Array(oldBuffer.byteLength + packet.data.byteLength); + buffer.set(oldBuffer); + buffer.set(packet.data, oldBuffer.byteLength); + } else { + buffer = packet.data; + } + + // unpack any ADTS frames which have been fully received + // for details on the ADTS header, see http://wiki.multimedia.cx/index.php?title=ADTS + while (i + 5 < buffer.length) { + + // Loook for the start of an ADTS header.. + if (buffer[i] !== 0xFF || (buffer[i + 1] & 0xF6) !== 0xF0) { + // If a valid header was not found, jump one forward and attempt to + // find a valid ADTS header starting at the next byte + i++; + continue; + } + + // The protection skip bit tells us if we have 2 bytes of CRC data at the + // end of the ADTS header + protectionSkipBytes = (~buffer[i + 1] & 0x01) * 2; + + // Frame length is a 13 bit integer starting 16 bits from the + // end of the sync sequence + frameLength = (buffer[i + 3] & 0x03) << 11 | buffer[i + 4] << 3 | (buffer[i + 5] & 0xe0) >> 5; + + sampleCount = ((buffer[i + 6] & 0x03) + 1) * 1024; + adtsFrameDuration = sampleCount * 90000 / ADTS_SAMPLING_FREQUENCIES[(buffer[i + 2] & 0x3c) >>> 2]; + + frameEnd = i + frameLength; + + // If we don't have enough data to actually finish this ADTS frame, return + // and wait for more data + if (buffer.byteLength < frameEnd) { + return; + } + + // Otherwise, deliver the complete AAC frame + this.trigger('data', { + pts: packet.pts + frameNum * adtsFrameDuration, + dts: packet.dts + frameNum * adtsFrameDuration, + sampleCount: sampleCount, + audioobjecttype: (buffer[i + 2] >>> 6 & 0x03) + 1, + channelcount: (buffer[i + 2] & 1) << 2 | (buffer[i + 3] & 0xc0) >>> 6, + samplerate: ADTS_SAMPLING_FREQUENCIES[(buffer[i + 2] & 0x3c) >>> 2], + samplingfrequencyindex: (buffer[i + 2] & 0x3c) >>> 2, + // assume ISO/IEC 14496-12 AudioSampleEntry default of 16 + samplesize: 16, + data: buffer.subarray(i + 7 + protectionSkipBytes, frameEnd) + }); + + // If the buffer is empty, clear it and return + if (buffer.byteLength === frameEnd) { + buffer = undefined; + return; + } + + frameNum++; + + // Remove the finished frame from the buffer and start the process again + buffer = buffer.subarray(frameEnd); + } + }; + this.flush = function () { + this.trigger('done'); + }; + }; + + _AdtsStream.prototype = new stream(); + + var adts = _AdtsStream; + + var ExpGolomb; + + /** + * Parser for exponential Golomb codes, a variable-bitwidth number encoding + * scheme used by h264. + */ + ExpGolomb = function ExpGolomb(workingData) { + var + // the number of bytes left to examine in workingData + workingBytesAvailable = workingData.byteLength, + + + // the current word being examined + workingWord = 0, + + // :uint + + // the number of bits left to examine in the current word + workingBitsAvailable = 0; // :uint; + + // ():uint + this.length = function () { + return 8 * workingBytesAvailable; + }; + + // ():uint + this.bitsAvailable = function () { + return 8 * workingBytesAvailable + workingBitsAvailable; + }; + + // ():void + this.loadWord = function () { + var position = workingData.byteLength - workingBytesAvailable, + workingBytes = new Uint8Array(4), + availableBytes = Math.min(4, workingBytesAvailable); + + if (availableBytes === 0) { + throw new Error('no bytes available'); + } + + workingBytes.set(workingData.subarray(position, position + availableBytes)); + workingWord = new DataView(workingBytes.buffer).getUint32(0); + + // track the amount of workingData that has been processed + workingBitsAvailable = availableBytes * 8; + workingBytesAvailable -= availableBytes; + }; + + // (count:int):void + this.skipBits = function (count) { + var skipBytes; // :int + if (workingBitsAvailable > count) { + workingWord <<= count; + workingBitsAvailable -= count; + } else { + count -= workingBitsAvailable; + skipBytes = Math.floor(count / 8); + + count -= skipBytes * 8; + workingBytesAvailable -= skipBytes; + + this.loadWord(); + + workingWord <<= count; + workingBitsAvailable -= count; + } + }; + + // (size:int):uint + this.readBits = function (size) { + var bits = Math.min(workingBitsAvailable, size), + + // :uint + valu = workingWord >>> 32 - bits; // :uint + // if size > 31, handle error + workingBitsAvailable -= bits; + if (workingBitsAvailable > 0) { + workingWord <<= bits; + } else if (workingBytesAvailable > 0) { + this.loadWord(); + } + + bits = size - bits; + if (bits > 0) { + return valu << bits | this.readBits(bits); + } + return valu; + }; + + // ():uint + this.skipLeadingZeros = function () { + var leadingZeroCount; // :uint + for (leadingZeroCount = 0; leadingZeroCount < workingBitsAvailable; ++leadingZeroCount) { + if ((workingWord & 0x80000000 >>> leadingZeroCount) !== 0) { + // the first bit of working word is 1 + workingWord <<= leadingZeroCount; + workingBitsAvailable -= leadingZeroCount; + return leadingZeroCount; + } + } + + // we exhausted workingWord and still have not found a 1 + this.loadWord(); + return leadingZeroCount + this.skipLeadingZeros(); + }; + + // ():void + this.skipUnsignedExpGolomb = function () { + this.skipBits(1 + this.skipLeadingZeros()); + }; + + // ():void + this.skipExpGolomb = function () { + this.skipBits(1 + this.skipLeadingZeros()); + }; + + // ():uint + this.readUnsignedExpGolomb = function () { + var clz = this.skipLeadingZeros(); // :uint + return this.readBits(clz + 1) - 1; + }; + + // ():int + this.readExpGolomb = function () { + var valu = this.readUnsignedExpGolomb(); // :int + if (0x01 & valu) { + // the number is odd if the low order bit is set + return 1 + valu >>> 1; // add 1 to make it even, and divide by 2 + } + return -1 * (valu >>> 1); // divide by two then make it negative + }; + + // Some convenience functions + // :Boolean + this.readBoolean = function () { + return this.readBits(1) === 1; + }; + + // ():int + this.readUnsignedByte = function () { + return this.readBits(8); + }; + + this.loadWord(); + }; + + var expGolomb = ExpGolomb; + + var _H264Stream, _NalByteStream; + var PROFILES_WITH_OPTIONAL_SPS_DATA; + + /** + * Accepts a NAL unit byte stream and unpacks the embedded NAL units. + */ + _NalByteStream = function NalByteStream() { + var syncPoint = 0, + i, + buffer; + _NalByteStream.prototype.init.call(this); + + this.push = function (data) { + var swapBuffer; + + if (!buffer) { + buffer = data.data; + } else { + swapBuffer = new Uint8Array(buffer.byteLength + data.data.byteLength); + swapBuffer.set(buffer); + swapBuffer.set(data.data, buffer.byteLength); + buffer = swapBuffer; + } + + // Rec. ITU-T H.264, Annex B + // scan for NAL unit boundaries + + // a match looks like this: + // 0 0 1 .. NAL .. 0 0 1 + // ^ sync point ^ i + // or this: + // 0 0 1 .. NAL .. 0 0 0 + // ^ sync point ^ i + + // advance the sync point to a NAL start, if necessary + for (; syncPoint < buffer.byteLength - 3; syncPoint++) { + if (buffer[syncPoint + 2] === 1) { + // the sync point is properly aligned + i = syncPoint + 5; + break; + } + } + + while (i < buffer.byteLength) { + // look at the current byte to determine if we've hit the end of + // a NAL unit boundary + switch (buffer[i]) { + case 0: + // skip past non-sync sequences + if (buffer[i - 1] !== 0) { + i += 2; + break; + } else if (buffer[i - 2] !== 0) { + i++; + break; + } + + // deliver the NAL unit if it isn't empty + if (syncPoint + 3 !== i - 2) { + this.trigger('data', buffer.subarray(syncPoint + 3, i - 2)); + } + + // drop trailing zeroes + do { + i++; + } while (buffer[i] !== 1 && i < buffer.length); + syncPoint = i - 2; + i += 3; + break; + case 1: + // skip past non-sync sequences + if (buffer[i - 1] !== 0 || buffer[i - 2] !== 0) { + i += 3; + break; + } + + // deliver the NAL unit + this.trigger('data', buffer.subarray(syncPoint + 3, i - 2)); + syncPoint = i - 2; + i += 3; + break; + default: + // the current byte isn't a one or zero, so it cannot be part + // of a sync sequence + i += 3; + break; + } + } + // filter out the NAL units that were delivered + buffer = buffer.subarray(syncPoint); + i -= syncPoint; + syncPoint = 0; + }; + + this.flush = function () { + // deliver the last buffered NAL unit + if (buffer && buffer.byteLength > 3) { + this.trigger('data', buffer.subarray(syncPoint + 3)); + } + // reset the stream state + buffer = null; + syncPoint = 0; + this.trigger('done'); + }; + }; + _NalByteStream.prototype = new stream(); + + // values of profile_idc that indicate additional fields are included in the SPS + // see Recommendation ITU-T H.264 (4/2013), + // 7.3.2.1.1 Sequence parameter set data syntax + PROFILES_WITH_OPTIONAL_SPS_DATA = { + 100: true, + 110: true, + 122: true, + 244: true, + 44: true, + 83: true, + 86: true, + 118: true, + 128: true, + 138: true, + 139: true, + 134: true + }; + + /** + * Accepts input from a ElementaryStream and produces H.264 NAL unit data + * events. + */ + _H264Stream = function H264Stream() { + var nalByteStream = new _NalByteStream(), + self, + trackId, + currentPts, + currentDts, + discardEmulationPreventionBytes, + readSequenceParameterSet, + skipScalingList; + + _H264Stream.prototype.init.call(this); + self = this; + + this.push = function (packet) { + if (packet.type !== 'video') { + return; + } + trackId = packet.trackId; + currentPts = packet.pts; + currentDts = packet.dts; + + nalByteStream.push(packet); + }; + + nalByteStream.on('data', function (data) { + var event = { + trackId: trackId, + pts: currentPts, + dts: currentDts, + data: data + }; + + switch (data[0] & 0x1f) { + case 0x05: + event.nalUnitType = 'slice_layer_without_partitioning_rbsp_idr'; + break; + case 0x06: + event.nalUnitType = 'sei_rbsp'; + event.escapedRBSP = discardEmulationPreventionBytes(data.subarray(1)); + break; + case 0x07: + event.nalUnitType = 'seq_parameter_set_rbsp'; + event.escapedRBSP = discardEmulationPreventionBytes(data.subarray(1)); + event.config = readSequenceParameterSet(event.escapedRBSP); + break; + case 0x08: + event.nalUnitType = 'pic_parameter_set_rbsp'; + break; + case 0x09: + event.nalUnitType = 'access_unit_delimiter_rbsp'; + break; + + default: + break; + } + self.trigger('data', event); + }); + nalByteStream.on('done', function () { + self.trigger('done'); + }); + + this.flush = function () { + nalByteStream.flush(); + }; + + /** + * Advance the ExpGolomb decoder past a scaling list. The scaling + * list is optionally transmitted as part of a sequence parameter + * set and is not relevant to transmuxing. + * @param count {number} the number of entries in this scaling list + * @param expGolombDecoder {object} an ExpGolomb pointed to the + * start of a scaling list + * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1 + */ + skipScalingList = function skipScalingList(count, expGolombDecoder) { + var lastScale = 8, + nextScale = 8, + j, + deltaScale; + + for (j = 0; j < count; j++) { + if (nextScale !== 0) { + deltaScale = expGolombDecoder.readExpGolomb(); + nextScale = (lastScale + deltaScale + 256) % 256; + } + + lastScale = nextScale === 0 ? lastScale : nextScale; + } + }; + + /** + * Expunge any "Emulation Prevention" bytes from a "Raw Byte + * Sequence Payload" + * @param data {Uint8Array} the bytes of a RBSP from a NAL + * unit + * @return {Uint8Array} the RBSP without any Emulation + * Prevention Bytes + */ + discardEmulationPreventionBytes = function discardEmulationPreventionBytes(data) { + var length = data.byteLength, + emulationPreventionBytesPositions = [], + i = 1, + newLength, + newData; + + // Find all `Emulation Prevention Bytes` + while (i < length - 2) { + if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) { + emulationPreventionBytesPositions.push(i + 2); + i += 2; + } else { + i++; + } + } + + // If no Emulation Prevention Bytes were found just return the original + // array + if (emulationPreventionBytesPositions.length === 0) { + return data; + } + + // Create a new array to hold the NAL unit data + newLength = length - emulationPreventionBytesPositions.length; + newData = new Uint8Array(newLength); + var sourceIndex = 0; + + for (i = 0; i < newLength; sourceIndex++, i++) { + if (sourceIndex === emulationPreventionBytesPositions[0]) { + // Skip this byte + sourceIndex++; + // Remove this position index + emulationPreventionBytesPositions.shift(); + } + newData[i] = data[sourceIndex]; + } + + return newData; + }; + + /** + * Read a sequence parameter set and return some interesting video + * properties. A sequence parameter set is the H264 metadata that + * describes the properties of upcoming video frames. + * @param data {Uint8Array} the bytes of a sequence parameter set + * @return {object} an object with configuration parsed from the + * sequence parameter set, including the dimensions of the + * associated video frames. + */ + readSequenceParameterSet = function readSequenceParameterSet(data) { + var frameCropLeftOffset = 0, + frameCropRightOffset = 0, + frameCropTopOffset = 0, + frameCropBottomOffset = 0, + sarScale = 1, + expGolombDecoder, + profileIdc, + levelIdc, + profileCompatibility, + chromaFormatIdc, + picOrderCntType, + numRefFramesInPicOrderCntCycle, + picWidthInMbsMinus1, + picHeightInMapUnitsMinus1, + frameMbsOnlyFlag, + scalingListCount, + sarRatio, + aspectRatioIdc, + i; + + expGolombDecoder = new expGolomb(data); + profileIdc = expGolombDecoder.readUnsignedByte(); // profile_idc + profileCompatibility = expGolombDecoder.readUnsignedByte(); // constraint_set[0-5]_flag + levelIdc = expGolombDecoder.readUnsignedByte(); // level_idc u(8) + expGolombDecoder.skipUnsignedExpGolomb(); // seq_parameter_set_id + + // some profiles have more optional data we don't need + if (PROFILES_WITH_OPTIONAL_SPS_DATA[profileIdc]) { + chromaFormatIdc = expGolombDecoder.readUnsignedExpGolomb(); + if (chromaFormatIdc === 3) { + expGolombDecoder.skipBits(1); // separate_colour_plane_flag + } + expGolombDecoder.skipUnsignedExpGolomb(); // bit_depth_luma_minus8 + expGolombDecoder.skipUnsignedExpGolomb(); // bit_depth_chroma_minus8 + expGolombDecoder.skipBits(1); // qpprime_y_zero_transform_bypass_flag + if (expGolombDecoder.readBoolean()) { + // seq_scaling_matrix_present_flag + scalingListCount = chromaFormatIdc !== 3 ? 8 : 12; + for (i = 0; i < scalingListCount; i++) { + if (expGolombDecoder.readBoolean()) { + // seq_scaling_list_present_flag[ i ] + if (i < 6) { + skipScalingList(16, expGolombDecoder); + } else { + skipScalingList(64, expGolombDecoder); + } + } + } + } + } + + expGolombDecoder.skipUnsignedExpGolomb(); // log2_max_frame_num_minus4 + picOrderCntType = expGolombDecoder.readUnsignedExpGolomb(); + + if (picOrderCntType === 0) { + expGolombDecoder.readUnsignedExpGolomb(); // log2_max_pic_order_cnt_lsb_minus4 + } else if (picOrderCntType === 1) { + expGolombDecoder.skipBits(1); // delta_pic_order_always_zero_flag + expGolombDecoder.skipExpGolomb(); // offset_for_non_ref_pic + expGolombDecoder.skipExpGolomb(); // offset_for_top_to_bottom_field + numRefFramesInPicOrderCntCycle = expGolombDecoder.readUnsignedExpGolomb(); + for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) { + expGolombDecoder.skipExpGolomb(); // offset_for_ref_frame[ i ] + } + } + + expGolombDecoder.skipUnsignedExpGolomb(); // max_num_ref_frames + expGolombDecoder.skipBits(1); // gaps_in_frame_num_value_allowed_flag + + picWidthInMbsMinus1 = expGolombDecoder.readUnsignedExpGolomb(); + picHeightInMapUnitsMinus1 = expGolombDecoder.readUnsignedExpGolomb(); + + frameMbsOnlyFlag = expGolombDecoder.readBits(1); + if (frameMbsOnlyFlag === 0) { + expGolombDecoder.skipBits(1); // mb_adaptive_frame_field_flag + } + + expGolombDecoder.skipBits(1); // direct_8x8_inference_flag + if (expGolombDecoder.readBoolean()) { + // frame_cropping_flag + frameCropLeftOffset = expGolombDecoder.readUnsignedExpGolomb(); + frameCropRightOffset = expGolombDecoder.readUnsignedExpGolomb(); + frameCropTopOffset = expGolombDecoder.readUnsignedExpGolomb(); + frameCropBottomOffset = expGolombDecoder.readUnsignedExpGolomb(); + } + if (expGolombDecoder.readBoolean()) { + // vui_parameters_present_flag + if (expGolombDecoder.readBoolean()) { + // aspect_ratio_info_present_flag + aspectRatioIdc = expGolombDecoder.readUnsignedByte(); + switch (aspectRatioIdc) { + case 1: + sarRatio = [1, 1]; + break; + case 2: + sarRatio = [12, 11]; + break; + case 3: + sarRatio = [10, 11]; + break; + case 4: + sarRatio = [16, 11]; + break; + case 5: + sarRatio = [40, 33]; + break; + case 6: + sarRatio = [24, 11]; + break; + case 7: + sarRatio = [20, 11]; + break; + case 8: + sarRatio = [32, 11]; + break; + case 9: + sarRatio = [80, 33]; + break; + case 10: + sarRatio = [18, 11]; + break; + case 11: + sarRatio = [15, 11]; + break; + case 12: + sarRatio = [64, 33]; + break; + case 13: + sarRatio = [160, 99]; + break; + case 14: + sarRatio = [4, 3]; + break; + case 15: + sarRatio = [3, 2]; + break; + case 16: + sarRatio = [2, 1]; + break; + case 255: { + sarRatio = [expGolombDecoder.readUnsignedByte() << 8 | expGolombDecoder.readUnsignedByte(), expGolombDecoder.readUnsignedByte() << 8 | expGolombDecoder.readUnsignedByte()]; + break; + } + } + if (sarRatio) { + sarScale = sarRatio[0] / sarRatio[1]; + } + } + } + return { + profileIdc: profileIdc, + levelIdc: levelIdc, + profileCompatibility: profileCompatibility, + width: Math.ceil(((picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale), + height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - frameCropTopOffset * 2 - frameCropBottomOffset * 2 + }; + }; + }; + _H264Stream.prototype = new stream(); + + var h264 = { + H264Stream: _H264Stream, + NalByteStream: _NalByteStream + }; + + // Constants + var _AacStream; + + /** + * Splits an incoming stream of binary data into ADTS and ID3 Frames. + */ + + _AacStream = function AacStream() { + var everything = new Uint8Array(), + timeStamp = 0; + + _AacStream.prototype.init.call(this); + + this.setTimestamp = function (timestamp) { + timeStamp = timestamp; + }; + + this.parseId3TagSize = function (header, byteIndex) { + var returnSize = header[byteIndex + 6] << 21 | header[byteIndex + 7] << 14 | header[byteIndex + 8] << 7 | header[byteIndex + 9], + flags = header[byteIndex + 5], + footerPresent = (flags & 16) >> 4; + + if (footerPresent) { + return returnSize + 20; + } + return returnSize + 10; + }; + + this.parseAdtsSize = function (header, byteIndex) { + var lowThree = (header[byteIndex + 5] & 0xE0) >> 5, + middle = header[byteIndex + 4] << 3, + highTwo = header[byteIndex + 3] & 0x3 << 11; + + return highTwo | middle | lowThree; + }; + + this.push = function (bytes) { + var frameSize = 0, + byteIndex = 0, + bytesLeft, + chunk, + packet, + tempLength; + + // If there are bytes remaining from the last segment, prepend them to the + // bytes that were pushed in + if (everything.length) { + tempLength = everything.length; + everything = new Uint8Array(bytes.byteLength + tempLength); + everything.set(everything.subarray(0, tempLength)); + everything.set(bytes, tempLength); + } else { + everything = bytes; + } + + while (everything.length - byteIndex >= 3) { + if (everything[byteIndex] === 'I'.charCodeAt(0) && everything[byteIndex + 1] === 'D'.charCodeAt(0) && everything[byteIndex + 2] === '3'.charCodeAt(0)) { + + // Exit early because we don't have enough to parse + // the ID3 tag header + if (everything.length - byteIndex < 10) { + break; + } + + // check framesize + frameSize = this.parseId3TagSize(everything, byteIndex); + + // Exit early if we don't have enough in the buffer + // to emit a full packet + if (frameSize > everything.length) { + break; + } + chunk = { + type: 'timed-metadata', + data: everything.subarray(byteIndex, byteIndex + frameSize) + }; + this.trigger('data', chunk); + byteIndex += frameSize; + continue; + } else if (everything[byteIndex] & 0xff === 0xff && (everything[byteIndex + 1] & 0xf0) === 0xf0) { + + // Exit early because we don't have enough to parse + // the ADTS frame header + if (everything.length - byteIndex < 7) { + break; + } + + frameSize = this.parseAdtsSize(everything, byteIndex); + + // Exit early if we don't have enough in the buffer + // to emit a full packet + if (frameSize > everything.length) { + break; + } + + packet = { + type: 'audio', + data: everything.subarray(byteIndex, byteIndex + frameSize), + pts: timeStamp, + dts: timeStamp + }; + this.trigger('data', packet); + byteIndex += frameSize; + continue; + } + byteIndex++; + } + bytesLeft = everything.length - byteIndex; + + if (bytesLeft > 0) { + everything = everything.subarray(byteIndex); + } else { + everything = new Uint8Array(); + } + }; + }; + + _AacStream.prototype = new stream(); + + var aac = _AacStream; + + var highPrefix = [33, 16, 5, 32, 164, 27]; + var lowPrefix = [33, 65, 108, 84, 1, 2, 4, 8, 168, 2, 4, 8, 17, 191, 252]; + var zeroFill = function zeroFill(count) { + var a = []; + while (count--) { + a.push(0); + } + return a; + }; + + var makeTable = function makeTable(metaTable) { + return Object.keys(metaTable).reduce(function (obj, key) { + obj[key] = new Uint8Array(metaTable[key].reduce(function (arr, part) { + return arr.concat(part); + }, [])); + return obj; + }, {}); + }; + + // Frames-of-silence to use for filling in missing AAC frames + var coneOfSilence = { + 96000: [highPrefix, [227, 64], zeroFill(154), [56]], + 88200: [highPrefix, [231], zeroFill(170), [56]], + 64000: [highPrefix, [248, 192], zeroFill(240), [56]], + 48000: [highPrefix, [255, 192], zeroFill(268), [55, 148, 128], zeroFill(54), [112]], + 44100: [highPrefix, [255, 192], zeroFill(268), [55, 163, 128], zeroFill(84), [112]], + 32000: [highPrefix, [255, 192], zeroFill(268), [55, 234], zeroFill(226), [112]], + 24000: [highPrefix, [255, 192], zeroFill(268), [55, 255, 128], zeroFill(268), [111, 112], zeroFill(126), [224]], + 16000: [highPrefix, [255, 192], zeroFill(268), [55, 255, 128], zeroFill(268), [111, 255], zeroFill(269), [223, 108], zeroFill(195), [1, 192]], + 12000: [lowPrefix, zeroFill(268), [3, 127, 248], zeroFill(268), [6, 255, 240], zeroFill(268), [13, 255, 224], zeroFill(268), [27, 253, 128], zeroFill(259), [56]], + 11025: [lowPrefix, zeroFill(268), [3, 127, 248], zeroFill(268), [6, 255, 240], zeroFill(268), [13, 255, 224], zeroFill(268), [27, 255, 192], zeroFill(268), [55, 175, 128], zeroFill(108), [112]], + 8000: [lowPrefix, zeroFill(268), [3, 121, 16], zeroFill(47), [7]] + }; + + var silence = makeTable(coneOfSilence); + + var ONE_SECOND_IN_TS = 90000, + + // 90kHz clock + secondsToVideoTs, + secondsToAudioTs, + videoTsToSeconds, + audioTsToSeconds, + audioTsToVideoTs, + videoTsToAudioTs; + + secondsToVideoTs = function secondsToVideoTs(seconds) { + return seconds * ONE_SECOND_IN_TS; + }; + + secondsToAudioTs = function secondsToAudioTs(seconds, sampleRate) { + return seconds * sampleRate; + }; + + videoTsToSeconds = function videoTsToSeconds(timestamp) { + return timestamp / ONE_SECOND_IN_TS; + }; + + audioTsToSeconds = function audioTsToSeconds(timestamp, sampleRate) { + return timestamp / sampleRate; + }; + + audioTsToVideoTs = function audioTsToVideoTs(timestamp, sampleRate) { + return secondsToVideoTs(audioTsToSeconds(timestamp, sampleRate)); + }; + + videoTsToAudioTs = function videoTsToAudioTs(timestamp, sampleRate) { + return secondsToAudioTs(videoTsToSeconds(timestamp), sampleRate); + }; + + var clock = { + secondsToVideoTs: secondsToVideoTs, + secondsToAudioTs: secondsToAudioTs, + videoTsToSeconds: videoTsToSeconds, + audioTsToSeconds: audioTsToSeconds, + audioTsToVideoTs: audioTsToVideoTs, + videoTsToAudioTs: videoTsToAudioTs + }; + + var H264Stream = h264.H264Stream; + + // constants + var AUDIO_PROPERTIES = ['audioobjecttype', 'channelcount', 'samplerate', 'samplingfrequencyindex', 'samplesize']; + + var VIDEO_PROPERTIES = ['width', 'height', 'profileIdc', 'levelIdc', 'profileCompatibility']; + + var ONE_SECOND_IN_TS$1 = 90000; // 90kHz clock + + // object types + var _VideoSegmentStream, _AudioSegmentStream, _Transmuxer, _CoalesceStream; + + // Helper functions + var createDefaultSample, isLikelyAacData, collectDtsInfo, clearDtsInfo, calculateTrackBaseMediaDecodeTime, + arrayEquals, sumFrameByteLengths; + + /** + * Default sample object + * see ISO/IEC 14496-12:2012, section 8.6.4.3 + */ + createDefaultSample = function createDefaultSample() { + return { + size: 0, + flags: { + isLeading: 0, + dependsOn: 1, + isDependedOn: 0, + hasRedundancy: 0, + degradationPriority: 0 + } + }; + }; + + isLikelyAacData = function isLikelyAacData(data) { + if (data[0] === 'I'.charCodeAt(0) && data[1] === 'D'.charCodeAt(0) && data[2] === '3'.charCodeAt(0)) { + return true; + } + return false; + }; + + /** + * Compare two arrays (even typed) for same-ness + */ + arrayEquals = function arrayEquals(a, b) { + var i; + + if (a.length !== b.length) { + return false; + } + + // compare the value of each element in the array + for (i = 0; i < a.length; i++) { + if (a[i] !== b[i]) { + return false; + } + } + + return true; + }; + + /** + * Sum the `byteLength` properties of the data in each AAC frame + */ + sumFrameByteLengths = function sumFrameByteLengths(array) { + var i, + currentObj, + sum = 0; + + // sum the byteLength's all each nal unit in the frame + for (i = 0; i < array.length; i++) { + currentObj = array[i]; + sum += currentObj.data.byteLength; + } + + return sum; + }; + + /** + * Constructs a single-track, ISO BMFF media segment from AAC data + * events. The output of this stream can be fed to a SourceBuffer + * configured with a suitable initialization segment. + * @param track {object} track metadata configuration + * @param options {object} transmuxer options object + * @param options.keepOriginalTimestamps {boolean} If true, keep the timestamps + * in the source; false to adjust the first segment to start at 0. + */ + _AudioSegmentStream = function AudioSegmentStream(track, options) { + var adtsFrames = [], + sequenceNumber = 0, + earliestAllowedDts = 0, + audioAppendStartTs = 0, + videoBaseMediaDecodeTime = Infinity; + + options = options || {}; + + _AudioSegmentStream.prototype.init.call(this); + + this.push = function (data) { + collectDtsInfo(track, data); + + if (track) { + AUDIO_PROPERTIES.forEach(function (prop) { + track[prop] = data[prop]; + }); + } + + // buffer audio data until end() is called + adtsFrames.push(data); + }; + + this.setEarliestDts = function (earliestDts) { + earliestAllowedDts = earliestDts - track.timelineStartInfo.baseMediaDecodeTime; + }; + + this.setVideoBaseMediaDecodeTime = function (baseMediaDecodeTime) { + videoBaseMediaDecodeTime = baseMediaDecodeTime; + }; + + this.setAudioAppendStart = function (timestamp) { + audioAppendStartTs = timestamp; + }; + + this.flush = function () { + var frames, moof, mdat, boxes; + + // return early if no audio data has been observed + if (adtsFrames.length === 0) { + this.trigger('done', 'AudioSegmentStream'); + return; + } + + frames = this.trimAdtsFramesByEarliestDts_(adtsFrames); + track.baseMediaDecodeTime = calculateTrackBaseMediaDecodeTime(track, options.keepOriginalTimestamps); + + this.prefixWithSilence_(track, frames); + + // we have to build the index from byte locations to + // samples (that is, adts frames) in the audio data + track.samples = this.generateSampleTable_(frames); + + // concatenate the audio data to constuct the mdat + mdat = mp4Generator.mdat(this.concatenateFrameData_(frames)); + + adtsFrames = []; + + moof = mp4Generator.moof(sequenceNumber, [track]); + boxes = new Uint8Array(moof.byteLength + mdat.byteLength); + + // bump the sequence number for next time + sequenceNumber++; + + boxes.set(moof); + boxes.set(mdat, moof.byteLength); + + clearDtsInfo(track); + + this.trigger('data', {track: track, boxes: boxes}); + this.trigger('done', 'AudioSegmentStream'); + }; + + // Possibly pad (prefix) the audio track with silence if appending this track + // would lead to the introduction of a gap in the audio buffer + this.prefixWithSilence_ = function (track, frames) { + var baseMediaDecodeTimeTs, + frameDuration = 0, + audioGapDuration = 0, + audioFillFrameCount = 0, + audioFillDuration = 0, + silentFrame, + i; + + if (!frames.length) { + return; + } + + baseMediaDecodeTimeTs = clock.audioTsToVideoTs(track.baseMediaDecodeTime, track.samplerate); + // determine frame clock duration based on sample rate, round up to avoid overfills + frameDuration = Math.ceil(ONE_SECOND_IN_TS$1 / (track.samplerate / 1024)); + + if (audioAppendStartTs && videoBaseMediaDecodeTime) { + // insert the shortest possible amount (audio gap or audio to video gap) + audioGapDuration = baseMediaDecodeTimeTs - Math.max(audioAppendStartTs, videoBaseMediaDecodeTime); + // number of full frames in the audio gap + audioFillFrameCount = Math.floor(audioGapDuration / frameDuration); + audioFillDuration = audioFillFrameCount * frameDuration; + } + + // don't attempt to fill gaps smaller than a single frame or larger + // than a half second + if (audioFillFrameCount < 1 || audioFillDuration > ONE_SECOND_IN_TS$1 / 2) { + return; + } + + silentFrame = silence[track.samplerate]; + + if (!silentFrame) { + // we don't have a silent frame pregenerated for the sample rate, so use a frame + // from the content instead + silentFrame = frames[0].data; + } + + for (i = 0; i < audioFillFrameCount; i++) { + frames.splice(i, 0, { + data: silentFrame + }); + } + + track.baseMediaDecodeTime -= Math.floor(clock.videoTsToAudioTs(audioFillDuration, track.samplerate)); + }; + + // If the audio segment extends before the earliest allowed dts + // value, remove AAC frames until starts at or after the earliest + // allowed DTS so that we don't end up with a negative baseMedia- + // DecodeTime for the audio track + this.trimAdtsFramesByEarliestDts_ = function (adtsFrames) { + if (track.minSegmentDts >= earliestAllowedDts) { + return adtsFrames; + } + + // We will need to recalculate the earliest segment Dts + track.minSegmentDts = Infinity; + + return adtsFrames.filter(function (currentFrame) { + // If this is an allowed frame, keep it and record it's Dts + if (currentFrame.dts >= earliestAllowedDts) { + track.minSegmentDts = Math.min(track.minSegmentDts, currentFrame.dts); + track.minSegmentPts = track.minSegmentDts; + return true; + } + // Otherwise, discard it + return false; + }); + }; + + // generate the track's raw mdat data from an array of frames + this.generateSampleTable_ = function (frames) { + var i, + currentFrame, + samples = []; + + for (i = 0; i < frames.length; i++) { + currentFrame = frames[i]; + samples.push({ + size: currentFrame.data.byteLength, + duration: 1024 // For AAC audio, all samples contain 1024 samples + }); + } + return samples; + }; + + // generate the track's sample table from an array of frames + this.concatenateFrameData_ = function (frames) { + var i, + currentFrame, + dataOffset = 0, + data = new Uint8Array(sumFrameByteLengths(frames)); + + for (i = 0; i < frames.length; i++) { + currentFrame = frames[i]; + + data.set(currentFrame.data, dataOffset); + dataOffset += currentFrame.data.byteLength; + } + return data; + }; + }; + + _AudioSegmentStream.prototype = new stream(); + + /** + * Constructs a single-track, ISO BMFF media segment from H264 data + * events. The output of this stream can be fed to a SourceBuffer + * configured with a suitable initialization segment. + * @param track {object} track metadata configuration + * @param options {object} transmuxer options object + * @param options.alignGopsAtEnd {boolean} If true, start from the end of the + * gopsToAlignWith list when attempting to align gop pts + * @param options.keepOriginalTimestamps {boolean} If true, keep the timestamps + * in the source; false to adjust the first segment to start at 0. + */ + _VideoSegmentStream = function VideoSegmentStream(track, options) { + var sequenceNumber = 0, + nalUnits = [], + gopsToAlignWith = [], + config, + pps; + + options = options || {}; + + _VideoSegmentStream.prototype.init.call(this); + + delete track.minPTS; + + this.gopCache_ = []; + + this.push = function (nalUnit) { + collectDtsInfo(track, nalUnit); + + // record the track config + if (nalUnit.nalUnitType === 'seq_parameter_set_rbsp' && !config) { + config = nalUnit.config; + track.sps = [nalUnit.data]; + + VIDEO_PROPERTIES.forEach(function (prop) { + track[prop] = config[prop]; + }, this); + } + + if (nalUnit.nalUnitType === 'pic_parameter_set_rbsp' && !pps) { + pps = nalUnit.data; + track.pps = [nalUnit.data]; + } + + // buffer video until flush() is called + nalUnits.push(nalUnit); + }; + + this.flush = function () { + var frames, gopForFusion, gops, moof, mdat, boxes; + + // Throw away nalUnits at the start of the byte stream until + // we find the first AUD + while (nalUnits.length) { + if (nalUnits[0].nalUnitType === 'access_unit_delimiter_rbsp') { + break; + } + nalUnits.shift(); + } + + // Return early if no video data has been observed + if (nalUnits.length === 0) { + this.resetStream_(); + this.trigger('done', 'VideoSegmentStream'); + return; + } + + // Organize the raw nal-units into arrays that represent + // higher-level constructs such as frames and gops + // (group-of-pictures) + frames = this.groupNalsIntoFrames_(nalUnits); + gops = this.groupFramesIntoGops_(frames); + + // If the first frame of this fragment is not a keyframe we have + // a problem since MSE (on Chrome) requires a leading keyframe. + // + // We have two approaches to repairing this situation: + // 1) GOP-FUSION: + // This is where we keep track of the GOPS (group-of-pictures) + // from previous fragments and attempt to find one that we can + // prepend to the current fragment in order to create a valid + // fragment. + // 2) KEYFRAME-PULLING: + // Here we search for the first keyframe in the fragment and + // throw away all the frames between the start of the fragment + // and that keyframe. We then extend the duration and pull the + // PTS of the keyframe forward so that it covers the time range + // of the frames that were disposed of. + // + // #1 is far prefereable over #2 which can cause "stuttering" but + // requires more things to be just right. + if (!gops[0][0].keyFrame) { + // Search for a gop for fusion from our gopCache + gopForFusion = this.getGopForFusion_(nalUnits[0], track); + + if (gopForFusion) { + gops.unshift(gopForFusion); + // Adjust Gops' metadata to account for the inclusion of the + // new gop at the beginning + gops.byteLength += gopForFusion.byteLength; + gops.nalCount += gopForFusion.nalCount; + gops.pts = gopForFusion.pts; + gops.dts = gopForFusion.dts; + gops.duration += gopForFusion.duration; + } else { + // If we didn't find a candidate gop fall back to keyframe-pulling + gops = this.extendFirstKeyFrame_(gops); + } + } + + // Trim gops to align with gopsToAlignWith + if (gopsToAlignWith.length) { + var alignedGops; + + if (options.alignGopsAtEnd) { + alignedGops = this.alignGopsAtEnd_(gops); + } else { + alignedGops = this.alignGopsAtStart_(gops); + } + + if (!alignedGops) { + // save all the nals in the last GOP into the gop cache + this.gopCache_.unshift({ + gop: gops.pop(), + pps: track.pps, + sps: track.sps + }); + + // Keep a maximum of 6 GOPs in the cache + this.gopCache_.length = Math.min(6, this.gopCache_.length); + + // Clear nalUnits + nalUnits = []; + + // return early no gops can be aligned with desired gopsToAlignWith + this.resetStream_(); + this.trigger('done', 'VideoSegmentStream'); + return; + } + + // Some gops were trimmed. clear dts info so minSegmentDts and pts are correct + // when recalculated before sending off to CoalesceStream + clearDtsInfo(track); + + gops = alignedGops; + } + + collectDtsInfo(track, gops); + + // First, we have to build the index from byte locations to + // samples (that is, frames) in the video data + track.samples = this.generateSampleTable_(gops); + + // Concatenate the video data and construct the mdat + mdat = mp4Generator.mdat(this.concatenateNalData_(gops)); + + track.baseMediaDecodeTime = calculateTrackBaseMediaDecodeTime(track, options.keepOriginalTimestamps); + + this.trigger('processedGopsInfo', gops.map(function (gop) { + return { + pts: gop.pts, + dts: gop.dts, + byteLength: gop.byteLength + }; + })); + + // save all the nals in the last GOP into the gop cache + this.gopCache_.unshift({ + gop: gops.pop(), + pps: track.pps, + sps: track.sps + }); + + // Keep a maximum of 6 GOPs in the cache + this.gopCache_.length = Math.min(6, this.gopCache_.length); + + // Clear nalUnits + nalUnits = []; + + this.trigger('baseMediaDecodeTime', track.baseMediaDecodeTime); + this.trigger('timelineStartInfo', track.timelineStartInfo); + + moof = mp4Generator.moof(sequenceNumber, [track]); + + // it would be great to allocate this array up front instead of + // throwing away hundreds of media segment fragments + boxes = new Uint8Array(moof.byteLength + mdat.byteLength); + + // Bump the sequence number for next time + sequenceNumber++; + + boxes.set(moof); + boxes.set(mdat, moof.byteLength); + + this.trigger('data', {track: track, boxes: boxes}); + + this.resetStream_(); + + // Continue with the flush process now + this.trigger('done', 'VideoSegmentStream'); + }; + + this.resetStream_ = function () { + clearDtsInfo(track); + + // reset config and pps because they may differ across segments + // for instance, when we are rendition switching + config = undefined; + pps = undefined; + }; + + // Search for a candidate Gop for gop-fusion from the gop cache and + // return it or return null if no good candidate was found + this.getGopForFusion_ = function (nalUnit) { + var halfSecond = 45000, + + // Half-a-second in a 90khz clock + allowableOverlap = 10000, + + // About 3 frames @ 30fps + nearestDistance = Infinity, + dtsDistance, + nearestGopObj, + currentGop, + currentGopObj, + i; + + // Search for the GOP nearest to the beginning of this nal unit + for (i = 0; i < this.gopCache_.length; i++) { + currentGopObj = this.gopCache_[i]; + currentGop = currentGopObj.gop; + + // Reject Gops with different SPS or PPS + if (!(track.pps && arrayEquals(track.pps[0], currentGopObj.pps[0])) || !(track.sps && arrayEquals(track.sps[0], currentGopObj.sps[0]))) { + continue; + } + + // Reject Gops that would require a negative baseMediaDecodeTime + if (currentGop.dts < track.timelineStartInfo.dts) { + continue; + } + + // The distance between the end of the gop and the start of the nalUnit + dtsDistance = nalUnit.dts - currentGop.dts - currentGop.duration; + + // Only consider GOPS that start before the nal unit and end within + // a half-second of the nal unit + if (dtsDistance >= -allowableOverlap && dtsDistance <= halfSecond) { + + // Always use the closest GOP we found if there is more than + // one candidate + if (!nearestGopObj || nearestDistance > dtsDistance) { + nearestGopObj = currentGopObj; + nearestDistance = dtsDistance; + } + } + } + + if (nearestGopObj) { + return nearestGopObj.gop; + } + return null; + }; + + this.extendFirstKeyFrame_ = function (gops) { + var currentGop; + + if (!gops[0][0].keyFrame && gops.length > 1) { + // Remove the first GOP + currentGop = gops.shift(); + + gops.byteLength -= currentGop.byteLength; + gops.nalCount -= currentGop.nalCount; + + // Extend the first frame of what is now the + // first gop to cover the time period of the + // frames we just removed + gops[0][0].dts = currentGop.dts; + gops[0][0].pts = currentGop.pts; + gops[0][0].duration += currentGop.duration; + } + + return gops; + }; + + // Convert an array of nal units into an array of frames with each frame being + // composed of the nal units that make up that frame + // Also keep track of cummulative data about the frame from the nal units such + // as the frame duration, starting pts, etc. + this.groupNalsIntoFrames_ = function (nalUnits) { + var i, + currentNal, + currentFrame = [], + frames = []; + + currentFrame.byteLength = 0; + + for (i = 0; i < nalUnits.length; i++) { + currentNal = nalUnits[i]; + + // Split on 'aud'-type nal units + if (currentNal.nalUnitType === 'access_unit_delimiter_rbsp') { + // Since the very first nal unit is expected to be an AUD + // only push to the frames array when currentFrame is not empty + if (currentFrame.length) { + currentFrame.duration = currentNal.dts - currentFrame.dts; + frames.push(currentFrame); + } + currentFrame = [currentNal]; + currentFrame.byteLength = currentNal.data.byteLength; + currentFrame.pts = currentNal.pts; + currentFrame.dts = currentNal.dts; + } else { + // Specifically flag key frames for ease of use later + if (currentNal.nalUnitType === 'slice_layer_without_partitioning_rbsp_idr') { + currentFrame.keyFrame = true; + } + currentFrame.duration = currentNal.dts - currentFrame.dts; + currentFrame.byteLength += currentNal.data.byteLength; + currentFrame.push(currentNal); + } + } + + // For the last frame, use the duration of the previous frame if we + // have nothing better to go on + if (frames.length && (!currentFrame.duration || currentFrame.duration <= 0)) { + currentFrame.duration = frames[frames.length - 1].duration; + } + + // Push the final frame + frames.push(currentFrame); + return frames; + }; + + // Convert an array of frames into an array of Gop with each Gop being composed + // of the frames that make up that Gop + // Also keep track of cummulative data about the Gop from the frames such as the + // Gop duration, starting pts, etc. + this.groupFramesIntoGops_ = function (frames) { + var i, + currentFrame, + currentGop = [], + gops = []; + + // We must pre-set some of the values on the Gop since we + // keep running totals of these values + currentGop.byteLength = 0; + currentGop.nalCount = 0; + currentGop.duration = 0; + currentGop.pts = frames[0].pts; + currentGop.dts = frames[0].dts; + + // store some metadata about all the Gops + gops.byteLength = 0; + gops.nalCount = 0; + gops.duration = 0; + gops.pts = frames[0].pts; + gops.dts = frames[0].dts; + + for (i = 0; i < frames.length; i++) { + currentFrame = frames[i]; + + if (currentFrame.keyFrame) { + // Since the very first frame is expected to be an keyframe + // only push to the gops array when currentGop is not empty + if (currentGop.length) { + gops.push(currentGop); + gops.byteLength += currentGop.byteLength; + gops.nalCount += currentGop.nalCount; + gops.duration += currentGop.duration; + } + + currentGop = [currentFrame]; + currentGop.nalCount = currentFrame.length; + currentGop.byteLength = currentFrame.byteLength; + currentGop.pts = currentFrame.pts; + currentGop.dts = currentFrame.dts; + currentGop.duration = currentFrame.duration; + } else { + currentGop.duration += currentFrame.duration; + currentGop.nalCount += currentFrame.length; + currentGop.byteLength += currentFrame.byteLength; + currentGop.push(currentFrame); + } + } + + if (gops.length && currentGop.duration <= 0) { + currentGop.duration = gops[gops.length - 1].duration; + } + gops.byteLength += currentGop.byteLength; + gops.nalCount += currentGop.nalCount; + gops.duration += currentGop.duration; + + // push the final Gop + gops.push(currentGop); + return gops; + }; + + // generate the track's sample table from an array of gops + this.generateSampleTable_ = function (gops, baseDataOffset) { + var h, + i, + sample, + currentGop, + currentFrame, + dataOffset = baseDataOffset || 0, + samples = []; + + for (h = 0; h < gops.length; h++) { + currentGop = gops[h]; + + for (i = 0; i < currentGop.length; i++) { + currentFrame = currentGop[i]; + + sample = createDefaultSample(); + + sample.dataOffset = dataOffset; + sample.compositionTimeOffset = currentFrame.pts - currentFrame.dts; + sample.duration = currentFrame.duration; + sample.size = 4 * currentFrame.length; // Space for nal unit size + sample.size += currentFrame.byteLength; + + if (currentFrame.keyFrame) { + sample.flags.dependsOn = 2; + } + + dataOffset += sample.size; + + samples.push(sample); + } + } + return samples; + }; + + // generate the track's raw mdat data from an array of gops + this.concatenateNalData_ = function (gops) { + var h, + i, + j, + currentGop, + currentFrame, + currentNal, + dataOffset = 0, + nalsByteLength = gops.byteLength, + numberOfNals = gops.nalCount, + totalByteLength = nalsByteLength + 4 * numberOfNals, + data = new Uint8Array(totalByteLength), + view = new DataView(data.buffer); + + // For each Gop.. + for (h = 0; h < gops.length; h++) { + currentGop = gops[h]; + + // For each Frame.. + for (i = 0; i < currentGop.length; i++) { + currentFrame = currentGop[i]; + + // For each NAL.. + for (j = 0; j < currentFrame.length; j++) { + currentNal = currentFrame[j]; + + view.setUint32(dataOffset, currentNal.data.byteLength); + dataOffset += 4; + data.set(currentNal.data, dataOffset); + dataOffset += currentNal.data.byteLength; + } + } + } + return data; + }; + + // trim gop list to the first gop found that has a matching pts with a gop in the list + // of gopsToAlignWith starting from the START of the list + this.alignGopsAtStart_ = function (gops) { + var alignIndex, gopIndex, align, gop, byteLength, nalCount, duration, alignedGops; + + byteLength = gops.byteLength; + nalCount = gops.nalCount; + duration = gops.duration; + alignIndex = gopIndex = 0; + + while (alignIndex < gopsToAlignWith.length && gopIndex < gops.length) { + align = gopsToAlignWith[alignIndex]; + gop = gops[gopIndex]; + + if (align.pts === gop.pts) { + break; + } + + if (gop.pts > align.pts) { + // this current gop starts after the current gop we want to align on, so increment + // align index + alignIndex++; + continue; + } + + // current gop starts before the current gop we want to align on. so increment gop + // index + gopIndex++; + byteLength -= gop.byteLength; + nalCount -= gop.nalCount; + duration -= gop.duration; + } + + if (gopIndex === 0) { + // no gops to trim + return gops; + } + + if (gopIndex === gops.length) { + // all gops trimmed, skip appending all gops + return null; + } + + alignedGops = gops.slice(gopIndex); + alignedGops.byteLength = byteLength; + alignedGops.duration = duration; + alignedGops.nalCount = nalCount; + alignedGops.pts = alignedGops[0].pts; + alignedGops.dts = alignedGops[0].dts; + + return alignedGops; + }; + + // trim gop list to the first gop found that has a matching pts with a gop in the list + // of gopsToAlignWith starting from the END of the list + this.alignGopsAtEnd_ = function (gops) { + var alignIndex, gopIndex, align, gop, alignEndIndex, matchFound; + + alignIndex = gopsToAlignWith.length - 1; + gopIndex = gops.length - 1; + alignEndIndex = null; + matchFound = false; + + while (alignIndex >= 0 && gopIndex >= 0) { + align = gopsToAlignWith[alignIndex]; + gop = gops[gopIndex]; + + if (align.pts === gop.pts) { + matchFound = true; + break; + } + + if (align.pts > gop.pts) { + alignIndex--; + continue; + } + + if (alignIndex === gopsToAlignWith.length - 1) { + // gop.pts is greater than the last alignment candidate. If no match is found + // by the end of this loop, we still want to append gops that come after this + // point + alignEndIndex = gopIndex; + } + + gopIndex--; + } + + if (!matchFound && alignEndIndex === null) { + return null; + } + + var trimIndex; + + if (matchFound) { + trimIndex = gopIndex; + } else { + trimIndex = alignEndIndex; + } + + if (trimIndex === 0) { + return gops; + } + + var alignedGops = gops.slice(trimIndex); + var metadata = alignedGops.reduce(function (total, gop) { + total.byteLength += gop.byteLength; + total.duration += gop.duration; + total.nalCount += gop.nalCount; + return total; + }, {byteLength: 0, duration: 0, nalCount: 0}); + + alignedGops.byteLength = metadata.byteLength; + alignedGops.duration = metadata.duration; + alignedGops.nalCount = metadata.nalCount; + alignedGops.pts = alignedGops[0].pts; + alignedGops.dts = alignedGops[0].dts; + + return alignedGops; + }; + + this.alignGopsWith = function (newGopsToAlignWith) { + gopsToAlignWith = newGopsToAlignWith; + }; + }; + + _VideoSegmentStream.prototype = new stream(); + + /** + * Store information about the start and end of the track and the + * duration for each frame/sample we process in order to calculate + * the baseMediaDecodeTime + */ + collectDtsInfo = function collectDtsInfo(track, data) { + if (typeof data.pts === 'number') { + if (track.timelineStartInfo.pts === undefined) { + track.timelineStartInfo.pts = data.pts; + } + + if (track.minSegmentPts === undefined) { + track.minSegmentPts = data.pts; + } else { + track.minSegmentPts = Math.min(track.minSegmentPts, data.pts); + } + + if (track.maxSegmentPts === undefined) { + track.maxSegmentPts = data.pts; + } else { + track.maxSegmentPts = Math.max(track.maxSegmentPts, data.pts); + } + } + + if (typeof data.dts === 'number') { + if (track.timelineStartInfo.dts === undefined) { + track.timelineStartInfo.dts = data.dts; + } + + if (track.minSegmentDts === undefined) { + track.minSegmentDts = data.dts; + } else { + track.minSegmentDts = Math.min(track.minSegmentDts, data.dts); + } + + if (track.maxSegmentDts === undefined) { + track.maxSegmentDts = data.dts; + } else { + track.maxSegmentDts = Math.max(track.maxSegmentDts, data.dts); + } + } + }; + + /** + * Clear values used to calculate the baseMediaDecodeTime between + * tracks + */ + clearDtsInfo = function clearDtsInfo(track) { + delete track.minSegmentDts; + delete track.maxSegmentDts; + delete track.minSegmentPts; + delete track.maxSegmentPts; + }; + + /** + * Calculate the track's baseMediaDecodeTime based on the earliest + * DTS the transmuxer has ever seen and the minimum DTS for the + * current track + * @param track {object} track metadata configuration + * @param keepOriginalTimestamps {boolean} If true, keep the timestamps + * in the source; false to adjust the first segment to start at 0. + */ + calculateTrackBaseMediaDecodeTime = function calculateTrackBaseMediaDecodeTime(track, keepOriginalTimestamps) { + var baseMediaDecodeTime, + scale, + minSegmentDts = track.minSegmentDts; + + // Optionally adjust the time so the first segment starts at zero. + if (!keepOriginalTimestamps) { + minSegmentDts -= track.timelineStartInfo.dts; + } + + // track.timelineStartInfo.baseMediaDecodeTime is the location, in time, where + // we want the start of the first segment to be placed + baseMediaDecodeTime = track.timelineStartInfo.baseMediaDecodeTime; + + // Add to that the distance this segment is from the very first + baseMediaDecodeTime += minSegmentDts; + + // baseMediaDecodeTime must not become negative + baseMediaDecodeTime = Math.max(0, baseMediaDecodeTime); + + if (track.type === 'audio') { + // Audio has a different clock equal to the sampling_rate so we need to + // scale the PTS values into the clock rate of the track + scale = track.samplerate / ONE_SECOND_IN_TS$1; + baseMediaDecodeTime *= scale; + baseMediaDecodeTime = Math.floor(baseMediaDecodeTime); + } + + return baseMediaDecodeTime; + }; + + /** + * A Stream that can combine multiple streams (ie. audio & video) + * into a single output segment for MSE. Also supports audio-only + * and video-only streams. + */ + _CoalesceStream = function CoalesceStream(options, metadataStream) { + // Number of Tracks per output segment + // If greater than 1, we combine multiple + // tracks into a single segment + this.numberOfTracks = 0; + this.metadataStream = metadataStream; + + if (typeof options.remux !== 'undefined') { + this.remuxTracks = !!options.remux; + } else { + this.remuxTracks = true; + } + + this.pendingTracks = []; + this.videoTrack = null; + this.pendingBoxes = []; + this.pendingCaptions = []; + this.pendingMetadata = []; + this.pendingBytes = 0; + this.emittedTracks = 0; + + _CoalesceStream.prototype.init.call(this); + + // Take output from multiple + this.push = function (output) { + // buffer incoming captions until the associated video segment + // finishes + if (output.text) { + return this.pendingCaptions.push(output); + } + // buffer incoming id3 tags until the final flush + if (output.frames) { + return this.pendingMetadata.push(output); + } + + // Add this track to the list of pending tracks and store + // important information required for the construction of + // the final segment + this.pendingTracks.push(output.track); + this.pendingBoxes.push(output.boxes); + this.pendingBytes += output.boxes.byteLength; + + if (output.track.type === 'video') { + this.videoTrack = output.track; + } + if (output.track.type === 'audio') { + this.audioTrack = output.track; + } + }; + }; + + _CoalesceStream.prototype = new stream(); + _CoalesceStream.prototype.flush = function (flushSource) { + var offset = 0, + event = { + captions: [], + captionStreams: {}, + metadata: [], + info: {} + }, + caption, + id3, + initSegment, + timelineStartPts = 0, + i; + + if (this.pendingTracks.length < this.numberOfTracks) { + if (flushSource !== 'VideoSegmentStream' && flushSource !== 'AudioSegmentStream') { + // Return because we haven't received a flush from a data-generating + // portion of the segment (meaning that we have only recieved meta-data + // or captions.) + return; + } else if (this.remuxTracks) { + // Return until we have enough tracks from the pipeline to remux (if we + // are remuxing audio and video into a single MP4) + return; + } else if (this.pendingTracks.length === 0) { + // In the case where we receive a flush without any data having been + // received we consider it an emitted track for the purposes of coalescing + // `done` events. + // We do this for the case where there is an audio and video track in the + // segment but no audio data. (seen in several playlists with alternate + // audio tracks and no audio present in the main TS segments.) + this.emittedTracks++; + + if (this.emittedTracks >= this.numberOfTracks) { + this.trigger('done'); + this.emittedTracks = 0; + } + return; + } + } + + if (this.videoTrack) { + timelineStartPts = this.videoTrack.timelineStartInfo.pts; + VIDEO_PROPERTIES.forEach(function (prop) { + event.info[prop] = this.videoTrack[prop]; + }, this); + } else if (this.audioTrack) { + timelineStartPts = this.audioTrack.timelineStartInfo.pts; + AUDIO_PROPERTIES.forEach(function (prop) { + event.info[prop] = this.audioTrack[prop]; + }, this); + } + + if (this.pendingTracks.length === 1) { + event.type = this.pendingTracks[0].type; + } else { + event.type = 'combined'; + } + + this.emittedTracks += this.pendingTracks.length; + + initSegment = mp4Generator.initSegment(this.pendingTracks); + + // Create a new typed array to hold the init segment + event.initSegment = new Uint8Array(initSegment.byteLength); + + // Create an init segment containing a moov + // and track definitions + event.initSegment.set(initSegment); + + // Create a new typed array to hold the moof+mdats + event.data = new Uint8Array(this.pendingBytes); + + // Append each moof+mdat (one per track) together + for (i = 0; i < this.pendingBoxes.length; i++) { + event.data.set(this.pendingBoxes[i], offset); + offset += this.pendingBoxes[i].byteLength; + } + + // Translate caption PTS times into second offsets into the + // video timeline for the segment, and add track info + for (i = 0; i < this.pendingCaptions.length; i++) { + caption = this.pendingCaptions[i]; + caption.startTime = caption.startPts - timelineStartPts; + caption.startTime /= 90e3; + caption.endTime = caption.endPts - timelineStartPts; + caption.endTime /= 90e3; + event.captionStreams[caption.stream] = true; + event.captions.push(caption); + } + + // Translate ID3 frame PTS times into second offsets into the + // video timeline for the segment + for (i = 0; i < this.pendingMetadata.length; i++) { + id3 = this.pendingMetadata[i]; + id3.cueTime = id3.pts - timelineStartPts; + id3.cueTime /= 90e3; + event.metadata.push(id3); + } + // We add this to every single emitted segment even though we only need + // it for the first + event.metadata.dispatchType = this.metadataStream.dispatchType; + + // Reset stream state + this.pendingTracks.length = 0; + this.videoTrack = null; + this.pendingBoxes.length = 0; + this.pendingCaptions.length = 0; + this.pendingBytes = 0; + this.pendingMetadata.length = 0; + + // Emit the built segment + this.trigger('data', event); + + // Only emit `done` if all tracks have been flushed and emitted + if (this.emittedTracks >= this.numberOfTracks) { + this.trigger('done'); + this.emittedTracks = 0; + } + }; + /** + * A Stream that expects MP2T binary data as input and produces + * corresponding media segments, suitable for use with Media Source + * Extension (MSE) implementations that support the ISO BMFF byte + * stream format, like Chrome. + */ + _Transmuxer = function Transmuxer(options) { + var self = this, + hasFlushed = true, + videoTrack, + audioTrack; + + _Transmuxer.prototype.init.call(this); + + options = options || {}; + this.baseMediaDecodeTime = options.baseMediaDecodeTime || 0; + this.transmuxPipeline_ = {}; + + this.setupAacPipeline = function () { + var pipeline = {}; + this.transmuxPipeline_ = pipeline; + + pipeline.type = 'aac'; + pipeline.metadataStream = new m2ts_1.MetadataStream(); + + // set up the parsing pipeline + pipeline.aacStream = new aac(); + pipeline.audioTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('audio'); + pipeline.timedMetadataTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('timed-metadata'); + pipeline.adtsStream = new adts(); + pipeline.coalesceStream = new _CoalesceStream(options, pipeline.metadataStream); + pipeline.headOfPipeline = pipeline.aacStream; + + pipeline.aacStream.pipe(pipeline.audioTimestampRolloverStream).pipe(pipeline.adtsStream); + pipeline.aacStream.pipe(pipeline.timedMetadataTimestampRolloverStream).pipe(pipeline.metadataStream).pipe(pipeline.coalesceStream); + + pipeline.metadataStream.on('timestamp', function (frame) { + pipeline.aacStream.setTimestamp(frame.timeStamp); + }); + + pipeline.aacStream.on('data', function (data) { + if (data.type === 'timed-metadata' && !pipeline.audioSegmentStream) { + audioTrack = audioTrack || { + timelineStartInfo: { + baseMediaDecodeTime: self.baseMediaDecodeTime + }, + codec: 'adts', + type: 'audio' + }; + // hook up the audio segment stream to the first track with aac data + pipeline.coalesceStream.numberOfTracks++; + pipeline.audioSegmentStream = new _AudioSegmentStream(audioTrack, options); + // Set up the final part of the audio pipeline + pipeline.adtsStream.pipe(pipeline.audioSegmentStream).pipe(pipeline.coalesceStream); + } + }); + + // Re-emit any data coming from the coalesce stream to the outside world + pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data')); + // Let the consumer know we have finished flushing the entire pipeline + pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done')); + }; + + this.setupTsPipeline = function () { + var pipeline = {}; + this.transmuxPipeline_ = pipeline; + + pipeline.type = 'ts'; + pipeline.metadataStream = new m2ts_1.MetadataStream(); + + // set up the parsing pipeline + pipeline.packetStream = new m2ts_1.TransportPacketStream(); + pipeline.parseStream = new m2ts_1.TransportParseStream(); + pipeline.elementaryStream = new m2ts_1.ElementaryStream(); + pipeline.videoTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('video'); + pipeline.audioTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('audio'); + pipeline.timedMetadataTimestampRolloverStream = new m2ts_1.TimestampRolloverStream('timed-metadata'); + pipeline.adtsStream = new adts(); + pipeline.h264Stream = new H264Stream(); + pipeline.captionStream = new m2ts_1.CaptionStream(); + pipeline.coalesceStream = new _CoalesceStream(options, pipeline.metadataStream); + pipeline.headOfPipeline = pipeline.packetStream; + + // disassemble MPEG2-TS packets into elementary streams + pipeline.packetStream.pipe(pipeline.parseStream).pipe(pipeline.elementaryStream); + + // !!THIS ORDER IS IMPORTANT!! + // demux the streams + pipeline.elementaryStream.pipe(pipeline.videoTimestampRolloverStream).pipe(pipeline.h264Stream); + pipeline.elementaryStream.pipe(pipeline.audioTimestampRolloverStream).pipe(pipeline.adtsStream); + + pipeline.elementaryStream.pipe(pipeline.timedMetadataTimestampRolloverStream).pipe(pipeline.metadataStream).pipe(pipeline.coalesceStream); + + // Hook up CEA-608/708 caption stream + pipeline.h264Stream.pipe(pipeline.captionStream).pipe(pipeline.coalesceStream); + + pipeline.elementaryStream.on('data', function (data) { + var i; + + if (data.type === 'metadata') { + i = data.tracks.length; + + // scan the tracks listed in the metadata + while (i--) { + if (!videoTrack && data.tracks[i].type === 'video') { + videoTrack = data.tracks[i]; + videoTrack.timelineStartInfo.baseMediaDecodeTime = self.baseMediaDecodeTime; + } else if (!audioTrack && data.tracks[i].type === 'audio') { + audioTrack = data.tracks[i]; + audioTrack.timelineStartInfo.baseMediaDecodeTime = self.baseMediaDecodeTime; + } + } + + // hook up the video segment stream to the first track with h264 data + if (videoTrack && !pipeline.videoSegmentStream) { + pipeline.coalesceStream.numberOfTracks++; + pipeline.videoSegmentStream = new _VideoSegmentStream(videoTrack, options); + + pipeline.videoSegmentStream.on('timelineStartInfo', function (timelineStartInfo) { + // When video emits timelineStartInfo data after a flush, we forward that + // info to the AudioSegmentStream, if it exists, because video timeline + // data takes precedence. + if (audioTrack) { + audioTrack.timelineStartInfo = timelineStartInfo; + // On the first segment we trim AAC frames that exist before the + // very earliest DTS we have seen in video because Chrome will + // interpret any video track with a baseMediaDecodeTime that is + // non-zero as a gap. + pipeline.audioSegmentStream.setEarliestDts(timelineStartInfo.dts); + } + }); + + pipeline.videoSegmentStream.on('processedGopsInfo', self.trigger.bind(self, 'gopInfo')); + + pipeline.videoSegmentStream.on('baseMediaDecodeTime', function (baseMediaDecodeTime) { + if (audioTrack) { + pipeline.audioSegmentStream.setVideoBaseMediaDecodeTime(baseMediaDecodeTime); + } + }); + + // Set up the final part of the video pipeline + pipeline.h264Stream.pipe(pipeline.videoSegmentStream).pipe(pipeline.coalesceStream); + } + + if (audioTrack && !pipeline.audioSegmentStream) { + // hook up the audio segment stream to the first track with aac data + pipeline.coalesceStream.numberOfTracks++; + pipeline.audioSegmentStream = new _AudioSegmentStream(audioTrack, options); + + // Set up the final part of the audio pipeline + pipeline.adtsStream.pipe(pipeline.audioSegmentStream).pipe(pipeline.coalesceStream); + } + } + }); + + // Re-emit any data coming from the coalesce stream to the outside world + pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data')); + // Let the consumer know we have finished flushing the entire pipeline + pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done')); + }; + + // hook up the segment streams once track metadata is delivered + this.setBaseMediaDecodeTime = function (baseMediaDecodeTime) { + var pipeline = this.transmuxPipeline_; + + this.baseMediaDecodeTime = baseMediaDecodeTime; + if (audioTrack) { + audioTrack.timelineStartInfo.dts = undefined; + audioTrack.timelineStartInfo.pts = undefined; + clearDtsInfo(audioTrack); + audioTrack.timelineStartInfo.baseMediaDecodeTime = baseMediaDecodeTime; + if (pipeline.audioTimestampRolloverStream) { + pipeline.audioTimestampRolloverStream.discontinuity(); + } + } + if (videoTrack) { + if (pipeline.videoSegmentStream) { + pipeline.videoSegmentStream.gopCache_ = []; + pipeline.videoTimestampRolloverStream.discontinuity(); + } + videoTrack.timelineStartInfo.dts = undefined; + videoTrack.timelineStartInfo.pts = undefined; + clearDtsInfo(videoTrack); + pipeline.captionStream.reset(); + videoTrack.timelineStartInfo.baseMediaDecodeTime = baseMediaDecodeTime; + } + + if (pipeline.timedMetadataTimestampRolloverStream) { + pipeline.timedMetadataTimestampRolloverStream.discontinuity(); + } + }; + + this.setAudioAppendStart = function (timestamp) { + if (audioTrack) { + this.transmuxPipeline_.audioSegmentStream.setAudioAppendStart(timestamp); + } + }; + + this.alignGopsWith = function (gopsToAlignWith) { + if (videoTrack && this.transmuxPipeline_.videoSegmentStream) { + this.transmuxPipeline_.videoSegmentStream.alignGopsWith(gopsToAlignWith); + } + }; + + // feed incoming data to the front of the parsing pipeline + this.push = function (data) { + if (hasFlushed) { + var isAac = isLikelyAacData(data); + + if (isAac && this.transmuxPipeline_.type !== 'aac') { + this.setupAacPipeline(); + } else if (!isAac && this.transmuxPipeline_.type !== 'ts') { + this.setupTsPipeline(); + } + hasFlushed = false; + } + this.transmuxPipeline_.headOfPipeline.push(data); + }; + + // flush any buffered data + this.flush = function () { + hasFlushed = true; + // Start at the top of the pipeline and flush all pending work + this.transmuxPipeline_.headOfPipeline.flush(); + }; + + // Caption data has to be reset when seeking outside buffered range + this.resetCaptions = function () { + if (this.transmuxPipeline_.captionStream) { + this.transmuxPipeline_.captionStream.reset(); + } + }; + }; + _Transmuxer.prototype = new stream(); + + var transmuxer = { + Transmuxer: _Transmuxer, + VideoSegmentStream: _VideoSegmentStream, + AudioSegmentStream: _AudioSegmentStream, + AUDIO_PROPERTIES: AUDIO_PROPERTIES, + VIDEO_PROPERTIES: VIDEO_PROPERTIES + }; + + var mp4 = { + generator: mp4Generator, + Transmuxer: transmuxer.Transmuxer, + AudioSegmentStream: transmuxer.AudioSegmentStream, + VideoSegmentStream: transmuxer.VideoSegmentStream + }; + + var classCallCheck$$1 = function classCallCheck$$1(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var createClass$$1 = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + /** + * @file transmuxer-worker.js + */ + + /** + * Re-emits transmuxer events by converting them into messages to the + * world outside the worker. + * + * @param {Object} transmuxer the transmuxer to wire events on + * @private + */ + var wireTransmuxerEvents = function wireTransmuxerEvents(transmuxer) { + transmuxer.on('data', function (segment) { + // transfer ownership of the underlying ArrayBuffer + // instead of doing a copy to save memory + // ArrayBuffers are transferable but generic TypedArrays are not + // @link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Passing_data_by_transferring_ownership_(transferable_objects) + var initArray = segment.initSegment; + + segment.initSegment = { + data: initArray.buffer, + byteOffset: initArray.byteOffset, + byteLength: initArray.byteLength + }; + + var typedArray = segment.data; + + segment.data = typedArray.buffer; + window_1$$1.postMessage({ + action: 'data', + segment: segment, + byteOffset: typedArray.byteOffset, + byteLength: typedArray.byteLength + }, [segment.data]); + }); + + if (transmuxer.captionStream) { + transmuxer.captionStream.on('data', function (caption) { + window_1$$1.postMessage({ + action: 'caption', + data: caption + }); + }); + } + + transmuxer.on('done', function (data) { + window_1$$1.postMessage({action: 'done'}); + }); + + transmuxer.on('gopInfo', function (gopInfo) { + window_1$$1.postMessage({ + action: 'gopInfo', + gopInfo: gopInfo + }); + }); + }; + + /** + * All incoming messages route through this hash. If no function exists + * to handle an incoming message, then we ignore the message. + * + * @class MessageHandlers + * @param {Object} options the options to initialize with + */ + + var MessageHandlers = function () { + function MessageHandlers(options) { + classCallCheck$$1(this, MessageHandlers); + + this.options = options || {}; + this.init(); + } + + /** + * initialize our web worker and wire all the events. + */ + + createClass$$1(MessageHandlers, [{ + key: 'init', + value: function init() { + if (this.transmuxer) { + this.transmuxer.dispose(); + } + this.transmuxer = new mp4.Transmuxer(this.options); + wireTransmuxerEvents(this.transmuxer); + } + + /** + * Adds data (a ts segment) to the start of the transmuxer pipeline for + * processing. + * + * @param {ArrayBuffer} data data to push into the muxer + */ + + }, { + key: 'push', + value: function push(data) { + // Cast array buffer to correct type for transmuxer + var segment = new Uint8Array(data.data, data.byteOffset, data.byteLength); + + this.transmuxer.push(segment); + } + + /** + * Recreate the transmuxer so that the next segment added via `push` + * start with a fresh transmuxer. + */ + + }, { + key: 'reset', + value: function reset() { + this.init(); + } + + /** + * Set the value that will be used as the `baseMediaDecodeTime` time for the + * next segment pushed in. Subsequent segments will have their `baseMediaDecodeTime` + * set relative to the first based on the PTS values. + * + * @param {Object} data used to set the timestamp offset in the muxer + */ + + }, { + key: 'setTimestampOffset', + value: function setTimestampOffset(data) { + var timestampOffset = data.timestampOffset || 0; + + this.transmuxer.setBaseMediaDecodeTime(Math.round(timestampOffset * 90000)); + } + }, { + key: 'setAudioAppendStart', + value: function setAudioAppendStart(data) { + this.transmuxer.setAudioAppendStart(Math.ceil(data.appendStart * 90000)); + } + + /** + * Forces the pipeline to finish processing the last segment and emit it's + * results. + * + * @param {Object} data event data, not really used + */ + + }, { + key: 'flush', + value: function flush(data) { + this.transmuxer.flush(); + } + }, { + key: 'resetCaptions', + value: function resetCaptions() { + this.transmuxer.resetCaptions(); + } + }, { + key: 'alignGopsWith', + value: function alignGopsWith(data) { + this.transmuxer.alignGopsWith(data.gopsToAlignWith.slice()); + } + }]); + return MessageHandlers; + }(); + + /** + * Our web wroker interface so that things can talk to mux.js + * that will be running in a web worker. the scope is passed to this by + * webworkify. + * + * @param {Object} self the scope for the web worker + */ + + var TransmuxerWorker = function TransmuxerWorker(self) { + self.onmessage = function (event) { + if (event.data.action === 'init' && event.data.options) { + this.messageHandlers = new MessageHandlers(event.data.options); + return; + } + + if (!this.messageHandlers) { + this.messageHandlers = new MessageHandlers(); + } + + if (event.data && event.data.action && event.data.action !== 'init') { + if (this.messageHandlers[event.data.action]) { + this.messageHandlers[event.data.action](event.data); + } + } + }; + }; + + var transmuxerWorker = new TransmuxerWorker(self); + + return transmuxerWorker; + }(); + }); + + /** + * @file codec-utils.js + */ + + /** + * Check if a codec string refers to an audio codec. + * + * @param {String} codec codec string to check + * @return {Boolean} if this is an audio codec + * @private + */ + var isAudioCodec = function isAudioCodec(codec) { + return (/mp4a\.\d+.\d+/i.test(codec) + ); + }; + + /** + * Check if a codec string refers to a video codec. + * + * @param {String} codec codec string to check + * @return {Boolean} if this is a video codec + * @private + */ + var isVideoCodec = function isVideoCodec(codec) { + return (/avc1\.[\da-f]+/i.test(codec) + ); + }; + + /** + * Parse a content type header into a type and parameters + * object + * + * @param {String} type the content type header + * @return {Object} the parsed content-type + * @private + */ + var parseContentType = function parseContentType(type) { + var object = {type: '', parameters: {}}; + var parameters = type.trim().split(';'); + + // first parameter should always be content-type + object.type = parameters.shift().trim(); + parameters.forEach(function (parameter) { + var pair = parameter.trim().split('='); + + if (pair.length > 1) { + var name = pair[0].replace(/"/g, '').trim(); + var value = pair[1].replace(/"/g, '').trim(); + + object.parameters[name] = value; + } + }); + + return object; + }; + + /** + * Replace the old apple-style `avc1.<dd>.<dd>` codec string with the standard + * `avc1.<hhhhhh>` + * + * @param {Array} codecs an array of codec strings to fix + * @return {Array} the translated codec array + * @private + */ + var translateLegacyCodecs = function translateLegacyCodecs(codecs) { + return codecs.map(function (codec) { + return codec.replace(/avc1\.(\d+)\.(\d+)/i, function (orig, profile, avcLevel) { + var profileHex = ('00' + Number(profile).toString(16)).slice(-2); + var avcLevelHex = ('00' + Number(avcLevel).toString(16)).slice(-2); + + return 'avc1.' + profileHex + '00' + avcLevelHex; + }); + }); + }; + + /** + * @file virtual-source-buffer.js + */ + + // We create a wrapper around the SourceBuffer so that we can manage the + // state of the `updating` property manually. We have to do this because + // Firefox changes `updating` to false long before triggering `updateend` + // events and that was causing strange problems in videojs-contrib-hls + var makeWrappedSourceBuffer = function makeWrappedSourceBuffer(mediaSource, mimeType) { + var sourceBuffer = mediaSource.addSourceBuffer(mimeType); + var wrapper = Object.create(null); + + wrapper.updating = false; + wrapper.realBuffer_ = sourceBuffer; + + var _loop = function _loop(key) { + if (typeof sourceBuffer[key] === 'function') { + wrapper[key] = function () { + return sourceBuffer[key].apply(sourceBuffer, arguments); + }; + } else if (typeof wrapper[key] === 'undefined') { + Object.defineProperty(wrapper, key, { + get: function get$$1() { + return sourceBuffer[key]; + }, + set: function set$$1(v) { + return sourceBuffer[key] = v; + } + }); + } + }; + + for (var key in sourceBuffer) { + _loop(key); + } + + return wrapper; + }; + + /** + * Returns a list of gops in the buffer that have a pts value of 3 seconds or more in + * front of current time. + * + * @param {Array} buffer + * The current buffer of gop information + * @param {Player} player + * The player instance + * @param {Double} mapping + * Offset to map display time to stream presentation time + * @return {Array} + * List of gops considered safe to append over + */ + var gopsSafeToAlignWith = function gopsSafeToAlignWith(buffer, player, mapping) { + if (!player || !buffer.length) { + return []; + } + + // pts value for current time + 3 seconds to give a bit more wiggle room + var currentTimePts = Math.ceil((player.currentTime() - mapping + 3) * 90000); + + var i = void 0; + + for (i = 0; i < buffer.length; i++) { + if (buffer[i].pts > currentTimePts) { + break; + } + } + + return buffer.slice(i); + }; + + /** + * Appends gop information (timing and byteLength) received by the transmuxer for the + * gops appended in the last call to appendBuffer + * + * @param {Array} buffer + * The current buffer of gop information + * @param {Array} gops + * List of new gop information + * @param {boolean} replace + * If true, replace the buffer with the new gop information. If false, append the + * new gop information to the buffer in the right location of time. + * @return {Array} + * Updated list of gop information + */ + var updateGopBuffer = function updateGopBuffer(buffer, gops, replace) { + if (!gops.length) { + return buffer; + } + + if (replace) { + // If we are in safe append mode, then completely overwrite the gop buffer + // with the most recent appeneded data. This will make sure that when appending + // future segments, we only try to align with gops that are both ahead of current + // time and in the last segment appended. + return gops.slice(); + } + + var start = gops[0].pts; + + var i = 0; + + for (i; i < buffer.length; i++) { + if (buffer[i].pts >= start) { + break; + } + } + + return buffer.slice(0, i).concat(gops); + }; + + /** + * Removes gop information in buffer that overlaps with provided start and end + * + * @param {Array} buffer + * The current buffer of gop information + * @param {Double} start + * position to start the remove at + * @param {Double} end + * position to end the remove at + * @param {Double} mapping + * Offset to map display time to stream presentation time + */ + var removeGopBuffer = function removeGopBuffer(buffer, start, end, mapping) { + var startPts = Math.ceil((start - mapping) * 90000); + var endPts = Math.ceil((end - mapping) * 90000); + var updatedBuffer = buffer.slice(); + + var i = buffer.length; + + while (i--) { + if (buffer[i].pts <= endPts) { + break; + } + } + + if (i === -1) { + // no removal because end of remove range is before start of buffer + return updatedBuffer; + } + + var j = i + 1; + + while (j--) { + if (buffer[j].pts <= startPts) { + break; + } + } + + // clamp remove range start to 0 index + j = Math.max(j, 0); + + updatedBuffer.splice(j, i - j + 1); + + return updatedBuffer; + }; + + /** + * VirtualSourceBuffers exist so that we can transmux non native formats + * into a native format, but keep the same api as a native source buffer. + * It creates a transmuxer, that works in its own thread (a web worker) and + * that transmuxer muxes the data into a native format. VirtualSourceBuffer will + * then send all of that data to the naive sourcebuffer so that it is + * indestinguishable from a natively supported format. + * + * @param {HtmlMediaSource} mediaSource the parent mediaSource + * @param {Array} codecs array of codecs that we will be dealing with + * @class VirtualSourceBuffer + * @extends video.js.EventTarget + */ + + var VirtualSourceBuffer = function (_videojs$EventTarget) { + inherits(VirtualSourceBuffer, _videojs$EventTarget); + + function VirtualSourceBuffer(mediaSource, codecs) { + classCallCheck(this, VirtualSourceBuffer); + + var _this7 = possibleConstructorReturn(this, _videojs$EventTarget.call(this, videojs$1.EventTarget)); + + _this7.timestampOffset_ = 0; + _this7.pendingBuffers_ = []; + _this7.bufferUpdating_ = false; + + _this7.mediaSource_ = mediaSource; + _this7.codecs_ = codecs; + _this7.audioCodec_ = null; + _this7.videoCodec_ = null; + _this7.audioDisabled_ = false; + _this7.appendAudioInitSegment_ = true; + _this7.gopBuffer_ = []; + _this7.timeMapping_ = 0; + _this7.safeAppend_ = videojs$1.browser.IE_VERSION >= 11; + + var options = { + remux: false, + alignGopsAtEnd: _this7.safeAppend_ + }; + + _this7.codecs_.forEach(function (codec) { + if (isAudioCodec(codec)) { + _this7.audioCodec_ = codec; + } else if (isVideoCodec(codec)) { + _this7.videoCodec_ = codec; + } + }); + + // append muxed segments to their respective native buffers as + // soon as they are available + _this7.transmuxer_ = new TransmuxWorker(); + _this7.transmuxer_.postMessage({action: 'init', options: options}); + + _this7.transmuxer_.onmessage = function (event) { + if (event.data.action === 'data') { + return _this7.data_(event); + } + + if (event.data.action === 'done') { + return _this7.done_(event); + } + + if (event.data.action === 'gopInfo') { + return _this7.appendGopInfo_(event); + } + }; + + // this timestampOffset is a property with the side-effect of resetting + // baseMediaDecodeTime in the transmuxer on the setter + Object.defineProperty(_this7, 'timestampOffset', { + get: function get$$1() { + return this.timestampOffset_; + }, + set: function set$$1(val) { + if (typeof val === 'number' && val >= 0) { + this.timestampOffset_ = val; + this.appendAudioInitSegment_ = true; + + // reset gop buffer on timestampoffset as this signals a change in timeline + this.gopBuffer_.length = 0; + this.timeMapping_ = 0; + + // We have to tell the transmuxer to set the baseMediaDecodeTime to + // the desired timestampOffset for the next segment + this.transmuxer_.postMessage({ + action: 'setTimestampOffset', + timestampOffset: val + }); + } + } + }); + + // setting the append window affects both source buffers + Object.defineProperty(_this7, 'appendWindowStart', { + get: function get$$1() { + return (this.videoBuffer_ || this.audioBuffer_).appendWindowStart; + }, + set: function set$$1(start) { + if (this.videoBuffer_) { + this.videoBuffer_.appendWindowStart = start; + } + if (this.audioBuffer_) { + this.audioBuffer_.appendWindowStart = start; + } + } + }); + + // this buffer is "updating" if either of its native buffers are + Object.defineProperty(_this7, 'updating', { + get: function get$$1() { + return !!(this.bufferUpdating_ || !this.audioDisabled_ && this.audioBuffer_ && this.audioBuffer_.updating || this.videoBuffer_ && this.videoBuffer_.updating); + } + }); + + // the buffered property is the intersection of the buffered + // ranges of the native source buffers + Object.defineProperty(_this7, 'buffered', { + get: function get$$1() { + var start = null; + var end = null; + var arity = 0; + var extents = []; + var ranges = []; + + // neither buffer has been created yet + if (!this.videoBuffer_ && !this.audioBuffer_) { + return videojs$1.createTimeRange(); + } + + // only one buffer is configured + if (!this.videoBuffer_) { + return this.audioBuffer_.buffered; + } + if (!this.audioBuffer_) { + return this.videoBuffer_.buffered; + } + + // both buffers are configured + if (this.audioDisabled_) { + return this.videoBuffer_.buffered; + } + + // both buffers are empty + if (this.videoBuffer_.buffered.length === 0 && this.audioBuffer_.buffered.length === 0) { + return videojs$1.createTimeRange(); + } + + // Handle the case where we have both buffers and create an + // intersection of the two + var videoBuffered = this.videoBuffer_.buffered; + var audioBuffered = this.audioBuffer_.buffered; + var count = videoBuffered.length; + + // A) Gather up all start and end times + while (count--) { + extents.push({time: videoBuffered.start(count), type: 'start'}); + extents.push({time: videoBuffered.end(count), type: 'end'}); + } + count = audioBuffered.length; + while (count--) { + extents.push({time: audioBuffered.start(count), type: 'start'}); + extents.push({time: audioBuffered.end(count), type: 'end'}); + } + // B) Sort them by time + extents.sort(function (a, b) { + return a.time - b.time; + }); + + // C) Go along one by one incrementing arity for start and decrementing + // arity for ends + for (count = 0; count < extents.length; count++) { + if (extents[count].type === 'start') { + arity++; + + // D) If arity is ever incremented to 2 we are entering an + // overlapping range + if (arity === 2) { + start = extents[count].time; + } + } else if (extents[count].type === 'end') { + arity--; + + // E) If arity is ever decremented to 1 we leaving an + // overlapping range + if (arity === 1) { + end = extents[count].time; + } + } + + // F) Record overlapping ranges + if (start !== null && end !== null) { + ranges.push([start, end]); + start = null; + end = null; + } + } + + return videojs$1.createTimeRanges(ranges); + } + }); + return _this7; + } + + /** + * When we get a data event from the transmuxer + * we call this function and handle the data that + * was sent to us + * + * @private + * @param {Event} event the data event from the transmuxer + */ + + + VirtualSourceBuffer.prototype.data_ = function data_(event) { + var segment = event.data.segment; + + // Cast ArrayBuffer to TypedArray + segment.data = new Uint8Array(segment.data, event.data.byteOffset, event.data.byteLength); + + segment.initSegment = new Uint8Array(segment.initSegment.data, segment.initSegment.byteOffset, segment.initSegment.byteLength); + + createTextTracksIfNecessary(this, this.mediaSource_, segment); + + // Add the segments to the pendingBuffers array + this.pendingBuffers_.push(segment); + return; + }; + + /** + * When we get a done event from the transmuxer + * we call this function and we process all + * of the pending data that we have been saving in the + * data_ function + * + * @private + * @param {Event} event the done event from the transmuxer + */ + + + VirtualSourceBuffer.prototype.done_ = function done_(event) { + // Don't process and append data if the mediaSource is closed + if (this.mediaSource_.readyState === 'closed') { + this.pendingBuffers_.length = 0; + return; + } + + // All buffers should have been flushed from the muxer + // start processing anything we have received + this.processPendingSegments_(); + return; + }; + + /** + * Create our internal native audio/video source buffers and add + * event handlers to them with the following conditions: + * 1. they do not already exist on the mediaSource + * 2. this VSB has a codec for them + * + * @private + */ + + + VirtualSourceBuffer.prototype.createRealSourceBuffers_ = function createRealSourceBuffers_() { + var _this8 = this; + + var types = ['audio', 'video']; + + types.forEach(function (type) { + // Don't create a SourceBuffer of this type if we don't have a + // codec for it + if (!_this8[type + 'Codec_']) { + return; + } + + // Do nothing if a SourceBuffer of this type already exists + if (_this8[type + 'Buffer_']) { + return; + } + + var buffer = null; + + // If the mediasource already has a SourceBuffer for the codec + // use that + if (_this8.mediaSource_[type + 'Buffer_']) { + buffer = _this8.mediaSource_[type + 'Buffer_']; + // In multiple audio track cases, the audio source buffer is disabled + // on the main VirtualSourceBuffer by the HTMLMediaSource much earlier + // than createRealSourceBuffers_ is called to create the second + // VirtualSourceBuffer because that happens as a side-effect of + // videojs-contrib-hls starting the audioSegmentLoader. As a result, + // the audioBuffer is essentially "ownerless" and no one will toggle + // the `updating` state back to false once the `updateend` event is received + // + // Setting `updating` to false manually will work around this + // situation and allow work to continue + buffer.updating = false; + } else { + var codecProperty = type + 'Codec_'; + var mimeType = type + '/mp4;codecs="' + _this8[codecProperty] + '"'; + + buffer = makeWrappedSourceBuffer(_this8.mediaSource_.nativeMediaSource_, mimeType); + + _this8.mediaSource_[type + 'Buffer_'] = buffer; + } + + _this8[type + 'Buffer_'] = buffer; + + // Wire up the events to the SourceBuffer + ['update', 'updatestart', 'updateend'].forEach(function (event) { + buffer.addEventListener(event, function () { + // if audio is disabled + if (type === 'audio' && _this8.audioDisabled_) { + return; + } + + if (event === 'updateend') { + _this8[type + 'Buffer_'].updating = false; + } + + var shouldTrigger = types.every(function (t) { + // skip checking audio's updating status if audio + // is not enabled + if (t === 'audio' && _this8.audioDisabled_) { + return true; + } + // if the other type if updating we don't trigger + if (type !== t && _this8[t + 'Buffer_'] && _this8[t + 'Buffer_'].updating) { + return false; + } + return true; + }); + + if (shouldTrigger) { + return _this8.trigger(event); + } + }); + }); + }); + }; + + /** + * Emulate the native mediasource function, but our function will + * send all of the proposed segments to the transmuxer so that we + * can transmux them before we append them to our internal + * native source buffers in the correct format. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/appendBuffer + * @param {Uint8Array} segment the segment to append to the buffer + */ + + + VirtualSourceBuffer.prototype.appendBuffer = function appendBuffer(segment) { + // Start the internal "updating" state + this.bufferUpdating_ = true; + + if (this.audioBuffer_ && this.audioBuffer_.buffered.length) { + var audioBuffered = this.audioBuffer_.buffered; + + this.transmuxer_.postMessage({ + action: 'setAudioAppendStart', + appendStart: audioBuffered.end(audioBuffered.length - 1) + }); + } + + if (this.videoBuffer_) { + this.transmuxer_.postMessage({ + action: 'alignGopsWith', + gopsToAlignWith: gopsSafeToAlignWith(this.gopBuffer_, this.mediaSource_.player_, this.timeMapping_) + }); + } + + this.transmuxer_.postMessage({ + action: 'push', + // Send the typed-array of data as an ArrayBuffer so that + // it can be sent as a "Transferable" and avoid the costly + // memory copy + data: segment.buffer, + + // To recreate the original typed-array, we need information + // about what portion of the ArrayBuffer it was a view into + byteOffset: segment.byteOffset, + byteLength: segment.byteLength + }, [segment.buffer]); + this.transmuxer_.postMessage({action: 'flush'}); + }; + + /** + * Appends gop information (timing and byteLength) received by the transmuxer for the + * gops appended in the last call to appendBuffer + * + * @param {Event} event + * The gopInfo event from the transmuxer + * @param {Array} event.data.gopInfo + * List of gop info to append + */ + + + VirtualSourceBuffer.prototype.appendGopInfo_ = function appendGopInfo_(event) { + this.gopBuffer_ = updateGopBuffer(this.gopBuffer_, event.data.gopInfo, this.safeAppend_); + }; + + /** + * Emulate the native mediasource function and remove parts + * of the buffer from any of our internal buffers that exist + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/remove + * @param {Double} start position to start the remove at + * @param {Double} end position to end the remove at + */ + + + VirtualSourceBuffer.prototype.remove = function remove(start, end) { + if (this.videoBuffer_) { + this.videoBuffer_.updating = true; + this.videoBuffer_.remove(start, end); + this.gopBuffer_ = removeGopBuffer(this.gopBuffer_, start, end, this.timeMapping_); + } + if (!this.audioDisabled_ && this.audioBuffer_) { + this.audioBuffer_.updating = true; + this.audioBuffer_.remove(start, end); + } + + // Remove Metadata Cues (id3) + removeCuesFromTrack(start, end, this.metadataTrack_); + + // Remove Any Captions + if (this.inbandTextTracks_) { + for (var track in this.inbandTextTracks_) { + removeCuesFromTrack(start, end, this.inbandTextTracks_[track]); + } + } + }; + + /** + * Process any segments that the muxer has output + * Concatenate segments together based on type and append them into + * their respective sourceBuffers + * + * @private + */ + + + VirtualSourceBuffer.prototype.processPendingSegments_ = function processPendingSegments_() { + var sortedSegments = { + video: { + segments: [], + bytes: 0 + }, + audio: { + segments: [], + bytes: 0 + }, + captions: [], + metadata: [] + }; + + // Sort segments into separate video/audio arrays and + // keep track of their total byte lengths + sortedSegments = this.pendingBuffers_.reduce(function (segmentObj, segment) { + var type = segment.type; + var data = segment.data; + var initSegment = segment.initSegment; + + segmentObj[type].segments.push(data); + segmentObj[type].bytes += data.byteLength; + + segmentObj[type].initSegment = initSegment; + + // Gather any captions into a single array + if (segment.captions) { + segmentObj.captions = segmentObj.captions.concat(segment.captions); + } + + if (segment.info) { + segmentObj[type].info = segment.info; + } + + // Gather any metadata into a single array + if (segment.metadata) { + segmentObj.metadata = segmentObj.metadata.concat(segment.metadata); + } + + return segmentObj; + }, sortedSegments); + + // Create the real source buffers if they don't exist by now since we + // finally are sure what tracks are contained in the source + if (!this.videoBuffer_ && !this.audioBuffer_) { + // Remove any codecs that may have been specified by default but + // are no longer applicable now + if (sortedSegments.video.bytes === 0) { + this.videoCodec_ = null; + } + if (sortedSegments.audio.bytes === 0) { + this.audioCodec_ = null; + } + + this.createRealSourceBuffers_(); + } + + if (sortedSegments.audio.info) { + this.mediaSource_.trigger({type: 'audioinfo', info: sortedSegments.audio.info}); + } + if (sortedSegments.video.info) { + this.mediaSource_.trigger({type: 'videoinfo', info: sortedSegments.video.info}); + } + + if (this.appendAudioInitSegment_) { + if (!this.audioDisabled_ && this.audioBuffer_) { + sortedSegments.audio.segments.unshift(sortedSegments.audio.initSegment); + sortedSegments.audio.bytes += sortedSegments.audio.initSegment.byteLength; + } + this.appendAudioInitSegment_ = false; + } + + var triggerUpdateend = false; + + // Merge multiple video and audio segments into one and append + if (this.videoBuffer_ && sortedSegments.video.bytes) { + sortedSegments.video.segments.unshift(sortedSegments.video.initSegment); + sortedSegments.video.bytes += sortedSegments.video.initSegment.byteLength; + this.concatAndAppendSegments_(sortedSegments.video, this.videoBuffer_); + // TODO: are video tracks the only ones with text tracks? + addTextTrackData(this, sortedSegments.captions, sortedSegments.metadata); + } else if (this.videoBuffer_ && (this.audioDisabled_ || !this.audioBuffer_)) { + // The transmuxer did not return any bytes of video, meaning it was all trimmed + // for gop alignment. Since we have a video buffer and audio is disabled, updateend + // will never be triggered by this source buffer, which will cause contrib-hls + // to be stuck forever waiting for updateend. If audio is not disabled, updateend + // will be triggered by the audio buffer, which will be sent upwards since the video + // buffer will not be in an updating state. + triggerUpdateend = true; + } + + if (!this.audioDisabled_ && this.audioBuffer_) { + this.concatAndAppendSegments_(sortedSegments.audio, this.audioBuffer_); + } + + this.pendingBuffers_.length = 0; + + if (triggerUpdateend) { + this.trigger('updateend'); + } + + // We are no longer in the internal "updating" state + this.bufferUpdating_ = false; + }; + + /** + * Combine all segments into a single Uint8Array and then append them + * to the destination buffer + * + * @param {Object} segmentObj + * @param {SourceBuffer} destinationBuffer native source buffer to append data to + * @private + */ + + + VirtualSourceBuffer.prototype.concatAndAppendSegments_ = function concatAndAppendSegments_(segmentObj, destinationBuffer) { + var offset = 0; + var tempBuffer = void 0; + + if (segmentObj.bytes) { + tempBuffer = new Uint8Array(segmentObj.bytes); + + // Combine the individual segments into one large typed-array + segmentObj.segments.forEach(function (segment) { + tempBuffer.set(segment, offset); + offset += segment.byteLength; + }); + + try { + destinationBuffer.updating = true; + destinationBuffer.appendBuffer(tempBuffer); + } catch (error) { + if (this.mediaSource_.player_) { + this.mediaSource_.player_.error({ + code: -3, + type: 'APPEND_BUFFER_ERR', + message: error.message, + originalError: error + }); + } + } + } + }; + + /** + * Emulate the native mediasource function. abort any soureBuffer + * actions and throw out any un-appended data. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/abort + */ + + + VirtualSourceBuffer.prototype.abort = function abort() { + if (this.videoBuffer_) { + this.videoBuffer_.abort(); + } + if (!this.audioDisabled_ && this.audioBuffer_) { + this.audioBuffer_.abort(); + } + if (this.transmuxer_) { + this.transmuxer_.postMessage({action: 'reset'}); + } + this.pendingBuffers_.length = 0; + this.bufferUpdating_ = false; + }; + + return VirtualSourceBuffer; + }(videojs$1.EventTarget); + + /** + * @file html-media-source.js + */ + + /** + * Our MediaSource implementation in HTML, mimics native + * MediaSource where/if possible. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource + * @class HtmlMediaSource + * @extends videojs.EventTarget + */ + + + var HtmlMediaSource = function (_videojs$EventTarget2) { + inherits(HtmlMediaSource, _videojs$EventTarget2); + + function HtmlMediaSource() { + classCallCheck(this, HtmlMediaSource); + + var _this9 = possibleConstructorReturn(this, _videojs$EventTarget2.call(this)); + + var property = void 0; + + _this9.nativeMediaSource_ = new window_1.MediaSource(); + // delegate to the native MediaSource's methods by default + for (property in _this9.nativeMediaSource_) { + if (!(property in HtmlMediaSource.prototype) && typeof _this9.nativeMediaSource_[property] === 'function') { + _this9[property] = _this9.nativeMediaSource_[property].bind(_this9.nativeMediaSource_); + } + } + + // emulate `duration` and `seekable` until seeking can be + // handled uniformly for live streams + // see https://github.com/w3c/media-source/issues/5 + _this9.duration_ = NaN; + Object.defineProperty(_this9, 'duration', { + get: function get$$1() { + if (this.duration_ === Infinity) { + return this.duration_; + } + return this.nativeMediaSource_.duration; + }, + set: function set$$1(duration) { + this.duration_ = duration; + if (duration !== Infinity) { + this.nativeMediaSource_.duration = duration; + return; + } + } + }); + Object.defineProperty(_this9, 'seekable', { + get: function get$$1() { + if (this.duration_ === Infinity) { + return videojs$1.createTimeRanges([[0, this.nativeMediaSource_.duration]]); + } + return this.nativeMediaSource_.seekable; + } + }); + + Object.defineProperty(_this9, 'readyState', { + get: function get$$1() { + return this.nativeMediaSource_.readyState; + } + }); + + Object.defineProperty(_this9, 'activeSourceBuffers', { + get: function get$$1() { + return this.activeSourceBuffers_; + } + }); + + // the list of virtual and native SourceBuffers created by this + // MediaSource + _this9.sourceBuffers = []; + + _this9.activeSourceBuffers_ = []; + + /** + * update the list of active source buffers based upon various + * imformation from HLS and video.js + * + * @private + */ + _this9.updateActiveSourceBuffers_ = function () { + // Retain the reference but empty the array + _this9.activeSourceBuffers_.length = 0; + + // If there is only one source buffer, then it will always be active and audio will + // be disabled based on the codec of the source buffer + if (_this9.sourceBuffers.length === 1) { + var sourceBuffer = _this9.sourceBuffers[0]; + + sourceBuffer.appendAudioInitSegment_ = true; + sourceBuffer.audioDisabled_ = !sourceBuffer.audioCodec_; + _this9.activeSourceBuffers_.push(sourceBuffer); + return; + } + + // There are 2 source buffers, a combined (possibly video only) source buffer and + // and an audio only source buffer. + // By default, the audio in the combined virtual source buffer is enabled + // and the audio-only source buffer (if it exists) is disabled. + var disableCombined = false; + var disableAudioOnly = true; + + // TODO: maybe we can store the sourcebuffers on the track objects? + // safari may do something like this + for (var i = 0; i < _this9.player_.audioTracks().length; i++) { + var track = _this9.player_.audioTracks()[i]; + + if (track.enabled && track.kind !== 'main') { + // The enabled track is an alternate audio track so disable the audio in + // the combined source buffer and enable the audio-only source buffer. + disableCombined = true; + disableAudioOnly = false; + break; + } + } + + _this9.sourceBuffers.forEach(function (sourceBuffer, index) { + /* eslinst-disable */ + // TODO once codecs are required, we can switch to using the codecs to determine + // what stream is the video stream, rather than relying on videoTracks + /* eslinst-enable */ + + sourceBuffer.appendAudioInitSegment_ = true; + + if (sourceBuffer.videoCodec_ && sourceBuffer.audioCodec_) { + // combined + sourceBuffer.audioDisabled_ = disableCombined; + } else if (sourceBuffer.videoCodec_ && !sourceBuffer.audioCodec_) { + // If the "combined" source buffer is video only, then we do not want + // disable the audio-only source buffer (this is mostly for demuxed + // audio and video hls) + sourceBuffer.audioDisabled_ = true; + disableAudioOnly = false; + } else if (!sourceBuffer.videoCodec_ && sourceBuffer.audioCodec_) { + // audio only + // In the case of audio only with alternate audio and disableAudioOnly is true + // this means we want to disable the audio on the alternate audio sourcebuffer + // but not the main "combined" source buffer. The "combined" source buffer is + // always at index 0, so this ensures audio won't be disabled in both source + // buffers. + sourceBuffer.audioDisabled_ = index ? disableAudioOnly : !disableAudioOnly; + if (sourceBuffer.audioDisabled_) { + return; + } + } + + _this9.activeSourceBuffers_.push(sourceBuffer); + }); + }; + + _this9.onPlayerMediachange_ = function () { + _this9.sourceBuffers.forEach(function (sourceBuffer) { + sourceBuffer.appendAudioInitSegment_ = true; + }); + }; + + _this9.onHlsReset_ = function () { + _this9.sourceBuffers.forEach(function (sourceBuffer) { + if (sourceBuffer.transmuxer_) { + sourceBuffer.transmuxer_.postMessage({action: 'resetCaptions'}); + } + }); + }; + + _this9.onHlsSegmentTimeMapping_ = function (event) { + _this9.sourceBuffers.forEach(function (buffer) { + return buffer.timeMapping_ = event.mapping; + }); + }; + + // Re-emit MediaSource events on the polyfill + ['sourceopen', 'sourceclose', 'sourceended'].forEach(function (eventName) { + this.nativeMediaSource_.addEventListener(eventName, this.trigger.bind(this)); + }, _this9); + + // capture the associated player when the MediaSource is + // successfully attached + _this9.on('sourceopen', function (event) { + // Get the player this MediaSource is attached to + var video = document_1.querySelector('[src="' + _this9.url_ + '"]'); + + if (!video) { + return; + } + + _this9.player_ = videojs$1(video.parentNode); + + // hls-reset is fired by videojs.Hls on to the tech after the main SegmentLoader + // resets its state and flushes the buffer + _this9.player_.tech_.on('hls-reset', _this9.onHlsReset_); + // hls-segment-time-mapping is fired by videojs.Hls on to the tech after the main + // SegmentLoader inspects an MTS segment and has an accurate stream to display + // time mapping + _this9.player_.tech_.on('hls-segment-time-mapping', _this9.onHlsSegmentTimeMapping_); + + if (_this9.player_.audioTracks && _this9.player_.audioTracks()) { + _this9.player_.audioTracks().on('change', _this9.updateActiveSourceBuffers_); + _this9.player_.audioTracks().on('addtrack', _this9.updateActiveSourceBuffers_); + _this9.player_.audioTracks().on('removetrack', _this9.updateActiveSourceBuffers_); + } + + _this9.player_.on('mediachange', _this9.onPlayerMediachange_); + }); + + _this9.on('sourceended', function (event) { + var duration = durationOfVideo(_this9.duration); + + for (var i = 0; i < _this9.sourceBuffers.length; i++) { + var sourcebuffer = _this9.sourceBuffers[i]; + var cues = sourcebuffer.metadataTrack_ && sourcebuffer.metadataTrack_.cues; + + if (cues && cues.length) { + cues[cues.length - 1].endTime = duration; + } + } + }); + + // explicitly terminate any WebWorkers that were created + // by SourceHandlers + _this9.on('sourceclose', function (event) { + this.sourceBuffers.forEach(function (sourceBuffer) { + if (sourceBuffer.transmuxer_) { + sourceBuffer.transmuxer_.terminate(); + } + }); + + this.sourceBuffers.length = 0; + if (!this.player_) { + return; + } + + if (this.player_.audioTracks && this.player_.audioTracks()) { + this.player_.audioTracks().off('change', this.updateActiveSourceBuffers_); + this.player_.audioTracks().off('addtrack', this.updateActiveSourceBuffers_); + this.player_.audioTracks().off('removetrack', this.updateActiveSourceBuffers_); + } + + // We can only change this if the player hasn't been disposed of yet + // because `off` eventually tries to use the el_ property. If it has + // been disposed of, then don't worry about it because there are no + // event handlers left to unbind anyway + if (this.player_.el_) { + this.player_.off('mediachange', this.onPlayerMediachange_); + this.player_.tech_.off('hls-reset', this.onHlsReset_); + this.player_.tech_.off('hls-segment-time-mapping', this.onHlsSegmentTimeMapping_); + } + }); + return _this9; + } + + /** + * Add a range that that can now be seeked to. + * + * @param {Double} start where to start the addition + * @param {Double} end where to end the addition + * @private + */ + + + HtmlMediaSource.prototype.addSeekableRange_ = function addSeekableRange_(start, end) { + var error = void 0; + + if (this.duration !== Infinity) { + error = new Error('MediaSource.addSeekableRange() can only be invoked ' + 'when the duration is Infinity'); + error.name = 'InvalidStateError'; + error.code = 11; + throw error; + } + + if (end > this.nativeMediaSource_.duration || isNaN(this.nativeMediaSource_.duration)) { + this.nativeMediaSource_.duration = end; + } + }; + + /** + * Add a source buffer to the media source. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/addSourceBuffer + * @param {String} type the content-type of the content + * @return {Object} the created source buffer + */ + + + HtmlMediaSource.prototype.addSourceBuffer = function addSourceBuffer(type) { + var buffer = void 0; + var parsedType = parseContentType(type); + + // Create a VirtualSourceBuffer to transmux MPEG-2 transport + // stream segments into fragmented MP4s + if (/^(video|audio)\/mp2t$/i.test(parsedType.type)) { + var codecs = []; + + if (parsedType.parameters && parsedType.parameters.codecs) { + codecs = parsedType.parameters.codecs.split(','); + codecs = translateLegacyCodecs(codecs); + codecs = codecs.filter(function (codec) { + return isAudioCodec(codec) || isVideoCodec(codec); + }); + } + + if (codecs.length === 0) { + codecs = ['avc1.4d400d', 'mp4a.40.2']; + } + + buffer = new VirtualSourceBuffer(this, codecs); + + if (this.sourceBuffers.length !== 0) { + // If another VirtualSourceBuffer already exists, then we are creating a + // SourceBuffer for an alternate audio track and therefore we know that + // the source has both an audio and video track. + // That means we should trigger the manual creation of the real + // SourceBuffers instead of waiting for the transmuxer to return data + this.sourceBuffers[0].createRealSourceBuffers_(); + buffer.createRealSourceBuffers_(); + + // Automatically disable the audio on the first source buffer if + // a second source buffer is ever created + this.sourceBuffers[0].audioDisabled_ = true; + } + } else { + // delegate to the native implementation + buffer = this.nativeMediaSource_.addSourceBuffer(type); + } + + this.sourceBuffers.push(buffer); + return buffer; + }; + + return HtmlMediaSource; + }(videojs$1.EventTarget); + + /** + * @file videojs-contrib-media-sources.js + */ + + + var urlCount = 0; + + // ------------ + // Media Source + // ------------ + + // store references to the media sources so they can be connected + // to a video element (a swf object) + // TODO: can we store this somewhere local to this module? + videojs$1.mediaSources = {}; + + /** + * Provide a method for a swf object to notify JS that a + * media source is now open. + * + * @param {String} msObjectURL string referencing the MSE Object URL + * @param {String} swfId the swf id + */ + var open = function open(msObjectURL, swfId) { + var mediaSource = videojs$1.mediaSources[msObjectURL]; + + if (mediaSource) { + mediaSource.trigger({type: 'sourceopen', swfId: swfId}); + } else { + throw new Error('Media Source not found (Video.js)'); + } + }; + + /** + * Check to see if the native MediaSource object exists and supports + * an MP4 container with both H.264 video and AAC-LC audio. + * + * @return {Boolean} if native media sources are supported + */ + var supportsNativeMediaSources = function supportsNativeMediaSources() { + return !!window_1.MediaSource && !!window_1.MediaSource.isTypeSupported && window_1.MediaSource.isTypeSupported('video/mp4;codecs="avc1.4d400d,mp4a.40.2"'); + }; + + /** + * An emulation of the MediaSource API so that we can support + * native and non-native functionality. returns an instance of + * HtmlMediaSource. + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/MediaSource/MediaSource + */ + var MediaSource = function MediaSource() { + this.MediaSource = { + open: open, + supportsNativeMediaSources: supportsNativeMediaSources + }; + + if (supportsNativeMediaSources()) { + return new HtmlMediaSource(); + } + + throw new Error('Cannot use create a virtual MediaSource for this video'); + }; + + MediaSource.open = open; + MediaSource.supportsNativeMediaSources = supportsNativeMediaSources; + + /** + * A wrapper around the native URL for our MSE object + * implementation, this object is exposed under videojs.URL + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/URL/URL + */ + var URL$1 = { + /** + * A wrapper around the native createObjectURL for our objects. + * This function maps a native or emulated mediaSource to a blob + * url so that it can be loaded into video.js + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL + * @param {MediaSource} object the object to create a blob url to + */ + createObjectURL: function createObjectURL(object) { + var objectUrlPrefix = 'blob:vjs-media-source/'; + var url = void 0; + + // use the native MediaSource to generate an object URL + if (object instanceof HtmlMediaSource) { + url = window_1.URL.createObjectURL(object.nativeMediaSource_); + object.url_ = url; + return url; + } + // if the object isn't an emulated MediaSource, delegate to the + // native implementation + if (!(object instanceof HtmlMediaSource)) { + url = window_1.URL.createObjectURL(object); + object.url_ = url; + return url; + } + + // build a URL that can be used to map back to the emulated + // MediaSource + url = objectUrlPrefix + urlCount; + + urlCount++; + + // setup the mapping back to object + videojs$1.mediaSources[url] = object; + + return url; + } + }; + + videojs$1.MediaSource = MediaSource; + videojs$1.URL = URL$1; + + var EventTarget$1$1 = videojs$1.EventTarget, + mergeOptions$2 = videojs$1.mergeOptions; + + /** + * Returns a new master manifest that is the result of merging an updated master manifest + * into the original version. + * + * @param {Object} oldMaster + * The old parsed mpd object + * @param {Object} newMaster + * The updated parsed mpd object + * @return {Object} + * A new object representing the original master manifest with the updated media + * playlists merged in + */ + + var updateMaster$1 = function updateMaster$1(oldMaster, newMaster) { + var update = mergeOptions$2(oldMaster, { + // These are top level properties that can be updated + duration: newMaster.duration, + minimumUpdatePeriod: newMaster.minimumUpdatePeriod + }); + + // First update the playlists in playlist list + for (var i = 0; i < newMaster.playlists.length; i++) { + var playlistUpdate = updateMaster(update, newMaster.playlists[i]); + + if (playlistUpdate) { + update = playlistUpdate; + } + } + + // Then update media group playlists + forEachMediaGroup(newMaster, function (properties, type, group, label) { + if (properties.playlists && properties.playlists.length) { + var uri = properties.playlists[0].uri; + var _playlistUpdate = updateMaster(update, properties.playlists[0]); + + if (_playlistUpdate) { + update = _playlistUpdate; + // update the playlist reference within media groups + update.mediaGroups[type][group][label].playlists[0] = update.playlists[uri]; + } + } + }); + + return update; + }; + + var DashPlaylistLoader = function (_EventTarget$) { + inherits(DashPlaylistLoader, _EventTarget$); + + // DashPlaylistLoader must accept either a src url or a playlist because subsequent + // playlist loader setups from media groups will expect to be able to pass a playlist + // (since there aren't external URLs to media playlists with DASH) + function DashPlaylistLoader(srcUrlOrPlaylist, hls, withCredentials, masterPlaylistLoader) { + classCallCheck(this, DashPlaylistLoader); + + var _this10 = possibleConstructorReturn(this, _EventTarget$.call(this)); + + _this10.hls_ = hls; + _this10.withCredentials = withCredentials; + + if (!srcUrlOrPlaylist) { + throw new Error('A non-empty playlist URL or playlist is required'); + } + + // event naming? + _this10.on('minimumUpdatePeriod', function () { + _this10.refreshXml_(); + }); + + // live playlist staleness timeout + _this10.on('mediaupdatetimeout', function () { + _this10.refreshMedia_(); + }); + + // initialize the loader state + if (typeof srcUrlOrPlaylist === 'string') { + _this10.srcUrl = srcUrlOrPlaylist; + _this10.state = 'HAVE_NOTHING'; + return possibleConstructorReturn(_this10); + } + + _this10.masterPlaylistLoader_ = masterPlaylistLoader; + + _this10.state = 'HAVE_METADATA'; + _this10.started = true; + // we only should have one playlist so select it + _this10.media(srcUrlOrPlaylist); + // trigger async to mimic behavior of HLS, where it must request a playlist + window_1.setTimeout(function () { + _this10.trigger('loadedmetadata'); + }, 0); + return _this10; + } + + DashPlaylistLoader.prototype.dispose = function dispose() { + this.stopRequest(); + window_1.clearTimeout(this.mediaUpdateTimeout); + }; + + DashPlaylistLoader.prototype.stopRequest = function stopRequest() { + if (this.request) { + var oldRequest = this.request; + + this.request = null; + oldRequest.onreadystatechange = null; + oldRequest.abort(); + } + }; + + DashPlaylistLoader.prototype.media = function media(playlist) { + // getter + if (!playlist) { + return this.media_; + } + + // setter + if (this.state === 'HAVE_NOTHING') { + throw new Error('Cannot switch media playlist from ' + this.state); + } + + var startingState = this.state; + + // find the playlist object if the target playlist has been specified by URI + if (typeof playlist === 'string') { + if (!this.master.playlists[playlist]) { + throw new Error('Unknown playlist URI: ' + playlist); + } + playlist = this.master.playlists[playlist]; + } + + var mediaChange = !this.media_ || playlist.uri !== this.media_.uri; + + this.state = 'HAVE_METADATA'; + + // switching to the active playlist is a no-op + if (!mediaChange) { + return; + } + + // switching from an already loaded playlist + if (this.media_) { + this.trigger('mediachanging'); + } + + this.media_ = playlist; + + this.refreshMedia_(); + + // trigger media change if the active media has been updated + if (startingState !== 'HAVE_MASTER') { + this.trigger('mediachange'); + } + }; + + DashPlaylistLoader.prototype.pause = function pause() { + this.stopRequest(); + if (this.state === 'HAVE_NOTHING') { + // If we pause the loader before any data has been retrieved, its as if we never + // started, so reset to an unstarted state. + this.started = false; + } + }; + + DashPlaylistLoader.prototype.load = function load() { + // because the playlists are internal to the manifest, load should either load the + // main manifest, or do nothing but trigger an event + if (!this.started) { + this.start(); + return; + } + + this.trigger('loadedplaylist'); + }; + + /** + * Parses the master xml string and updates playlist uri references + * + * @return {Object} + * The parsed mpd manifest object + */ + + + DashPlaylistLoader.prototype.parseMasterXml = function parseMasterXml() { + var master = parse(this.masterXml_, { + manifestUri: this.srcUrl, + clientOffset: this.clientOffset_ + }); + + master.uri = this.srcUrl; + + // Set up phony URIs for the playlists since we won't have external URIs for DASH + // but reference playlists by their URI throughout the project + // TODO: Should we create the dummy uris in mpd-parser as well (leaning towards yes). + for (var i = 0; i < master.playlists.length; i++) { + var phonyUri = 'placeholder-uri-' + i; + + master.playlists[i].uri = phonyUri; + // set up by URI references + master.playlists[phonyUri] = master.playlists[i]; + } + + // set up phony URIs for the media group playlists since we won't have external + // URIs for DASH but reference playlists by their URI throughout the project + forEachMediaGroup(master, function (properties, mediaType, groupKey, labelKey) { + if (properties.playlists && properties.playlists.length) { + var _phonyUri = 'placeholder-uri-' + mediaType + '-' + groupKey + '-' + labelKey; + + properties.playlists[0].uri = _phonyUri; + // setup URI references + master.playlists[_phonyUri] = properties.playlists[0]; + } + }); + + setupMediaPlaylists(master); + resolveMediaGroupUris(master); + + return master; + }; + + DashPlaylistLoader.prototype.start = function start() { + var _this11 = this; + + this.started = true; + + // request the specified URL + this.request = this.hls_.xhr({ + uri: this.srcUrl, + withCredentials: this.withCredentials + }, function (error, req) { + // disposed + if (!_this11.request) { + return; + } + + // clear the loader's request reference + _this11.request = null; + + if (error) { + _this11.error = { + status: req.status, + message: 'DASH playlist request error at URL: ' + _this11.srcUrl, + responseText: req.responseText, + // MEDIA_ERR_NETWORK + code: 2 + }; + if (_this11.state === 'HAVE_NOTHING') { + _this11.started = false; + } + return _this11.trigger('error'); + } + + _this11.masterXml_ = req.responseText; + + if (req.responseHeaders && req.responseHeaders.date) { + _this11.masterLoaded_ = Date.parse(req.responseHeaders.date); + } else { + _this11.masterLoaded_ = Date.now(); + } + + _this11.syncClientServerClock_(_this11.onClientServerClockSync_.bind(_this11)); + }); + }; + + /** + * Parses the master xml for UTCTiming node to sync the client clock to the server + * clock. If the UTCTiming node requires a HEAD or GET request, that request is made. + * + * @param {Function} done + * Function to call when clock sync has completed + */ + + + DashPlaylistLoader.prototype.syncClientServerClock_ = function syncClientServerClock_(done) { + var _this12 = this; + + var utcTiming = parseUTCTiming(this.masterXml_); + + // No UTCTiming element found in the mpd. Use Date header from mpd request as the + // server clock + if (utcTiming === null) { + this.clientOffset_ = this.masterLoaded_ - Date.now(); + return done(); + } + + if (utcTiming.method === 'DIRECT') { + this.clientOffset_ = utcTiming.value - Date.now(); + return done(); + } + + this.request = this.hls_.xhr({ + uri: resolveUrl$1(this.srcUrl, utcTiming.value), + method: utcTiming.method, + withCredentials: this.withCredentials + }, function (error, req) { + // disposed + if (!_this12.request) { + return; + } + + if (error) { + // sync request failed, fall back to using date header from mpd + // TODO: log warning + _this12.clientOffset_ = _this12.masterLoaded_ - Date.now(); + return done(); + } + + var serverTime = void 0; + + if (utcTiming.method === 'HEAD') { + if (!req.responseHeaders || !req.responseHeaders.date) { + // expected date header not preset, fall back to using date header from mpd + // TODO: log warning + serverTime = _this12.masterLoaded_; + } else { + serverTime = Date.parse(req.responseHeaders.date); + } + } else { + serverTime = Date.parse(req.responseText); + } + + _this12.clientOffset_ = serverTime - Date.now(); + + done(); + }); + }; + + /** + * Handler for after client/server clock synchronization has happened. Sets up + * xml refresh timer if specificed by the manifest. + */ + + + DashPlaylistLoader.prototype.onClientServerClockSync_ = function onClientServerClockSync_() { + var _this13 = this; + + this.master = this.parseMasterXml(); + + this.state = 'HAVE_MASTER'; + + this.trigger('loadedplaylist'); + + if (!this.media_) { + // no media playlist was specifically selected so start + // from the first listed one + this.media(this.master.playlists[0]); + } + // trigger loadedmetadata to resolve setup of media groups + // trigger async to mimic behavior of HLS, where it must request a playlist + window_1.setTimeout(function () { + _this13.trigger('loadedmetadata'); + }, 0); + + // TODO: minimumUpdatePeriod can have a value of 0. Currently the manifest will not + // be refreshed when this is the case. The inter-op guide says that when the + // minimumUpdatePeriod is 0, the manifest should outline all currently available + // segments, but future segments may require an update. I think a good solution + // would be to update the manifest at the same rate that the media playlists + // are "refreshed", i.e. every targetDuration. + if (this.master.minimumUpdatePeriod) { + window_1.setTimeout(function () { + _this13.trigger('minimumUpdatePeriod'); + }, this.master.minimumUpdatePeriod); + } + }; + + /** + * Sends request to refresh the master xml and updates the parsed master manifest + * TODO: Does the client offset need to be recalculated when the xml is refreshed? + */ + + + DashPlaylistLoader.prototype.refreshXml_ = function refreshXml_() { + var _this14 = this; + + this.request = this.hls_.xhr({ + uri: this.srcUrl, + withCredentials: this.withCredentials + }, function (error, req) { + // disposed + if (!_this14.request) { + return; + } + + // clear the loader's request reference + _this14.request = null; + + if (error) { + _this14.error = { + status: req.status, + message: 'DASH playlist request error at URL: ' + _this14.srcUrl, + responseText: req.responseText, + // MEDIA_ERR_NETWORK + code: 2 + }; + if (_this14.state === 'HAVE_NOTHING') { + _this14.started = false; + } + return _this14.trigger('error'); + } + + _this14.masterXml_ = req.responseText; + + var newMaster = _this14.parseMasterXml(); + + _this14.master = updateMaster$1(_this14.master, newMaster); + + window_1.setTimeout(function () { + _this14.trigger('minimumUpdatePeriod'); + }, _this14.master.minimumUpdatePeriod); + }); + }; + + /** + * Refreshes the media playlist by re-parsing the master xml and updating playlist + * references. If this is an alternate loader, the updated parsed manifest is retrieved + * from the master loader. + */ + + + DashPlaylistLoader.prototype.refreshMedia_ = function refreshMedia_() { + var _this15 = this; + + var oldMaster = void 0; + var newMaster = void 0; + + if (this.masterPlaylistLoader_) { + oldMaster = this.masterPlaylistLoader_.master; + newMaster = this.masterPlaylistLoader_.parseMasterXml(); + } else { + oldMaster = this.master; + newMaster = this.parseMasterXml(); + } + + var updatedMaster = updateMaster$1(oldMaster, newMaster); + + if (updatedMaster) { + if (this.masterPlaylistLoader_) { + this.masterPlaylistLoader_.master = updatedMaster; + } else { + this.master = updatedMaster; + } + this.media_ = updatedMaster.playlists[this.media_.uri]; + } else { + this.trigger('playlistunchanged'); + } + + if (!this.media().endList) { + this.mediaUpdateTimeout = window_1.setTimeout(function () { + _this15.trigger('mediaupdatetimeout'); + }, refreshDelay(this.media(), !!updatedMaster)); + } + + this.trigger('loadedplaylist'); + }; + + return DashPlaylistLoader; + }(EventTarget$1$1); + + var logger = function logger(source) { + if (videojs$1.log.debug) { + return videojs$1.log.debug.bind(videojs$1, 'VHS:', source + ' >'); + } + + return function () { + }; + }; + + function noop$1() { + } + + /** + * @file source-updater.js + */ + + /** + * A queue of callbacks to be serialized and applied when a + * MediaSource and its associated SourceBuffers are not in the + * updating state. It is used by the segment loader to update the + * underlying SourceBuffers when new data is loaded, for instance. + * + * @class SourceUpdater + * @param {MediaSource} mediaSource the MediaSource to create the + * SourceBuffer from + * @param {String} mimeType the desired MIME type of the underlying + * SourceBuffer + * @param {Object} sourceBufferEmitter an event emitter that fires when a source buffer is + * added to the media source + */ + + var SourceUpdater = function () { + function SourceUpdater(mediaSource, mimeType, type, sourceBufferEmitter) { + classCallCheck(this, SourceUpdater); + + this.callbacks_ = []; + this.pendingCallback_ = null; + this.timestampOffset_ = 0; + this.mediaSource = mediaSource; + this.processedAppend_ = false; + this.type_ = type; + this.mimeType_ = mimeType; + this.logger_ = logger('SourceUpdater[' + type + '][' + mimeType + ']'); + + if (mediaSource.readyState === 'closed') { + mediaSource.addEventListener('sourceopen', this.createSourceBuffer_.bind(this, mimeType, sourceBufferEmitter)); + } else { + this.createSourceBuffer_(mimeType, sourceBufferEmitter); + } + } + + SourceUpdater.prototype.createSourceBuffer_ = function createSourceBuffer_(mimeType, sourceBufferEmitter) { + var _this16 = this; + + this.sourceBuffer_ = this.mediaSource.addSourceBuffer(mimeType); + + this.logger_('created SourceBuffer'); + + if (sourceBufferEmitter) { + sourceBufferEmitter.trigger('sourcebufferadded'); + + if (this.mediaSource.sourceBuffers.length < 2) { + // There's another source buffer we must wait for before we can start updating + // our own (or else we can get into a bad state, i.e., appending video/audio data + // before the other video/audio source buffer is available and leading to a video + // or audio only buffer). + sourceBufferEmitter.on('sourcebufferadded', function () { + _this16.start_(); + }); + return; + } + } + + this.start_(); + }; + + SourceUpdater.prototype.start_ = function start_() { + var _this17 = this; + + this.started_ = true; + + // run completion handlers and process callbacks as updateend + // events fire + this.onUpdateendCallback_ = function () { + var pendingCallback = _this17.pendingCallback_; + + _this17.pendingCallback_ = null; + + _this17.logger_('buffered [' + printableRange(_this17.buffered()) + ']'); + + if (pendingCallback) { + pendingCallback(); + } + + _this17.runCallback_(); + }; + + this.sourceBuffer_.addEventListener('updateend', this.onUpdateendCallback_); + + this.runCallback_(); + }; + + /** + * Aborts the current segment and resets the segment parser. + * + * @param {Function} done function to call when done + * @see http://w3c.github.io/media-source/#widl-SourceBuffer-abort-void + */ + + + SourceUpdater.prototype.abort = function abort(done) { + var _this18 = this; + + if (this.processedAppend_) { + this.queueCallback_(function () { + _this18.sourceBuffer_.abort(); + }, done); + } + }; + + /** + * Queue an update to append an ArrayBuffer. + * + * @param {ArrayBuffer} bytes + * @param {Function} done the function to call when done + * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-appendBuffer-void-ArrayBuffer-data + */ + + + SourceUpdater.prototype.appendBuffer = function appendBuffer(bytes, done) { + var _this19 = this; + + this.processedAppend_ = true; + this.queueCallback_(function () { + _this19.sourceBuffer_.appendBuffer(bytes); + }, done); + }; + + /** + * Indicates what TimeRanges are buffered in the managed SourceBuffer. + * + * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-buffered + */ + + + SourceUpdater.prototype.buffered = function buffered() { + if (!this.sourceBuffer_) { + return videojs$1.createTimeRanges(); + } + return this.sourceBuffer_.buffered; + }; + + /** + * Queue an update to remove a time range from the buffer. + * + * @param {Number} start where to start the removal + * @param {Number} end where to end the removal + * @see http://www.w3.org/TR/media-source/#widl-SourceBuffer-remove-void-double-start-unrestricted-double-end + */ + + + SourceUpdater.prototype.remove = function remove(start, end) { + var _this20 = this; + + if (this.processedAppend_) { + this.queueCallback_(function () { + _this20.logger_('remove [' + start + ' => ' + end + ']'); + _this20.sourceBuffer_.remove(start, end); + }, noop$1); + } + }; + + /** + * Whether the underlying sourceBuffer is updating or not + * + * @return {Boolean} the updating status of the SourceBuffer + */ + + + SourceUpdater.prototype.updating = function updating() { + return !this.sourceBuffer_ || this.sourceBuffer_.updating || this.pendingCallback_; + }; + + /** + * Set/get the timestampoffset on the SourceBuffer + * + * @return {Number} the timestamp offset + */ + + + SourceUpdater.prototype.timestampOffset = function timestampOffset(offset) { + var _this21 = this; + + if (typeof offset !== 'undefined') { + this.queueCallback_(function () { + _this21.sourceBuffer_.timestampOffset = offset; + }); + this.timestampOffset_ = offset; + } + return this.timestampOffset_; + }; + + /** + * Queue a callback to run + */ + + + SourceUpdater.prototype.queueCallback_ = function queueCallback_(callback, done) { + this.callbacks_.push([callback.bind(this), done]); + this.runCallback_(); + }; + + /** + * Run a queued callback + */ + + + SourceUpdater.prototype.runCallback_ = function runCallback_() { + var callbacks = void 0; + + if (!this.updating() && this.callbacks_.length && this.started_) { + callbacks = this.callbacks_.shift(); + this.pendingCallback_ = callbacks[1]; + callbacks[0](); + } + }; + + /** + * dispose of the source updater and the underlying sourceBuffer + */ + + + SourceUpdater.prototype.dispose = function dispose() { + this.sourceBuffer_.removeEventListener('updateend', this.onUpdateendCallback_); + if (this.sourceBuffer_ && this.mediaSource.readyState === 'open') { + this.sourceBuffer_.abort(); + } + }; + + return SourceUpdater; + }(); + + var Config = { + GOAL_BUFFER_LENGTH: 30, + MAX_GOAL_BUFFER_LENGTH: 60, + GOAL_BUFFER_LENGTH_RATE: 1, + // A fudge factor to apply to advertised playlist bitrates to account for + // temporary flucations in client bandwidth + BANDWIDTH_VARIANCE: 1.2, + // How much of the buffer must be filled before we consider upswitching + BUFFER_LOW_WATER_LINE: 0, + MAX_BUFFER_LOW_WATER_LINE: 30, + BUFFER_LOW_WATER_LINE_RATE: 1 + }; + + var REQUEST_ERRORS = { + FAILURE: 2, + TIMEOUT: -101, + ABORTED: -102 + }; + + /** + * Turns segment byterange into a string suitable for use in + * HTTP Range requests + * + * @param {Object} byterange - an object with two values defining the start and end + * of a byte-range + */ + var byterangeStr = function byterangeStr(byterange) { + var byterangeStart = void 0; + var byterangeEnd = void 0; + + // `byterangeEnd` is one less than `offset + length` because the HTTP range + // header uses inclusive ranges + byterangeEnd = byterange.offset + byterange.length - 1; + byterangeStart = byterange.offset; + return 'bytes=' + byterangeStart + '-' + byterangeEnd; + }; + + /** + * Defines headers for use in the xhr request for a particular segment. + * + * @param {Object} segment - a simplified copy of the segmentInfo object + * from SegmentLoader + */ + var segmentXhrHeaders = function segmentXhrHeaders(segment) { + var headers = {}; + + if (segment.byterange) { + headers.Range = byterangeStr(segment.byterange); + } + return headers; + }; + + /** + * Abort all requests + * + * @param {Object} activeXhrs - an object that tracks all XHR requests + */ + var abortAll = function abortAll(activeXhrs) { + activeXhrs.forEach(function (xhr) { + xhr.abort(); + }); + }; + + /** + * Gather important bandwidth stats once a request has completed + * + * @param {Object} request - the XHR request from which to gather stats + */ + var getRequestStats = function getRequestStats(request) { + return { + bandwidth: request.bandwidth, + bytesReceived: request.bytesReceived || 0, + roundTripTime: request.roundTripTime || 0 + }; + }; + + /** + * If possible gather bandwidth stats as a request is in + * progress + * + * @param {Event} progressEvent - an event object from an XHR's progress event + */ + var getProgressStats = function getProgressStats(progressEvent) { + var request = progressEvent.target; + var roundTripTime = Date.now() - request.requestTime; + var stats = { + bandwidth: Infinity, + bytesReceived: 0, + roundTripTime: roundTripTime || 0 + }; + + stats.bytesReceived = progressEvent.loaded; + // This can result in Infinity if stats.roundTripTime is 0 but that is ok + // because we should only use bandwidth stats on progress to determine when + // abort a request early due to insufficient bandwidth + stats.bandwidth = Math.floor(stats.bytesReceived / stats.roundTripTime * 8 * 1000); + + return stats; + }; + + /** + * Handle all error conditions in one place and return an object + * with all the information + * + * @param {Error|null} error - if non-null signals an error occured with the XHR + * @param {Object} request - the XHR request that possibly generated the error + */ + var handleErrors = function handleErrors(error, request) { + if (request.timedout) { + return { + status: request.status, + message: 'HLS request timed-out at URL: ' + request.uri, + code: REQUEST_ERRORS.TIMEOUT, + xhr: request + }; + } + + if (request.aborted) { + return { + status: request.status, + message: 'HLS request aborted at URL: ' + request.uri, + code: REQUEST_ERRORS.ABORTED, + xhr: request + }; + } + + if (error) { + return { + status: request.status, + message: 'HLS request errored at URL: ' + request.uri, + code: REQUEST_ERRORS.FAILURE, + xhr: request + }; + } + + return null; + }; + + /** + * Handle responses for key data and convert the key data to the correct format + * for the decryption step later + * + * @param {Object} segment - a simplified copy of the segmentInfo object + * from SegmentLoader + * @param {Function} finishProcessingFn - a callback to execute to continue processing + * this request + */ + var handleKeyResponse = function handleKeyResponse(segment, finishProcessingFn) { + return function (error, request) { + var response = request.response; + var errorObj = handleErrors(error, request); + + if (errorObj) { + return finishProcessingFn(errorObj, segment); + } + + if (response.byteLength !== 16) { + return finishProcessingFn({ + status: request.status, + message: 'Invalid HLS key at URL: ' + request.uri, + code: REQUEST_ERRORS.FAILURE, + xhr: request + }, segment); + } + + var view = new DataView(response); + + segment.key.bytes = new Uint32Array([view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)]); + return finishProcessingFn(null, segment); + }; + }; + + /** + * Handle init-segment responses + * + * @param {Object} segment - a simplified copy of the segmentInfo object + * from SegmentLoader + * @param {Function} finishProcessingFn - a callback to execute to continue processing + * this request + */ + var handleInitSegmentResponse = function handleInitSegmentResponse(segment, finishProcessingFn) { + return function (error, request) { + var response = request.response; + var errorObj = handleErrors(error, request); + + if (errorObj) { + return finishProcessingFn(errorObj, segment); + } + + // stop processing if received empty content + if (response.byteLength === 0) { + return finishProcessingFn({ + status: request.status, + message: 'Empty HLS segment content at URL: ' + request.uri, + code: REQUEST_ERRORS.FAILURE, + xhr: request + }, segment); + } + + segment.map.bytes = new Uint8Array(request.response); + return finishProcessingFn(null, segment); + }; + }; + + /** + * Response handler for segment-requests being sure to set the correct + * property depending on whether the segment is encryped or not + * Also records and keeps track of stats that are used for ABR purposes + * + * @param {Object} segment - a simplified copy of the segmentInfo object + * from SegmentLoader + * @param {Function} finishProcessingFn - a callback to execute to continue processing + * this request + */ + var handleSegmentResponse = function handleSegmentResponse(segment, finishProcessingFn) { + return function (error, request) { + var response = request.response; + var errorObj = handleErrors(error, request); + + if (errorObj) { + return finishProcessingFn(errorObj, segment); + } + + // stop processing if received empty content + if (response.byteLength === 0) { + return finishProcessingFn({ + status: request.status, + message: 'Empty HLS segment content at URL: ' + request.uri, + code: REQUEST_ERRORS.FAILURE, + xhr: request + }, segment); + } + + segment.stats = getRequestStats(request); + + if (segment.key) { + segment.encryptedBytes = new Uint8Array(request.response); + } else { + segment.bytes = new Uint8Array(request.response); + } + + return finishProcessingFn(null, segment); + }; + }; + + /** + * Decrypt the segment via the decryption web worker + * + * @param {WebWorker} decrypter - a WebWorker interface to AES-128 decryption routines + * @param {Object} segment - a simplified copy of the segmentInfo object + * from SegmentLoader + * @param {Function} doneFn - a callback that is executed after decryption has completed + */ + var decryptSegment = function decryptSegment(decrypter, segment, doneFn) { + var decryptionHandler = function decryptionHandler(event) { + if (event.data.source === segment.requestId) { + decrypter.removeEventListener('message', decryptionHandler); + var decrypted = event.data.decrypted; + + segment.bytes = new Uint8Array(decrypted.bytes, decrypted.byteOffset, decrypted.byteLength); + return doneFn(null, segment); + } + }; + + decrypter.addEventListener('message', decryptionHandler); + + // this is an encrypted segment + // incrementally decrypt the segment + decrypter.postMessage(createTransferableMessage({ + source: segment.requestId, + encrypted: segment.encryptedBytes, + key: segment.key.bytes, + iv: segment.key.iv + }), [segment.encryptedBytes.buffer, segment.key.bytes.buffer]); + }; + + /** + * The purpose of this function is to get the most pertinent error from the + * array of errors. + * For instance if a timeout and two aborts occur, then the aborts were + * likely triggered by the timeout so return that error object. + */ + var getMostImportantError = function getMostImportantError(errors) { + return errors.reduce(function (prev, err) { + return err.code > prev.code ? err : prev; + }); + }; + + /** + * This function waits for all XHRs to finish (with either success or failure) + * before continueing processing via it's callback. The function gathers errors + * from each request into a single errors array so that the error status for + * each request can be examined later. + * + * @param {Object} activeXhrs - an object that tracks all XHR requests + * @param {WebWorker} decrypter - a WebWorker interface to AES-128 decryption routines + * @param {Function} doneFn - a callback that is executed after all resources have been + * downloaded and any decryption completed + */ + var waitForCompletion = function waitForCompletion(activeXhrs, decrypter, doneFn) { + var errors = []; + var count = 0; + + return function (error, segment) { + if (error) { + // If there are errors, we have to abort any outstanding requests + abortAll(activeXhrs); + errors.push(error); + } + count += 1; + + if (count === activeXhrs.length) { + // Keep track of when *all* of the requests have completed + segment.endOfAllRequests = Date.now(); + + if (errors.length > 0) { + var worstError = getMostImportantError(errors); + + return doneFn(worstError, segment); + } + if (segment.encryptedBytes) { + return decryptSegment(decrypter, segment, doneFn); + } + // Otherwise, everything is ready just continue + return doneFn(null, segment); + } + }; + }; + + /** + * Simple progress event callback handler that gathers some stats before + * executing a provided callback with the `segment` object + * + * @param {Object} segment - a simplified copy of the segmentInfo object + * from SegmentLoader + * @param {Function} progressFn - a callback that is executed each time a progress event + * is received + * @param {Event} event - the progress event object from XMLHttpRequest + */ + var handleProgress = function handleProgress(segment, progressFn) { + return function (event) { + segment.stats = videojs$1.mergeOptions(segment.stats, getProgressStats(event)); + + // record the time that we receive the first byte of data + if (!segment.stats.firstBytesReceivedAt && segment.stats.bytesReceived) { + segment.stats.firstBytesReceivedAt = Date.now(); + } + + return progressFn(event, segment); + }; + }; + + /** + * Load all resources and does any processing necessary for a media-segment + * + * Features: + * decrypts the media-segment if it has a key uri and an iv + * aborts *all* requests if *any* one request fails + * + * The segment object, at minimum, has the following format: + * { + * resolvedUri: String, + * [byterange]: { + * offset: Number, + * length: Number + * }, + * [key]: { + * resolvedUri: String + * [byterange]: { + * offset: Number, + * length: Number + * }, + * iv: { + * bytes: Uint32Array + * } + * }, + * [map]: { + * resolvedUri: String, + * [byterange]: { + * offset: Number, + * length: Number + * }, + * [bytes]: Uint8Array + * } + * } + * ...where [name] denotes optional properties + * + * @param {Function} xhr - an instance of the xhr wrapper in xhr.js + * @param {Object} xhrOptions - the base options to provide to all xhr requests + * @param {WebWorker} decryptionWorker - a WebWorker interface to AES-128 + * decryption routines + * @param {Object} segment - a simplified copy of the segmentInfo object + * from SegmentLoader + * @param {Function} progressFn - a callback that receives progress events from the main + * segment's xhr request + * @param {Function} doneFn - a callback that is executed only once all requests have + * succeeded or failed + * @returns {Function} a function that, when invoked, immediately aborts all + * outstanding requests + */ + var mediaSegmentRequest = function mediaSegmentRequest(xhr, xhrOptions, decryptionWorker, segment, progressFn, doneFn) { + var activeXhrs = []; + var finishProcessingFn = waitForCompletion(activeXhrs, decryptionWorker, doneFn); + + // optionally, request the decryption key + if (segment.key) { + var keyRequestOptions = videojs$1.mergeOptions(xhrOptions, { + uri: segment.key.resolvedUri, + responseType: 'arraybuffer' + }); + var keyRequestCallback = handleKeyResponse(segment, finishProcessingFn); + var keyXhr = xhr(keyRequestOptions, keyRequestCallback); + + activeXhrs.push(keyXhr); + } + + // optionally, request the associated media init segment + if (segment.map && !segment.map.bytes) { + var initSegmentOptions = videojs$1.mergeOptions(xhrOptions, { + uri: segment.map.resolvedUri, + responseType: 'arraybuffer', + headers: segmentXhrHeaders(segment.map) + }); + var initSegmentRequestCallback = handleInitSegmentResponse(segment, finishProcessingFn); + var initSegmentXhr = xhr(initSegmentOptions, initSegmentRequestCallback); + + activeXhrs.push(initSegmentXhr); + } + + var segmentRequestOptions = videojs$1.mergeOptions(xhrOptions, { + uri: segment.resolvedUri, + responseType: 'arraybuffer', + headers: segmentXhrHeaders(segment) + }); + var segmentRequestCallback = handleSegmentResponse(segment, finishProcessingFn); + var segmentXhr = xhr(segmentRequestOptions, segmentRequestCallback); + + segmentXhr.addEventListener('progress', handleProgress(segment, progressFn)); + activeXhrs.push(segmentXhr); + + return function () { + return abortAll(activeXhrs); + }; + }; + + /** + * @file - codecs.js - Handles tasks regarding codec strings such as translating them to + * codec strings, or translating codec strings into objects that can be examined. + */ + + // Default codec parameters if none were provided for video and/or audio + var defaultCodecs = { + videoCodec: 'avc1', + videoObjectTypeIndicator: '.4d400d', + // AAC-LC + audioProfile: '2' + }; + + /** + * Parses a codec string to retrieve the number of codecs specified, + * the video codec and object type indicator, and the audio profile. + */ + + var parseCodecs = function parseCodecs() { + var codecs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + + var result = { + codecCount: 0 + }; + var parsed = void 0; + + result.codecCount = codecs.split(',').length; + result.codecCount = result.codecCount || 2; + + // parse the video codec + parsed = /(^|\s|,)+(avc[13])([^ ,]*)/i.exec(codecs); + if (parsed) { + result.videoCodec = parsed[2]; + result.videoObjectTypeIndicator = parsed[3]; + } + + // parse the last field of the audio codec + result.audioProfile = /(^|\s|,)+mp4a.[0-9A-Fa-f]+\.([0-9A-Fa-f]+)/i.exec(codecs); + result.audioProfile = result.audioProfile && result.audioProfile[2]; + + return result; + }; + + /** + * Replace codecs in the codec string with the old apple-style `avc1.<dd>.<dd>` to the + * standard `avc1.<hhhhhh>`. + * + * @param codecString {String} the codec string + * @return {String} the codec string with old apple-style codecs replaced + * + * @private + */ + var mapLegacyAvcCodecs = function mapLegacyAvcCodecs(codecString) { + return codecString.replace(/avc1\.(\d+)\.(\d+)/i, function (match) { + return translateLegacyCodecs([match])[0]; + }); + }; + + /** + * Build a media mime-type string from a set of parameters + * @param {String} type either 'audio' or 'video' + * @param {String} container either 'mp2t' or 'mp4' + * @param {Array} codecs an array of codec strings to add + * @return {String} a valid media mime-type + */ + var makeMimeTypeString = function makeMimeTypeString(type, container, codecs) { + // The codecs array is filtered so that falsey values are + // dropped and don't cause Array#join to create spurious + // commas + return type + '/' + container + '; codecs="' + codecs.filter(function (c) { + return !!c; + }).join(', ') + '"'; + }; + + /** + * Returns the type container based on information in the playlist + * @param {Playlist} media the current media playlist + * @return {String} a valid media container type + */ + var getContainerType = function getContainerType(media) { + // An initialization segment means the media playlist is an iframe + // playlist or is using the mp4 container. We don't currently + // support iframe playlists, so assume this is signalling mp4 + // fragments. + if (media.segments && media.segments.length && media.segments[0].map) { + return 'mp4'; + } + return 'mp2t'; + }; + + /** + * Returns a set of codec strings parsed from the playlist or the default + * codec strings if no codecs were specified in the playlist + * @param {Playlist} media the current media playlist + * @return {Object} an object with the video and audio codecs + */ + var getCodecs = function getCodecs(media) { + // if the codecs were explicitly specified, use them instead of the + // defaults + var mediaAttributes = media.attributes || {}; + + if (mediaAttributes.CODECS) { + return parseCodecs(mediaAttributes.CODECS); + } + return defaultCodecs; + }; + + var audioProfileFromDefault = function audioProfileFromDefault(master, audioGroupId) { + if (!master.mediaGroups.AUDIO || !audioGroupId) { + return null; + } + + var audioGroup = master.mediaGroups.AUDIO[audioGroupId]; + + if (!audioGroup) { + return null; + } + + for (var name in audioGroup) { + var audioType = audioGroup[name]; + + if (audioType.default && audioType.playlists) { + // codec should be the same for all playlists within the audio type + return parseCodecs(audioType.playlists[0].attributes.CODECS).audioProfile; + } + } + + return null; + }; + + /** + * Calculates the MIME type strings for a working configuration of + * SourceBuffers to playOld variant streams in a master playlist. If + * there is no possible working configuration, an empty array will be + * returned. + * + * @param master {Object} the m3u8 object for the master playlist + * @param media {Object} the m3u8 object for the variant playlist + * @return {Array} the MIME type strings. If the array has more than + * one entry, the first element should be applied to the video + * SourceBuffer and the second to the audio SourceBuffer. + * + * @private + */ + var mimeTypesForPlaylist = function mimeTypesForPlaylist(master, media) { + var containerType = getContainerType(media); + var codecInfo = getCodecs(media); + var mediaAttributes = media.attributes || {}; + // Default condition for a traditional HLS (no demuxed audio/video) + var isMuxed = true; + var isMaat = false; + + if (!media) { + // Not enough information + return []; + } + + if (master.mediaGroups.AUDIO && mediaAttributes.AUDIO) { + var audioGroup = master.mediaGroups.AUDIO[mediaAttributes.AUDIO]; + + // Handle the case where we are in a multiple-audio track scenario + if (audioGroup) { + isMaat = true; + // Start with the everything demuxed then... + isMuxed = false; + // ...check to see if any audio group tracks are muxed (ie. lacking a uri) + for (var groupId in audioGroup) { + // either a uri is present (if the case of HLS and an external playlist), or + // playlists is present (in the case of DASH where we don't have external audio + // playlists) + if (!audioGroup[groupId].uri && !audioGroup[groupId].playlists) { + isMuxed = true; + break; + } + } + } + } + + // HLS with multiple-audio tracks must always get an audio codec. + // Put another way, there is no way to have a video-only multiple-audio HLS! + if (isMaat && !codecInfo.audioProfile) { + if (!isMuxed) { + // It is possible for codecs to be specified on the audio media group playlist but + // not on the rendition playlist. This is mostly the case for DASH, where audio and + // video are always separate (and separately specified). + codecInfo.audioProfile = audioProfileFromDefault(master, mediaAttributes.AUDIO); + } + + if (!codecInfo.audioProfile) { + videojs$1.log.warn('Multiple audio tracks present but no audio codec string is specified. ' + 'Attempting to use the default audio codec (mp4a.40.2)'); + codecInfo.audioProfile = defaultCodecs.audioProfile; + } + } + + // Generate the final codec strings from the codec object generated above + var codecStrings = {}; + + if (codecInfo.videoCodec) { + codecStrings.video = '' + codecInfo.videoCodec + codecInfo.videoObjectTypeIndicator; + } + + if (codecInfo.audioProfile) { + codecStrings.audio = 'mp4a.40.' + codecInfo.audioProfile; + } + + // Finally, make and return an array with proper mime-types depending on + // the configuration + var justAudio = makeMimeTypeString('audio', containerType, [codecStrings.audio]); + var justVideo = makeMimeTypeString('video', containerType, [codecStrings.video]); + var bothVideoAudio = makeMimeTypeString('video', containerType, [codecStrings.video, codecStrings.audio]); + + if (isMaat) { + if (!isMuxed && codecStrings.video) { + return [justVideo, justAudio]; + } + + if (!isMuxed && !codecStrings.video) { + // There is no muxed content and no video codec string, so this is an audio only + // stream with alternate audio. + return [justAudio, justAudio]; + } + + // There exists the possiblity that this will return a `video/container` + // mime-type for the first entry in the array even when there is only audio. + // This doesn't appear to be a problem and simplifies the code. + return [bothVideoAudio, justAudio]; + } + + // If there is no video codec at all, always just return a single + // audio/<container> mime-type + if (!codecStrings.video) { + return [justAudio]; + } + + // When not using separate audio media groups, audio and video is + // *always* muxed + return [bothVideoAudio]; + }; + + // Utilities + + /** + * Returns the CSS value for the specified property on an element + * using `getComputedStyle`. Firefox has a long-standing issue where + * getComputedStyle() may return null when running in an iframe with + * `display: none`. + * + * @see https://bugzilla.mozilla.org/show_bug.cgi?id=548397 + * @param {HTMLElement} el the htmlelement to work on + * @param {string} the proprety to get the style for + */ + var safeGetComputedStyle = function safeGetComputedStyle(el, property) { + var result = void 0; + + if (!el) { + return ''; + } + + result = window_1.getComputedStyle(el); + if (!result) { + return ''; + } + + return result[property]; + }; + + /** + * Resuable stable sort function + * + * @param {Playlists} array + * @param {Function} sortFn Different comparators + * @function stableSort + */ + var stableSort = function stableSort(array, sortFn) { + var newArray = array.slice(); + + array.sort(function (left, right) { + var cmp = sortFn(left, right); + + if (cmp === 0) { + return newArray.indexOf(left) - newArray.indexOf(right); + } + return cmp; + }); + }; + + /** + * A comparator function to sort two playlist object by bandwidth. + * + * @param {Object} left a media playlist object + * @param {Object} right a media playlist object + * @return {Number} Greater than zero if the bandwidth attribute of + * left is greater than the corresponding attribute of right. Less + * than zero if the bandwidth of right is greater than left and + * exactly zero if the two are equal. + */ + var comparePlaylistBandwidth = function comparePlaylistBandwidth(left, right) { + var leftBandwidth = void 0; + var rightBandwidth = void 0; + + if (left.attributes.BANDWIDTH) { + leftBandwidth = left.attributes.BANDWIDTH; + } + leftBandwidth = leftBandwidth || window_1.Number.MAX_VALUE; + if (right.attributes.BANDWIDTH) { + rightBandwidth = right.attributes.BANDWIDTH; + } + rightBandwidth = rightBandwidth || window_1.Number.MAX_VALUE; + + return leftBandwidth - rightBandwidth; + }; + + /** + * A comparator function to sort two playlist object by resolution (width). + * @param {Object} left a media playlist object + * @param {Object} right a media playlist object + * @return {Number} Greater than zero if the resolution.width attribute of + * left is greater than the corresponding attribute of right. Less + * than zero if the resolution.width of right is greater than left and + * exactly zero if the two are equal. + */ + var comparePlaylistResolution = function comparePlaylistResolution(left, right) { + var leftWidth = void 0; + var rightWidth = void 0; + + if (left.attributes.RESOLUTION && left.attributes.RESOLUTION.width) { + leftWidth = left.attributes.RESOLUTION.width; + } + + leftWidth = leftWidth || window_1.Number.MAX_VALUE; + + if (right.attributes.RESOLUTION && right.attributes.RESOLUTION.width) { + rightWidth = right.attributes.RESOLUTION.width; + } + + rightWidth = rightWidth || window_1.Number.MAX_VALUE; + + // NOTE - Fallback to bandwidth sort as appropriate in cases where multiple renditions + // have the same media dimensions/ resolution + if (leftWidth === rightWidth && left.attributes.BANDWIDTH && right.attributes.BANDWIDTH) { + return left.attributes.BANDWIDTH - right.attributes.BANDWIDTH; + } + return leftWidth - rightWidth; + }; + + /** + * Chooses the appropriate media playlist based on bandwidth and player size + * + * @param {Object} master + * Object representation of the master manifest + * @param {Number} playerBandwidth + * Current calculated bandwidth of the player + * @param {Number} playerWidth + * Current width of the player element + * @param {Number} playerHeight + * Current height of the player element + * @return {Playlist} the highest bitrate playlist less than the + * currently detected bandwidth, accounting for some amount of + * bandwidth variance + */ + var simpleSelector = function simpleSelector(master, playerBandwidth, playerWidth, playerHeight) { + // convert the playlists to an intermediary representation to make comparisons easier + var sortedPlaylistReps = master.playlists.map(function (playlist) { + var width = void 0; + var height = void 0; + var bandwidth = void 0; + + width = playlist.attributes.RESOLUTION && playlist.attributes.RESOLUTION.width; + height = playlist.attributes.RESOLUTION && playlist.attributes.RESOLUTION.height; + bandwidth = playlist.attributes.BANDWIDTH; + + bandwidth = bandwidth || window_1.Number.MAX_VALUE; + + return { + bandwidth: bandwidth, + width: width, + height: height, + playlist: playlist + }; + }); + + stableSort(sortedPlaylistReps, function (left, right) { + return left.bandwidth - right.bandwidth; + }); + + // filter out any playlists that have been excluded due to + // incompatible configurations + sortedPlaylistReps = sortedPlaylistReps.filter(function (rep) { + return !Playlist.isIncompatible(rep.playlist); + }); + + // filter out any playlists that have been disabled manually through the representations + // api or blacklisted temporarily due to playback errors. + var enabledPlaylistReps = sortedPlaylistReps.filter(function (rep) { + return Playlist.isEnabled(rep.playlist); + }); + + if (!enabledPlaylistReps.length) { + // if there are no enabled playlists, then they have all been blacklisted or disabled + // by the user through the representations api. In this case, ignore blacklisting and + // fallback to what the user wants by using playlists the user has not disabled. + enabledPlaylistReps = sortedPlaylistReps.filter(function (rep) { + return !Playlist.isDisabled(rep.playlist); + }); + } + + // filter out any variant that has greater effective bitrate + // than the current estimated bandwidth + var bandwidthPlaylistReps = enabledPlaylistReps.filter(function (rep) { + return rep.bandwidth * Config.BANDWIDTH_VARIANCE < playerBandwidth; + }); + + var highestRemainingBandwidthRep = bandwidthPlaylistReps[bandwidthPlaylistReps.length - 1]; + + // get all of the renditions with the same (highest) bandwidth + // and then taking the very first element + var bandwidthBestRep = bandwidthPlaylistReps.filter(function (rep) { + return rep.bandwidth === highestRemainingBandwidthRep.bandwidth; + })[0]; + + // filter out playlists without resolution information + var haveResolution = bandwidthPlaylistReps.filter(function (rep) { + return rep.width && rep.height; + }); + + // sort variants by resolution + stableSort(haveResolution, function (left, right) { + return left.width - right.width; + }); + + // if we have the exact resolution as the player use it + var resolutionBestRepList = haveResolution.filter(function (rep) { + return rep.width === playerWidth && rep.height === playerHeight; + }); + + highestRemainingBandwidthRep = resolutionBestRepList[resolutionBestRepList.length - 1]; + // ensure that we pick the highest bandwidth variant that have exact resolution + var resolutionBestRep = resolutionBestRepList.filter(function (rep) { + return rep.bandwidth === highestRemainingBandwidthRep.bandwidth; + })[0]; + + var resolutionPlusOneList = void 0; + var resolutionPlusOneSmallest = void 0; + var resolutionPlusOneRep = void 0; + + // find the smallest variant that is larger than the player + // if there is no match of exact resolution + if (!resolutionBestRep) { + resolutionPlusOneList = haveResolution.filter(function (rep) { + return rep.width > playerWidth || rep.height > playerHeight; + }); + + // find all the variants have the same smallest resolution + resolutionPlusOneSmallest = resolutionPlusOneList.filter(function (rep) { + return rep.width === resolutionPlusOneList[0].width && rep.height === resolutionPlusOneList[0].height; + }); + + // ensure that we also pick the highest bandwidth variant that + // is just-larger-than the video player + highestRemainingBandwidthRep = resolutionPlusOneSmallest[resolutionPlusOneSmallest.length - 1]; + resolutionPlusOneRep = resolutionPlusOneSmallest.filter(function (rep) { + return rep.bandwidth === highestRemainingBandwidthRep.bandwidth; + })[0]; + } + + // fallback chain of variants + var chosenRep = resolutionPlusOneRep || resolutionBestRep || bandwidthBestRep || enabledPlaylistReps[0] || sortedPlaylistReps[0]; + + return chosenRep ? chosenRep.playlist : null; + }; + + // Playlist Selectors + + /** + * Chooses the appropriate media playlist based on the most recent + * bandwidth estimate and the player size. + * + * Expects to be called within the context of an instance of HlsHandler + * + * @return {Playlist} the highest bitrate playlist less than the + * currently detected bandwidth, accounting for some amount of + * bandwidth variance + */ + var lastBandwidthSelector = function lastBandwidthSelector() { + return simpleSelector(this.playlists.master, this.systemBandwidth, parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10), parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10)); + }; + + /** + * Chooses the appropriate media playlist based on the potential to rebuffer + * + * @param {Object} settings + * Object of information required to use this selector + * @param {Object} settings.master + * Object representation of the master manifest + * @param {Number} settings.currentTime + * The current time of the player + * @param {Number} settings.bandwidth + * Current measured bandwidth + * @param {Number} settings.duration + * Duration of the media + * @param {Number} settings.segmentDuration + * Segment duration to be used in round trip time calculations + * @param {Number} settings.timeUntilRebuffer + * Time left in seconds until the player has to rebuffer + * @param {Number} settings.currentTimeline + * The current timeline segments are being loaded from + * @param {SyncController} settings.syncController + * SyncController for determining if we have a sync point for a given playlist + * @return {Object|null} + * {Object} return.playlist + * The highest bandwidth playlist with the least amount of rebuffering + * {Number} return.rebufferingImpact + * The amount of time in seconds switching to this playlist will rebuffer. A + * negative value means that switching will cause zero rebuffering. + */ + var minRebufferMaxBandwidthSelector = function minRebufferMaxBandwidthSelector(settings) { + var master = settings.master, + currentTime = settings.currentTime, + bandwidth = settings.bandwidth, + duration$$1 = settings.duration, + segmentDuration = settings.segmentDuration, + timeUntilRebuffer = settings.timeUntilRebuffer, + currentTimeline = settings.currentTimeline, + syncController = settings.syncController; + + // filter out any playlists that have been excluded due to + // incompatible configurations + + var compatiblePlaylists = master.playlists.filter(function (playlist) { + return !Playlist.isIncompatible(playlist); + }); + + // filter out any playlists that have been disabled manually through the representations + // api or blacklisted temporarily due to playback errors. + var enabledPlaylists = compatiblePlaylists.filter(Playlist.isEnabled); + + if (!enabledPlaylists.length) { + // if there are no enabled playlists, then they have all been blacklisted or disabled + // by the user through the representations api. In this case, ignore blacklisting and + // fallback to what the user wants by using playlists the user has not disabled. + enabledPlaylists = compatiblePlaylists.filter(function (playlist) { + return !Playlist.isDisabled(playlist); + }); + } + + var bandwidthPlaylists = enabledPlaylists.filter(Playlist.hasAttribute.bind(null, 'BANDWIDTH')); + + var rebufferingEstimates = bandwidthPlaylists.map(function (playlist) { + var syncPoint = syncController.getSyncPoint(playlist, duration$$1, currentTimeline, currentTime); + // If there is no sync point for this playlist, switching to it will require a + // sync request first. This will double the request time + var numRequests = syncPoint ? 1 : 2; + var requestTimeEstimate = Playlist.estimateSegmentRequestTime(segmentDuration, bandwidth, playlist); + var rebufferingImpact = requestTimeEstimate * numRequests - timeUntilRebuffer; + + return { + playlist: playlist, + rebufferingImpact: rebufferingImpact + }; + }); + + var noRebufferingPlaylists = rebufferingEstimates.filter(function (estimate) { + return estimate.rebufferingImpact <= 0; + }); + + // Sort by bandwidth DESC + stableSort(noRebufferingPlaylists, function (a, b) { + return comparePlaylistBandwidth(b.playlist, a.playlist); + }); + + if (noRebufferingPlaylists.length) { + return noRebufferingPlaylists[0]; + } + + stableSort(rebufferingEstimates, function (a, b) { + return a.rebufferingImpact - b.rebufferingImpact; + }); + + return rebufferingEstimates[0] || null; + }; + + /** + * Chooses the appropriate media playlist, which in this case is the lowest bitrate + * one with video. If no renditions with video exist, return the lowest audio rendition. + * + * Expects to be called within the context of an instance of HlsHandler + * + * @return {Object|null} + * {Object} return.playlist + * The lowest bitrate playlist that contains a video codec. If no such rendition + * exists pick the lowest audio rendition. + */ + var lowestBitrateCompatibleVariantSelector = function lowestBitrateCompatibleVariantSelector() { + // filter out any playlists that have been excluded due to + // incompatible configurations or playback errors + var playlists = this.playlists.master.playlists.filter(Playlist.isEnabled); + + // Sort ascending by bitrate + stableSort(playlists, function (a, b) { + return comparePlaylistBandwidth(a, b); + }); + + // Parse and assume that playlists with no video codec have no video + // (this is not necessarily true, although it is generally true). + // + // If an entire manifest has no valid videos everything will get filtered + // out. + var playlistsWithVideo = playlists.filter(function (playlist) { + return parseCodecs(playlist.attributes.CODECS).videoCodec; + }); + + return playlistsWithVideo[0] || null; + }; + + /** + * @file segment-loader.js + */ + + // in ms + var CHECK_BUFFER_DELAY = 500; + + /** + * Determines if we should call endOfStream on the media source based + * on the state of the buffer or if appened segment was the final + * segment in the playlist. + * + * @param {Object} playlist a media playlist object + * @param {Object} mediaSource the MediaSource object + * @param {Number} segmentIndex the index of segment we last appended + * @returns {Boolean} do we need to call endOfStream on the MediaSource + */ + var detectEndOfStream = function detectEndOfStream(playlist, mediaSource, segmentIndex) { + if (!playlist || !mediaSource) { + return false; + } + + var segments = playlist.segments; + + // determine a few boolean values to help make the branch below easier + // to read + var appendedLastSegment = segmentIndex === segments.length; + + // if we've buffered to the end of the video, we need to call endOfStream + // so that MediaSources can trigger the `ended` event when it runs out of + // buffered data instead of waiting for me + return playlist.endList && mediaSource.readyState === 'open' && appendedLastSegment; + }; + + var finite = function finite(num) { + return typeof num === 'number' && isFinite(num); + }; + + var illegalMediaSwitch = function illegalMediaSwitch(loaderType, startingMedia, newSegmentMedia) { + // Although these checks should most likely cover non 'main' types, for now it narrows + // the scope of our checks. + if (loaderType !== 'main' || !startingMedia || !newSegmentMedia) { + return null; + } + + if (!newSegmentMedia.containsAudio && !newSegmentMedia.containsVideo) { + return 'Neither audio nor video found in segment.'; + } + + if (startingMedia.containsVideo && !newSegmentMedia.containsVideo) { + return 'Only audio found in segment when we expected video.' + ' We can\'t switch to audio only from a stream that had video.' + ' To get rid of this message, please add codec information to the manifest.'; + } + + if (!startingMedia.containsVideo && newSegmentMedia.containsVideo) { + return 'Video found in segment when we expected only audio.' + ' We can\'t switch to a stream with video from an audio only stream.' + ' To get rid of this message, please add codec information to the manifest.'; + } + + return null; + }; + + /** + * Calculates a time value that is safe to remove from the back buffer without interupting + * playback. + * + * @param {TimeRange} seekable + * The current seekable range + * @param {Number} currentTime + * The current time of the player + * @param {Number} targetDuration + * The target duration of the current playlist + * @return {Number} + * Time that is safe to remove from the back buffer without interupting playback + */ + var safeBackBufferTrimTime = function safeBackBufferTrimTime(seekable$$1, currentTime, targetDuration) { + var removeToTime = void 0; + + if (seekable$$1.length && seekable$$1.start(0) > 0 && seekable$$1.start(0) < currentTime) { + // If we have a seekable range use that as the limit for what can be removed safely + removeToTime = seekable$$1.start(0); + } else { + // otherwise remove anything older than 30 seconds before the current playOld head + removeToTime = currentTime - 30; + } + + // Don't allow removing from the buffer within target duration of current time + // to avoid the possibility of removing the GOP currently being played which could + // cause playback stalls. + return Math.min(removeToTime, currentTime - targetDuration); + }; + + var segmentInfoString = function segmentInfoString(segmentInfo) { + var _segmentInfo$segment = segmentInfo.segment, + start = _segmentInfo$segment.start, + end = _segmentInfo$segment.end, + _segmentInfo$playlist = segmentInfo.playlist, + seq = _segmentInfo$playlist.mediaSequence, + id = _segmentInfo$playlist.id, + _segmentInfo$playlist2 = _segmentInfo$playlist.segments, + segments = _segmentInfo$playlist2 === undefined ? [] : _segmentInfo$playlist2, + index = segmentInfo.mediaIndex, + timeline = segmentInfo.timeline; + + + return ['appending [' + index + '] of [' + seq + ', ' + (seq + segments.length) + '] from playlist [' + id + ']', '[' + start + ' => ' + end + '] in timeline [' + timeline + ']'].join(' '); + }; + + /** + * An object that manages segment loading and appending. + * + * @class SegmentLoader + * @param {Object} options required and optional options + * @extends videojs.EventTarget + */ + + var SegmentLoader = function (_videojs$EventTarget3) { + inherits(SegmentLoader, _videojs$EventTarget3); + + function SegmentLoader(settings) { + classCallCheck(this, SegmentLoader); + + // check pre-conditions + var _this22 = possibleConstructorReturn(this, _videojs$EventTarget3.call(this)); + + if (!settings) { + throw new TypeError('Initialization settings are required'); + } + if (typeof settings.currentTime !== 'function') { + throw new TypeError('No currentTime getter specified'); + } + if (!settings.mediaSource) { + throw new TypeError('No MediaSource specified'); + } + // public properties + _this22.bandwidth = settings.bandwidth; + _this22.throughput = {rate: 0, count: 0}; + _this22.roundTrip = NaN; + _this22.resetStats_(); + _this22.mediaIndex = null; + + // private settings + _this22.hasPlayed_ = settings.hasPlayed; + _this22.currentTime_ = settings.currentTime; + _this22.seekable_ = settings.seekable; + _this22.seeking_ = settings.seeking; + _this22.duration_ = settings.duration; + _this22.mediaSource_ = settings.mediaSource; + _this22.hls_ = settings.hls; + _this22.loaderType_ = settings.loaderType; + _this22.startingMedia_ = void 0; + _this22.segmentMetadataTrack_ = settings.segmentMetadataTrack; + _this22.goalBufferLength_ = settings.goalBufferLength; + _this22.sourceType_ = settings.sourceType; + _this22.state_ = 'INIT'; + + // private instance variables + _this22.checkBufferTimeout_ = null; + _this22.error_ = void 0; + _this22.currentTimeline_ = -1; + _this22.pendingSegment_ = null; + _this22.mimeType_ = null; + _this22.sourceUpdater_ = null; + _this22.xhrOptions_ = null; + + // Fragmented mp4 playback + _this22.activeInitSegmentId_ = null; + _this22.initSegments_ = {}; + + _this22.decrypter_ = settings.decrypter; + + // Manages the tracking and generation of sync-points, mappings + // between a time in the display time and a segment index within + // a playlist + _this22.syncController_ = settings.syncController; + _this22.syncPoint_ = { + segmentIndex: 0, + time: 0 + }; + + _this22.syncController_.on('syncinfoupdate', function () { + return _this22.trigger('syncinfoupdate'); + }); + + _this22.mediaSource_.addEventListener('sourceopen', function () { + return _this22.ended_ = false; + }); + + // ...for determining the fetch location + _this22.fetchAtBuffer_ = false; + + _this22.logger_ = logger('SegmentLoader[' + _this22.loaderType_ + ']'); + + Object.defineProperty(_this22, 'state', { + get: function get$$1() { + return this.state_; + }, + set: function set$$1(newState) { + if (newState !== this.state_) { + this.logger_(this.state_ + ' -> ' + newState); + this.state_ = newState; + } + } + }); + return _this22; + } + + /** + * reset all of our media stats + * + * @private + */ + + + SegmentLoader.prototype.resetStats_ = function resetStats_() { + this.mediaBytesTransferred = 0; + this.mediaRequests = 0; + this.mediaRequestsAborted = 0; + this.mediaRequestsTimedout = 0; + this.mediaRequestsErrored = 0; + this.mediaTransferDuration = 0; + this.mediaSecondsLoaded = 0; + }; + + /** + * dispose of the SegmentLoader and reset to the default state + */ + + + SegmentLoader.prototype.dispose = function dispose() { + this.state = 'DISPOSED'; + this.pause(); + this.abort_(); + if (this.sourceUpdater_) { + this.sourceUpdater_.dispose(); + } + this.resetStats_(); + }; + + /** + * abort anything that is currently doing on with the SegmentLoader + * and reset to a default state + */ + + + SegmentLoader.prototype.abort = function abort() { + if (this.state !== 'WAITING') { + if (this.pendingSegment_) { + this.pendingSegment_ = null; + } + return; + } + + this.abort_(); + + // We aborted the requests we were waiting on, so reset the loader's state to READY + // since we are no longer "waiting" on any requests. XHR callback is not always run + // when the request is aborted. This will prevent the loader from being stuck in the + // WAITING state indefinitely. + this.state = 'READY'; + + // don't wait for buffer check timeouts to begin fetching the + // next segment + if (!this.paused()) { + this.monitorBuffer_(); + } + }; + + /** + * abort all pending xhr requests and null any pending segements + * + * @private + */ + + + SegmentLoader.prototype.abort_ = function abort_() { + if (this.pendingSegment_) { + this.pendingSegment_.abortRequests(); + } + + // clear out the segment being processed + this.pendingSegment_ = null; + }; + + /** + * set an error on the segment loader and null out any pending segements + * + * @param {Error} error the error to set on the SegmentLoader + * @return {Error} the error that was set or that is currently set + */ + + + SegmentLoader.prototype.error = function error(_error) { + if (typeof _error !== 'undefined') { + this.error_ = _error; + } + + this.pendingSegment_ = null; + return this.error_; + }; + + SegmentLoader.prototype.endOfStream = function endOfStream() { + this.ended_ = true; + this.pause(); + this.trigger('ended'); + }; + + /** + * Indicates which time ranges are buffered + * + * @return {TimeRange} + * TimeRange object representing the current buffered ranges + */ + + + SegmentLoader.prototype.buffered_ = function buffered_() { + if (!this.sourceUpdater_) { + return videojs$1.createTimeRanges(); + } + + return this.sourceUpdater_.buffered(); + }; + + /** + * Gets and sets init segment for the provided map + * + * @param {Object} map + * The map object representing the init segment to get or set + * @param {Boolean=} set + * If true, the init segment for the provided map should be saved + * @return {Object} + * map object for desired init segment + */ + + + SegmentLoader.prototype.initSegment = function initSegment(map) { + var set$$1 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!map) { + return null; + } + + var id = initSegmentId(map); + var storedMap = this.initSegments_[id]; + + if (set$$1 && !storedMap && map.bytes) { + this.initSegments_[id] = storedMap = { + resolvedUri: map.resolvedUri, + byterange: map.byterange, + bytes: map.bytes + }; + } + + return storedMap || map; + }; + + /** + * Returns true if all configuration required for loading is present, otherwise false. + * + * @return {Boolean} True if the all configuration is ready for loading + * @private + */ + + + SegmentLoader.prototype.couldBeginLoading_ = function couldBeginLoading_() { + return this.playlist_ && ( + // the source updater is created when init_ is called, so either having a + // source updater or being in the INIT state with a mimeType is enough + // to say we have all the needed configuration to start loading. + this.sourceUpdater_ || this.mimeType_ && this.state === 'INIT') && !this.paused(); + }; + + /** + * load a playlist and start to fill the buffer + */ + + + SegmentLoader.prototype.load = function load() { + // un-pause + this.monitorBuffer_(); + + // if we don't have a playlist yet, keep waiting for one to be + // specified + if (!this.playlist_) { + return; + } + + // not sure if this is the best place for this + this.syncController_.setDateTimeMapping(this.playlist_); + + // if all the configuration is ready, initialize and begin loading + if (this.state === 'INIT' && this.couldBeginLoading_()) { + return this.init_(); + } + + // if we're in the middle of processing a segment already, don't + // kick off an additional segment request + if (!this.couldBeginLoading_() || this.state !== 'READY' && this.state !== 'INIT') { + return; + } + + this.state = 'READY'; + }; + + /** + * Once all the starting parameters have been specified, begin + * operation. This method should only be invoked from the INIT + * state. + * + * @private + */ + + + SegmentLoader.prototype.init_ = function init_() { + this.state = 'READY'; + this.sourceUpdater_ = new SourceUpdater(this.mediaSource_, this.mimeType_, this.loaderType_, this.sourceBufferEmitter_); + this.resetEverything(); + return this.monitorBuffer_(); + }; + + /** + * set a playlist on the segment loader + * + * @param {PlaylistLoader} media the playlist to set on the segment loader + */ + + + SegmentLoader.prototype.playlist = function playlist(newPlaylist) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (!newPlaylist) { + return; + } + + var oldPlaylist = this.playlist_; + var segmentInfo = this.pendingSegment_; + + this.playlist_ = newPlaylist; + this.xhrOptions_ = options; + + // when we haven't started playing yet, the start of a live playlist + // is always our zero-time so force a sync update each time the playlist + // is refreshed from the server + if (!this.hasPlayed_()) { + newPlaylist.syncInfo = { + mediaSequence: newPlaylist.mediaSequence, + time: 0 + }; + } + + var oldId = oldPlaylist ? oldPlaylist.id : null; + + this.logger_('playlist update [' + oldId + ' => ' + newPlaylist.id + ']'); + + // in VOD, this is always a rendition switch (or we updated our syncInfo above) + // in LIVE, we always want to update with new playlists (including refreshes) + this.trigger('syncinfoupdate'); + + // if we were unpaused but waiting for a playlist, start + // buffering now + if (this.state === 'INIT' && this.couldBeginLoading_()) { + return this.init_(); + } + + if (!oldPlaylist || oldPlaylist.uri !== newPlaylist.uri) { + if (this.mediaIndex !== null) { + // we must "resync" the segment loader when we switch renditions and + // the segment loader is already synced to the previous rendition + this.resyncLoader(); + } + + // the rest of this function depends on `oldPlaylist` being defined + return; + } + + // we reloaded the same playlist so we are in a live scenario + // and we will likely need to adjust the mediaIndex + var mediaSequenceDiff = newPlaylist.mediaSequence - oldPlaylist.mediaSequence; + + this.logger_('live window shift [' + mediaSequenceDiff + ']'); + + // update the mediaIndex on the SegmentLoader + // this is important because we can abort a request and this value must be + // equal to the last appended mediaIndex + if (this.mediaIndex !== null) { + this.mediaIndex -= mediaSequenceDiff; + } + + // update the mediaIndex on the SegmentInfo object + // this is important because we will update this.mediaIndex with this value + // in `handleUpdateEnd_` after the segment has been successfully appended + if (segmentInfo) { + segmentInfo.mediaIndex -= mediaSequenceDiff; + + // we need to update the referenced segment so that timing information is + // saved for the new playlist's segment, however, if the segment fell off the + // playlist, we can leave the old reference and just lose the timing info + if (segmentInfo.mediaIndex >= 0) { + segmentInfo.segment = newPlaylist.segments[segmentInfo.mediaIndex]; + } + } + + this.syncController_.saveExpiredSegmentInfo(oldPlaylist, newPlaylist); + }; + + /** + * Prevent the loader from fetching additional segments. If there + * is a segment request outstanding, it will finish processing + * before the loader halts. A segment loader can be unpaused by + * calling load(). + */ + + + SegmentLoader.prototype.pause = function pause() { + if (this.checkBufferTimeout_) { + window_1.clearTimeout(this.checkBufferTimeout_); + + this.checkBufferTimeout_ = null; + } + }; + + /** + * Returns whether the segment loader is fetching additional + * segments when given the opportunity. This property can be + * modified through calls to pause() and load(). + */ + + + SegmentLoader.prototype.paused = function paused() { + return this.checkBufferTimeout_ === null; + }; + + /** + * create/set the following mimetype on the SourceBuffer through a + * SourceUpdater + * + * @param {String} mimeType the mime type string to use + * @param {Object} sourceBufferEmitter an event emitter that fires when a source buffer + * is added to the media source + */ + + + SegmentLoader.prototype.mimeType = function mimeType(_mimeType, sourceBufferEmitter) { + if (this.mimeType_) { + return; + } + + this.mimeType_ = _mimeType; + this.sourceBufferEmitter_ = sourceBufferEmitter; + // if we were unpaused but waiting for a sourceUpdater, start + // buffering now + if (this.state === 'INIT' && this.couldBeginLoading_()) { + this.init_(); + } + }; + + /** + * Delete all the buffered data and reset the SegmentLoader + */ + + + SegmentLoader.prototype.resetEverything = function resetEverything() { + this.ended_ = false; + this.resetLoader(); + this.remove(0, this.duration_()); + this.trigger('reseteverything'); + }; + + /** + * Force the SegmentLoader to resync and start loading around the currentTime instead + * of starting at the end of the buffer + * + * Useful for fast quality changes + */ + + + SegmentLoader.prototype.resetLoader = function resetLoader() { + this.fetchAtBuffer_ = false; + this.resyncLoader(); + }; + + /** + * Force the SegmentLoader to restart synchronization and make a conservative guess + * before returning to the simple walk-forward method + */ + + + SegmentLoader.prototype.resyncLoader = function resyncLoader() { + this.mediaIndex = null; + this.syncPoint_ = null; + this.abort(); + }; + + /** + * Remove any data in the source buffer between start and end times + * @param {Number} start - the start time of the region to remove from the buffer + * @param {Number} end - the end time of the region to remove from the buffer + */ + + + SegmentLoader.prototype.remove = function remove(start, end) { + if (this.sourceUpdater_) { + this.sourceUpdater_.remove(start, end); + } + removeCuesFromTrack(start, end, this.segmentMetadataTrack_); + }; + + /** + * (re-)schedule monitorBufferTick_ to run as soon as possible + * + * @private + */ + + + SegmentLoader.prototype.monitorBuffer_ = function monitorBuffer_() { + if (this.checkBufferTimeout_) { + window_1.clearTimeout(this.checkBufferTimeout_); + } + + this.checkBufferTimeout_ = window_1.setTimeout(this.monitorBufferTick_.bind(this), 1); + }; + + /** + * As long as the SegmentLoader is in the READY state, periodically + * invoke fillBuffer_(). + * + * @private + */ + + + SegmentLoader.prototype.monitorBufferTick_ = function monitorBufferTick_() { + if (this.state === 'READY') { + this.fillBuffer_(); + } + + if (this.checkBufferTimeout_) { + window_1.clearTimeout(this.checkBufferTimeout_); + } + + this.checkBufferTimeout_ = window_1.setTimeout(this.monitorBufferTick_.bind(this), CHECK_BUFFER_DELAY); + }; + + /** + * fill the buffer with segements unless the sourceBuffers are + * currently updating + * + * Note: this function should only ever be called by monitorBuffer_ + * and never directly + * + * @private + */ + + + SegmentLoader.prototype.fillBuffer_ = function fillBuffer_() { + if (this.sourceUpdater_.updating()) { + return; + } + + if (!this.syncPoint_) { + this.syncPoint_ = this.syncController_.getSyncPoint(this.playlist_, this.duration_(), this.currentTimeline_, this.currentTime_()); + } + + // see if we need to begin loading immediately + var segmentInfo = this.checkBuffer_(this.buffered_(), this.playlist_, this.mediaIndex, this.hasPlayed_(), this.currentTime_(), this.syncPoint_); + + if (!segmentInfo) { + return; + } + + var isEndOfStream = detectEndOfStream(this.playlist_, this.mediaSource_, segmentInfo.mediaIndex); + + if (isEndOfStream) { + this.endOfStream(); + return; + } + + if (segmentInfo.mediaIndex === this.playlist_.segments.length - 1 && this.mediaSource_.readyState === 'ended' && !this.seeking_()) { + return; + } + + // We will need to change timestampOffset of the sourceBuffer if either of + // the following conditions are true: + // - The segment.timeline !== this.currentTimeline + // (we are crossing a discontinuity somehow) + // - The "timestampOffset" for the start of this segment is less than + // the currently set timestampOffset + if (segmentInfo.timeline !== this.currentTimeline_ || segmentInfo.startOfSegment !== null && segmentInfo.startOfSegment < this.sourceUpdater_.timestampOffset()) { + this.syncController_.reset(); + segmentInfo.timestampOffset = segmentInfo.startOfSegment; + } + + this.loadSegment_(segmentInfo); + }; + + /** + * Determines what segment request should be made, given current playback + * state. + * + * @param {TimeRanges} buffered - the state of the buffer + * @param {Object} playlist - the playlist object to fetch segments from + * @param {Number} mediaIndex - the previous mediaIndex fetched or null + * @param {Boolean} hasPlayed - a flag indicating whether we have played or not + * @param {Number} currentTime - the playback position in seconds + * @param {Object} syncPoint - a segment info object that describes the + * @returns {Object} a segment request object that describes the segment to load + */ + + + SegmentLoader.prototype.checkBuffer_ = function checkBuffer_(buffered, playlist, mediaIndex, hasPlayed, currentTime, syncPoint) { + var lastBufferedEnd = 0; + var startOfSegment = void 0; + + if (buffered.length) { + lastBufferedEnd = buffered.end(buffered.length - 1); + } + + var bufferedTime = Math.max(0, lastBufferedEnd - currentTime); + + if (!playlist.segments.length) { + return null; + } + + // if there is plenty of content buffered, and the video has + // been played before relax for awhile + if (bufferedTime >= this.goalBufferLength_()) { + return null; + } + + // if the video has not yet played once, and we already have + // one segment downloaded do nothing + if (!hasPlayed && bufferedTime >= 1) { + return null; + } + + // When the syncPoint is null, there is no way of determining a good + // conservative segment index to fetch from + // The best thing to do here is to get the kind of sync-point data by + // making a request + if (syncPoint === null) { + mediaIndex = this.getSyncSegmentCandidate_(playlist); + return this.generateSegmentInfo_(playlist, mediaIndex, null, true); + } + + // Under normal playback conditions fetching is a simple walk forward + if (mediaIndex !== null) { + var segment = playlist.segments[mediaIndex]; + + if (segment && segment.end) { + startOfSegment = segment.end; + } else { + startOfSegment = lastBufferedEnd; + } + return this.generateSegmentInfo_(playlist, mediaIndex + 1, startOfSegment, false); + } + + // There is a sync-point but the lack of a mediaIndex indicates that + // we need to make a good conservative guess about which segment to + // fetch + if (this.fetchAtBuffer_) { + // Find the segment containing the end of the buffer + var mediaSourceInfo = Playlist.getMediaInfoForTime(playlist, lastBufferedEnd, syncPoint.segmentIndex, syncPoint.time); + + mediaIndex = mediaSourceInfo.mediaIndex; + startOfSegment = mediaSourceInfo.startTime; + } else { + // Find the segment containing currentTime + var _mediaSourceInfo = Playlist.getMediaInfoForTime(playlist, currentTime, syncPoint.segmentIndex, syncPoint.time); + + mediaIndex = _mediaSourceInfo.mediaIndex; + startOfSegment = _mediaSourceInfo.startTime; + } + + return this.generateSegmentInfo_(playlist, mediaIndex, startOfSegment, false); + }; + + /** + * The segment loader has no recourse except to fetch a segment in the + * current playlist and use the internal timestamps in that segment to + * generate a syncPoint. This function returns a good candidate index + * for that process. + * + * @param {Object} playlist - the playlist object to look for a + * @returns {Number} An index of a segment from the playlist to load + */ + + + SegmentLoader.prototype.getSyncSegmentCandidate_ = function getSyncSegmentCandidate_(playlist) { + var _this23 = this; + + if (this.currentTimeline_ === -1) { + return 0; + } + + var segmentIndexArray = playlist.segments.map(function (s, i) { + return { + timeline: s.timeline, + segmentIndex: i + }; + }).filter(function (s) { + return s.timeline === _this23.currentTimeline_; + }); + + if (segmentIndexArray.length) { + return segmentIndexArray[Math.min(segmentIndexArray.length - 1, 1)].segmentIndex; + } + + return Math.max(playlist.segments.length - 1, 0); + }; + + SegmentLoader.prototype.generateSegmentInfo_ = function generateSegmentInfo_(playlist, mediaIndex, startOfSegment, isSyncRequest) { + if (mediaIndex < 0 || mediaIndex >= playlist.segments.length) { + return null; + } + + var segment = playlist.segments[mediaIndex]; + + return { + requestId: 'segment-loader-' + Math.random(), + // resolve the segment URL relative to the playlist + uri: segment.resolvedUri, + // the segment's mediaIndex at the time it was requested + mediaIndex: mediaIndex, + // whether or not to update the SegmentLoader's state with this + // segment's mediaIndex + isSyncRequest: isSyncRequest, + startOfSegment: startOfSegment, + // the segment's playlist + playlist: playlist, + // unencrypted bytes of the segment + bytes: null, + // when a key is defined for this segment, the encrypted bytes + encryptedBytes: null, + // The target timestampOffset for this segment when we append it + // to the source buffer + timestampOffset: null, + // The timeline that the segment is in + timeline: segment.timeline, + // The expected duration of the segment in seconds + duration: segment.duration, + // retain the segment in case the playlist updates while doing an async process + segment: segment + }; + }; + + /** + * Determines if the network has enough bandwidth to complete the current segment + * request in a timely manner. If not, the request will be aborted early and bandwidth + * updated to trigger a playlist switch. + * + * @param {Object} stats + * Object containing stats about the request timing and size + * @return {Boolean} True if the request was aborted, false otherwise + * @private + */ + + + SegmentLoader.prototype.abortRequestEarly_ = function abortRequestEarly_(stats) { + if (this.hls_.tech_.paused() || + // Don't abort if the current playlist is on the lowestEnabledRendition + // TODO: Replace using timeout with a boolean indicating whether this playlist is + // the lowestEnabledRendition. + !this.xhrOptions_.timeout || + // Don't abort if we have no bandwidth information to estimate segment sizes + !this.playlist_.attributes.BANDWIDTH) { + return false; + } + + // Wait at least 1 second since the first byte of data has been received before + // using the calculated bandwidth from the progress event to allow the bitrate + // to stabilize + if (Date.now() - (stats.firstBytesReceivedAt || Date.now()) < 1000) { + return false; + } + + var currentTime = this.currentTime_(); + var measuredBandwidth = stats.bandwidth; + var segmentDuration = this.pendingSegment_.duration; + + var requestTimeRemaining = Playlist.estimateSegmentRequestTime(segmentDuration, measuredBandwidth, this.playlist_, stats.bytesReceived); + + // Subtract 1 from the timeUntilRebuffer so we still consider an early abort + // if we are only left with less than 1 second when the request completes. + // A negative timeUntilRebuffering indicates we are already rebuffering + var timeUntilRebuffer$$1 = timeUntilRebuffer(this.buffered_(), currentTime, this.hls_.tech_.playbackRate()) - 1; + + // Only consider aborting early if the estimated time to finish the download + // is larger than the estimated time until the player runs out of forward buffer + if (requestTimeRemaining <= timeUntilRebuffer$$1) { + return false; + } + + var switchCandidate = minRebufferMaxBandwidthSelector({ + master: this.hls_.playlists.master, + currentTime: currentTime, + bandwidth: measuredBandwidth, + duration: this.duration_(), + segmentDuration: segmentDuration, + timeUntilRebuffer: timeUntilRebuffer$$1, + currentTimeline: this.currentTimeline_, + syncController: this.syncController_ + }); + + if (!switchCandidate) { + return; + } + + var rebufferingImpact = requestTimeRemaining - timeUntilRebuffer$$1; + + var timeSavedBySwitching = rebufferingImpact - switchCandidate.rebufferingImpact; + + var minimumTimeSaving = 0.5; + + // If we are already rebuffering, increase the amount of variance we add to the + // potential round trip time of the new request so that we are not too aggressive + // with switching to a playlist that might save us a fraction of a second. + if (timeUntilRebuffer$$1 <= TIME_FUDGE_FACTOR) { + minimumTimeSaving = 1; + } + + if (!switchCandidate.playlist || switchCandidate.playlist.uri === this.playlist_.uri || timeSavedBySwitching < minimumTimeSaving) { + return false; + } + + // set the bandwidth to that of the desired playlist being sure to scale by + // BANDWIDTH_VARIANCE and add one so the playlist selector does not exclude it + // don't trigger a bandwidthupdate as the bandwidth is artifial + this.bandwidth = switchCandidate.playlist.attributes.BANDWIDTH * Config.BANDWIDTH_VARIANCE + 1; + this.abort(); + this.trigger('earlyabort'); + return true; + }; + + /** + * XHR `progress` event handler + * + * @param {Event} + * The XHR `progress` event + * @param {Object} simpleSegment + * A simplified segment object copy + * @private + */ + + + SegmentLoader.prototype.handleProgress_ = function handleProgress_(event, simpleSegment) { + if (!this.pendingSegment_ || simpleSegment.requestId !== this.pendingSegment_.requestId || this.abortRequestEarly_(simpleSegment.stats)) { + return; + } + + this.trigger('progress'); + }; + + /** + * load a specific segment from a request into the buffer + * + * @private + */ + + + SegmentLoader.prototype.loadSegment_ = function loadSegment_(segmentInfo) { + this.state = 'WAITING'; + this.pendingSegment_ = segmentInfo; + this.trimBackBuffer_(segmentInfo); + + segmentInfo.abortRequests = mediaSegmentRequest(this.hls_.xhr, this.xhrOptions_, this.decrypter_, this.createSimplifiedSegmentObj_(segmentInfo), + // progress callback + this.handleProgress_.bind(this), this.segmentRequestFinished_.bind(this)); + }; + + /** + * trim the back buffer so that we don't have too much data + * in the source buffer + * + * @private + * + * @param {Object} segmentInfo - the current segment + */ + + + SegmentLoader.prototype.trimBackBuffer_ = function trimBackBuffer_(segmentInfo) { + var removeToTime = safeBackBufferTrimTime(this.seekable_(), this.currentTime_(), this.playlist_.targetDuration || 10); + + // Chrome has a hard limit of 150MB of + // buffer and a very conservative "garbage collector" + // We manually clear out the old buffer to ensure + // we don't trigger the QuotaExceeded error + // on the source buffer during subsequent appends + + if (removeToTime > 0) { + this.remove(0, removeToTime); + } + }; + + /** + * created a simplified copy of the segment object with just the + * information necessary to perform the XHR and decryption + * + * @private + * + * @param {Object} segmentInfo - the current segment + * @returns {Object} a simplified segment object copy + */ + + + SegmentLoader.prototype.createSimplifiedSegmentObj_ = function createSimplifiedSegmentObj_(segmentInfo) { + var segment = segmentInfo.segment; + var simpleSegment = { + resolvedUri: segment.resolvedUri, + byterange: segment.byterange, + requestId: segmentInfo.requestId + }; + + if (segment.key) { + // if the media sequence is greater than 2^32, the IV will be incorrect + // assuming 10s segments, that would be about 1300 years + var iv = segment.key.iv || new Uint32Array([0, 0, 0, segmentInfo.mediaIndex + segmentInfo.playlist.mediaSequence]); + + simpleSegment.key = { + resolvedUri: segment.key.resolvedUri, + iv: iv + }; + } + + if (segment.map) { + simpleSegment.map = this.initSegment(segment.map); + } + + return simpleSegment; + }; + + /** + * Handle the callback from the segmentRequest function and set the + * associated SegmentLoader state and errors if necessary + * + * @private + */ + + + SegmentLoader.prototype.segmentRequestFinished_ = function segmentRequestFinished_(error, simpleSegment) { + // every request counts as a media request even if it has been aborted + // or canceled due to a timeout + this.mediaRequests += 1; + + if (simpleSegment.stats) { + this.mediaBytesTransferred += simpleSegment.stats.bytesReceived; + this.mediaTransferDuration += simpleSegment.stats.roundTripTime; + } + + // The request was aborted and the SegmentLoader has already been reset + if (!this.pendingSegment_) { + this.mediaRequestsAborted += 1; + return; + } + + // the request was aborted and the SegmentLoader has already started + // another request. this can happen when the timeout for an aborted + // request triggers due to a limitation in the XHR library + // do not count this as any sort of request or we risk double-counting + if (simpleSegment.requestId !== this.pendingSegment_.requestId) { + return; + } + + // an error occurred from the active pendingSegment_ so reset everything + if (error) { + this.pendingSegment_ = null; + this.state = 'READY'; + + // the requests were aborted just record the aborted stat and exit + // this is not a true error condition and nothing corrective needs + // to be done + if (error.code === REQUEST_ERRORS.ABORTED) { + this.mediaRequestsAborted += 1; + return; + } + + this.pause(); + + // the error is really just that at least one of the requests timed-out + // set the bandwidth to a very low value and trigger an ABR switch to + // take emergency action + if (error.code === REQUEST_ERRORS.TIMEOUT) { + this.mediaRequestsTimedout += 1; + this.bandwidth = 1; + this.roundTrip = NaN; + this.trigger('bandwidthupdate'); + return; + } + + // if control-flow has arrived here, then the error is real + // emit an error event to blacklist the current playlist + this.mediaRequestsErrored += 1; + this.error(error); + this.trigger('error'); + return; + } + + // the response was a success so set any bandwidth stats the request + // generated for ABR purposes + this.bandwidth = simpleSegment.stats.bandwidth; + this.roundTrip = simpleSegment.stats.roundTripTime; + + // if this request included an initialization segment, save that data + // to the initSegment cache + if (simpleSegment.map) { + simpleSegment.map = this.initSegment(simpleSegment.map, true); + } + + this.processSegmentResponse_(simpleSegment); + }; + + /** + * Move any important data from the simplified segment object + * back to the real segment object for future phases + * + * @private + */ + + + SegmentLoader.prototype.processSegmentResponse_ = function processSegmentResponse_(simpleSegment) { + var segmentInfo = this.pendingSegment_; + + segmentInfo.bytes = simpleSegment.bytes; + if (simpleSegment.map) { + segmentInfo.segment.map.bytes = simpleSegment.map.bytes; + } + + segmentInfo.endOfAllRequests = simpleSegment.endOfAllRequests; + this.handleSegment_(); + }; + + /** + * append a decrypted segement to the SourceBuffer through a SourceUpdater + * + * @private + */ + + + SegmentLoader.prototype.handleSegment_ = function handleSegment_() { + var _this24 = this; + + if (!this.pendingSegment_) { + this.state = 'READY'; + return; + } + + var segmentInfo = this.pendingSegment_; + var segment = segmentInfo.segment; + var timingInfo = this.syncController_.probeSegmentInfo(segmentInfo); + + // When we have our first timing info, determine what media types this loader is + // dealing with. Although we're maintaining extra state, it helps to preserve the + // separation of segment loader from the actual source buffers. + if (typeof this.startingMedia_ === 'undefined' && timingInfo && ( + // Guard against cases where we're not getting timing info at all until we are + // certain that all streams will provide it. + timingInfo.containsAudio || timingInfo.containsVideo)) { + this.startingMedia_ = { + containsAudio: timingInfo.containsAudio, + containsVideo: timingInfo.containsVideo + }; + } + + var illegalMediaSwitchError = illegalMediaSwitch(this.loaderType_, this.startingMedia_, timingInfo); + + if (illegalMediaSwitchError) { + this.error({ + message: illegalMediaSwitchError, + blacklistDuration: Infinity + }); + this.trigger('error'); + return; + } + + if (segmentInfo.isSyncRequest) { + this.trigger('syncinfoupdate'); + this.pendingSegment_ = null; + this.state = 'READY'; + return; + } + + if (segmentInfo.timestampOffset !== null && segmentInfo.timestampOffset !== this.sourceUpdater_.timestampOffset()) { + this.sourceUpdater_.timestampOffset(segmentInfo.timestampOffset); + // fired when a timestamp offset is set in HLS (can also identify discontinuities) + this.trigger('timestampoffset'); + } + + var timelineMapping = this.syncController_.mappingForTimeline(segmentInfo.timeline); + + if (timelineMapping !== null) { + this.trigger({ + type: 'segmenttimemapping', + mapping: timelineMapping + }); + } + + this.state = 'APPENDING'; + + // if the media initialization segment is changing, append it + // before the content segment + if (segment.map) { + var initId = initSegmentId(segment.map); + + if (!this.activeInitSegmentId_ || this.activeInitSegmentId_ !== initId) { + var initSegment = this.initSegment(segment.map); + + this.sourceUpdater_.appendBuffer(initSegment.bytes, function () { + _this24.activeInitSegmentId_ = initId; + }); + } + } + + segmentInfo.byteLength = segmentInfo.bytes.byteLength; + if (typeof segment.start === 'number' && typeof segment.end === 'number') { + this.mediaSecondsLoaded += segment.end - segment.start; + } else { + this.mediaSecondsLoaded += segment.duration; + } + + this.logger_(segmentInfoString(segmentInfo)); + + this.sourceUpdater_.appendBuffer(segmentInfo.bytes, this.handleUpdateEnd_.bind(this)); + }; + + /** + * callback to run when appendBuffer is finished. detects if we are + * in a good state to do things with the data we got, or if we need + * to wait for more + * + * @private + */ + + + SegmentLoader.prototype.handleUpdateEnd_ = function handleUpdateEnd_() { + if (!this.pendingSegment_) { + this.state = 'READY'; + if (!this.paused()) { + this.monitorBuffer_(); + } + return; + } + + var segmentInfo = this.pendingSegment_; + var segment = segmentInfo.segment; + var isWalkingForward = this.mediaIndex !== null; + + this.pendingSegment_ = null; + this.recordThroughput_(segmentInfo); + this.addSegmentMetadataCue_(segmentInfo); + + this.state = 'READY'; + + this.mediaIndex = segmentInfo.mediaIndex; + this.fetchAtBuffer_ = true; + this.currentTimeline_ = segmentInfo.timeline; + + // We must update the syncinfo to recalculate the seekable range before + // the following conditional otherwise it may consider this a bad "guess" + // and attempt to resync when the post-update seekable window and live + // point would mean that this was the perfect segment to fetch + this.trigger('syncinfoupdate'); + + // If we previously appended a segment that ends more than 3 targetDurations before + // the currentTime_ that means that our conservative guess was too conservative. + // In that case, reset the loader state so that we try to use any information gained + // from the previous request to create a new, more accurate, sync-point. + if (segment.end && this.currentTime_() - segment.end > segmentInfo.playlist.targetDuration * 3) { + this.resetEverything(); + return; + } + + // Don't do a rendition switch unless we have enough time to get a sync segment + // and conservatively guess + if (isWalkingForward) { + this.trigger('bandwidthupdate'); + } + this.trigger('progress'); + + // any time an update finishes and the last segment is in the + // buffer, end the stream. this ensures the "ended" event will + // fire if playback reaches that point. + var isEndOfStream = detectEndOfStream(segmentInfo.playlist, this.mediaSource_, segmentInfo.mediaIndex + 1); + + if (isEndOfStream) { + this.endOfStream(); + } + + if (!this.paused()) { + this.monitorBuffer_(); + } + }; + + /** + * Records the current throughput of the decrypt, transmux, and append + * portion of the semgment pipeline. `throughput.rate` is a the cumulative + * moving average of the throughput. `throughput.count` is the number of + * data points in the average. + * + * @private + * @param {Object} segmentInfo the object returned by loadSegment + */ + + + SegmentLoader.prototype.recordThroughput_ = function recordThroughput_(segmentInfo) { + var rate = this.throughput.rate; + // Add one to the time to ensure that we don't accidentally attempt to divide + // by zero in the case where the throughput is ridiculously high + var segmentProcessingTime = Date.now() - segmentInfo.endOfAllRequests + 1; + // Multiply by 8000 to convert from bytes/millisecond to bits/second + var segmentProcessingThroughput = Math.floor(segmentInfo.byteLength / segmentProcessingTime * 8 * 1000); + + // This is just a cumulative moving average calculation: + // newAvg = oldAvg + (sample - oldAvg) / (sampleCount + 1) + this.throughput.rate += (segmentProcessingThroughput - rate) / ++this.throughput.count; + }; + + /** + * Adds a cue to the segment-metadata track with some metadata information about the + * segment + * + * @private + * @param {Object} segmentInfo + * the object returned by loadSegment + * @method addSegmentMetadataCue_ + */ + + + SegmentLoader.prototype.addSegmentMetadataCue_ = function addSegmentMetadataCue_(segmentInfo) { + if (!this.segmentMetadataTrack_) { + return; + } + + var segment = segmentInfo.segment; + var start = segment.start; + var end = segment.end; + + // Do not try adding the cue if the start and end times are invalid. + if (!finite(start) || !finite(end)) { + return; + } + + removeCuesFromTrack(start, end, this.segmentMetadataTrack_); + + var Cue = window_1.WebKitDataCue || window_1.VTTCue; + var value = { + bandwidth: segmentInfo.playlist.attributes.BANDWIDTH, + resolution: segmentInfo.playlist.attributes.RESOLUTION, + codecs: segmentInfo.playlist.attributes.CODECS, + byteLength: segmentInfo.byteLength, + uri: segmentInfo.uri, + timeline: segmentInfo.timeline, + playlist: segmentInfo.playlist.uri, + start: start, + end: end + }; + var data = JSON.stringify(value); + var cue = new Cue(start, end, data); + + // Attach the metadata to the value property of the cue to keep consistency between + // the differences of WebKitDataCue in safari and VTTCue in other browsers + cue.value = value; + + this.segmentMetadataTrack_.addCue(cue); + }; + + return SegmentLoader; + }(videojs$1.EventTarget); + + /** + * @file vtt-segment-loader.js + */ + + var VTT_LINE_TERMINATORS = new Uint8Array('\n\n'.split('').map(function (char) { + return char.charCodeAt(0); + })); + + var uintToString = function uintToString(uintArray) { + return String.fromCharCode.apply(null, uintArray); + }; + + /** + * An object that manages segment loading and appending. + * + * @class VTTSegmentLoader + * @param {Object} options required and optional options + * @extends videojs.EventTarget + */ + + var VTTSegmentLoader = function (_SegmentLoader) { + inherits(VTTSegmentLoader, _SegmentLoader); + + function VTTSegmentLoader(settings) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, VTTSegmentLoader); + + // SegmentLoader requires a MediaSource be specified or it will throw an error; + // however, VTTSegmentLoader has no need of a media source, so delete the reference + var _this25 = possibleConstructorReturn(this, _SegmentLoader.call(this, settings, options)); + + _this25.mediaSource_ = null; + + _this25.subtitlesTrack_ = null; + return _this25; + } + + /** + * Indicates which time ranges are buffered + * + * @return {TimeRange} + * TimeRange object representing the current buffered ranges + */ + + + VTTSegmentLoader.prototype.buffered_ = function buffered_() { + if (!this.subtitlesTrack_ || !this.subtitlesTrack_.cues.length) { + return videojs$1.createTimeRanges(); + } + + var cues = this.subtitlesTrack_.cues; + var start = cues[0].startTime; + var end = cues[cues.length - 1].startTime; + + return videojs$1.createTimeRanges([[start, end]]); + }; + + /** + * Gets and sets init segment for the provided map + * + * @param {Object} map + * The map object representing the init segment to get or set + * @param {Boolean=} set + * If true, the init segment for the provided map should be saved + * @return {Object} + * map object for desired init segment + */ + + + VTTSegmentLoader.prototype.initSegment = function initSegment(map) { + var set$$1 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!map) { + return null; + } + + var id = initSegmentId(map); + var storedMap = this.initSegments_[id]; + + if (set$$1 && !storedMap && map.bytes) { + // append WebVTT line terminators to the media initialization segment if it exists + // to follow the WebVTT spec (https://w3c.github.io/webvtt/#file-structure) that + // requires two or more WebVTT line terminators between the WebVTT header and the + // rest of the file + var combinedByteLength = VTT_LINE_TERMINATORS.byteLength + map.bytes.byteLength; + var combinedSegment = new Uint8Array(combinedByteLength); + + combinedSegment.set(map.bytes); + combinedSegment.set(VTT_LINE_TERMINATORS, map.bytes.byteLength); + + this.initSegments_[id] = storedMap = { + resolvedUri: map.resolvedUri, + byterange: map.byterange, + bytes: combinedSegment + }; + } + + return storedMap || map; + }; + + /** + * Returns true if all configuration required for loading is present, otherwise false. + * + * @return {Boolean} True if the all configuration is ready for loading + * @private + */ + + + VTTSegmentLoader.prototype.couldBeginLoading_ = function couldBeginLoading_() { + return this.playlist_ && this.subtitlesTrack_ && !this.paused(); + }; + + /** + * Once all the starting parameters have been specified, begin + * operation. This method should only be invoked from the INIT + * state. + * + * @private + */ + + + VTTSegmentLoader.prototype.init_ = function init_() { + this.state = 'READY'; + this.resetEverything(); + return this.monitorBuffer_(); + }; + + /** + * Set a subtitle track on the segment loader to add subtitles to + * + * @param {TextTrack=} track + * The text track to add loaded subtitles to + * @return {TextTrack} + * Returns the subtitles track + */ + + + VTTSegmentLoader.prototype.track = function track(_track) { + if (typeof _track === 'undefined') { + return this.subtitlesTrack_; + } + + this.subtitlesTrack_ = _track; + + // if we were unpaused but waiting for a sourceUpdater, start + // buffering now + if (this.state === 'INIT' && this.couldBeginLoading_()) { + this.init_(); + } + + return this.subtitlesTrack_; + }; + + /** + * Remove any data in the source buffer between start and end times + * @param {Number} start - the start time of the region to remove from the buffer + * @param {Number} end - the end time of the region to remove from the buffer + */ + + + VTTSegmentLoader.prototype.remove = function remove(start, end) { + removeCuesFromTrack(start, end, this.subtitlesTrack_); + }; + + /** + * fill the buffer with segements unless the sourceBuffers are + * currently updating + * + * Note: this function should only ever be called by monitorBuffer_ + * and never directly + * + * @private + */ + + + VTTSegmentLoader.prototype.fillBuffer_ = function fillBuffer_() { + var _this26 = this; + + if (!this.syncPoint_) { + this.syncPoint_ = this.syncController_.getSyncPoint(this.playlist_, this.duration_(), this.currentTimeline_, this.currentTime_()); + } + + // see if we need to begin loading immediately + var segmentInfo = this.checkBuffer_(this.buffered_(), this.playlist_, this.mediaIndex, this.hasPlayed_(), this.currentTime_(), this.syncPoint_); + + segmentInfo = this.skipEmptySegments_(segmentInfo); + + if (!segmentInfo) { + return; + } + + if (this.syncController_.timestampOffsetForTimeline(segmentInfo.timeline) === null) { + // We don't have the timestamp offset that we need to sync subtitles. + // Rerun on a timestamp offset or user interaction. + var checkTimestampOffset = function checkTimestampOffset() { + _this26.state = 'READY'; + if (!_this26.paused()) { + // if not paused, queue a buffer check as soon as possible + _this26.monitorBuffer_(); + } + }; + + this.syncController_.one('timestampoffset', checkTimestampOffset); + this.state = 'WAITING_ON_TIMELINE'; + return; + } + + this.loadSegment_(segmentInfo); + }; + + /** + * Prevents the segment loader from requesting segments we know contain no subtitles + * by walking forward until we find the next segment that we don't know whether it is + * empty or not. + * + * @param {Object} segmentInfo + * a segment info object that describes the current segment + * @return {Object} + * a segment info object that describes the current segment + */ + + + VTTSegmentLoader.prototype.skipEmptySegments_ = function skipEmptySegments_(segmentInfo) { + while (segmentInfo && segmentInfo.segment.empty) { + segmentInfo = this.generateSegmentInfo_(segmentInfo.playlist, segmentInfo.mediaIndex + 1, segmentInfo.startOfSegment + segmentInfo.duration, segmentInfo.isSyncRequest); + } + return segmentInfo; + }; + + /** + * append a decrypted segement to the SourceBuffer through a SourceUpdater + * + * @private + */ + + + VTTSegmentLoader.prototype.handleSegment_ = function handleSegment_() { + var _this27 = this; + + if (!this.pendingSegment_ || !this.subtitlesTrack_) { + this.state = 'READY'; + return; + } + + this.state = 'APPENDING'; + + var segmentInfo = this.pendingSegment_; + var segment = segmentInfo.segment; + + // Make sure that vttjs has loaded, otherwise, wait till it finished loading + if (typeof window_1.WebVTT !== 'function' && this.subtitlesTrack_ && this.subtitlesTrack_.tech_) { + + var loadHandler = function loadHandler() { + _this27.handleSegment_(); + }; + + this.state = 'WAITING_ON_VTTJS'; + this.subtitlesTrack_.tech_.one('vttjsloaded', loadHandler); + this.subtitlesTrack_.tech_.one('vttjserror', function () { + _this27.subtitlesTrack_.tech_.off('vttjsloaded', loadHandler); + _this27.error({ + message: 'Error loading vtt.js' + }); + _this27.state = 'READY'; + _this27.pause(); + _this27.trigger('error'); + }); + + return; + } + + segment.requested = true; + + try { + this.parseVTTCues_(segmentInfo); + } catch (e) { + this.error({ + message: e.message + }); + this.state = 'READY'; + this.pause(); + return this.trigger('error'); + } + + this.updateTimeMapping_(segmentInfo, this.syncController_.timelines[segmentInfo.timeline], this.playlist_); + + if (segmentInfo.isSyncRequest) { + this.trigger('syncinfoupdate'); + this.pendingSegment_ = null; + this.state = 'READY'; + return; + } + + segmentInfo.byteLength = segmentInfo.bytes.byteLength; + + this.mediaSecondsLoaded += segment.duration; + + if (segmentInfo.cues.length) { + // remove any overlapping cues to prevent doubling + this.remove(segmentInfo.cues[0].endTime, segmentInfo.cues[segmentInfo.cues.length - 1].endTime); + } + + segmentInfo.cues.forEach(function (cue) { + _this27.subtitlesTrack_.addCue(cue); + }); + + this.handleUpdateEnd_(); + }; + + /** + * Uses the WebVTT parser to parse the segment response + * + * @param {Object} segmentInfo + * a segment info object that describes the current segment + * @private + */ + + + VTTSegmentLoader.prototype.parseVTTCues_ = function parseVTTCues_(segmentInfo) { + var decoder = void 0; + var decodeBytesToString = false; + + if (typeof window_1.TextDecoder === 'function') { + decoder = new window_1.TextDecoder('utf8'); + } else { + decoder = window_1.WebVTT.StringDecoder(); + decodeBytesToString = true; + } + + var parser = new window_1.WebVTT.Parser(window_1, window_1.vttjs, decoder); + + segmentInfo.cues = []; + segmentInfo.timestampmap = {MPEGTS: 0, LOCAL: 0}; + + parser.oncue = segmentInfo.cues.push.bind(segmentInfo.cues); + parser.ontimestampmap = function (map) { + return segmentInfo.timestampmap = map; + }; + parser.onparsingerror = function (error) { + videojs$1.log.warn('Error encountered when parsing cues: ' + error.message); + }; + + if (segmentInfo.segment.map) { + var mapData = segmentInfo.segment.map.bytes; + + if (decodeBytesToString) { + mapData = uintToString(mapData); + } + + parser.parse(mapData); + } + + var segmentData = segmentInfo.bytes; + + if (decodeBytesToString) { + segmentData = uintToString(segmentData); + } + + parser.parse(segmentData); + parser.flush(); + }; + + /** + * Updates the start and end times of any cues parsed by the WebVTT parser using + * the information parsed from the X-TIMESTAMP-MAP header and a TS to media time mapping + * from the SyncController + * + * @param {Object} segmentInfo + * a segment info object that describes the current segment + * @param {Object} mappingObj + * object containing a mapping from TS to media time + * @param {Object} playlist + * the playlist object containing the segment + * @private + */ + + + VTTSegmentLoader.prototype.updateTimeMapping_ = function updateTimeMapping_(segmentInfo, mappingObj, playlist) { + var segment = segmentInfo.segment; + + if (!mappingObj) { + // If the sync controller does not have a mapping of TS to Media Time for the + // timeline, then we don't have enough information to update the cue + // start/end times + return; + } + + if (!segmentInfo.cues.length) { + // If there are no cues, we also do not have enough information to figure out + // segment timing. Mark that the segment contains no cues so we don't re-request + // an empty segment. + segment.empty = true; + return; + } + + var timestampmap = segmentInfo.timestampmap; + var diff = timestampmap.MPEGTS / 90000 - timestampmap.LOCAL + mappingObj.mapping; + + segmentInfo.cues.forEach(function (cue) { + // First convert cue time to TS time using the timestamp-map provided within the vtt + cue.startTime += diff; + cue.endTime += diff; + }); + + if (!playlist.syncInfo) { + var firstStart = segmentInfo.cues[0].startTime; + var lastStart = segmentInfo.cues[segmentInfo.cues.length - 1].startTime; + + playlist.syncInfo = { + mediaSequence: playlist.mediaSequence + segmentInfo.mediaIndex, + time: Math.min(firstStart, lastStart - segment.duration) + }; + } + }; + + return VTTSegmentLoader; + }(SegmentLoader); + + /** + * @file ad-cue-tags.js + */ + + /** + * Searches for an ad cue that overlaps with the given mediaTime + */ + + + var findAdCue = function findAdCue(track, mediaTime) { + var cues = track.cues; + + for (var i = 0; i < cues.length; i++) { + var cue = cues[i]; + + if (mediaTime >= cue.adStartTime && mediaTime <= cue.adEndTime) { + return cue; + } + } + return null; + }; + + var updateAdCues = function updateAdCues(media, track) { + var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + + if (!media.segments) { + return; + } + + var mediaTime = offset; + var cue = void 0; + + for (var i = 0; i < media.segments.length; i++) { + var segment = media.segments[i]; + + if (!cue) { + // Since the cues will span for at least the segment duration, adding a fudge + // factor of half segment duration will prevent duplicate cues from being + // created when timing info is not exact (e.g. cue start time initialized + // at 10.006677, but next call mediaTime is 10.003332 ) + cue = findAdCue(track, mediaTime + segment.duration / 2); + } + + if (cue) { + if ('cueIn' in segment) { + // Found a CUE-IN so end the cue + cue.endTime = mediaTime; + cue.adEndTime = mediaTime; + mediaTime += segment.duration; + cue = null; + continue; + } + + if (mediaTime < cue.endTime) { + // Already processed this mediaTime for this cue + mediaTime += segment.duration; + continue; + } + + // otherwise extend cue until a CUE-IN is found + cue.endTime += segment.duration; + } else { + if ('cueOut' in segment) { + cue = new window_1.VTTCue(mediaTime, mediaTime + segment.duration, segment.cueOut); + cue.adStartTime = mediaTime; + // Assumes tag format to be + // #EXT-X-CUE-OUT:30 + cue.adEndTime = mediaTime + parseFloat(segment.cueOut); + track.addCue(cue); + } + + if ('cueOutCont' in segment) { + // Entered into the middle of an ad cue + var adOffset = void 0; + var adTotal = void 0; + + // Assumes tag formate to be + // #EXT-X-CUE-OUT-CONT:10/30 + + var _segment$cueOutCont$s = segment.cueOutCont.split('/').map(parseFloat); + + adOffset = _segment$cueOutCont$s[0]; + adTotal = _segment$cueOutCont$s[1]; + + + cue = new window_1.VTTCue(mediaTime, mediaTime + segment.duration, ''); + cue.adStartTime = mediaTime - adOffset; + cue.adEndTime = cue.adStartTime + adTotal; + track.addCue(cue); + } + } + mediaTime += segment.duration; + } + }; + + /** + * @file sync-controller.js + */ + + var tsprobe = tsInspector.inspect; + + var syncPointStrategies = [ + // Stategy "VOD": Handle the VOD-case where the sync-point is *always* + // the equivalence display-time 0 === segment-index 0 + { + name: 'VOD', + run: function run(syncController, playlist, duration$$1, currentTimeline, currentTime) { + if (duration$$1 !== Infinity) { + var syncPoint = { + time: 0, + segmentIndex: 0 + }; + + return syncPoint; + } + return null; + } + }, + // Stategy "ProgramDateTime": We have a program-date-time tag in this playlist + { + name: 'ProgramDateTime', + run: function run(syncController, playlist, duration$$1, currentTimeline, currentTime) { + if (!syncController.datetimeToDisplayTime) { + return null; + } + + var segments = playlist.segments || []; + var syncPoint = null; + var lastDistance = null; + + currentTime = currentTime || 0; + + for (var i = 0; i < segments.length; i++) { + var segment = segments[i]; + + if (segment.dateTimeObject) { + var segmentTime = segment.dateTimeObject.getTime() / 1000; + var segmentStart = segmentTime + syncController.datetimeToDisplayTime; + var distance = Math.abs(currentTime - segmentStart); + + // Once the distance begins to increase, we have passed + // currentTime and can stop looking for better candidates + if (lastDistance !== null && lastDistance < distance) { + break; + } + + lastDistance = distance; + syncPoint = { + time: segmentStart, + segmentIndex: i + }; + } + } + return syncPoint; + } + }, + // Stategy "Segment": We have a known time mapping for a timeline and a + // segment in the current timeline with timing data + { + name: 'Segment', + run: function run(syncController, playlist, duration$$1, currentTimeline, currentTime) { + var segments = playlist.segments || []; + var syncPoint = null; + var lastDistance = null; + + currentTime = currentTime || 0; + + for (var i = 0; i < segments.length; i++) { + var segment = segments[i]; + + if (segment.timeline === currentTimeline && typeof segment.start !== 'undefined') { + var distance = Math.abs(currentTime - segment.start); + + // Once the distance begins to increase, we have passed + // currentTime and can stop looking for better candidates + if (lastDistance !== null && lastDistance < distance) { + break; + } + + if (!syncPoint || lastDistance === null || lastDistance >= distance) { + lastDistance = distance; + syncPoint = { + time: segment.start, + segmentIndex: i + }; + } + } + } + return syncPoint; + } + }, + // Stategy "Discontinuity": We have a discontinuity with a known + // display-time + { + name: 'Discontinuity', + run: function run(syncController, playlist, duration$$1, currentTimeline, currentTime) { + var syncPoint = null; + + currentTime = currentTime || 0; + + if (playlist.discontinuityStarts && playlist.discontinuityStarts.length) { + var lastDistance = null; + + for (var i = 0; i < playlist.discontinuityStarts.length; i++) { + var segmentIndex = playlist.discontinuityStarts[i]; + var discontinuity = playlist.discontinuitySequence + i + 1; + var discontinuitySync = syncController.discontinuities[discontinuity]; + + if (discontinuitySync) { + var distance = Math.abs(currentTime - discontinuitySync.time); + + // Once the distance begins to increase, we have passed + // currentTime and can stop looking for better candidates + if (lastDistance !== null && lastDistance < distance) { + break; + } + + if (!syncPoint || lastDistance === null || lastDistance >= distance) { + lastDistance = distance; + syncPoint = { + time: discontinuitySync.time, + segmentIndex: segmentIndex + }; + } + } + } + } + return syncPoint; + } + }, + // Stategy "Playlist": We have a playlist with a known mapping of + // segment index to display time + { + name: 'Playlist', + run: function run(syncController, playlist, duration$$1, currentTimeline, currentTime) { + if (playlist.syncInfo) { + var syncPoint = { + time: playlist.syncInfo.time, + segmentIndex: playlist.syncInfo.mediaSequence - playlist.mediaSequence + }; + + return syncPoint; + } + return null; + } + }]; + + var SyncController = function (_videojs$EventTarget4) { + inherits(SyncController, _videojs$EventTarget4); + + function SyncController() { + classCallCheck(this, SyncController); + + // Segment Loader state variables... + // ...for synching across variants + var _this28 = possibleConstructorReturn(this, _videojs$EventTarget4.call(this)); + + _this28.inspectCache_ = undefined; + + // ...for synching across variants + _this28.timelines = []; + _this28.discontinuities = []; + _this28.datetimeToDisplayTime = null; + + _this28.logger_ = logger('SyncController'); + return _this28; + } + + /** + * Find a sync-point for the playlist specified + * + * A sync-point is defined as a known mapping from display-time to + * a segment-index in the current playlist. + * + * @param {Playlist} playlist + * The playlist that needs a sync-point + * @param {Number} duration + * Duration of the MediaSource (Infinite if playing a live source) + * @param {Number} currentTimeline + * The last timeline from which a segment was loaded + * @returns {Object} + * A sync-point object + */ + + + SyncController.prototype.getSyncPoint = function getSyncPoint(playlist, duration$$1, currentTimeline, currentTime) { + var syncPoints = this.runStrategies_(playlist, duration$$1, currentTimeline, currentTime); + + if (!syncPoints.length) { + // Signal that we need to attempt to get a sync-point manually + // by fetching a segment in the playlist and constructing + // a sync-point from that information + return null; + } + + // Now find the sync-point that is closest to the currentTime because + // that should result in the most accurate guess about which segment + // to fetch + return this.selectSyncPoint_(syncPoints, {key: 'time', value: currentTime}); + }; + + /** + * Calculate the amount of time that has expired off the playlist during playback + * + * @param {Playlist} playlist + * Playlist object to calculate expired from + * @param {Number} duration + * Duration of the MediaSource (Infinity if playling a live source) + * @returns {Number|null} + * The amount of time that has expired off the playlist during playback. Null + * if no sync-points for the playlist can be found. + */ + + + SyncController.prototype.getExpiredTime = function getExpiredTime(playlist, duration$$1) { + if (!playlist || !playlist.segments) { + return null; + } + + var syncPoints = this.runStrategies_(playlist, duration$$1, playlist.discontinuitySequence, 0); + + // Without sync-points, there is not enough information to determine the expired time + if (!syncPoints.length) { + return null; + } + + var syncPoint = this.selectSyncPoint_(syncPoints, { + key: 'segmentIndex', + value: 0 + }); + + // If the sync-point is beyond the start of the playlist, we want to subtract the + // duration from index 0 to syncPoint.segmentIndex instead of adding. + if (syncPoint.segmentIndex > 0) { + syncPoint.time *= -1; + } + + return Math.abs(syncPoint.time + sumDurations(playlist, syncPoint.segmentIndex, 0)); + }; + + /** + * Runs each sync-point strategy and returns a list of sync-points returned by the + * strategies + * + * @private + * @param {Playlist} playlist + * The playlist that needs a sync-point + * @param {Number} duration + * Duration of the MediaSource (Infinity if playing a live source) + * @param {Number} currentTimeline + * The last timeline from which a segment was loaded + * @returns {Array} + * A list of sync-point objects + */ + + + SyncController.prototype.runStrategies_ = function runStrategies_(playlist, duration$$1, currentTimeline, currentTime) { + var syncPoints = []; + + // Try to find a sync-point in by utilizing various strategies... + for (var i = 0; i < syncPointStrategies.length; i++) { + var strategy = syncPointStrategies[i]; + var syncPoint = strategy.run(this, playlist, duration$$1, currentTimeline, currentTime); + + if (syncPoint) { + syncPoint.strategy = strategy.name; + syncPoints.push({ + strategy: strategy.name, + syncPoint: syncPoint + }); + } + } + + return syncPoints; + }; + + /** + * Selects the sync-point nearest the specified target + * + * @private + * @param {Array} syncPoints + * List of sync-points to select from + * @param {Object} target + * Object specifying the property and value we are targeting + * @param {String} target.key + * Specifies the property to target. Must be either 'time' or 'segmentIndex' + * @param {Number} target.value + * The value to target for the specified key. + * @returns {Object} + * The sync-point nearest the target + */ + + + SyncController.prototype.selectSyncPoint_ = function selectSyncPoint_(syncPoints, target) { + var bestSyncPoint = syncPoints[0].syncPoint; + var bestDistance = Math.abs(syncPoints[0].syncPoint[target.key] - target.value); + var bestStrategy = syncPoints[0].strategy; + + for (var i = 1; i < syncPoints.length; i++) { + var newDistance = Math.abs(syncPoints[i].syncPoint[target.key] - target.value); + + if (newDistance < bestDistance) { + bestDistance = newDistance; + bestSyncPoint = syncPoints[i].syncPoint; + bestStrategy = syncPoints[i].strategy; + } + } + + this.logger_('syncPoint for [' + target.key + ': ' + target.value + '] chosen with strategy' + (' [' + bestStrategy + ']: [time:' + bestSyncPoint.time + ',') + (' segmentIndex:' + bestSyncPoint.segmentIndex + ']')); + + return bestSyncPoint; + }; + + /** + * Save any meta-data present on the segments when segments leave + * the live window to the playlist to allow for synchronization at the + * playlist level later. + * + * @param {Playlist} oldPlaylist - The previous active playlist + * @param {Playlist} newPlaylist - The updated and most current playlist + */ + + + SyncController.prototype.saveExpiredSegmentInfo = function saveExpiredSegmentInfo(oldPlaylist, newPlaylist) { + var mediaSequenceDiff = newPlaylist.mediaSequence - oldPlaylist.mediaSequence; + + // When a segment expires from the playlist and it has a start time + // save that information as a possible sync-point reference in future + for (var i = mediaSequenceDiff - 1; i >= 0; i--) { + var lastRemovedSegment = oldPlaylist.segments[i]; + + if (lastRemovedSegment && typeof lastRemovedSegment.start !== 'undefined') { + newPlaylist.syncInfo = { + mediaSequence: oldPlaylist.mediaSequence + i, + time: lastRemovedSegment.start + }; + this.logger_('playlist refresh sync: [time:' + newPlaylist.syncInfo.time + ',' + (' mediaSequence: ' + newPlaylist.syncInfo.mediaSequence + ']')); + this.trigger('syncinfoupdate'); + break; + } + } + }; + + /** + * Save the mapping from playlist's ProgramDateTime to display. This should + * only ever happen once at the start of playback. + * + * @param {Playlist} playlist - The currently active playlist + */ + + + SyncController.prototype.setDateTimeMapping = function setDateTimeMapping(playlist) { + if (!this.datetimeToDisplayTime && playlist.segments && playlist.segments.length && playlist.segments[0].dateTimeObject) { + var playlistTimestamp = playlist.segments[0].dateTimeObject.getTime() / 1000; + + this.datetimeToDisplayTime = -playlistTimestamp; + } + }; + + /** + * Reset the state of the inspection cache when we do a rendition + * switch + */ + + + SyncController.prototype.reset = function reset() { + this.inspectCache_ = undefined; + }; + + /** + * Probe or inspect a fmp4 or an mpeg2-ts segment to determine the start + * and end of the segment in it's internal "media time". Used to generate + * mappings from that internal "media time" to the display time that is + * shown on the player. + * + * @param {SegmentInfo} segmentInfo - The current active request information + */ + + + SyncController.prototype.probeSegmentInfo = function probeSegmentInfo(segmentInfo) { + var segment = segmentInfo.segment; + var playlist = segmentInfo.playlist; + var timingInfo = void 0; + + if (segment.map) { + timingInfo = this.probeMp4Segment_(segmentInfo); + } else { + timingInfo = this.probeTsSegment_(segmentInfo); + } + + if (timingInfo) { + if (this.calculateSegmentTimeMapping_(segmentInfo, timingInfo)) { + this.saveDiscontinuitySyncInfo_(segmentInfo); + + // If the playlist does not have sync information yet, record that information + // now with segment timing information + if (!playlist.syncInfo) { + playlist.syncInfo = { + mediaSequence: playlist.mediaSequence + segmentInfo.mediaIndex, + time: segment.start + }; + } + } + } + + return timingInfo; + }; + + /** + * Probe an fmp4 or an mpeg2-ts segment to determine the start of the segment + * in it's internal "media time". + * + * @private + * @param {SegmentInfo} segmentInfo - The current active request information + * @return {object} The start and end time of the current segment in "media time" + */ + + + SyncController.prototype.probeMp4Segment_ = function probeMp4Segment_(segmentInfo) { + var segment = segmentInfo.segment; + var timescales = probe.timescale(segment.map.bytes); + var startTime = probe.startTime(timescales, segmentInfo.bytes); + + if (segmentInfo.timestampOffset !== null) { + segmentInfo.timestampOffset -= startTime; + } + + return { + start: startTime, + end: startTime + segment.duration + }; + }; + + /** + * Probe an mpeg2-ts segment to determine the start and end of the segment + * in it's internal "media time". + * + * @private + * @param {SegmentInfo} segmentInfo - The current active request information + * @return {object} The start and end time of the current segment in "media time" + */ + + + SyncController.prototype.probeTsSegment_ = function probeTsSegment_(segmentInfo) { + var timeInfo = tsprobe(segmentInfo.bytes, this.inspectCache_); + var segmentStartTime = void 0; + var segmentEndTime = void 0; + + if (!timeInfo) { + return null; + } + + if (timeInfo.video && timeInfo.video.length === 2) { + this.inspectCache_ = timeInfo.video[1].dts; + segmentStartTime = timeInfo.video[0].dtsTime; + segmentEndTime = timeInfo.video[1].dtsTime; + } else if (timeInfo.audio && timeInfo.audio.length === 2) { + this.inspectCache_ = timeInfo.audio[1].dts; + segmentStartTime = timeInfo.audio[0].dtsTime; + segmentEndTime = timeInfo.audio[1].dtsTime; + } + + return { + start: segmentStartTime, + end: segmentEndTime, + containsVideo: timeInfo.video && timeInfo.video.length === 2, + containsAudio: timeInfo.audio && timeInfo.audio.length === 2 + }; + }; + + SyncController.prototype.timestampOffsetForTimeline = function timestampOffsetForTimeline(timeline) { + if (typeof this.timelines[timeline] === 'undefined') { + return null; + } + return this.timelines[timeline].time; + }; + + SyncController.prototype.mappingForTimeline = function mappingForTimeline(timeline) { + if (typeof this.timelines[timeline] === 'undefined') { + return null; + } + return this.timelines[timeline].mapping; + }; + + /** + * Use the "media time" for a segment to generate a mapping to "display time" and + * save that display time to the segment. + * + * @private + * @param {SegmentInfo} segmentInfo + * The current active request information + * @param {object} timingInfo + * The start and end time of the current segment in "media time" + * @returns {Boolean} + * Returns false if segment time mapping could not be calculated + */ + + + SyncController.prototype.calculateSegmentTimeMapping_ = function calculateSegmentTimeMapping_(segmentInfo, timingInfo) { + var segment = segmentInfo.segment; + var mappingObj = this.timelines[segmentInfo.timeline]; + + if (segmentInfo.timestampOffset !== null) { + mappingObj = { + time: segmentInfo.startOfSegment, + mapping: segmentInfo.startOfSegment - timingInfo.start + }; + this.timelines[segmentInfo.timeline] = mappingObj; + this.trigger('timestampoffset'); + + this.logger_('time mapping for timeline ' + segmentInfo.timeline + ': ' + ('[time: ' + mappingObj.time + '] [mapping: ' + mappingObj.mapping + ']')); + + segment.start = segmentInfo.startOfSegment; + segment.end = timingInfo.end + mappingObj.mapping; + } else if (mappingObj) { + segment.start = timingInfo.start + mappingObj.mapping; + segment.end = timingInfo.end + mappingObj.mapping; + } else { + return false; + } + + return true; + }; + + /** + * Each time we have discontinuity in the playlist, attempt to calculate the location + * in display of the start of the discontinuity and save that. We also save an accuracy + * value so that we save values with the most accuracy (closest to 0.) + * + * @private + * @param {SegmentInfo} segmentInfo - The current active request information + */ + + + SyncController.prototype.saveDiscontinuitySyncInfo_ = function saveDiscontinuitySyncInfo_(segmentInfo) { + var playlist = segmentInfo.playlist; + var segment = segmentInfo.segment; + + // If the current segment is a discontinuity then we know exactly where + // the start of the range and it's accuracy is 0 (greater accuracy values + // mean more approximation) + if (segment.discontinuity) { + this.discontinuities[segment.timeline] = { + time: segment.start, + accuracy: 0 + }; + } else if (playlist.discontinuityStarts && playlist.discontinuityStarts.length) { + // Search for future discontinuities that we can provide better timing + // information for and save that information for sync purposes + for (var i = 0; i < playlist.discontinuityStarts.length; i++) { + var segmentIndex = playlist.discontinuityStarts[i]; + var discontinuity = playlist.discontinuitySequence + i + 1; + var mediaIndexDiff = segmentIndex - segmentInfo.mediaIndex; + var accuracy = Math.abs(mediaIndexDiff); + + if (!this.discontinuities[discontinuity] || this.discontinuities[discontinuity].accuracy > accuracy) { + var time = void 0; + + if (mediaIndexDiff < 0) { + time = segment.start - sumDurations(playlist, segmentInfo.mediaIndex, segmentIndex); + } else { + time = segment.end + sumDurations(playlist, segmentInfo.mediaIndex + 1, segmentIndex); + } + + this.discontinuities[discontinuity] = { + time: time, + accuracy: accuracy + }; + } + } + } + }; + + return SyncController; + }(videojs$1.EventTarget); + + var Decrypter$1 = new shimWorker("./decrypter-worker.worker.js", function (window, document$$1) { + var self = this; + var decrypterWorker = function () { + + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + var win; + + if (typeof window !== "undefined") { + win = window; + } else if (typeof commonjsGlobal !== "undefined") { + win = commonjsGlobal; + } else if (typeof self !== "undefined") { + win = self; + } else { + win = {}; + } + + var window_1$$1 = win; + + /* + * pkcs7.pad + * https://github.com/brightcove/pkcs7 + * + * Copyright (c) 2014 Brightcove + * Licensed under the apache2 license. + */ + + /** + * Returns the subarray of a Uint8Array without PKCS#7 padding. + * @param padded {Uint8Array} unencrypted bytes that have been padded + * @return {Uint8Array} the unpadded bytes + * @see http://tools.ietf.org/html/rfc5652 + */ + function unpad(padded) { + return padded.subarray(0, padded.byteLength - padded[padded.byteLength - 1]); + } + + var classCallCheck$$1 = function classCallCheck$$1(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var createClass$$1 = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + var inherits$$1 = function inherits$$1(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === 'undefined' ? 'undefined' : _typeof(superClass))); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + }; + + var possibleConstructorReturn$$1 = function possibleConstructorReturn$$1(self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && ((typeof call === 'undefined' ? 'undefined' : _typeof(call)) === "object" || typeof call === "function") ? call : self; + }; + + /** + * @file aes.js + * + * This file contains an adaptation of the AES decryption algorithm + * from the Standford Javascript Cryptography Library. That work is + * covered by the following copyright and permissions notice: + * + * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the authors. + */ + + /** + * Expand the S-box tables. + * + * @private + */ + var precompute = function precompute() { + var tables = [[[], [], [], [], []], [[], [], [], [], []]]; + var encTable = tables[0]; + var decTable = tables[1]; + var sbox = encTable[4]; + var sboxInv = decTable[4]; + var i = void 0; + var x = void 0; + var xInv = void 0; + var d = []; + var th = []; + var x2 = void 0; + var x4 = void 0; + var x8 = void 0; + var s = void 0; + var tEnc = void 0; + var tDec = void 0; + + // Compute double and third tables + for (i = 0; i < 256; i++) { + th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i; + } + + for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) { + // Compute sbox + s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4; + s = s >> 8 ^ s & 255 ^ 99; + sbox[x] = s; + sboxInv[s] = x; + + // Compute MixColumns + x8 = d[x4 = d[x2 = d[x]]]; + tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100; + tEnc = d[s] * 0x101 ^ s * 0x1010100; + + for (i = 0; i < 4; i++) { + encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8; + decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8; + } + } + + // Compactify. Considerable speedup on Firefox. + for (i = 0; i < 5; i++) { + encTable[i] = encTable[i].slice(0); + decTable[i] = decTable[i].slice(0); + } + return tables; + }; + var aesTables = null; + + /** + * Schedule out an AES key for both encryption and decryption. This + * is a low-level class. Use a cipher mode to do bulk encryption. + * + * @class AES + * @param key {Array} The key as an array of 4, 6 or 8 words. + */ + + var AES = function () { + function AES(key) { + classCallCheck$$1(this, AES); + + /** + * The expanded S-box and inverse S-box tables. These will be computed + * on the client so that we don't have to send them down the wire. + * + * There are two tables, _tables[0] is for encryption and + * _tables[1] is for decryption. + * + * The first 4 sub-tables are the expanded S-box with MixColumns. The + * last (_tables[01][4]) is the S-box itself. + * + * @private + */ + // if we have yet to precompute the S-box tables + // do so now + if (!aesTables) { + aesTables = precompute(); + } + // then make a copy of that object for use + this._tables = [[aesTables[0][0].slice(), aesTables[0][1].slice(), aesTables[0][2].slice(), aesTables[0][3].slice(), aesTables[0][4].slice()], [aesTables[1][0].slice(), aesTables[1][1].slice(), aesTables[1][2].slice(), aesTables[1][3].slice(), aesTables[1][4].slice()]]; + var i = void 0; + var j = void 0; + var tmp = void 0; + var encKey = void 0; + var decKey = void 0; + var sbox = this._tables[0][4]; + var decTable = this._tables[1]; + var keyLen = key.length; + var rcon = 1; + + if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) { + throw new Error('Invalid aes key size'); + } + + encKey = key.slice(0); + decKey = []; + this._key = [encKey, decKey]; + + // schedule encryption keys + for (i = keyLen; i < 4 * keyLen + 28; i++) { + tmp = encKey[i - 1]; + + // apply sbox + if (i % keyLen === 0 || keyLen === 8 && i % keyLen === 4) { + tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255]; + + // shift rows and add rcon + if (i % keyLen === 0) { + tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24; + rcon = rcon << 1 ^ (rcon >> 7) * 283; + } + } + + encKey[i] = encKey[i - keyLen] ^ tmp; + } + + // schedule decryption keys + for (j = 0; i; j++, i--) { + tmp = encKey[j & 3 ? i : i - 4]; + if (i <= 4 || j < 4) { + decKey[j] = tmp; + } else { + decKey[j] = decTable[0][sbox[tmp >>> 24]] ^ decTable[1][sbox[tmp >> 16 & 255]] ^ decTable[2][sbox[tmp >> 8 & 255]] ^ decTable[3][sbox[tmp & 255]]; + } + } + } + + /** + * Decrypt 16 bytes, specified as four 32-bit words. + * + * @param {Number} encrypted0 the first word to decrypt + * @param {Number} encrypted1 the second word to decrypt + * @param {Number} encrypted2 the third word to decrypt + * @param {Number} encrypted3 the fourth word to decrypt + * @param {Int32Array} out the array to write the decrypted words + * into + * @param {Number} offset the offset into the output array to start + * writing results + * @return {Array} The plaintext. + */ + + AES.prototype.decrypt = function decrypt$$1(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) { + var key = this._key[1]; + // state variables a,b,c,d are loaded with pre-whitened data + var a = encrypted0 ^ key[0]; + var b = encrypted3 ^ key[1]; + var c = encrypted2 ^ key[2]; + var d = encrypted1 ^ key[3]; + var a2 = void 0; + var b2 = void 0; + var c2 = void 0; + + // key.length === 2 ? + var nInnerRounds = key.length / 4 - 2; + var i = void 0; + var kIndex = 4; + var table = this._tables[1]; + + // load up the tables + var table0 = table[0]; + var table1 = table[1]; + var table2 = table[2]; + var table3 = table[3]; + var sbox = table[4]; + + // Inner rounds. Cribbed from OpenSSL. + for (i = 0; i < nInnerRounds; i++) { + a2 = table0[a >>> 24] ^ table1[b >> 16 & 255] ^ table2[c >> 8 & 255] ^ table3[d & 255] ^ key[kIndex]; + b2 = table0[b >>> 24] ^ table1[c >> 16 & 255] ^ table2[d >> 8 & 255] ^ table3[a & 255] ^ key[kIndex + 1]; + c2 = table0[c >>> 24] ^ table1[d >> 16 & 255] ^ table2[a >> 8 & 255] ^ table3[b & 255] ^ key[kIndex + 2]; + d = table0[d >>> 24] ^ table1[a >> 16 & 255] ^ table2[b >> 8 & 255] ^ table3[c & 255] ^ key[kIndex + 3]; + kIndex += 4; + a = a2; + b = b2; + c = c2; + } + + // Last round. + for (i = 0; i < 4; i++) { + out[(3 & -i) + offset] = sbox[a >>> 24] << 24 ^ sbox[b >> 16 & 255] << 16 ^ sbox[c >> 8 & 255] << 8 ^ sbox[d & 255] ^ key[kIndex++]; + a2 = a; + a = b; + b = c; + c = d; + d = a2; + } + }; + + return AES; + }(); + + /** + * @file stream.js + */ + /** + * A lightweight readable stream implemention that handles event dispatching. + * + * @class Stream + */ + var Stream = function () { + function Stream() { + classCallCheck$$1(this, Stream); + + this.listeners = {}; + } + + /** + * Add a listener for a specified event type. + * + * @param {String} type the event name + * @param {Function} listener the callback to be invoked when an event of + * the specified type occurs + */ + + Stream.prototype.on = function on(type, listener) { + if (!this.listeners[type]) { + this.listeners[type] = []; + } + this.listeners[type].push(listener); + }; + + /** + * Remove a listener for a specified event type. + * + * @param {String} type the event name + * @param {Function} listener a function previously registered for this + * type of event through `on` + * @return {Boolean} if we could turn it off or not + */ + + Stream.prototype.off = function off(type, listener) { + if (!this.listeners[type]) { + return false; + } + + var index = this.listeners[type].indexOf(listener); + + this.listeners[type].splice(index, 1); + return index > -1; + }; + + /** + * Trigger an event of the specified type on this stream. Any additional + * arguments to this function are passed as parameters to event listeners. + * + * @param {String} type the event name + */ + + Stream.prototype.trigger = function trigger(type) { + var callbacks = this.listeners[type]; + + if (!callbacks) { + return; + } + + // Slicing the arguments on every invocation of this method + // can add a significant amount of overhead. Avoid the + // intermediate object creation for the common case of a + // single callback argument + if (arguments.length === 2) { + var length = callbacks.length; + + for (var i = 0; i < length; ++i) { + callbacks[i].call(this, arguments[1]); + } + } else { + var args = Array.prototype.slice.call(arguments, 1); + var _length = callbacks.length; + + for (var _i = 0; _i < _length; ++_i) { + callbacks[_i].apply(this, args); + } + } + }; + + /** + * Destroys the stream and cleans up. + */ + + Stream.prototype.dispose = function dispose() { + this.listeners = {}; + }; + /** + * Forwards all `data` events on this stream to the destination stream. The + * destination stream should provide a method `push` to receive the data + * events as they arrive. + * + * @param {Stream} destination the stream that will receive all `data` events + * @see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options + */ + + Stream.prototype.pipe = function pipe(destination) { + this.on('data', function (data) { + destination.push(data); + }); + }; + + return Stream; + }(); + + /** + * @file async-stream.js + */ + /** + * A wrapper around the Stream class to use setTiemout + * and run stream "jobs" Asynchronously + * + * @class AsyncStream + * @extends Stream + */ + + var AsyncStream$$1 = function (_Stream) { + inherits$$1(AsyncStream$$1, _Stream); + + function AsyncStream$$1() { + classCallCheck$$1(this, AsyncStream$$1); + + var _this = possibleConstructorReturn$$1(this, _Stream.call(this, Stream)); + + _this.jobs = []; + _this.delay = 1; + _this.timeout_ = null; + return _this; + } + + /** + * process an async job + * + * @private + */ + + AsyncStream$$1.prototype.processJob_ = function processJob_() { + this.jobs.shift()(); + if (this.jobs.length) { + this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay); + } else { + this.timeout_ = null; + } + }; + + /** + * push a job into the stream + * + * @param {Function} job the job to push into the stream + */ + + AsyncStream$$1.prototype.push = function push(job) { + this.jobs.push(job); + if (!this.timeout_) { + this.timeout_ = setTimeout(this.processJob_.bind(this), this.delay); + } + }; + + return AsyncStream$$1; + }(Stream); + + /** + * @file decrypter.js + * + * An asynchronous implementation of AES-128 CBC decryption with + * PKCS#7 padding. + */ + + /** + * Convert network-order (big-endian) bytes into their little-endian + * representation. + */ + var ntoh = function ntoh(word) { + return word << 24 | (word & 0xff00) << 8 | (word & 0xff0000) >> 8 | word >>> 24; + }; + + /** + * Decrypt bytes using AES-128 with CBC and PKCS#7 padding. + * + * @param {Uint8Array} encrypted the encrypted bytes + * @param {Uint32Array} key the bytes of the decryption key + * @param {Uint32Array} initVector the initialization vector (IV) to + * use for the first round of CBC. + * @return {Uint8Array} the decrypted bytes + * + * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard + * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29 + * @see https://tools.ietf.org/html/rfc2315 + */ + var decrypt$$1 = function decrypt$$1(encrypted, key, initVector) { + // word-level access to the encrypted bytes + var encrypted32 = new Int32Array(encrypted.buffer, encrypted.byteOffset, encrypted.byteLength >> 2); + + var decipher = new AES(Array.prototype.slice.call(key)); + + // byte and word-level access for the decrypted output + var decrypted = new Uint8Array(encrypted.byteLength); + var decrypted32 = new Int32Array(decrypted.buffer); + + // temporary variables for working with the IV, encrypted, and + // decrypted data + var init0 = void 0; + var init1 = void 0; + var init2 = void 0; + var init3 = void 0; + var encrypted0 = void 0; + var encrypted1 = void 0; + var encrypted2 = void 0; + var encrypted3 = void 0; + + // iteration variable + var wordIx = void 0; + + // pull out the words of the IV to ensure we don't modify the + // passed-in reference and easier access + init0 = initVector[0]; + init1 = initVector[1]; + init2 = initVector[2]; + init3 = initVector[3]; + + // decrypt four word sequences, applying cipher-block chaining (CBC) + // to each decrypted block + for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) { + // convert big-endian (network order) words into little-endian + // (javascript order) + encrypted0 = ntoh(encrypted32[wordIx]); + encrypted1 = ntoh(encrypted32[wordIx + 1]); + encrypted2 = ntoh(encrypted32[wordIx + 2]); + encrypted3 = ntoh(encrypted32[wordIx + 3]); + + // decrypt the block + decipher.decrypt(encrypted0, encrypted1, encrypted2, encrypted3, decrypted32, wordIx); + + // XOR with the IV, and restore network byte-order to obtain the + // plaintext + decrypted32[wordIx] = ntoh(decrypted32[wordIx] ^ init0); + decrypted32[wordIx + 1] = ntoh(decrypted32[wordIx + 1] ^ init1); + decrypted32[wordIx + 2] = ntoh(decrypted32[wordIx + 2] ^ init2); + decrypted32[wordIx + 3] = ntoh(decrypted32[wordIx + 3] ^ init3); + + // setup the IV for the next round + init0 = encrypted0; + init1 = encrypted1; + init2 = encrypted2; + init3 = encrypted3; + } + + return decrypted; + }; + + /** + * The `Decrypter` class that manages decryption of AES + * data through `AsyncStream` objects and the `decrypt` + * function + * + * @param {Uint8Array} encrypted the encrypted bytes + * @param {Uint32Array} key the bytes of the decryption key + * @param {Uint32Array} initVector the initialization vector (IV) to + * @param {Function} done the function to run when done + * @class Decrypter + */ + + var Decrypter$$1 = function () { + function Decrypter$$1(encrypted, key, initVector, done) { + classCallCheck$$1(this, Decrypter$$1); + + var step = Decrypter$$1.STEP; + var encrypted32 = new Int32Array(encrypted.buffer); + var decrypted = new Uint8Array(encrypted.byteLength); + var i = 0; + + this.asyncStream_ = new AsyncStream$$1(); + + // split up the encryption job and do the individual chunks asynchronously + this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted)); + for (i = step; i < encrypted32.length; i += step) { + initVector = new Uint32Array([ntoh(encrypted32[i - 4]), ntoh(encrypted32[i - 3]), ntoh(encrypted32[i - 2]), ntoh(encrypted32[i - 1])]); + this.asyncStream_.push(this.decryptChunk_(encrypted32.subarray(i, i + step), key, initVector, decrypted)); + } + // invoke the done() callback when everything is finished + this.asyncStream_.push(function () { + // remove pkcs#7 padding from the decrypted bytes + done(null, unpad(decrypted)); + }); + } + + /** + * a getter for step the maximum number of bytes to process at one time + * + * @return {Number} the value of step 32000 + */ + + /** + * @private + */ + Decrypter$$1.prototype.decryptChunk_ = function decryptChunk_(encrypted, key, initVector, decrypted) { + return function () { + var bytes = decrypt$$1(encrypted, key, initVector); + + decrypted.set(bytes, encrypted.byteOffset); + }; + }; + + createClass$$1(Decrypter$$1, null, [{ + key: 'STEP', + get: function get$$1() { + // 4 * 8000; + return 32000; + } + }]); + return Decrypter$$1; + }(); + + /** + * @file bin-utils.js + */ + + /** + * Creates an object for sending to a web worker modifying properties that are TypedArrays + * into a new object with seperated properties for the buffer, byteOffset, and byteLength. + * + * @param {Object} message + * Object of properties and values to send to the web worker + * @return {Object} + * Modified message with TypedArray values expanded + * @function createTransferableMessage + */ + var createTransferableMessage = function createTransferableMessage(message) { + var transferable = {}; + + Object.keys(message).forEach(function (key) { + var value = message[key]; + + if (ArrayBuffer.isView(value)) { + transferable[key] = { + bytes: value.buffer, + byteOffset: value.byteOffset, + byteLength: value.byteLength + }; + } else { + transferable[key] = value; + } + }); + + return transferable; + }; + + /** + * Our web worker interface so that things can talk to aes-decrypter + * that will be running in a web worker. the scope is passed to this by + * webworkify. + * + * @param {Object} self + * the scope for the web worker + */ + var DecrypterWorker = function DecrypterWorker(self) { + self.onmessage = function (event) { + var data = event.data; + var encrypted = new Uint8Array(data.encrypted.bytes, data.encrypted.byteOffset, data.encrypted.byteLength); + var key = new Uint32Array(data.key.bytes, data.key.byteOffset, data.key.byteLength / 4); + var iv = new Uint32Array(data.iv.bytes, data.iv.byteOffset, data.iv.byteLength / 4); + + /* eslint-disable no-new, handle-callback-err */ + new Decrypter$$1(encrypted, key, iv, function (err, bytes) { + window_1$$1.postMessage(createTransferableMessage({ + source: data.source, + decrypted: bytes + }), [bytes.buffer]); + }); + /* eslint-enable */ + }; + }; + + var decrypterWorker = new DecrypterWorker(self); + + return decrypterWorker; + }(); + }); + + /** + * Convert the properties of an HLS track into an audioTrackKind. + * + * @private + */ + var audioTrackKind_ = function audioTrackKind_(properties) { + var kind = properties.default ? 'main' : 'alternative'; + + if (properties.characteristics && properties.characteristics.indexOf('public.accessibility.describes-video') >= 0) { + kind = 'main-desc'; + } + + return kind; + }; + + /** + * Pause provided segment loader and playlist loader if active + * + * @param {SegmentLoader} segmentLoader + * SegmentLoader to pause + * @param {Object} mediaType + * Active media type + * @function stopLoaders + */ + var stopLoaders = function stopLoaders(segmentLoader, mediaType) { + segmentLoader.abort(); + segmentLoader.pause(); + + if (mediaType && mediaType.activePlaylistLoader) { + mediaType.activePlaylistLoader.pause(); + mediaType.activePlaylistLoader = null; + } + }; + + /** + * Start loading provided segment loader and playlist loader + * + * @param {PlaylistLoader} playlistLoader + * PlaylistLoader to start loading + * @param {Object} mediaType + * Active media type + * @function startLoaders + */ + var startLoaders = function startLoaders(playlistLoader, mediaType) { + // Segment loader will be started after `loadedmetadata` or `loadedplaylist` from the + // playlist loader + mediaType.activePlaylistLoader = playlistLoader; + playlistLoader.load(); + }; + + /** + * Returns a function to be called when the media group changes. It performs a + * non-destructive (preserve the buffer) resync of the SegmentLoader. This is because a + * change of group is merely a rendition switch of the same content at another encoding, + * rather than a change of content, such as switching audio from English to Spanish. + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @return {Function} + * Handler for a non-destructive resync of SegmentLoader when the active media + * group changes. + * @function onGroupChanged + */ + var onGroupChanged = function onGroupChanged(type, settings) { + return function () { + var _settings$segmentLoad = settings.segmentLoaders, + segmentLoader = _settings$segmentLoad[type], + mainSegmentLoader = _settings$segmentLoad.main, + mediaType = settings.mediaTypes[type]; + + var activeTrack = mediaType.activeTrack(); + var activeGroup = mediaType.activeGroup(activeTrack); + var previousActiveLoader = mediaType.activePlaylistLoader; + + stopLoaders(segmentLoader, mediaType); + + if (!activeGroup) { + // there is no group active + return; + } + + if (!activeGroup.playlistLoader) { + if (previousActiveLoader) { + // The previous group had a playlist loader but the new active group does not + // this means we are switching from demuxed to muxed audio. In this case we want to + // do a destructive reset of the main segment loader and not restart the audio + // loaders. + mainSegmentLoader.resetEverything(); + } + return; + } + + // Non-destructive resync + segmentLoader.resyncLoader(); + + startLoaders(activeGroup.playlistLoader, mediaType); + }; + }; + + /** + * Returns a function to be called when the media track changes. It performs a + * destructive reset of the SegmentLoader to ensure we start loading as close to + * currentTime as possible. + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @return {Function} + * Handler for a destructive reset of SegmentLoader when the active media + * track changes. + * @function onTrackChanged + */ + var onTrackChanged = function onTrackChanged(type, settings) { + return function () { + var _settings$segmentLoad2 = settings.segmentLoaders, + segmentLoader = _settings$segmentLoad2[type], + mainSegmentLoader = _settings$segmentLoad2.main, + mediaType = settings.mediaTypes[type]; + + var activeTrack = mediaType.activeTrack(); + var activeGroup = mediaType.activeGroup(activeTrack); + var previousActiveLoader = mediaType.activePlaylistLoader; + + stopLoaders(segmentLoader, mediaType); + + if (!activeGroup) { + // there is no group active so we do not want to restart loaders + return; + } + + if (!activeGroup.playlistLoader) { + // when switching from demuxed audio/video to muxed audio/video (noted by no playlist + // loader for the audio group), we want to do a destructive reset of the main segment + // loader and not restart the audio loaders + mainSegmentLoader.resetEverything(); + return; + } + + if (previousActiveLoader === activeGroup.playlistLoader) { + // Nothing has actually changed. This can happen because track change events can fire + // multiple times for a "single" change. One for enabling the new active track, and + // one for disabling the track that was active + startLoaders(activeGroup.playlistLoader, mediaType); + return; + } + + if (segmentLoader.track) { + // For WebVTT, set the new text track in the segmentloader + segmentLoader.track(activeTrack); + } + + // destructive reset + segmentLoader.resetEverything(); + + startLoaders(activeGroup.playlistLoader, mediaType); + }; + }; + + var onError = { + /** + * Returns a function to be called when a SegmentLoader or PlaylistLoader encounters + * an error. + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @return {Function} + * Error handler. Logs warning (or error if the playlist is blacklisted) to + * console and switches back to default audio track. + * @function onError.AUDIO + */ + AUDIO: function AUDIO(type, settings) { + return function () { + var segmentLoader = settings.segmentLoaders[type], + mediaType = settings.mediaTypes[type], + blacklistCurrentPlaylist = settings.blacklistCurrentPlaylist; + + + stopLoaders(segmentLoader, mediaType); + + // switch back to default audio track + var activeTrack = mediaType.activeTrack(); + var activeGroup = mediaType.activeGroup(); + var id = (activeGroup.filter(function (group) { + return group.default; + })[0] || activeGroup[0]).id; + var defaultTrack = mediaType.tracks[id]; + + if (activeTrack === defaultTrack) { + // Default track encountered an error. All we can do now is blacklist the current + // rendition and hope another will switch audio groups + blacklistCurrentPlaylist({ + message: 'Problem encountered loading the default audio track.' + }); + return; + } + + videojs$1.log.warn('Problem encountered loading the alternate audio track.' + 'Switching back to default.'); + + for (var trackId in mediaType.tracks) { + mediaType.tracks[trackId].enabled = mediaType.tracks[trackId] === defaultTrack; + } + + mediaType.onTrackChanged(); + }; + }, + /** + * Returns a function to be called when a SegmentLoader or PlaylistLoader encounters + * an error. + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @return {Function} + * Error handler. Logs warning to console and disables the active subtitle track + * @function onError.SUBTITLES + */ + SUBTITLES: function SUBTITLES(type, settings) { + return function () { + var segmentLoader = settings.segmentLoaders[type], + mediaType = settings.mediaTypes[type]; + + + videojs$1.log.warn('Problem encountered loading the subtitle track.' + 'Disabling subtitle track.'); + + stopLoaders(segmentLoader, mediaType); + + var track = mediaType.activeTrack(); + + if (track) { + track.mode = 'disabled'; + } + + mediaType.onTrackChanged(); + }; + } + }; + + var setupListeners = { + /** + * Setup event listeners for audio playlist loader + * + * @param {String} type + * MediaGroup type + * @param {PlaylistLoader|null} playlistLoader + * PlaylistLoader to register listeners on + * @param {Object} settings + * Object containing required information for media groups + * @function setupListeners.AUDIO + */ + AUDIO: function AUDIO(type, playlistLoader, settings) { + if (!playlistLoader) { + // no playlist loader means audio will be muxed with the video + return; + } + + var tech = settings.tech, + requestOptions = settings.requestOptions, + segmentLoader = settings.segmentLoaders[type]; + + + playlistLoader.on('loadedmetadata', function () { + var media = playlistLoader.media(); + + segmentLoader.playlist(media, requestOptions); + + // if the video is already playing, or if this isn't a live video and preload + // permits, start downloading segments + if (!tech.paused() || media.endList && tech.preload() !== 'none') { + segmentLoader.load(); + } + }); + + playlistLoader.on('loadedplaylist', function () { + segmentLoader.playlist(playlistLoader.media(), requestOptions); + + // If the player isn't paused, ensure that the segment loader is running + if (!tech.paused()) { + segmentLoader.load(); + } + }); + + playlistLoader.on('error', onError[type](type, settings)); + }, + /** + * Setup event listeners for subtitle playlist loader + * + * @param {String} type + * MediaGroup type + * @param {PlaylistLoader|null} playlistLoader + * PlaylistLoader to register listeners on + * @param {Object} settings + * Object containing required information for media groups + * @function setupListeners.SUBTITLES + */ + SUBTITLES: function SUBTITLES(type, playlistLoader, settings) { + var tech = settings.tech, + requestOptions = settings.requestOptions, + segmentLoader = settings.segmentLoaders[type], + mediaType = settings.mediaTypes[type]; + + + playlistLoader.on('loadedmetadata', function () { + var media = playlistLoader.media(); + + segmentLoader.playlist(media, requestOptions); + segmentLoader.track(mediaType.activeTrack()); + + // if the video is already playing, or if this isn't a live video and preload + // permits, start downloading segments + if (!tech.paused() || media.endList && tech.preload() !== 'none') { + segmentLoader.load(); + } + }); + + playlistLoader.on('loadedplaylist', function () { + segmentLoader.playlist(playlistLoader.media(), requestOptions); + + // If the player isn't paused, ensure that the segment loader is running + if (!tech.paused()) { + segmentLoader.load(); + } + }); + + playlistLoader.on('error', onError[type](type, settings)); + } + }; + + var byGroupId = function byGroupId(type, groupId) { + return function (playlist) { + return playlist.attributes[type] === groupId; + }; + }; + + var byResolvedUri = function byResolvedUri(resolvedUri) { + return function (playlist) { + return playlist.resolvedUri === resolvedUri; + }; + }; + + var initialize = { + /** + * Setup PlaylistLoaders and AudioTracks for the audio groups + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @function initialize.AUDIO + */ + 'AUDIO': function AUDIO(type, settings) { + var hls = settings.hls, + sourceType = settings.sourceType, + segmentLoader = settings.segmentLoaders[type], + withCredentials = settings.requestOptions.withCredentials, + _settings$master = settings.master, + mediaGroups = _settings$master.mediaGroups, + playlists = _settings$master.playlists, + _settings$mediaTypes$ = settings.mediaTypes[type], + groups = _settings$mediaTypes$.groups, + tracks = _settings$mediaTypes$.tracks, + masterPlaylistLoader = settings.masterPlaylistLoader; + + // force a default if we have none + + if (!mediaGroups[type] || Object.keys(mediaGroups[type]).length === 0) { + mediaGroups[type] = {main: {default: {default: true}}}; + } + + for (var groupId in mediaGroups[type]) { + if (!groups[groupId]) { + groups[groupId] = []; + } + + // List of playlists that have an AUDIO attribute value matching the current + // group ID + var groupPlaylists = playlists.filter(byGroupId(type, groupId)); + + for (var variantLabel in mediaGroups[type][groupId]) { + var properties = mediaGroups[type][groupId][variantLabel]; + + // List of playlists for the current group ID that have a matching uri with + // this alternate audio variant + var matchingPlaylists = groupPlaylists.filter(byResolvedUri(properties.resolvedUri)); + + if (matchingPlaylists.length) { + // If there is a playlist that has the same uri as this audio variant, assume + // that the playlist is audio only. We delete the resolvedUri property here + // to prevent a playlist loader from being created so that we don't have + // both the main and audio segment loaders loading the same audio segments + // from the same playlist. + delete properties.resolvedUri; + } + + var playlistLoader = void 0; + + if (properties.resolvedUri) { + playlistLoader = new PlaylistLoader(properties.resolvedUri, hls, withCredentials); + } else if (properties.playlists && sourceType === 'dash') { + playlistLoader = new DashPlaylistLoader(properties.playlists[0], hls, withCredentials, masterPlaylistLoader); + } else { + // no resolvedUri means the audio is muxed with the video when using this + // audio track + playlistLoader = null; + } + + properties = videojs$1.mergeOptions({id: variantLabel, playlistLoader: playlistLoader}, properties); + + setupListeners[type](type, properties.playlistLoader, settings); + + groups[groupId].push(properties); + + if (typeof tracks[variantLabel] === 'undefined') { + var track = new videojs$1.AudioTrack({ + id: variantLabel, + kind: audioTrackKind_(properties), + enabled: false, + language: properties.language, + default: properties.default, + label: variantLabel + }); + + tracks[variantLabel] = track; + } + } + } + + // setup single error event handler for the segment loader + segmentLoader.on('error', onError[type](type, settings)); + }, + /** + * Setup PlaylistLoaders and TextTracks for the subtitle groups + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @function initialize.SUBTITLES + */ + 'SUBTITLES': function SUBTITLES(type, settings) { + var tech = settings.tech, + hls = settings.hls, + sourceType = settings.sourceType, + segmentLoader = settings.segmentLoaders[type], + withCredentials = settings.requestOptions.withCredentials, + mediaGroups = settings.master.mediaGroups, + _settings$mediaTypes$2 = settings.mediaTypes[type], + groups = _settings$mediaTypes$2.groups, + tracks = _settings$mediaTypes$2.tracks, + masterPlaylistLoader = settings.masterPlaylistLoader; + + + for (var groupId in mediaGroups[type]) { + if (!groups[groupId]) { + groups[groupId] = []; + } + + for (var variantLabel in mediaGroups[type][groupId]) { + if (mediaGroups[type][groupId][variantLabel].forced) { + // Subtitle playlists with the forced attribute are not selectable in Safari. + // According to Apple's HLS Authoring Specification: + // If content has forced subtitles and regular subtitles in a given language, + // the regular subtitles track in that language MUST contain both the forced + // subtitles and the regular subtitles for that language. + // Because of this requirement and that Safari does not add forced subtitles, + // forced subtitles are skipped here to maintain consistent experience across + // all platforms + continue; + } + + var properties = mediaGroups[type][groupId][variantLabel]; + + var playlistLoader = void 0; + + if (sourceType === 'hls') { + playlistLoader = new PlaylistLoader(properties.resolvedUri, hls, withCredentials); + } else if (sourceType === 'dash') { + playlistLoader = new DashPlaylistLoader(properties.playlists[0], hls, withCredentials, masterPlaylistLoader); + } + + properties = videojs$1.mergeOptions({ + id: variantLabel, + playlistLoader: playlistLoader + }, properties); + + setupListeners[type](type, properties.playlistLoader, settings); + + groups[groupId].push(properties); + + if (typeof tracks[variantLabel] === 'undefined') { + var track = tech.addRemoteTextTrack({ + id: variantLabel, + kind: 'subtitles', + enabled: false, + language: properties.language, + label: variantLabel + }, false).track; + + tracks[variantLabel] = track; + } + } + } + + // setup single error event handler for the segment loader + segmentLoader.on('error', onError[type](type, settings)); + }, + /** + * Setup TextTracks for the closed-caption groups + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @function initialize['CLOSED-CAPTIONS'] + */ + 'CLOSED-CAPTIONS': function CLOSEDCAPTIONS(type, settings) { + var tech = settings.tech, + mediaGroups = settings.master.mediaGroups, + _settings$mediaTypes$3 = settings.mediaTypes[type], + groups = _settings$mediaTypes$3.groups, + tracks = _settings$mediaTypes$3.tracks; + + + for (var groupId in mediaGroups[type]) { + if (!groups[groupId]) { + groups[groupId] = []; + } + + for (var variantLabel in mediaGroups[type][groupId]) { + var properties = mediaGroups[type][groupId][variantLabel]; + + // We only support CEA608 captions for now, so ignore anything that + // doesn't use a CCx INSTREAM-ID + if (!properties.instreamId.match(/CC\d/)) { + continue; + } + + // No PlaylistLoader is required for Closed-Captions because the captions are + // embedded within the video stream + groups[groupId].push(videojs$1.mergeOptions({id: variantLabel}, properties)); + + if (typeof tracks[variantLabel] === 'undefined') { + var track = tech.addRemoteTextTrack({ + id: properties.instreamId, + kind: 'captions', + enabled: false, + language: properties.language, + label: variantLabel + }, false).track; + + tracks[variantLabel] = track; + } + } + } + } + }; + + /** + * Returns a function used to get the active group of the provided type + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @return {Function} + * Function that returns the active media group for the provided type. Takes an + * optional parameter {TextTrack} track. If no track is provided, a list of all + * variants in the group, otherwise the variant corresponding to the provided + * track is returned. + * @function activeGroup + */ + var activeGroup = function activeGroup(type, settings) { + return function (track) { + var masterPlaylistLoader = settings.masterPlaylistLoader, + groups = settings.mediaTypes[type].groups; + + + var media = masterPlaylistLoader.media(); + + if (!media) { + return null; + } + + var variants = null; + + if (media.attributes[type]) { + variants = groups[media.attributes[type]]; + } + + variants = variants || groups.main; + + if (typeof track === 'undefined') { + return variants; + } + + if (track === null) { + // An active track was specified so a corresponding group is expected. track === null + // means no track is currently active so there is no corresponding group + return null; + } + + return variants.filter(function (props) { + return props.id === track.id; + })[0] || null; + }; + }; + + var activeTrack = { + /** + * Returns a function used to get the active track of type provided + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @return {Function} + * Function that returns the active media track for the provided type. Returns + * null if no track is active + * @function activeTrack.AUDIO + */ + AUDIO: function AUDIO(type, settings) { + return function () { + var tracks = settings.mediaTypes[type].tracks; + + + for (var id in tracks) { + if (tracks[id].enabled) { + return tracks[id]; + } + } + + return null; + }; + }, + /** + * Returns a function used to get the active track of type provided + * + * @param {String} type + * MediaGroup type + * @param {Object} settings + * Object containing required information for media groups + * @return {Function} + * Function that returns the active media track for the provided type. Returns + * null if no track is active + * @function activeTrack.SUBTITLES + */ + SUBTITLES: function SUBTITLES(type, settings) { + return function () { + var tracks = settings.mediaTypes[type].tracks; + + + for (var id in tracks) { + if (tracks[id].mode === 'showing') { + return tracks[id]; + } + } + + return null; + }; + } + }; + + /** + * Setup PlaylistLoaders and Tracks for media groups (Audio, Subtitles, + * Closed-Captions) specified in the master manifest. + * + * @param {Object} settings + * Object containing required information for setting up the media groups + * @param {SegmentLoader} settings.segmentLoaders.AUDIO + * Audio segment loader + * @param {SegmentLoader} settings.segmentLoaders.SUBTITLES + * Subtitle segment loader + * @param {SegmentLoader} settings.segmentLoaders.main + * Main segment loader + * @param {Tech} settings.tech + * The tech of the player + * @param {Object} settings.requestOptions + * XHR request options used by the segment loaders + * @param {PlaylistLoader} settings.masterPlaylistLoader + * PlaylistLoader for the master source + * @param {HlsHandler} settings.hls + * HLS SourceHandler + * @param {Object} settings.master + * The parsed master manifest + * @param {Object} settings.mediaTypes + * Object to store the loaders, tracks, and utility methods for each media type + * @param {Function} settings.blacklistCurrentPlaylist + * Blacklists the current rendition and forces a rendition switch. + * @function setupMediaGroups + */ + var setupMediaGroups = function setupMediaGroups(settings) { + ['AUDIO', 'SUBTITLES', 'CLOSED-CAPTIONS'].forEach(function (type) { + initialize[type](type, settings); + }); + + var mediaTypes = settings.mediaTypes, + masterPlaylistLoader = settings.masterPlaylistLoader, + tech = settings.tech, + hls = settings.hls; + + // setup active group and track getters and change event handlers + + ['AUDIO', 'SUBTITLES'].forEach(function (type) { + mediaTypes[type].activeGroup = activeGroup(type, settings); + mediaTypes[type].activeTrack = activeTrack[type](type, settings); + mediaTypes[type].onGroupChanged = onGroupChanged(type, settings); + mediaTypes[type].onTrackChanged = onTrackChanged(type, settings); + }); + + // DO NOT enable the default subtitle or caption track. + // DO enable the default audio track + var audioGroup = mediaTypes.AUDIO.activeGroup(); + var groupId = (audioGroup.filter(function (group) { + return group.default; + })[0] || audioGroup[0]).id; + + mediaTypes.AUDIO.tracks[groupId].enabled = true; + mediaTypes.AUDIO.onTrackChanged(); + + masterPlaylistLoader.on('mediachange', function () { + ['AUDIO', 'SUBTITLES'].forEach(function (type) { + return mediaTypes[type].onGroupChanged(); + }); + }); + + // custom audio track change event handler for usage event + var onAudioTrackChanged = function onAudioTrackChanged() { + mediaTypes.AUDIO.onTrackChanged(); + tech.trigger({type: 'usage', name: 'hls-audio-change'}); + }; + + tech.audioTracks().addEventListener('change', onAudioTrackChanged); + tech.remoteTextTracks().addEventListener('change', mediaTypes.SUBTITLES.onTrackChanged); + + hls.on('dispose', function () { + tech.audioTracks().removeEventListener('change', onAudioTrackChanged); + tech.remoteTextTracks().removeEventListener('change', mediaTypes.SUBTITLES.onTrackChanged); + }); + + // clear existing audio tracks and add the ones we just created + tech.clearTracks('audio'); + + for (var id in mediaTypes.AUDIO.tracks) { + tech.audioTracks().addTrack(mediaTypes.AUDIO.tracks[id]); + } + }; + + /** + * Creates skeleton object used to store the loaders, tracks, and utility methods for each + * media type + * + * @return {Object} + * Object to store the loaders, tracks, and utility methods for each media type + * @function createMediaTypes + */ + var createMediaTypes = function createMediaTypes() { + var mediaTypes = {}; + + ['AUDIO', 'SUBTITLES', 'CLOSED-CAPTIONS'].forEach(function (type) { + mediaTypes[type] = { + groups: {}, + tracks: {}, + activePlaylistLoader: null, + activeGroup: noop$1, + activeTrack: noop$1, + onGroupChanged: noop$1, + onTrackChanged: noop$1 + }; + }); + + return mediaTypes; + }; + + /** + * @file master-playlist-controller.js + */ + + var ABORT_EARLY_BLACKLIST_SECONDS = 60 * 2; + + var Hls = void 0; + + // SegmentLoader stats that need to have each loader's + // values summed to calculate the final value + var loaderStats = ['mediaRequests', 'mediaRequestsAborted', 'mediaRequestsTimedout', 'mediaRequestsErrored', 'mediaTransferDuration', 'mediaBytesTransferred']; + var sumLoaderStat = function sumLoaderStat(stat) { + return this.audioSegmentLoader_[stat] + this.mainSegmentLoader_[stat]; + }; + + /** + * the master playlist controller controller all interactons + * between playlists and segmentloaders. At this time this mainly + * involves a master playlist and a series of audio playlists + * if they are available + * + * @class MasterPlaylistController + * @extends videojs.EventTarget + */ + + var MasterPlaylistController = function (_videojs$EventTarget5) { + inherits(MasterPlaylistController, _videojs$EventTarget5); + + function MasterPlaylistController(options) { + classCallCheck(this, MasterPlaylistController); + + var _this29 = possibleConstructorReturn(this, _videojs$EventTarget5.call(this)); + + var url = options.url, + withCredentials = options.withCredentials, + tech = options.tech, + bandwidth = options.bandwidth, + externHls = options.externHls, + useCueTags = options.useCueTags, + blacklistDuration = options.blacklistDuration, + enableLowInitialPlaylist = options.enableLowInitialPlaylist, + sourceType = options.sourceType; + + + if (!url) { + throw new Error('A non-empty playlist URL is required'); + } + + Hls = externHls; + + _this29.withCredentials = withCredentials; + _this29.tech_ = tech; + _this29.hls_ = tech.hls; + _this29.sourceType_ = sourceType; + _this29.useCueTags_ = useCueTags; + _this29.blacklistDuration = blacklistDuration; + _this29.enableLowInitialPlaylist = enableLowInitialPlaylist; + if (_this29.useCueTags_) { + _this29.cueTagsTrack_ = _this29.tech_.addTextTrack('metadata', 'ad-cues'); + _this29.cueTagsTrack_.inBandMetadataTrackDispatchType = ''; + } + + _this29.requestOptions_ = { + withCredentials: _this29.withCredentials, + timeout: null + }; + + _this29.mediaTypes_ = createMediaTypes(); + + _this29.mediaSource = new videojs$1.MediaSource(); + + // load the media source into the player + _this29.mediaSource.addEventListener('sourceopen', _this29.handleSourceOpen_.bind(_this29)); + + _this29.seekable_ = videojs$1.createTimeRanges(); + _this29.hasPlayed_ = function () { + return false; + }; + + _this29.syncController_ = new SyncController(options); + _this29.segmentMetadataTrack_ = tech.addRemoteTextTrack({ + kind: 'metadata', + label: 'segment-metadata' + }, false).track; + + _this29.decrypter_ = new Decrypter$1(); + + var segmentLoaderSettings = { + hls: _this29.hls_, + mediaSource: _this29.mediaSource, + currentTime: _this29.tech_.currentTime.bind(_this29.tech_), + seekable: function seekable() { + return _this29.seekable(); + }, + seeking: function seeking() { + return _this29.tech_.seeking(); + }, + duration: function duration() { + return _this29.mediaSource.duration; + }, + hasPlayed: function hasPlayed() { + return _this29.hasPlayed_(); + }, + goalBufferLength: function goalBufferLength() { + return _this29.goalBufferLength(); + }, + bandwidth: bandwidth, + syncController: _this29.syncController_, + decrypter: _this29.decrypter_, + sourceType: _this29.sourceType_ + }; + + _this29.masterPlaylistLoader_ = _this29.sourceType_ === 'dash' ? new DashPlaylistLoader(url, _this29.hls_, _this29.withCredentials) : new PlaylistLoader(url, _this29.hls_, _this29.withCredentials); + _this29.setupMasterPlaylistLoaderListeners_(); + + // setup segment loaders + // combined audio/video or just video when alternate audio track is selected + _this29.mainSegmentLoader_ = new SegmentLoader(videojs$1.mergeOptions(segmentLoaderSettings, { + segmentMetadataTrack: _this29.segmentMetadataTrack_, + loaderType: 'main' + }), options); + + // alternate audio track + _this29.audioSegmentLoader_ = new SegmentLoader(videojs$1.mergeOptions(segmentLoaderSettings, { + loaderType: 'audio' + }), options); + + _this29.subtitleSegmentLoader_ = new VTTSegmentLoader(videojs$1.mergeOptions(segmentLoaderSettings, { + loaderType: 'vtt' + }), options); + + _this29.setupSegmentLoaderListeners_(); + + // Create SegmentLoader stat-getters + loaderStats.forEach(function (stat) { + _this29[stat + '_'] = sumLoaderStat.bind(_this29, stat); + }); + + _this29.logger_ = logger('MPC'); + + _this29.masterPlaylistLoader_.load(); + return _this29; + } + + /** + * Register event handlers on the master playlist loader. A helper + * function for construction time. + * + * @private + */ + + + MasterPlaylistController.prototype.setupMasterPlaylistLoaderListeners_ = function setupMasterPlaylistLoaderListeners_() { + var _this30 = this; + + this.masterPlaylistLoader_.on('loadedmetadata', function () { + var media = _this30.masterPlaylistLoader_.media(); + var requestTimeout = _this30.masterPlaylistLoader_.targetDuration * 1.5 * 1000; + + // If we don't have any more available playlists, we don't want to + // timeout the request. + if (isLowestEnabledRendition(_this30.masterPlaylistLoader_.master, _this30.masterPlaylistLoader_.media())) { + _this30.requestOptions_.timeout = 0; + } else { + _this30.requestOptions_.timeout = requestTimeout; + } + + // if this isn't a live video and preload permits, start + // downloading segments + if (media.endList && _this30.tech_.preload() !== 'none') { + _this30.mainSegmentLoader_.playlist(media, _this30.requestOptions_); + _this30.mainSegmentLoader_.load(); + } + + setupMediaGroups({ + sourceType: _this30.sourceType_, + segmentLoaders: { + AUDIO: _this30.audioSegmentLoader_, + SUBTITLES: _this30.subtitleSegmentLoader_, + main: _this30.mainSegmentLoader_ + }, + tech: _this30.tech_, + requestOptions: _this30.requestOptions_, + masterPlaylistLoader: _this30.masterPlaylistLoader_, + hls: _this30.hls_, + master: _this30.master(), + mediaTypes: _this30.mediaTypes_, + blacklistCurrentPlaylist: _this30.blacklistCurrentPlaylist.bind(_this30) + }); + + _this30.triggerPresenceUsage_(_this30.master(), media); + + try { + _this30.setupSourceBuffers_(); + } catch (e) { + videojs$1.log.warn('Failed to create SourceBuffers', e); + return _this30.mediaSource.endOfStream('decode'); + } + _this30.setupFirstPlay(); + + _this30.trigger('selectedinitialmedia'); + }); + + this.masterPlaylistLoader_.on('loadedplaylist', function () { + var updatedPlaylist = _this30.masterPlaylistLoader_.media(); + + if (!updatedPlaylist) { + // blacklist any variants that are not supported by the browser before selecting + // an initial media as the playlist selectors do not consider browser support + _this30.excludeUnsupportedVariants_(); + + var selectedMedia = void 0; + + if (_this30.enableLowInitialPlaylist) { + selectedMedia = _this30.selectInitialPlaylist(); + } + + if (!selectedMedia) { + selectedMedia = _this30.selectPlaylist(); + } + + _this30.initialMedia_ = selectedMedia; + _this30.masterPlaylistLoader_.media(_this30.initialMedia_); + return; + } + + if (_this30.useCueTags_) { + _this30.updateAdCues_(updatedPlaylist); + } + + // TODO: Create a new event on the PlaylistLoader that signals + // that the segments have changed in some way and use that to + // update the SegmentLoader instead of doing it twice here and + // on `mediachange` + _this30.mainSegmentLoader_.playlist(updatedPlaylist, _this30.requestOptions_); + _this30.updateDuration(); + + // If the player isn't paused, ensure that the segment loader is running, + // as it is possible that it was temporarily stopped while waiting for + // a playlist (e.g., in case the playlist errored and we re-requested it). + if (!_this30.tech_.paused()) { + _this30.mainSegmentLoader_.load(); + } + + if (!updatedPlaylist.endList) { + var addSeekableRange = function addSeekableRange() { + var seekable$$1 = _this30.seekable(); + + if (seekable$$1.length !== 0) { + _this30.mediaSource.addSeekableRange_(seekable$$1.start(0), seekable$$1.end(0)); + } + }; + + if (_this30.duration() !== Infinity) { + var onDurationchange = function onDurationchange() { + if (_this30.duration() === Infinity) { + addSeekableRange(); + } else { + _this30.tech_.one('durationchange', onDurationchange); + } + }; + + _this30.tech_.one('durationchange', onDurationchange); + } else { + addSeekableRange(); + } + } + }); + + this.masterPlaylistLoader_.on('error', function () { + _this30.blacklistCurrentPlaylist(_this30.masterPlaylistLoader_.error); + }); + + this.masterPlaylistLoader_.on('mediachanging', function () { + _this30.mainSegmentLoader_.abort(); + _this30.mainSegmentLoader_.pause(); + }); + + this.masterPlaylistLoader_.on('mediachange', function () { + var media = _this30.masterPlaylistLoader_.media(); + var requestTimeout = _this30.masterPlaylistLoader_.targetDuration * 1.5 * 1000; + + // If we don't have any more available playlists, we don't want to + // timeout the request. + if (isLowestEnabledRendition(_this30.masterPlaylistLoader_.master, _this30.masterPlaylistLoader_.media())) { + _this30.requestOptions_.timeout = 0; + } else { + _this30.requestOptions_.timeout = requestTimeout; + } + + // TODO: Create a new event on the PlaylistLoader that signals + // that the segments have changed in some way and use that to + // update the SegmentLoader instead of doing it twice here and + // on `loadedplaylist` + _this30.mainSegmentLoader_.playlist(media, _this30.requestOptions_); + _this30.mainSegmentLoader_.load(); + + _this30.tech_.trigger({ + type: 'mediachange', + bubbles: true + }); + }); + + this.masterPlaylistLoader_.on('playlistunchanged', function () { + var updatedPlaylist = _this30.masterPlaylistLoader_.media(); + var playlistOutdated = _this30.stuckAtPlaylistEnd_(updatedPlaylist); + + if (playlistOutdated) { + // Playlist has stopped updating and we're stuck at its end. Try to + // blacklist it and switch to another playlist in the hope that that + // one is updating (and give the player a chance to re-adjust to the + // safe live point). + _this30.blacklistCurrentPlaylist({ + message: 'Playlist no longer updating.' + }); + // useful for monitoring QoS + _this30.tech_.trigger('playliststuck'); + } + }); + + this.masterPlaylistLoader_.on('renditiondisabled', function () { + _this30.tech_.trigger({type: 'usage', name: 'hls-rendition-disabled'}); + }); + this.masterPlaylistLoader_.on('renditionenabled', function () { + _this30.tech_.trigger({type: 'usage', name: 'hls-rendition-enabled'}); + }); + }; + + /** + * A helper function for triggerring presence usage events once per source + * + * @private + */ + + + MasterPlaylistController.prototype.triggerPresenceUsage_ = function triggerPresenceUsage_(master, media) { + var mediaGroups = master.mediaGroups || {}; + var defaultDemuxed = true; + var audioGroupKeys = Object.keys(mediaGroups.AUDIO); + + for (var mediaGroup in mediaGroups.AUDIO) { + for (var label in mediaGroups.AUDIO[mediaGroup]) { + var properties = mediaGroups.AUDIO[mediaGroup][label]; + + if (!properties.uri) { + defaultDemuxed = false; + } + } + } + + if (defaultDemuxed) { + this.tech_.trigger({type: 'usage', name: 'hls-demuxed'}); + } + + if (Object.keys(mediaGroups.SUBTITLES).length) { + this.tech_.trigger({type: 'usage', name: 'hls-webvtt'}); + } + + if (Hls.Playlist.isAes(media)) { + this.tech_.trigger({type: 'usage', name: 'hls-aes'}); + } + + if (Hls.Playlist.isFmp4(media)) { + this.tech_.trigger({type: 'usage', name: 'hls-fmp4'}); + } + + if (audioGroupKeys.length && Object.keys(mediaGroups.AUDIO[audioGroupKeys[0]]).length > 1) { + this.tech_.trigger({type: 'usage', name: 'hls-alternate-audio'}); + } + + if (this.useCueTags_) { + this.tech_.trigger({type: 'usage', name: 'hls-playlist-cue-tags'}); + } + }; + /** + * Register event handlers on the segment loaders. A helper function + * for construction time. + * + * @private + */ + + + MasterPlaylistController.prototype.setupSegmentLoaderListeners_ = function setupSegmentLoaderListeners_() { + var _this31 = this; + + this.mainSegmentLoader_.on('bandwidthupdate', function () { + var nextPlaylist = _this31.selectPlaylist(); + var currentPlaylist = _this31.masterPlaylistLoader_.media(); + var buffered = _this31.tech_.buffered(); + var forwardBuffer = buffered.length ? buffered.end(buffered.length - 1) - _this31.tech_.currentTime() : 0; + + var bufferLowWaterLine = _this31.bufferLowWaterLine(); + + // If the playlist is live, then we want to not take low water line into account. + // This is because in LIVE, the player plays 3 segments from the end of the + // playlist, and if `BUFFER_LOW_WATER_LINE` is greater than the duration availble + // in those segments, a viewer will never experience a rendition upswitch. + if (!currentPlaylist.endList || + // For the same reason as LIVE, we ignore the low water line when the VOD + // duration is below the max potential low water line + _this31.duration() < Config.MAX_BUFFER_LOW_WATER_LINE || + // we want to switch down to lower resolutions quickly to continue playback, but + nextPlaylist.attributes.BANDWIDTH < currentPlaylist.attributes.BANDWIDTH || + // ensure we have some buffer before we switch up to prevent us running out of + // buffer while loading a higher rendition. + forwardBuffer >= bufferLowWaterLine) { + _this31.masterPlaylistLoader_.media(nextPlaylist); + } + + _this31.tech_.trigger('bandwidthupdate'); + }); + this.mainSegmentLoader_.on('progress', function () { + _this31.trigger('progress'); + }); + + this.mainSegmentLoader_.on('error', function () { + _this31.blacklistCurrentPlaylist(_this31.mainSegmentLoader_.error()); + }); + + this.mainSegmentLoader_.on('syncinfoupdate', function () { + _this31.onSyncInfoUpdate_(); + }); + + this.mainSegmentLoader_.on('timestampoffset', function () { + _this31.tech_.trigger({type: 'usage', name: 'hls-timestamp-offset'}); + }); + this.audioSegmentLoader_.on('syncinfoupdate', function () { + _this31.onSyncInfoUpdate_(); + }); + + this.mainSegmentLoader_.on('ended', function () { + _this31.onEndOfStream(); + }); + + this.mainSegmentLoader_.on('earlyabort', function () { + _this31.blacklistCurrentPlaylist({ + message: 'Aborted early because there isn\'t enough bandwidth to complete the ' + 'request without rebuffering.' + }, ABORT_EARLY_BLACKLIST_SECONDS); + }); + + this.mainSegmentLoader_.on('reseteverything', function () { + // If playing an MTS stream, a videojs.MediaSource is listening for + // hls-reset to reset caption parsing state in the transmuxer + _this31.tech_.trigger('hls-reset'); + }); + + this.mainSegmentLoader_.on('segmenttimemapping', function (event) { + // If playing an MTS stream in html, a videojs.MediaSource is listening for + // hls-segment-time-mapping update its internal mapping of stream to display time + _this31.tech_.trigger({ + type: 'hls-segment-time-mapping', + mapping: event.mapping + }); + }); + + this.audioSegmentLoader_.on('ended', function () { + _this31.onEndOfStream(); + }); + }; + + MasterPlaylistController.prototype.mediaSecondsLoaded_ = function mediaSecondsLoaded_() { + return Math.max(this.audioSegmentLoader_.mediaSecondsLoaded + this.mainSegmentLoader_.mediaSecondsLoaded); + }; + + /** + * Call load on our SegmentLoaders + */ + + + MasterPlaylistController.prototype.load = function load() { + this.mainSegmentLoader_.load(); + if (this.mediaTypes_.AUDIO.activePlaylistLoader) { + this.audioSegmentLoader_.load(); + } + if (this.mediaTypes_.SUBTITLES.activePlaylistLoader) { + this.subtitleSegmentLoader_.load(); + } + }; + + /** + * Re-tune playback quality level for the current player + * conditions. This method may perform destructive actions, like + * removing already buffered content, to readjust the currently + * active playlist quickly. + * + * @private + */ + + + MasterPlaylistController.prototype.fastQualityChange_ = function fastQualityChange_() { + var media = this.selectPlaylist(); + + if (media !== this.masterPlaylistLoader_.media()) { + this.masterPlaylistLoader_.media(media); + + this.mainSegmentLoader_.resetLoader(); + // don't need to reset audio as it is reset when media changes + } + }; + + /** + * Begin playback. + */ + + + MasterPlaylistController.prototype.play = function play() { + if (this.setupFirstPlay()) { + return; + } + + if (this.tech_.ended()) { + this.tech_.setCurrentTime(0); + } + + if (this.hasPlayed_()) { + this.load(); + } + + var seekable$$1 = this.tech_.seekable(); + + // if the viewer has paused and we fell out of the live window, + // seek forward to the live point + if (this.tech_.duration() === Infinity) { + if (this.tech_.currentTime() < seekable$$1.start(0)) { + return this.tech_.setCurrentTime(seekable$$1.end(seekable$$1.length - 1)); + } + } + }; + + /** + * Seek to the latest media position if this is a live video and the + * player and video are loaded and initialized. + */ + + + MasterPlaylistController.prototype.setupFirstPlay = function setupFirstPlay() { + var _this32 = this; + + var media = this.masterPlaylistLoader_.media(); + + // Check that everything is ready to begin buffering for the first call to playOld + // If 1) there is no active media + // 2) the player is paused + // 3) the first playOld has already been setup + // then exit early + if (!media || this.tech_.paused() || this.hasPlayed_()) { + return false; + } + + // when the video is a live stream + if (!media.endList) { + var seekable$$1 = this.seekable(); + + if (!seekable$$1.length) { + // without a seekable range, the player cannot seek to begin buffering at the live + // point + return false; + } + + if (videojs$1.browser.IE_VERSION && this.tech_.readyState() === 0) { + // IE11 throws an InvalidStateError if you try to set currentTime while the + // readyState is 0, so it must be delayed until the tech fires loadedmetadata. + this.tech_.one('loadedmetadata', function () { + _this32.trigger('firstplay'); + _this32.tech_.setCurrentTime(seekable$$1.end(0)); + _this32.hasPlayed_ = function () { + return true; + }; + }); + + return false; + } + + // trigger firstplay to inform the source handler to ignore the next seek event + this.trigger('firstplay'); + // seek to the live point + this.tech_.setCurrentTime(seekable$$1.end(0)); + } + + this.hasPlayed_ = function () { + return true; + }; + // we can begin loading now that everything is ready + this.load(); + return true; + }; + + /** + * handle the sourceopen event on the MediaSource + * + * @private + */ + + + MasterPlaylistController.prototype.handleSourceOpen_ = function handleSourceOpen_() { + // Only attempt to create the source buffer if none already exist. + // handleSourceOpen is also called when we are "re-opening" a source buffer + // after `endOfStream` has been called (in response to a seek for instance) + try { + this.setupSourceBuffers_(); + } catch (e) { + videojs$1.log.warn('Failed to create Source Buffers', e); + return this.mediaSource.endOfStream('decode'); + } + + // if autoplay is enabled, begin playback. This is duplicative of + // code in video.js but is required because playOld() must be invoked + // *after* the media source has opened. + if (this.tech_.autoplay()) { + var playPromise = this.tech_.play(); + + // Catch/silence error when a pause interrupts a playOld request + // on browsers which return a promise + if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') { + playPromise.then(null, function (e) { + }); + } + } + + this.trigger('sourceopen'); + }; + + /** + * Calls endOfStream on the media source when all active stream types have called + * endOfStream + * + * @param {string} streamType + * Stream type of the segment loader that called endOfStream + * @private + */ + + + MasterPlaylistController.prototype.onEndOfStream = function onEndOfStream() { + var isEndOfStream = this.mainSegmentLoader_.ended_; + + if (this.mediaTypes_.AUDIO.activePlaylistLoader) { + // if the audio playlist loader exists, then alternate audio is active + if (!this.mainSegmentLoader_.startingMedia_ || this.mainSegmentLoader_.startingMedia_.containsVideo) { + // if we do not know if the main segment loader contains video yet or if we + // definitively know the main segment loader contains video, then we need to wait + // for both main and audio segment loaders to call endOfStream + isEndOfStream = isEndOfStream && this.audioSegmentLoader_.ended_; + } else { + // otherwise just rely on the audio loader + isEndOfStream = this.audioSegmentLoader_.ended_; + } + } + + if (isEndOfStream) { + this.mediaSource.endOfStream(); + } + }; + + /** + * Check if a playlist has stopped being updated + * @param {Object} playlist the media playlist object + * @return {boolean} whether the playlist has stopped being updated or not + */ + + + MasterPlaylistController.prototype.stuckAtPlaylistEnd_ = function stuckAtPlaylistEnd_(playlist) { + var seekable$$1 = this.seekable(); + + if (!seekable$$1.length) { + // playlist doesn't have enough information to determine whether we are stuck + return false; + } + + var expired = this.syncController_.getExpiredTime(playlist, this.mediaSource.duration); + + if (expired === null) { + return false; + } + + // does not use the safe live end to calculate playlist end, since we + // don't want to say we are stuck while there is still content + var absolutePlaylistEnd = Hls.Playlist.playlistEnd(playlist, expired); + var currentTime = this.tech_.currentTime(); + var buffered = this.tech_.buffered(); + + if (!buffered.length) { + // return true if the playhead reached the absolute end of the playlist + return absolutePlaylistEnd - currentTime <= SAFE_TIME_DELTA; + } + var bufferedEnd = buffered.end(buffered.length - 1); + + // return true if there is too little buffer left and buffer has reached absolute + // end of playlist + return bufferedEnd - currentTime <= SAFE_TIME_DELTA && absolutePlaylistEnd - bufferedEnd <= SAFE_TIME_DELTA; + }; + + /** + * Blacklists a playlist when an error occurs for a set amount of time + * making it unavailable for selection by the rendition selection algorithm + * and then forces a new playlist (rendition) selection. + * + * @param {Object=} error an optional error that may include the playlist + * to blacklist + * @param {Number=} blacklistDuration an optional number of seconds to blacklist the + * playlist + */ + + + MasterPlaylistController.prototype.blacklistCurrentPlaylist = function blacklistCurrentPlaylist() { + var error = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var blacklistDuration = arguments[1]; + + var currentPlaylist = void 0; + var nextPlaylist = void 0; + + // If the `error` was generated by the playlist loader, it will contain + // the playlist we were trying to load (but failed) and that should be + // blacklisted instead of the currently selected playlist which is likely + // out-of-date in this scenario + currentPlaylist = error.playlist || this.masterPlaylistLoader_.media(); + + blacklistDuration = blacklistDuration || error.blacklistDuration || this.blacklistDuration; + + // If there is no current playlist, then an error occurred while we were + // trying to load the master OR while we were disposing of the tech + if (!currentPlaylist) { + this.error = error; + + try { + return this.mediaSource.endOfStream('network'); + } catch (e) { + return this.trigger('error'); + } + } + + var isFinalRendition = this.masterPlaylistLoader_.master.playlists.filter(isEnabled).length === 1; + + if (isFinalRendition) { + // Never blacklisting this playlist because it's final rendition + videojs$1.log.warn('Problem encountered with the current ' + 'HLS playlist. Trying again since it is the final playlist.'); + + this.tech_.trigger('retryplaylist'); + return this.masterPlaylistLoader_.load(isFinalRendition); + } + // Blacklist this playlist + currentPlaylist.excludeUntil = Date.now() + blacklistDuration * 1000; + this.tech_.trigger('blacklistplaylist'); + this.tech_.trigger({type: 'usage', name: 'hls-rendition-blacklisted'}); + + // Select a new playlist + nextPlaylist = this.selectPlaylist(); + videojs$1.log.warn('Problem encountered with the current HLS playlist.' + (error.message ? ' ' + error.message : '') + ' Switching to another playlist.'); + + return this.masterPlaylistLoader_.media(nextPlaylist); + }; + + /** + * Pause all segment loaders + */ + + + MasterPlaylistController.prototype.pauseLoading = function pauseLoading() { + this.mainSegmentLoader_.pause(); + if (this.mediaTypes_.AUDIO.activePlaylistLoader) { + this.audioSegmentLoader_.pause(); + } + if (this.mediaTypes_.SUBTITLES.activePlaylistLoader) { + this.subtitleSegmentLoader_.pause(); + } + }; + + /** + * set the current time on all segment loaders + * + * @param {TimeRange} currentTime the current time to set + * @return {TimeRange} the current time + */ + + + MasterPlaylistController.prototype.setCurrentTime = function setCurrentTime(currentTime) { + var buffered = findRange(this.tech_.buffered(), currentTime); + + if (!(this.masterPlaylistLoader_ && this.masterPlaylistLoader_.media())) { + // return immediately if the metadata is not ready yet + return 0; + } + + // it's clearly an edge-case but don't thrown an error if asked to + // seek within an empty playlist + if (!this.masterPlaylistLoader_.media().segments) { + return 0; + } + + // In flash playback, the segment loaders should be reset on every seek, even + // in buffer seeks. If the seek location is already buffered, continue buffering as + // usual + // TODO: redo this comment + if (buffered && buffered.length) { + return currentTime; + } + + // cancel outstanding requests so we begin buffering at the new + // location + this.mainSegmentLoader_.resetEverything(); + this.mainSegmentLoader_.abort(); + if (this.mediaTypes_.AUDIO.activePlaylistLoader) { + this.audioSegmentLoader_.resetEverything(); + this.audioSegmentLoader_.abort(); + } + if (this.mediaTypes_.SUBTITLES.activePlaylistLoader) { + this.subtitleSegmentLoader_.resetEverything(); + this.subtitleSegmentLoader_.abort(); + } + + // start segment loader loading in case they are paused + this.load(); + }; + + /** + * get the current duration + * + * @return {TimeRange} the duration + */ + + + MasterPlaylistController.prototype.duration = function duration() { + if (!this.masterPlaylistLoader_) { + return 0; + } + + if (this.mediaSource) { + return this.mediaSource.duration; + } + + return Hls.Playlist.duration(this.masterPlaylistLoader_.media()); + }; + + /** + * check the seekable range + * + * @return {TimeRange} the seekable range + */ + + + MasterPlaylistController.prototype.seekable = function seekable() { + return this.seekable_; + }; + + MasterPlaylistController.prototype.onSyncInfoUpdate_ = function onSyncInfoUpdate_() { + var mainSeekable = void 0; + var audioSeekable = void 0; + + if (!this.masterPlaylistLoader_) { + return; + } + + var media = this.masterPlaylistLoader_.media(); + + if (!media) { + return; + } + + var expired = this.syncController_.getExpiredTime(media, this.mediaSource.duration); + + if (expired === null) { + // not enough information to update seekable + return; + } + + mainSeekable = Hls.Playlist.seekable(media, expired); + + if (mainSeekable.length === 0) { + return; + } + + if (this.mediaTypes_.AUDIO.activePlaylistLoader) { + media = this.mediaTypes_.AUDIO.activePlaylistLoader.media(); + expired = this.syncController_.getExpiredTime(media, this.mediaSource.duration); + + if (expired === null) { + return; + } + + audioSeekable = Hls.Playlist.seekable(media, expired); + + if (audioSeekable.length === 0) { + return; + } + } + + if (!audioSeekable) { + // seekable has been calculated based on buffering video data so it + // can be returned directly + this.seekable_ = mainSeekable; + } else if (audioSeekable.start(0) > mainSeekable.end(0) || mainSeekable.start(0) > audioSeekable.end(0)) { + // seekables are pretty far off, rely on main + this.seekable_ = mainSeekable; + } else { + this.seekable_ = videojs$1.createTimeRanges([[audioSeekable.start(0) > mainSeekable.start(0) ? audioSeekable.start(0) : mainSeekable.start(0), audioSeekable.end(0) < mainSeekable.end(0) ? audioSeekable.end(0) : mainSeekable.end(0)]]); + } + + this.logger_('seekable updated [' + printableRange(this.seekable_) + ']'); + + this.tech_.trigger('seekablechanged'); + }; + + /** + * Update the player duration + */ + + + MasterPlaylistController.prototype.updateDuration = function updateDuration() { + var _this33 = this; + + var oldDuration = this.mediaSource.duration; + var newDuration = Hls.Playlist.duration(this.masterPlaylistLoader_.media()); + var buffered = this.tech_.buffered(); + var setDuration = function setDuration() { + _this33.mediaSource.duration = newDuration; + _this33.tech_.trigger('durationchange'); + + _this33.mediaSource.removeEventListener('sourceopen', setDuration); + }; + + if (buffered.length > 0) { + newDuration = Math.max(newDuration, buffered.end(buffered.length - 1)); + } + + // if the duration has changed, invalidate the cached value + if (oldDuration !== newDuration) { + // update the duration + if (this.mediaSource.readyState !== 'open') { + this.mediaSource.addEventListener('sourceopen', setDuration); + } else { + setDuration(); + } + } + }; + + /** + * dispose of the MasterPlaylistController and everything + * that it controls + */ + + + MasterPlaylistController.prototype.dispose = function dispose() { + var _this34 = this; + + this.decrypter_.terminate(); + this.masterPlaylistLoader_.dispose(); + this.mainSegmentLoader_.dispose(); + + ['AUDIO', 'SUBTITLES'].forEach(function (type) { + var groups = _this34.mediaTypes_[type].groups; + + for (var id in groups) { + groups[id].forEach(function (group) { + if (group.playlistLoader) { + group.playlistLoader.dispose(); + } + }); + } + }); + + this.audioSegmentLoader_.dispose(); + this.subtitleSegmentLoader_.dispose(); + }; + + /** + * return the master playlist object if we have one + * + * @return {Object} the master playlist object that we parsed + */ + + + MasterPlaylistController.prototype.master = function master() { + return this.masterPlaylistLoader_.master; + }; + + /** + * return the currently selected playlist + * + * @return {Object} the currently selected playlist object that we parsed + */ + + + MasterPlaylistController.prototype.media = function media() { + // playlist loader will not return media if it has not been fully loaded + return this.masterPlaylistLoader_.media() || this.initialMedia_; + }; + + /** + * setup our internal source buffers on our segment Loaders + * + * @private + */ + + + MasterPlaylistController.prototype.setupSourceBuffers_ = function setupSourceBuffers_() { + var media = this.masterPlaylistLoader_.media(); + var mimeTypes = void 0; + + // wait until a media playlist is available and the Media Source is + // attached + if (!media || this.mediaSource.readyState !== 'open') { + return; + } + + mimeTypes = mimeTypesForPlaylist(this.masterPlaylistLoader_.master, media); + if (mimeTypes.length < 1) { + this.error = 'No compatible SourceBuffer configuration for the variant stream:' + media.resolvedUri; + return this.mediaSource.endOfStream('decode'); + } + + this.configureLoaderMimeTypes_(mimeTypes); + // exclude any incompatible variant streams from future playlist + // selection + this.excludeIncompatibleVariants_(media); + }; + + MasterPlaylistController.prototype.configureLoaderMimeTypes_ = function configureLoaderMimeTypes_(mimeTypes) { + // If the content is demuxed, we can't start appending segments to a source buffer + // until both source buffers are set up, or else the browser may not let us add the + // second source buffer (it will assume we are playing either audio only or video + // only). + var sourceBufferEmitter = + // If there is more than one mime type + mimeTypes.length > 1 && + // and the first mime type does not have muxed video and audio + mimeTypes[0].indexOf(',') === -1 && + // and the two mime types are different (they can be the same in the case of audio + // only with alternate audio) + mimeTypes[0] !== mimeTypes[1] ? + // then we want to wait on the second source buffer + new videojs$1.EventTarget() : + // otherwise there is no need to wait as the content is either audio only, + // video only, or muxed content. + null; + + this.mainSegmentLoader_.mimeType(mimeTypes[0], sourceBufferEmitter); + if (mimeTypes[1]) { + this.audioSegmentLoader_.mimeType(mimeTypes[1], sourceBufferEmitter); + } + }; + + /** + * Blacklists playlists with codecs that are unsupported by the browser. + */ + + + MasterPlaylistController.prototype.excludeUnsupportedVariants_ = function excludeUnsupportedVariants_() { + this.master().playlists.forEach(function (variant) { + if (variant.attributes.CODECS && window_1.MediaSource && window_1.MediaSource.isTypeSupported && !window_1.MediaSource.isTypeSupported('video/mp4; codecs="' + mapLegacyAvcCodecs(variant.attributes.CODECS) + '"')) { + variant.excludeUntil = Infinity; + } + }); + }; + + /** + * Blacklist playlists that are known to be codec or + * stream-incompatible with the SourceBuffer configuration. For + * instance, Media Source Extensions would cause the video element to + * stall waiting for video data if you switched from a variant with + * video and audio to an audio-only one. + * + * @param {Object} media a media playlist compatible with the current + * set of SourceBuffers. Variants in the current master playlist that + * do not appear to have compatible codec or stream configurations + * will be excluded from the default playlist selection algorithm + * indefinitely. + * @private + */ + + + MasterPlaylistController.prototype.excludeIncompatibleVariants_ = function excludeIncompatibleVariants_(media) { + var codecCount = 2; + var videoCodec = null; + var codecs = void 0; + + if (media.attributes.CODECS) { + codecs = parseCodecs(media.attributes.CODECS); + videoCodec = codecs.videoCodec; + codecCount = codecs.codecCount; + } + + this.master().playlists.forEach(function (variant) { + var variantCodecs = { + codecCount: 2, + videoCodec: null + }; + + if (variant.attributes.CODECS) { + variantCodecs = parseCodecs(variant.attributes.CODECS); + } + + // if the streams differ in the presence or absence of audio or + // video, they are incompatible + if (variantCodecs.codecCount !== codecCount) { + variant.excludeUntil = Infinity; + } + + // if h.264 is specified on the current playlist, some flavor of + // it must be specified on all compatible variants + if (variantCodecs.videoCodec !== videoCodec) { + variant.excludeUntil = Infinity; + } + }); + }; + + MasterPlaylistController.prototype.updateAdCues_ = function updateAdCues_(media) { + var offset = 0; + var seekable$$1 = this.seekable(); + + if (seekable$$1.length) { + offset = seekable$$1.start(0); + } + + updateAdCues(media, this.cueTagsTrack_, offset); + }; + + /** + * Calculates the desired forward buffer length based on current time + * + * @return {Number} Desired forward buffer length in seconds + */ + + + MasterPlaylistController.prototype.goalBufferLength = function goalBufferLength() { + var currentTime = this.tech_.currentTime(); + var initial = Config.GOAL_BUFFER_LENGTH; + var rate = Config.GOAL_BUFFER_LENGTH_RATE; + var max = Math.max(initial, Config.MAX_GOAL_BUFFER_LENGTH); + + return Math.min(initial + currentTime * rate, max); + }; + + /** + * Calculates the desired buffer low water line based on current time + * + * @return {Number} Desired buffer low water line in seconds + */ + + + MasterPlaylistController.prototype.bufferLowWaterLine = function bufferLowWaterLine() { + var currentTime = this.tech_.currentTime(); + var initial = Config.BUFFER_LOW_WATER_LINE; + var rate = Config.BUFFER_LOW_WATER_LINE_RATE; + var max = Math.max(initial, Config.MAX_BUFFER_LOW_WATER_LINE); + + return Math.min(initial + currentTime * rate, max); + }; + + return MasterPlaylistController; + }(videojs$1.EventTarget); + + /** + * Returns a function that acts as the Enable/disable playlist function. + * + * @param {PlaylistLoader} loader - The master playlist loader + * @param {String} playlistUri - uri of the playlist + * @param {Function} changePlaylistFn - A function to be called after a + * playlist's enabled-state has been changed. Will NOT be called if a + * playlist's enabled-state is unchanged + * @param {Boolean=} enable - Value to set the playlist enabled-state to + * or if undefined returns the current enabled-state for the playlist + * @return {Function} Function for setting/getting enabled + */ + + + var enableFunction = function enableFunction(loader, playlistUri, changePlaylistFn) { + return function (enable) { + var playlist = loader.master.playlists[playlistUri]; + var incompatible = isIncompatible(playlist); + var currentlyEnabled = isEnabled(playlist); + + if (typeof enable === 'undefined') { + return currentlyEnabled; + } + + if (enable) { + delete playlist.disabled; + } else { + playlist.disabled = true; + } + + if (enable !== currentlyEnabled && !incompatible) { + // Ensure the outside world knows about our changes + changePlaylistFn(); + if (enable) { + loader.trigger('renditionenabled'); + } else { + loader.trigger('renditiondisabled'); + } + } + return enable; + }; + }; + + /** + * The representation object encapsulates the publicly visible information + * in a media playlist along with a setter/getter-type function (enabled) + * for changing the enabled-state of a particular playlist entry + * + * @class Representation + */ + + var Representation = function Representation(hlsHandler, playlist, id) { + classCallCheck(this, Representation); + + // Get a reference to a bound version of fastQualityChange_ + var fastChangeFunction = hlsHandler.masterPlaylistController_.fastQualityChange_.bind(hlsHandler.masterPlaylistController_); + + // some playlist attributes are optional + if (playlist.attributes.RESOLUTION) { + var resolution = playlist.attributes.RESOLUTION; + + this.width = resolution.width; + this.height = resolution.height; + } + + this.bandwidth = playlist.attributes.BANDWIDTH; + + // The id is simply the ordinality of the media playlist + // within the master playlist + this.id = id; + + // Partially-apply the enableFunction to create a playlist- + // specific variant + this.enabled = enableFunction(hlsHandler.playlists, playlist.uri, fastChangeFunction); + }; + + /** + * A mixin function that adds the `representations` api to an instance + * of the HlsHandler class + * @param {HlsHandler} hlsHandler - An instance of HlsHandler to add the + * representation API into + */ + + + var renditionSelectionMixin = function renditionSelectionMixin(hlsHandler) { + var playlists = hlsHandler.playlists; + + // Add a single API-specific function to the HlsHandler instance + hlsHandler.representations = function () { + return playlists.master.playlists.filter(function (media) { + return !isIncompatible(media); + }).map(function (e, i) { + return new Representation(hlsHandler, e, e.uri); + }); + }; + }; + + /** + * @file playback-watcher.js + * + * Playback starts, and now my watch begins. It shall not end until my death. I shall + * take no wait, hold no uncleared timeouts, father no bad seeks. I shall wear no crowns + * and win no glory. I shall live and die at my post. I am the corrector of the underflow. + * I am the watcher of gaps. I am the shield that guards the realms of seekable. I pledge + * my life and honor to the Playback Watch, for this Player and all the Players to come. + */ + + // Set of events that reset the playback-watcher time check logic and clear the timeout + var timerCancelEvents = ['seeking', 'seeked', 'pause', 'playing', 'error']; + + /** + * @class PlaybackWatcher + */ + + var PlaybackWatcher = function () { + /** + * Represents an PlaybackWatcher object. + * @constructor + * @param {object} options an object that includes the tech and settings + */ + function PlaybackWatcher(options) { + var _this35 = this; + + classCallCheck(this, PlaybackWatcher); + + this.tech_ = options.tech; + this.seekable = options.seekable; + + this.consecutiveUpdates = 0; + this.lastRecordedTime = null; + this.timer_ = null; + this.checkCurrentTimeTimeout_ = null; + this.logger_ = logger('PlaybackWatcher'); + + this.logger_('initialize'); + + var canPlayHandler = function canPlayHandler() { + return _this35.monitorCurrentTime_(); + }; + var waitingHandler = function waitingHandler() { + return _this35.techWaiting_(); + }; + var cancelTimerHandler = function cancelTimerHandler() { + return _this35.cancelTimer_(); + }; + var fixesBadSeeksHandler = function fixesBadSeeksHandler() { + return _this35.fixesBadSeeks_(); + }; + + this.tech_.on('seekablechanged', fixesBadSeeksHandler); + this.tech_.on('waiting', waitingHandler); + this.tech_.on(timerCancelEvents, cancelTimerHandler); + this.tech_.on('canplay', canPlayHandler); + + // Define the dispose function to clean up our events + this.dispose = function () { + _this35.logger_('dispose'); + _this35.tech_.off('seekablechanged', fixesBadSeeksHandler); + _this35.tech_.off('waiting', waitingHandler); + _this35.tech_.off(timerCancelEvents, cancelTimerHandler); + _this35.tech_.off('canplay', canPlayHandler); + if (_this35.checkCurrentTimeTimeout_) { + window_1.clearTimeout(_this35.checkCurrentTimeTimeout_); + } + _this35.cancelTimer_(); + }; + } + + /** + * Periodically check current time to see if playback stopped + * + * @private + */ + + + PlaybackWatcher.prototype.monitorCurrentTime_ = function monitorCurrentTime_() { + this.checkCurrentTime_(); + + if (this.checkCurrentTimeTimeout_) { + window_1.clearTimeout(this.checkCurrentTimeTimeout_); + } + + // 42 = 24 fps // 250 is what Webkit uses // FF uses 15 + this.checkCurrentTimeTimeout_ = window_1.setTimeout(this.monitorCurrentTime_.bind(this), 250); + }; + + /** + * The purpose of this function is to emulate the "waiting" event on + * browsers that do not emit it when they are waiting for more + * data to continue playback + * + * @private + */ + + + PlaybackWatcher.prototype.checkCurrentTime_ = function checkCurrentTime_() { + if (this.tech_.seeking() && this.fixesBadSeeks_()) { + this.consecutiveUpdates = 0; + this.lastRecordedTime = this.tech_.currentTime(); + return; + } + + if (this.tech_.paused() || this.tech_.seeking()) { + return; + } + + var currentTime = this.tech_.currentTime(); + var buffered = this.tech_.buffered(); + + if (this.lastRecordedTime === currentTime && (!buffered.length || currentTime + SAFE_TIME_DELTA >= buffered.end(buffered.length - 1))) { + // If current time is at the end of the final buffered region, then any playback + // stall is most likely caused by buffering in a low bandwidth environment. The tech + // should fire a `waiting` event in this scenario, but due to browser and tech + // inconsistencies. Calling `techWaiting_` here allows us to simulate + // responding to a native `waiting` event when the tech fails to emit one. + return this.techWaiting_(); + } + + if (this.consecutiveUpdates >= 5 && currentTime === this.lastRecordedTime) { + this.consecutiveUpdates++; + this.waiting_(); + } else if (currentTime === this.lastRecordedTime) { + this.consecutiveUpdates++; + } else { + this.consecutiveUpdates = 0; + this.lastRecordedTime = currentTime; + } + }; + + /** + * Cancels any pending timers and resets the 'timeupdate' mechanism + * designed to detect that we are stalled + * + * @private + */ + + + PlaybackWatcher.prototype.cancelTimer_ = function cancelTimer_() { + this.consecutiveUpdates = 0; + + if (this.timer_) { + this.logger_('cancelTimer_'); + clearTimeout(this.timer_); + } + + this.timer_ = null; + }; + + /** + * Fixes situations where there's a bad seek + * + * @return {Boolean} whether an action was taken to fix the seek + * @private + */ + + + PlaybackWatcher.prototype.fixesBadSeeks_ = function fixesBadSeeks_() { + var seeking = this.tech_.seeking(); + var seekable = this.seekable(); + var currentTime = this.tech_.currentTime(); + var seekTo = void 0; + + if (seeking && this.afterSeekableWindow_(seekable, currentTime)) { + var seekableEnd = seekable.end(seekable.length - 1); + + // sync to live point (if VOD, our seekable was updated and we're simply adjusting) + seekTo = seekableEnd; + } + + if (seeking && this.beforeSeekableWindow_(seekable, currentTime)) { + var seekableStart = seekable.start(0); + + // sync to the beginning of the live window + // provide a buffer of .1 seconds to handle rounding/imprecise numbers + seekTo = seekableStart + SAFE_TIME_DELTA; + } + + if (typeof seekTo !== 'undefined') { + this.logger_('Trying to seek outside of seekable at time ' + currentTime + ' with ' + ('seekable range ' + printableRange(seekable) + '. Seeking to ') + (seekTo + '.')); + + this.tech_.setCurrentTime(seekTo); + return true; + } + + return false; + }; + + /** + * Handler for situations when we determine the player is waiting. + * + * @private + */ + + + PlaybackWatcher.prototype.waiting_ = function waiting_() { + if (this.techWaiting_()) { + return; + } + + // All tech waiting checks failed. Use last resort correction + var currentTime = this.tech_.currentTime(); + var buffered = this.tech_.buffered(); + var currentRange = findRange(buffered, currentTime); + + // Sometimes the player can stall for unknown reasons within a contiguous buffered + // region with no indication that anything is amiss (seen in Firefox). Seeking to + // currentTime is usually enough to kickstart the player. This checks that the player + // is currently within a buffered region before attempting a corrective seek. + // Chrome does not appear to continue `timeupdate` events after a `waiting` event + // until there is ~ 3 seconds of forward buffer available. PlaybackWatcher should also + // make sure there is ~3 seconds of forward buffer before taking any corrective action + // to avoid triggering an `unknownwaiting` event when the network is slow. + if (currentRange.length && currentTime + 3 <= currentRange.end(0)) { + this.cancelTimer_(); + this.tech_.setCurrentTime(currentTime); + + this.logger_('Stopped at ' + currentTime + ' while inside a buffered region ' + ('[' + currentRange.start(0) + ' -> ' + currentRange.end(0) + ']. Attempting to resume ') + 'playback by seeking to the current time.'); + + // unknown waiting corrections may be useful for monitoring QoS + this.tech_.trigger({type: 'usage', name: 'hls-unknown-waiting'}); + return; + } + }; + + /** + * Handler for situations when the tech fires a `waiting` event + * + * @return {Boolean} + * True if an action (or none) was needed to correct the waiting. False if no + * checks passed + * @private + */ + + + PlaybackWatcher.prototype.techWaiting_ = function techWaiting_() { + var seekable = this.seekable(); + var currentTime = this.tech_.currentTime(); + + if (this.tech_.seeking() && this.fixesBadSeeks_()) { + // Tech is seeking or bad seek fixed, no action needed + return true; + } + + if (this.tech_.seeking() || this.timer_ !== null) { + // Tech is seeking or already waiting on another action, no action needed + return true; + } + + if (this.beforeSeekableWindow_(seekable, currentTime)) { + var livePoint = seekable.end(seekable.length - 1); + + this.logger_('Fell out of live window at time ' + currentTime + '. Seeking to ' + ('live point (seekable end) ' + livePoint)); + this.cancelTimer_(); + this.tech_.setCurrentTime(livePoint); + + // live window resyncs may be useful for monitoring QoS + this.tech_.trigger({type: 'usage', name: 'hls-live-resync'}); + return true; + } + + var buffered = this.tech_.buffered(); + var nextRange = findNextRange(buffered, currentTime); + + if (this.videoUnderflow_(nextRange, buffered, currentTime)) { + // Even though the video underflowed and was stuck in a gap, the audio overplayed + // the gap, leading currentTime into a buffered range. Seeking to currentTime + // allows the video to catch up to the audio position without losing any audio + // (only suffering ~3 seconds of frozen video and a pause in audio playback). + this.cancelTimer_(); + this.tech_.setCurrentTime(currentTime); + + // video underflow may be useful for monitoring QoS + this.tech_.trigger({type: 'usage', name: 'hls-video-underflow'}); + return true; + } + + // check for gap + if (nextRange.length > 0) { + var difference = nextRange.start(0) - currentTime; + + this.logger_('Stopped at ' + currentTime + ', setting timer for ' + difference + ', seeking ' + ('to ' + nextRange.start(0))); + + this.timer_ = setTimeout(this.skipTheGap_.bind(this), difference * 1000, currentTime); + return true; + } + + // All checks failed. Returning false to indicate failure to correct waiting + return false; + }; + + PlaybackWatcher.prototype.afterSeekableWindow_ = function afterSeekableWindow_(seekable, currentTime) { + if (!seekable.length) { + // we can't make a solid case if there's no seekable, default to false + return false; + } + + if (currentTime > seekable.end(seekable.length - 1) + SAFE_TIME_DELTA) { + return true; + } + + return false; + }; + + PlaybackWatcher.prototype.beforeSeekableWindow_ = function beforeSeekableWindow_(seekable, currentTime) { + if (seekable.length && + // can't fall before 0 and 0 seekable start identifies VOD stream + seekable.start(0) > 0 && currentTime < seekable.start(0) - SAFE_TIME_DELTA) { + return true; + } + + return false; + }; + + PlaybackWatcher.prototype.videoUnderflow_ = function videoUnderflow_(nextRange, buffered, currentTime) { + if (nextRange.length === 0) { + // Even if there is no available next range, there is still a possibility we are + // stuck in a gap due to video underflow. + var gap = this.gapFromVideoUnderflow_(buffered, currentTime); + + if (gap) { + this.logger_('Encountered a gap in video from ' + gap.start + ' to ' + gap.end + '. ' + ('Seeking to current time ' + currentTime)); + + return true; + } + } + + return false; + }; + + /** + * Timer callback. If playback still has not proceeded, then we seek + * to the start of the next buffered region. + * + * @private + */ + + + PlaybackWatcher.prototype.skipTheGap_ = function skipTheGap_(scheduledCurrentTime) { + var buffered = this.tech_.buffered(); + var currentTime = this.tech_.currentTime(); + var nextRange = findNextRange(buffered, currentTime); + + this.cancelTimer_(); + + if (nextRange.length === 0 || currentTime !== scheduledCurrentTime) { + return; + } + + this.logger_('skipTheGap_:', 'currentTime:', currentTime, 'scheduled currentTime:', scheduledCurrentTime, 'nextRange start:', nextRange.start(0)); + + // only seek if we still have not played + this.tech_.setCurrentTime(nextRange.start(0) + TIME_FUDGE_FACTOR); + + this.tech_.trigger({type: 'usage', name: 'hls-gap-skip'}); + }; + + PlaybackWatcher.prototype.gapFromVideoUnderflow_ = function gapFromVideoUnderflow_(buffered, currentTime) { + // At least in Chrome, if there is a gap in the video buffer, the audio will continue + // playing for ~3 seconds after the video gap starts. This is done to account for + // video buffer underflow/underrun (note that this is not done when there is audio + // buffer underflow/underrun -- in that case the video will stop as soon as it + // encounters the gap, as audio stalls are more noticeable/jarring to a user than + // video stalls). The player's time will reflect the playthrough of audio, so the + // time will appear as if we are in a buffered region, even if we are stuck in a + // "gap." + // + // Example: + // video buffer: 0 => 10.1, 10.2 => 20 + // audio buffer: 0 => 20 + // overall buffer: 0 => 10.1, 10.2 => 20 + // current time: 13 + // + // Chrome's video froze at 10 seconds, where the video buffer encountered the gap, + // however, the audio continued playing until it reached ~3 seconds past the gap + // (13 seconds), at which point it stops as well. Since current time is past the + // gap, findNextRange will return no ranges. + // + // To check for this issue, we see if there is a gap that starts somewhere within + // a 3 second range (3 seconds +/- 1 second) back from our current time. + var gaps = findGaps(buffered); + + for (var i = 0; i < gaps.length; i++) { + var start = gaps.start(i); + var end = gaps.end(i); + + // gap is starts no more than 4 seconds back + if (currentTime - start < 4 && currentTime - start > 2) { + return { + start: start, + end: end + }; + } + } + + return null; + }; + + return PlaybackWatcher; + }(); + + var defaultOptions = { + errorInterval: 30, + getSource: function getSource(next) { + var tech = this.tech({IWillNotUseThisInPlugins: true}); + var sourceObj = tech.currentSource_; + + return next(sourceObj); + } + }; + + /** + * Main entry point for the plugin + * + * @param {Player} player a reference to a videojs Player instance + * @param {Object} [options] an object with plugin options + * @private + */ + var initPlugin = function initPlugin(player, options) { + var lastCalled = 0; + var seekTo = 0; + var localOptions = videojs$1.mergeOptions(defaultOptions, options); + + player.ready(function () { + player.trigger({type: 'usage', name: 'hls-error-reload-initialized'}); + }); + + /** + * Player modifications to perform that must wait until `loadedmetadata` + * has been triggered + * + * @private + */ + var loadedMetadataHandler = function loadedMetadataHandler() { + if (seekTo) { + player.currentTime(seekTo); + } + }; + + /** + * Set the source on the player element, playOld, and seek if necessary + * + * @param {Object} sourceObj An object specifying the source url and mime-type to playOld + * @private + */ + var setSource = function setSource(sourceObj) { + if (sourceObj === null || sourceObj === undefined) { + return; + } + seekTo = player.duration() !== Infinity && player.currentTime() || 0; + + player.one('loadedmetadata', loadedMetadataHandler); + + player.src(sourceObj); + player.trigger({type: 'usage', name: 'hls-error-reload'}); + player.play(); + }; + + /** + * Attempt to get a source from either the built-in getSource function + * or a custom function provided via the options + * + * @private + */ + var errorHandler = function errorHandler() { + // Do not attempt to reload the source if a source-reload occurred before + // 'errorInterval' time has elapsed since the last source-reload + if (Date.now() - lastCalled < localOptions.errorInterval * 1000) { + player.trigger({type: 'usage', name: 'hls-error-reload-canceled'}); + return; + } + + if (!localOptions.getSource || typeof localOptions.getSource !== 'function') { + videojs$1.log.error('ERROR: reloadSourceOnError - The option getSource must be a function!'); + return; + } + lastCalled = Date.now(); + + return localOptions.getSource.call(player, setSource); + }; + + /** + * Unbind any event handlers that were bound by the plugin + * + * @private + */ + var cleanupEvents = function cleanupEvents() { + player.off('loadedmetadata', loadedMetadataHandler); + player.off('error', errorHandler); + player.off('dispose', cleanupEvents); + }; + + /** + * Cleanup before re-initializing the plugin + * + * @param {Object} [newOptions] an object with plugin options + * @private + */ + var reinitPlugin = function reinitPlugin(newOptions) { + cleanupEvents(); + initPlugin(player, newOptions); + }; + + player.on('error', errorHandler); + player.on('dispose', cleanupEvents); + + // Overwrite the plugin function so that we can correctly cleanup before + // initializing the plugin + player.reloadSourceOnError = reinitPlugin; + }; + + /** + * Reload the source when an error is detected as long as there + * wasn't an error previously within the last 30 seconds + * + * @param {Object} [options] an object with plugin options + */ + var reloadSourceOnError = function reloadSourceOnError(options) { + initPlugin(this, options); + }; + + var version$3 = "1.0.0"; + + /** + * @file videojs-http-streaming.js + * + * The main file for the HLS project. + * License: https://github.com/videojs/videojs-http-streaming/blob/master/LICENSE + */ + + var Hls$1 = { + PlaylistLoader: PlaylistLoader, + Playlist: Playlist, + Decrypter: Decrypter, + AsyncStream: AsyncStream, + decrypt: decrypt, + utils: utils, + + STANDARD_PLAYLIST_SELECTOR: lastBandwidthSelector, + INITIAL_PLAYLIST_SELECTOR: lowestBitrateCompatibleVariantSelector, + comparePlaylistBandwidth: comparePlaylistBandwidth, + comparePlaylistResolution: comparePlaylistResolution, + + xhr: xhrFactory() + }; + + // 0.5 MB/s + var INITIAL_BANDWIDTH = 4194304; + + // Define getter/setters for config properites + ['GOAL_BUFFER_LENGTH', 'MAX_GOAL_BUFFER_LENGTH', 'GOAL_BUFFER_LENGTH_RATE', 'BUFFER_LOW_WATER_LINE', 'MAX_BUFFER_LOW_WATER_LINE', 'BUFFER_LOW_WATER_LINE_RATE', 'BANDWIDTH_VARIANCE'].forEach(function (prop) { + Object.defineProperty(Hls$1, prop, { + get: function get$$1() { + videojs$1.log.warn('using Hls.' + prop + ' is UNSAFE be sure you know what you are doing'); + return Config[prop]; + }, + set: function set$$1(value) { + videojs$1.log.warn('using Hls.' + prop + ' is UNSAFE be sure you know what you are doing'); + + if (typeof value !== 'number' || value < 0) { + videojs$1.log.warn('value of Hls.' + prop + ' must be greater than or equal to 0'); + return; + } + + Config[prop] = value; + } + }); + }); + + var simpleTypeFromSourceType = function simpleTypeFromSourceType(type) { + var mpegurlRE = /^(audio|video|application)\/(x-|vnd\.apple\.)?mpegurl/i; + + if (mpegurlRE.test(type)) { + return 'hls'; + } + + var dashRE = /^application\/dash\+xml/i; + + if (dashRE.test(type)) { + return 'dash'; + } + + return null; + }; + + /** + * Updates the selectedIndex of the QualityLevelList when a mediachange happens in hls. + * + * @param {QualityLevelList} qualityLevels The QualityLevelList to update. + * @param {PlaylistLoader} playlistLoader PlaylistLoader containing the new media info. + * @function handleHlsMediaChange + */ + var handleHlsMediaChange = function handleHlsMediaChange(qualityLevels, playlistLoader) { + var newPlaylist = playlistLoader.media(); + var selectedIndex = -1; + + for (var i = 0; i < qualityLevels.length; i++) { + if (qualityLevels[i].id === newPlaylist.uri) { + selectedIndex = i; + break; + } + } + + qualityLevels.selectedIndex_ = selectedIndex; + qualityLevels.trigger({ + selectedIndex: selectedIndex, + type: 'change' + }); + }; + + /** + * Adds quality levels to list once playlist metadata is available + * + * @param {QualityLevelList} qualityLevels The QualityLevelList to attach events to. + * @param {Object} hls Hls object to listen to for media events. + * @function handleHlsLoadedMetadata + */ + var handleHlsLoadedMetadata = function handleHlsLoadedMetadata(qualityLevels, hls) { + hls.representations().forEach(function (rep) { + qualityLevels.addQualityLevel(rep); + }); + handleHlsMediaChange(qualityLevels, hls.playlists); + }; + + // HLS is a source handler, not a tech. Make sure attempts to use it + // as one do not cause exceptions. + Hls$1.canPlaySource = function () { + return videojs$1.log.warn('HLS is no longer a tech. Please remove it from ' + 'your player\'s techOrder.'); + }; + + var emeKeySystems = function emeKeySystems(keySystemOptions, videoPlaylist, audioPlaylist) { + if (!keySystemOptions) { + return keySystemOptions; + } + + // upsert the content types based on the selected playlist + var keySystemContentTypes = {}; + + for (var keySystem in keySystemOptions) { + keySystemContentTypes[keySystem] = { + audioContentType: 'audio/mp4; codecs="' + audioPlaylist.attributes.CODECS + '"', + videoContentType: 'video/mp4; codecs="' + videoPlaylist.attributes.CODECS + '"' + }; + + if (videoPlaylist.contentProtection && videoPlaylist.contentProtection[keySystem] && videoPlaylist.contentProtection[keySystem].pssh) { + keySystemContentTypes[keySystem].pssh = videoPlaylist.contentProtection[keySystem].pssh; + } + + // videojs-contrib-eme accepts the option of specifying: 'com.some.cdm': 'url' + // so we need to prevent overwriting the URL entirely + if (typeof keySystemOptions[keySystem] === 'string') { + keySystemContentTypes[keySystem].url = keySystemOptions[keySystem]; + } + } + + return videojs$1.mergeOptions(keySystemOptions, keySystemContentTypes); + }; + + var setupEmeOptions = function setupEmeOptions(hlsHandler) { + if (hlsHandler.options_.sourceType !== 'dash') { + return; + } + var player = videojs$1.players[hlsHandler.tech_.options_.playerId]; + + if (player.eme) { + var sourceOptions = emeKeySystems(hlsHandler.source_.keySystems, hlsHandler.playlists.media(), hlsHandler.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader.media()); + + if (sourceOptions) { + player.currentSource().keySystems = sourceOptions; + } + } + }; + + /** + * Whether the browser has built-in HLS support. + */ + Hls$1.supportsNativeHls = function () { + var video = document_1.createElement('video'); + + // native HLS is definitely not supported if HTML5 video isn't + if (!videojs$1.getTech('Html5').isSupported()) { + return false; + } + + // HLS manifests can go by many mime-types + var canPlay = [ + // Apple santioned + 'application/vnd.apple.mpegurl', + // Apple sanctioned for backwards compatibility + 'audio/mpegurl', + // Very common + 'audio/x-mpegurl', + // Very common + 'application/x-mpegurl', + // Included for completeness + 'video/x-mpegurl', 'video/mpegurl', 'application/mpegurl']; + + return canPlay.some(function (canItPlay) { + return (/maybe|probably/i.test(video.canPlayType(canItPlay)) + ); + }); + }(); + + Hls$1.supportsNativeDash = function () { + if (!videojs$1.getTech('Html5').isSupported()) { + return false; + } + + return (/maybe|probably/i.test(document_1.createElement('video').canPlayType('application/dash+xml')) + ); + }(); + + Hls$1.supportsTypeNatively = function (type) { + if (type === 'hls') { + return Hls$1.supportsNativeHls; + } + + if (type === 'dash') { + return Hls$1.supportsNativeDash; + } + + return false; + }; + + /** + * HLS is a source handler, not a tech. Make sure attempts to use it + * as one do not cause exceptions. + */ + Hls$1.isSupported = function () { + return videojs$1.log.warn('HLS is no longer a tech. Please remove it from ' + 'your player\'s techOrder.'); + }; + + var Component$1 = videojs$1.getComponent('Component'); + + /** + * The Hls Handler object, where we orchestrate all of the parts + * of HLS to interact with video.js + * + * @class HlsHandler + * @extends videojs.Component + * @param {Object} source the soruce object + * @param {Tech} tech the parent tech object + * @param {Object} options optional and required options + */ + + var HlsHandler = function (_Component) { + inherits(HlsHandler, _Component); + + function HlsHandler(source, tech, options) { + classCallCheck(this, HlsHandler); + + // tech.player() is deprecated but setup a reference to HLS for + // backwards-compatibility + var _this36 = possibleConstructorReturn(this, _Component.call(this, tech, options.hls)); + + if (tech.options_ && tech.options_.playerId) { + var _player = videojs$1(tech.options_.playerId); + + if (!_player.hasOwnProperty('hls')) { + Object.defineProperty(_player, 'hls', { + get: function get$$1() { + videojs$1.log.warn('player.hls is deprecated. Use player.tech_.hls instead.'); + tech.trigger({type: 'usage', name: 'hls-player-access'}); + return _this36; + } + }); + } + + // Set up a reference to the HlsHandler from player.vhs. This allows users to start + // migrating from player.tech_.hls... to player.vhs... for API access. Although this + // isn't the most appropriate form of reference for video.js (since all APIs should + // be provided through core video.js), it is a common pattern for plugins, and vhs + // will act accordingly. + _player.vhs = _this36; + // deprecated, for backwards compatibility + _player.dash = _this36; + } + + _this36.tech_ = tech; + _this36.source_ = source; + _this36.stats = {}; + _this36.ignoreNextSeekingEvent_ = false; + _this36.setOptions_(); + + // overriding native HLS only works if audio tracks have been emulated + // error early if we're misconfigured: + if (_this36.options_.overrideNative && (tech.featuresNativeVideoTracks || tech.featuresNativeAudioTracks)) { + throw new Error('Overriding native HLS requires emulated tracks. ' + 'See https://git.io/vMpjB'); + } + + // listen for fullscreenchange events for this player so that we + // can adjust our quality selection quickly + _this36.on(document_1, ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange'], function (event) { + var fullscreenElement = document_1.fullscreenElement || document_1.webkitFullscreenElement || document_1.mozFullScreenElement || document_1.msFullscreenElement; + + if (fullscreenElement && fullscreenElement.contains(_this36.tech_.el())) { + _this36.masterPlaylistController_.fastQualityChange_(); + } + }); + + _this36.on(_this36.tech_, 'seeking', function () { + if (this.ignoreNextSeekingEvent_) { + this.ignoreNextSeekingEvent_ = false; + return; + } + + this.setCurrentTime(this.tech_.currentTime()); + }); + _this36.on(_this36.tech_, 'error', function () { + if (this.masterPlaylistController_) { + this.masterPlaylistController_.pauseLoading(); + } + }); + + _this36.on(_this36.tech_, 'play', _this36.play); + return _this36; + } + + HlsHandler.prototype.setOptions_ = function setOptions_() { + var _this37 = this; + + // defaults + this.options_.withCredentials = this.options_.withCredentials || false; + + if (typeof this.options_.blacklistDuration !== 'number') { + this.options_.blacklistDuration = 5 * 60; + } + + // start playlist selection at a reasonable bandwidth for + // broadband internet (0.5 MB/s) or mobile (0.0625 MB/s) + if (typeof this.options_.bandwidth !== 'number') { + this.options_.bandwidth = INITIAL_BANDWIDTH; + } + + // If the bandwidth number is unchanged from the initial setting + // then this takes precedence over the enableLowInitialPlaylist option + this.options_.enableLowInitialPlaylist = this.options_.enableLowInitialPlaylist && this.options_.bandwidth === INITIAL_BANDWIDTH; + + // grab options passed to player.src + ['withCredentials', 'bandwidth'].forEach(function (option) { + if (typeof _this37.source_[option] !== 'undefined') { + _this37.options_[option] = _this37.source_[option]; + } + }); + + this.bandwidth = this.options_.bandwidth; + }; + /** + * called when player.src gets called, handle a new source + * + * @param {Object} src the source object to handle + */ + + + HlsHandler.prototype.src = function src(_src, type) { + var _this38 = this; + + // do nothing if the src is falsey + if (!_src) { + return; + } + this.setOptions_(); + // add master playlist controller options + this.options_.url = this.source_.src; + this.options_.tech = this.tech_; + this.options_.externHls = Hls$1; + this.options_.sourceType = simpleTypeFromSourceType(type); + + this.masterPlaylistController_ = new MasterPlaylistController(this.options_); + this.playbackWatcher_ = new PlaybackWatcher(videojs$1.mergeOptions(this.options_, { + seekable: function seekable() { + return _this38.seekable(); + } + })); + + this.masterPlaylistController_.on('error', function () { + var player = videojs$1.players[_this38.tech_.options_.playerId]; + + player.error(_this38.masterPlaylistController_.error); + }); + + // `this` in selectPlaylist should be the HlsHandler for backwards + // compatibility with < v2 + this.masterPlaylistController_.selectPlaylist = this.selectPlaylist ? this.selectPlaylist.bind(this) : Hls$1.STANDARD_PLAYLIST_SELECTOR.bind(this); + + this.masterPlaylistController_.selectInitialPlaylist = Hls$1.INITIAL_PLAYLIST_SELECTOR.bind(this); + + // re-expose some internal objects for backwards compatibility with < v2 + this.playlists = this.masterPlaylistController_.masterPlaylistLoader_; + this.mediaSource = this.masterPlaylistController_.mediaSource; + + // Proxy assignment of some properties to the master playlist + // controller. Using a custom property for backwards compatibility + // with < v2 + Object.defineProperties(this, { + selectPlaylist: { + get: function get$$1() { + return this.masterPlaylistController_.selectPlaylist; + }, + set: function set$$1(selectPlaylist) { + this.masterPlaylistController_.selectPlaylist = selectPlaylist.bind(this); + } + }, + throughput: { + get: function get$$1() { + return this.masterPlaylistController_.mainSegmentLoader_.throughput.rate; + }, + set: function set$$1(throughput) { + this.masterPlaylistController_.mainSegmentLoader_.throughput.rate = throughput; + // By setting `count` to 1 the throughput value becomes the starting value + // for the cumulative average + this.masterPlaylistController_.mainSegmentLoader_.throughput.count = 1; + } + }, + bandwidth: { + get: function get$$1() { + return this.masterPlaylistController_.mainSegmentLoader_.bandwidth; + }, + set: function set$$1(bandwidth) { + this.masterPlaylistController_.mainSegmentLoader_.bandwidth = bandwidth; + // setting the bandwidth manually resets the throughput counter + // `count` is set to zero that current value of `rate` isn't included + // in the cumulative average + this.masterPlaylistController_.mainSegmentLoader_.throughput = { + rate: 0, + count: 0 + }; + } + }, + /** + * `systemBandwidth` is a combination of two serial processes bit-rates. The first + * is the network bitrate provided by `bandwidth` and the second is the bitrate of + * the entire process after that - decryption, transmuxing, and appending - provided + * by `throughput`. + * + * Since the two process are serial, the overall system bandwidth is given by: + * sysBandwidth = 1 / (1 / bandwidth + 1 / throughput) + */ + systemBandwidth: { + get: function get$$1() { + var invBandwidth = 1 / (this.bandwidth || 1); + var invThroughput = void 0; + + if (this.throughput > 0) { + invThroughput = 1 / this.throughput; + } else { + invThroughput = 0; + } + + var systemBitrate = Math.floor(1 / (invBandwidth + invThroughput)); + + return systemBitrate; + }, + set: function set$$1() { + videojs$1.log.error('The "systemBandwidth" property is read-only'); + } + } + }); + + Object.defineProperties(this.stats, { + bandwidth: { + get: function get$$1() { + return _this38.bandwidth || 0; + }, + enumerable: true + }, + mediaRequests: { + get: function get$$1() { + return _this38.masterPlaylistController_.mediaRequests_() || 0; + }, + enumerable: true + }, + mediaRequestsAborted: { + get: function get$$1() { + return _this38.masterPlaylistController_.mediaRequestsAborted_() || 0; + }, + enumerable: true + }, + mediaRequestsTimedout: { + get: function get$$1() { + return _this38.masterPlaylistController_.mediaRequestsTimedout_() || 0; + }, + enumerable: true + }, + mediaRequestsErrored: { + get: function get$$1() { + return _this38.masterPlaylistController_.mediaRequestsErrored_() || 0; + }, + enumerable: true + }, + mediaTransferDuration: { + get: function get$$1() { + return _this38.masterPlaylistController_.mediaTransferDuration_() || 0; + }, + enumerable: true + }, + mediaBytesTransferred: { + get: function get$$1() { + return _this38.masterPlaylistController_.mediaBytesTransferred_() || 0; + }, + enumerable: true + }, + mediaSecondsLoaded: { + get: function get$$1() { + return _this38.masterPlaylistController_.mediaSecondsLoaded_() || 0; + }, + enumerable: true + }, + buffered: { + get: function get$$1() { + return timeRangesToArray(_this38.tech_.buffered()); + }, + enumerable: true + }, + currentTime: { + get: function get$$1() { + return _this38.tech_.currentTime(); + }, + enumerable: true + }, + currentSource: { + get: function get$$1() { + return _this38.tech_.currentSource_; + }, + enumerable: true + }, + currentTech: { + get: function get$$1() { + return _this38.tech_.name_; + }, + enumerable: true + }, + duration: { + get: function get$$1() { + return _this38.tech_.duration(); + }, + enumerable: true + }, + master: { + get: function get$$1() { + return _this38.playlists.master; + }, + enumerable: true + }, + playerDimensions: { + get: function get$$1() { + return _this38.tech_.currentDimensions(); + }, + enumerable: true + }, + seekable: { + get: function get$$1() { + return timeRangesToArray(_this38.tech_.seekable()); + }, + enumerable: true + }, + timestamp: { + get: function get$$1() { + return Date.now(); + }, + enumerable: true + }, + videoPlaybackQuality: { + get: function get$$1() { + return _this38.tech_.getVideoPlaybackQuality(); + }, + enumerable: true + } + }); + + this.tech_.one('canplay', this.masterPlaylistController_.setupFirstPlay.bind(this.masterPlaylistController_)); + + this.masterPlaylistController_.on('selectedinitialmedia', function () { + // Add the manual rendition mix-in to HlsHandler + renditionSelectionMixin(_this38); + setupEmeOptions(_this38); + }); + + // the bandwidth of the primary segment loader is our best + // estimate of overall bandwidth + this.on(this.masterPlaylistController_, 'progress', function () { + this.tech_.trigger('progress'); + }); + + // In the live case, we need to ignore the very first `seeking` event since + // that will be the result of the seek-to-live behavior + this.on(this.masterPlaylistController_, 'firstplay', function () { + this.ignoreNextSeekingEvent_ = true; + }); + + this.tech_.ready(function () { + return _this38.setupQualityLevels_(); + }); + + // do nothing if the tech has been disposed already + // this can occur if someone sets the src in player.ready(), for instance + if (!this.tech_.el()) { + return; + } + + this.tech_.src(videojs$1.URL.createObjectURL(this.masterPlaylistController_.mediaSource)); + }; + + /** + * Initializes the quality levels and sets listeners to update them. + * + * @method setupQualityLevels_ + * @private + */ + + + HlsHandler.prototype.setupQualityLevels_ = function setupQualityLevels_() { + var _this39 = this; + + var player = videojs$1.players[this.tech_.options_.playerId]; + + if (player && player.qualityLevels) { + this.qualityLevels_ = player.qualityLevels(); + + this.masterPlaylistController_.on('selectedinitialmedia', function () { + handleHlsLoadedMetadata(_this39.qualityLevels_, _this39); + }); + + this.playlists.on('mediachange', function () { + handleHlsMediaChange(_this39.qualityLevels_, _this39.playlists); + }); + } + }; + + /** + * Begin playing the video. + */ + + + HlsHandler.prototype.play = function play() { + this.masterPlaylistController_.play(); + }; + + /** + * a wrapper around the function in MasterPlaylistController + */ + + + HlsHandler.prototype.setCurrentTime = function setCurrentTime(currentTime) { + this.masterPlaylistController_.setCurrentTime(currentTime); + }; + + /** + * a wrapper around the function in MasterPlaylistController + */ + + + HlsHandler.prototype.duration = function duration() { + return this.masterPlaylistController_.duration(); + }; + + /** + * a wrapper around the function in MasterPlaylistController + */ + + + HlsHandler.prototype.seekable = function seekable() { + return this.masterPlaylistController_.seekable(); + }; + + /** + * Abort all outstanding work and cleanup. + */ + + + HlsHandler.prototype.dispose = function dispose() { + if (this.playbackWatcher_) { + this.playbackWatcher_.dispose(); + } + if (this.masterPlaylistController_) { + this.masterPlaylistController_.dispose(); + } + if (this.qualityLevels_) { + this.qualityLevels_.dispose(); + } + _Component.prototype.dispose.call(this); + }; + + return HlsHandler; + }(Component$1); + + /** + * The Source Handler object, which informs video.js what additional + * MIME types are supported and sets up playback. It is registered + * automatically to the appropriate tech based on the capabilities of + * the browser it is running in. It is not necessary to use or modify + * this object in normal usage. + */ + + + var HlsSourceHandler = { + name: 'videojs-http-streaming', + VERSION: version$3, + canHandleSource: function canHandleSource(srcObj) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var localOptions = videojs$1.mergeOptions(videojs$1.options, options); + + return HlsSourceHandler.canPlayType(srcObj.type, localOptions); + }, + handleSource: function handleSource(source, tech) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + var localOptions = videojs$1.mergeOptions(videojs$1.options, options); + + tech.hls = new HlsHandler(source, tech, localOptions); + tech.hls.xhr = xhrFactory(); + + tech.hls.src(source.src, source.type); + return tech.hls; + }, + canPlayType: function canPlayType(type) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var _videojs$mergeOptions = videojs$1.mergeOptions(videojs$1.options, options), + overrideNative = _videojs$mergeOptions.hls.overrideNative; + + var supportedType = simpleTypeFromSourceType(type); + var canUseMsePlayback = supportedType && (!Hls$1.supportsTypeNatively(supportedType) || overrideNative); + + return canUseMsePlayback ? 'maybe' : ''; + } + }; + + if (typeof videojs$1.MediaSource === 'undefined' || typeof videojs$1.URL === 'undefined') { + videojs$1.MediaSource = MediaSource; + videojs$1.URL = URL$1; + } + + // register source handlers with the appropriate techs + if (MediaSource.supportsNativeMediaSources()) { + videojs$1.getTech('Html5').registerSourceHandler(HlsSourceHandler, 0); + } + + videojs$1.HlsHandler = HlsHandler; + videojs$1.HlsSourceHandler = HlsSourceHandler; + videojs$1.Hls = Hls$1; + if (!videojs$1.use) { + videojs$1.registerComponent('Hls', Hls$1); + } + videojs$1.options.hls = videojs$1.options.hls || {}; + + if (videojs$1.registerPlugin) { + videojs$1.registerPlugin('reloadSourceOnError', reloadSourceOnError); + } else { + videojs$1.plugin('reloadSourceOnError', reloadSourceOnError); + } + + return videojs$1; + +}))); diff --git a/form/src/assets/libs/video-js-7.0.0/video.min.js b/form/src/assets/libs/video-js-7.0.0/video.min.js new file mode 100644 index 0000000..5d05e6c --- /dev/null +++ b/form/src/assets/libs/video-js-7.0.0/video.min.js @@ -0,0 +1,12 @@ +/** + * @license + * Video.js 7.0.0 <http://videojs.com/> + * Copyright Brightcove, Inc. <https://www.brightcove.com/> + * Available under Apache License Version 2.0 + * <https://github.com/videojs/video.js/blob/master/LICENSE> + * + * Includes vtt.js <https://github.com/mozilla/vtt.js> + * Available under Apache License Version 2.0 + * <https://github.com/mozilla/vtt.js/blob/master/LICENSE> + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.videojs=e()}(this,function(){var d="7.0.0",t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function e(t,e){return t(e={exports:{}},e.exports),e.exports}var i,g="undefined"!=typeof window?window:"undefined"!=typeof t?t:"undefined"!=typeof self?self:{},r={},n=Object.freeze({default:r}),s=n&&r||n,a="undefined"!=typeof t?t:"undefined"!=typeof window?window:{};"undefined"!=typeof document?i=document:(i=a["__GLOBAL_DOCUMENT_CACHE@4"])||(i=a["__GLOBAL_DOCUMENT_CACHE@4"]=s);var p=i,o=void 0,u="info",l=[],c=function(t,e){var i=o.levels[u],r=new RegExp("^("+i+")$");if("log"!==t&&e.unshift(t.toUpperCase()+":"),l&&l.push([].concat(e)),e.unshift("VIDEOJS:"),g.console){var n=g.console[t];n||"debug"!==t||(n=g.console.info||g.console.log),n&&i&&r.test(t)&&n[Array.isArray(e)?"apply":"call"](g.console,e)}};(o=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];c("log",e)}).levels={all:"debug|log|warn|error",off:"",debug:"debug|log|warn|error",info:"log|warn|error",warn:"warn|error",error:"error",DEFAULT:u},o.level=function(t){if("string"==typeof t){if(!o.levels.hasOwnProperty(t))throw new Error('"'+t+'" in not a valid log level');u=t}return u},o.history=function(){return l?[].concat(l):[]},o.history.clear=function(){l&&(l.length=0)},o.history.disable=function(){null!==l&&(l.length=0,l=null)},o.history.enable=function(){null===l&&(l=[])},o.error=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];return c("error",e)},o.warn=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];return c("warn",e)},o.debug=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];return c("debug",e)};var f=o;var m=function(t){for(var e="",i=0;i<arguments.length;i++)e+=t[i].replace(/\n\r?\s*/g,"")+(arguments[i+1]||"");return e},v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},y=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},_=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)},b=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e},h=function(t,e){return t.raw=e,t},T=Object.prototype.toString,S=function(t){return E(t)?Object.keys(t):[]};function k(e,i){S(e).forEach(function(t){return i(e[t],t)})}function C(i){for(var t=arguments.length,e=Array(1<t?t-1:0),r=1;r<t;r++)e[r-1]=arguments[r];return Object.assign?Object.assign.apply(Object,[i].concat(e)):(e.forEach(function(t){t&&k(t,function(t,e){i[e]=t})}),i)}function E(t){return!!t&&"object"===("undefined"==typeof t?"undefined":v(t))}function w(t){return E(t)&&"[object Object]"===T.call(t)&&t.constructor===Object}function A(t,e){if(!t||!e)return"";if("function"==typeof g.getComputedStyle){var i=g.getComputedStyle(t);return i?i[e]:""}return""}var L=h(["Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set "," to ","."],["Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set "," to ","."]);function P(t){return"string"==typeof t&&/\S/.test(t)}function O(t){if(/\s/.test(t))throw new Error("class has illegal whitespace characters")}function x(){return p===g.document}function I(t){return E(t)&&1===t.nodeType}function D(){try{return g.parent!==g.self}catch(t){return!0}}function R(r){return function(t,e){if(!P(t))return p[r](null);P(e)&&(e=p.querySelector(e));var i=I(e)?e:p;return i[r]&&i[r](t)}}function M(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"div",i=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},e=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{},r=arguments[3],n=p.createElement(t);return Object.getOwnPropertyNames(i).forEach(function(t){var e=i[t];-1!==t.indexOf("aria-")||"role"===t||"type"===t?(f.warn(m(L,t,e)),n.setAttribute(t,e)):"textContent"===t?U(n,e):n[t]=e}),Object.getOwnPropertyNames(e).forEach(function(t){n.setAttribute(t,e[t])}),r&&et(n,r),n}function U(t,e){return"undefined"==typeof t.textContent?t.innerText=e:t.textContent=e,t}function N(t,e){e.firstChild?e.insertBefore(t,e.firstChild):e.appendChild(t)}function B(t,e){return O(e),t.classList?t.classList.contains(e):(i=e,new RegExp("(^|\\s)"+i+"($|\\s)")).test(t.className);var i}function j(t,e){return t.classList?t.classList.add(e):B(t,e)||(t.className=(t.className+" "+e).trim()),t}function F(t,e){return t.classList?t.classList.remove(e):(O(e),t.className=t.className.split(/\s+/).filter(function(t){return t!==e}).join(" ")),t}function H(t,e,i){var r=B(t,e);if("function"==typeof i&&(i=i(t,e)),"boolean"!=typeof i&&(i=!r),i!==r)return i?j(t,e):F(t,e),t}function V(i,r){Object.getOwnPropertyNames(r).forEach(function(t){var e=r[t];null===e||"undefined"==typeof e||!1===e?i.removeAttribute(t):i.setAttribute(t,!0===e?"":e)})}function q(t){var e={},i=",autoplay,controls,playsinline,loop,muted,default,defaultMuted,";if(t&&t.attributes&&0<t.attributes.length)for(var r=t.attributes,n=r.length-1;0<=n;n--){var s=r[n].name,a=r[n].value;"boolean"!=typeof t[s]&&-1===i.indexOf(","+s+",")||(a=null!==a),e[s]=a}return e}function W(t,e){return t.getAttribute(e)}function z(t,e,i){t.setAttribute(e,i)}function G(t,e){t.removeAttribute(e)}function X(){p.body.focus(),p.onselectstart=function(){return!1}}function Y(){p.onselectstart=function(){return!0}}function $(t){if(t&&t.getBoundingClientRect&&t.parentNode){var e=t.getBoundingClientRect(),i={};return["bottom","height","left","right","top","width"].forEach(function(t){void 0!==e[t]&&(i[t]=e[t])}),i.height||(i.height=parseFloat(A(t,"height"))),i.width||(i.width=parseFloat(A(t,"width"))),i}}function K(t){var e=void 0;if(t.getBoundingClientRect&&t.parentNode&&(e=t.getBoundingClientRect()),!e)return{left:0,top:0};var i=p.documentElement,r=p.body,n=i.clientLeft||r.clientLeft||0,s=g.pageXOffset||r.scrollLeft,a=e.left+s-n,o=i.clientTop||r.clientTop||0,u=g.pageYOffset||r.scrollTop,l=e.top+u-o;return{left:Math.round(a),top:Math.round(l)}}function Q(t,e){var i={},r=K(t),n=t.offsetWidth,s=t.offsetHeight,a=r.top,o=r.left,u=e.pageY,l=e.pageX;return e.changedTouches&&(l=e.changedTouches[0].pageX,u=e.changedTouches[0].pageY),i.y=Math.max(0,Math.min(1,(a-u+s)/s)),i.x=Math.max(0,Math.min(1,(l-o)/n)),i}function J(t){return E(t)&&3===t.nodeType}function Z(t){for(;t.firstChild;)t.removeChild(t.firstChild);return t}function tt(t){return"function"==typeof t&&(t=t()),(Array.isArray(t)?t:[t]).map(function(t){return"function"==typeof t&&(t=t()),I(t)||J(t)?t:"string"==typeof t&&/\S/.test(t)?p.createTextNode(t):void 0}).filter(function(t){return t})}function et(e,t){return tt(t).forEach(function(t){return e.appendChild(t)}),e}function it(t,e){return et(Z(t),e)}function rt(t){return void 0===t.button&&void 0===t.buttons||(0===t.button&&void 0===t.buttons||0===t.button&&1===t.buttons)}var nt=R("querySelector"),st=R("querySelectorAll"),at=Object.freeze({isReal:x,isEl:I,isInFrame:D,createEl:M,textContent:U,prependTo:N,hasClass:B,addClass:j,removeClass:F,toggleClass:H,setAttributes:V,getAttributes:q,getAttribute:W,setAttribute:z,removeAttribute:G,blockTextSelection:X,unblockTextSelection:Y,getBoundingClientRect:$,findPosition:K,getPointerPosition:Q,isTextNode:J,emptyEl:Z,normalizeContent:tt,appendContent:et,insertContent:it,isSingleLeftClick:rt,$:nt,$$:st}),ot=1;function ut(){return ot++}var lt={},ct="vdata"+(new Date).getTime();function ht(t){var e=t[ct];return e||(e=t[ct]=ut()),lt[e]||(lt[e]={}),lt[e]}function dt(t){var e=t[ct];return!!e&&!!Object.getOwnPropertyNames(lt[e]).length}function pt(e){var t=e[ct];if(t){delete lt[t];try{delete e[ct]}catch(t){e.removeAttribute?e.removeAttribute(ct):e[ct]=null}}}function ft(t,e){var i=ht(t);0===i.handlers[e].length&&(delete i.handlers[e],t.removeEventListener?t.removeEventListener(e,i.dispatcher,!1):t.detachEvent&&t.detachEvent("on"+e,i.dispatcher)),Object.getOwnPropertyNames(i.handlers).length<=0&&(delete i.handlers,delete i.dispatcher,delete i.disabled),0===Object.getOwnPropertyNames(i).length&&pt(t)}function mt(e,i,t,r){t.forEach(function(t){e(i,t,r)})}function gt(t){function e(){return!0}function i(){return!1}if(!t||!t.isPropagationStopped){var r=t||g.event;for(var n in t={},r)"layerX"!==n&&"layerY"!==n&&"keyLocation"!==n&&"webkitMovementX"!==n&&"webkitMovementY"!==n&&("returnValue"===n&&r.preventDefault||(t[n]=r[n]));if(t.target||(t.target=t.srcElement||p),t.relatedTarget||(t.relatedTarget=t.fromElement===t.target?t.toElement:t.fromElement),t.preventDefault=function(){r.preventDefault&&r.preventDefault(),t.returnValue=!1,r.returnValue=!1,t.defaultPrevented=!0},t.defaultPrevented=!1,t.stopPropagation=function(){r.stopPropagation&&r.stopPropagation(),t.cancelBubble=!0,r.cancelBubble=!0,t.isPropagationStopped=e},t.isPropagationStopped=i,t.stopImmediatePropagation=function(){r.stopImmediatePropagation&&r.stopImmediatePropagation(),t.isImmediatePropagationStopped=e,t.stopPropagation()},t.isImmediatePropagationStopped=i,null!==t.clientX&&void 0!==t.clientX){var s=p.documentElement,a=p.body;t.pageX=t.clientX+(s&&s.scrollLeft||a&&a.scrollLeft||0)-(s&&s.clientLeft||a&&a.clientLeft||0),t.pageY=t.clientY+(s&&s.scrollTop||a&&a.scrollTop||0)-(s&&s.clientTop||a&&a.clientTop||0)}t.which=t.charCode||t.keyCode,null!==t.button&&void 0!==t.button&&(t.button=1&t.button?0:4&t.button?1:2&t.button?2:0)}return t}var yt=!1;!function(){try{var t=Object.defineProperty({},"passive",{get:function(){yt=!0}});g.addEventListener("test",null,t),g.removeEventListener("test",null,t)}catch(t){}}();var vt=["touchstart","touchmove"];function _t(a,t,e){if(Array.isArray(t))return mt(_t,a,t,e);var o=ht(a);if(o.handlers||(o.handlers={}),o.handlers[t]||(o.handlers[t]=[]),e.guid||(e.guid=ut()),o.handlers[t].push(e),o.dispatcher||(o.disabled=!1,o.dispatcher=function(t,e){if(!o.disabled){t=gt(t);var i=o.handlers[t.type];if(i)for(var r=i.slice(0),n=0,s=r.length;n<s&&!t.isImmediatePropagationStopped();n++)try{r[n].call(a,t,e)}catch(t){f.error(t)}}}),1===o.handlers[t].length)if(a.addEventListener){var i=!1;yt&&-1<vt.indexOf(t)&&(i={passive:!0}),a.addEventListener(t,o.dispatcher,i)}else a.attachEvent&&a.attachEvent("on"+t,o.dispatcher)}function bt(t,e,i){if(dt(t)){var r=ht(t);if(r.handlers){if(Array.isArray(e))return mt(bt,t,e,i);var n=function(t,e){r.handlers[e]=[],ft(t,e)};if(void 0!==e){var s=r.handlers[e];if(s)if(i){if(i.guid)for(var a=0;a<s.length;a++)s[a].guid===i.guid&&s.splice(a--,1);ft(t,e)}else n(t,e)}else for(var o in r.handlers)Object.prototype.hasOwnProperty.call(r.handlers||{},o)&&n(t,o)}}}function Tt(t,e,i){var r=dt(t)?ht(t):{},n=t.parentNode||t.ownerDocument;if("string"==typeof e?e={type:e,target:t}:e.target||(e.target=t),e=gt(e),r.dispatcher&&r.dispatcher.call(t,e,i),n&&!e.isPropagationStopped()&&!0===e.bubbles)Tt.call(null,n,e,i);else if(!n&&!e.defaultPrevented){var s=ht(e.target);e.target[e.type]&&(s.disabled=!0,"function"==typeof e.target[e.type]&&e.target[e.type](),s.disabled=!1)}return!e.defaultPrevented}function St(e,i,r){if(Array.isArray(i))return mt(St,e,i,r);var t=function t(){bt(e,i,t),r.apply(this,arguments)};t.guid=r.guid=r.guid||ut(),_t(e,i,t)}var kt=Object.freeze({fixEvent:gt,on:_t,off:bt,trigger:Tt,one:St}),Ct=!1,Et=void 0,wt=function(){if(x()&&!1!==Et.options.autoSetup){var t=Array.prototype.slice.call(p.getElementsByTagName("video")),e=Array.prototype.slice.call(p.getElementsByTagName("audio")),i=Array.prototype.slice.call(p.getElementsByTagName("video-js")),r=t.concat(e,i);if(r&&0<r.length)for(var n=0,s=r.length;n<s;n++){var a=r[n];if(!a||!a.getAttribute){At(1);break}void 0===a.player&&null!==a.getAttribute("data-setup")&&Et(a)}else Ct||At(1)}};function At(t,e){e&&(Et=e),g.setTimeout(wt,t)}x()&&"complete"===p.readyState?Ct=!0:St(g,"load",function(){Ct=!0});var Lt=function(t){var e=p.createElement("style");return e.className=t,e},Pt=function(t,e){t.styleSheet?t.styleSheet.cssText=e:t.textContent=e},Ot=function(t,e,i){e.guid||(e.guid=ut());var r=function(){return e.apply(t,arguments)};return r.guid=i?i+"_"+e.guid:e.guid,r},xt=function(e,i){var r=Date.now();return function(){var t=Date.now();i<=t-r&&(e.apply(void 0,arguments),r=t)}},It=function(r,n,s){var a=3<arguments.length&&void 0!==arguments[3]?arguments[3]:g,o=void 0;return function(){var t=this,e=arguments,i=function(){i=o=null,s||r.apply(t,e)};!o&&s&&r.apply(t,e),a.clearTimeout(o),o=a.setTimeout(i,n)}},Dt=function(){};Dt.prototype.allowedEvents_={},Dt.prototype.addEventListener=Dt.prototype.on=function(t,e){var i=this.addEventListener;this.addEventListener=function(){},_t(this,t,e),this.addEventListener=i},Dt.prototype.removeEventListener=Dt.prototype.off=function(t,e){bt(this,t,e)},Dt.prototype.one=function(t,e){var i=this.addEventListener;this.addEventListener=function(){},St(this,t,e),this.addEventListener=i},Dt.prototype.dispatchEvent=Dt.prototype.trigger=function(t){var e=t.type||t;"string"==typeof t&&(t={type:e}),t=gt(t),this.allowedEvents_[e]&&this["on"+e]&&this["on"+e](t),Tt(this,t)};var Rt=function(e){return e instanceof Dt||!!e.eventBusEl_&&["on","one","off","trigger"].every(function(t){return"function"==typeof e[t]})},Mt=function(t){return"string"==typeof t&&/\S/.test(t)||Array.isArray(t)&&!!t.length},Ut=function(t){if(!t.nodeName&&!Rt(t))throw new Error("Invalid target; must be a DOM node or evented object.")},Nt=function(t){if(!Mt(t))throw new Error("Invalid event type; must be a non-empty string or array.")},Bt=function(t){if("function"!=typeof t)throw new Error("Invalid listener; must be a function.")},jt=function(t,e){var i=e.length<3||e[0]===t||e[0]===t.eventBusEl_,r=void 0,n=void 0,s=void 0;return i?(r=t.eventBusEl_,3<=e.length&&e.shift(),n=e[0],s=e[1]):(r=e[0],n=e[1],s=e[2]),Ut(r),Nt(n),Bt(s),{isTargetingSelf:i,target:r,type:n,listener:s=Ot(t,s)}},Ft=function(t,e,i,r){Ut(t),t.nodeName?kt[e](t,i,r):t[e](i,r)},Ht={on:function(){for(var t=this,e=arguments.length,i=Array(e),r=0;r<e;r++)i[r]=arguments[r];var n=jt(this,i),s=n.isTargetingSelf,a=n.target,o=n.type,u=n.listener;if(Ft(a,"on",o,u),!s){var l=function(){return t.off(a,o,u)};l.guid=u.guid;var c=function(){return t.off("dispose",l)};c.guid=u.guid,Ft(this,"on","dispose",l),Ft(a,"on","dispose",c)}},one:function(){for(var n=this,t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];var r=jt(this,e),s=r.isTargetingSelf,a=r.target,o=r.type,u=r.listener;if(s)Ft(a,"one",o,u);else{var l=function t(){for(var e=arguments.length,i=Array(e),r=0;r<e;r++)i[r]=arguments[r];n.off(a,o,t),u.apply(null,i)};l.guid=u.guid,Ft(a,"one",o,l)}},off:function(t,e,i){if(!t||Mt(t))bt(this.eventBusEl_,t,e);else{var r=t,n=e;Ut(r),Nt(n),Bt(i),i=Ot(this,i),this.off("dispose",i),r.nodeName?(bt(r,n,i),bt(r,"dispose",i)):Rt(r)&&(r.off(n,i),r.off("dispose",i))}},trigger:function(t,e){return Tt(this.eventBusEl_,t,e)}};function Vt(t){var e=(1<arguments.length&&void 0!==arguments[1]?arguments[1]:{}).eventBusKey;if(e){if(!t[e].nodeName)throw new Error('The eventBusKey "'+e+'" does not refer to an element.');t.eventBusEl_=t[e]}else t.eventBusEl_=M("span",{className:"vjs-event-bus"});return C(t,Ht),t.on("dispose",function(){t.off(),g.setTimeout(function(){t.eventBusEl_=null},0)}),t}var qt={state:{},setState:function(t){var i=this;"function"==typeof t&&(t=t());var r=void 0;return k(t,function(t,e){i.state[e]!==t&&((r=r||{})[e]={from:i.state[e],to:t}),i.state[e]=t}),r&&Rt(this)&&this.trigger({changes:r,type:"statechanged"}),r}};function Wt(t,e){return C(t,qt),t.state=C({},t.state,e),"function"==typeof t.handleStateChanged&&Rt(t)&&t.on("statechanged",t.handleStateChanged),t}function zt(t){return"string"!=typeof t?t:t.charAt(0).toUpperCase()+t.slice(1)}function Gt(){for(var i={},t=arguments.length,e=Array(t),r=0;r<t;r++)e[r]=arguments[r];return e.forEach(function(t){t&&k(t,function(t,e){w(t)?(w(i[e])||(i[e]={}),i[e]=Gt(i[e],t)):i[e]=t})}),i}var Xt=function(){function l(t,e,i){if(y(this,l),!t&&this.play?this.player_=t=this:this.player_=t,this.options_=Gt({},this.options_),e=this.options_=Gt(this.options_,e),this.id_=e.id||e.el&&e.el.id,!this.id_){var r=t&&t.id&&t.id()||"no_player";this.id_=r+"_component_"+ut()}this.name_=e.name||null,e.el?this.el_=e.el:!1!==e.createEl&&(this.el_=this.createEl()),!1!==e.evented&&Vt(this,{eventBusKey:this.el_?"el_":null}),Wt(this,this.constructor.defaultState),this.children_=[],this.childIndex_={},!(this.childNameIndex_={})!==e.initChildren&&this.initChildren(),this.ready(i),!1!==e.reportTouchActivity&&this.enableTouchActivity()}return l.prototype.dispose=function(){if(this.trigger({type:"dispose",bubbles:!1}),this.children_)for(var t=this.children_.length-1;0<=t;t--)this.children_[t].dispose&&this.children_[t].dispose();this.children_=null,this.childIndex_=null,this.childNameIndex_=null,this.el_&&(this.el_.parentNode&&this.el_.parentNode.removeChild(this.el_),pt(this.el_),this.el_=null),this.player_=null},l.prototype.player=function(){return this.player_},l.prototype.options=function(t){return f.warn("this.options() has been deprecated and will be moved to the constructor in 6.0"),t&&(this.options_=Gt(this.options_,t)),this.options_},l.prototype.el=function(){return this.el_},l.prototype.createEl=function(t,e,i){return M(t,e,i)},l.prototype.localize=function(t,n){var e=2<arguments.length&&void 0!==arguments[2]?arguments[2]:t,i=this.player_.language&&this.player_.language(),r=this.player_.languages&&this.player_.languages(),s=r&&r[i],a=i&&i.split("-")[0],o=r&&r[a],u=e;return s&&s[t]?u=s[t]:o&&o[t]&&(u=o[t]),n&&(u=u.replace(/\{(\d+)\}/g,function(t,e){var i=n[e-1],r=i;return"undefined"==typeof i&&(r=t),r})),u},l.prototype.contentEl=function(){return this.contentEl_||this.el_},l.prototype.id=function(){return this.id_},l.prototype.name=function(){return this.name_},l.prototype.children=function(){return this.children_},l.prototype.getChildById=function(t){return this.childIndex_[t]},l.prototype.getChild=function(t){if(t)return t=zt(t),this.childNameIndex_[t]},l.prototype.addChild=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:this.children_.length,r=void 0,n=void 0;if("string"==typeof t){n=zt(t);var s=e.componentClass||n;e.name=n;var a=l.getComponent(s);if(!a)throw new Error("Component "+s+" does not exist");if("function"!=typeof a)return null;r=new a(this.player_||this,e)}else r=t;if(this.children_.splice(i,0,r),"function"==typeof r.id&&(this.childIndex_[r.id()]=r),(n=n||r.name&&zt(r.name()))&&(this.childNameIndex_[n]=r),"function"==typeof r.el&&r.el()){var o=this.contentEl().children[i]||null;this.contentEl().insertBefore(r.el(),o)}return r},l.prototype.removeChild=function(t){if("string"==typeof t&&(t=this.getChild(t)),t&&this.children_){for(var e=!1,i=this.children_.length-1;0<=i;i--)if(this.children_[i]===t){e=!0,this.children_.splice(i,1);break}if(e){this.childIndex_[t.id()]=null,this.childNameIndex_[t.name()]=null;var r=t.el();r&&r.parentNode===this.contentEl()&&this.contentEl().removeChild(t.el())}}},l.prototype.initChildren=function(){var n=this,r=this.options_.children;if(r){var s=this.options_,t=void 0,i=l.getComponent("Tech");(t=Array.isArray(r)?r:Object.keys(r)).concat(Object.keys(this.options_).filter(function(e){return!t.some(function(t){return"string"==typeof t?e===t:e===t.name})})).map(function(t){var e=void 0,i=void 0;return"string"==typeof t?i=r[e=t]||n.options_[e]||{}:(e=t.name,i=t),{name:e,opts:i}}).filter(function(t){var e=l.getComponent(t.opts.componentClass||zt(t.name));return e&&!i.isTech(e)}).forEach(function(t){var e=t.name,i=t.opts;if(void 0!==s[e]&&(i=s[e]),!1!==i){!0===i&&(i={}),i.playerOptions=n.options_.playerOptions;var r=n.addChild(e,i);r&&(n[e]=r)}})}},l.prototype.buildCSSClass=function(){return""},l.prototype.ready=function(t){var e=1<arguments.length&&void 0!==arguments[1]&&arguments[1];if(t)return this.isReady_?void(e?t.call(this):this.setTimeout(t,1)):(this.readyQueue_=this.readyQueue_||[],void this.readyQueue_.push(t))},l.prototype.triggerReady=function(){this.isReady_=!0,this.setTimeout(function(){var t=this.readyQueue_;this.readyQueue_=[],t&&0<t.length&&t.forEach(function(t){t.call(this)},this),this.trigger("ready")},1)},l.prototype.$=function(t,e){return nt(t,e||this.contentEl())},l.prototype.$$=function(t,e){return st(t,e||this.contentEl())},l.prototype.hasClass=function(t){return B(this.el_,t)},l.prototype.addClass=function(t){j(this.el_,t)},l.prototype.removeClass=function(t){F(this.el_,t)},l.prototype.toggleClass=function(t,e){H(this.el_,t,e)},l.prototype.show=function(){this.removeClass("vjs-hidden")},l.prototype.hide=function(){this.addClass("vjs-hidden")},l.prototype.lockShowing=function(){this.addClass("vjs-lock-showing")},l.prototype.unlockShowing=function(){this.removeClass("vjs-lock-showing")},l.prototype.getAttribute=function(t){return W(this.el_,t)},l.prototype.setAttribute=function(t,e){z(this.el_,t,e)},l.prototype.removeAttribute=function(t){G(this.el_,t)},l.prototype.width=function(t,e){return this.dimension("width",t,e)},l.prototype.height=function(t,e){return this.dimension("height",t,e)},l.prototype.dimensions=function(t,e){this.width(t,!0),this.height(e)},l.prototype.dimension=function(t,e,i){if(void 0!==e)return null!==e&&e==e||(e=0),-1!==(""+e).indexOf("%")||-1!==(""+e).indexOf("px")?this.el_.style[t]=e:this.el_.style[t]="auto"===e?"":e+"px",void(i||this.trigger("componentresize"));if(!this.el_)return 0;var r=this.el_.style[t],n=r.indexOf("px");return-1!==n?parseInt(r.slice(0,n),10):parseInt(this.el_["offset"+zt(t)],10)},l.prototype.currentDimension=function(t){var e=0;if("width"!==t&&"height"!==t)throw new Error("currentDimension only accepts width or height value");if("function"==typeof g.getComputedStyle){var i=g.getComputedStyle(this.el_);e=i.getPropertyValue(t)||i[t]}if(0===(e=parseFloat(e))){var r="offset"+zt(t);e=this.el_[r]}return e},l.prototype.currentDimensions=function(){return{width:this.currentDimension("width"),height:this.currentDimension("height")}},l.prototype.currentWidth=function(){return this.currentDimension("width")},l.prototype.currentHeight=function(){return this.currentDimension("height")},l.prototype.focus=function(){this.el_.focus()},l.prototype.blur=function(){this.el_.blur()},l.prototype.emitTapEvents=function(){var e=0,r=null,n=void 0;this.on("touchstart",function(t){1===t.touches.length&&(r={pageX:t.touches[0].pageX,pageY:t.touches[0].pageY},e=(new Date).getTime(),n=!0)}),this.on("touchmove",function(t){if(1<t.touches.length)n=!1;else if(r){var e=t.touches[0].pageX-r.pageX,i=t.touches[0].pageY-r.pageY;10<Math.sqrt(e*e+i*i)&&(n=!1)}});var t=function(){n=!1};this.on("touchleave",t),this.on("touchcancel",t),this.on("touchend",function(t){!(r=null)===n&&((new Date).getTime()-e<200&&(t.preventDefault(),this.trigger("tap")))})},l.prototype.enableTouchActivity=function(){if(this.player()&&this.player().reportUserActivity){var e=Ot(this.player(),this.player().reportUserActivity),i=void 0;this.on("touchstart",function(){e(),this.clearInterval(i),i=this.setInterval(e,250)});var t=function(t){e(),this.clearInterval(i)};this.on("touchmove",e),this.on("touchend",t),this.on("touchcancel",t)}},l.prototype.setTimeout=function(t,e){var i=this;t=Ot(this,t);var r=g.setTimeout(t,e),n=function(){return i.clearTimeout(r)};return n.guid="vjs-timeout-"+r,this.on("dispose",n),r},l.prototype.clearTimeout=function(t){g.clearTimeout(t);var e=function(){};return e.guid="vjs-timeout-"+t,this.off("dispose",e),t},l.prototype.setInterval=function(t,e){var i=this;t=Ot(this,t);var r=g.setInterval(t,e),n=function(){return i.clearInterval(r)};return n.guid="vjs-interval-"+r,this.on("dispose",n),r},l.prototype.clearInterval=function(t){g.clearInterval(t);var e=function(){};return e.guid="vjs-interval-"+t,this.off("dispose",e),t},l.prototype.requestAnimationFrame=function(t){var e=this;if(this.supportsRaf_){t=Ot(this,t);var i=g.requestAnimationFrame(t),r=function(){return e.cancelAnimationFrame(i)};return r.guid="vjs-raf-"+i,this.on("dispose",r),i}return this.setTimeout(t,1e3/60)},l.prototype.cancelAnimationFrame=function(t){if(this.supportsRaf_){g.cancelAnimationFrame(t);var e=function(){};return e.guid="vjs-raf-"+t,this.off("dispose",e),t}return this.clearTimeout(t)},l.registerComponent=function(t,e){if("string"!=typeof t||!t)throw new Error('Illegal component name, "'+t+'"; must be a non-empty string.');var i=l.getComponent("Tech"),r=i&&i.isTech(e),n=l===e||l.prototype.isPrototypeOf(e.prototype);if(r||!n){var s=void 0;throw s=r?"techs must be registered using Tech.registerTech()":"must be a Component subclass",new Error('Illegal component, "'+t+'"; '+s+".")}t=zt(t),l.components_||(l.components_={});var a=l.getComponent("Player");if("Player"===t&&a&&a.players){var o=a.players,u=Object.keys(o);if(o&&0<u.length&&u.map(function(t){return o[t]}).every(Boolean))throw new Error("Can not register Player component after player has been created.")}return l.components_[t]=e},l.getComponent=function(t){if(t)return t=zt(t),l.components_&&l.components_[t]?l.components_[t]:void 0},l}();Xt.prototype.supportsRaf_="function"==typeof g.requestAnimationFrame&&"function"==typeof g.cancelAnimationFrame,Xt.registerComponent("Component",Xt);var Yt,$t,Kt,Qt,Jt=g.navigator&&g.navigator.userAgent||"",Zt=/AppleWebKit\/([\d.]+)/i.exec(Jt),te=Zt?parseFloat(Zt.pop()):null,ee=/iPad/i.test(Jt),ie=/iPhone/i.test(Jt)&&!ee,re=/iPod/i.test(Jt),ne=ie||ee||re,se=(Yt=Jt.match(/OS (\d+)_/i))&&Yt[1]?Yt[1]:null,ae=/Android/i.test(Jt),oe=function(){var t=Jt.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);if(!t)return null;var e=t[1]&&parseFloat(t[1]),i=t[2]&&parseFloat(t[2]);return e&&i?parseFloat(t[1]+"."+t[2]):e||null}(),ue=ae&&oe<5&&te<537,le=/Firefox/i.test(Jt),ce=/Edge/i.test(Jt),he=!ce&&/Chrome/i.test(Jt),de=($t=Jt.match(/Chrome\/(\d+)/))&&$t[1]?parseFloat($t[1]):null,pe=(Kt=/MSIE\s(\d+)\.\d/.exec(Jt),!(Qt=Kt&&parseFloat(Kt[1]))&&/Trident\/7.0/i.test(Jt)&&/rv:11.0/.test(Jt)&&(Qt=11),Qt),fe=/Safari/i.test(Jt)&&!he&&!ae&&!ce,me=fe||ne,ge=x()&&("ontouchstart"in g||g.DocumentTouch&&g.document instanceof g.DocumentTouch),ye=Object.freeze({IS_IPAD:ee,IS_IPHONE:ie,IS_IPOD:re,IS_IOS:ne,IOS_VERSION:se,IS_ANDROID:ae,ANDROID_VERSION:oe,IS_NATIVE_ANDROID:ue,IS_FIREFOX:le,IS_EDGE:ce,IS_CHROME:he,CHROME_VERSION:de,IE_VERSION:pe,IS_SAFARI:fe,IS_ANY_SAFARI:me,TOUCH_ENABLED:ge});function ve(t,e,i,r){return function(t,e,i){if("number"!=typeof e||e<0||i<e)throw new Error("Failed to execute '"+t+"' on 'TimeRanges': The index provided ("+e+") is non-numeric or out of bounds (0-"+i+").")}(t,r,i.length-1),i[r][e]}function _e(t){return void 0===t||0===t.length?{length:0,start:function(){throw new Error("This TimeRanges object is empty")},end:function(){throw new Error("This TimeRanges object is empty")}}:{length:t.length,start:ve.bind(null,"start",0,t),end:ve.bind(null,"end",1,t)}}function be(t,e){return Array.isArray(t)?_e(t):void 0===t||void 0===e?_e():_e([[t,e]])}function Te(t,e){var i=0,r=void 0,n=void 0;if(!e)return 0;t&&t.length||(t=be(0,0));for(var s=0;s<t.length;s++)r=t.start(s),e<(n=t.end(s))&&(n=e),i+=n-r;return i/e}for(var Se={},ke=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],Ce=ke[0],Ee=void 0,we=0;we<ke.length;we++)if(ke[we][1]in p){Ee=ke[we];break}if(Ee)for(var Ae=0;Ae<Ee.length;Ae++)Se[Ce[Ae]]=Ee[Ae];function Le(t){if(t instanceof Le)return t;"number"==typeof t?this.code=t:"string"==typeof t?this.message=t:E(t)&&("number"==typeof t.code&&(this.code=t.code),C(this,t)),this.message||(this.message=Le.defaultMessages[this.code]||"")}Le.prototype.code=0,Le.prototype.message="",Le.prototype.status=null,Le.errorTypes=["MEDIA_ERR_CUSTOM","MEDIA_ERR_ABORTED","MEDIA_ERR_NETWORK","MEDIA_ERR_DECODE","MEDIA_ERR_SRC_NOT_SUPPORTED","MEDIA_ERR_ENCRYPTED"],Le.defaultMessages={1:"You aborted the media playback",2:"A network error caused the media download to fail part-way.",3:"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.",4:"The media could not be loaded, either because the server or network failed or because the format is not supported.",5:"The media is encrypted and we do not have the keys to decrypt it."};for(var Pe=0;Pe<Le.errorTypes.length;Pe++)Le[Le.errorTypes[Pe]]=Pe,Le.prototype[Le.errorTypes[Pe]]=Pe;var Oe=function(t,e){var i,r=null;try{i=JSON.parse(t,e)}catch(t){r=t}return[r,i]};function xe(t){return null!=t&&"function"==typeof t.then}function Ie(t){xe(t)&&t.then(null,function(t){})}var De=function(r){return["kind","label","language","id","inBandMetadataTrackDispatchType","mode","src"].reduce(function(t,e,i){return r[e]&&(t[e]=r[e]),t},{cues:r.cues&&Array.prototype.map.call(r.cues,function(t){return{startTime:t.startTime,endTime:t.endTime,text:t.text,id:t.id}})})},Re=function(t){var e=t.$$("track"),i=Array.prototype.map.call(e,function(t){return t.track});return Array.prototype.map.call(e,function(t){var e=De(t.track);return t.src&&(e.src=t.src),e}).concat(Array.prototype.filter.call(t.textTracks(),function(t){return-1===i.indexOf(t)}).map(De))},Me=function(t,i){return t.forEach(function(t){var e=i.addRemoteTextTrack(t).track;!t.src&&t.cues&&t.cues.forEach(function(t){return e.addCue(t)})}),i.textTracks()},Ue="vjs-modal-dialog",Ne=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.opened_=i.hasBeenOpened_=i.hasBeenFilled_=!1,i.closeable(!i.options_.uncloseable),i.content(i.options_.content),i.contentEl_=M("div",{className:Ue+"-content"},{role:"document"}),i.descEl_=M("p",{className:Ue+"-description vjs-control-text",id:i.el().getAttribute("aria-describedby")}),U(i.descEl_,i.description()),i.el_.appendChild(i.descEl_),i.el_.appendChild(i.contentEl_),i}return _(n,r),n.prototype.createEl=function(){return r.prototype.createEl.call(this,"div",{className:this.buildCSSClass(),tabIndex:-1},{"aria-describedby":this.id()+"_description","aria-hidden":"true","aria-label":this.label(),role:"dialog"})},n.prototype.dispose=function(){this.contentEl_=null,this.descEl_=null,this.previouslyActiveEl_=null,r.prototype.dispose.call(this)},n.prototype.buildCSSClass=function(){return Ue+" vjs-hidden "+r.prototype.buildCSSClass.call(this)},n.prototype.handleKeyPress=function(t){27===t.which&&this.closeable()&&this.close()},n.prototype.label=function(){return this.localize(this.options_.label||"Modal Window")},n.prototype.description=function(){var t=this.options_.description||this.localize("This is a modal window.");return this.closeable()&&(t+=" "+this.localize("This modal can be closed by pressing the Escape key or activating the close button.")),t},n.prototype.open=function(){if(!this.opened_){var t=this.player();this.trigger("beforemodalopen"),this.opened_=!0,(this.options_.fillAlways||!this.hasBeenOpened_&&!this.hasBeenFilled_)&&this.fill(),this.wasPlaying_=!t.paused(),this.options_.pauseOnOpen&&this.wasPlaying_&&t.pause(),this.closeable()&&this.on(this.el_.ownerDocument,"keydown",Ot(this,this.handleKeyPress)),this.hadControls_=t.controls(),t.controls(!1),this.show(),this.conditionalFocus_(),this.el().setAttribute("aria-hidden","false"),this.trigger("modalopen"),this.hasBeenOpened_=!0}},n.prototype.opened=function(t){return"boolean"==typeof t&&this[t?"open":"close"](),this.opened_},n.prototype.close=function(){if(this.opened_){var t=this.player();this.trigger("beforemodalclose"),this.opened_=!1,this.wasPlaying_&&this.options_.pauseOnOpen&&t.play(),this.closeable()&&this.off(this.el_.ownerDocument,"keydown",Ot(this,this.handleKeyPress)),this.hadControls_&&t.controls(!0),this.hide(),this.el().setAttribute("aria-hidden","true"),this.trigger("modalclose"),this.conditionalBlur_(),this.options_.temporary&&this.dispose()}},n.prototype.closeable=function(t){if("boolean"==typeof t){var e=this.closeable_=!!t,i=this.getChild("closeButton");if(e&&!i){var r=this.contentEl_;this.contentEl_=this.el_,i=this.addChild("closeButton",{controlText:"Close Modal Dialog"}),this.contentEl_=r,this.on(i,"close",this.close)}!e&&i&&(this.off(i,"close",this.close),this.removeChild(i),i.dispose())}return this.closeable_},n.prototype.fill=function(){this.fillWith(this.content())},n.prototype.fillWith=function(t){var e=this.contentEl(),i=e.parentNode,r=e.nextSibling;this.trigger("beforemodalfill"),this.hasBeenFilled_=!0,i.removeChild(e),this.empty(),it(e,t),this.trigger("modalfill"),r?i.insertBefore(e,r):i.appendChild(e);var n=this.getChild("closeButton");n&&i.appendChild(n.el_)},n.prototype.empty=function(){this.trigger("beforemodalempty"),Z(this.contentEl()),this.trigger("modalempty")},n.prototype.content=function(t){return"undefined"!=typeof t&&(this.content_=t),this.content_},n.prototype.conditionalFocus_=function(){var t=p.activeElement,e=this.player_.el_;this.previouslyActiveEl_=null,(e.contains(t)||e===t)&&(this.previouslyActiveEl_=t,this.focus(),this.on(p,"keydown",this.handleKeyDown))},n.prototype.conditionalBlur_=function(){this.previouslyActiveEl_&&(this.previouslyActiveEl_.focus(),this.previouslyActiveEl_=null),this.off(p,"keydown",this.handleKeyDown)},n.prototype.handleKeyDown=function(t){if(9===t.which){for(var e=this.focusableEls_(),i=this.el_.querySelector(":focus"),r=void 0,n=0;n<e.length;n++)if(i===e[n]){r=n;break}p.activeElement===this.el_&&(r=0),t.shiftKey&&0===r?(e[e.length-1].focus(),t.preventDefault()):t.shiftKey||r!==e.length-1||(e[0].focus(),t.preventDefault())}},n.prototype.focusableEls_=function(){var t=this.el_.querySelectorAll("*");return Array.prototype.filter.call(t,function(t){return(t instanceof g.HTMLAnchorElement||t instanceof g.HTMLAreaElement)&&t.hasAttribute("href")||(t instanceof g.HTMLInputElement||t instanceof g.HTMLSelectElement||t instanceof g.HTMLTextAreaElement||t instanceof g.HTMLButtonElement)&&!t.hasAttribute("disabled")||t instanceof g.HTMLIFrameElement||t instanceof g.HTMLObjectElement||t instanceof g.HTMLEmbedElement||t.hasAttribute("tabindex")&&-1!==t.getAttribute("tabindex")||t.hasAttribute("contenteditable")})},n}(Xt);Ne.prototype.options_={pauseOnOpen:!0,temporary:!0},Xt.registerComponent("ModalDialog",Ne);var Be=function(r){function n(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];y(this,n);var e=b(this,r.call(this));e.tracks_=[],Object.defineProperty(e,"length",{get:function(){return this.tracks_.length}});for(var i=0;i<t.length;i++)e.addTrack(t[i]);return e}return _(n,r),n.prototype.addTrack=function(t){var e=this.tracks_.length;""+e in this||Object.defineProperty(this,e,{get:function(){return this.tracks_[e]}}),-1===this.tracks_.indexOf(t)&&(this.tracks_.push(t),this.trigger({track:t,type:"addtrack"}))},n.prototype.removeTrack=function(t){for(var e=void 0,i=0,r=this.length;i<r;i++)if(this[i]===t){(e=this[i]).off&&e.off(),this.tracks_.splice(i,1);break}e&&this.trigger({track:e,type:"removetrack"})},n.prototype.getTrackById=function(t){for(var e=null,i=0,r=this.length;i<r;i++){var n=this[i];if(n.id===t){e=n;break}}return e},n}(Dt);for(var je in Be.prototype.allowedEvents_={change:"change",addtrack:"addtrack",removetrack:"removetrack"},Be.prototype.allowedEvents_)Be.prototype["on"+je]=null;var Fe=function(t,e){for(var i=0;i<t.length;i++)Object.keys(t[i]).length&&e.id!==t[i].id&&(t[i].enabled=!1)},He=function(r){function n(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];y(this,n);for(var e=t.length-1;0<=e;e--)if(t[e].enabled){Fe(t,t[e]);break}var i=b(this,r.call(this,t));return i.changing_=!1,i}return _(n,r),n.prototype.addTrack=function(t){var e=this;t.enabled&&Fe(this,t),r.prototype.addTrack.call(this,t),t.addEventListener&&t.addEventListener("enabledchange",function(){e.changing_||(e.changing_=!0,Fe(e,t),e.changing_=!1,e.trigger("change"))})},n}(Be),Ve=function(t,e){for(var i=0;i<t.length;i++)Object.keys(t[i]).length&&e.id!==t[i].id&&(t[i].selected=!1)},qe=function(r){function n(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];y(this,n);for(var e=t.length-1;0<=e;e--)if(t[e].selected){Ve(t,t[e]);break}var i=b(this,r.call(this,t));return i.changing_=!1,Object.defineProperty(i,"selectedIndex",{get:function(){for(var t=0;t<this.length;t++)if(this[t].selected)return t;return-1},set:function(){}}),i}return _(n,r),n.prototype.addTrack=function(t){var e=this;t.selected&&Ve(this,t),r.prototype.addTrack.call(this,t),t.addEventListener&&t.addEventListener("selectedchange",function(){e.changing_||(e.changing_=!0,Ve(e,t),e.changing_=!1,e.trigger("change"))})},n}(Be),We=function(e){function t(){return y(this,t),b(this,e.apply(this,arguments))}return _(t,e),t.prototype.addTrack=function(t){e.prototype.addTrack.call(this,t),t.addEventListener("modechange",Ot(this,function(){this.trigger("change")}));-1===["metadata","chapters"].indexOf(t.kind)&&t.addEventListener("modechange",Ot(this,function(){this.trigger("selectedlanguagechange")}))},t}(Be),ze=function(){function r(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];y(this,r),this.trackElements_=[],Object.defineProperty(this,"length",{get:function(){return this.trackElements_.length}});for(var e=0,i=t.length;e<i;e++)this.addTrackElement_(t[e])}return r.prototype.addTrackElement_=function(t){var e=this.trackElements_.length;""+e in this||Object.defineProperty(this,e,{get:function(){return this.trackElements_[e]}}),-1===this.trackElements_.indexOf(t)&&this.trackElements_.push(t)},r.prototype.getTrackElementByTrack_=function(t){for(var e=void 0,i=0,r=this.trackElements_.length;i<r;i++)if(t===this.trackElements_[i].track){e=this.trackElements_[i];break}return e},r.prototype.removeTrackElement_=function(t){for(var e=0,i=this.trackElements_.length;e<i;e++)if(t===this.trackElements_[e]){this.trackElements_.splice(e,1);break}},r}(),Ge=function(){function e(t){y(this,e),e.prototype.setCues_.call(this,t),Object.defineProperty(this,"length",{get:function(){return this.length_}})}return e.prototype.setCues_=function(t){var e=this.length||0,i=0,r=t.length;this.cues_=t,this.length_=t.length;var n=function(t){""+t in this||Object.defineProperty(this,""+t,{get:function(){return this.cues_[t]}})};if(e<r)for(i=e;i<r;i++)n.call(this,i)},e.prototype.getCueById=function(t){for(var e=null,i=0,r=this.length;i<r;i++){var n=this[i];if(n.id===t){e=n;break}}return e},e}(),Xe={alternative:"alternative",captions:"captions",main:"main",sign:"sign",subtitles:"subtitles",commentary:"commentary"},Ye={alternative:"alternative",descriptions:"descriptions",main:"main","main-desc":"main-desc",translation:"translation",commentary:"commentary"},$e={subtitles:"subtitles",captions:"captions",descriptions:"descriptions",chapters:"chapters",metadata:"metadata"},Ke={disabled:"disabled",hidden:"hidden",showing:"showing"},Qe=function(s){function a(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};y(this,a);var e=b(this,s.call(this)),i={id:t.id||"vjs_track_"+ut(),kind:t.kind||"",label:t.label||"",language:t.language||""},r=function(t){Object.defineProperty(e,t,{get:function(){return i[t]},set:function(){}})};for(var n in i)r(n);return e}return _(a,s),a}(Dt),Je=function(t){var e=["protocol","hostname","port","pathname","search","hash","host"],i=p.createElement("a");i.href=t;var r=""===i.host&&"file:"!==i.protocol,n=void 0;r&&((n=p.createElement("div")).innerHTML='<a href="'+t+'"></a>',i=n.firstChild,n.setAttribute("style","display:none; position:absolute;"),p.body.appendChild(n));for(var s={},a=0;a<e.length;a++)s[e[a]]=i[e[a]];return"http:"===s.protocol&&(s.host=s.host.replace(/:80$/,"")),"https:"===s.protocol&&(s.host=s.host.replace(/:443$/,"")),s.protocol||(s.protocol=g.location.protocol),r&&p.body.removeChild(n),s},Ze=function(t){if(!t.match(/^https?:\/\//)){var e=p.createElement("div");e.innerHTML='<a href="'+t+'">x</a>',t=e.firstChild.href}return t},ti=function(t){if("string"==typeof t){var e=/^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i.exec(t);if(e)return e.pop().toLowerCase()}return""},ei=function(t){var e=g.location,i=Je(t);return(":"===i.protocol?e.protocol:i.protocol)+i.host!==e.protocol+e.host},ii=Object.freeze({parseUrl:Je,getAbsoluteURL:Ze,getFileExtension:ti,isCrossOrigin:ei}),ri=function(t){var e=ni.call(t);return"[object Function]"===e||"function"==typeof t&&"[object RegExp]"!==e||"undefined"!=typeof window&&(t===window.setTimeout||t===window.alert||t===window.confirm||t===window.prompt)},ni=Object.prototype.toString;var si=Object.freeze({default:ri,__moduleExports:ri}),ai=e(function(t,e){(e=t.exports=function(t){return t.replace(/^\s*|\s*$/g,"")}).left=function(t){return t.replace(/^\s*/,"")},e.right=function(t){return t.replace(/\s*$/,"")}}),oi=ai.left,ui=ai.right,li=Object.freeze({default:ai,__moduleExports:ai,left:oi,right:ui}),ci=si&&ri||si,hi=function(t,e,i){if(!ci(e))throw new TypeError("iterator must be a function");arguments.length<3&&(i=this);"[object Array]"===di.call(t)?function(t,e,i){for(var r=0,n=t.length;r<n;r++)pi.call(t,r)&&e.call(i,t[r],r,t)}(t,e,i):"string"==typeof t?function(t,e,i){for(var r=0,n=t.length;r<n;r++)e.call(i,t.charAt(r),r,t)}(t,e,i):function(t,e,i){for(var r in t)pi.call(t,r)&&e.call(i,t[r],r,t)}(t,e,i)},di=Object.prototype.toString,pi=Object.prototype.hasOwnProperty;var fi=Object.freeze({default:hi,__moduleExports:hi}),mi=li&&ai||li,gi=fi&&hi||fi,yi=function(t){if(!t)return{};var s={};return gi(mi(t).split("\n"),function(t){var e,i=t.indexOf(":"),r=mi(t.slice(0,i)).toLowerCase(),n=mi(t.slice(i+1));"undefined"==typeof s[r]?s[r]=n:(e=s[r],"[object Array]"===Object.prototype.toString.call(e)?s[r].push(n):s[r]=[s[r],n])}),s},vi=Object.freeze({default:yi,__moduleExports:yi}),_i=function(){for(var t={},e=0;e<arguments.length;e++){var i=arguments[e];for(var r in i)bi.call(i,r)&&(t[r]=i[r])}return t},bi=Object.prototype.hasOwnProperty;var Ti=Object.freeze({default:_i,__moduleExports:_i}),Si=vi&&yi||vi,ki=Ti&&_i||Ti,Ci=wi;function Ei(t,e,i){var r=t;return ci(e)?(i=e,"string"==typeof t&&(r={uri:t})):r=ki(e,{uri:t}),r.callback=i,r}function wi(t,e,i){return Ai(e=Ei(t,e,i))}function Ai(r){if("undefined"==typeof r.callback)throw new Error("callback argument missing");var n=!1,s=function(t,e,i){n||(n=!0,r.callback(t,e,i))};function e(t){return clearTimeout(u),t instanceof Error||(t=new Error(""+(t||"Unknown XMLHttpRequest Error"))),t.statusCode=0,s(t,m)}function t(){if(!a){var t;clearTimeout(u),t=r.useXDR&&void 0===o.status?200:1223===o.status?204:o.status;var e=m,i=null;return 0!==t?(e={body:function(){var t=void 0;if(t=o.response?o.response:o.responseText||function(t){if("document"===t.responseType)return t.responseXML;var e=t.responseXML&&"parsererror"===t.responseXML.documentElement.nodeName;return""!==t.responseType||e?null:t.responseXML}(o),f)try{t=JSON.parse(t)}catch(t){}return t}(),statusCode:t,method:c,headers:{},url:l,rawRequest:o},o.getAllResponseHeaders&&(e.headers=Si(o.getAllResponseHeaders()))):i=new Error("Internal XMLHttpRequest Error"),s(i,e,e.body)}}var i,a,o=r.xhr||null;o||(o=r.cors||r.useXDR?new wi.XDomainRequest:new wi.XMLHttpRequest);var u,l=o.url=r.uri||r.url,c=o.method=r.method||"GET",h=r.body||r.data,d=o.headers=r.headers||{},p=!!r.sync,f=!1,m={body:void 0,headers:{},statusCode:0,method:c,url:l,rawRequest:o};if("json"in r&&!1!==r.json&&(f=!0,d.accept||d.Accept||(d.Accept="application/json"),"GET"!==c&&"HEAD"!==c&&(d["content-type"]||d["Content-Type"]||(d["Content-Type"]="application/json"),h=JSON.stringify(!0===r.json?h:r.json))),o.onreadystatechange=function(){4===o.readyState&&setTimeout(t,0)},o.onload=t,o.onerror=e,o.onprogress=function(){},o.onabort=function(){a=!0},o.ontimeout=e,o.open(c,l,!p,r.username,r.password),p||(o.withCredentials=!!r.withCredentials),!p&&0<r.timeout&&(u=setTimeout(function(){if(!a){a=!0,o.abort("timeout");var t=new Error("XMLHttpRequest timeout");t.code="ETIMEDOUT",e(t)}},r.timeout)),o.setRequestHeader)for(i in d)d.hasOwnProperty(i)&&o.setRequestHeader(i,d[i]);else if(r.headers&&!function(t){for(var e in t)if(t.hasOwnProperty(e))return!1;return!0}(r.headers))throw new Error("Headers cannot be set on an XDomainRequest object");return"responseType"in r&&(o.responseType=r.responseType),"beforeSend"in r&&"function"==typeof r.beforeSend&&r.beforeSend(o),o.send(h||null),o}wi.XMLHttpRequest=g.XMLHttpRequest||function(){},wi.XDomainRequest="withCredentials"in new wi.XMLHttpRequest?wi.XMLHttpRequest:g.XDomainRequest,function(t,e){for(var i=0;i<t.length;i++)e(t[i])}(["get","put","post","patch","head","delete"],function(r){wi["delete"===r?"del":r]=function(t,e,i){return(e=Ei(t,e,i)).method=r.toUpperCase(),Ai(e)}});var Li=function(t,e){var i=new g.WebVTT.Parser(g,g.vttjs,g.WebVTT.StringDecoder()),r=[];i.oncue=function(t){e.addCue(t)},i.onparsingerror=function(t){r.push(t)},i.onflush=function(){e.trigger({type:"loadeddata",target:e})},i.parse(t),0<r.length&&(g.console&&g.console.groupCollapsed&&g.console.groupCollapsed("Text Track parsing errors for "+e.src),r.forEach(function(t){return f.error(t)}),g.console&&g.console.groupEnd&&g.console.groupEnd()),i.flush()},Pi=function(t,n){var e={uri:t},i=ei(t);i&&(e.cors=i),Ci(e,Ot(this,function(t,e,i){if(t)return f.error(t,e);if(n.loaded_=!0,"function"!=typeof g.WebVTT){if(n.tech_){var r=function(){return Li(i,n)};n.tech_.on("vttjsloaded",r),n.tech_.on("vttjserror",function(){f.error("vttjs failed to load, stopping trying to process "+n.src),n.tech_.off("vttjsloaded",r)})}}else Li(i,n)}))},Oi=function(l){function c(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};if(y(this,c),!t.tech)throw new Error("A tech was not provided.");var e=Gt(t,{kind:$e[t.kind]||"subtitles",language:t.language||t.srclang||""}),i=Ke[e.mode]||"disabled",r=e.default;"metadata"!==e.kind&&"chapters"!==e.kind||(i="hidden");var n=b(this,l.call(this,e));n.tech_=e.tech,n.cues_=[],n.activeCues_=[];var s=new Ge(n.cues_),a=new Ge(n.activeCues_),o=!1,u=Ot(n,function(){this.activeCues,o&&(this.trigger("cuechange"),o=!1)});return"disabled"!==i&&n.tech_.ready(function(){n.tech_.on("timeupdate",u)},!0),Object.defineProperties(n,{default:{get:function(){return r},set:function(){}},mode:{get:function(){return i},set:function(t){var e=this;Ke[t]&&("showing"===(i=t)&&this.tech_.ready(function(){e.tech_.on("timeupdate",u)},!0),this.trigger("modechange"))}},cues:{get:function(){return this.loaded_?s:null},set:function(){}},activeCues:{get:function(){if(!this.loaded_)return null;if(0===this.cues.length)return a;for(var t=this.tech_.currentTime(),e=[],i=0,r=this.cues.length;i<r;i++){var n=this.cues[i];n.startTime<=t&&n.endTime>=t?e.push(n):n.startTime===n.endTime&&n.startTime<=t&&n.startTime+.5>=t&&e.push(n)}if(o=!1,e.length!==this.activeCues_.length)o=!0;else for(var s=0;s<e.length;s++)-1===this.activeCues_.indexOf(e[s])&&(o=!0);return this.activeCues_=e,a.setCues_(this.activeCues_),a},set:function(){}}}),e.src?(n.src=e.src,Pi(e.src,n)):n.loaded_=!0,n}return _(c,l),c.prototype.addCue=function(t){var e=t;if(g.vttjs&&!(t instanceof g.vttjs.VTTCue)){for(var i in e=new g.vttjs.VTTCue(t.startTime,t.endTime,t.text),t)i in e||(e[i]=t[i]);e.id=t.id,e.originalCue_=t}for(var r=this.tech_.textTracks(),n=0;n<r.length;n++)r[n]!==this&&r[n].removeCue(e);this.cues_.push(e),this.cues.setCues_(this.cues_)},c.prototype.removeCue=function(t){for(var e=this.cues_.length;e--;){var i=this.cues_[e];if(i===t||i.originalCue_&&i.originalCue_===t){this.cues_.splice(e,1),this.cues.setCues_(this.cues_);break}}},c}(Qe);Oi.prototype.allowedEvents_={cuechange:"cuechange"};var xi=function(n){function s(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};y(this,s);var e=Gt(t,{kind:Ye[t.kind]||""}),i=b(this,n.call(this,e)),r=!1;return Object.defineProperty(i,"enabled",{get:function(){return r},set:function(t){"boolean"==typeof t&&t!==r&&(r=t,this.trigger("enabledchange"))}}),e.enabled&&(i.enabled=e.enabled),i.loaded_=!0,i}return _(s,n),s}(Qe),Ii=function(n){function s(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};y(this,s);var e=Gt(t,{kind:Xe[t.kind]||""}),i=b(this,n.call(this,e)),r=!1;return Object.defineProperty(i,"selected",{get:function(){return r},set:function(t){"boolean"==typeof t&&t!==r&&(r=t,this.trigger("selectedchange"))}}),e.selected&&(i.selected=e.selected),i}return _(s,n),s}(Qe),Di=0,Ri=2,Mi=function(n){function s(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};y(this,s);var e=b(this,n.call(this)),i=void 0,r=new Oi(t);return e.kind=r.kind,e.src=r.src,e.srclang=r.language,e.label=r.label,e.default=r.default,Object.defineProperties(e,{readyState:{get:function(){return i}},track:{get:function(){return r}}}),i=Di,r.addEventListener("loadeddata",function(){i=Ri,e.trigger({type:"load",target:e})}),e}return _(s,n),s}(Dt);Mi.prototype.allowedEvents_={load:"load"},Mi.NONE=Di,Mi.LOADING=1,Mi.LOADED=Ri,Mi.ERROR=3;var Ui={audio:{ListClass:He,TrackClass:xi,capitalName:"Audio"},video:{ListClass:qe,TrackClass:Ii,capitalName:"Video"},text:{ListClass:We,TrackClass:Oi,capitalName:"Text"}};Object.keys(Ui).forEach(function(t){Ui[t].getterName=t+"Tracks",Ui[t].privateName=t+"Tracks_"});var Ni={remoteText:{ListClass:We,TrackClass:Oi,capitalName:"RemoteText",getterName:"remoteTextTracks",privateName:"remoteTextTracks_"},remoteTextEl:{ListClass:ze,TrackClass:Mi,capitalName:"RemoteTextTrackEls",getterName:"remoteTextTrackEls",privateName:"remoteTextTrackEls_"}},Bi=Gt(Ui,Ni);Ni.names=Object.keys(Ni),Ui.names=Object.keys(Ui),Bi.names=[].concat(Ni.names).concat(Ui.names);var ji=Object.create||function(){function e(){}return function(t){if(1!==arguments.length)throw new Error("Object.create shim only accepts one parameter.");return e.prototype=t,new e}}();function Fi(t,e){this.name="ParsingError",this.code=t.code,this.message=e||t.message}function Hi(t){function e(t,e,i,r){return 3600*(0|t)+60*(0|e)+(0|i)+(0|r)/1e3}var i=t.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);return i?i[3]?e(i[1],i[2],i[3].replace(":",""),i[4]):59<i[1]?e(i[1],i[2],0,i[4]):e(0,i[1],i[2],i[4]):null}function Vi(){this.values=ji(null)}function qi(t,e,i,r){var n=r?t.split(r):[t];for(var s in n)if("string"==typeof n[s]){var a=n[s].split(i);if(2===a.length)e(a[0],a[1])}}function Wi(e,t,s){var i,r,a,n=e;function o(){var t=Hi(e);if(null===t)throw new Fi(Fi.Errors.BadTimeStamp,"Malformed timestamp: "+n);return e=e.replace(/^[^\sa-zA-Z-]+/,""),t}function u(){e=e.replace(/^\s+/,"")}if(u(),t.startTime=o(),u(),"--\x3e"!==e.substr(0,3))throw new Fi(Fi.Errors.BadTimeStamp,"Malformed time stamp (time stamps must be separated by '--\x3e'): "+n);e=e.substr(3),u(),t.endTime=o(),u(),i=e,r=t,a=new Vi,qi(i,function(t,e){switch(t){case"region":for(var i=s.length-1;0<=i;i--)if(s[i].id===e){a.set(t,s[i].region);break}break;case"vertical":a.alt(t,e,["rl","lr"]);break;case"line":var r=e.split(","),n=r[0];a.integer(t,n),a.percent(t,n)&&a.set("snapToLines",!1),a.alt(t,n,["auto"]),2===r.length&&a.alt("lineAlign",r[1],["start","middle","end"]);break;case"position":r=e.split(","),a.percent(t,r[0]),2===r.length&&a.alt("positionAlign",r[1],["start","middle","end"]);break;case"size":a.percent(t,e);break;case"align":a.alt(t,e,["start","middle","end","left","right"])}},/:/,/\s/),r.region=a.get("region",null),r.vertical=a.get("vertical",""),r.line=a.get("line","auto"),r.lineAlign=a.get("lineAlign","start"),r.snapToLines=a.get("snapToLines",!0),r.size=a.get("size",100),r.align=a.get("align","middle"),r.position=a.get("position",{start:0,left:0,middle:50,end:100,right:100},r.align),r.positionAlign=a.get("positionAlign",{start:"start",left:"start",middle:"middle",end:"end",right:"end"},r.align)}((Fi.prototype=ji(Error.prototype)).constructor=Fi).Errors={BadSignature:{code:0,message:"Malformed WebVTT signature."},BadTimeStamp:{code:1,message:"Malformed time stamp."}},Vi.prototype={set:function(t,e){this.get(t)||""===e||(this.values[t]=e)},get:function(t,e,i){return i?this.has(t)?this.values[t]:e[i]:this.has(t)?this.values[t]:e},has:function(t){return t in this.values},alt:function(t,e,i){for(var r=0;r<i.length;++r)if(e===i[r]){this.set(t,e);break}},integer:function(t,e){/^-?\d+$/.test(e)&&this.set(t,parseInt(e,10))},percent:function(t,e){return!!(e.match(/^([\d]{1,3})(\.[\d]*)?%$/)&&0<=(e=parseFloat(e))&&e<=100)&&(this.set(t,e),!0)}};var zi={"&":"&","<":"<",">":">","‎":"‎","‏":"â€"," ":" "},Gi={c:"span",i:"i",b:"b",u:"u",ruby:"ruby",rt:"rt",v:"span",lang:"span"},Xi={v:"title",lang:"lang"},Yi={rt:"ruby"};function $i(s,i){function t(){if(!i)return null;var t,e=i.match(/^([^<]*)(<[^>]*>?)?/);return t=e[1]?e[1]:e[2],i=i.substr(t.length),t}function e(t){return zi[t]}function r(t){for(;f=t.match(/&(amp|lt|gt|lrm|rlm|nbsp);/);)t=t.replace(f[0],e);return t}function n(t,e){var i=Gi[t];if(!i)return null;var r=s.document.createElement(i);r.localName=i;var n=Xi[t];return n&&e&&(r[n]=e.trim()),r}for(var a,o,u,l=s.document.createElement("div"),c=l,h=[];null!==(a=t());)if("<"!==a[0])c.appendChild(s.document.createTextNode(r(a)));else{if("/"===a[1]){h.length&&h[h.length-1]===a.substr(2).replace(">","")&&(h.pop(),c=c.parentNode);continue}var d,p=Hi(a.substr(1,a.length-2));if(p){d=s.document.createProcessingInstruction("timestamp",p),c.appendChild(d);continue}var f=a.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/);if(!f)continue;if(!(d=n(f[1],f[3])))continue;if(o=c,Yi[(u=d).localName]&&Yi[u.localName]!==o.localName)continue;f[2]&&(d.className=f[2].substr(1).replace("."," ")),h.push(f[1]),c.appendChild(d),c=d}return l}var Ki=[[1470,1470],[1472,1472],[1475,1475],[1478,1478],[1488,1514],[1520,1524],[1544,1544],[1547,1547],[1549,1549],[1563,1563],[1566,1610],[1645,1647],[1649,1749],[1765,1766],[1774,1775],[1786,1805],[1807,1808],[1810,1839],[1869,1957],[1969,1969],[1984,2026],[2036,2037],[2042,2042],[2048,2069],[2074,2074],[2084,2084],[2088,2088],[2096,2110],[2112,2136],[2142,2142],[2208,2208],[2210,2220],[8207,8207],[64285,64285],[64287,64296],[64298,64310],[64312,64316],[64318,64318],[64320,64321],[64323,64324],[64326,64449],[64467,64829],[64848,64911],[64914,64967],[65008,65020],[65136,65140],[65142,65276],[67584,67589],[67592,67592],[67594,67637],[67639,67640],[67644,67644],[67647,67669],[67671,67679],[67840,67867],[67872,67897],[67903,67903],[67968,68023],[68030,68031],[68096,68096],[68112,68115],[68117,68119],[68121,68147],[68160,68167],[68176,68184],[68192,68223],[68352,68405],[68416,68437],[68440,68466],[68472,68479],[68608,68680],[126464,126467],[126469,126495],[126497,126498],[126500,126500],[126503,126503],[126505,126514],[126516,126519],[126521,126521],[126523,126523],[126530,126530],[126535,126535],[126537,126537],[126539,126539],[126541,126543],[126545,126546],[126548,126548],[126551,126551],[126553,126553],[126555,126555],[126557,126557],[126559,126559],[126561,126562],[126564,126564],[126567,126570],[126572,126578],[126580,126583],[126585,126588],[126590,126590],[126592,126601],[126603,126619],[126625,126627],[126629,126633],[126635,126651],[1114109,1114109]];function Qi(t){for(var e=0;e<Ki.length;e++){var i=Ki[e];if(t>=i[0]&&t<=i[1])return!0}return!1}function Ji(){}function Zi(t,e,i){Ji.call(this),this.cue=e,this.cueDiv=$i(t,e.text);var r={color:"rgba(255, 255, 255, 1)",backgroundColor:"rgba(0, 0, 0, 0.8)",position:"relative",left:0,right:0,top:0,bottom:0,display:"inline",writingMode:""===e.vertical?"horizontal-tb":"lr"===e.vertical?"vertical-lr":"vertical-rl",unicodeBidi:"plaintext"};this.applyStyles(r,this.cueDiv),this.div=t.document.createElement("div"),r={direction:function(t){var e=[],i="";if(!t||!t.childNodes)return"ltr";function n(t,e){for(var i=e.childNodes.length-1;0<=i;i--)t.push(e.childNodes[i])}function s(t){if(!t||!t.length)return null;var e=t.pop(),i=e.textContent||e.innerText;if(i){var r=i.match(/^.*(\n|\r)/);return r?r[t.length=0]:i}return"ruby"===e.tagName?s(t):e.childNodes?(n(t,e),s(t)):void 0}for(n(e,t);i=s(e);)for(var r=0;r<i.length;r++)if(Qi(i.charCodeAt(r)))return"rtl";return"ltr"}(this.cueDiv),writingMode:""===e.vertical?"horizontal-tb":"lr"===e.vertical?"vertical-lr":"vertical-rl",unicodeBidi:"plaintext",textAlign:"middle"===e.align?"center":e.align,font:i.font,whiteSpace:"pre-line",position:"absolute"},this.applyStyles(r),this.div.appendChild(this.cueDiv);var n=0;switch(e.positionAlign){case"start":n=e.position;break;case"middle":n=e.position-e.size/2;break;case"end":n=e.position-e.size}""===e.vertical?this.applyStyles({left:this.formatStyle(n,"%"),width:this.formatStyle(e.size,"%")}):this.applyStyles({top:this.formatStyle(n,"%"),height:this.formatStyle(e.size,"%")}),this.move=function(t){this.applyStyles({top:this.formatStyle(t.top,"px"),bottom:this.formatStyle(t.bottom,"px"),left:this.formatStyle(t.left,"px"),right:this.formatStyle(t.right,"px"),height:this.formatStyle(t.height,"px"),width:this.formatStyle(t.width,"px")})}}function tr(t){var e,i,r,n;if(t.div){i=t.div.offsetHeight,r=t.div.offsetWidth,n=t.div.offsetTop;var s=(s=t.div.childNodes)&&(s=s[0])&&s.getClientRects&&s.getClientRects();t=t.div.getBoundingClientRect(),e=s?Math.max(s[0]&&s[0].height||0,t.height/s.length):0}this.left=t.left,this.right=t.right,this.top=t.top||n,this.height=t.height||i,this.bottom=t.bottom||n+(t.height||i),this.width=t.width||r,this.lineHeight=void 0!==e?e:t.lineHeight}function er(t,e,o,u){var i=new tr(e),r=e.cue,n=function(t){if("number"==typeof t.line&&(t.snapToLines||0<=t.line&&t.line<=100))return t.line;if(!t.track||!t.track.textTrackList||!t.track.textTrackList.mediaElement)return-1;for(var e=t.track,i=e.textTrackList,r=0,n=0;n<i.length&&i[n]!==e;n++)"showing"===i[n].mode&&r++;return-1*++r}(r),s=[];if(r.snapToLines){var a;switch(r.vertical){case"":s=["+y","-y"],a="height";break;case"rl":s=["+x","-x"],a="width";break;case"lr":s=["-x","+x"],a="width"}var l=i.lineHeight,c=l*Math.round(n),h=o[a]+l,d=s[0];Math.abs(c)>h&&(c=c<0?-1:1,c*=Math.ceil(h/l)*l),n<0&&(c+=""===r.vertical?o.height:o.width,s=s.reverse()),i.move(d,c)}else{var p=i.lineHeight/o.height*100;switch(r.lineAlign){case"middle":n-=p/2;break;case"end":n-=p}switch(r.vertical){case"":e.applyStyles({top:e.formatStyle(n,"%")});break;case"rl":e.applyStyles({left:e.formatStyle(n,"%")});break;case"lr":e.applyStyles({right:e.formatStyle(n,"%")})}s=["+y","-x","+x","-y"],i=new tr(e)}var f=function(t,e){for(var i,r=new tr(t),n=1,s=0;s<e.length;s++){for(;t.overlapsOppositeAxis(o,e[s])||t.within(o)&&t.overlapsAny(u);)t.move(e[s]);if(t.within(o))return t;var a=t.intersectPercentage(o);a<n&&(i=new tr(t),n=a),t=new tr(r)}return i||r}(i,s);e.move(f.toCSSCompatValues(o))}function ir(){}Ji.prototype.applyStyles=function(t,e){for(var i in e=e||this.div,t)t.hasOwnProperty(i)&&(e.style[i]=t[i])},Ji.prototype.formatStyle=function(t,e){return 0===t?0:t+e},(Zi.prototype=ji(Ji.prototype)).constructor=Zi,tr.prototype.move=function(t,e){switch(e=void 0!==e?e:this.lineHeight,t){case"+x":this.left+=e,this.right+=e;break;case"-x":this.left-=e,this.right-=e;break;case"+y":this.top+=e,this.bottom+=e;break;case"-y":this.top-=e,this.bottom-=e}},tr.prototype.overlaps=function(t){return this.left<t.right&&this.right>t.left&&this.top<t.bottom&&this.bottom>t.top},tr.prototype.overlapsAny=function(t){for(var e=0;e<t.length;e++)if(this.overlaps(t[e]))return!0;return!1},tr.prototype.within=function(t){return this.top>=t.top&&this.bottom<=t.bottom&&this.left>=t.left&&this.right<=t.right},tr.prototype.overlapsOppositeAxis=function(t,e){switch(e){case"+x":return this.left<t.left;case"-x":return this.right>t.right;case"+y":return this.top<t.top;case"-y":return this.bottom>t.bottom}},tr.prototype.intersectPercentage=function(t){return Math.max(0,Math.min(this.right,t.right)-Math.max(this.left,t.left))*Math.max(0,Math.min(this.bottom,t.bottom)-Math.max(this.top,t.top))/(this.height*this.width)},tr.prototype.toCSSCompatValues=function(t){return{top:this.top-t.top,bottom:t.bottom-this.bottom,left:this.left-t.left,right:t.right-this.right,height:this.height,width:this.width}},tr.getSimpleBoxPosition=function(t){var e=t.div?t.div.offsetHeight:t.tagName?t.offsetHeight:0,i=t.div?t.div.offsetWidth:t.tagName?t.offsetWidth:0,r=t.div?t.div.offsetTop:t.tagName?t.offsetTop:0;return{left:(t=t.div?t.div.getBoundingClientRect():t.tagName?t.getBoundingClientRect():t).left,right:t.right,top:t.top||r,height:t.height||e,bottom:t.bottom||r+(t.height||e),width:t.width||i}},ir.StringDecoder=function(){return{decode:function(t){if(!t)return"";if("string"!=typeof t)throw new Error("Error - expected string data.");return decodeURIComponent(encodeURIComponent(t))}}},ir.convertCueToDOMTree=function(t,e){return t&&e?$i(t,e):null};ir.processCues=function(r,n,t){if(!r||!n||!t)return null;for(;t.firstChild;)t.removeChild(t.firstChild);var s=r.document.createElement("div");if(s.style.position="absolute",s.style.left="0",s.style.right="0",s.style.top="0",s.style.bottom="0",s.style.margin="1.5%",t.appendChild(s),function(t){for(var e=0;e<t.length;e++)if(t[e].hasBeenReset||!t[e].displayState)return!0;return!1}(n)){var a=[],o=tr.getSimpleBoxPosition(s),u={font:Math.round(.05*o.height*100)/100+"px sans-serif"};!function(){for(var t,e,i=0;i<n.length;i++)e=n[i],t=new Zi(r,e,u),s.appendChild(t.div),er(0,t,o,a),e.displayState=t.div,a.push(tr.getSimpleBoxPosition(t))}()}else for(var e=0;e<n.length;e++)s.appendChild(n[e].displayState)},(ir.Parser=function(t,e,i){i||(i=e,e={}),e||(e={}),this.window=t,this.vttjs=e,this.state="INITIAL",this.buffer="",this.decoder=i||new TextDecoder("utf8"),this.regionList=[]}).prototype={reportOrThrowError:function(t){if(!(t instanceof Fi))throw t;this.onparsingerror&&this.onparsingerror(t)},parse:function(t){var s=this;function e(){for(var t=s.buffer,e=0;e<t.length&&"\r"!==t[e]&&"\n"!==t[e];)++e;var i=t.substr(0,e);return"\r"===t[e]&&++e,"\n"===t[e]&&++e,s.buffer=t.substr(e),i}function i(t){t.match(/X-TIMESTAMP-MAP/)?qi(t,function(t,e){switch(t){case"X-TIMESTAMP-MAP":i=e,r=new Vi,qi(i,function(t,e){switch(t){case"MPEGT":r.integer(t+"S",e);break;case"LOCA":r.set(t+"L",Hi(e))}},/[^\d]:/,/,/),s.ontimestampmap&&s.ontimestampmap({MPEGTS:r.get("MPEGTS"),LOCAL:r.get("LOCAL")})}var i,r},/=/):qi(t,function(t,e){switch(t){case"Region":!function(t){var n=new Vi;if(qi(t,function(t,e){switch(t){case"id":n.set(t,e);break;case"width":n.percent(t,e);break;case"lines":n.integer(t,e);break;case"regionanchor":case"viewportanchor":var i=e.split(",");if(2!==i.length)break;var r=new Vi;if(r.percent("x",i[0]),r.percent("y",i[1]),!r.has("x")||!r.has("y"))break;n.set(t+"X",r.get("x")),n.set(t+"Y",r.get("y"));break;case"scroll":n.alt(t,e,["up"])}},/=/,/\s/),n.has("id")){var e=new(s.vttjs.VTTRegion||s.window.VTTRegion);e.width=n.get("width",100),e.lines=n.get("lines",3),e.regionAnchorX=n.get("regionanchorX",0),e.regionAnchorY=n.get("regionanchorY",100),e.viewportAnchorX=n.get("viewportanchorX",0),e.viewportAnchorY=n.get("viewportanchorY",100),e.scroll=n.get("scroll",""),s.onregion&&s.onregion(e),s.regionList.push({id:n.get("id"),region:e})}}(e)}},/:/)}t&&(s.buffer+=s.decoder.decode(t,{stream:!0}));try{var r;if("INITIAL"===s.state){if(!/\r\n|\n/.test(s.buffer))return this;var n=(r=e()).match(/^WEBVTT([ \t].*)?$/);if(!n||!n[0])throw new Fi(Fi.Errors.BadSignature);s.state="HEADER"}for(var a=!1;s.buffer;){if(!/\r\n|\n/.test(s.buffer))return this;switch(a?a=!1:r=e(),s.state){case"HEADER":/:/.test(r)?i(r):r||(s.state="ID");continue;case"NOTE":r||(s.state="ID");continue;case"ID":if(/^NOTE($|[ \t])/.test(r)){s.state="NOTE";break}if(!r)continue;if(s.cue=new(s.vttjs.VTTCue||s.window.VTTCue)(0,0,""),s.state="CUE",-1===r.indexOf("--\x3e")){s.cue.id=r;continue}case"CUE":try{Wi(r,s.cue,s.regionList)}catch(t){s.reportOrThrowError(t),s.cue=null,s.state="BADCUE";continue}s.state="CUETEXT";continue;case"CUETEXT":var o=-1!==r.indexOf("--\x3e");if(!r||o&&(a=!0)){s.oncue&&s.oncue(s.cue),s.cue=null,s.state="ID";continue}s.cue.text&&(s.cue.text+="\n"),s.cue.text+=r;continue;case"BADCUE":r||(s.state="ID");continue}}}catch(t){s.reportOrThrowError(t),"CUETEXT"===s.state&&s.cue&&s.oncue&&s.oncue(s.cue),s.cue=null,s.state="INITIAL"===s.state?"BADWEBVTT":"BADCUE"}return this},flush:function(){var e=this;try{if(e.buffer+=e.decoder.decode(),(e.cue||"HEADER"===e.state)&&(e.buffer+="\n\n",e.parse()),"INITIAL"===e.state)throw new Fi(Fi.Errors.BadSignature)}catch(t){e.reportOrThrowError(t)}return e.onflush&&e.onflush(),this}};var rr=ir,nr=Object.freeze({default:rr,__moduleExports:rr}),sr="auto",ar={"":1,lr:1,rl:1},or={start:1,middle:1,end:1,left:1,right:1};function ur(t){return"string"==typeof t&&(!!or[t.toLowerCase()]&&t.toLowerCase())}function lr(t,e,i){this.hasBeenReset=!1;var r="",n=!1,s=t,a=e,o=i,u=null,l="",c=!0,h="auto",d="start",p=50,f="middle",m=50,g="middle";Object.defineProperties(this,{id:{enumerable:!0,get:function(){return r},set:function(t){r=""+t}},pauseOnExit:{enumerable:!0,get:function(){return n},set:function(t){n=!!t}},startTime:{enumerable:!0,get:function(){return s},set:function(t){if("number"!=typeof t)throw new TypeError("Start time must be set to a number.");s=t,this.hasBeenReset=!0}},endTime:{enumerable:!0,get:function(){return a},set:function(t){if("number"!=typeof t)throw new TypeError("End time must be set to a number.");a=t,this.hasBeenReset=!0}},text:{enumerable:!0,get:function(){return o},set:function(t){o=""+t,this.hasBeenReset=!0}},region:{enumerable:!0,get:function(){return u},set:function(t){u=t,this.hasBeenReset=!0}},vertical:{enumerable:!0,get:function(){return l},set:function(t){var e,i="string"==typeof(e=t)&&!!ar[e.toLowerCase()]&&e.toLowerCase();if(!1===i)throw new SyntaxError("An invalid or illegal string was specified.");l=i,this.hasBeenReset=!0}},snapToLines:{enumerable:!0,get:function(){return c},set:function(t){c=!!t,this.hasBeenReset=!0}},line:{enumerable:!0,get:function(){return h},set:function(t){if("number"!=typeof t&&t!==sr)throw new SyntaxError("An invalid number or illegal string was specified.");h=t,this.hasBeenReset=!0}},lineAlign:{enumerable:!0,get:function(){return d},set:function(t){var e=ur(t);if(!e)throw new SyntaxError("An invalid or illegal string was specified.");d=e,this.hasBeenReset=!0}},position:{enumerable:!0,get:function(){return p},set:function(t){if(t<0||100<t)throw new Error("Position must be between 0 and 100.");p=t,this.hasBeenReset=!0}},positionAlign:{enumerable:!0,get:function(){return f},set:function(t){var e=ur(t);if(!e)throw new SyntaxError("An invalid or illegal string was specified.");f=e,this.hasBeenReset=!0}},size:{enumerable:!0,get:function(){return m},set:function(t){if(t<0||100<t)throw new Error("Size must be between 0 and 100.");m=t,this.hasBeenReset=!0}},align:{enumerable:!0,get:function(){return g},set:function(t){var e=ur(t);if(!e)throw new SyntaxError("An invalid or illegal string was specified.");g=e,this.hasBeenReset=!0}}}),this.displayState=void 0}lr.prototype.getCueAsHTML=function(){return WebVTT.convertCueToDOMTree(window,this.text)};var cr=lr,hr=Object.freeze({default:cr,__moduleExports:cr}),dr={"":!0,up:!0};function pr(t){return"number"==typeof t&&0<=t&&t<=100}var fr=function(){var e=100,i=3,r=0,n=100,s=0,a=100,o="";Object.defineProperties(this,{width:{enumerable:!0,get:function(){return e},set:function(t){if(!pr(t))throw new Error("Width must be between 0 and 100.");e=t}},lines:{enumerable:!0,get:function(){return i},set:function(t){if("number"!=typeof t)throw new TypeError("Lines must be set to a number.");i=t}},regionAnchorY:{enumerable:!0,get:function(){return n},set:function(t){if(!pr(t))throw new Error("RegionAnchorX must be between 0 and 100.");n=t}},regionAnchorX:{enumerable:!0,get:function(){return r},set:function(t){if(!pr(t))throw new Error("RegionAnchorY must be between 0 and 100.");r=t}},viewportAnchorY:{enumerable:!0,get:function(){return a},set:function(t){if(!pr(t))throw new Error("ViewportAnchorY must be between 0 and 100.");a=t}},viewportAnchorX:{enumerable:!0,get:function(){return s},set:function(t){if(!pr(t))throw new Error("ViewportAnchorX must be between 0 and 100.");s=t}},scroll:{enumerable:!0,get:function(){return o},set:function(t){var e,i="string"==typeof(e=t)&&!!dr[e.toLowerCase()]&&e.toLowerCase();if(!1===i)throw new SyntaxError("An invalid or illegal string was specified.");o=i}}})},mr=Object.freeze({default:fr,__moduleExports:fr}),gr=nr&&rr||nr,yr=hr&&cr||hr,vr=mr&&fr||mr,_r=e(function(t){var e=t.exports={WebVTT:gr,VTTCue:yr,VTTRegion:vr};g.vttjs=e,g.WebVTT=e.WebVTT;var i=e.VTTCue,r=e.VTTRegion,n=g.VTTCue,s=g.VTTRegion;e.shim=function(){g.VTTCue=i,g.VTTRegion=r},e.restore=function(){g.VTTCue=n,g.VTTRegion=s},g.VTTCue||e.shim()});_r.WebVTT,_r.VTTCue,_r.VTTRegion;var br=function(e){function n(){var i=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{},t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:function(){};y(this,n),i.reportTouchActivity=!1;var r=b(this,e.call(this,null,i,t));return r.hasStarted_=!1,r.on("playing",function(){this.hasStarted_=!0}),r.on("loadstart",function(){this.hasStarted_=!1}),Bi.names.forEach(function(t){var e=Bi[t];i&&i[e.getterName]&&(r[e.privateName]=i[e.getterName])}),r.featuresProgressEvents||r.manualProgressOn(),r.featuresTimeupdateEvents||r.manualTimeUpdatesOn(),["Text","Audio","Video"].forEach(function(t){!1===i["native"+t+"Tracks"]&&(r["featuresNative"+t+"Tracks"]=!1)}),!1===i.nativeCaptions||!1===i.nativeTextTracks?r.featuresNativeTextTracks=!1:!0!==i.nativeCaptions&&!0!==i.nativeTextTracks||(r.featuresNativeTextTracks=!0),r.featuresNativeTextTracks||r.emulateTextTracks(),r.autoRemoteTextTracks_=new Bi.text.ListClass,r.initTrackListeners(),i.nativeControlsForTouch||r.emitTapEvents(),r.constructor&&(r.name_=r.constructor.name||"Unknown Tech"),r}return _(n,e),n.prototype.triggerSourceset=function(t){var e=this;this.isReady_||this.one("ready",function(){return e.setTimeout(function(){return e.triggerSourceset(t)},1)}),this.trigger({src:t,type:"sourceset"})},n.prototype.manualProgressOn=function(){this.on("durationchange",this.onDurationChange),this.manualProgress=!0,this.one("ready",this.trackProgress)},n.prototype.manualProgressOff=function(){this.manualProgress=!1,this.stopTrackingProgress(),this.off("durationchange",this.onDurationChange)},n.prototype.trackProgress=function(t){this.stopTrackingProgress(),this.progressInterval=this.setInterval(Ot(this,function(){var t=this.bufferedPercent();this.bufferedPercent_!==t&&this.trigger("progress"),1===(this.bufferedPercent_=t)&&this.stopTrackingProgress()}),500)},n.prototype.onDurationChange=function(t){this.duration_=this.duration()},n.prototype.buffered=function(){return be(0,0)},n.prototype.bufferedPercent=function(){return Te(this.buffered(),this.duration_)},n.prototype.stopTrackingProgress=function(){this.clearInterval(this.progressInterval)},n.prototype.manualTimeUpdatesOn=function(){this.manualTimeUpdates=!0,this.on("play",this.trackCurrentTime),this.on("pause",this.stopTrackingCurrentTime)},n.prototype.manualTimeUpdatesOff=function(){this.manualTimeUpdates=!1,this.stopTrackingCurrentTime(),this.off("play",this.trackCurrentTime),this.off("pause",this.stopTrackingCurrentTime)},n.prototype.trackCurrentTime=function(){this.currentTimeInterval&&this.stopTrackingCurrentTime(),this.currentTimeInterval=this.setInterval(function(){this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})},250)},n.prototype.stopTrackingCurrentTime=function(){this.clearInterval(this.currentTimeInterval),this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})},n.prototype.dispose=function(){this.clearTracks(Ui.names),this.manualProgress&&this.manualProgressOff(),this.manualTimeUpdates&&this.manualTimeUpdatesOff(),e.prototype.dispose.call(this)},n.prototype.clearTracks=function(t){var n=this;(t=[].concat(t)).forEach(function(t){for(var e=n[t+"Tracks"]()||[],i=e.length;i--;){var r=e[i];"text"===t&&n.removeRemoteTextTrack(r),e.removeTrack(r)}})},n.prototype.cleanupAutoTextTracks=function(){for(var t=this.autoRemoteTextTracks_||[],e=t.length;e--;){var i=t[e];this.removeRemoteTextTrack(i)}},n.prototype.reset=function(){},n.prototype.error=function(t){return void 0!==t&&(this.error_=new Le(t),this.trigger("error")),this.error_},n.prototype.played=function(){return this.hasStarted_?be(0,0):be()},n.prototype.setCurrentTime=function(){this.manualTimeUpdates&&this.trigger({type:"timeupdate",target:this,manuallyTriggered:!0})},n.prototype.initTrackListeners=function(){var n=this;Ui.names.forEach(function(t){var e=Ui[t],i=function(){n.trigger(t+"trackchange")},r=n[e.getterName]();r.addEventListener("removetrack",i),r.addEventListener("addtrack",i),n.on("dispose",function(){r.removeEventListener("removetrack",i),r.removeEventListener("addtrack",i)})})},n.prototype.addWebVttScript_=function(){var t=this;if(!g.WebVTT)if(p.body.contains(this.el())){if(!this.options_["vtt.js"]&&w(_r)&&0<Object.keys(_r).length)return void this.trigger("vttjsloaded");var e=p.createElement("script");e.src=this.options_["vtt.js"]||"https://vjs.zencdn.net/vttjs/0.14.1/vtt.min.js",e.onload=function(){t.trigger("vttjsloaded")},e.onerror=function(){t.trigger("vttjserror")},this.on("dispose",function(){e.onload=null,e.onerror=null}),g.WebVTT=!0,this.el().parentNode.appendChild(e)}else this.ready(this.addWebVttScript_)},n.prototype.emulateTextTracks=function(){var t=this,i=this.textTracks(),e=this.remoteTextTracks(),r=function(t){return i.addTrack(t.track)},n=function(t){return i.removeTrack(t.track)};e.on("addtrack",r),e.on("removetrack",n),this.addWebVttScript_();var s=function(){return t.trigger("texttrackchange")},a=function(){s();for(var t=0;t<i.length;t++){var e=i[t];e.removeEventListener("cuechange",s),"showing"===e.mode&&e.addEventListener("cuechange",s)}};a(),i.addEventListener("change",a),i.addEventListener("addtrack",a),i.addEventListener("removetrack",a),this.on("dispose",function(){e.off("addtrack",r),e.off("removetrack",n),i.removeEventListener("change",a),i.removeEventListener("addtrack",a),i.removeEventListener("removetrack",a);for(var t=0;t<i.length;t++){i[t].removeEventListener("cuechange",s)}})},n.prototype.addTextTrack=function(t,e,i){if(!t)throw new Error("TextTrack kind is required but was not provided");return function(t,e,i,r){var n=4<arguments.length&&void 0!==arguments[4]?arguments[4]:{},s=t.textTracks();n.kind=e,i&&(n.label=i),r&&(n.language=r),n.tech=t;var a=new Bi.text.TrackClass(n);return s.addTrack(a),a}(this,t,e,i)},n.prototype.createRemoteTextTrack=function(t){var e=Gt(t,{tech:this});return new Ni.remoteTextEl.TrackClass(e)},n.prototype.addRemoteTextTrack=function(){var t=this,e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{},i=arguments[1],r=this.createRemoteTextTrack(e);return!0!==i&&!1!==i&&(f.warn('Calling addRemoteTextTrack without explicitly setting the "manualCleanup" parameter to `true` is deprecated and default to `false` in future version of video.js'),i=!0),this.remoteTextTrackEls().addTrackElement_(r),this.remoteTextTracks().addTrack(r.track),!0!==i&&this.ready(function(){return t.autoRemoteTextTracks_.addTrack(r.track)}),r},n.prototype.removeRemoteTextTrack=function(t){var e=this.remoteTextTrackEls().getTrackElementByTrack_(t);this.remoteTextTrackEls().removeTrackElement_(e),this.remoteTextTracks().removeTrack(t),this.autoRemoteTextTracks_.removeTrack(t)},n.prototype.getVideoPlaybackQuality=function(){return{}},n.prototype.setPoster=function(){},n.prototype.playsinline=function(){},n.prototype.setPlaysinline=function(){},n.prototype.overrideNativeAudioTracks=function(){},n.prototype.overrideNativeVideoTracks=function(){},n.prototype.canPlayType=function(){return""},n.canPlayType=function(){return""},n.canPlaySource=function(t,e){return n.canPlayType(t.type)},n.isTech=function(t){return t.prototype instanceof n||t instanceof n||t===n},n.registerTech=function(t,e){if(n.techs_||(n.techs_={}),!n.isTech(e))throw new Error("Tech "+t+" must be a Tech");if(!n.canPlayType)throw new Error("Techs must have a static canPlayType method on them");if(!n.canPlaySource)throw new Error("Techs must have a static canPlaySource method on them");return t=zt(t),n.techs_[t]=e,"Tech"!==t&&n.defaultTechOrder_.push(t),e},n.getTech=function(t){if(t)return t=zt(t),n.techs_&&n.techs_[t]?n.techs_[t]:g&&g.videojs&&g.videojs[t]?(f.warn("The "+t+" tech was added to the videojs object when it should be registered using videojs.registerTech(name, tech)"),g.videojs[t]):void 0},n}(Xt);Bi.names.forEach(function(t){var e=Bi[t];br.prototype[e.getterName]=function(){return this[e.privateName]=this[e.privateName]||new e.ListClass,this[e.privateName]}}),br.prototype.featuresVolumeControl=!0,br.prototype.featuresFullscreenResize=!1,br.prototype.featuresPlaybackRate=!1,br.prototype.featuresProgressEvents=!1,br.prototype.featuresSourceset=!1,br.prototype.featuresTimeupdateEvents=!1,br.prototype.featuresNativeTextTracks=!1,br.withSourceHandlers=function(n){n.registerSourceHandler=function(t,e){var i=n.sourceHandlers;i||(i=n.sourceHandlers=[]),void 0===e&&(e=i.length),i.splice(e,0,t)},n.canPlayType=function(t){for(var e=n.sourceHandlers||[],i=void 0,r=0;r<e.length;r++)if(i=e[r].canPlayType(t))return i;return""},n.selectSourceHandler=function(t,e){for(var i=n.sourceHandlers||[],r=0;r<i.length;r++)if(i[r].canHandleSource(t,e))return i[r];return null},n.canPlaySource=function(t,e){var i=n.selectSourceHandler(t,e);return i?i.canHandleSource(t,e):""};["seekable","seeking","duration"].forEach(function(t){var e=this[t];"function"==typeof e&&(this[t]=function(){return this.sourceHandler_&&this.sourceHandler_[t]?this.sourceHandler_[t].apply(this.sourceHandler_,arguments):e.apply(this,arguments)})},n.prototype),n.prototype.setSource=function(t){var e=n.selectSourceHandler(t,this.options_);e||(n.nativeSourceHandler?e=n.nativeSourceHandler:f.error("No source handler found for the current source.")),this.disposeSourceHandler(),this.off("dispose",this.disposeSourceHandler),e!==n.nativeSourceHandler&&(this.currentSource_=t),this.sourceHandler_=e.handleSource(t,this,this.options_),this.on("dispose",this.disposeSourceHandler)},n.prototype.disposeSourceHandler=function(){this.currentSource_&&(this.clearTracks(["audio","video"]),this.currentSource_=null),this.cleanupAutoTextTracks(),this.sourceHandler_&&(this.sourceHandler_.dispose&&this.sourceHandler_.dispose(),this.sourceHandler_=null)}},Xt.registerComponent("Tech",br),br.registerTech("Tech",br),br.defaultTechOrder_=[];var Tr={},Sr={},kr={};function Cr(t,e,i){t.setTimeout(function(){return function i(){var r=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};var t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:[];var n=arguments[2];var s=arguments[3];var a=4<arguments.length&&void 0!==arguments[4]?arguments[4]:[];var o=5<arguments.length&&void 0!==arguments[5]&&arguments[5];var e=t[0],u=t.slice(1);if("string"==typeof e)i(r,Tr[e],n,s,a,o);else if(e){var l=function(t,e){var i=Sr[t.id()],r=null;if(null==i)return r=e(t),Sr[t.id()]=[[e,r]],r;for(var n=0;n<i.length;n++){var s=i[n],a=s[0],o=s[1];a===e&&(r=o)}null===r&&(r=e(t),i.push([e,r]));return r}(s,e);l.setSource(C({},r),function(t,e){if(t)return i(r,u,n,s,a,o);a.push(l),i(e,r.type===e.type?u:Tr[e.type],n,s,a,o)})}else u.length?i(r,u,n,s,a,o):o?n(r,a):i(r,Tr["*"],n,s,a,!0)}(e,Tr[e.type],i,t)},1)}function Er(t,e,i){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null,n="call"+zt(i),s=t.reduce(Pr(n),r),a=s===kr,o=a?null:e[i](s);return function(t,e,i,r){for(var n=t.length-1;0<=n;n--){var s=t[n];s[e]&&s[e](r,i)}}(t,i,o,a),o}var wr={buffered:1,currentTime:1,duration:1,seekable:1,played:1,paused:1},Ar={setCurrentTime:1},Lr={play:1,pause:1};function Pr(i){return function(t,e){return t===kr?kr:e[i]?e[i](t):t}}var Or={opus:"video/ogg",ogv:"video/ogg",mp4:"video/mp4",mov:"video/mp4",m4v:"video/mp4",mkv:"video/x-matroska",mp3:"audio/mpeg",aac:"audio/aac",oga:"audio/ogg",m3u8:"application/x-mpegURL"},xr=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",e=ti(t);return Or[e.toLowerCase()]||""};function Ir(t){var e=xr(t.src);return!t.type&&e&&(t.type=e),t}var Dr=function(l){function c(t,e,i){y(this,c);var r=Gt({createEl:!1},e),n=b(this,l.call(this,t,r,i));if(e.playerOptions.sources&&0!==e.playerOptions.sources.length)t.src(e.playerOptions.sources);else for(var s=0,a=e.playerOptions.techOrder;s<a.length;s++){var o=zt(a[s]),u=br.getTech(o);if(o||(u=Xt.getComponent(o)),u&&u.isSupported()){t.loadTech_(o);break}}return n}return _(c,l),c}(Xt);Xt.registerComponent("MediaLoader",Dr);var Rr=function(n){function r(t,e){y(this,r);var i=b(this,n.call(this,t,e));return i.emitTapEvents(),i.enable(),i}return _(r,n),r.prototype.createEl=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"div",e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};e=C({innerHTML:'<span aria-hidden="true" class="vjs-icon-placeholder"></span>',className:this.buildCSSClass(),tabIndex:0},e),"button"===t&&f.error("Creating a ClickableComponent with an HTML element of "+t+" is not supported; use a Button instead."),i=C({role:"button"},i),this.tabIndex_=e.tabIndex;var r=n.prototype.createEl.call(this,t,e,i);return this.createControlTextEl(r),r},r.prototype.dispose=function(){this.controlTextEl_=null,n.prototype.dispose.call(this)},r.prototype.createControlTextEl=function(t){return this.controlTextEl_=M("span",{className:"vjs-control-text"},{"aria-live":"polite"}),t&&t.appendChild(this.controlTextEl_),this.controlText(this.controlText_,t),this.controlTextEl_},r.prototype.controlText=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:this.el();if(void 0===t)return this.controlText_||"Need Text";var i=this.localize(t);this.controlText_=t,U(this.controlTextEl_,i),this.nonIconControl||e.setAttribute("title",i)},r.prototype.buildCSSClass=function(){return"vjs-control vjs-button "+n.prototype.buildCSSClass.call(this)},r.prototype.enable=function(){this.enabled_||(this.enabled_=!0,this.removeClass("vjs-disabled"),this.el_.setAttribute("aria-disabled","false"),"undefined"!=typeof this.tabIndex_&&this.el_.setAttribute("tabIndex",this.tabIndex_),this.on(["tap","click"],this.handleClick),this.on("focus",this.handleFocus),this.on("blur",this.handleBlur))},r.prototype.disable=function(){this.enabled_=!1,this.addClass("vjs-disabled"),this.el_.setAttribute("aria-disabled","true"),"undefined"!=typeof this.tabIndex_&&this.el_.removeAttribute("tabIndex"),this.off(["tap","click"],this.handleClick),this.off("focus",this.handleFocus),this.off("blur",this.handleBlur)},r.prototype.handleClick=function(t){},r.prototype.handleFocus=function(t){_t(p,"keydown",Ot(this,this.handleKeyPress))},r.prototype.handleKeyPress=function(t){32===t.which||13===t.which?(t.preventDefault(),this.trigger("click")):n.prototype.handleKeyPress&&n.prototype.handleKeyPress.call(this,t)},r.prototype.handleBlur=function(t){bt(p,"keydown",Ot(this,this.handleKeyPress))},r}(Xt);Xt.registerComponent("ClickableComponent",Rr);var Mr=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.update(),t.on("posterchange",Ot(i,i.update)),i}return _(n,r),n.prototype.dispose=function(){this.player().off("posterchange",this.update),r.prototype.dispose.call(this)},n.prototype.createEl=function(){return M("div",{className:"vjs-poster",tabIndex:-1})},n.prototype.update=function(t){var e=this.player().poster();this.setSrc(e),e?this.show():this.hide()},n.prototype.setSrc=function(t){var e="";t&&(e='url("'+t+'")'),this.el_.style.backgroundImage=e},n.prototype.handleClick=function(t){this.player_.controls()&&(this.player_.paused()?this.player_.play():this.player_.pause())},n}(Rr);Xt.registerComponent("PosterImage",Mr);var Ur="#222",Nr={monospace:"monospace",sansSerif:"sans-serif",serif:"serif",monospaceSansSerif:'"Andale Mono", "Lucida Console", monospace',monospaceSerif:'"Courier New", monospace',proportionalSansSerif:"sans-serif",proportionalSerif:"serif",casual:'"Comic Sans MS", Impact, fantasy',script:'"Monotype Corsiva", cursive',smallcaps:'"Andale Mono", "Lucida Console", monospace, sans-serif'};function Br(t,e){return"rgba("+parseInt(t[1]+t[1],16)+","+parseInt(t[2]+t[2],16)+","+parseInt(t[3]+t[3],16)+","+e+")"}function jr(t,e,i){try{t.style[e]=i}catch(t){return}}var Fr=function(n){function s(i,t,e){y(this,s);var r=b(this,n.call(this,i,t,e));return i.on("loadstart",Ot(r,r.toggleDisplay)),i.on("texttrackchange",Ot(r,r.updateDisplay)),i.on("loadstart",Ot(r,r.preselectTrack)),i.ready(Ot(r,function(){if(i.tech_&&i.tech_.featuresNativeTextTracks)this.hide();else{i.on("fullscreenchange",Ot(this,this.updateDisplay));for(var t=this.options_.playerOptions.tracks||[],e=0;e<t.length;e++)this.player_.addRemoteTextTrack(t[e],!0);this.preselectTrack()}})),r}return _(s,n),s.prototype.preselectTrack=function(){for(var t={captions:1,subtitles:1},e=this.player_.textTracks(),i=this.player_.cache_.selectedLanguage,r=void 0,n=void 0,s=void 0,a=0;a<e.length;a++){var o=e[a];i&&i.enabled&&i.language===o.language?o.kind===i.kind?s=o:s||(s=o):i&&!i.enabled?n=r=s=null:o.default&&("descriptions"!==o.kind||r?o.kind in t&&!n&&(n=o):r=o)}s?s.mode="showing":n?n.mode="showing":r&&(r.mode="showing")},s.prototype.toggleDisplay=function(){this.player_.tech_&&this.player_.tech_.featuresNativeTextTracks?this.hide():this.show()},s.prototype.createEl=function(){return n.prototype.createEl.call(this,"div",{className:"vjs-text-track-display"},{"aria-live":"off","aria-atomic":"true"})},s.prototype.clearDisplay=function(){"function"==typeof g.WebVTT&&g.WebVTT.processCues(g,[],this.el_)},s.prototype.updateDisplay=function(){var t=this.player_.textTracks();this.clearDisplay();for(var e=null,i=null,r=t.length;r--;){var n=t[r];"showing"===n.mode&&("descriptions"===n.kind?e=n:i=n)}i?("off"!==this.getAttribute("aria-live")&&this.setAttribute("aria-live","off"),this.updateForTrack(i)):e&&("assertive"!==this.getAttribute("aria-live")&&this.setAttribute("aria-live","assertive"),this.updateForTrack(e))},s.prototype.updateForTrack=function(t){if("function"==typeof g.WebVTT&&t.activeCues){for(var e=[],i=0;i<t.activeCues.length;i++)e.push(t.activeCues[i]);if(g.WebVTT.processCues(g,e,this.el_),this.player_.textTrackSettings)for(var r=this.player_.textTrackSettings.getValues(),n=e.length;n--;){var s=e[n];if(s){var a=s.displayState;if(r.color&&(a.firstChild.style.color=r.color),r.textOpacity&&jr(a.firstChild,"color",Br(r.color||"#fff",r.textOpacity)),r.backgroundColor&&(a.firstChild.style.backgroundColor=r.backgroundColor),r.backgroundOpacity&&jr(a.firstChild,"backgroundColor",Br(r.backgroundColor||"#000",r.backgroundOpacity)),r.windowColor&&(r.windowOpacity?jr(a,"backgroundColor",Br(r.windowColor,r.windowOpacity)):a.style.backgroundColor=r.windowColor),r.edgeStyle&&("dropshadow"===r.edgeStyle?a.firstChild.style.textShadow="2px 2px 3px #222, 2px 2px 4px #222, 2px 2px 5px "+Ur:"raised"===r.edgeStyle?a.firstChild.style.textShadow="1px 1px #222, 2px 2px #222, 3px 3px "+Ur:"depressed"===r.edgeStyle?a.firstChild.style.textShadow="1px 1px #ccc, 0 1px #ccc, -1px -1px #222, 0 -1px "+Ur:"uniform"===r.edgeStyle&&(a.firstChild.style.textShadow="0 0 4px #222, 0 0 4px #222, 0 0 4px #222, 0 0 4px "+Ur)),r.fontPercent&&1!==r.fontPercent){var o=g.parseFloat(a.style.fontSize);a.style.fontSize=o*r.fontPercent+"px",a.style.height="auto",a.style.top="auto",a.style.bottom="2px"}r.fontFamily&&"default"!==r.fontFamily&&("small-caps"===r.fontFamily?a.firstChild.style.fontVariant="small-caps":a.firstChild.style.fontFamily=Nr[r.fontFamily])}}}},s}(Xt);Xt.registerComponent("TextTrackDisplay",Fr);var Hr=function(n){function t(){return y(this,t),b(this,n.apply(this,arguments))}return _(t,n),t.prototype.createEl=function(){var t=this.player_.isAudio(),e=this.localize(t?"Audio Player":"Video Player"),i=M("span",{className:"vjs-control-text",innerHTML:this.localize("{1} is loading.",[e])}),r=n.prototype.createEl.call(this,"div",{className:"vjs-loading-spinner",dir:"ltr"});return r.appendChild(i),r},t}(Xt);Xt.registerComponent("LoadingSpinner",Hr);var Vr=function(e){function t(){return y(this,t),b(this,e.apply(this,arguments))}return _(t,e),t.prototype.createEl=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};e=C({innerHTML:'<span aria-hidden="true" class="vjs-icon-placeholder"></span>',className:this.buildCSSClass()},e),i=C({type:"button"},i);var r=Xt.prototype.createEl.call(this,"button",e,i);return this.createControlTextEl(r),r},t.prototype.addChild=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=this.constructor.name;return f.warn("Adding an actionable (user controllable) child to a Button ("+i+") is not supported; use a ClickableComponent instead."),Xt.prototype.addChild.call(this,t,e)},t.prototype.enable=function(){e.prototype.enable.call(this),this.el_.removeAttribute("disabled")},t.prototype.disable=function(){e.prototype.disable.call(this),this.el_.setAttribute("disabled","disabled")},t.prototype.handleKeyPress=function(t){32!==t.which&&13!==t.which&&e.prototype.handleKeyPress.call(this,t)},t}(Rr);Xt.registerComponent("Button",Vr);var qr=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.mouseused_=!1,i.on("mousedown",i.handleMouseDown),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-big-playOld-button"},n.prototype.handleClick=function(t){var e=this.player_.play();if(!(this.mouseused_&&t.clientX&&t.clientY)){var i=this.player_.getChild("controlBar"),r=i&&i.getChild("playToggle");if(r){var n=function(){return r.focus()};xe(e)?e.then(n,function(){}):this.setTimeout(n,1)}else this.player_.focus()}},n.prototype.handleKeyPress=function(t){this.mouseused_=!1,r.prototype.handleKeyPress.call(this,t)},n.prototype.handleMouseDown=function(t){this.mouseused_=!0},n}(Vr);qr.prototype.controlText_="Play Video",Xt.registerComponent("BigPlayButton",qr);var Wr=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.controlText(e&&e.controlText||i.localize("Close")),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-close-button "+r.prototype.buildCSSClass.call(this)},n.prototype.handleClick=function(t){this.trigger({type:"close",bubbles:!1})},n}(Vr);Xt.registerComponent("CloseButton",Wr);var zr=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.on(t,"play",i.handlePlay),i.on(t,"pause",i.handlePause),i.on(t,"ended",i.handleEnded),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-playOld-control "+r.prototype.buildCSSClass.call(this)},n.prototype.handleClick=function(t){this.player_.paused()?this.player_.play():this.player_.pause()},n.prototype.handleSeeked=function(t){this.removeClass("vjs-ended"),this.player_.paused()?this.handlePause(t):this.handlePlay(t)},n.prototype.handlePlay=function(t){this.removeClass("vjs-ended"),this.removeClass("vjs-paused"),this.addClass("vjs-playing"),this.controlText("Pause")},n.prototype.handlePause=function(t){this.removeClass("vjs-playing"),this.addClass("vjs-paused"),this.controlText("Play")},n.prototype.handleEnded=function(t){this.removeClass("vjs-playing"),this.addClass("vjs-ended"),this.controlText("Replay"),this.one(this.player_,"seeked",this.handleSeeked)},n}(Vr);zr.prototype.controlText_="Play",Xt.registerComponent("PlayToggle",zr);var Gr=function(t,e){t=t<0?0:t;var i=Math.floor(t%60),r=Math.floor(t/60%60),n=Math.floor(t/3600),s=Math.floor(e/60%60),a=Math.floor(e/3600);return(isNaN(t)||t===1/0)&&(n=r=i="-"),(n=0<n||0<a?n+":":"")+(r=((n||10<=s)&&r<10?"0"+r:r)+":")+(i=i<10?"0"+i:i)},Xr=Gr;function Yr(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:t;return Xr(t,e)}var $r=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.throttledUpdateContent=xt(Ot(i,i.updateContent),25),i.on(t,"timeupdate",i.throttledUpdateContent),i}return _(n,r),n.prototype.createEl=function(t){var e=this.buildCSSClass(),i=r.prototype.createEl.call(this,"div",{className:e+" vjs-time-control vjs-control",innerHTML:'<span class="vjs-control-text">'+this.localize(this.labelText_)+" </span>"});return this.contentEl_=M("span",{className:e+"-display"},{"aria-live":"off"}),this.updateTextNode_(),i.appendChild(this.contentEl_),i},n.prototype.dispose=function(){this.contentEl_=null,this.textNode_=null,r.prototype.dispose.call(this)},n.prototype.updateTextNode_=function(){if(this.contentEl_){for(;this.contentEl_.firstChild;)this.contentEl_.removeChild(this.contentEl_.firstChild);this.textNode_=p.createTextNode(this.formattedTime_||this.formatTime_(0)),this.contentEl_.appendChild(this.textNode_)}},n.prototype.formatTime_=function(t){return Yr(t)},n.prototype.updateFormattedTime_=function(t){var e=this.formatTime_(t);e!==this.formattedTime_&&(this.formattedTime_=e,this.requestAnimationFrame(this.updateTextNode_))},n.prototype.updateContent=function(t){},n}(Xt);$r.prototype.labelText_="Time",$r.prototype.controlText_="Time",Xt.registerComponent("TimeDisplay",$r);var Kr=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.on(t,"ended",i.handleEnded),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-current-time"},n.prototype.updateContent=function(t){var e=this.player_.scrubbing()?this.player_.getCache().currentTime:this.player_.currentTime();this.updateFormattedTime_(e)},n.prototype.handleEnded=function(t){this.player_.duration()&&this.updateFormattedTime_(this.player_.duration())},n}($r);Kr.prototype.labelText_="Current Time",Kr.prototype.controlText_="Current Time",Xt.registerComponent("CurrentTimeDisplay",Kr);var Qr=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.on(t,"durationchange",i.updateContent),i.on(t,"loadedmetadata",i.throttledUpdateContent),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-duration"},n.prototype.updateContent=function(t){var e=this.player_.duration();e&&this.duration_!==e&&(this.duration_=e,this.updateFormattedTime_(e))},n}($r);Qr.prototype.labelText_="Duration",Qr.prototype.controlText_="Duration",Xt.registerComponent("DurationDisplay",Qr);var Jr=function(t){function e(){return y(this,e),b(this,t.apply(this,arguments))}return _(e,t),e.prototype.createEl=function(){return t.prototype.createEl.call(this,"div",{className:"vjs-time-control vjs-time-divider",innerHTML:"<div><span>/</span></div>"})},e}(Xt);Xt.registerComponent("TimeDivider",Jr);var Zr=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.on(t,"durationchange",i.throttledUpdateContent),i.on(t,"ended",i.handleEnded),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-remaining-time"},n.prototype.formatTime_=function(t){return"-"+r.prototype.formatTime_.call(this,t)},n.prototype.updateContent=function(t){this.player_.duration()&&(this.player_.remainingTimeDisplay?this.updateFormattedTime_(this.player_.remainingTimeDisplay()):this.updateFormattedTime_(this.player_.remainingTime()))},n.prototype.handleEnded=function(t){this.player_.duration()&&this.updateFormattedTime_(0)},n}($r);Zr.prototype.labelText_="Remaining Time",Zr.prototype.controlText_="Remaining Time",Xt.registerComponent("RemainingTimeDisplay",Zr);var tn=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.updateShowing(),i.on(i.player(),"durationchange",i.updateShowing),i}return _(n,r),n.prototype.createEl=function(){var t=r.prototype.createEl.call(this,"div",{className:"vjs-live-control vjs-control"});return this.contentEl_=M("div",{className:"vjs-live-display",innerHTML:'<span class="vjs-control-text">'+this.localize("Stream Type")+" </span>"+this.localize("LIVE")},{"aria-live":"off"}),t.appendChild(this.contentEl_),t},n.prototype.dispose=function(){this.contentEl_=null,r.prototype.dispose.call(this)},n.prototype.updateShowing=function(t){this.player().duration()===1/0?this.show():this.hide()},n}(Xt);Xt.registerComponent("LiveDisplay",tn);var en=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.bar=i.getChild(i.options_.barName),i.vertical(!!i.options_.vertical),i.enable(),i}return _(n,r),n.prototype.enabled=function(){return this.enabled_},n.prototype.enable=function(){this.enabled()||(this.on("mousedown",this.handleMouseDown),this.on("touchstart",this.handleMouseDown),this.on("focus",this.handleFocus),this.on("blur",this.handleBlur),this.on("click",this.handleClick),this.on(this.player_,"controlsvisible",this.update),this.playerEvent&&this.on(this.player_,this.playerEvent,this.update),this.removeClass("disabled"),this.setAttribute("tabindex",0),this.enabled_=!0)},n.prototype.disable=function(){if(this.enabled()){var t=this.bar.el_.ownerDocument;this.off("mousedown",this.handleMouseDown),this.off("touchstart",this.handleMouseDown),this.off("focus",this.handleFocus),this.off("blur",this.handleBlur),this.off("click",this.handleClick),this.off(this.player_,"controlsvisible",this.update),this.off(t,"mousemove",this.handleMouseMove),this.off(t,"mouseup",this.handleMouseUp),this.off(t,"touchmove",this.handleMouseMove),this.off(t,"touchend",this.handleMouseUp),this.removeAttribute("tabindex"),this.addClass("disabled"),this.playerEvent&&this.off(this.player_,this.playerEvent,this.update),this.enabled_=!1}},n.prototype.createEl=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};return e.className=e.className+" vjs-slider",e=C({tabIndex:0},e),i=C({role:"slider","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0},i),r.prototype.createEl.call(this,t,e,i)},n.prototype.handleMouseDown=function(t){var e=this.bar.el_.ownerDocument;t.preventDefault(),X(),this.addClass("vjs-sliding"),this.trigger("slideractive"),this.on(e,"mousemove",this.handleMouseMove),this.on(e,"mouseup",this.handleMouseUp),this.on(e,"touchmove",this.handleMouseMove),this.on(e,"touchend",this.handleMouseUp),this.handleMouseMove(t)},n.prototype.handleMouseMove=function(t){},n.prototype.handleMouseUp=function(){var t=this.bar.el_.ownerDocument;Y(),this.removeClass("vjs-sliding"),this.trigger("sliderinactive"),this.off(t,"mousemove",this.handleMouseMove),this.off(t,"mouseup",this.handleMouseUp),this.off(t,"touchmove",this.handleMouseMove),this.off(t,"touchend",this.handleMouseUp),this.update()},n.prototype.update=function(){if(this.el_){var t=this.getPercent(),e=this.bar;if(e){("number"!=typeof t||t!=t||t<0||t===1/0)&&(t=0);var i=(100*t).toFixed(2)+"%",r=e.el().style;return this.vertical()?r.height=i:r.width=i,t}}},n.prototype.calculateDistance=function(t){var e=Q(this.el_,t);return this.vertical()?e.y:e.x},n.prototype.handleFocus=function(){this.on(this.bar.el_.ownerDocument,"keydown",this.handleKeyPress)},n.prototype.handleKeyPress=function(t){37===t.which||40===t.which?(t.preventDefault(),this.stepBack()):38!==t.which&&39!==t.which||(t.preventDefault(),this.stepForward())},n.prototype.handleBlur=function(){this.off(this.bar.el_.ownerDocument,"keydown",this.handleKeyPress)},n.prototype.handleClick=function(t){t.stopImmediatePropagation(),t.preventDefault()},n.prototype.vertical=function(t){if(void 0===t)return this.vertical_||!1;this.vertical_=!!t,this.vertical_?this.addClass("vjs-slider-vertical"):this.addClass("vjs-slider-horizontal")},n}(Xt);Xt.registerComponent("Slider",en);var rn=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.partEls_=[],i.on(t,"progress",i.update),i}return _(n,r),n.prototype.createEl=function(){return r.prototype.createEl.call(this,"div",{className:"vjs-load-progress",innerHTML:'<span class="vjs-control-text"><span>'+this.localize("Loaded")+"</span>: 0%</span>"})},n.prototype.dispose=function(){this.partEls_=null,r.prototype.dispose.call(this)},n.prototype.update=function(t){var e=this.player_.buffered(),i=this.player_.duration(),r=this.player_.bufferedEnd(),n=this.partEls_,s=function(t,e){var i=t/e||0;return 100*(1<=i?1:i)+"%"};this.el_.style.width=s(r,i);for(var a=0;a<e.length;a++){var o=e.start(a),u=e.end(a),l=n[a];l||(l=this.el_.appendChild(M()),n[a]=l),l.style.left=s(o,r),l.style.width=s(u-o,r)}for(var c=n.length;c>e.length;c--)this.el_.removeChild(n[c-1]);n.length=e.length},n}(Xt);Xt.registerComponent("LoadProgressBar",rn);var nn=function(t){function e(){return y(this,e),b(this,t.apply(this,arguments))}return _(e,t),e.prototype.createEl=function(){return t.prototype.createEl.call(this,"div",{className:"vjs-time-tooltip"})},e.prototype.update=function(t,e,i){var r=$(this.el_),n=$(this.player_.el()),s=t.width*e;if(n&&r){var a=t.left-n.left+s,o=t.width-s+(n.right-t.right),u=r.width/2;a<u?u+=u-a:o<u&&(u=o),u<0?u=0:u>r.width&&(u=r.width),this.el_.style.right="-"+u+"px",U(this.el_,i)}},e}(Xt);Xt.registerComponent("TimeTooltip",nn);var sn=function(t){function e(){return y(this,e),b(this,t.apply(this,arguments))}return _(e,t),e.prototype.createEl=function(){return t.prototype.createEl.call(this,"div",{className:"vjs-playOld-progress vjs-slider-bar",innerHTML:'<span class="vjs-control-text"><span>'+this.localize("Progress")+"</span>: 0%</span>"})},e.prototype.update=function(i,r){var n=this;this.rafId_&&this.cancelAnimationFrame(this.rafId_),this.rafId_=this.requestAnimationFrame(function(){var t=Yr(n.player_.scrubbing()?n.player_.getCache().currentTime:n.player_.currentTime(),n.player_.duration()),e=n.getChild("timeTooltip");e&&e.update(i,r,t)})},e}(Xt);sn.prototype.options_={children:[]},ne||ae||sn.prototype.options_.children.push("timeTooltip"),Xt.registerComponent("PlayProgressBar",sn);var an=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.update=xt(Ot(i,i.update),25),i}return _(n,r),n.prototype.createEl=function(){return r.prototype.createEl.call(this,"div",{className:"vjs-mouse-display"})},n.prototype.update=function(i,r){var n=this;this.rafId_&&this.cancelAnimationFrame(this.rafId_),this.rafId_=this.requestAnimationFrame(function(){var t=n.player_.duration(),e=Yr(r*t,t);n.el_.style.left=i.width*r+"px",n.getChild("timeTooltip").update(i,r,e)})},n}(Xt);an.prototype.options_={children:["timeTooltip"]},Xt.registerComponent("MouseTimeDisplay",an);var on=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.setEventHandlers_(),i}return _(n,r),n.prototype.setEventHandlers_=function(){var t=this;this.update=xt(Ot(this,this.update),30),this.on(this.player_,"timeupdate",this.update),this.on(this.player_,"ended",this.handleEnded),this.updateInterval=null,this.on(this.player_,["playing"],function(){t.clearInterval(t.updateInterval),t.updateInterval=t.setInterval(function(){t.requestAnimationFrame(function(){t.update()})},30)}),this.on(this.player_,["ended","pause","waiting"],function(){t.clearInterval(t.updateInterval)}),this.on(this.player_,["timeupdate","ended"],this.update)},n.prototype.createEl=function(){return r.prototype.createEl.call(this,"div",{className:"vjs-progress-holder"},{"aria-label":this.localize("Progress Bar")})},n.prototype.update_=function(t,e){var i=this.player_.duration();this.el_.setAttribute("aria-valuenow",(100*e).toFixed(2)),this.el_.setAttribute("aria-valuetext",this.localize("progress bar timing: currentTime={1} duration={2}",[Yr(t,i),Yr(i,i)],"{1} of {2}")),this.bar.update($(this.el_),e)},n.prototype.update=function(t){var e=r.prototype.update.call(this);return this.update_(this.getCurrentTime_(),e),e},n.prototype.getCurrentTime_=function(){return this.player_.scrubbing()?this.player_.getCache().currentTime:this.player_.currentTime()},n.prototype.handleEnded=function(t){this.update_(this.player_.duration(),1)},n.prototype.getPercent=function(){var t=this.getCurrentTime_()/this.player_.duration();return 1<=t?1:t||0},n.prototype.handleMouseDown=function(t){rt(t)&&(t.stopPropagation(),this.player_.scrubbing(!0),this.videoWasPlaying=!this.player_.paused(),this.player_.pause(),r.prototype.handleMouseDown.call(this,t))},n.prototype.handleMouseMove=function(t){if(rt(t)){var e=this.calculateDistance(t)*this.player_.duration();e===this.player_.duration()&&(e-=.1),this.player_.currentTime(e)}},n.prototype.enable=function(){r.prototype.enable.call(this);var t=this.getChild("mouseTimeDisplay");t&&t.show()},n.prototype.disable=function(){r.prototype.disable.call(this);var t=this.getChild("mouseTimeDisplay");t&&t.hide()},n.prototype.handleMouseUp=function(t){r.prototype.handleMouseUp.call(this,t),t&&t.stopPropagation(),this.player_.scrubbing(!1),this.player_.trigger({type:"timeupdate",target:this,manuallyTriggered:!0}),this.videoWasPlaying&&Ie(this.player_.play())},n.prototype.stepForward=function(){this.player_.currentTime(this.player_.currentTime()+5)},n.prototype.stepBack=function(){this.player_.currentTime(this.player_.currentTime()-5)},n.prototype.handleAction=function(t){this.player_.paused()?this.player_.play():this.player_.pause()},n.prototype.handleKeyPress=function(t){32===t.which||13===t.which?(t.preventDefault(),this.handleAction(t)):r.prototype.handleKeyPress&&r.prototype.handleKeyPress.call(this,t)},n}(en);on.prototype.options_={children:["loadProgressBar","playProgressBar"],barName:"playProgressBar"},ne||ae||on.prototype.options_.children.splice(1,0,"mouseTimeDisplay"),on.prototype.playerEvent="timeupdate",Xt.registerComponent("SeekBar",on);var un=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.handleMouseMove=xt(Ot(i,i.handleMouseMove),25),i.throttledHandleMouseSeek=xt(Ot(i,i.handleMouseSeek),25),i.enable(),i}return _(n,r),n.prototype.createEl=function(){return r.prototype.createEl.call(this,"div",{className:"vjs-progress-control vjs-control"})},n.prototype.handleMouseMove=function(t){var e=this.getChild("seekBar");if(e){var i=e.getChild("mouseTimeDisplay"),r=e.el(),n=$(r),s=Q(r,t).x;1<s?s=1:s<0&&(s=0),i&&i.update(n,s)}},n.prototype.handleMouseSeek=function(t){var e=this.getChild("seekBar");e&&e.handleMouseMove(t)},n.prototype.enabled=function(){return this.enabled_},n.prototype.disable=function(){this.children().forEach(function(t){return t.disable&&t.disable()}),this.enabled()&&(this.off(["mousedown","touchstart"],this.handleMouseDown),this.off(this.el_,"mousemove",this.handleMouseMove),this.handleMouseUp(),this.addClass("disabled"),this.enabled_=!1)},n.prototype.enable=function(){this.children().forEach(function(t){return t.enable&&t.enable()}),this.enabled()||(this.on(["mousedown","touchstart"],this.handleMouseDown),this.on(this.el_,"mousemove",this.handleMouseMove),this.removeClass("disabled"),this.enabled_=!0)},n.prototype.handleMouseDown=function(t){var e=this.el_.ownerDocument,i=this.getChild("seekBar");i&&i.handleMouseDown(t),this.on(e,"mousemove",this.throttledHandleMouseSeek),this.on(e,"touchmove",this.throttledHandleMouseSeek),this.on(e,"mouseup",this.handleMouseUp),this.on(e,"touchend",this.handleMouseUp)},n.prototype.handleMouseUp=function(t){var e=this.el_.ownerDocument,i=this.getChild("seekBar");i&&i.handleMouseUp(t),this.off(e,"mousemove",this.throttledHandleMouseSeek),this.off(e,"touchmove",this.throttledHandleMouseSeek),this.off(e,"mouseup",this.handleMouseUp),this.off(e,"touchend",this.handleMouseUp)},n}(Xt);un.prototype.options_={children:["seekBar"]},Xt.registerComponent("ProgressControl",un);var ln=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.on(t,"fullscreenchange",i.handleFullscreenChange),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-fullscreen-control "+r.prototype.buildCSSClass.call(this)},n.prototype.handleFullscreenChange=function(t){this.player_.isFullscreen()?this.controlText("Non-Fullscreen"):this.controlText("Fullscreen")},n.prototype.handleClick=function(t){this.player_.isFullscreen()?this.player_.exitFullscreen():this.player_.requestFullscreen()},n}(Vr);ln.prototype.controlText_="Fullscreen",Xt.registerComponent("FullscreenToggle",ln);var cn=function(t,e){e.tech_&&!e.tech_.featuresVolumeControl&&t.addClass("vjs-hidden"),t.on(e,"loadstart",function(){e.tech_.featuresVolumeControl?t.removeClass("vjs-hidden"):t.addClass("vjs-hidden")})},hn=function(t){function e(){return y(this,e),b(this,t.apply(this,arguments))}return _(e,t),e.prototype.createEl=function(){return t.prototype.createEl.call(this,"div",{className:"vjs-volume-level",innerHTML:'<span class="vjs-control-text"></span>'})},e}(Xt);Xt.registerComponent("VolumeLevel",hn);var dn=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.on("slideractive",i.updateLastVolume_),i.on(t,"volumechange",i.updateARIAAttributes),t.ready(function(){return i.updateARIAAttributes()}),i}return _(n,r),n.prototype.createEl=function(){return r.prototype.createEl.call(this,"div",{className:"vjs-volume-bar vjs-slider-bar"},{"aria-label":this.localize("Volume Level"),"aria-live":"polite"})},n.prototype.handleMouseDown=function(t){rt(t)&&r.prototype.handleMouseDown.call(this,t)},n.prototype.handleMouseMove=function(t){rt(t)&&(this.checkMuted(),this.player_.volume(this.calculateDistance(t)))},n.prototype.checkMuted=function(){this.player_.muted()&&this.player_.muted(!1)},n.prototype.getPercent=function(){return this.player_.muted()?0:this.player_.volume()},n.prototype.stepForward=function(){this.checkMuted(),this.player_.volume(this.player_.volume()+.1)},n.prototype.stepBack=function(){this.checkMuted(),this.player_.volume(this.player_.volume()-.1)},n.prototype.updateARIAAttributes=function(t){var e=this.player_.muted()?0:this.volumeAsPercentage_();this.el_.setAttribute("aria-valuenow",e),this.el_.setAttribute("aria-valuetext",e+"%")},n.prototype.volumeAsPercentage_=function(){return Math.round(100*this.player_.volume())},n.prototype.updateLastVolume_=function(){var t=this,e=this.player_.volume();this.one("sliderinactive",function(){0===t.player_.volume()&&t.player_.lastVolume_(e)})},n}(en);dn.prototype.options_={children:["volumeLevel"],barName:"volumeLevel"},dn.prototype.playerEvent="volumechange",Xt.registerComponent("VolumeBar",dn);var pn=function(r){function n(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};y(this,n),e.vertical=e.vertical||!1,("undefined"==typeof e.volumeBar||w(e.volumeBar))&&(e.volumeBar=e.volumeBar||{},e.volumeBar.vertical=e.vertical);var i=b(this,r.call(this,t,e));return cn(i,t),i.throttledHandleMouseMove=xt(Ot(i,i.handleMouseMove),25),i.on("mousedown",i.handleMouseDown),i.on("touchstart",i.handleMouseDown),i.on(i.volumeBar,["focus","slideractive"],function(){i.volumeBar.addClass("vjs-slider-active"),i.addClass("vjs-slider-active"),i.trigger("slideractive")}),i.on(i.volumeBar,["blur","sliderinactive"],function(){i.volumeBar.removeClass("vjs-slider-active"),i.removeClass("vjs-slider-active"),i.trigger("sliderinactive")}),i}return _(n,r),n.prototype.createEl=function(){var t="vjs-volume-horizontal";return this.options_.vertical&&(t="vjs-volume-vertical"),r.prototype.createEl.call(this,"div",{className:"vjs-volume-control vjs-control "+t})},n.prototype.handleMouseDown=function(t){var e=this.el_.ownerDocument;this.on(e,"mousemove",this.throttledHandleMouseMove),this.on(e,"touchmove",this.throttledHandleMouseMove),this.on(e,"mouseup",this.handleMouseUp),this.on(e,"touchend",this.handleMouseUp)},n.prototype.handleMouseUp=function(t){var e=this.el_.ownerDocument;this.off(e,"mousemove",this.throttledHandleMouseMove),this.off(e,"touchmove",this.throttledHandleMouseMove),this.off(e,"mouseup",this.handleMouseUp),this.off(e,"touchend",this.handleMouseUp)},n.prototype.handleMouseMove=function(t){this.volumeBar.handleMouseMove(t)},n}(Xt);pn.prototype.options_={children:["volumeBar"]},Xt.registerComponent("VolumeControl",pn);var fn=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return cn(i,t),i.on(t,["loadstart","volumechange"],i.update),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-mute-control "+r.prototype.buildCSSClass.call(this)},n.prototype.handleClick=function(t){var e=this.player_.volume(),i=this.player_.lastVolume_();if(0===e){var r=i<.1?.1:i;this.player_.volume(r),this.player_.muted(!1)}else this.player_.muted(!this.player_.muted())},n.prototype.update=function(t){this.updateIcon_(),this.updateControlText_()},n.prototype.updateIcon_=function(){var t=this.player_.volume(),e=3;0===t||this.player_.muted()?e=0:t<.33?e=1:t<.67&&(e=2);for(var i=0;i<4;i++)F(this.el_,"vjs-vol-"+i);j(this.el_,"vjs-vol-"+e)},n.prototype.updateControlText_=function(){var t=this.player_.muted()||0===this.player_.volume()?"Unmute":"Mute";this.controlText()!==t&&this.controlText(t)},n}(Vr);fn.prototype.controlText_="Mute",Xt.registerComponent("MuteToggle",fn);var mn=function(r){function n(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};y(this,n),"undefined"!=typeof e.inline?e.inline=e.inline:e.inline=!0,("undefined"==typeof e.volumeControl||w(e.volumeControl))&&(e.volumeControl=e.volumeControl||{},e.volumeControl.vertical=!e.inline);var i=b(this,r.call(this,t,e));return cn(i,t),i.on(i.volumeControl,["slideractive"],i.sliderActive_),i.on(i.volumeControl,["sliderinactive"],i.sliderInactive_),i}return _(n,r),n.prototype.sliderActive_=function(){this.addClass("vjs-slider-active")},n.prototype.sliderInactive_=function(){this.removeClass("vjs-slider-active")},n.prototype.createEl=function(){var t="vjs-volume-panel-horizontal";return this.options_.inline||(t="vjs-volume-panel-vertical"),r.prototype.createEl.call(this,"div",{className:"vjs-volume-panel vjs-control "+t})},n}(Xt);mn.prototype.options_={children:["muteToggle","volumeControl"]},Xt.registerComponent("VolumePanel",mn);var gn=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return e&&(i.menuButton_=e.menuButton),i.focusedChild_=-1,i.on("keydown",i.handleKeyPress),i}return _(n,r),n.prototype.addItem=function(e){this.addChild(e),e.on("click",Ot(this,function(t){this.menuButton_&&(this.menuButton_.unpressButton(),"CaptionSettingsMenuItem"!==e.name()&&this.menuButton_.focus())}))},n.prototype.createEl=function(){var t=this.options_.contentElType||"ul";this.contentEl_=M(t,{className:"vjs-menu-content"}),this.contentEl_.setAttribute("role","menu");var e=r.prototype.createEl.call(this,"div",{append:this.contentEl_,className:"vjs-menu"});return e.appendChild(this.contentEl_),_t(e,"click",function(t){t.preventDefault(),t.stopImmediatePropagation()}),e},n.prototype.dispose=function(){this.contentEl_=null,r.prototype.dispose.call(this)},n.prototype.handleKeyPress=function(t){37===t.which||40===t.which?(t.preventDefault(),this.stepForward()):38!==t.which&&39!==t.which||(t.preventDefault(),this.stepBack())},n.prototype.stepForward=function(){var t=0;void 0!==this.focusedChild_&&(t=this.focusedChild_+1),this.focus(t)},n.prototype.stepBack=function(){var t=0;void 0!==this.focusedChild_&&(t=this.focusedChild_-1),this.focus(t)},n.prototype.focus=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0,e=this.children().slice();e.length&&e[0].className&&/vjs-menu-title/.test(e[0].className)&&e.shift(),0<e.length&&(t<0?t=0:t>=e.length&&(t=e.length-1),e[this.focusedChild_=t].el_.focus())},n}(Xt);Xt.registerComponent("Menu",gn);var yn=function(n){function s(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};y(this,s);var i=b(this,n.call(this,t,e));i.menuButton_=new Vr(t,e),i.menuButton_.controlText(i.controlText_),i.menuButton_.el_.setAttribute("aria-haspopup","true");var r=Vr.prototype.buildCSSClass();return i.menuButton_.el_.className=i.buildCSSClass()+" "+r,i.menuButton_.removeClass("vjs-control"),i.addChild(i.menuButton_),i.update(),i.enabled_=!0,i.on(i.menuButton_,"tap",i.handleClick),i.on(i.menuButton_,"click",i.handleClick),i.on(i.menuButton_,"focus",i.handleFocus),i.on(i.menuButton_,"blur",i.handleBlur),i.on("keydown",i.handleSubmenuKeyPress),i}return _(s,n),s.prototype.update=function(){var t=this.createMenu();this.menu&&(this.menu.dispose(),this.removeChild(this.menu)),this.menu=t,this.addChild(t),this.buttonPressed_=!1,this.menuButton_.el_.setAttribute("aria-expanded","false"),this.items&&this.items.length<=this.hideThreshold_?this.hide():this.show()},s.prototype.createMenu=function(){var t=new gn(this.player_,{menuButton:this});if(this.hideThreshold_=0,this.options_.title){var e=M("li",{className:"vjs-menu-title",innerHTML:zt(this.options_.title),tabIndex:-1});this.hideThreshold_+=1,t.children_.unshift(e),N(e,t.contentEl())}if(this.items=this.createItems(),this.items)for(var i=0;i<this.items.length;i++)t.addItem(this.items[i]);return t},s.prototype.createItems=function(){},s.prototype.createEl=function(){return n.prototype.createEl.call(this,"div",{className:this.buildWrapperCSSClass()},{})},s.prototype.buildWrapperCSSClass=function(){var t="vjs-menu-button";return!0===this.options_.inline?t+="-inline":t+="-popup","vjs-menu-button "+t+" "+Vr.prototype.buildCSSClass()+" "+n.prototype.buildCSSClass.call(this)},s.prototype.buildCSSClass=function(){var t="vjs-menu-button";return!0===this.options_.inline?t+="-inline":t+="-popup","vjs-menu-button "+t+" "+n.prototype.buildCSSClass.call(this)},s.prototype.controlText=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:this.menuButton_.el();return this.menuButton_.controlText(t,e)},s.prototype.handleClick=function(t){this.one(this.menu.contentEl(),"mouseleave",Ot(this,function(t){this.unpressButton(),this.el_.blur()})),this.buttonPressed_?this.unpressButton():this.pressButton()},s.prototype.focus=function(){this.menuButton_.focus()},s.prototype.blur=function(){this.menuButton_.blur()},s.prototype.handleFocus=function(){_t(p,"keydown",Ot(this,this.handleKeyPress))},s.prototype.handleBlur=function(){bt(p,"keydown",Ot(this,this.handleKeyPress))},s.prototype.handleKeyPress=function(t){27===t.which||9===t.which?(this.buttonPressed_&&this.unpressButton(),9!==t.which&&(t.preventDefault(),this.menuButton_.el_.focus())):38!==t.which&&40!==t.which||this.buttonPressed_||(this.pressButton(),t.preventDefault())},s.prototype.handleSubmenuKeyPress=function(t){27!==t.which&&9!==t.which||(this.buttonPressed_&&this.unpressButton(),9!==t.which&&(t.preventDefault(),this.menuButton_.el_.focus()))},s.prototype.pressButton=function(){if(this.enabled_){if(this.buttonPressed_=!0,this.menu.lockShowing(),this.menuButton_.el_.setAttribute("aria-expanded","true"),ne&&D())return;this.menu.focus()}},s.prototype.unpressButton=function(){this.enabled_&&(this.buttonPressed_=!1,this.menu.unlockShowing(),this.menuButton_.el_.setAttribute("aria-expanded","false"))},s.prototype.disable=function(){this.unpressButton(),this.enabled_=!1,this.addClass("vjs-disabled"),this.menuButton_.disable()},s.prototype.enable=function(){this.enabled_=!0,this.removeClass("vjs-disabled"),this.menuButton_.enable()},s}(Xt);Xt.registerComponent("MenuButton",yn);var vn=function(s){function a(t,e){y(this,a);var i=e.tracks,r=b(this,s.call(this,t,e));if(r.items.length<=1&&r.hide(),!i)return b(r);var n=Ot(r,r.update);return i.addEventListener("removetrack",n),i.addEventListener("addtrack",n),r.player_.on("ready",n),r.player_.on("dispose",function(){i.removeEventListener("removetrack",n),i.removeEventListener("addtrack",n)}),r}return _(a,s),a}(yn);Xt.registerComponent("TrackButton",vn);var _n=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.selectable=e.selectable,i.isSelected_=e.selected||!1,i.selected(i.isSelected_),i.selectable?i.el_.setAttribute("role","menuitemcheckbox"):i.el_.setAttribute("role","menuitem"),i}return _(n,r),n.prototype.createEl=function(t,e,i){return this.nonIconControl=!0,r.prototype.createEl.call(this,"li",C({className:"vjs-menu-item",innerHTML:'<span class="vjs-menu-item-text">'+this.localize(this.options_.label)+"</span>",tabIndex:-1},e),i)},n.prototype.handleClick=function(t){this.selected(!0)},n.prototype.selected=function(t){this.selectable&&(t?(this.addClass("vjs-selected"),this.el_.setAttribute("aria-checked","true"),this.controlText(", selected"),this.isSelected_=!0):(this.removeClass("vjs-selected"),this.el_.setAttribute("aria-checked","false"),this.controlText(""),this.isSelected_=!1))},n}(Rr);Xt.registerComponent("MenuItem",_n);var bn=function(u){function l(t,e){y(this,l);var i=e.track,r=t.textTracks();e.label=i.label||i.language||"Unknown",e.selected="showing"===i.mode;var n=b(this,u.call(this,t,e));n.track=i;var s=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];n.handleTracksChange.apply(n,e)},a=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];n.handleSelectedLanguageChange.apply(n,e)};if(t.on(["loadstart","texttrackchange"],s),r.addEventListener("change",s),r.addEventListener("selectedlanguagechange",a),n.on("dispose",function(){t.off(["loadstart","texttrackchange"],s),r.removeEventListener("change",s),r.removeEventListener("selectedlanguagechange",a)}),void 0===r.onchange){var o=void 0;n.on(["tap","click"],function(){if("object"!==v(g.Event))try{o=new g.Event("change")}catch(t){}o||(o=p.createEvent("Event")).initEvent("change",!0,!0),r.dispatchEvent(o)})}return n.handleTracksChange(),n}return _(l,u),l.prototype.handleClick=function(t){var e=this.track.kind,i=this.track.kinds,r=this.player_.textTracks();if(i||(i=[e]),u.prototype.handleClick.call(this,t),r)for(var n=0;n<r.length;n++){var s=r[n];s===this.track&&-1<i.indexOf(s.kind)?"showing"!==s.mode&&(s.mode="showing"):"disabled"!==s.mode&&(s.mode="disabled")}},l.prototype.handleTracksChange=function(t){var e="showing"===this.track.mode;e!==this.isSelected_&&this.selected(e)},l.prototype.handleSelectedLanguageChange=function(t){if("showing"===this.track.mode){var e=this.player_.cache_.selectedLanguage;if(e&&e.enabled&&e.language===this.track.language&&e.kind!==this.track.kind)return;this.player_.cache_.selectedLanguage={enabled:!0,language:this.track.language,kind:this.track.kind}}},l.prototype.dispose=function(){this.track=null,u.prototype.dispose.call(this)},l}(_n);Xt.registerComponent("TextTrackMenuItem",bn);var Tn=function(i){function r(t,e){return y(this,r),e.track={player:t,kind:e.kind,kinds:e.kinds,default:!1,mode:"disabled"},e.kinds||(e.kinds=[e.kind]),e.label?e.track.label=e.label:e.track.label=e.kinds.join(" and ")+" off",e.selectable=!0,b(this,i.call(this,t,e))}return _(r,i),r.prototype.handleTracksChange=function(t){for(var e=this.player().textTracks(),i=!0,r=0,n=e.length;r<n;r++){var s=e[r];if(-1<this.options_.kinds.indexOf(s.kind)&&"showing"===s.mode){i=!1;break}}i!==this.isSelected_&&this.selected(i)},r.prototype.handleSelectedLanguageChange=function(t){for(var e=this.player().textTracks(),i=!0,r=0,n=e.length;r<n;r++){var s=e[r];if(-1<["captions","descriptions","subtitles"].indexOf(s.kind)&&"showing"===s.mode){i=!1;break}}i&&(this.player_.cache_.selectedLanguage={enabled:!1})},r}(bn);Xt.registerComponent("OffTextTrackMenuItem",Tn);var Sn=function(i){function r(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};return y(this,r),e.tracks=t.textTracks(),b(this,i.call(this,t,e))}return _(r,i),r.prototype.createItems=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:bn,i=void 0;this.label_&&(i=this.label_+" off"),t.push(new Tn(this.player_,{kinds:this.kinds_,kind:this.kind_,label:i})),this.hideThreshold_+=1;var r=this.player_.textTracks();Array.isArray(this.kinds_)||(this.kinds_=[this.kind_]);for(var n=0;n<r.length;n++){var s=r[n];if(-1<this.kinds_.indexOf(s.kind)){var a=new e(this.player_,{track:s,selectable:!0});a.addClass("vjs-"+s.kind+"-menu-item"),t.push(a)}}return t},r}(vn);Xt.registerComponent("TextTrackButton",Sn);var kn=function(a){function o(t,e){y(this,o);var i=e.track,r=e.cue,n=t.currentTime();e.selectable=!0,e.label=r.text,e.selected=r.startTime<=n&&n<r.endTime;var s=b(this,a.call(this,t,e));return s.track=i,s.cue=r,i.addEventListener("cuechange",Ot(s,s.update)),s}return _(o,a),o.prototype.handleClick=function(t){a.prototype.handleClick.call(this),this.player_.currentTime(this.cue.startTime),this.update(this.cue.startTime)},o.prototype.update=function(t){var e=this.cue,i=this.player_.currentTime();this.selected(e.startTime<=i&&i<e.endTime)},o}(_n);Xt.registerComponent("ChaptersTrackMenuItem",kn);var Cn=function(r){function n(t,e,i){return y(this,n),b(this,r.call(this,t,e,i))}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-chapters-button "+r.prototype.buildCSSClass.call(this)},n.prototype.buildWrapperCSSClass=function(){return"vjs-chapters-button "+r.prototype.buildWrapperCSSClass.call(this)},n.prototype.update=function(t){this.track_&&(!t||"addtrack"!==t.type&&"removetrack"!==t.type)||this.setTrack(this.findChaptersTrack()),r.prototype.update.call(this)},n.prototype.setTrack=function(t){if(this.track_!==t){if(this.updateHandler_||(this.updateHandler_=this.update.bind(this)),this.track_){var e=this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_);e&&e.removeEventListener("load",this.updateHandler_),this.track_=null}if(this.track_=t,this.track_){this.track_.mode="hidden";var i=this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_);i&&i.addEventListener("load",this.updateHandler_)}}},n.prototype.findChaptersTrack=function(){for(var t=this.player_.textTracks()||[],e=t.length-1;0<=e;e--){var i=t[e];if(i.kind===this.kind_)return i}},n.prototype.getMenuCaption=function(){return this.track_&&this.track_.label?this.track_.label:this.localize(zt(this.kind_))},n.prototype.createMenu=function(){return this.options_.title=this.getMenuCaption(),r.prototype.createMenu.call(this)},n.prototype.createItems=function(){var t=[];if(!this.track_)return t;var e=this.track_.cues;if(!e)return t;for(var i=0,r=e.length;i<r;i++){var n=e[i],s=new kn(this.player_,{track:this.track_,cue:n});t.push(s)}return t},n}(Sn);Cn.prototype.kind_="chapters",Cn.prototype.controlText_="Chapters",Xt.registerComponent("ChaptersButton",Cn);var En=function(a){function o(t,e,i){y(this,o);var r=b(this,a.call(this,t,e,i)),n=t.textTracks(),s=Ot(r,r.handleTracksChange);return n.addEventListener("change",s),r.on("dispose",function(){n.removeEventListener("change",s)}),r}return _(o,a),o.prototype.handleTracksChange=function(t){for(var e=this.player().textTracks(),i=!1,r=0,n=e.length;r<n;r++){var s=e[r];if(s.kind!==this.kind_&&"showing"===s.mode){i=!0;break}}i?this.disable():this.enable()},o.prototype.buildCSSClass=function(){return"vjs-descriptions-button "+a.prototype.buildCSSClass.call(this)},o.prototype.buildWrapperCSSClass=function(){return"vjs-descriptions-button "+a.prototype.buildWrapperCSSClass.call(this)},o}(Sn);En.prototype.kind_="descriptions",En.prototype.controlText_="Descriptions",Xt.registerComponent("DescriptionsButton",En);var wn=function(r){function n(t,e,i){return y(this,n),b(this,r.call(this,t,e,i))}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-subtitles-button "+r.prototype.buildCSSClass.call(this)},n.prototype.buildWrapperCSSClass=function(){return"vjs-subtitles-button "+r.prototype.buildWrapperCSSClass.call(this)},n}(Sn);wn.prototype.kind_="subtitles",wn.prototype.controlText_="Subtitles",Xt.registerComponent("SubtitlesButton",wn);var An=function(r){function n(t,e){y(this,n),e.track={player:t,kind:e.kind,label:e.kind+" settings",selectable:!1,default:!1,mode:"disabled"},e.selectable=!1,e.name="CaptionSettingsMenuItem";var i=b(this,r.call(this,t,e));return i.addClass("vjs-texttrack-settings"),i.controlText(", opens "+e.kind+" settings dialog"),i}return _(n,r),n.prototype.handleClick=function(t){this.player().getChild("textTrackSettings").open()},n}(bn);Xt.registerComponent("CaptionSettingsMenuItem",An);var Ln=function(r){function n(t,e,i){return y(this,n),b(this,r.call(this,t,e,i))}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-captions-button "+r.prototype.buildCSSClass.call(this)},n.prototype.buildWrapperCSSClass=function(){return"vjs-captions-button "+r.prototype.buildWrapperCSSClass.call(this)},n.prototype.createItems=function(){var t=[];return this.player().tech_&&this.player().tech_.featuresNativeTextTracks||!this.player().getChild("textTrackSettings")||(t.push(new An(this.player_,{kind:this.kind_})),this.hideThreshold_+=1),r.prototype.createItems.call(this,t)},n}(Sn);Ln.prototype.kind_="captions",Ln.prototype.controlText_="Captions",Xt.registerComponent("CaptionsButton",Ln);var Pn=function(n){function t(){return y(this,t),b(this,n.apply(this,arguments))}return _(t,n),t.prototype.createEl=function(t,e,i){var r='<span class="vjs-menu-item-text">'+this.localize(this.options_.label);return"captions"===this.options_.track.kind&&(r+='\n <span aria-hidden="true" class="vjs-icon-placeholder"></span>\n <span class="vjs-control-text"> '+this.localize("Captions")+"</span>\n "),r+="</span>",n.prototype.createEl.call(this,t,C({innerHTML:r},e),i)},t}(bn);Xt.registerComponent("SubsCapsMenuItem",Pn);var On=function(r){function n(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};y(this,n);var i=b(this,r.call(this,t,e));return i.label_="subtitles",-1<["en","en-us","en-ca","fr-ca"].indexOf(i.player_.language_)&&(i.label_="captions"),i.menuButton_.controlText(zt(i.label_)),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-subs-caps-button "+r.prototype.buildCSSClass.call(this)},n.prototype.buildWrapperCSSClass=function(){return"vjs-subs-caps-button "+r.prototype.buildWrapperCSSClass.call(this)},n.prototype.createItems=function(){var t=[];return this.player().tech_&&this.player().tech_.featuresNativeTextTracks||!this.player().getChild("textTrackSettings")||(t.push(new An(this.player_,{kind:this.label_})),this.hideThreshold_+=1),t=r.prototype.createItems.call(this,t,Pn)},n}(Sn);On.prototype.kinds_=["captions","subtitles"],On.prototype.controlText_="Subtitles",Xt.registerComponent("SubsCapsButton",On);var xn=function(a){function o(t,e){y(this,o);var i=e.track,r=t.audioTracks();e.label=i.label||i.language||"Unknown",e.selected=i.enabled;var n=b(this,a.call(this,t,e));n.track=i;var s=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];n.handleTracksChange.apply(n,e)};return r.addEventListener("change",s),n.on("dispose",function(){r.removeEventListener("change",s)}),n}return _(o,a),o.prototype.handleClick=function(t){var e=this.player_.audioTracks();a.prototype.handleClick.call(this,t);for(var i=0;i<e.length;i++){var r=e[i];r.enabled=r===this.track}},o.prototype.handleTracksChange=function(t){this.selected(this.track.enabled)},o}(_n);Xt.registerComponent("AudioTrackMenuItem",xn);var In=function(i){function r(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};return y(this,r),e.tracks=t.audioTracks(),b(this,i.call(this,t,e))}return _(r,i),r.prototype.buildCSSClass=function(){return"vjs-audio-button "+i.prototype.buildCSSClass.call(this)},r.prototype.buildWrapperCSSClass=function(){return"vjs-audio-button "+i.prototype.buildWrapperCSSClass.call(this)},r.prototype.createItems=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];this.hideThreshold_=1;for(var e=this.player_.audioTracks(),i=0;i<e.length;i++){var r=e[i];t.push(new xn(this.player_,{track:r,selectable:!0}))}return t},r}(vn);In.prototype.controlText_="Audio Track",Xt.registerComponent("AudioTrackButton",In);var Dn=function(s){function a(t,e){y(this,a);var i=e.rate,r=parseFloat(i,10);e.label=i,e.selected=1===r,e.selectable=!0;var n=b(this,s.call(this,t,e));return n.label=i,n.rate=r,n.on(t,"ratechange",n.update),n}return _(a,s),a.prototype.handleClick=function(t){s.prototype.handleClick.call(this),this.player().playbackRate(this.rate)},a.prototype.update=function(t){this.selected(this.player().playbackRate()===this.rate)},a}(_n);Dn.prototype.contentElType="button",Xt.registerComponent("PlaybackRateMenuItem",Dn);var Rn=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.updateVisibility(),i.updateLabel(),i.on(t,"loadstart",i.updateVisibility),i.on(t,"ratechange",i.updateLabel),i}return _(n,r),n.prototype.createEl=function(){var t=r.prototype.createEl.call(this);return this.labelEl_=M("div",{className:"vjs-playback-rate-value",innerHTML:"1x"}),t.appendChild(this.labelEl_),t},n.prototype.dispose=function(){this.labelEl_=null,r.prototype.dispose.call(this)},n.prototype.buildCSSClass=function(){return"vjs-playback-rate "+r.prototype.buildCSSClass.call(this)},n.prototype.buildWrapperCSSClass=function(){return"vjs-playback-rate "+r.prototype.buildWrapperCSSClass.call(this)},n.prototype.createMenu=function(){var t=new gn(this.player()),e=this.playbackRates();if(e)for(var i=e.length-1;0<=i;i--)t.addChild(new Dn(this.player(),{rate:e[i]+"x"}));return t},n.prototype.updateARIAAttributes=function(){this.el().setAttribute("aria-valuenow",this.player().playbackRate())},n.prototype.handleClick=function(t){for(var e=this.player().playbackRate(),i=this.playbackRates(),r=i[0],n=0;n<i.length;n++)if(i[n]>e){r=i[n];break}this.player().playbackRate(r)},n.prototype.playbackRates=function(){return this.options_.playbackRates||this.options_.playerOptions&&this.options_.playerOptions.playbackRates},n.prototype.playbackRateSupported=function(){return this.player().tech_&&this.player().tech_.featuresPlaybackRate&&this.playbackRates()&&0<this.playbackRates().length},n.prototype.updateVisibility=function(t){this.playbackRateSupported()?this.removeClass("vjs-hidden"):this.addClass("vjs-hidden")},n.prototype.updateLabel=function(t){this.playbackRateSupported()&&(this.labelEl_.innerHTML=this.player().playbackRate()+"x")},n}(yn);Rn.prototype.controlText_="Playback Rate",Xt.registerComponent("PlaybackRateMenuButton",Rn);var Mn=function(t){function e(){return y(this,e),b(this,t.apply(this,arguments))}return _(e,t),e.prototype.buildCSSClass=function(){return"vjs-spacer "+t.prototype.buildCSSClass.call(this)},e.prototype.createEl=function(){return t.prototype.createEl.call(this,"div",{className:this.buildCSSClass()})},e}(Xt);Xt.registerComponent("Spacer",Mn);var Un=function(e){function t(){return y(this,t),b(this,e.apply(this,arguments))}return _(t,e),t.prototype.buildCSSClass=function(){return"vjs-custom-control-spacer "+e.prototype.buildCSSClass.call(this)},t.prototype.createEl=function(){var t=e.prototype.createEl.call(this,{className:this.buildCSSClass()});return t.innerHTML=" ",t},t}(Mn);Xt.registerComponent("CustomControlSpacer",Un);var Nn=function(t){function e(){return y(this,e),b(this,t.apply(this,arguments))}return _(e,t),e.prototype.createEl=function(){return t.prototype.createEl.call(this,"div",{className:"vjs-control-bar",dir:"ltr"})},e}(Xt);Nn.prototype.options_={children:["playToggle","volumePanel","currentTimeDisplay","timeDivider","durationDisplay","progressControl","liveDisplay","remainingTimeDisplay","customControlSpacer","playbackRateMenuButton","chaptersButton","descriptionsButton","subsCapsButton","audioTrackButton","fullscreenToggle"]},Xt.registerComponent("ControlBar",Nn);var Bn=function(r){function n(t,e){y(this,n);var i=b(this,r.call(this,t,e));return i.on(t,"error",i.open),i}return _(n,r),n.prototype.buildCSSClass=function(){return"vjs-error-display "+r.prototype.buildCSSClass.call(this)},n.prototype.content=function(){var t=this.player().error();return t?this.localize(t.message):""},n}(Ne);Bn.prototype.options_=Gt(Ne.prototype.options_,{pauseOnOpen:!1,fillAlways:!0,temporary:!1,uncloseable:!0}),Xt.registerComponent("ErrorDisplay",Bn);var jn="vjs-text-track-settings",Fn=["#000","Black"],Hn=["#00F","Blue"],Vn=["#0FF","Cyan"],qn=["#0F0","Green"],Wn=["#F0F","Magenta"],zn=["#F00","Red"],Gn=["#FFF","White"],Xn=["#FF0","Yellow"],Yn=["1","Opaque"],$n=["0.5","Semi-Transparent"],Kn=["0","Transparent"],Qn={backgroundColor:{selector:".vjs-bg-color > select",id:"captions-background-color-%s",label:"Color",options:[Fn,Gn,zn,qn,Hn,Xn,Wn,Vn]},backgroundOpacity:{selector:".vjs-bg-opacity > select",id:"captions-background-opacity-%s",label:"Transparency",options:[Yn,$n,Kn]},color:{selector:".vjs-fg-color > select",id:"captions-foreground-color-%s",label:"Color",options:[Gn,Fn,zn,qn,Hn,Xn,Wn,Vn]},edgeStyle:{selector:".vjs-edge-style > select",id:"%s",label:"Text Edge Style",options:[["none","None"],["raised","Raised"],["depressed","Depressed"],["uniform","Uniform"],["dropshadow","Dropshadow"]]},fontFamily:{selector:".vjs-font-family > select",id:"captions-font-family-%s",label:"Font Family",options:[["proportionalSansSerif","Proportional Sans-Serif"],["monospaceSansSerif","Monospace Sans-Serif"],["proportionalSerif","Proportional Serif"],["monospaceSerif","Monospace Serif"],["casual","Casual"],["script","Script"],["small-caps","Small Caps"]]},fontPercent:{selector:".vjs-font-percent > select",id:"captions-font-size-%s",label:"Font Size",options:[["0.50","50%"],["0.75","75%"],["1.00","100%"],["1.25","125%"],["1.50","150%"],["1.75","175%"],["2.00","200%"],["3.00","300%"],["4.00","400%"]],default:2,parser:function(t){return"1.00"===t?null:Number(t)}},textOpacity:{selector:".vjs-text-opacity > select",id:"captions-foreground-opacity-%s",label:"Transparency",options:[Yn,$n]},windowColor:{selector:".vjs-window-color > select",id:"captions-window-color-%s",label:"Color"},windowOpacity:{selector:".vjs-window-opacity > select",id:"captions-window-opacity-%s",label:"Transparency",options:[Kn,$n,Yn]}};function Jn(t,e){if(e&&(t=e(t)),t&&"none"!==t)return t}Qn.windowColor.options=Qn.backgroundColor.options;var Zn=function(r){function n(t,e){y(this,n),e.temporary=!1;var i=b(this,r.call(this,t,e));return i.updateDisplay=Ot(i,i.updateDisplay),i.fill(),i.hasBeenOpened_=i.hasBeenFilled_=!0,i.endDialog=M("p",{className:"vjs-control-text",textContent:i.localize("End of dialog window.")}),i.el().appendChild(i.endDialog),i.setDefaults(),void 0===e.persistTextTrackSettings&&(i.options_.persistTextTrackSettings=i.options_.playerOptions.persistTextTrackSettings),i.on(i.$(".vjs-done-button"),"click",function(){i.saveSettings(),i.close()}),i.on(i.$(".vjs-default-button"),"click",function(){i.setDefaults(),i.updateDisplay()}),k(Qn,function(t){i.on(i.$(t.selector),"change",i.updateDisplay)}),i.options_.persistTextTrackSettings&&i.restoreSettings(),i}return _(n,r),n.prototype.dispose=function(){this.endDialog=null,r.prototype.dispose.call(this)},n.prototype.createElSelect_=function(t){var i=this,e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:"",r=2<arguments.length&&void 0!==arguments[2]?arguments[2]:"label",n=Qn[t],s=n.id.replace("%s",this.id_),a=[e,s].join(" ").trim();return["<"+r+' id="'+s+'" class="'+("label"===r?"vjs-label":"")+'">',this.localize(n.label),"</"+r+">",'<select aria-labelledby="'+a+'">'].concat(n.options.map(function(t){var e=s+"-"+t[1].replace(/\W+/g,"");return['<option id="'+e+'" value="'+t[0]+'" ','aria-labelledby="'+a+" "+e+'">',i.localize(t[1]),"</option>"].join("")})).concat("</select>").join("")},n.prototype.createElFgColor_=function(){var t="captions-text-legend-"+this.id_;return['<fieldset class="vjs-fg-color vjs-track-setting">','<legend id="'+t+'">',this.localize("Text"),"</legend>",this.createElSelect_("color",t),'<span class="vjs-text-opacity vjs-opacity">',this.createElSelect_("textOpacity",t),"</span>","</fieldset>"].join("")},n.prototype.createElBgColor_=function(){var t="captions-background-"+this.id_;return['<fieldset class="vjs-bg-color vjs-track-setting">','<legend id="'+t+'">',this.localize("Background"),"</legend>",this.createElSelect_("backgroundColor",t),'<span class="vjs-bg-opacity vjs-opacity">',this.createElSelect_("backgroundOpacity",t),"</span>","</fieldset>"].join("")},n.prototype.createElWinColor_=function(){var t="captions-window-"+this.id_;return['<fieldset class="vjs-window-color vjs-track-setting">','<legend id="'+t+'">',this.localize("Window"),"</legend>",this.createElSelect_("windowColor",t),'<span class="vjs-window-opacity vjs-opacity">',this.createElSelect_("windowOpacity",t),"</span>","</fieldset>"].join("")},n.prototype.createElColors_=function(){return M("div",{className:"vjs-track-settings-colors",innerHTML:[this.createElFgColor_(),this.createElBgColor_(),this.createElWinColor_()].join("")})},n.prototype.createElFont_=function(){return M("div",{className:"vjs-track-settings-font",innerHTML:['<fieldset class="vjs-font-percent vjs-track-setting">',this.createElSelect_("fontPercent","","legend"),"</fieldset>",'<fieldset class="vjs-edge-style vjs-track-setting">',this.createElSelect_("edgeStyle","","legend"),"</fieldset>",'<fieldset class="vjs-font-family vjs-track-setting">',this.createElSelect_("fontFamily","","legend"),"</fieldset>"].join("")})},n.prototype.createElControls_=function(){var t=this.localize("restore all settings to the default values");return M("div",{className:"vjs-track-settings-controls",innerHTML:['<button class="vjs-default-button" title="'+t+'">',this.localize("Reset"),'<span class="vjs-control-text"> '+t+"</span>","</button>",'<button class="vjs-done-button">'+this.localize("Done")+"</button>"].join("")})},n.prototype.content=function(){return[this.createElColors_(),this.createElFont_(),this.createElControls_()]},n.prototype.label=function(){return this.localize("Caption Settings Dialog")},n.prototype.description=function(){return this.localize("Beginning of dialog window. Escape will cancel and close the window.")},n.prototype.buildCSSClass=function(){return r.prototype.buildCSSClass.call(this)+" vjs-text-track-settings"},n.prototype.getValues=function(){var a=this;return function(i,r){var t=2<arguments.length&&void 0!==arguments[2]?arguments[2]:0;return S(i).reduce(function(t,e){return r(t,i[e],e)},t)}(Qn,function(t,e,i){var r,n,s=(r=a.$(e.selector),n=e.parser,Jn(r.options[r.options.selectedIndex].value,n));return void 0!==s&&(t[i]=s),t},{})},n.prototype.setValues=function(i){var r=this;k(Qn,function(t,e){!function(t,e,i){if(e)for(var r=0;r<t.options.length;r++)if(Jn(t.options[r].value,i)===e){t.selectedIndex=r;break}}(r.$(t.selector),i[e],t.parser)})},n.prototype.setDefaults=function(){var i=this;k(Qn,function(t){var e=t.hasOwnProperty("default")?t.default:0;i.$(t.selector).selectedIndex=e})},n.prototype.restoreSettings=function(){var t=void 0;try{t=JSON.parse(g.localStorage.getItem(jn))}catch(t){f.warn(t)}t&&this.setValues(t)},n.prototype.saveSettings=function(){if(this.options_.persistTextTrackSettings){var t=this.getValues();try{Object.keys(t).length?g.localStorage.setItem(jn,JSON.stringify(t)):g.localStorage.removeItem(jn)}catch(t){f.warn(t)}}},n.prototype.updateDisplay=function(){var t=this.player_.getChild("textTrackDisplay");t&&t.updateDisplay()},n.prototype.conditionalBlur_=function(){this.previouslyActiveEl_=null,this.off(p,"keydown",this.handleKeyDown);var t=this.player_.controlBar,e=t&&t.subsCapsButton,i=t&&t.captionsButton;e?e.focus():i&&i.focus()},n}(Ne);Xt.registerComponent("TextTrackSettings",Zn);var ts=function(s){function a(t,e){y(this,a);var i=e.ResizeObserver||g.ResizeObserver;null===e.ResizeObserver&&(i=!1);var r=Gt({createEl:!i},e),n=b(this,s.call(this,t,r));return n.ResizeObserver=e.ResizeObserver||g.ResizeObserver,n.loadListener_=null,n.resizeObserver_=null,n.debouncedHandler_=It(function(){n.resizeHandler()},100,!1,t),i?(n.resizeObserver_=new n.ResizeObserver(n.debouncedHandler_),n.resizeObserver_.observe(t.el())):(n.loadListener_=function(){n.el_.contentWindow&&_t(n.el_.contentWindow,"resize",n.debouncedHandler_),n.off("load",n.loadListener_)},n.on("load",n.loadListener_)),n}return _(a,s),a.prototype.createEl=function(){return s.prototype.createEl.call(this,"iframe",{className:"vjs-resize-manager"})},a.prototype.resizeHandler=function(){this.player_.trigger("playerresize")},a.prototype.dispose=function(){this.resizeObserver_&&(this.resizeObserver_.unobserve(this.player_.el()),this.resizeObserver_.disconnect()),this.el_&&this.el_.contentWindow&&bt(this.el_.contentWindow,"resize",this.debouncedHandler_),this.loadListener_&&this.off("load",this.loadListener_),this.ResizeObserver=null,this.resizeObserver=null,this.debouncedHandler_=null,this.loadListener_=null},a}(Xt);Xt.registerComponent("ResizeManager",ts);var es=function(t){var e=t.el();if(e.hasAttribute("src"))return t.triggerSourceset(e.src),!0;var i=t.$$("source"),r=[],n="";if(!i.length)return!1;for(var s=0;s<i.length;s++){var a=i[s].src;a&&-1===r.indexOf(a)&&r.push(a)}return!!r.length&&(1===r.length&&(n=r[0]),t.triggerSourceset(n),!0)},is=Object.defineProperty({},"innerHTML",{get:function(){return this.cloneNode(!0).innerHTML},set:function(t){var e=p.createElement(this.nodeName.toLowerCase());e.innerHTML=t;for(var i=p.createDocumentFragment();e.childNodes.length;)i.appendChild(e.childNodes[0]);return this.innerText="",g.Element.prototype.appendChild.call(this,i),this.innerHTML}}),rs=function(t,e){for(var i={},r=0;r<t.length&&!((i=Object.getOwnPropertyDescriptor(t[r],e))&&i.set&&i.get);r++);return i.enumerable=!0,i.configurable=!0,i},ns=function(s){var a=s.el();if(!a.resetSourceWatch_){var e={},t=rs([s.el(),g.HTMLMediaElement.prototype,g.Element.prototype,is],"innerHTML"),i=function(n){return function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];var r=n.apply(a,e);return es(s),r}};["append","appendChild","insertAdjacentHTML"].forEach(function(t){a[t]&&(e[t]=a[t],a[t]=i(e[t]))}),Object.defineProperty(a,"innerHTML",Gt(t,{set:i(t.set)})),a.resetSourceWatch_=function(){a.resetSourceWatch_=null,Object.keys(e).forEach(function(t){a[t]=e[t]}),Object.defineProperty(a,"innerHTML",t)},s.one("sourceset",a.resetSourceWatch_)}},ss=Object.defineProperty({},"src",{get:function(){return this.hasAttribute("src")?Ze(g.Element.prototype.getAttribute.call(this,"src")):""},set:function(t){return g.Element.prototype.setAttribute.call(this,"src",t),t}}),as=function(r){if(r.featuresSourceset){var n=r.el();if(!n.resetSourceset_){var i=rs([r.el(),g.HTMLMediaElement.prototype,ss],"src"),s=n.setAttribute,e=n.load;Object.defineProperty(n,"src",Gt(i,{set:function(t){var e=i.set.call(n,t);return r.triggerSourceset(n.src),e}})),n.setAttribute=function(t,e){var i=s.call(n,t,e);return/src/i.test(t)&&r.triggerSourceset(n.src),i},n.load=function(){var t=e.call(n);return es(r)||(r.triggerSourceset(""),ns(r)),t},n.currentSrc?r.triggerSourceset(n.currentSrc):es(r)||ns(r),n.resetSourceset_=function(){n.resetSourceset_=null,n.load=e,n.setAttribute=s,Object.defineProperty(n,"src",i),n.resetSourceWatch_&&n.resetSourceWatch_()}}}},os=h(["Text Tracks are being loaded from another origin but the crossorigin attribute isn't used.\n This may prevent text tracks from loading."],["Text Tracks are being loaded from another origin but the crossorigin attribute isn't used.\n This may prevent text tracks from loading."]),us=function(c){function h(t,e){y(this,h);var i=b(this,c.call(this,t,e)),r=t.source,n=!1;if(r&&(i.el_.currentSrc!==r.src||t.tag&&3===t.tag.initNetworkState_)?i.setSource(r):i.handleLateInit_(i.el_),t.enableSourceset&&i.setupSourcesetHandling_(),i.el_.hasChildNodes()){for(var s=i.el_.childNodes,a=s.length,o=[];a--;){var u=s[a];"track"===u.nodeName.toLowerCase()&&(i.featuresNativeTextTracks?(i.remoteTextTrackEls().addTrackElement_(u),i.remoteTextTracks().addTrack(u.track),i.textTracks().addTrack(u.track),n||i.el_.hasAttribute("crossorigin")||!ei(u.src)||(n=!0)):o.push(u))}for(var l=0;l<o.length;l++)i.el_.removeChild(o[l])}return i.proxyNativeTracks_(),i.featuresNativeTextTracks&&n&&f.warn(m(os)),i.restoreMetadataTracksInIOSNativePlayer_(),(ge||ie||ue)&&!0===t.nativeControlsForTouch&&i.setControls(!0),i.proxyWebkitFullscreen_(),i.triggerReady(),i}return _(h,c),h.prototype.dispose=function(){this.el_.resetSourceset_&&this.el_.resetSourceset_(),h.disposeMediaElement(this.el_),this.options_=null,c.prototype.dispose.call(this)},h.prototype.setupSourcesetHandling_=function(){as(this)},h.prototype.restoreMetadataTracksInIOSNativePlayer_=function(){var r=this.textTracks(),n=void 0,t=function(){n=[];for(var t=0;t<r.length;t++){var e=r[t];"metadata"===e.kind&&n.push({track:e,storedMode:e.mode})}};t(),r.addEventListener("change",t),this.on("dispose",function(){return r.removeEventListener("change",t)});var e=function t(){for(var e=0;e<n.length;e++){var i=n[e];"disabled"===i.track.mode&&i.track.mode!==i.storedMode&&(i.track.mode=i.storedMode)}r.removeEventListener("change",t)};this.on("webkitbeginfullscreen",function(){r.removeEventListener("change",t),r.removeEventListener("change",e),r.addEventListener("change",e)}),this.on("webkitendfullscreen",function(){r.removeEventListener("change",t),r.addEventListener("change",t),r.removeEventListener("change",e)})},h.prototype.overrideNative_=function(t,e){var i=this;if(e===this["featuresNative"+t+"Tracks"]){var r=t.toLowerCase();this[r+"TracksListeners_"]&&Object.keys(this[r+"TracksListeners_"]).forEach(function(t){i.el()[r+"Tracks"].removeEventListener(t,i[r+"TracksListeners_"][t])}),this["featuresNative"+t+"Tracks"]=!e,this[r+"TracksListeners_"]=null,this.proxyNativeTracksForType_(r)}},h.prototype.overrideNativeAudioTracks=function(t){this.overrideNative_("Audio",t)},h.prototype.overrideNativeVideoTracks=function(t){this.overrideNative_("Video",t)},h.prototype.proxyNativeTracksForType_=function(t){var r=this,e=Ui[t],n=this.el()[e.getterName],s=this[e.getterName]();if(this["featuresNative"+e.capitalName+"Tracks"]&&n&&n.addEventListener){var a={change:function(t){s.trigger({type:"change",target:s,currentTarget:s,srcElement:s})},addtrack:function(t){s.addTrack(t.track)},removetrack:function(t){s.removeTrack(t.track)}},i=function(){for(var t=[],e=0;e<s.length;e++){for(var i=!1,r=0;r<n.length;r++)if(n[r]===s[e]){i=!0;break}i||t.push(s[e])}for(;t.length;)s.removeTrack(t.shift())};this[e.getterName+"Listeners_"]=a,Object.keys(a).forEach(function(e){var i=a[e];n.addEventListener(e,i),r.on("dispose",function(t){return n.removeEventListener(e,i)})}),this.on("loadstart",i),this.on("dispose",function(t){return r.off("loadstart",i)})}},h.prototype.proxyNativeTracks_=function(){var e=this;Ui.names.forEach(function(t){e.proxyNativeTracksForType_(t)})},h.prototype.createEl=function(){var t=this.options_.tag;if(!t||!this.options_.playerElIngest&&!this.movingMediaElementInDOM){if(t){var e=t.cloneNode(!0);t.parentNode&&t.parentNode.insertBefore(e,t),h.disposeMediaElement(t),t=e}else{t=p.createElement("video");var i=Gt({},this.options_.tag&&q(this.options_.tag));ge&&!0===this.options_.nativeControlsForTouch||delete i.controls,V(t,C(i,{id:this.options_.techId,class:"vjs-tech"}))}t.playerId=this.options_.playerId}"undefined"!=typeof this.options_.preload&&z(t,"preload",this.options_.preload);for(var r=["loop","muted","playsinline","autoplay"],n=0;n<r.length;n++){var s=r[n],a=this.options_[s];"undefined"!=typeof a&&(a?z(t,s,s):G(t,s),t[s]=a)}return t},h.prototype.handleLateInit_=function(t){if(0!==t.networkState&&3!==t.networkState){if(0===t.readyState){var e=!1,i=function(){e=!0};this.on("loadstart",i);var r=function(){e||this.trigger("loadstart")};return this.on("loadedmetadata",r),void this.ready(function(){this.off("loadstart",i),this.off("loadedmetadata",r),e||this.trigger("loadstart")})}var n=["loadstart"];n.push("loadedmetadata"),2<=t.readyState&&n.push("loadeddata"),3<=t.readyState&&n.push("canplay"),4<=t.readyState&&n.push("canplaythrough"),this.ready(function(){n.forEach(function(t){this.trigger(t)},this)})}},h.prototype.setCurrentTime=function(t){try{this.el_.currentTime=t}catch(t){f(t,"Video is not ready. (Video.js)")}},h.prototype.duration=function(){var e=this;if(this.el_.duration===1/0&&ae&&he&&0===this.el_.currentTime){return this.on("timeupdate",function t(){0<e.el_.currentTime&&(e.el_.duration===1/0&&e.trigger("durationchange"),e.off("timeupdate",t))}),NaN}return this.el_.duration||NaN},h.prototype.width=function(){return this.el_.offsetWidth},h.prototype.height=function(){return this.el_.offsetHeight},h.prototype.proxyWebkitFullscreen_=function(){var t=this;if("webkitDisplayingFullscreen"in this.el_){var e=function(){this.trigger("fullscreenchange",{isFullscreen:!1})},i=function(){"webkitPresentationMode"in this.el_&&"picture-in-picture"!==this.el_.webkitPresentationMode&&(this.one("webkitendfullscreen",e),this.trigger("fullscreenchange",{isFullscreen:!0}))};this.on("webkitbeginfullscreen",i),this.on("dispose",function(){t.off("webkitbeginfullscreen",i),t.off("webkitendfullscreen",e)})}},h.prototype.supportsFullScreen=function(){if("function"==typeof this.el_.webkitEnterFullScreen){var t=g.navigator&&g.navigator.userAgent||"";if(/Android/.test(t)||!/Chrome|Mac OS X 10.5/.test(t))return!0}return!1},h.prototype.enterFullScreen=function(){var t=this.el_;t.paused&&t.networkState<=t.HAVE_METADATA?(this.el_.play(),this.setTimeout(function(){t.pause(),t.webkitEnterFullScreen()},0)):t.webkitEnterFullScreen()},h.prototype.exitFullScreen=function(){this.el_.webkitExitFullScreen()},h.prototype.src=function(t){if(void 0===t)return this.el_.src;this.setSrc(t)},h.prototype.reset=function(){h.resetMediaElement(this.el_)},h.prototype.currentSrc=function(){return this.currentSource_?this.currentSource_.src:this.el_.currentSrc},h.prototype.setControls=function(t){this.el_.controls=!!t},h.prototype.addTextTrack=function(t,e,i){return this.featuresNativeTextTracks?this.el_.addTextTrack(t,e,i):c.prototype.addTextTrack.call(this,t,e,i)},h.prototype.createRemoteTextTrack=function(t){if(!this.featuresNativeTextTracks)return c.prototype.createRemoteTextTrack.call(this,t);var e=p.createElement("track");return t.kind&&(e.kind=t.kind),t.label&&(e.label=t.label),(t.language||t.srclang)&&(e.srclang=t.language||t.srclang),t.default&&(e.default=t.default),t.id&&(e.id=t.id),t.src&&(e.src=t.src),e},h.prototype.addRemoteTextTrack=function(t,e){var i=c.prototype.addRemoteTextTrack.call(this,t,e);return this.featuresNativeTextTracks&&this.el().appendChild(i),i},h.prototype.removeRemoteTextTrack=function(t){if(c.prototype.removeRemoteTextTrack.call(this,t),this.featuresNativeTextTracks)for(var e=this.$$("track"),i=e.length;i--;)t!==e[i]&&t!==e[i].track||this.el().removeChild(e[i])},h.prototype.getVideoPlaybackQuality=function(){if("function"==typeof this.el().getVideoPlaybackQuality)return this.el().getVideoPlaybackQuality();var t={};return"undefined"!=typeof this.el().webkitDroppedFrameCount&&"undefined"!=typeof this.el().webkitDecodedFrameCount&&(t.droppedVideoFrames=this.el().webkitDroppedFrameCount,t.totalVideoFrames=this.el().webkitDecodedFrameCount),g.performance&&"function"==typeof g.performance.now?t.creationTime=g.performance.now():g.performance&&g.performance.timing&&"number"==typeof g.performance.timing.navigationStart&&(t.creationTime=g.Date.now()-g.performance.timing.navigationStart),t},h}(br);if(x()){us.TEST_VID=p.createElement("video");var ls=p.createElement("track");ls.kind="captions",ls.srclang="en",ls.label="English",us.TEST_VID.appendChild(ls)}us.isSupported=function(){try{us.TEST_VID.volume=.5}catch(t){return!1}return!(!us.TEST_VID||!us.TEST_VID.canPlayType)},us.canPlayType=function(t){return us.TEST_VID.canPlayType(t)},us.canPlaySource=function(t,e){return us.canPlayType(t.type)},us.canControlVolume=function(){try{var t=us.TEST_VID.volume;return us.TEST_VID.volume=t/2+.1,t!==us.TEST_VID.volume}catch(t){return!1}},us.canControlPlaybackRate=function(){if(ae&&he&&de<58)return!1;try{var t=us.TEST_VID.playbackRate;return us.TEST_VID.playbackRate=t/2+.1,t!==us.TEST_VID.playbackRate}catch(t){return!1}},us.canOverrideAttributes=function(){try{var t=function(){};Object.defineProperty(p.createElement("video"),"src",{get:t,set:t}),Object.defineProperty(p.createElement("audio"),"src",{get:t,set:t}),Object.defineProperty(p.createElement("video"),"innerHTML",{get:t,set:t}),Object.defineProperty(p.createElement("audio"),"innerHTML",{get:t,set:t})}catch(t){return!1}return!0},us.supportsNativeTextTracks=function(){return me},us.supportsNativeVideoTracks=function(){return!(!us.TEST_VID||!us.TEST_VID.videoTracks)},us.supportsNativeAudioTracks=function(){return!(!us.TEST_VID||!us.TEST_VID.audioTracks)},us.Events=["loadstart","suspend","abort","error","emptied","stalled","loadedmetadata","loadeddata","canplay","canplaythrough","playing","waiting","seeking","seeked","ended","durationchange","timeupdate","progress","play","pause","ratechange","resize","volumechange"],us.prototype.featuresVolumeControl=us.canControlVolume(),us.prototype.featuresPlaybackRate=us.canControlPlaybackRate(),us.prototype.featuresSourceset=us.canOverrideAttributes(),us.prototype.movingMediaElementInDOM=!ne,us.prototype.featuresFullscreenResize=!0,us.prototype.featuresProgressEvents=!0,us.prototype.featuresTimeupdateEvents=!0,us.prototype.featuresNativeTextTracks=us.supportsNativeTextTracks(),us.prototype.featuresNativeVideoTracks=us.supportsNativeVideoTracks(),us.prototype.featuresNativeAudioTracks=us.supportsNativeAudioTracks();var cs=us.TEST_VID&&us.TEST_VID.constructor.prototype.canPlayType,hs=/^application\/(?:x-|vnd\.apple\.)mpegurl/i;us.patchCanPlayType=function(){4<=oe&&!le&&!he&&(us.TEST_VID.constructor.prototype.canPlayType=function(t){return t&&hs.test(t)?"maybe":cs.call(this,t)})},us.unpatchCanPlayType=function(){var t=us.TEST_VID.constructor.prototype.canPlayType;return us.TEST_VID.constructor.prototype.canPlayType=cs,t},us.patchCanPlayType(),us.disposeMediaElement=function(t){if(t){for(t.parentNode&&t.parentNode.removeChild(t);t.hasChildNodes();)t.removeChild(t.firstChild);t.removeAttribute("src"),"function"==typeof t.load&&function(){try{t.load()}catch(t){}}()}},us.resetMediaElement=function(t){if(t){for(var e=t.querySelectorAll("source"),i=e.length;i--;)t.removeChild(e[i]);t.removeAttribute("src"),"function"==typeof t.load&&function(){try{t.load()}catch(t){}}()}},["muted","defaultMuted","autoplay","controls","loop","playsinline"].forEach(function(t){us.prototype[t]=function(){return this.el_[t]||this.el_.hasAttribute(t)}}),["muted","defaultMuted","autoplay","loop","playsinline"].forEach(function(e){us.prototype["set"+zt(e)]=function(t){(this.el_[e]=t)?this.el_.setAttribute(e,e):this.el_.removeAttribute(e)}}),["paused","currentTime","buffered","volume","poster","preload","error","seeking","seekable","ended","playbackRate","defaultPlaybackRate","played","networkState","readyState","videoWidth","videoHeight"].forEach(function(t){us.prototype[t]=function(){return this.el_[t]}}),["volume","src","poster","preload","playbackRate","defaultPlaybackRate"].forEach(function(e){us.prototype["set"+zt(e)]=function(t){this.el_[e]=t}}),["pause","load","play"].forEach(function(t){us.prototype[t]=function(){return this.el_[t]()}}),br.withSourceHandlers(us),us.nativeSourceHandler={},us.nativeSourceHandler.canPlayType=function(t){try{return us.TEST_VID.canPlayType(t)}catch(t){return""}},us.nativeSourceHandler.canHandleSource=function(t,e){if(t.type)return us.nativeSourceHandler.canPlayType(t.type);if(t.src){var i=ti(t.src);return us.nativeSourceHandler.canPlayType("video/"+i)}return""},us.nativeSourceHandler.handleSource=function(t,e,i){e.setSrc(t.src)},us.nativeSourceHandler.dispose=function(){},us.registerSourceHandler(us.nativeSourceHandler),br.registerTech("Html5",us);var ds=h(["\n Using the tech directly can be dangerous. I hope you know what you're doing.\n See https://github.com/videojs/video.js/issues/2617 for more info.\n "],["\n Using the tech directly can be dangerous. I hope you know what you're doing.\n See https://github.com/videojs/video.js/issues/2617 for more info.\n "]),ps=["progress","abort","suspend","emptied","stalled","loadedmetadata","loadeddata","timeupdate","resize","volumechange","texttrackchange"],fs={canplay:"CanPlay",canplaythrough:"CanPlayThrough",playing:"Playing",seeked:"Seeked"},ms=function(c){function h(t,e,i){if(y(this,h),t.id=t.id||e.id||"vjs_video_"+ut(),(e=C(h.getTagSettings(t),e)).initChildren=!1,e.createEl=!1,e.evented=!1,e.reportTouchActivity=!1,!e.language)if("function"==typeof t.closest){var r=t.closest("[lang]");r&&r.getAttribute&&(e.language=r.getAttribute("lang"))}else for(var n=t;n&&1===n.nodeType;){if(q(n).hasOwnProperty("lang")){e.language=n.getAttribute("lang");break}n=n.parentNode}var s=b(this,c.call(this,null,e,i));if(s.isPosterFromTech_=!1,s.queuedCallbacks_=[],s.isReady_=!1,s.hasStarted_=!1,s.userActive_=!1,!s.options_||!s.options_.techOrder||!s.options_.techOrder.length)throw new Error("No techOrder specified. Did you overwrite videojs.options instead of just changing the properties you want to override?");if(s.tag=t,s.tagAttributes=t&&q(t),s.language(s.options_.language),e.languages){var a={};Object.getOwnPropertyNames(e.languages).forEach(function(t){a[t.toLowerCase()]=e.languages[t]}),s.languages_=a}else s.languages_=h.prototype.options_.languages;s.cache_={},s.poster_=e.poster||"",s.controls_=!!e.controls,s.cache_.lastVolume=1,t.controls=!1,t.removeAttribute("controls"),s.scrubbing_=!1,s.el_=s.createEl(),s.cache_.lastPlaybackRate=s.defaultPlaybackRate(),Vt(s,{eventBusKey:"el_"});var o=Gt(s.options_);if(e.plugins){var u=e.plugins;Object.keys(u).forEach(function(t){if("function"!=typeof this[t])throw new Error('plugin "'+t+'" does not exist');this[t](u[t])},s)}s.options_.playerOptions=o,s.middleware_=[],s.initChildren(),s.isAudio("audio"===t.nodeName.toLowerCase()),s.controls()?s.addClass("vjs-controls-enabled"):s.addClass("vjs-controls-disabled"),s.el_.setAttribute("role","region"),s.isAudio()?s.el_.setAttribute("aria-label",s.localize("Audio Player")):s.el_.setAttribute("aria-label",s.localize("Video Player")),s.isAudio()&&s.addClass("vjs-audio"),s.flexNotSupported_()&&s.addClass("vjs-no-flex"),ne||s.addClass("vjs-workinghover"),h.players[s.id_]=s;var l=d.split(".")[0];return s.addClass("vjs-v"+l),s.userActive(!0),s.reportUserActivity(),s.one("play",s.listenForUserActivity_),s.on("fullscreenchange",s.handleFullscreenChange_),s.on("stageclick",s.handleStageClick_),s.changingSrc_=!1,s.playWaitingForReady_=!1,s.playOnLoadstart_=null,s}return _(h,c),h.prototype.dispose=function(){this.trigger("dispose"),this.off("dispose"),this.styleEl_&&this.styleEl_.parentNode&&(this.styleEl_.parentNode.removeChild(this.styleEl_),this.styleEl_=null),h.players[this.id_]=null,this.tag&&this.tag.player&&(this.tag.player=null),this.el_&&this.el_.player&&(this.el_.player=null),this.tech_&&(this.tech_.dispose(),this.isPosterFromTech_=!1,this.poster_=""),this.playerElIngest_&&(this.playerElIngest_=null),this.tag&&(this.tag=null),Sr[this.id()]=null,c.prototype.dispose.call(this)},h.prototype.createEl=function(){var e=this.tag,i=void 0,t=this.playerElIngest_=e.parentNode&&e.parentNode.hasAttribute&&e.parentNode.hasAttribute("data-vjs-player"),r="video-js"===this.tag.tagName.toLowerCase();t?i=this.el_=e.parentNode:r||(i=this.el_=c.prototype.createEl.call(this,"div"));var n=q(e);if(r){for(i=this.el_=e,e=this.tag=p.createElement("video");i.children.length;)e.appendChild(i.firstChild);B(i,"video-js")||j(i,"video-js"),i.appendChild(e),t=this.playerElIngest_=i,Object.keys(i).forEach(function(t){e[t]=i[t]})}if(e.setAttribute("tabindex","-1"),e.removeAttribute("width"),e.removeAttribute("height"),Object.getOwnPropertyNames(n).forEach(function(t){i.setAttribute(t,n[t]),r&&e.setAttribute(t,n[t])}),e.playerId=e.id,e.id+="_html5_api",e.className="vjs-tech",e.player=i.player=this,this.addClass("vjs-paused"),!0!==g.VIDEOJS_NO_DYNAMIC_STYLE){this.styleEl_=Lt("vjs-styles-dimensions");var s=nt(".vjs-styles-defaults"),a=nt("head");a.insertBefore(this.styleEl_,s?s.nextSibling:a.firstChild)}this.width(this.options_.width),this.height(this.options_.height),this.fluid(this.options_.fluid),this.aspectRatio(this.options_.aspectRatio);for(var o=e.getElementsByTagName("a"),u=0;u<o.length;u++){var l=o.item(u);j(l,"vjs-hidden"),l.setAttribute("hidden","hidden")}return e.initNetworkState_=e.networkState,e.parentNode&&!t&&e.parentNode.insertBefore(i,e),N(e,i),this.children_.unshift(e),this.el_.setAttribute("lang",this.language_),this.el_=i},h.prototype.width=function(t){return this.dimension("width",t)},h.prototype.height=function(t){return this.dimension("height",t)},h.prototype.dimension=function(t,e){var i=t+"_";if(void 0===e)return this[i]||0;if(""===e)return this[i]=void 0,void this.updateStyleEl_();var r=parseFloat(e);isNaN(r)?f.error('Improper value "'+e+'" supplied for for '+t):(this[i]=r,this.updateStyleEl_())},h.prototype.fluid=function(t){if(void 0===t)return!!this.fluid_;this.fluid_=!!t,t?this.addClass("vjs-fluid"):this.removeClass("vjs-fluid"),this.updateStyleEl_()},h.prototype.aspectRatio=function(t){if(void 0===t)return this.aspectRatio_;if(!/^\d+\:\d+$/.test(t))throw new Error("Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.");this.aspectRatio_=t,this.fluid(!0),this.updateStyleEl_()},h.prototype.updateStyleEl_=function(){if(!0!==g.VIDEOJS_NO_DYNAMIC_STYLE){var t=void 0,e=void 0,i=void 0,r=(void 0!==this.aspectRatio_&&"auto"!==this.aspectRatio_?this.aspectRatio_:0<this.videoWidth()?this.videoWidth()+":"+this.videoHeight():"16:9").split(":"),n=r[1]/r[0];t=void 0!==this.width_?this.width_:void 0!==this.height_?this.height_/n:this.videoWidth()||300,e=void 0!==this.height_?this.height_:t*n,i=/^[^a-zA-Z]/.test(this.id())?"dimensions-"+this.id():this.id()+"-dimensions",this.addClass(i),Pt(this.styleEl_,"\n ."+i+" {\n width: "+t+"px;\n height: "+e+"px;\n }\n\n ."+i+".vjs-fluid {\n padding-top: "+100*n+"%;\n }\n ")}else{var s="number"==typeof this.width_?this.width_:this.options_.width,a="number"==typeof this.height_?this.height_:this.options_.height,o=this.tech_&&this.tech_.el();o&&(0<=s&&(o.width=s),0<=a&&(o.height=a))}},h.prototype.loadTech_=function(t,e){var i=this;this.tech_&&this.unloadTech_();var r=zt(t),n=t.charAt(0).toLowerCase()+t.slice(1);"Html5"!==r&&this.tag&&(br.getTech("Html5").disposeMediaElement(this.tag),this.tag.player=null,this.tag=null),this.techName_=r,this.isReady_=!1;var s={source:e,nativeControlsForTouch:this.options_.nativeControlsForTouch,playerId:this.id(),techId:this.id()+"_"+r+"_api",autoplay:this.options_.autoplay,playsinline:this.options_.playsinline,preload:this.options_.preload,loop:this.options_.loop,muted:this.options_.muted,poster:this.poster(),language:this.language(),playerElIngest:this.playerElIngest_||!1,"vtt.js":this.options_["vtt.js"],canOverridePoster:!!this.options_.techCanOverridePoster,enableSourceset:this.options_.enableSourceset};Bi.names.forEach(function(t){var e=Bi[t];s[e.getterName]=i[e.privateName]}),C(s,this.options_[r]),C(s,this.options_[n]),C(s,this.options_[t.toLowerCase()]),this.tag&&(s.tag=this.tag),e&&e.src===this.cache_.src&&0<this.cache_.currentTime&&(s.startTime=this.cache_.currentTime);var a=br.getTech(t);if(!a)throw new Error("No Tech named '"+r+"' exists! '"+r+"' should be registered using videojs.registerTech()'");this.tech_=new a(s),this.tech_.ready(Ot(this,this.handleTechReady_),!0),Me(this.textTracksJson_||[],this.tech_),ps.forEach(function(t){i.on(i.tech_,t,i["handleTech"+zt(t)+"_"])}),Object.keys(fs).forEach(function(e){i.on(i.tech_,e,function(t){0===i.tech_.playbackRate()&&i.tech_.seeking()?i.queuedCallbacks_.push({callback:i["handleTech"+fs[e]+"_"].bind(i),event:t}):i["handleTech"+fs[e]+"_"](t)})}),this.on(this.tech_,"loadstart",this.handleTechLoadStart_),this.on(this.tech_,"sourceset",this.handleTechSourceset_),this.on(this.tech_,"waiting",this.handleTechWaiting_),this.on(this.tech_,"ended",this.handleTechEnded_),this.on(this.tech_,"seeking",this.handleTechSeeking_),this.on(this.tech_,"play",this.handleTechPlay_),this.on(this.tech_,"firstplay",this.handleTechFirstPlay_),this.on(this.tech_,"pause",this.handleTechPause_),this.on(this.tech_,"durationchange",this.handleTechDurationChange_),this.on(this.tech_,"fullscreenchange",this.handleTechFullscreenChange_),this.on(this.tech_,"error",this.handleTechError_),this.on(this.tech_,"loadedmetadata",this.updateStyleEl_),this.on(this.tech_,"posterchange",this.handleTechPosterChange_),this.on(this.tech_,"textdata",this.handleTechTextData_),this.on(this.tech_,"ratechange",this.handleTechRateChange_),this.usingNativeControls(this.techGet_("controls")),this.controls()&&!this.usingNativeControls()&&this.addTechControlsListeners_(),this.tech_.el().parentNode===this.el()||"Html5"===r&&this.tag||N(this.tech_.el(),this.el()),this.tag&&(this.tag.player=null,this.tag=null)},h.prototype.unloadTech_=function(){var i=this;Bi.names.forEach(function(t){var e=Bi[t];i[e.privateName]=i[e.getterName]()}),this.textTracksJson_=Re(this.tech_),this.isReady_=!1,this.tech_.dispose(),this.tech_=!1,this.isPosterFromTech_&&(this.poster_="",this.trigger("posterchange")),this.isPosterFromTech_=!1},h.prototype.tech=function(t){return void 0===t&&f.warn(m(ds)),this.tech_},h.prototype.addTechControlsListeners_=function(){this.removeTechControlsListeners_(),this.on(this.tech_,"mousedown",this.handleTechClick_),this.on(this.tech_,"touchstart",this.handleTechTouchStart_),this.on(this.tech_,"touchmove",this.handleTechTouchMove_),this.on(this.tech_,"touchend",this.handleTechTouchEnd_),this.on(this.tech_,"tap",this.handleTechTap_)},h.prototype.removeTechControlsListeners_=function(){this.off(this.tech_,"tap",this.handleTechTap_),this.off(this.tech_,"touchstart",this.handleTechTouchStart_),this.off(this.tech_,"touchmove",this.handleTechTouchMove_),this.off(this.tech_,"touchend",this.handleTechTouchEnd_),this.off(this.tech_,"mousedown",this.handleTechClick_)},h.prototype.handleTechReady_=function(){if(this.triggerReady(),this.cache_.volume&&this.techCall_("setVolume",this.cache_.volume),this.handleTechPosterChange_(),this.handleTechDurationChange_(),(this.src()||this.currentSrc())&&this.tag&&this.options_.autoplay&&this.paused())try{delete this.tag.poster}catch(t){f("deleting tag.poster throws in some browsers",t)}},h.prototype.handleTechLoadStart_=function(){this.removeClass("vjs-ended"),this.removeClass("vjs-seeking"),this.error(null),this.paused()?(this.hasStarted(!1),this.trigger("loadstart")):(this.trigger("loadstart"),this.trigger("firstplay"))},h.prototype.updateSourceCaches_=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",e=t,i="";"string"!=typeof e&&(e=t.src,i=t.type),this.cache_.source=this.cache_.source||{},this.cache_.sources=this.cache_.sources||[],e&&!i&&(i=function(t,e){if(!e)return"";if(t.cache_.source.src===e&&t.cache_.source.type)return t.cache_.source.type;var i=t.cache_.sources.filter(function(t){return t.src===e});if(i.length)return i[0].type;for(var r=t.$$("source"),n=0;n<r.length;n++){var s=r[n];if(s.type&&s.src&&s.src===e)return s.type}return xr(e)}(this,e)),this.cache_.source={src:e,type:i};for(var r=this.cache_.sources.filter(function(t){return t.src&&t.src===e}),n=[],s=this.$$("source"),a=[],o=0;o<s.length;o++){var u=q(s[o]);n.push(u),u.src&&u.src===e&&a.push(u.src)}a.length&&!r.length?this.cache_.sources=n:r.length||(this.cache_.sources=[this.cache_.source]),this.cache_.src=e},h.prototype.handleTechSourceset_=function(t){var i=this;if(!this.changingSrc_&&(this.updateSourceCaches_(t.src),!t.src)){this.tech_.one(["sourceset","loadstart"],function t(e){"sourceset"!==e.type&&i.updateSourceCaches_(i.techGet_("currentSrc")),i.tech_.off(["sourceset","loadstart"],t)})}this.trigger({src:t.src,type:"sourceset"})},h.prototype.hasStarted=function(t){if(void 0===t)return this.hasStarted_;t!==this.hasStarted_&&(this.hasStarted_=t,this.hasStarted_?(this.addClass("vjs-has-started"),this.trigger("firstplay")):this.removeClass("vjs-has-started"))},h.prototype.handleTechPlay_=function(){this.removeClass("vjs-ended"),this.removeClass("vjs-paused"),this.addClass("vjs-playing"),this.hasStarted(!0),this.trigger("play")},h.prototype.handleTechRateChange_=function(){0<this.tech_.playbackRate()&&0===this.cache_.lastPlaybackRate&&(this.queuedCallbacks_.forEach(function(t){return t.callback(t.event)}),this.queuedCallbacks_=[]),this.cache_.lastPlaybackRate=this.tech_.playbackRate(),this.trigger("ratechange")},h.prototype.handleTechWaiting_=function(){var t=this;this.addClass("vjs-waiting"),this.trigger("waiting"),this.one("timeupdate",function(){return t.removeClass("vjs-waiting")})},h.prototype.handleTechCanPlay_=function(){this.removeClass("vjs-waiting"),this.trigger("canplay")},h.prototype.handleTechCanPlayThrough_=function(){this.removeClass("vjs-waiting"),this.trigger("canplaythrough")},h.prototype.handleTechPlaying_=function(){this.removeClass("vjs-waiting"),this.trigger("playing")},h.prototype.handleTechSeeking_=function(){this.addClass("vjs-seeking"),this.trigger("seeking")},h.prototype.handleTechSeeked_=function(){this.removeClass("vjs-seeking"),this.trigger("seeked")},h.prototype.handleTechFirstPlay_=function(){this.options_.starttime&&(f.warn("Passing the `starttime` option to the player will be deprecated in 6.0"),this.currentTime(this.options_.starttime)),this.addClass("vjs-has-started"),this.trigger("firstplay")},h.prototype.handleTechPause_=function(){this.removeClass("vjs-playing"),this.addClass("vjs-paused"),this.trigger("pause")},h.prototype.handleTechEnded_=function(){this.addClass("vjs-ended"),this.options_.loop?(this.currentTime(0),this.play()):this.paused()||this.pause(),this.trigger("ended")},h.prototype.handleTechDurationChange_=function(){this.duration(this.techGet_("duration"))},h.prototype.handleTechClick_=function(t){rt(t)&&this.controls_&&(this.paused()?this.play():this.pause())},h.prototype.handleTechTap_=function(){this.userActive(!this.userActive())},h.prototype.handleTechTouchStart_=function(){this.userWasActive=this.userActive()},h.prototype.handleTechTouchMove_=function(){this.userWasActive&&this.reportUserActivity()},h.prototype.handleTechTouchEnd_=function(t){t.preventDefault()},h.prototype.handleFullscreenChange_=function(){this.isFullscreen()?this.addClass("vjs-fullscreen"):this.removeClass("vjs-fullscreen")},h.prototype.handleStageClick_=function(){this.reportUserActivity()},h.prototype.handleTechFullscreenChange_=function(t,e){e&&this.isFullscreen(e.isFullscreen),this.trigger("fullscreenchange")},h.prototype.handleTechError_=function(){var t=this.tech_.error();this.error(t)},h.prototype.handleTechTextData_=function(){var t=null;1<arguments.length&&(t=arguments[1]),this.trigger("textdata",t)},h.prototype.getCache=function(){return this.cache_},h.prototype.techCall_=function(n,s){this.ready(function(){if(n in Ar)return t=this.middleware_,e=this.tech_,r=s,e[i=n](t.reduce(Pr(i),r));if(n in Lr)return Er(this.middleware_,this.tech_,n,s);var t,e,i,r;try{this.tech_&&this.tech_[n](s)}catch(t){throw f(t),t}},!0)},h.prototype.techGet_=function(e){if(this.tech_&&this.tech_.isReady_){if(e in wr)return t=this.middleware_,i=this.tech_,r=e,t.reduceRight(Pr(r),i[r]());if(e in Lr)return Er(this.middleware_,this.tech_,e);var t,i,r;try{return this.tech_[e]()}catch(t){if(void 0===this.tech_[e])throw f("Video.js: "+e+" method not defined for "+this.techName_+" playback technology.",t),t;if("TypeError"===t.name)throw f("Video.js: "+e+" unavailable on "+this.techName_+" playback technology element.",t),this.tech_.isReady_=!1,t;throw f(t),t}}},h.prototype.play=function(){var t=this;if(this.playOnLoadstart_&&this.off("loadstart",this.playOnLoadstart_),this.isReady_){if(!this.changingSrc_&&(this.src()||this.currentSrc()))return this.techGet_("play");this.playOnLoadstart_=function(){t.playOnLoadstart_=null,Ie(t.play())},this.one("loadstart",this.playOnLoadstart_)}else{if(this.playWaitingForReady_)return;this.playWaitingForReady_=!0,this.ready(function(){t.playWaitingForReady_=!1,Ie(t.play())})}},h.prototype.pause=function(){this.techCall_("pause")},h.prototype.paused=function(){return!1!==this.techGet_("paused")},h.prototype.played=function(){return this.techGet_("played")||be(0,0)},h.prototype.scrubbing=function(t){if("undefined"==typeof t)return this.scrubbing_;this.scrubbing_=!!t,t?this.addClass("vjs-scrubbing"):this.removeClass("vjs-scrubbing")},h.prototype.currentTime=function(t){return"undefined"!=typeof t?(t<0&&(t=0),void this.techCall_("setCurrentTime",t)):(this.cache_.currentTime=this.techGet_("currentTime")||0,this.cache_.currentTime)},h.prototype.duration=function(t){if(void 0===t)return void 0!==this.cache_.duration?this.cache_.duration:NaN;(t=parseFloat(t))<0&&(t=1/0),t!==this.cache_.duration&&((this.cache_.duration=t)===1/0?this.addClass("vjs-live"):this.removeClass("vjs-live"),this.trigger("durationchange"))},h.prototype.remainingTime=function(){return this.duration()-this.currentTime()},h.prototype.remainingTimeDisplay=function(){return Math.floor(this.duration())-Math.floor(this.currentTime())},h.prototype.buffered=function(){var t=this.techGet_("buffered");return t&&t.length||(t=be(0,0)),t},h.prototype.bufferedPercent=function(){return Te(this.buffered(),this.duration())},h.prototype.bufferedEnd=function(){var t=this.buffered(),e=this.duration(),i=t.end(t.length-1);return e<i&&(i=e),i},h.prototype.volume=function(t){var e=void 0;return void 0!==t?(e=Math.max(0,Math.min(1,parseFloat(t))),this.cache_.volume=e,this.techCall_("setVolume",e),void(0<e&&this.lastVolume_(e))):(e=parseFloat(this.techGet_("volume")),isNaN(e)?1:e)},h.prototype.muted=function(t){if(void 0===t)return this.techGet_("muted")||!1;this.techCall_("setMuted",t)},h.prototype.defaultMuted=function(t){return void 0!==t?this.techCall_("setDefaultMuted",t):this.techGet_("defaultMuted")||!1},h.prototype.lastVolume_=function(t){if(void 0===t||0===t)return this.cache_.lastVolume;this.cache_.lastVolume=t},h.prototype.supportsFullScreen=function(){return this.techGet_("supportsFullScreen")||!1},h.prototype.isFullscreen=function(t){if(void 0===t)return!!this.isFullscreen_;this.isFullscreen_=!!t},h.prototype.requestFullscreen=function(){var i=Se;this.isFullscreen(!0),i.requestFullscreen?(_t(p,i.fullscreenchange,Ot(this,function t(e){this.isFullscreen(p[i.fullscreenElement]),!1===this.isFullscreen()&&bt(p,i.fullscreenchange,t),this.trigger("fullscreenchange")})),this.el_[i.requestFullscreen]()):this.tech_.supportsFullScreen()?this.techCall_("enterFullScreen"):(this.enterFullWindow(),this.trigger("fullscreenchange"))},h.prototype.exitFullscreen=function(){var t=Se;this.isFullscreen(!1),t.requestFullscreen?p[t.exitFullscreen]():this.tech_.supportsFullScreen()?this.techCall_("exitFullScreen"):(this.exitFullWindow(),this.trigger("fullscreenchange"))},h.prototype.enterFullWindow=function(){this.isFullWindow=!0,this.docOrigOverflow=p.documentElement.style.overflow,_t(p,"keydown",Ot(this,this.fullWindowOnEscKey)),p.documentElement.style.overflow="hidden",j(p.body,"vjs-full-window"),this.trigger("enterFullWindow")},h.prototype.fullWindowOnEscKey=function(t){27===t.keyCode&&(!0===this.isFullscreen()?this.exitFullscreen():this.exitFullWindow())},h.prototype.exitFullWindow=function(){this.isFullWindow=!1,bt(p,"keydown",this.fullWindowOnEscKey),p.documentElement.style.overflow=this.docOrigOverflow,F(p.body,"vjs-full-window"),this.trigger("exitFullWindow")},h.prototype.canPlayType=function(t){for(var e=void 0,i=0,r=this.options_.techOrder;i<r.length;i++){var n=r[i],s=br.getTech(n);if(s||(s=Xt.getComponent(n)),s){if(s.isSupported()&&(e=s.canPlayType(t)))return e}else f.error('The "'+n+'" tech is undefined. Skipped browser support check for that tech.')}return""},h.prototype.selectSource=function(t){var i,r=this,e=this.options_.techOrder.map(function(t){return[t,br.getTech(t)]}).filter(function(t){var e=t[0],i=t[1];return i?i.isSupported():(f.error('The "'+e+'" tech is undefined. Skipped browser support check for that tech.'),!1)}),n=function(t,i,r){var n=void 0;return t.some(function(e){return i.some(function(t){if(n=r(e,t))return!0})}),n},s=function(t,e){var i=t[0];if(t[1].canPlaySource(e,r.options_[i.toLowerCase()]))return{source:e,tech:i}};return(this.options_.sourceOrder?n(t,e,(i=s,function(t,e){return i(e,t)})):n(e,t,s))||!1},h.prototype.src=function(t){var n=this;if("undefined"==typeof t)return this.cache_.src||"";var s=function e(t){if(Array.isArray(t)){var i=[];t.forEach(function(t){t=e(t),Array.isArray(t)?i=i.concat(t):E(t)&&i.push(t)}),t=i}else t="string"==typeof t&&t.trim()?[Ir({src:t})]:E(t)&&"string"==typeof t.src&&t.src&&t.src.trim()?[Ir(t)]:[];return t}(t);s.length?(this.changingSrc_=!0,this.cache_.sources=s,this.updateSourceCaches_(s[0]),Cr(this,s[0],function(t,e){var i,r;if(n.middleware_=e,n.cache_.sources=s,n.updateSourceCaches_(t),n.src_(t))return 1<s.length?n.src(s.slice(1)):(n.changingSrc_=!1,n.setTimeout(function(){this.error({code:4,message:this.localize(this.options_.notSupportedMessage)})},0),void n.triggerReady());i=e,r=n.tech_,i.forEach(function(t){return t.setTech&&t.setTech(r)})})):this.setTimeout(function(){this.error({code:4,message:this.localize(this.options_.notSupportedMessage)})},0)},h.prototype.src_=function(t){var e,i,r=this,n=this.selectSource([t]);return!n||(e=n.tech,i=this.techName_,zt(e)!==zt(i)?(this.changingSrc_=!0,this.loadTech_(n.tech,n.source),this.tech_.ready(function(){r.changingSrc_=!1})):this.ready(function(){this.tech_.constructor.prototype.hasOwnProperty("setSource")?this.techCall_("setSource",t):this.techCall_("src",t.src),this.changingSrc_=!1},!0),!1)},h.prototype.load=function(){this.techCall_("load")},h.prototype.reset=function(){this.loadTech_(this.options_.techOrder[0],null),this.techCall_("reset")},h.prototype.currentSources=function(){var t=this.currentSource(),e=[];return 0!==Object.keys(t).length&&e.push(t),this.cache_.sources||e},h.prototype.currentSource=function(){return this.cache_.source||{}},h.prototype.currentSrc=function(){return this.currentSource()&&this.currentSource().src||""},h.prototype.currentType=function(){return this.currentSource()&&this.currentSource().type||""},h.prototype.preload=function(t){return void 0!==t?(this.techCall_("setPreload",t),void(this.options_.preload=t)):this.techGet_("preload")},h.prototype.autoplay=function(t){return void 0!==t?(this.techCall_("setAutoplay",t),void(this.options_.autoplay=t)):this.techGet_("autoplay",t)},h.prototype.playsinline=function(t){return void 0!==t?(this.techCall_("setPlaysinline",t),this.options_.playsinline=t,this):this.techGet_("playsinline")},h.prototype.loop=function(t){return void 0!==t?(this.techCall_("setLoop",t),void(this.options_.loop=t)):this.techGet_("loop")},h.prototype.poster=function(t){if(void 0===t)return this.poster_;t||(t=""),t!==this.poster_&&(this.poster_=t,this.techCall_("setPoster",t),this.isPosterFromTech_=!1,this.trigger("posterchange"))},h.prototype.handleTechPosterChange_=function(){if((!this.poster_||this.options_.techCanOverridePoster)&&this.tech_&&this.tech_.poster){var t=this.tech_.poster()||"";t!==this.poster_&&(this.poster_=t,this.isPosterFromTech_=!0,this.trigger("posterchange"))}},h.prototype.controls=function(t){if(void 0===t)return!!this.controls_;t=!!t,this.controls_!==t&&(this.controls_=t,this.usingNativeControls()&&this.techCall_("setControls",t),this.controls_?(this.removeClass("vjs-controls-disabled"),this.addClass("vjs-controls-enabled"),this.trigger("controlsenabled"),this.usingNativeControls()||this.addTechControlsListeners_()):(this.removeClass("vjs-controls-enabled"),this.addClass("vjs-controls-disabled"),this.trigger("controlsdisabled"),this.usingNativeControls()||this.removeTechControlsListeners_()))},h.prototype.usingNativeControls=function(t){if(void 0===t)return!!this.usingNativeControls_;t=!!t,this.usingNativeControls_!==t&&(this.usingNativeControls_=t,this.usingNativeControls_?(this.addClass("vjs-using-native-controls"),this.trigger("usingnativecontrols")):(this.removeClass("vjs-using-native-controls"),this.trigger("usingcustomcontrols")))},h.prototype.error=function(t){return void 0===t?this.error_||null:null===t?(this.error_=t,this.removeClass("vjs-error"),void(this.errorDisplay&&this.errorDisplay.close())):(this.error_=new Le(t),this.addClass("vjs-error"),f.error("(CODE:"+this.error_.code+" "+Le.errorTypes[this.error_.code]+")",this.error_.message,this.error_),void this.trigger("error"))},h.prototype.reportUserActivity=function(t){this.userActivity_=!0},h.prototype.userActive=function(t){if(void 0===t)return this.userActive_;if((t=!!t)!==this.userActive_){if(this.userActive_=t,this.userActive_)return this.userActivity_=!0,this.removeClass("vjs-user-inactive"),this.addClass("vjs-user-active"),void this.trigger("useractive");this.tech_&&this.tech_.one("mousemove",function(t){t.stopPropagation(),t.preventDefault()}),this.userActivity_=!1,this.removeClass("vjs-user-active"),this.addClass("vjs-user-inactive"),this.trigger("userinactive")}},h.prototype.listenForUserActivity_=function(){var e=void 0,i=void 0,r=void 0,n=Ot(this,this.reportUserActivity);this.on("mousedown",function(){n(),this.clearInterval(e),e=this.setInterval(n,250)}),this.on("mousemove",function(t){t.screenX===i&&t.screenY===r||(i=t.screenX,r=t.screenY,n())}),this.on("mouseup",function(t){n(),this.clearInterval(e)}),this.on("keydown",n),this.on("keyup",n);var s=void 0;this.setInterval(function(){if(this.userActivity_){this.userActivity_=!1,this.userActive(!0),this.clearTimeout(s);var t=this.options_.inactivityTimeout;t<=0||(s=this.setTimeout(function(){this.userActivity_||this.userActive(!1)},t))}},250)},h.prototype.playbackRate=function(t){if(void 0===t)return this.tech_&&this.tech_.featuresPlaybackRate?this.cache_.lastPlaybackRate||this.techGet_("playbackRate"):1;this.techCall_("setPlaybackRate",t)},h.prototype.defaultPlaybackRate=function(t){return void 0!==t?this.techCall_("setDefaultPlaybackRate",t):this.tech_&&this.tech_.featuresPlaybackRate?this.techGet_("defaultPlaybackRate"):1},h.prototype.isAudio=function(t){if(void 0===t)return!!this.isAudio_;this.isAudio_=!!t},h.prototype.addTextTrack=function(t,e,i){if(this.tech_)return this.tech_.addTextTrack(t,e,i)},h.prototype.addRemoteTextTrack=function(t,e){if(this.tech_)return this.tech_.addRemoteTextTrack(t,e)},h.prototype.removeRemoteTextTrack=function(){var t=(0<arguments.length&&void 0!==arguments[0]?arguments[0]:{}).track,e=void 0===t?arguments[0]:t;if(this.tech_)return this.tech_.removeRemoteTextTrack(e)},h.prototype.getVideoPlaybackQuality=function(){return this.techGet_("getVideoPlaybackQuality")},h.prototype.videoWidth=function(){return this.tech_&&this.tech_.videoWidth&&this.tech_.videoWidth()||0},h.prototype.videoHeight=function(){return this.tech_&&this.tech_.videoHeight&&this.tech_.videoHeight()||0},h.prototype.language=function(t){if(void 0===t)return this.language_;this.language_=String(t).toLowerCase()},h.prototype.languages=function(){return Gt(h.prototype.options_.languages,this.languages_)},h.prototype.toJSON=function(){var t=Gt(this.options_),e=t.tracks;t.tracks=[];for(var i=0;i<e.length;i++){var r=e[i];(r=Gt(r)).player=void 0,t.tracks[i]=r}return t},h.prototype.createModal=function(t,e){var i=this;(e=e||{}).content=t||"";var r=new Ne(this,e);return this.addChild(r),r.on("dispose",function(){i.removeChild(r)}),r.open(),r},h.getTagSettings=function(t){var e={sources:[],tracks:[]},i=q(t),r=i["data-setup"];if(B(t,"vjs-fluid")&&(i.fluid=!0),null!==r){var n=Oe(r||"{}"),s=n[0],a=n[1];s&&f.error(s),C(i,a)}if(C(e,i),t.hasChildNodes())for(var o=t.childNodes,u=0,l=o.length;u<l;u++){var c=o[u],h=c.nodeName.toLowerCase();"source"===h?e.sources.push(q(c)):"track"===h&&e.tracks.push(q(c))}return e},h.prototype.flexNotSupported_=function(){var t=p.createElement("i");return!("flexBasis"in t.style||"webkitFlexBasis"in t.style||"mozFlexBasis"in t.style||"msFlexBasis"in t.style||"msFlexOrder"in t.style)},h}(Xt);Bi.names.forEach(function(t){var e=Bi[t];ms.prototype[e.getterName]=function(){return this.tech_?this.tech_[e.getterName]():(this[e.privateName]=this[e.privateName]||new e.ListClass,this[e.privateName])}}),ms.players={};var gs=g.navigator;ms.prototype.options_={techOrder:br.defaultTechOrder_,html5:{},flash:{},inactivityTimeout:2e3,playbackRates:[],children:["mediaLoader","posterImage","textTrackDisplay","loadingSpinner","bigPlayButton","controlBar","errorDisplay","textTrackSettings","resizeManager"],language:gs&&(gs.languages&&gs.languages[0]||gs.userLanguage||gs.language)||"en",languages:{},notSupportedMessage:"No compatible source was found for this media."},["ended","seeking","seekable","networkState","readyState"].forEach(function(t){ms.prototype[t]=function(){return this.techGet_(t)}}),ps.forEach(function(t){ms.prototype["handleTech"+zt(t)+"_"]=function(){return this.trigger(t)}}),Xt.registerComponent("Player",ms);var ys="plugin",vs="activePlugins_",_s={},bs=function(t){return _s.hasOwnProperty(t)},Ts=function(t){return bs(t)?_s[t]:void 0},Ss=function(t,e){t[vs]=t[vs]||{},t[vs][e]=!0},ks=function(t,e,i){var r=(i?"before":"")+"pluginsetup";t.trigger(r,e),t.trigger(r+":"+e.name,e)},Cs=function(n,s){return s.prototype.name=n,function(){ks(this,{name:n,plugin:s,instance:null},!0);for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];var r=new(Function.prototype.bind.apply(s,[null].concat([this].concat(e))));return this[n]=function(){return r},ks(this,r.getEventHash()),r}},Es=function(){function s(t){if(y(this,s),this.constructor===s)throw new Error("Plugin must be sub-classed; not directly instantiated.");this.player=t,Vt(this),delete this.trigger,Wt(this,this.constructor.defaultState),Ss(t,this.name),this.dispose=Ot(this,this.dispose),t.on("dispose",this.dispose)}return s.prototype.version=function(){return this.constructor.VERSION},s.prototype.getEventHash=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};return t.name=this.name,t.plugin=this.constructor,t.instance=this,t},s.prototype.trigger=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};return Tt(this.eventBusEl_,t,this.getEventHash(e))},s.prototype.handleStateChanged=function(t){},s.prototype.dispose=function(){var t=this.name,e=this.player;this.trigger("dispose"),this.off(),e.off("dispose",this.dispose),e[vs][t]=!1,this.player=this.state=null,e[t]=Cs(t,_s[t])},s.isBasic=function(t){var e="string"==typeof t?Ts(t):t;return"function"==typeof e&&!s.prototype.isPrototypeOf(e.prototype)},s.registerPlugin=function(t,e){if("string"!=typeof t)throw new Error('Illegal plugin name, "'+t+'", must be a string, was '+("undefined"==typeof t?"undefined":v(t))+".");if(bs(t))f.warn('A plugin named "'+t+'" already exists. You may want to avoid re-registering plugins!');else if(ms.prototype.hasOwnProperty(t))throw new Error('Illegal plugin name, "'+t+'", cannot share a name with an existing player method!');if("function"!=typeof e)throw new Error('Illegal plugin for "'+t+'", must be a function, was '+("undefined"==typeof e?"undefined":v(e))+".");var i,r,n;return _s[t]=e,t!==ys&&(s.isBasic(e)?ms.prototype[t]=(i=t,r=e,n=function(){ks(this,{name:i,plugin:r,instance:null},!0);var t=r.apply(this,arguments);return Ss(this,i),ks(this,{name:i,plugin:r,instance:t}),t},Object.keys(r).forEach(function(t){n[t]=r[t]}),n):ms.prototype[t]=Cs(t,e)),e},s.deregisterPlugin=function(t){if(t===ys)throw new Error("Cannot de-register base plugin.");bs(t)&&(delete _s[t],delete ms.prototype[t])},s.getPlugins=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:Object.keys(_s),i=void 0;return t.forEach(function(t){var e=Ts(t);e&&((i=i||{})[t]=e)}),i},s.getPluginVersion=function(t){var e=Ts(t);return e&&e.VERSION||""},s}();Es.getPlugin=Ts,Es.BASE_PLUGIN_NAME=ys,Es.registerPlugin(ys,Es),ms.prototype.usingPlugin=function(t){return!!this[vs]&&!0===this[vs][t]},ms.prototype.hasPlugin=function(t){return!!bs(t)};var ws=function(t){return 0===t.indexOf("#")?t.slice(1):t};function As(t,i,e){var r=As.getPlayer(t);if(r)return i&&f.warn('Player "'+t+'" is already initialised. Options will not be applied.'),e&&r.ready(e),r;var n="string"==typeof t?nt("#"+ws(t)):t;if(!I(n))throw new TypeError("The element or ID supplied is not valid. (videojs)");p.body.contains(n)||f.warn("The element supplied is not included in the DOM"),i=i||{},As.hooks("beforesetup").forEach(function(t){var e=t(n,Gt(i));E(e)&&!Array.isArray(e)?i=Gt(i,e):f.error("please return an object in beforesetup hooks")});var s=Xt.getComponent("Player");return r=new s(n,i,e),As.hooks("setup").forEach(function(t){return t(r)}),r}if(As.hooks_={},As.hooks=function(t,e){return As.hooks_[t]=As.hooks_[t]||[],e&&(As.hooks_[t]=As.hooks_[t].concat(e)),As.hooks_[t]},As.hook=function(t,e){As.hooks(t,e)},As.hookOnce=function(i,t){As.hooks(i,[].concat(t).map(function(e){return function t(){return As.removeHook(i,t),e.apply(void 0,arguments)}}))},As.removeHook=function(t,e){var i=As.hooks(t).indexOf(e);return!(i<=-1)&&(As.hooks_[t]=As.hooks_[t].slice(),As.hooks_[t].splice(i,1),!0)},!0!==g.VIDEOJS_NO_DYNAMIC_STYLE&&x()){var Ls=nt(".vjs-styles-defaults");if(!Ls){Ls=Lt("vjs-styles-defaults");var Ps=nt("head");Ps&&Ps.insertBefore(Ls,Ps.firstChild),Pt(Ls,"\n .video-js {\n width: 300px;\n height: 150px;\n }\n\n .vjs-fluid {\n padding-top: 56.25%\n }\n ")}}At(1,As),As.VERSION=d,As.options=ms.prototype.options_,As.getPlayers=function(){return ms.players},As.getPlayer=function(t){var e=ms.players,i=void 0;if("string"==typeof t){var r=ws(t),n=e[r];if(n)return n;i=nt("#"+r)}else i=t;if(I(i)){var s=i,a=s.player,o=s.playerId;if(a||e[o])return a||e[o]}},As.getAllPlayers=function(){return Object.keys(ms.players).map(function(t){return ms.players[t]}).filter(Boolean)},As.players=ms.players,As.getComponent=Xt.getComponent,As.registerComponent=function(t,e){br.isTech(e)&&f.warn("The "+t+" tech was registered as a component. It should instead be registered using videojs.registerTech(name, tech)"),Xt.registerComponent.call(Xt,t,e)},As.getTech=br.getTech,As.registerTech=br.registerTech,As.use=function(t,e){Tr[t]=Tr[t]||[],Tr[t].push(e)},Object.defineProperty(As,"middleware",{value:{},writeable:!1,enumerable:!0}),Object.defineProperty(As.middleware,"TERMINATOR",{value:kr,writeable:!1,enumerable:!0}),As.browser=ye,As.TOUCH_ENABLED=ge,As.extend=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=function(){t.apply(this,arguments)},r={};for(var n in"object"===("undefined"==typeof e?"undefined":v(e))?(e.constructor!==Object.prototype.constructor&&(i=e.constructor),r=e):"function"==typeof e&&(i=e),function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+("undefined"==typeof e?"undefined":v(e)));t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(t.super_=e)}(i,t),r)r.hasOwnProperty(n)&&(i.prototype[n]=r[n]);return i},As.mergeOptions=Gt,As.bind=Ot,As.registerPlugin=Es.registerPlugin,As.plugin=function(t,e){return f.warn("videojs.plugin() is deprecated; use videojs.registerPlugin() instead"),Es.registerPlugin(t,e)},As.getPlugins=Es.getPlugins,As.getPlugin=Es.getPlugin,As.getPluginVersion=Es.getPluginVersion,As.addLanguage=function(t,e){var i;return t=(""+t).toLowerCase(),As.options.languages=Gt(As.options.languages,((i={})[t]=e,i)),As.options.languages[t]},As.log=f,As.createTimeRange=As.createTimeRanges=be,As.formatTime=Yr,As.setFormatTime=function(t){Xr=t},As.resetFormatTime=function(){Xr=Gr},As.parseUrl=Je,As.isCrossOrigin=ei,As.EventTarget=Dt,As.on=_t,As.one=St,As.off=bt,As.trigger=Tt,As.xhr=Ci,As.TextTrack=Oi,As.AudioTrack=xi,As.VideoTrack=Ii,["isEl","isTextNode","createEl","hasClass","addClass","removeClass","toggleClass","setAttributes","getAttributes","emptyEl","appendContent","insertContent"].forEach(function(t){As[t]=function(){return f.warn("videojs."+t+"() is deprecated; use videojs.dom."+t+"() instead"),at[t].apply(null,arguments)}}),As.computedStyle=A,As.dom=at,As.url=ii;var Os=e(function(t,e){var i,c,r,n,h;i=/^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/\;?#]*)?(.*?)??(;.*?)?(\?.*?)?(#.*?)?$/,c=/^([^\/;?#]*)(.*)$/,r=/(?:\/|^)\.(?=\/)/g,n=/(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g,h={buildAbsoluteURL:function(t,e,i){if(i=i||{},t=t.trim(),!(e=e.trim())){if(!i.alwaysNormalize)return t;var r=h.parseURL(t);if(!r)throw new Error("Error trying to parse base URL.");return r.path=h.normalizePath(r.path),h.buildURLFromParts(r)}var n=h.parseURL(e);if(!n)throw new Error("Error trying to parse relative URL.");if(n.scheme)return i.alwaysNormalize?(n.path=h.normalizePath(n.path),h.buildURLFromParts(n)):e;var s=h.parseURL(t);if(!s)throw new Error("Error trying to parse base URL.");if(!s.netLoc&&s.path&&"/"!==s.path[0]){var a=c.exec(s.path);s.netLoc=a[1],s.path=a[2]}s.netLoc&&!s.path&&(s.path="/");var o={scheme:s.scheme,netLoc:n.netLoc,path:null,params:n.params,query:n.query,fragment:n.fragment};if(!n.netLoc&&(o.netLoc=s.netLoc,"/"!==n.path[0]))if(n.path){var u=s.path,l=u.substring(0,u.lastIndexOf("/")+1)+n.path;o.path=h.normalizePath(l)}else o.path=s.path,n.params||(o.params=s.params,n.query||(o.query=s.query));return null===o.path&&(o.path=i.alwaysNormalize?h.normalizePath(n.path):n.path),h.buildURLFromParts(o)},parseURL:function(t){var e=i.exec(t);return e?{scheme:e[1]||"",netLoc:e[2]||"",path:e[3]||"",params:e[4]||"",query:e[5]||"",fragment:e[6]||""}:null},normalizePath:function(t){for(t=t.split("").reverse().join("").replace(r,"");t.length!==(t=t.replace(n,"")).length;);return t.split("").reverse().join("")},buildURLFromParts:function(t){return t.scheme+t.netLoc+t.path+t.params+t.query+t.fragment}},t.exports=h}),xs=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},Is=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var r in i)Object.prototype.hasOwnProperty.call(i,r)&&(t[r]=i[r])}return t},Ds=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+("undefined"==typeof e?"undefined":v(e)));t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)},Rs=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!==("undefined"==typeof e?"undefined":v(e))&&"function"!=typeof e?t:e},Ms=function(){function t(){xs(this,t),this.listeners={}}return t.prototype.on=function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},t.prototype.off=function(t,e){if(!this.listeners[t])return!1;var i=this.listeners[t].indexOf(e);return this.listeners[t].splice(i,1),-1<i},t.prototype.trigger=function(t){var e=this.listeners[t],i=void 0,r=void 0,n=void 0;if(e)if(2===arguments.length)for(r=e.length,i=0;i<r;++i)e[i].call(this,arguments[1]);else for(n=Array.prototype.slice.call(arguments,1),r=e.length,i=0;i<r;++i)e[i].apply(this,n)},t.prototype.dispose=function(){this.listeners={}},t.prototype.pipe=function(e){this.on("data",function(t){e.push(t)})},t}(),Us=function(e){function i(){xs(this,i);var t=Rs(this,e.call(this));return t.buffer="",t}return Ds(i,e),i.prototype.push=function(t){var e=void 0;for(this.buffer+=t,e=this.buffer.indexOf("\n");-1<e;e=this.buffer.indexOf("\n"))this.trigger("data",this.buffer.substring(0,e)),this.buffer=this.buffer.substring(e+1)},i}(Ms),Ns=function(t){for(var e=t.split(new RegExp('(?:^|,)((?:[^=]*)=(?:"[^"]*"|[^,]*))')),i={},r=e.length,n=void 0;r--;)""!==e[r]&&((n=/([^=]*)=(.*)/.exec(e[r]).slice(1))[0]=n[0].replace(/^\s+|\s+$/g,""),n[1]=n[1].replace(/^\s+|\s+$/g,""),n[1]=n[1].replace(/^['"](.*)['"]$/g,"$1"),i[n[0]]=n[1]);return i},Bs=function(e){function i(){xs(this,i);var t=Rs(this,e.call(this));return t.customParsers=[],t}return Ds(i,e),i.prototype.push=function(t){var e=void 0,i=void 0;if(0!==(t=t.replace(/^[\u0000\s]+|[\u0000\s]+$/g,"")).length)if("#"===t[0]){for(var r=0;r<this.customParsers.length;r++)if(this.customParsers[r].call(this,t))return;if(0===t.indexOf("#EXT"))if(t=t.replace("\r",""),e=/^#EXTM3U/.exec(t))this.trigger("data",{type:"tag",tagType:"m3u"});else{if(e=/^#EXTINF:?([0-9\.]*)?,?(.*)?$/.exec(t))return i={type:"tag",tagType:"inf"},e[1]&&(i.duration=parseFloat(e[1])),e[2]&&(i.title=e[2]),void this.trigger("data",i);if(e=/^#EXT-X-TARGETDURATION:?([0-9.]*)?/.exec(t))return i={type:"tag",tagType:"targetduration"},e[1]&&(i.duration=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#ZEN-TOTAL-DURATION:?([0-9.]*)?/.exec(t))return i={type:"tag",tagType:"totalduration"},e[1]&&(i.duration=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-VERSION:?([0-9.]*)?/.exec(t))return i={type:"tag",tagType:"version"},e[1]&&(i.version=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-MEDIA-SEQUENCE:?(\-?[0-9.]*)?/.exec(t))return i={type:"tag",tagType:"media-sequence"},e[1]&&(i.number=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-DISCONTINUITY-SEQUENCE:?(\-?[0-9.]*)?/.exec(t))return i={type:"tag",tagType:"discontinuity-sequence"},e[1]&&(i.number=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-PLAYLIST-TYPE:?(.*)?$/.exec(t))return i={type:"tag",tagType:"playlist-type"},e[1]&&(i.playlistType=e[1]),void this.trigger("data",i);if(e=/^#EXT-X-BYTERANGE:?([0-9.]*)?@?([0-9.]*)?/.exec(t))return i={type:"tag",tagType:"byterange"},e[1]&&(i.length=parseInt(e[1],10)),e[2]&&(i.offset=parseInt(e[2],10)),void this.trigger("data",i);if(e=/^#EXT-X-ALLOW-CACHE:?(YES|NO)?/.exec(t))return i={type:"tag",tagType:"allow-cache"},e[1]&&(i.allowed=!/NO/.test(e[1])),void this.trigger("data",i);if(e=/^#EXT-X-MAP:?(.*)$/.exec(t)){if(i={type:"tag",tagType:"map"},e[1]){var n=Ns(e[1]);if(n.URI&&(i.uri=n.URI),n.BYTERANGE){var s=n.BYTERANGE.split("@"),a=s[0],o=s[1];i.byterange={},a&&(i.byterange.length=parseInt(a,10)),o&&(i.byterange.offset=parseInt(o,10))}}this.trigger("data",i)}else if(e=/^#EXT-X-STREAM-INF:?(.*)$/.exec(t)){if(i={type:"tag",tagType:"stream-inf"},e[1]){if(i.attributes=Ns(e[1]),i.attributes.RESOLUTION){var u=i.attributes.RESOLUTION.split("x"),l={};u[0]&&(l.width=parseInt(u[0],10)),u[1]&&(l.height=parseInt(u[1],10)),i.attributes.RESOLUTION=l}i.attributes.BANDWIDTH&&(i.attributes.BANDWIDTH=parseInt(i.attributes.BANDWIDTH,10)),i.attributes["PROGRAM-ID"]&&(i.attributes["PROGRAM-ID"]=parseInt(i.attributes["PROGRAM-ID"],10))}this.trigger("data",i)}else{if(e=/^#EXT-X-MEDIA:?(.*)$/.exec(t))return i={type:"tag",tagType:"media"},e[1]&&(i.attributes=Ns(e[1])),void this.trigger("data",i);if(e=/^#EXT-X-ENDLIST/.exec(t))this.trigger("data",{type:"tag",tagType:"endlist"});else if(e=/^#EXT-X-DISCONTINUITY/.exec(t))this.trigger("data",{type:"tag",tagType:"discontinuity"});else{if(e=/^#EXT-X-PROGRAM-DATE-TIME:?(.*)$/.exec(t))return i={type:"tag",tagType:"program-date-time"},e[1]&&(i.dateTimeString=e[1],i.dateTimeObject=new Date(e[1])),void this.trigger("data",i);if(e=/^#EXT-X-KEY:?(.*)$/.exec(t))return i={type:"tag",tagType:"key"},e[1]&&(i.attributes=Ns(e[1]),i.attributes.IV&&("0x"===i.attributes.IV.substring(0,2).toLowerCase()&&(i.attributes.IV=i.attributes.IV.substring(2)),i.attributes.IV=i.attributes.IV.match(/.{8}/g),i.attributes.IV[0]=parseInt(i.attributes.IV[0],16),i.attributes.IV[1]=parseInt(i.attributes.IV[1],16),i.attributes.IV[2]=parseInt(i.attributes.IV[2],16),i.attributes.IV[3]=parseInt(i.attributes.IV[3],16),i.attributes.IV=new Uint32Array(i.attributes.IV))),void this.trigger("data",i);if(e=/^#EXT-X-START:?(.*)$/.exec(t))return i={type:"tag",tagType:"start"},e[1]&&(i.attributes=Ns(e[1]),i.attributes["TIME-OFFSET"]=parseFloat(i.attributes["TIME-OFFSET"]),i.attributes.PRECISE=/YES/.test(i.attributes.PRECISE)),void this.trigger("data",i);if(e=/^#EXT-X-CUE-OUT-CONT:?(.*)?$/.exec(t))return i={type:"tag",tagType:"cue-out-cont"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);if(e=/^#EXT-X-CUE-OUT:?(.*)?$/.exec(t))return i={type:"tag",tagType:"cue-out"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);if(e=/^#EXT-X-CUE-IN:?(.*)?$/.exec(t))return i={type:"tag",tagType:"cue-in"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);this.trigger("data",{type:"tag",data:t.slice(4)})}}}else this.trigger("data",{type:"comment",text:t.slice(1)})}else this.trigger("data",{type:"uri",uri:t})},i.prototype.addParser=function(t){var e=this,i=t.expression,r=t.customType,n=t.dataParser,s=t.segment;"function"!=typeof n&&(n=function(t){return t}),this.customParsers.push(function(t){if(i.exec(t))return e.trigger("data",{type:"custom",data:n(t),customType:r,segment:s}),!0})},i}(Ms),js=function(e){function i(){xs(this,i);var t=Rs(this,e.call(this));t.lineStream=new Us,t.parseStream=new Bs,t.lineStream.pipe(t.parseStream);var n=t,s=[],a={},o=void 0,u=void 0,l={AUDIO:{},VIDEO:{},"CLOSED-CAPTIONS":{},SUBTITLES:{}},c=0;return t.manifest={allowCache:!0,discontinuityStarts:[],segments:[]},t.parseStream.on("data",function(e){var i=void 0,r=void 0;({tag:function(){({"allow-cache":function(){this.manifest.allowCache=e.allowed,"allowed"in e||(this.trigger("info",{message:"defaulting allowCache to YES"}),this.manifest.allowCache=!0)},byterange:function(){var t={};"length"in e&&((a.byterange=t).length=e.length,"offset"in e||(this.trigger("info",{message:"defaulting offset to zero"}),e.offset=0)),"offset"in e&&((a.byterange=t).offset=e.offset)},endlist:function(){this.manifest.endList=!0},inf:function(){"mediaSequence"in this.manifest||(this.manifest.mediaSequence=0,this.trigger("info",{message:"defaulting media sequence to zero"})),"discontinuitySequence"in this.manifest||(this.manifest.discontinuitySequence=0,this.trigger("info",{message:"defaulting discontinuity sequence to zero"})),0<e.duration&&(a.duration=e.duration),0===e.duration&&(a.duration=.01,this.trigger("info",{message:"updating zero segment duration to a small value"})),this.manifest.segments=s},key:function(){e.attributes?"NONE"!==e.attributes.METHOD?e.attributes.URI?(e.attributes.METHOD||this.trigger("warn",{message:"defaulting key method to AES-128"}),u={method:e.attributes.METHOD||"AES-128",uri:e.attributes.URI},"undefined"!=typeof e.attributes.IV&&(u.iv=e.attributes.IV)):this.trigger("warn",{message:"ignoring key declaration without URI"}):u=null:this.trigger("warn",{message:"ignoring key declaration without attribute list"})},"media-sequence":function(){isFinite(e.number)?this.manifest.mediaSequence=e.number:this.trigger("warn",{message:"ignoring invalid media sequence: "+e.number})},"discontinuity-sequence":function(){isFinite(e.number)?(this.manifest.discontinuitySequence=e.number,c=e.number):this.trigger("warn",{message:"ignoring invalid discontinuity sequence: "+e.number})},"playlist-type":function(){/VOD|EVENT/.test(e.playlistType)?this.manifest.playlistType=e.playlistType:this.trigger("warn",{message:"ignoring unknown playlist type: "+e.playlist})},map:function(){o={},e.uri&&(o.uri=e.uri),e.byterange&&(o.byterange=e.byterange)},"stream-inf":function(){this.manifest.playlists=s,this.manifest.mediaGroups=this.manifest.mediaGroups||l,e.attributes?(a.attributes||(a.attributes={}),Is(a.attributes,e.attributes)):this.trigger("warn",{message:"ignoring empty stream-inf attributes"})},media:function(){if(this.manifest.mediaGroups=this.manifest.mediaGroups||l,e.attributes&&e.attributes.TYPE&&e.attributes["GROUP-ID"]&&e.attributes.NAME){var t=this.manifest.mediaGroups[e.attributes.TYPE];t[e.attributes["GROUP-ID"]]=t[e.attributes["GROUP-ID"]]||{},i=t[e.attributes["GROUP-ID"]],(r={default:/yes/i.test(e.attributes.DEFAULT)}).default?r.autoselect=!0:r.autoselect=/yes/i.test(e.attributes.AUTOSELECT),e.attributes.LANGUAGE&&(r.language=e.attributes.LANGUAGE),e.attributes.URI&&(r.uri=e.attributes.URI),e.attributes["INSTREAM-ID"]&&(r.instreamId=e.attributes["INSTREAM-ID"]),e.attributes.CHARACTERISTICS&&(r.characteristics=e.attributes.CHARACTERISTICS),e.attributes.FORCED&&(r.forced=/yes/i.test(e.attributes.FORCED)),i[e.attributes.NAME]=r}else this.trigger("warn",{message:"ignoring incomplete or missing media group"})},discontinuity:function(){c+=1,a.discontinuity=!0,this.manifest.discontinuityStarts.push(s.length)},"program-date-time":function(){"undefined"==typeof this.manifest.dateTimeString&&(this.manifest.dateTimeString=e.dateTimeString,this.manifest.dateTimeObject=e.dateTimeObject),a.dateTimeString=e.dateTimeString,a.dateTimeObject=e.dateTimeObject},targetduration:function(){!isFinite(e.duration)||e.duration<0?this.trigger("warn",{message:"ignoring invalid target duration: "+e.duration}):this.manifest.targetDuration=e.duration},totalduration:function(){!isFinite(e.duration)||e.duration<0?this.trigger("warn",{message:"ignoring invalid total duration: "+e.duration}):this.manifest.totalDuration=e.duration},start:function(){e.attributes&&!isNaN(e.attributes["TIME-OFFSET"])?this.manifest.start={timeOffset:e.attributes["TIME-OFFSET"],precise:e.attributes.PRECISE}:this.trigger("warn",{message:"ignoring start declaration without appropriate attribute list"})},"cue-out":function(){a.cueOut=e.data},"cue-out-cont":function(){a.cueOutCont=e.data},"cue-in":function(){a.cueIn=e.data}}[e.tagType]||function(){}).call(n)},uri:function(){a.uri=e.uri,s.push(a),!this.manifest.targetDuration||"duration"in a||(this.trigger("warn",{message:"defaulting segment duration to the target duration"}),a.duration=this.manifest.targetDuration),u&&(a.key=u),a.timeline=c,o&&(a.map=o),a={}},comment:function(){},custom:function(){e.segment?(a.custom=a.custom||{},a.custom[e.customType]=e.data):(this.manifest.custom=this.manifest.custom||{},this.manifest.custom[e.customType]=e.data)}})[e.type].call(n)}),t}return Ds(i,e),i.prototype.push=function(t){this.lineStream.push(t)},i.prototype.end=function(){this.lineStream.push("\n")},i.prototype.addParser=function(t){this.parseStream.addParser(t)},i}(Ms),Fs=function(t){var e,i=t.attributes,r=t.segments,n={attributes:(e={NAME:i.id,AUDIO:"audio",SUBTITLES:"subs",RESOLUTION:{width:i.width,height:i.height},CODECS:i.codecs,BANDWIDTH:i.bandwidth},e["PROGRAM-ID"]=1,e),uri:"",endList:"static"===(i.type||"static"),timeline:i.periodIndex,resolvedUri:"",targetDuration:i.duration,segments:r,mediaSequence:r.length?r[0].number:1};return i.contentProtection&&(n.contentProtection=i.contentProtection),n},Hs=function(t){return!!t&&"object"===("undefined"==typeof t?"undefined":v(t))},Vs=function r(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];return e.reduce(function(e,i){return Object.keys(i).forEach(function(t){Array.isArray(e[t])&&Array.isArray(i[t])?e[t]=e[t].concat(i[t]):Hs(e[t])&&Hs(i[t])?e[t]=r(e[t],i[t]):e[t]=i[t]}),e},{})},qs=function(t,e){return/^[a-z]+:/i.test(e)?e:(/\/\//i.test(t)||(t=Os.buildAbsoluteURL(g.location.href,t)),Os.buildAbsoluteURL(t,e))},Ws=function(t){var e=t.baseUrl,i=void 0===e?"":e,r=t.source,n=void 0===r?"":r,s=t.range,a=void 0===s?"":s,o={uri:n,resolvedUri:qs(i||"",n)};if(a){var u=a.split("-"),l=parseInt(u[0],10),c=parseInt(u[1],10);o.byterange={length:c-l,offset:l}}return o},zs=function(t,e){for(var i,r,n,s,a,o,u,l,c,h,d,p,f=t.type,m=void 0===f?"static":f,g=t.minimumUpdatePeriod,y=void 0===g?0:g,v=t.media,_=void 0===v?"":v,b=t.sourceDuration,T=t.timescale,S=void 0===T?1:T,k=t.startNumber,C=void 0===k?1:k,E=t.periodIndex,w=[],A=-1,L=0;L<e.length;L++){var P=e[L],O=P.d,x=P.r||0,I=P.t||0;A<0&&(A=I),I&&A<I&&(A=I);var D=void 0;if(x<0){var R=L+1;R===e.length?"dynamic"===m&&0<y&&0<_.indexOf("$Number$")?(r=A,n=O,void 0,s=(i=t).NOW,a=i.clientOffset,o=i.availabilityStartTime,u=i.timescale,l=void 0===u?1:u,c=i.start,h=void 0===c?0:c,d=i.minimumUpdatePeriod,p=(s+a)/1e3+(void 0===d?0:d)-(o+h),D=Math.ceil((p*l-r)/n)):D=(b*S-A)/O:D=(e[R].t-A)/O}else D=x+1;for(var M=C+w.length+D,U=C+w.length;U<M;)w.push({number:U,duration:O/S,time:A,timeline:E}),A+=O,U++}return w},Gs=function(t){return t.reduce(function(t,e){return t.concat(e)},[])},Xs=function(t){if(!t.length)return[];for(var e=[],i=0;i<t.length;i++)e.push(t[i]);return e},Ys={static:function(t){var e=t.duration,i=t.timescale,r=void 0===i?1:i,n=t.sourceDuration;return{start:0,end:Math.ceil(n/(e/r))}},dynamic:function(t){var e=t.NOW,i=t.clientOffset,r=t.availabilityStartTime,n=t.timescale,s=void 0===n?1:n,a=t.duration,o=t.start,u=void 0===o?0:o,l=t.minimumUpdatePeriod,c=void 0===l?0:l,h=t.timeShiftBufferDepth,d=void 0===h?1/0:h,p=(e+i)/1e3,f=r+u,m=p+c-f,g=Math.ceil(m*s/a),y=Math.floor((p-f-d)*s/a),v=Math.floor((p-f)*s/a);return{start:Math.max(0,y),end:Math.min(g,v)}}},$s=function(t){var o,e=t.type,i=void 0===e?"static":e,r=t.duration,n=t.timescale,s=void 0===n?1:n,a=t.sourceDuration,u=Ys[i](t),l=function(t,e){for(var i=[],r=t;r<e;r++)i.push(r);return i}(u.start,u.end).map((o=t,function(t,e){var i=o.duration,r=o.timescale,n=void 0===r?1:r,s=o.periodIndex,a=o.startNumber;return{number:(void 0===a?1:a)+t,duration:i/n,timeline:s,time:e*i}}));if("static"===i){var c=l.length-1;l[c].duration=a-r/s*c}return l},Ks=/\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g,Qs=function(t,e){return t.replace(Ks,(s=e,function(t,e,i,r){if("$$"===t)return"$";if("undefined"==typeof s[e])return t;var n=""+s[e];return"RepresentationID"===e?n:(r=i?parseInt(r,10):1)<=n.length?n:""+new Array(r-n.length+1).join("0")+n}));var s},Js=function(i,t){var e,r,n={RepresentationID:i.id,Bandwidth:i.bandwidth||0},s=i.initialization,a=void 0===s?{sourceURL:"",range:""}:s,o=Ws({baseUrl:i.baseUrl,source:Qs(a.sourceURL,n),range:a.range});return(r=t,(e=i).duration||r?e.duration?$s(e):zs(e,r):[{number:e.startNumber||1,duration:e.sourceDuration,time:0,timeline:e.periodIndex}]).map(function(t){n.Number=t.number,n.Time=t.time;var e=Qs(i.media||"",n);return{uri:e,timeline:t.timeline,duration:t.duration,resolvedUri:qs(i.baseUrl||"",e),map:o,number:t.number}})},Zs="INVALID_NUMBER_OF_PERIOD",ta="DASH_EMPTY_MANIFEST",ea="DASH_INVALID_XML",ia="NO_BASE_URL",ra="SEGMENT_TIME_UNSPECIFIED",na="UNSUPPORTED_UTC_TIMING_SCHEME",sa=function(u,t){var e=u.duration,i=u.segmentUrls,r=void 0===i?[]:i;if(!e&&!t||e&&t)throw new Error(ra);var n=r.map(function(t){return i=t,r=(e=u).baseUrl,n=e.initialization,a=Ws({baseUrl:r,source:(s=void 0===n?{}:n).sourceURL,range:s.range}),(o=Ws({baseUrl:r,source:i.media,range:i.mediaRange})).map=a,o;var e,i,r,n,s,a,o}),s=void 0;return e&&(s=$s(u)),t&&(s=zs(u,t)),s.map(function(t,e){if(n[e]){var i=n[e];return i.timeline=t.timeline,i.duration=t.duration,i.number=t.number,i}}).filter(function(t){return t})},aa=function(t){var e=t.baseUrl,i=t.initialization,r=void 0===i?{}:i,n=t.sourceDuration,s=t.timescale,a=void 0===s?1:s,o=t.indexRange,u=void 0===o?"":o,l=t.duration;if(!e)throw new Error(ia);var c=Ws({baseUrl:e,source:r.sourceURL,range:r.range}),h=Ws({baseUrl:e,source:e,range:u});if(h.map=c,l){var d=$s(t);d.length&&(h.duration=d[0].duration,h.timeline=d[0].timeline)}else n&&(h.duration=n/a,h.timeline=0);return h.number=0,[h]},oa=function(t){var e=t.attributes,i=t.segmentInfo,r=void 0,n=void 0;if(i.template?(n=Js,r=Vs(e,i.template)):i.base?(n=aa,r=Vs(e,i.base)):i.list&&(n=sa,r=Vs(e,i.list)),!n)return{attributes:e};var s=n(r,i.timeline);if(r.duration){var a=r,o=a.duration,u=a.timescale,l=void 0===u?1:u;r.duration=o/l}else s.length?r.duration=s.reduce(function(t,e){return Math.max(t,Math.ceil(e.duration))},0):r.duration=0;return{attributes:r,segments:s}},ua=function(t,e){return Xs(t.childNodes).filter(function(t){return t.tagName===e})},la=function(t){return t.textContent.trim()},ca=function(t){var e=/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/.exec(t);if(!e)return 0;var i=e.slice(1),r=i[0],n=i[1],s=i[2],a=i[3],o=i[4],u=i[5];return 31536e3*parseFloat(r||0)+2592e3*parseFloat(n||0)+86400*parseFloat(s||0)+3600*parseFloat(a||0)+60*parseFloat(o||0)+parseFloat(u||0)},ha={mediaPresentationDuration:function(t){return ca(t)},availabilityStartTime:function(t){return/^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/.test(e=t)&&(e+="Z"),Date.parse(e)/1e3;var e},minimumUpdatePeriod:function(t){return ca(t)},timeShiftBufferDepth:function(t){return ca(t)},start:function(t){return ca(t)},width:function(t){return parseInt(t,10)},height:function(t){return parseInt(t,10)},bandwidth:function(t){return parseInt(t,10)},startNumber:function(t){return parseInt(t,10)},timescale:function(t){return parseInt(t,10)},duration:function(t){var e=parseInt(t,10);return isNaN(e)?ca(t):e},d:function(t){return parseInt(t,10)},t:function(t){return parseInt(t,10)},r:function(t){return parseInt(t,10)},DEFAULT:function(t){return t}},da=function(t){return t&&t.attributes?Xs(t.attributes).reduce(function(t,e){var i=ha[e.name]||ha.DEFAULT;return t[e.name]=i(e.value),t},{}):{}};var pa,fa,ma={"urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b":"org.w3.clearkey","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"com.widevine.alpha","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb":"com.adobe.primetime"},ga=function(t,i){return i.length?Gs(t.map(function(e){return i.map(function(t){return qs(e,la(t))})})):t},ya=function(t){var e=ua(t,"SegmentTemplate")[0],i=ua(t,"SegmentList")[0],r=i&&ua(i,"SegmentURL").map(function(t){return Vs({tag:"SegmentURL"},da(t))}),n=ua(t,"SegmentBase")[0],s=i||e,a=s&&ua(s,"SegmentTimeline")[0],o=i||n||e,u=o&&ua(o,"Initialization")[0],l=e&&da(e);l&&u?l.initialization=u&&da(u):l&&l.initialization&&(l.initialization={sourceURL:l.initialization});var c={template:l,timeline:a&&ua(a,"S").map(function(t){return da(t)}),list:i&&Vs(da(i),{segmentUrls:r,initialization:da(u)}),base:n&&Vs(da(n),{initialization:da(u)})};return Object.keys(c).forEach(function(t){c[t]||delete c[t]}),c},va=function(t){return t.reduce(function(t,e){var i=da(e),r=ma[i.schemeIdUri];if(r){t[r]={attributes:i};var n=ua(e,"cenc:pssh")[0];if(n){var s=la(n),a=s&&function(t){for(var e=g.atob(t),i=new Uint8Array(e.length),r=0;r<e.length;r++)i[r]=e.charCodeAt(r);return i}(s);t[r].pssh=a}}return t},{})},_a=function(p,f,m){return function(t){var e=da(t),i=ga(f,ua(t,"BaseURL")),r=ua(t,"Role")[0],n={role:da(r)},s=Vs(p,e,n),a=va(ua(t,"ContentProtection"));Object.keys(a).length&&(s=Vs(s,{contentProtection:a}));var o,u,l,c=ya(t),h=ua(t,"Representation"),d=Vs(m,c);return Gs(h.map((o=s,u=i,l=d,function(t){var e=ua(t,"BaseURL"),i=ga(u,e),r=Vs(o,da(t)),n=ya(t);return i.map(function(t){return{segmentInfo:Vs(l,n),attributes:Vs(r,{baseUrl:t})}})})))}},ba=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=e.manifestUri,r=void 0===i?"":i,n=e.NOW,s=void 0===n?Date.now():n,a=e.clientOffset,o=void 0===a?0:a,u=ua(t,"Period");if(1!==u.length)throw new Error(Zs);var l,c,h=da(t),d=ga([r],ua(t,"BaseURL"));return h.sourceDuration=h.mediaPresentationDuration||0,h.NOW=s,h.clientOffset=o,Gs(u.map((l=h,c=d,function(t,e){var i=ga(c,ua(t,"BaseURL")),r=da(t),n=Vs(l,r,{periodIndex:e}),s=ua(t,"AdaptationSet"),a=ya(t);return Gs(s.map(_a(n,i,a)))})))},Ta=function(t){if(""===t)throw new Error(ta);var e=(new g.DOMParser).parseFromString(t,"application/xml"),i=e&&"MPD"===e.documentElement.tagName?e.documentElement:null;if(!i||i&&0<i.getElementsByTagName("parsererror").length)throw new Error(ea);return i},Sa=function(t,e){return function(t){var e;if(!t.length)return{};var i=t[0].attributes,r=i.sourceDuration,n=i.minimumUpdatePeriod,s=void 0===n?0:n,a=t.filter(function(t){var e=t.attributes;return"video/mp4"===e.mimeType||"video"===e.contentType}).map(Fs),o=t.filter(function(t){var e=t.attributes;return"audio/mp4"===e.mimeType||"audio"===e.contentType}),u=t.filter(function(t){var e=t.attributes;return"text/vtt"===e.mimeType||"text"===e.contentType}),l={allowCache:!0,discontinuityStarts:[],segments:[],endList:!0,mediaGroups:(e={AUDIO:{},VIDEO:{}},e["CLOSED-CAPTIONS"]={},e.SUBTITLES={},e),uri:"",duration:r,playlists:a,minimumUpdatePeriod:1e3*s};return o.length&&(l.mediaGroups.AUDIO.audio=o.reduce(function(t,e){var i,r,n,s,a,o=e.attributes.role&&e.attributes.role.value||"main",u=e.attributes.lang||"",l="main";return u&&(l=e.attributes.lang+" ("+o+")"),t[l]&&t[l].playlists[0].attributes.BANDWIDTH>e.attributes.bandwidth||(t[l]={language:u,autoselect:!0,default:"main"===o,playlists:[(i=e,n=i.attributes,s=i.segments,a={attributes:(r={NAME:n.id,BANDWIDTH:n.bandwidth,CODECS:n.codecs},r["PROGRAM-ID"]=1,r),uri:"",endList:"static"===(n.type||"static"),timeline:n.periodIndex,resolvedUri:"",targetDuration:n.duration,segments:s,mediaSequence:s.length?s[0].number:1},n.contentProtection&&(a.contentProtection=n.contentProtection),a)],uri:""}),t},{})),u.length&&(l.mediaGroups.SUBTITLES.subs=u.reduce(function(t,e){var i,r,n,s,a=e.attributes.lang||"text";return t[a]||(t[a]={language:a,default:!1,autoselect:!1,playlists:[(i=e,n=i.attributes,s=i.segments,"undefined"==typeof s&&(s=[{uri:n.baseUrl,timeline:n.periodIndex,resolvedUri:n.baseUrl||"",duration:n.sourceDuration,number:0}],n.duration=n.sourceDuration),{attributes:(r={NAME:n.id,BANDWIDTH:n.bandwidth},r["PROGRAM-ID"]=1,r),uri:"",endList:"static"===(n.type||"static"),timeline:n.periodIndex,resolvedUri:n.baseUrl||"",targetDuration:n.duration,segments:s,mediaSequence:s.length?s[0].number:1})],uri:""}),t},{})),l}(ba(Ta(t),e).map(oa))},ka=function(t){return function(t){var e=ua(t,"UTCTiming")[0];if(!e)return null;var i=da(e);switch(i.schemeIdUri){case"urn:mpeg:dash:utc:http-head:2014":case"urn:mpeg:dash:utc:http-head:2012":i.method="HEAD";break;case"urn:mpeg:dash:utc:http-xsdate:2014":case"urn:mpeg:dash:utc:http-iso:2014":case"urn:mpeg:dash:utc:http-xsdate:2012":case"urn:mpeg:dash:utc:http-iso:2012":i.method="GET";break;case"urn:mpeg:dash:utc:direct:2014":case"urn:mpeg:dash:utc:direct:2012":i.method="DIRECT",i.value=Date.parse(i.value);break;case"urn:mpeg:dash:utc:http-ntp:2014":case"urn:mpeg:dash:utc:ntp:2014":case"urn:mpeg:dash:utc:sntp:2014":default:throw new Error(na)}return i}(Ta(t))},Ca={toUnsigned:function(t){return t>>>0}},Ea=Ca.toUnsigned,wa=Object.freeze({default:Ca,__moduleExports:Ca,toUnsigned:Ea}),Aa=(wa&&Ca||wa).toUnsigned;pa=function(t,e){var i,r,n,s,a,o=[];if(!e.length)return null;for(i=0;i<t.byteLength;)r=Aa(t[i]<<24|t[i+1]<<16|t[i+2]<<8|t[i+3]),n=fa(t.subarray(i+4,i+8)),s=1<r?i+r:t.byteLength,n===e[0]&&(1===e.length?o.push(t.subarray(i+8,s)):(a=pa(t.subarray(i+8,s),e.slice(1))).length&&(o=o.concat(a))),i=s;return o};fa=function(t){var e="";return e+=String.fromCharCode(t[0]),e+=String.fromCharCode(t[1]),e+=String.fromCharCode(t[2]),e+=String.fromCharCode(t[3])};var La=function(t){return pa(t,["moov","trak"]).reduce(function(t,e){var i,r,n,s,a;return(i=pa(e,["tkhd"])[0])?(r=i[0],s=Aa(i[n=0===r?12:20]<<24|i[n+1]<<16|i[n+2]<<8|i[n+3]),(a=pa(e,["mdia","mdhd"])[0])?(n=0===(r=a[0])?12:20,t[s]=Aa(a[n]<<24|a[n+1]<<16|a[n+2]<<8|a[n+3]),t):null):null},{})},Pa=function(n,t){var e,i,r;return e=pa(t,["moof","traf"]),i=[].concat.apply([],e.map(function(r){return pa(r,["tfhd"]).map(function(t){var e,i;return e=Aa(t[4]<<24|t[5]<<16|t[6]<<8|t[7]),i=n[e]||9e4,(pa(r,["tfdt"]).map(function(t){var e,i;return e=t[0],i=Aa(t[4]<<24|t[5]<<16|t[6]<<8|t[7]),1===e&&(i*=Math.pow(2,32),i+=Aa(t[8]<<24|t[9]<<16|t[10]<<8|t[11])),i})[0]||1/0)/i})})),r=Math.min.apply(null,i),isFinite(r)?r:0},Oa={H264_STREAM_TYPE:27,ADTS_STREAM_TYPE:15,METADATA_STREAM_TYPE:21},xa=Oa.H264_STREAM_TYPE,Ia=Oa.ADTS_STREAM_TYPE,Da=Oa.METADATA_STREAM_TYPE,Ra=Object.freeze({default:Oa,__moduleExports:Oa,H264_STREAM_TYPE:xa,ADTS_STREAM_TYPE:Ia,METADATA_STREAM_TYPE:Da}),Ma=function(){this.init=function(){var s={};this.on=function(t,e){s[t]||(s[t]=[]),s[t]=s[t].concat(e)},this.off=function(t,e){var i;return!!s[t]&&(i=s[t].indexOf(e),s[t]=s[t].slice(),s[t].splice(i,1),-1<i)},this.trigger=function(t){var e,i,r,n;if(e=s[t])if(2===arguments.length)for(r=e.length,i=0;i<r;++i)e[i].call(this,arguments[1]);else{for(n=[],i=arguments.length,i=1;i<arguments.length;++i)n.push(arguments[i]);for(r=e.length,i=0;i<r;++i)e[i].apply(this,n)}},this.dispose=function(){s={}}}};Ma.prototype.pipe=function(e){return this.on("data",function(t){e.push(t)}),this.on("done",function(t){e.flush(t)}),e},Ma.prototype.push=function(t){this.trigger("data",t)},Ma.prototype.flush=function(t){this.trigger("done",t)};var Ua=Ma,Na=Object.freeze({default:Ua,__moduleExports:Ua}),Ba=function(t,e){var i=1;for(e<t&&(i=-1);4294967296<Math.abs(e-t);)t+=8589934592*i;return t},ja=function t(e){var i,r;t.prototype.init.call(this),this.type_=e,this.push=function(t){t.type===this.type_&&(void 0===r&&(r=t.dts),t.dts=Ba(t.dts,r),t.pts=Ba(t.pts,r),i=t.dts,this.trigger("data",t))},this.flush=function(){r=i,this.trigger("done")},this.discontinuity=function(){i=r=void 0}};ja.prototype=new(Na&&Ua||Na);var Fa={TimestampRolloverStream:ja,handleRollover:Ba},Ha=Fa.TimestampRolloverStream,Va=Fa.handleRollover,qa=Object.freeze({default:Fa,__moduleExports:Fa,TimestampRolloverStream:Ha,handleRollover:Va}),Wa=Ra&&Oa||Ra,za=function(t){var e=31&t[1];return e<<=8,e|=t[2]},Ga=function(t){return!!(64&t[1])},Xa=function(t){var e=0;return 1<(48&t[3])>>>4&&(e+=t[4]+1),e},Ya=function(t){switch(t){case 5:return"slice_layer_without_partitioning_rbsp_idr";case 6:return"sei_rbsp";case 7:return"seq_parameter_set_rbsp";case 8:return"pic_parameter_set_rbsp";case 9:return"access_unit_delimiter_rbsp";default:return null}},$a={parseType:function(t,e){var i=za(t);return 0===i?"pat":i===e?"pmt":e?"pes":null},parsePat:function(t){var e=Ga(t),i=4+Xa(t);return e&&(i+=t[i]+1),(31&t[i+10])<<8|t[i+11]},parsePmt:function(t){var e={},i=Ga(t),r=4+Xa(t);if(i&&(r+=t[r]+1),1&t[r+5]){var n;n=3+((15&t[r+1])<<8|t[r+2])-4;for(var s=12+((15&t[r+10])<<8|t[r+11]);s<n;){var a=r+s;e[(31&t[a+1])<<8|t[a+2]]=t[a],s+=5+((15&t[a+3])<<8|t[a+4])}return e}},parsePayloadUnitStartIndicator:Ga,parsePesType:function(t,e){switch(e[za(t)]){case Wa.H264_STREAM_TYPE:return"video";case Wa.ADTS_STREAM_TYPE:return"audio";case Wa.METADATA_STREAM_TYPE:return"timed-metadata";default:return null}},parsePesTime:function(t){if(!Ga(t))return null;var e=4+Xa(t);if(e>=t.byteLength)return null;var i,r=null;return 192&(i=t[e+7])&&((r={}).pts=(14&t[e+9])<<27|(255&t[e+10])<<20|(254&t[e+11])<<12|(255&t[e+12])<<5|(254&t[e+13])>>>3,r.pts*=4,r.pts+=(6&t[e+13])>>>1,r.dts=r.pts,64&i&&(r.dts=(14&t[e+14])<<27|(255&t[e+15])<<20|(254&t[e+16])<<12|(255&t[e+17])<<5|(254&t[e+18])>>>3,r.dts*=4,r.dts+=(6&t[e+18])>>>1)),r},videoPacketContainsKeyFrame:function(t){for(var e=4+Xa(t),i=t.subarray(e),r=0,n=0,s=!1;n<i.byteLength-3;n++)if(1===i[n+2]){r=n+5;break}for(;r<i.byteLength;)switch(i[r]){case 0:if(0!==i[r-1]){r+=2;break}if(0!==i[r-2]){r++;break}for(n+3!==r-2&&"slice_layer_without_partitioning_rbsp_idr"===Ya(31&i[n+3])&&(s=!0);1!==i[++r]&&r<i.length;);n=r-2,r+=3;break;case 1:if(0!==i[r-1]||0!==i[r-2]){r+=3;break}"slice_layer_without_partitioning_rbsp_idr"===Ya(31&i[n+3])&&(s=!0),n=r-2,r+=3;break;default:r+=3}return i=i.subarray(n),r-=n,n=0,i&&3<i.byteLength&&"slice_layer_without_partitioning_rbsp_idr"===Ya(31&i[n+3])&&(s=!0),s}},Ka=$a.parseType,Qa=$a.parsePat,Ja=$a.parsePmt,Za=$a.parsePayloadUnitStartIndicator,to=$a.parsePesType,eo=$a.parsePesTime,io=$a.videoPacketContainsKeyFrame,ro=Object.freeze({default:$a,__moduleExports:$a,parseType:Ka,parsePat:Qa,parsePmt:Ja,parsePayloadUnitStartIndicator:Za,parsePesType:to,parsePesTime:eo,videoPacketContainsKeyFrame:io}),no=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],so=function(t){return t[0]<<21|t[1]<<14|t[2]<<7|t[3]},ao={parseId3TagSize:function(t,e){var i=t[e+6]<<21|t[e+7]<<14|t[e+8]<<7|t[e+9];return(16&t[e+5])>>4?i+20:i+10},parseAdtsSize:function(t,e){var i=(224&t[e+5])>>5,r=t[e+4]<<3;return 6144&t[e+3]|r|i},parseType:function(t,e){return t[e]==="I".charCodeAt(0)&&t[e+1]==="D".charCodeAt(0)&&t[e+2]==="3".charCodeAt(0)?"timed-metadata":!0&t[e]&&240==(240&t[e+1])?"audio":null},parseSampleRate:function(t){for(var e=0;e+5<t.length;){if(255===t[e]&&240==(246&t[e+1]))return no[(60&t[e+2])>>>2];e++}return null},parseAacTimestamp:function(t){var e,i,r;e=10,64&t[5]&&(e+=4,e+=so(t.subarray(10,14)));do{if((i=so(t.subarray(e+4,e+8)))<1)return null;if("PRIV"===String.fromCharCode(t[e],t[e+1],t[e+2],t[e+3])){r=t.subarray(e+10,e+i+10);for(var n=0;n<r.byteLength;n++)if(0===r[n]){if("com.apple.streaming.transportStreamTimestamp"===unescape(function(t,e,i){var r,n="";for(r=e;r<i;r++)n+="%"+("00"+t[r].toString(16)).slice(-2);return n}(r,0,n))){var s=r.subarray(n+1),a=(1&s[3])<<30|s[4]<<22|s[5]<<14|s[6]<<6|s[7]>>>2;return a*=4,a+=3&s[7]}break}}e+=10,e+=i}while(e<t.byteLength);return null}},oo=ao.parseId3TagSize,uo=ao.parseAdtsSize,lo=ao.parseType,co=ao.parseSampleRate,ho=ao.parseAacTimestamp,po=Object.freeze({default:ao,__moduleExports:ao,parseId3TagSize:oo,parseAdtsSize:uo,parseType:lo,parseSampleRate:co,parseAacTimestamp:ho}),fo=ro&&$a||ro,mo=po&&ao||po,go=(qa&&Fa||qa).handleRollover,yo={};yo.ts=fo,yo.aac=mo;var vo=188,_o=function(t,e,i){for(var r,n,s,a,o=0,u=vo,l=!1;u<t.byteLength;)if(71!==t[o]||71!==t[u])o++,u++;else{switch(r=t.subarray(o,u),yo.ts.parseType(r,e.pid)){case"pes":n=yo.ts.parsePesType(r,e.table),s=yo.ts.parsePayloadUnitStartIndicator(r),"audio"===n&&s&&(a=yo.ts.parsePesTime(r))&&(a.type="audio",i.audio.push(a),l=!0)}if(l)break;o+=vo,u+=vo}for(o=(u=t.byteLength)-vo,l=!1;0<=o;)if(71!==t[o]||71!==t[u])o--,u--;else{switch(r=t.subarray(o,u),yo.ts.parseType(r,e.pid)){case"pes":n=yo.ts.parsePesType(r,e.table),s=yo.ts.parsePayloadUnitStartIndicator(r),"audio"===n&&s&&(a=yo.ts.parsePesTime(r))&&(a.type="audio",i.audio.push(a),l=!0)}if(l)break;o-=vo,u-=vo}},bo=function(t,e,i){for(var r,n,s,a,o,u,l,c=0,h=vo,d=!1,p={data:[],size:0};h<t.byteLength;)if(71!==t[c]||71!==t[h])c++,h++;else{switch(r=t.subarray(c,h),yo.ts.parseType(r,e.pid)){case"pes":if(n=yo.ts.parsePesType(r,e.table),s=yo.ts.parsePayloadUnitStartIndicator(r),"video"===n&&(s&&!d&&(a=yo.ts.parsePesTime(r))&&(a.type="video",i.video.push(a),d=!0),!i.firstKeyFrame)){if(s&&0!==p.size){for(o=new Uint8Array(p.size),u=0;p.data.length;)l=p.data.shift(),o.set(l,u),u+=l.byteLength;yo.ts.videoPacketContainsKeyFrame(o)&&(i.firstKeyFrame=yo.ts.parsePesTime(o),i.firstKeyFrame.type="video"),p.size=0}p.data.push(r),p.size+=r.byteLength}}if(d&&i.firstKeyFrame)break;c+=vo,h+=vo}for(c=(h=t.byteLength)-vo,d=!1;0<=c;)if(71!==t[c]||71!==t[h])c--,h--;else{switch(r=t.subarray(c,h),yo.ts.parseType(r,e.pid)){case"pes":n=yo.ts.parsePesType(r,e.table),s=yo.ts.parsePayloadUnitStartIndicator(r),"video"===n&&s&&(a=yo.ts.parsePesTime(r))&&(a.type="video",i.video.push(a),d=!0)}if(d)break;c-=vo,h-=vo}},To=function(t){var e={pid:null,table:null},i={};for(var r in function(t,e){for(var i,r=0,n=vo;n<t.byteLength;)if(71!==t[r]||71!==t[n])r++,n++;else{switch(i=t.subarray(r,n),yo.ts.parseType(i,e.pid)){case"pat":e.pid||(e.pid=yo.ts.parsePat(i));break;case"pmt":e.table||(e.table=yo.ts.parsePmt(i))}if(e.pid&&e.table)return;r+=vo,n+=vo}}(t,e),e.table){if(e.table.hasOwnProperty(r))switch(e.table[r]){case Wa.H264_STREAM_TYPE:i.video=[],bo(t,e,i),0===i.video.length&&delete i.video;break;case Wa.ADTS_STREAM_TYPE:i.audio=[],_o(t,e,i),0===i.audio.length&&delete i.audio}}return i},So=function(t,e){var i,r;return(r=(i=t)[0]==="I".charCodeAt(0)&&i[1]==="D".charCodeAt(0)&&i[2]==="3".charCodeAt(0)?function(t){for(var e,i=!1,r=0,n=null,s=null,a=0,o=0;3<=t.length-o;){switch(yo.aac.parseType(t,o)){case"timed-metadata":if(t.length-o<10){i=!0;break}if((a=yo.aac.parseId3TagSize(t,o))>t.length){i=!0;break}null===s&&(e=t.subarray(o,o+a),s=yo.aac.parseAacTimestamp(e)),o+=a;break;case"audio":if(t.length-o<7){i=!0;break}if((a=yo.aac.parseAdtsSize(t,o))>t.length){i=!0;break}null===n&&(e=t.subarray(o,o+a),n=yo.aac.parseSampleRate(e)),r++,o+=a;break;default:o++}if(i)return null}if(null===n||null===s)return null;var u=9e4/n;return{audio:[{type:"audio",dts:s,pts:s},{type:"audio",dts:s+1024*r*u,pts:s+1024*r*u}]}}(t):To(t))&&(r.audio||r.video)?(function(t,e){if(t.audio&&t.audio.length){var i=e;"undefined"==typeof i&&(i=t.audio[0].dts),t.audio.forEach(function(t){t.dts=go(t.dts,i),t.pts=go(t.pts,i),t.dtsTime=t.dts/9e4,t.ptsTime=t.pts/9e4})}if(t.video&&t.video.length){var r=e;if("undefined"==typeof r&&(r=t.video[0].dts),t.video.forEach(function(t){t.dts=go(t.dts,r),t.pts=go(t.pts,r),t.dtsTime=t.dts/9e4,t.ptsTime=t.pts/9e4}),t.firstKeyFrame){var n=t.firstKeyFrame;n.dts=go(n.dts,r),n.pts=go(n.pts,r),n.dtsTime=n.dts/9e4,n.ptsTime=n.dts/9e4}}}(r,e),r):null};var ko=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},Co=function(){function r(t,e){for(var i=0;i<e.length;i++){var r=e[i];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,e,i){return e&&r(t.prototype,e),i&&r(t,i),t}}(),Eo=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!==("undefined"==typeof e?"undefined":v(e))&&"function"!=typeof e?t:e},wo=function(){var t=[[[],[],[],[],[]],[[],[],[],[],[]]],e=t[0],i=t[1],r=e[4],n=i[4],s=void 0,a=void 0,o=void 0,u=[],l=[],c=void 0,h=void 0,d=void 0,p=void 0,f=void 0;for(s=0;s<256;s++)l[(u[s]=s<<1^283*(s>>7))^s]=s;for(a=o=0;!r[a];a^=c||1,o=l[o]||1)for(d=(d=o^o<<1^o<<2^o<<3^o<<4)>>8^255&d^99,f=16843009*u[h=u[c=u[n[r[a]=d]=a]]]^65537*h^257*c^16843008*a,p=257*u[d]^16843008*d,s=0;s<4;s++)e[s][a]=p=p<<24^p>>>8,i[s][d]=f=f<<24^f>>>8;for(s=0;s<5;s++)e[s]=e[s].slice(0),i[s]=i[s].slice(0);return t},Ao=null,Lo=function(){function c(t){ko(this,c),Ao||(Ao=wo()),this._tables=[[Ao[0][0].slice(),Ao[0][1].slice(),Ao[0][2].slice(),Ao[0][3].slice(),Ao[0][4].slice()],[Ao[1][0].slice(),Ao[1][1].slice(),Ao[1][2].slice(),Ao[1][3].slice(),Ao[1][4].slice()]];var e=void 0,i=void 0,r=void 0,n=void 0,s=void 0,a=this._tables[0][4],o=this._tables[1],u=t.length,l=1;if(4!==u&&6!==u&&8!==u)throw new Error("Invalid aes key size");for(n=t.slice(0),s=[],this._key=[n,s],e=u;e<4*u+28;e++)r=n[e-1],(e%u==0||8===u&&e%u==4)&&(r=a[r>>>24]<<24^a[r>>16&255]<<16^a[r>>8&255]<<8^a[255&r],e%u==0&&(r=r<<8^r>>>24^l<<24,l=l<<1^283*(l>>7))),n[e]=n[e-u]^r;for(i=0;e;i++,e--)r=n[3&i?e:e-4],s[i]=e<=4||i<4?r:o[0][a[r>>>24]]^o[1][a[r>>16&255]]^o[2][a[r>>8&255]]^o[3][a[255&r]]}return c.prototype.decrypt=function(t,e,i,r,n,s){var a=this._key[1],o=t^a[0],u=r^a[1],l=i^a[2],c=e^a[3],h=void 0,d=void 0,p=void 0,f=a.length/4-2,m=void 0,g=4,y=this._tables[1],v=y[0],_=y[1],b=y[2],T=y[3],S=y[4];for(m=0;m<f;m++)h=v[o>>>24]^_[u>>16&255]^b[l>>8&255]^T[255&c]^a[g],d=v[u>>>24]^_[l>>16&255]^b[c>>8&255]^T[255&o]^a[g+1],p=v[l>>>24]^_[c>>16&255]^b[o>>8&255]^T[255&u]^a[g+2],c=v[c>>>24]^_[o>>16&255]^b[u>>8&255]^T[255&l]^a[g+3],g+=4,o=h,u=d,l=p;for(m=0;m<4;m++)n[(3&-m)+s]=S[o>>>24]<<24^S[u>>16&255]<<16^S[l>>8&255]<<8^S[255&c]^a[g++],h=o,o=u,u=l,l=c,c=h},c}(),Po=function(){function t(){ko(this,t),this.listeners={}}return t.prototype.on=function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},t.prototype.off=function(t,e){if(!this.listeners[t])return!1;var i=this.listeners[t].indexOf(e);return this.listeners[t].splice(i,1),-1<i},t.prototype.trigger=function(t){var e=this.listeners[t];if(e)if(2===arguments.length)for(var i=e.length,r=0;r<i;++r)e[r].call(this,arguments[1]);else for(var n=Array.prototype.slice.call(arguments,1),s=e.length,a=0;a<s;++a)e[a].apply(this,n)},t.prototype.dispose=function(){this.listeners={}},t.prototype.pipe=function(e){this.on("data",function(t){e.push(t)})},t}(),Oo=function(e){function i(){ko(this,i);var t=Eo(this,e.call(this,Po));return t.jobs=[],t.delay=1,t.timeout_=null,t}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+("undefined"==typeof e?"undefined":v(e)));t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(i,e),i.prototype.processJob_=function(){this.jobs.shift()(),this.jobs.length?this.timeout_=setTimeout(this.processJob_.bind(this),this.delay):this.timeout_=null},i.prototype.push=function(t){this.jobs.push(t),this.timeout_||(this.timeout_=setTimeout(this.processJob_.bind(this),this.delay))},i}(Po),xo=function(t){return t<<24|(65280&t)<<8|(16711680&t)>>8|t>>>24},Io=function(t,e,i){var r=new Int32Array(t.buffer,t.byteOffset,t.byteLength>>2),n=new Lo(Array.prototype.slice.call(e)),s=new Uint8Array(t.byteLength),a=new Int32Array(s.buffer),o=void 0,u=void 0,l=void 0,c=void 0,h=void 0,d=void 0,p=void 0,f=void 0,m=void 0;for(o=i[0],u=i[1],l=i[2],c=i[3],m=0;m<r.length;m+=4)h=xo(r[m]),d=xo(r[m+1]),p=xo(r[m+2]),f=xo(r[m+3]),n.decrypt(h,d,p,f,a,m),a[m]=xo(a[m]^o),a[m+1]=xo(a[m+1]^u),a[m+2]=xo(a[m+2]^l),a[m+3]=xo(a[m+3]^c),o=h,u=d,l=p,c=f;return s},Do=function(){function u(t,e,i,r){ko(this,u);var n=u.STEP,s=new Int32Array(t.buffer),a=new Uint8Array(t.byteLength),o=0;for(this.asyncStream_=new Oo,this.asyncStream_.push(this.decryptChunk_(s.subarray(o,o+n),e,i,a)),o=n;o<s.length;o+=n)i=new Uint32Array([xo(s[o-4]),xo(s[o-3]),xo(s[o-2]),xo(s[o-1])]),this.asyncStream_.push(this.decryptChunk_(s.subarray(o,o+n),e,i,a));this.asyncStream_.push(function(){var t;r(null,(t=a).subarray(0,t.byteLength-t[t.byteLength-1]))})}return u.prototype.decryptChunk_=function(e,i,r,n){return function(){var t=Io(e,i,r);n.set(t,e.byteOffset)}},Co(u,null,[{key:"STEP",get:function(){return 32e3}}]),u}(),Ro=function(t,e){return/^[a-z]+:/i.test(e)?e:(/\/\//i.test(t)||(t=Os.buildAbsoluteURL(g.location.href,t)),Os.buildAbsoluteURL(t,e))},Mo=As.mergeOptions,Uo=As.log,No=function(n,s){["AUDIO","SUBTITLES"].forEach(function(t){for(var e in n.mediaGroups[t])for(var i in n.mediaGroups[t][e]){var r=n.mediaGroups[t][e][i];s(r,t,e,i)}})},Bo=function(t,e){var i=Mo(t,{}),r=i.playlists[e.uri];if(!r)return null;if(r.segments&&e.segments&&r.segments.length===e.segments.length&&r.mediaSequence===e.mediaSequence)return null;var n=Mo(r,e);r.segments&&(n.segments=function(t,e,i){var r=e.slice();i=i||0;for(var n=Math.min(t.length,e.length+i),s=i;s<n;s++)r[s-i]=Mo(t[s],r[s-i]);return r}(r.segments,e.segments,e.mediaSequence-r.mediaSequence)),n.segments.forEach(function(t){var e,i;e=t,i=n.resolvedUri,e.resolvedUri||(e.resolvedUri=Ro(i,e.uri)),e.key&&!e.key.resolvedUri&&(e.key.resolvedUri=Ro(i,e.key.uri)),e.map&&!e.map.resolvedUri&&(e.map.resolvedUri=Ro(i,e.map.uri))});for(var s=0;s<i.playlists.length;s++)i.playlists[s].uri===e.uri&&(i.playlists[s]=n);return i.playlists[e.uri]=n,i},jo=function(t){for(var e=t.playlists.length;e--;){var i=t.playlists[e];(t.playlists[i.uri]=i).resolvedUri=Ro(t.uri,i.uri),i.id=e,i.attributes||(i.attributes={},Uo.warn("Invalid playlist STREAM-INF detected. Missing BANDWIDTH attribute."))}},Fo=function(e){No(e,function(t){t.uri&&(t.resolvedUri=Ro(e.uri,t.uri))})},Ho=function(t,e){var i=t.segments[t.segments.length-1];return e&&i&&i.duration?1e3*i.duration:500*(t.targetDuration||10)},Vo=function(n){function s(t,e,i){y(this,s);var r=b(this,n.call(this));if(r.srcUrl=t,r.hls_=e,r.withCredentials=i,!r.srcUrl)throw new Error("A non-empty playlist URL is required");return r.state="HAVE_NOTHING",r.on("mediaupdatetimeout",function(){"HAVE_METADATA"===r.state&&(r.state="HAVE_CURRENT_METADATA",r.request=r.hls_.xhr({uri:Ro(r.master.uri,r.media().uri),withCredentials:r.withCredentials},function(t,e){if(r.request)return t?r.playlistRequestError(r.request,r.media().uri,"HAVE_METADATA"):void r.haveMetadata(r.request,r.media().uri)}))}),r}return _(s,n),s.prototype.playlistRequestError=function(t,e,i){this.request=null,i&&(this.state=i),this.error={playlist:this.master.playlists[e],status:t.status,message:"HLS playlist request error at URL: "+e,responseText:t.responseText,code:500<=t.status?4:2},this.trigger("error")},s.prototype.haveMetadata=function(t,e){var i=this;this.request=null,this.state="HAVE_METADATA";var r=new js;r.push(t.responseText),r.end(),r.manifest.uri=e,r.manifest.attributes=r.manifest.attributes||{};var n=Bo(this.master,r.manifest);this.targetDuration=r.manifest.targetDuration,n?(this.master=n,this.media_=this.master.playlists[r.manifest.uri]):this.trigger("playlistunchanged"),this.media().endList||(g.clearTimeout(this.mediaUpdateTimeout),this.mediaUpdateTimeout=g.setTimeout(function(){i.trigger("mediaupdatetimeout")},Ho(this.media(),!!n))),this.trigger("loadedplaylist")},s.prototype.dispose=function(){this.stopRequest(),g.clearTimeout(this.mediaUpdateTimeout)},s.prototype.stopRequest=function(){if(this.request){var t=this.request;this.request=null,t.onreadystatechange=null,t.abort()}},s.prototype.media=function(i){var r=this;if(!i)return this.media_;if("HAVE_NOTHING"===this.state)throw new Error("Cannot switch media playlist from "+this.state);var n=this.state;if("string"==typeof i){if(!this.master.playlists[i])throw new Error("Unknown playlist URI: "+i);i=this.master.playlists[i]}var t=!this.media_||i.uri!==this.media_.uri;if(this.master.playlists[i.uri].endList)return this.request&&(this.request.onreadystatechange=null,this.request.abort(),this.request=null),this.state="HAVE_METADATA",this.media_=i,void(t&&(this.trigger("mediachanging"),this.trigger("mediachange")));if(t){if(this.state="SWITCHING_MEDIA",this.request){if(Ro(this.master.uri,i.uri)===this.request.url)return;this.request.onreadystatechange=null,this.request.abort(),this.request=null}this.media_&&this.trigger("mediachanging"),this.request=this.hls_.xhr({uri:Ro(this.master.uri,i.uri),withCredentials:this.withCredentials},function(t,e){if(r.request){if(t)return r.playlistRequestError(r.request,i.uri,n);r.haveMetadata(e,i.uri),"HAVE_MASTER"===n?r.trigger("loadedmetadata"):r.trigger("mediachange")}})}},s.prototype.pause=function(){this.stopRequest(),g.clearTimeout(this.mediaUpdateTimeout),"HAVE_NOTHING"===this.state&&(this.started=!1),"SWITCHING_MEDIA"===this.state?this.media_?this.state="HAVE_METADATA":this.state="HAVE_MASTER":"HAVE_CURRENT_METADATA"===this.state&&(this.state="HAVE_METADATA")},s.prototype.load=function(t){var e=this;g.clearTimeout(this.mediaUpdateTimeout);var i=this.media();if(t){var r=i?i.targetDuration/2*1e3:5e3;this.mediaUpdateTimeout=g.setTimeout(function(){return e.load()},r)}else this.started?i&&!i.endList?this.trigger("mediaupdatetimeout"):this.trigger("loadedplaylist"):this.start()},s.prototype.start=function(){var r=this;this.started=!0,this.request=this.hls_.xhr({uri:this.srcUrl,withCredentials:this.withCredentials},function(t,e){if(r.request){if(r.request=null,t)return r.error={status:e.status,message:"HLS playlist request error at URL: "+r.srcUrl,responseText:e.responseText,code:2},"HAVE_NOTHING"===r.state&&(r.started=!1),r.trigger("error");var i=new js;return i.push(e.responseText),i.end(),r.state="HAVE_MASTER",i.manifest.uri=r.srcUrl,i.manifest.playlists?(r.master=i.manifest,jo(r.master),Fo(r.master),r.trigger("loadedplaylist"),void(r.request||r.media(i.manifest.playlists[0]))):(r.master={mediaGroups:{AUDIO:{},VIDEO:{},"CLOSED-CAPTIONS":{},SUBTITLES:{}},uri:g.location.href,playlists:[{uri:r.srcUrl,id:0}]},r.master.playlists[r.srcUrl]=r.master.playlists[0],r.master.playlists[0].resolvedUri=r.srcUrl,r.master.playlists[0].attributes=r.master.playlists[0].attributes||{},r.haveMetadata(e,r.srcUrl),r.trigger("loadedmetadata"))}})},s}(As.EventTarget),qo=As.createTimeRange,Wo=function(t,e,i){var r,n;return"undefined"==typeof e&&(e=t.mediaSequence+t.segments.length),e<t.mediaSequence?0:(r=function(t,e){var i=0,r=e-t.mediaSequence,n=t.segments[r];if(n){if("undefined"!=typeof n.start)return{result:n.start,precise:!0};if("undefined"!=typeof n.end)return{result:n.end-n.duration,precise:!0}}for(;r--;){if("undefined"!=typeof(n=t.segments[r]).end)return{result:i+n.end,precise:!0};if(i+=n.duration,"undefined"!=typeof n.start)return{result:i+n.start,precise:!0}}return{result:i,precise:!1}}(t,e)).precise?r.result:(n=function(t,e){for(var i=0,r=void 0,n=e-t.mediaSequence;n<t.segments.length;n++){if("undefined"!=typeof(r=t.segments[n]).start)return{result:r.start-i,precise:!0};if(i+=r.duration,"undefined"!=typeof r.end)return{result:r.end-i,precise:!0}}return{result:-1,precise:!1}}(t,e)).precise?n.result:r.result+i},zo=function(t,e,i){if(!t)return 0;if("number"!=typeof i&&(i=0),"undefined"==typeof e){if(t.totalDuration)return t.totalDuration;if(!t.endList)return g.Infinity}return Wo(t,e,i)},Go=function(t,e,i){var r=0;if(i<e){var n=[i,e];e=n[0],i=n[1]}if(e<0){for(var s=e;s<Math.min(0,i);s++)r+=t.targetDuration;e=0}for(var a=e;a<i;a++)r+=t.segments[a].duration;return r},Xo=function(t){if(!t.segments.length)return 0;for(var e=t.segments.length-1,i=t.segments[e].duration||t.targetDuration,r=i+2*t.targetDuration;e--&&!(r<=(i+=t.segments[e].duration)););return Math.max(0,e)},Yo=function(t,e,i){if(!t||!t.segments)return null;if(t.endList)return zo(t);if(null===e)return null;e=e||0;var r=i?Xo(t):t.segments.length;return Wo(t,t.mediaSequence+r,e)},$o=function(t){return t-Math.floor(t)==0},Ko=function(t,e){if($o(e))return e+.1*t;for(var i=e.toString().split(".")[1].length,r=1;r<=i;r++){var n=Math.pow(10,r),s=e*n;if($o(s)||r===i)return(s+t)/n}},Qo=Ko.bind(null,1),Jo=Ko.bind(null,-1),Zo=function(t){return t.excludeUntil&&t.excludeUntil>Date.now()},tu=function(t){return t.excludeUntil&&t.excludeUntil===1/0},eu=function(t){var e=Zo(t);return!t.disabled&&!e},iu=function(t,e){return e.attributes&&e.attributes[t]},ru=function(t,e){if(1===t.playlists.length)return!0;var i=e.attributes.BANDWIDTH||Number.MAX_VALUE;return 0===t.playlists.filter(function(t){return!!eu(t)&&(t.attributes.BANDWIDTH||0)<i}).length},nu={duration:zo,seekable:function(t,e){var i=e||0,r=Yo(t,e,!0);return null===r?qo():qo(i,r)},safeLiveIndex:Xo,getMediaInfoForTime:function(t,e,i,r){var n=void 0,s=void 0,a=t.segments.length,o=e-r;if(o<0){if(0<i)for(n=i-1;0<=n;n--)if(s=t.segments[n],0<(o+=Jo(s.duration)))return{mediaIndex:n,startTime:r-Go(t,i,n)};return{mediaIndex:0,startTime:e}}if(i<0){for(n=i;n<0;n++)if((o-=t.targetDuration)<0)return{mediaIndex:0,startTime:e};i=0}for(n=i;n<a;n++)if(s=t.segments[n],(o-=Qo(s.duration))<0)return{mediaIndex:n,startTime:r+Go(t,i,n)};return{mediaIndex:a-1,startTime:e}},isEnabled:eu,isDisabled:function(t){return t.disabled},isBlacklisted:Zo,isIncompatible:tu,playlistEnd:Yo,isAes:function(t){for(var e=0;e<t.segments.length;e++)if(t.segments[e].key)return!0;return!1},isFmp4:function(t){for(var e=0;e<t.segments.length;e++)if(t.segments[e].map)return!0;return!1},hasAttribute:iu,estimateSegmentRequestTime:function(t,e,i){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:0;return iu("BANDWIDTH",i)?(t*i.attributes.BANDWIDTH-8*r)/e:NaN},isLowestEnabledRendition:ru},su=As.xhr,au=As.mergeOptions,ou=function(){return function t(e,r){e=au({timeout:45e3},e);var i=t.beforeRequest||As.Hls.xhr.beforeRequest;if(i&&"function"==typeof i){var n=i(e);n&&(e=n)}var s=su(e,function(t,e){var i=s.response;!t&&i&&(s.responseTime=Date.now(),s.roundTripTime=s.responseTime-s.requestTime,s.bytesReceived=i.byteLength||i.length,s.bandwidth||(s.bandwidth=Math.floor(s.bytesReceived/s.roundTripTime*8*1e3))),e.headers&&(s.responseHeaders=e.headers),t&&"ETIMEDOUT"===t.code&&(s.timedout=!0),t||s.aborted||200===e.statusCode||206===e.statusCode||0===e.statusCode||(t=new Error("XHR Failed with a response of: "+(s&&(i||s.responseText)))),r(t,s)}),a=s.abort;return s.abort=function(){return s.aborted=!0,a.apply(s,arguments)},s.uri=e.uri,s.requestTime=Date.now(),s}},uu=function(t,e){var i=t.toString(16);return"00".substring(0,2-i.length)+i+(e%2?" ":"")},lu=function(t){return 32<=t&&t<126?String.fromCharCode(t):"."},cu=function(i){var r={};return Object.keys(i).forEach(function(t){var e=i[t];ArrayBuffer.isView(e)?r[t]={bytes:e.buffer,byteOffset:e.byteOffset,byteLength:e.byteLength}:r[t]=e}),r},hu=function(t){var e=t.byterange||{length:1/0,offset:0};return[e.length,e.offset,t.resolvedUri].join(",")},du=function(t){for(var e=Array.prototype.slice.call(t),i="",r=0;r<e.length/16;r++)i+=e.slice(16*r,16*r+16).map(uu).join("")+" "+e.slice(16*r,16*r+16).map(lu).join("")+"\n";return i},pu=Object.freeze({createTransferableMessage:cu,initSegmentId:hu,hexDump:du,tagDump:function(t){var e=t.bytes;return du(e)},textRanges:function(t){var e,i,r="",n=void 0;for(n=0;n<t.length;n++)r+=(i=n,(e=t).start(i)+"-"+e.end(i)+" ");return r}}),fu=1/30,mu=function(t,e){var i=[],r=void 0;if(t&&t.length)for(r=0;r<t.length;r++)e(t.start(r),t.end(r))&&i.push([t.start(r),t.end(r)]);return As.createTimeRanges(i)},gu=function(t,i){return mu(t,function(t,e){return t-fu<=i&&i<=e+fu})},yu=function(t,e){return mu(t,function(t){return e<=t-fu})},vu=function(t){var e=[];if(!t||!t.length)return"";for(var i=0;i<t.length;i++)e.push(t.start(i)+" => "+t.end(i));return e.join(", ")},_u=function(t){for(var e=[],i=0;i<t.length;i++)e.push({start:t.start(i),end:t.end(i)});return e},bu=function(t,e,i){var r=void 0,n=void 0;if(i&&i.cues)for(r=i.cues.length;r--;)(n=i.cues[r]).startTime<=e&&n.endTime>=t&&i.removeCue(n)},Tu=function(t){return isNaN(t)||Math.abs(t)===1/0?Number.MAX_VALUE:t},Su=function(t,e,i){var n=g.WebKitDataCue||g.VTTCue;if(e&&e.forEach(function(t){var e=t.stream;this.inbandTextTracks_[e].addCue(new n(t.startTime+this.timestampOffset,t.endTime+this.timestampOffset,t.text))},t),i){var s=Tu(t.mediaSource_.duration);if(i.forEach(function(t){var r=t.cueTime+this.timestampOffset;t.frames.forEach(function(t){var e,i=new n(r,r,t.value||t.url||t.data||"");i.frame=t,i.value=t,e=i,Object.defineProperties(e.frame,{id:{get:function(){return As.log.warn("cue.frame.id is deprecated. Use cue.value.key instead."),e.value.key}},value:{get:function(){return As.log.warn("cue.frame.value is deprecated. Use cue.value.data instead."),e.value.data}},privateData:{get:function(){return As.log.warn("cue.frame.privateData is deprecated. Use cue.value.data instead."),e.value.data}}}),this.metadataTrack_.addCue(i)},this)},t),t.metadataTrack_&&t.metadataTrack_.cues&&t.metadataTrack_.cues.length){for(var r=t.metadataTrack_.cues,a=[],o=0;o<r.length;o++)r[o]&&a.push(r[o]);var u=a.reduce(function(t,e){var i=t[e.startTime]||[];return i.push(e),t[e.startTime]=i,t},{}),l=Object.keys(u).sort(function(t,e){return Number(t)-Number(e)});l.forEach(function(t,e){var i=u[t],r=Number(l[e+1])||s;i.forEach(function(t){t.endTime=r})})}}},ku="undefined"!=typeof window?window:{},Cu="undefined"==typeof Symbol?"__target":Symbol(),Eu="application/javascript",wu=ku.BlobBuilder||ku.WebKitBlobBuilder||ku.MozBlobBuilder||ku.MSBlobBuilder,Au=ku.URL||ku.webkitURL||Au&&Au.msURL,Lu=ku.Worker;function Pu(n,s){return function(t){var e=this;if(!s)return new Lu(n);if(Lu&&!t){var i=Du(s.toString().replace(/^function.+?{/,"").slice(0,-1));return this[Cu]=new Lu(i),function(t,e){if(!t||!e)return;var i=t.terminate;t.objURL=e,t.terminate=function(){t.objURL&&Au.revokeObjectURL(t.objURL),i.call(t)}}(this[Cu],i),this[Cu]}var r={postMessage:function(t){e.onmessage&&setTimeout(function(){e.onmessage({data:t,target:r})})}};s.call(r),this.postMessage=function(t){setTimeout(function(){r.onmessage({data:t,target:e})})},this.isThisThread=!0}}if(Lu){var Ou,xu=Du("self.onmessage = function () {}"),Iu=new Uint8Array(1);try{(Ou=new Lu(xu)).postMessage(Iu,[Iu.buffer])}catch(t){Lu=null}finally{Au.revokeObjectURL(xu),Ou&&Ou.terminate()}}function Du(e){try{return Au.createObjectURL(new Blob([e],{type:Eu}))}catch(t){var i=new wu;return i.append(e),Au.createObjectURL(i.getBlob(type))}}var Ru=new Pu("./transmuxer-worker.worker.js",function(ie,t){var re=this;!function(){var o,e,i,n,s,r,t,a,u,l,c,h,d,p,f,m,g,y,v,_,b,T,S,k,C,E,w,A,L,P,O,x,I,D,R,M,U,N,B,j,F="undefined"!=typeof ie?ie:"undefined"!=typeof global?global:"undefined"!=typeof re?re:{},H="undefined"!=typeof ie?ie:"undefined"!=typeof F?F:"undefined"!=typeof re?re:{},V=Math.pow(2,32)-1;!function(){var t;if(T={avc1:[],avcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],mvex:[],mvhd:[],sdtp:[],smhd:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],styp:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[]},"undefined"!=typeof Uint8Array){for(t in T)T.hasOwnProperty(t)&&(T[t]=[t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2),t.charCodeAt(3)]);S=new Uint8Array(["i".charCodeAt(0),"s".charCodeAt(0),"o".charCodeAt(0),"m".charCodeAt(0)]),C=new Uint8Array(["a".charCodeAt(0),"v".charCodeAt(0),"c".charCodeAt(0),"1".charCodeAt(0)]),k=new Uint8Array([0,0,0,1]),E=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),w=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]),A={video:E,audio:w},O=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),P=new Uint8Array([0,0,0,0,0,0,0,0]),x=new Uint8Array([0,0,0,0,0,0,0,0]),I=x,D=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),R=x,L=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0])}}(),o=function(t){var e,i,r=[],n=0;for(e=1;e<arguments.length;e++)r.push(arguments[e]);for(e=r.length;e--;)n+=r[e].byteLength;for(i=new Uint8Array(n+8),new DataView(i.buffer,i.byteOffset,i.byteLength).setUint32(0,i.byteLength),i.set(t,4),e=0,n=8;e<r.length;e++)i.set(r[e],n),n+=r[e].byteLength;return i},e=function(){return o(T.dinf,o(T.dref,O))},i=function(t){return o(T.esds,new Uint8Array([0,0,0,0,3,25,0,0,0,4,17,64,21,0,6,0,0,0,218,192,0,0,218,192,5,2,t.audioobjecttype<<3|t.samplingfrequencyindex>>>1,t.samplingfrequencyindex<<7|t.channelcount<<3,6,1,2]))},f=function(t){return o(T.hdlr,A[t])},p=function(t){var e=new Uint8Array([0,0,0,0,0,0,0,2,0,0,0,3,0,1,95,144,t.duration>>>24&255,t.duration>>>16&255,t.duration>>>8&255,255&t.duration,85,196,0,0]);return t.samplerate&&(e[12]=t.samplerate>>>24&255,e[13]=t.samplerate>>>16&255,e[14]=t.samplerate>>>8&255,e[15]=255&t.samplerate),o(T.mdhd,e)},d=function(t){return o(T.mdia,p(t),f(t.type),r(t))},s=function(t){return o(T.mfhd,new Uint8Array([0,0,0,0,(4278190080&t)>>24,(16711680&t)>>16,(65280&t)>>8,255&t]))},r=function(t){return o(T.minf,"video"===t.type?o(T.vmhd,L):o(T.smhd,P),e(),g(t))},t=function(t,e){for(var i=[],r=e.length;r--;)i[r]=v(e[r]);return o.apply(null,[T.moof,s(t)].concat(i))},a=function(t){for(var e=t.length,i=[];e--;)i[e]=c(t[e]);return o.apply(null,[T.moov,l(4294967295)].concat(i).concat(u(t)))},u=function(t){for(var e=t.length,i=[];e--;)i[e]=_(t[e]);return o.apply(null,[T.mvex].concat(i))},l=function(t){var e=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,2,0,1,95,144,(4278190080&t)>>24,(16711680&t)>>16,(65280&t)>>8,255&t,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]);return o(T.mvhd,e)},m=function(t){var e,i,r=t.samples||[],n=new Uint8Array(4+r.length);for(i=0;i<r.length;i++)e=r[i].flags,n[i+4]=e.dependsOn<<4|e.isDependedOn<<2|e.hasRedundancy;return o(T.sdtp,n)},g=function(t){return o(T.stbl,y(t),o(T.stts,R),o(T.stsc,I),o(T.stsz,D),o(T.stco,x))},y=function(t){return o(T.stsd,new Uint8Array([0,0,0,0,0,0,0,1]),"video"===t.type?M(t):U(t))},M=function(t){var e,i=t.sps||[],r=t.pps||[],n=[],s=[];for(e=0;e<i.length;e++)n.push((65280&i[e].byteLength)>>>8),n.push(255&i[e].byteLength),n=n.concat(Array.prototype.slice.call(i[e]));for(e=0;e<r.length;e++)s.push((65280&r[e].byteLength)>>>8),s.push(255&r[e].byteLength),s=s.concat(Array.prototype.slice.call(r[e]));return o(T.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(65280&t.width)>>8,255&t.width,(65280&t.height)>>8,255&t.height,0,72,0,0,0,72,0,0,0,0,0,0,0,1,19,118,105,100,101,111,106,115,45,99,111,110,116,114,105,98,45,104,108,115,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),o(T.avcC,new Uint8Array([1,t.profileIdc,t.profileCompatibility,t.levelIdc,255].concat([i.length]).concat(n).concat([r.length]).concat(s))),o(T.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])))},U=function(t){return o(T.mp4a,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,(65280&t.channelcount)>>8,255&t.channelcount,(65280&t.samplesize)>>8,255&t.samplesize,0,0,0,0,(65280&t.samplerate)>>8,255&t.samplerate,0,0]),i(t))},h=function(t){var e=new Uint8Array([0,0,0,7,0,0,0,0,0,0,0,0,(4278190080&t.id)>>24,(16711680&t.id)>>16,(65280&t.id)>>8,255&t.id,0,0,0,0,(4278190080&t.duration)>>24,(16711680&t.duration)>>16,(65280&t.duration)>>8,255&t.duration,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,(65280&t.width)>>8,255&t.width,0,0,(65280&t.height)>>8,255&t.height,0,0]);return o(T.tkhd,e)},v=function(t){var e,i,r,n,s,a;return e=o(T.tfhd,new Uint8Array([0,0,0,58,(4278190080&t.id)>>24,(16711680&t.id)>>16,(65280&t.id)>>8,255&t.id,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0])),s=Math.floor(t.baseMediaDecodeTime/(V+1)),a=Math.floor(t.baseMediaDecodeTime%(V+1)),i=o(T.tfdt,new Uint8Array([1,0,0,0,s>>>24&255,s>>>16&255,s>>>8&255,255&s,a>>>24&255,a>>>16&255,a>>>8&255,255&a])),92,"audio"===t.type?(r=b(t,92),o(T.traf,e,i,r)):(n=m(t),r=b(t,n.length+92),o(T.traf,e,i,r,n))},c=function(t){return t.duration=t.duration||4294967295,o(T.trak,h(t),d(t))},_=function(t){var e=new Uint8Array([0,0,0,0,(4278190080&t.id)>>24,(16711680&t.id)>>16,(65280&t.id)>>8,255&t.id,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]);return"video"!==t.type&&(e[e.length-1]=0),o(T.trex,e)},j=function(t,e){var i=0,r=0,n=0,s=0;return t.length&&(void 0!==t[0].duration&&(i=1),void 0!==t[0].size&&(r=2),void 0!==t[0].flags&&(n=4),void 0!==t[0].compositionTimeOffset&&(s=8)),[0,0,i|r|n|s,1,(4278190080&t.length)>>>24,(16711680&t.length)>>>16,(65280&t.length)>>>8,255&t.length,(4278190080&e)>>>24,(16711680&e)>>>16,(65280&e)>>>8,255&e]},B=function(t,e){var i,r,n,s;for(e+=20+16*(r=t.samples||[]).length,i=j(r,e),s=0;s<r.length;s++)n=r[s],i=i.concat([(4278190080&n.duration)>>>24,(16711680&n.duration)>>>16,(65280&n.duration)>>>8,255&n.duration,(4278190080&n.size)>>>24,(16711680&n.size)>>>16,(65280&n.size)>>>8,255&n.size,n.flags.isLeading<<2|n.flags.dependsOn,n.flags.isDependedOn<<6|n.flags.hasRedundancy<<4|n.flags.paddingValue<<1|n.flags.isNonSyncSample,61440&n.flags.degradationPriority,15&n.flags.degradationPriority,(4278190080&n.compositionTimeOffset)>>>24,(16711680&n.compositionTimeOffset)>>>16,(65280&n.compositionTimeOffset)>>>8,255&n.compositionTimeOffset]);return o(T.trun,new Uint8Array(i))},N=function(t,e){var i,r,n,s;for(e+=20+8*(r=t.samples||[]).length,i=j(r,e),s=0;s<r.length;s++)n=r[s],i=i.concat([(4278190080&n.duration)>>>24,(16711680&n.duration)>>>16,(65280&n.duration)>>>8,255&n.duration,(4278190080&n.size)>>>24,(16711680&n.size)>>>16,(65280&n.size)>>>8,255&n.size]);return o(T.trun,new Uint8Array(i))},b=function(t,e){return"audio"===t.type?N(t,e):B(t,e)};var q={ftyp:n=function(){return o(T.ftyp,S,k,S,C)},mdat:function(t){return o(T.mdat,t)},moof:t,moov:a,initSegment:function(t){var e,i=n(),r=a(t);return(e=new Uint8Array(i.byteLength+r.byteLength)).set(i),e.set(r,i.byteLength),e}},W=function(){this.init=function(){var s={};this.on=function(t,e){s[t]||(s[t]=[]),s[t]=s[t].concat(e)},this.off=function(t,e){var i;return!!s[t]&&(i=s[t].indexOf(e),s[t]=s[t].slice(),s[t].splice(i,1),-1<i)},this.trigger=function(t){var e,i,r,n;if(e=s[t])if(2===arguments.length)for(r=e.length,i=0;i<r;++i)e[i].call(this,arguments[1]);else{for(n=[],i=arguments.length,i=1;i<arguments.length;++i)n.push(arguments[i]);for(r=e.length,i=0;i<r;++i)e[i].apply(this,n)}},this.dispose=function(){s={}}}};W.prototype.pipe=function(e){return this.on("data",function(t){e.push(t)}),this.on("done",function(t){e.flush(t)}),e},W.prototype.push=function(t){this.trigger("data",t)},W.prototype.flush=function(t){this.trigger("done",t)};var z=W,G=function t(){t.prototype.init.call(this),this.captionPackets_=[],this.ccStreams_=[new Q(0,0),new Q(0,1),new Q(1,0),new Q(1,1)],this.reset(),this.ccStreams_.forEach(function(t){t.on("data",this.trigger.bind(this,"data")),t.on("done",this.trigger.bind(this,"done"))},this)};(G.prototype=new z).push=function(t){var e,i,r;if("sei_rbsp"===t.nalUnitType&&(4===(e=function(t){for(var e=0,i={payloadType:-1,payloadSize:0},r=0,n=0;e<t.byteLength&&128!==t[e];){for(;255===t[e];)r+=255,e++;for(r+=t[e++];255===t[e];)n+=255,e++;if(n+=t[e++],!i.payload&&4===r){i.payloadType=r,i.payloadSize=n,i.payload=t.subarray(e,e+n);break}e+=n,n=r=0}return i}(t.escapedRBSP)).payloadType&&(i=181!==(r=e).payload[0]?null:49!=(r.payload[1]<<8|r.payload[2])?null:"GA94"!==String.fromCharCode(r.payload[3],r.payload[4],r.payload[5],r.payload[6])?null:3!==r.payload[7]?null:r.payload.subarray(8,r.payload.length-1))))if(t.dts<this.latestDts_)this.ignoreNextEqualDts_=!0;else{if(t.dts===this.latestDts_&&this.ignoreNextEqualDts_)return this.numSameDts_--,void(this.numSameDts_||(this.ignoreNextEqualDts_=!1));this.captionPackets_=this.captionPackets_.concat(function(t,e){var i,r,n,s,a=[];if(!(64&e[0]))return a;for(r=31&e[0],i=0;i<r;i++)s={type:3&e[2+(n=3*i)],pts:t},4&e[n+2]&&(s.ccData=e[n+3]<<8|e[n+4],a.push(s));return a}(t.pts,i)),this.latestDts_!==t.dts&&(this.numSameDts_=0),this.numSameDts_++,this.latestDts_=t.dts}},G.prototype.flush=function(){this.captionPackets_.length?(this.captionPackets_.forEach(function(t,e){t.presortIndex=e}),this.captionPackets_.sort(function(t,e){return t.pts===e.pts?t.presortIndex-e.presortIndex:t.pts-e.pts}),this.captionPackets_.forEach(function(t){t.type<2&&this.dispatchCea608Packet(t)},this),this.captionPackets_.length=0,this.ccStreams_.forEach(function(t){t.flush()},this)):this.ccStreams_.forEach(function(t){t.flush()},this)},G.prototype.reset=function(){this.latestDts_=null,this.ignoreNextEqualDts_=!1,this.numSameDts_=0,this.activeCea608Channel_=[null,null],this.ccStreams_.forEach(function(t){t.reset()})},G.prototype.dispatchCea608Packet=function(t){this.setsChannel1Active(t)?this.activeCea608Channel_[t.type]=0:this.setsChannel2Active(t)&&(this.activeCea608Channel_[t.type]=1),null!==this.activeCea608Channel_[t.type]&&this.ccStreams_[(t.type<<1)+this.activeCea608Channel_[t.type]].push(t)},G.prototype.setsChannel1Active=function(t){return 4096==(30720&t.ccData)},G.prototype.setsChannel2Active=function(t){return 6144==(30720&t.ccData)};var X={42:225,92:233,94:237,95:243,96:250,123:231,124:247,125:209,126:241,127:9608,304:174,305:176,306:189,307:191,308:8482,309:162,310:163,311:9834,312:224,313:160,314:232,315:226,316:234,317:238,318:244,319:251,544:193,545:201,546:211,547:218,548:220,549:252,550:8216,551:161,552:42,553:39,554:8212,555:169,556:8480,557:8226,558:8220,559:8221,560:192,561:194,562:199,563:200,564:202,565:203,566:235,567:206,568:207,569:239,570:212,571:217,572:249,573:219,574:171,575:187,800:195,801:227,802:205,803:204,804:236,805:210,806:242,807:213,808:245,809:123,810:125,811:92,812:94,813:95,814:124,815:126,816:196,817:228,818:214,819:246,820:223,821:165,822:164,823:9474,824:197,825:229,826:216,827:248,828:9484,829:9488,830:9492,831:9496},Y=function(t){return null===t?"":(t=X[t]||t,String.fromCharCode(t))},$=[4352,4384,4608,4640,5376,5408,5632,5664,5888,5920,4096,4864,4896,5120,5152],K=function(){for(var t=[],e=15;e--;)t.push("");return t},Q=function t(e,i){t.prototype.init.call(this),this.field_=e||0,this.dataChannel_=i||0,this.name_="CC"+(1+(this.field_<<1|this.dataChannel_)),this.setConstants(),this.reset(),this.push=function(t){var e,i,r,n,s;if((e=32639&t.ccData)!==this.lastControlCode_){if(4096==(61440&e)?this.lastControlCode_=e:e!==this.PADDING_&&(this.lastControlCode_=null),r=e>>>8,n=255&e,e!==this.PADDING_)if(e===this.RESUME_CAPTION_LOADING_)this.mode_="popOn";else if(e===this.END_OF_CAPTION_)this.clearFormatting(t.pts),this.flushDisplayed(t.pts),i=this.displayed_,this.displayed_=this.nonDisplayed_,this.nonDisplayed_=i,this.startPts_=t.pts;else if(e===this.ROLL_UP_2_ROWS_)this.topRow_=13,this.mode_="rollUp";else if(e===this.ROLL_UP_3_ROWS_)this.topRow_=12,this.mode_="rollUp";else if(e===this.ROLL_UP_4_ROWS_)this.topRow_=11,this.mode_="rollUp";else if(e===this.CARRIAGE_RETURN_)this.clearFormatting(t.pts),this.flushDisplayed(t.pts),this.shiftRowsUp_(),this.startPts_=t.pts;else if(e===this.BACKSPACE_)"popOn"===this.mode_?this.nonDisplayed_[14]=this.nonDisplayed_[14].slice(0,-1):this.displayed_[14]=this.displayed_[14].slice(0,-1);else if(e===this.ERASE_DISPLAYED_MEMORY_)this.flushDisplayed(t.pts),this.displayed_=K();else if(e===this.ERASE_NON_DISPLAYED_MEMORY_)this.nonDisplayed_=K();else if(e===this.RESUME_DIRECT_CAPTIONING_)this.mode_="paintOn";else if(this.isSpecialCharacter(r,n))s=Y((r=(3&r)<<8)|n),this[this.mode_](t.pts,s),this.column_++;else if(this.isExtCharacter(r,n))"popOn"===this.mode_?this.nonDisplayed_[this.row_]=this.nonDisplayed_[this.row_].slice(0,-1):this.displayed_[14]=this.displayed_[14].slice(0,-1),s=Y((r=(3&r)<<8)|n),this[this.mode_](t.pts,s),this.column_++;else if(this.isMidRowCode(r,n))this.clearFormatting(t.pts),this[this.mode_](t.pts," "),this.column_++,14==(14&n)&&this.addFormatting(t.pts,["i"]),1==(1&n)&&this.addFormatting(t.pts,["u"]);else if(this.isOffsetControlCode(r,n))this.column_+=3&n;else if(this.isPAC(r,n)){var a=$.indexOf(7968&e);a!==this.row_&&(this.clearFormatting(t.pts),this.row_=a),1&n&&-1===this.formatting_.indexOf("u")&&this.addFormatting(t.pts,["u"]),16==(16&e)&&(this.column_=4*((14&e)>>1)),this.isColorPAC(n)&&14==(14&n)&&this.addFormatting(t.pts,["i"])}else this.isNormalChar(r)&&(0===n&&(n=null),s=Y(r),s+=Y(n),this[this.mode_](t.pts,s),this.column_+=s.length)}else this.lastControlCode_=null}};Q.prototype=new z,Q.prototype.flushDisplayed=function(t){var e=this.displayed_.map(function(t){return t.trim()}).join("\n").replace(/^\n+|\n+$/g,"");e.length&&this.trigger("data",{startPts:this.startPts_,endPts:t,text:e,stream:this.name_})},Q.prototype.reset=function(){this.mode_="popOn",this.topRow_=0,this.startPts_=0,this.displayed_=K(),this.nonDisplayed_=K(),this.lastControlCode_=null,this.column_=0,this.row_=14,this.formatting_=[]},Q.prototype.setConstants=function(){0===this.dataChannel_?(this.BASE_=16,this.EXT_=17,this.CONTROL_=(20|this.field_)<<8,this.OFFSET_=23):1===this.dataChannel_&&(this.BASE_=24,this.EXT_=25,this.CONTROL_=(28|this.field_)<<8,this.OFFSET_=31),this.PADDING_=0,this.RESUME_CAPTION_LOADING_=32|this.CONTROL_,this.END_OF_CAPTION_=47|this.CONTROL_,this.ROLL_UP_2_ROWS_=37|this.CONTROL_,this.ROLL_UP_3_ROWS_=38|this.CONTROL_,this.ROLL_UP_4_ROWS_=39|this.CONTROL_,this.CARRIAGE_RETURN_=45|this.CONTROL_,this.RESUME_DIRECT_CAPTIONING_=41|this.CONTROL_,this.BACKSPACE_=33|this.CONTROL_,this.ERASE_DISPLAYED_MEMORY_=44|this.CONTROL_,this.ERASE_NON_DISPLAYED_MEMORY_=46|this.CONTROL_},Q.prototype.isSpecialCharacter=function(t,e){return t===this.EXT_&&48<=e&&e<=63},Q.prototype.isExtCharacter=function(t,e){return(t===this.EXT_+1||t===this.EXT_+2)&&32<=e&&e<=63},Q.prototype.isMidRowCode=function(t,e){return t===this.EXT_&&32<=e&&e<=47},Q.prototype.isOffsetControlCode=function(t,e){return t===this.OFFSET_&&33<=e&&e<=35},Q.prototype.isPAC=function(t,e){return t>=this.BASE_&&t<this.BASE_+8&&64<=e&&e<=127},Q.prototype.isColorPAC=function(t){return 64<=t&&t<=79||96<=t&&t<=127},Q.prototype.isNormalChar=function(t){return 32<=t&&t<=127},Q.prototype.addFormatting=function(t,e){this.formatting_=this.formatting_.concat(e);var i=e.reduce(function(t,e){return t+"<"+e+">"},"");this[this.mode_](t,i)},Q.prototype.clearFormatting=function(t){if(this.formatting_.length){var e=this.formatting_.reverse().reduce(function(t,e){return t+"</"+e+">"},"");this.formatting_=[],this[this.mode_](t,e)}},Q.prototype.popOn=function(t,e){var i=this.nonDisplayed_[this.row_];i+=e,this.nonDisplayed_[this.row_]=i},Q.prototype.rollUp=function(t,e){var i=this.displayed_[14];i+=e,this.displayed_[14]=i},Q.prototype.shiftRowsUp_=function(){var t;for(t=0;t<this.topRow_;t++)this.displayed_[t]="";for(t=this.topRow_;t<14;t++)this.displayed_[t]=this.displayed_[t+1];this.displayed_[14]=""},Q.prototype.paintOn=function(){};var J={CaptionStream:G,Cea608Stream:Q},Z={H264_STREAM_TYPE:27,ADTS_STREAM_TYPE:15,METADATA_STREAM_TYPE:21},tt=function(t,e){var i=1;for(e<t&&(i=-1);4294967296<Math.abs(e-t);)t+=8589934592*i;return t},et=function t(e){var i,r;t.prototype.init.call(this),this.type_=e,this.push=function(t){t.type===this.type_&&(void 0===r&&(r=t.dts),t.dts=tt(t.dts,r),t.pts=tt(t.pts,r),i=t.dts,this.trigger("data",t))},this.flush=function(){r=i,this.trigger("done")},this.discontinuity=function(){i=r=void 0}};et.prototype=new z;var it,rt=et,nt=function(t,e,i){var r,n="";for(r=e;r<i;r++)n+="%"+("00"+t[r].toString(16)).slice(-2);return n},st=function(t,e,i){return decodeURIComponent(nt(t,e,i))},at=function(t){return t[0]<<21|t[1]<<14|t[2]<<7|t[3]},ot={TXXX:function(t){var e;if(3===t.data[0]){for(e=1;e<t.data.length;e++)if(0===t.data[e]){t.description=st(t.data,1,e),t.value=st(t.data,e+1,t.data.length).replace(/\0*$/,"");break}t.data=t.value}},WXXX:function(t){var e;if(3===t.data[0])for(e=1;e<t.data.length;e++)if(0===t.data[e]){t.description=st(t.data,1,e),t.url=st(t.data,e+1,t.data.length);break}},PRIV:function(t){var e,i;for(e=0;e<t.data.length;e++)if(0===t.data[e]){t.owner=(i=t.data,unescape(nt(i,0,e)));break}t.privateData=t.data.subarray(e+1),t.data=t.privateData}};(it=function(t){var e,u={debug:!(!t||!t.debug),descriptor:t&&t.descriptor},l=0,c=[],h=0;if(it.prototype.init.call(this),this.dispatchType=Z.METADATA_STREAM_TYPE.toString(16),u.descriptor)for(e=0;e<u.descriptor.length;e++)this.dispatchType+=("00"+u.descriptor[e].toString(16)).slice(-2);this.push=function(t){var e,i,r,n,s;if("timed-metadata"===t.type)if(t.dataAlignmentIndicator&&(h=0,c.length=0),0===c.length&&(t.data.length<10||t.data[0]!=="I".charCodeAt(0)||t.data[1]!=="D".charCodeAt(0)||t.data[2]!=="3".charCodeAt(0)))u.debug;else if(c.push(t),h+=t.data.byteLength,1===c.length&&(l=at(t.data.subarray(6,10)),l+=10),!(h<l)){for(e={data:new Uint8Array(l),frames:[],pts:c[0].pts,dts:c[0].dts},s=0;s<l;)e.data.set(c[0].data.subarray(0,l-s),s),s+=c[0].data.byteLength,h-=c[0].data.byteLength,c.shift();i=10,64&e.data[5]&&(i+=4,i+=at(e.data.subarray(10,14)),l-=at(e.data.subarray(16,20)));do{if((r=at(e.data.subarray(i+4,i+8)))<1)return;if((n={id:String.fromCharCode(e.data[i],e.data[i+1],e.data[i+2],e.data[i+3]),data:e.data.subarray(i+10,i+r+10)}).key=n.id,ot[n.id]&&(ot[n.id](n),"com.apple.streaming.transportStreamTimestamp"===n.owner)){var a=n.data,o=(1&a[3])<<30|a[4]<<22|a[5]<<14|a[6]<<6|a[7]>>>2;o*=4,o+=3&a[7],n.timeStamp=o,void 0===e.pts&&void 0===e.dts&&(e.pts=n.timeStamp,e.dts=n.timeStamp),this.trigger("timestamp",n)}e.frames.push(n),i+=10,i+=r}while(i<l);this.trigger("data",e)}}}).prototype=new z;var ut,lt,ct,ht=it,dt=rt;(ut=function(){var n=new Uint8Array(188),s=0;ut.prototype.init.call(this),this.push=function(t){var e,i=0,r=188;for(s?((e=new Uint8Array(t.byteLength+s)).set(n.subarray(0,s)),e.set(t,s),s=0):e=t;r<e.byteLength;)71!==e[i]||71!==e[r]?(i++,r++):(this.trigger("data",e.subarray(i,r)),i+=188,r+=188);i<e.byteLength&&(n.set(e.subarray(i),0),s=e.byteLength-i)},this.flush=function(){188===s&&71===n[0]&&(this.trigger("data",n),s=0),this.trigger("done")}}).prototype=new z,(lt=function(){var r,n,s,a;lt.prototype.init.call(this),(a=this).packetsWaitingForPmt=[],this.programMapTable=void 0,r=function(t,e){var i=0;e.payloadUnitStartIndicator&&(i+=t[i]+1),"pat"===e.type?n(t.subarray(i),e):s(t.subarray(i),e)},n=function(t,e){e.section_number=t[7],e.last_section_number=t[8],a.pmtPid=(31&t[10])<<8|t[11],e.pmtPid=a.pmtPid},s=function(t,e){var i,r;if(1&t[5]){for(a.programMapTable={video:null,audio:null,"timed-metadata":{}},i=3+((15&t[1])<<8|t[2])-4,r=12+((15&t[10])<<8|t[11]);r<i;){var n=t[r],s=(31&t[r+1])<<8|t[r+2];n===Z.H264_STREAM_TYPE&&null===a.programMapTable.video?a.programMapTable.video=s:n===Z.ADTS_STREAM_TYPE&&null===a.programMapTable.audio?a.programMapTable.audio=s:n===Z.METADATA_STREAM_TYPE&&(a.programMapTable["timed-metadata"][s]=n),r+=5+((15&t[r+3])<<8|t[r+4])}e.programMapTable=a.programMapTable}},this.push=function(t){var e={},i=4;if(e.payloadUnitStartIndicator=!!(64&t[1]),e.pid=31&t[1],e.pid<<=8,e.pid|=t[2],1<(48&t[3])>>>4&&(i+=t[i]+1),0===e.pid)e.type="pat",r(t.subarray(i),e),this.trigger("data",e);else if(e.pid===this.pmtPid)for(e.type="pmt",r(t.subarray(i),e),this.trigger("data",e);this.packetsWaitingForPmt.length;)this.processPes_.apply(this,this.packetsWaitingForPmt.shift());else void 0===this.programMapTable?this.packetsWaitingForPmt.push([t,i,e]):this.processPes_(t,i,e)},this.processPes_=function(t,e,i){i.pid===this.programMapTable.video?i.streamType=Z.H264_STREAM_TYPE:i.pid===this.programMapTable.audio?i.streamType=Z.ADTS_STREAM_TYPE:i.streamType=this.programMapTable["timed-metadata"][i.pid],i.type="pes",i.data=t.subarray(e),this.trigger("data",i)}}).prototype=new z,lt.STREAM_TYPES={h264:27,adts:15},(ct=function(){var d=this,r={data:[],size:0},n={data:[],size:0},s={data:[],size:0},a=function(t,e,i){var r,n,s=new Uint8Array(t.size),a={type:e},o=0,u=0;if(t.data.length&&!(t.size<9)){for(a.trackId=t.data[0].pid,o=0;o<t.data.length;o++)n=t.data[o],s.set(n.data,u),u+=n.data.byteLength;var l,c,h;l=s,(c=a).packetLength=6+(l[4]<<8|l[5]),c.dataAlignmentIndicator=0!=(4&l[6]),192&(h=l[7])&&(c.pts=(14&l[9])<<27|(255&l[10])<<20|(254&l[11])<<12|(255&l[12])<<5|(254&l[13])>>>3,c.pts*=4,c.pts+=(6&l[13])>>>1,c.dts=c.pts,64&h&&(c.dts=(14&l[14])<<27|(255&l[15])<<20|(254&l[16])<<12|(255&l[17])<<5|(254&l[18])>>>3,c.dts*=4,c.dts+=(6&l[18])>>>1)),c.data=l.subarray(9+l[8]),r="video"===e||a.packetLength<=t.size,(i||r)&&(t.size=0,t.data.length=0),r&&d.trigger("data",a)}};ct.prototype.init.call(this),this.push=function(i){({pat:function(){},pes:function(){var t,e;switch(i.streamType){case Z.H264_STREAM_TYPE:case Z.H264_STREAM_TYPE:t=r,e="video";break;case Z.ADTS_STREAM_TYPE:t=n,e="audio";break;case Z.METADATA_STREAM_TYPE:t=s,e="timed-metadata";break;default:return}i.payloadUnitStartIndicator&&a(t,e,!0),t.data.push(i),t.size+=i.data.byteLength},pmt:function(){var t={type:"metadata",tracks:[]},e=i.programMapTable;null!==e.video&&t.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+e.video,codec:"avc",type:"video"}),null!==e.audio&&t.tracks.push({timelineStartInfo:{baseMediaDecodeTime:0},id:+e.audio,codec:"adts",type:"audio"}),d.trigger("data",t)}})[i.type]()},this.flush=function(){a(r,"video"),a(n,"audio"),a(s,"timed-metadata"),this.trigger("done")}}).prototype=new z;var pt={PAT_PID:0,MP2T_PACKET_LENGTH:188,TransportPacketStream:ut,TransportParseStream:lt,ElementaryStream:ct,TimestampRolloverStream:dt,CaptionStream:J.CaptionStream,Cea608Stream:J.Cea608Stream,MetadataStream:ht};for(var ft in Z)Z.hasOwnProperty(ft)&&(pt[ft]=Z[ft]);var mt,gt=pt,yt=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350];(mt=function(){var l;mt.prototype.init.call(this),this.push=function(t){var e,i,r,n,s,a,o=0,u=0;if("audio"===t.type)for(l?(n=l,(l=new Uint8Array(n.byteLength+t.data.byteLength)).set(n),l.set(t.data,n.byteLength)):l=t.data;o+5<l.length;)if(255===l[o]&&240==(246&l[o+1])){if(i=2*(1&~l[o+1]),e=(3&l[o+3])<<11|l[o+4]<<3|(224&l[o+5])>>5,a=9e4*(s=1024*(1+(3&l[o+6])))/yt[(60&l[o+2])>>>2],r=o+e,l.byteLength<r)return;if(this.trigger("data",{pts:t.pts+u*a,dts:t.dts+u*a,sampleCount:s,audioobjecttype:1+(l[o+2]>>>6&3),channelcount:(1&l[o+2])<<2|(192&l[o+3])>>>6,samplerate:yt[(60&l[o+2])>>>2],samplingfrequencyindex:(60&l[o+2])>>>2,samplesize:16,data:l.subarray(o+7+i,r)}),l.byteLength===r)return void(l=void 0);u++,l=l.subarray(r)}else o++},this.flush=function(){this.trigger("done")}}).prototype=new z;var vt,_t,bt,Tt=mt,St=function(r){var n=r.byteLength,s=0,a=0;this.length=function(){return 8*n},this.bitsAvailable=function(){return 8*n+a},this.loadWord=function(){var t=r.byteLength-n,e=new Uint8Array(4),i=Math.min(4,n);if(0===i)throw new Error("no bytes available");e.set(r.subarray(t,t+i)),s=new DataView(e.buffer).getUint32(0),a=8*i,n-=i},this.skipBits=function(t){var e;t<a||(t-=a,t-=8*(e=Math.floor(t/8)),n-=e,this.loadWord()),s<<=t,a-=t},this.readBits=function(t){var e=Math.min(a,t),i=s>>>32-e;return 0<(a-=e)?s<<=e:0<n&&this.loadWord(),0<(e=t-e)?i<<e|this.readBits(e):i},this.skipLeadingZeros=function(){var t;for(t=0;t<a;++t)if(0!=(s&2147483648>>>t))return s<<=t,a-=t,t;return this.loadWord(),t+this.skipLeadingZeros()},this.skipUnsignedExpGolomb=function(){this.skipBits(1+this.skipLeadingZeros())},this.skipExpGolomb=function(){this.skipBits(1+this.skipLeadingZeros())},this.readUnsignedExpGolomb=function(){var t=this.skipLeadingZeros();return this.readBits(t+1)-1},this.readExpGolomb=function(){var t=this.readUnsignedExpGolomb();return 1&t?1+t>>>1:-1*(t>>>1)},this.readBoolean=function(){return 1===this.readBits(1)},this.readUnsignedByte=function(){return this.readBits(8)},this.loadWord()};(_t=function(){var i,r,n=0;_t.prototype.init.call(this),this.push=function(t){var e;for(r?((e=new Uint8Array(r.byteLength+t.data.byteLength)).set(r),e.set(t.data,r.byteLength),r=e):r=t.data;n<r.byteLength-3;n++)if(1===r[n+2]){i=n+5;break}for(;i<r.byteLength;)switch(r[i]){case 0:if(0!==r[i-1]){i+=2;break}if(0!==r[i-2]){i++;break}for(n+3!==i-2&&this.trigger("data",r.subarray(n+3,i-2));1!==r[++i]&&i<r.length;);n=i-2,i+=3;break;case 1:if(0!==r[i-1]||0!==r[i-2]){i+=3;break}this.trigger("data",r.subarray(n+3,i-2)),n=i-2,i+=3;break;default:i+=3}r=r.subarray(n),i-=n,n=0},this.flush=function(){r&&3<r.byteLength&&this.trigger("data",r.subarray(n+3)),r=null,n=0,this.trigger("done")}}).prototype=new z,bt={100:!0,110:!0,122:!0,244:!0,44:!0,83:!0,86:!0,118:!0,128:!0,138:!0,139:!0,134:!0},(vt=function(){var i,r,n,s,a,o,_,e=new _t;vt.prototype.init.call(this),(i=this).push=function(t){"video"===t.type&&(r=t.trackId,n=t.pts,s=t.dts,e.push(t))},e.on("data",function(t){var e={trackId:r,pts:n,dts:s,data:t};switch(31&t[0]){case 5:e.nalUnitType="slice_layer_without_partitioning_rbsp_idr";break;case 6:e.nalUnitType="sei_rbsp",e.escapedRBSP=a(t.subarray(1));break;case 7:e.nalUnitType="seq_parameter_set_rbsp",e.escapedRBSP=a(t.subarray(1)),e.config=o(e.escapedRBSP);break;case 8:e.nalUnitType="pic_parameter_set_rbsp";break;case 9:e.nalUnitType="access_unit_delimiter_rbsp"}i.trigger("data",e)}),e.on("done",function(){i.trigger("done")}),this.flush=function(){e.flush()},_=function(t,e){var i,r=8,n=8;for(i=0;i<t;i++)0!==n&&(n=(r+e.readExpGolomb()+256)%256),r=0===n?r:n},a=function(t){for(var e,i,r=t.byteLength,n=[],s=1;s<r-2;)0===t[s]&&0===t[s+1]&&3===t[s+2]?(n.push(s+2),s+=2):s++;if(0===n.length)return t;e=r-n.length,i=new Uint8Array(e);var a=0;for(s=0;s<e;a++,s++)a===n[0]&&(a++,n.shift()),i[s]=t[a];return i},o=function(t){var e,i,r,n,s,a,o,u,l,c,h,d,p,f=0,m=0,g=0,y=0,v=1;if(i=(e=new St(t)).readUnsignedByte(),n=e.readUnsignedByte(),r=e.readUnsignedByte(),e.skipUnsignedExpGolomb(),bt[i]&&(3===(s=e.readUnsignedExpGolomb())&&e.skipBits(1),e.skipUnsignedExpGolomb(),e.skipUnsignedExpGolomb(),e.skipBits(1),e.readBoolean()))for(h=3!==s?8:12,p=0;p<h;p++)e.readBoolean()&&_(p<6?16:64,e);if(e.skipUnsignedExpGolomb(),0===(a=e.readUnsignedExpGolomb()))e.readUnsignedExpGolomb();else if(1===a)for(e.skipBits(1),e.skipExpGolomb(),e.skipExpGolomb(),o=e.readUnsignedExpGolomb(),p=0;p<o;p++)e.skipExpGolomb();if(e.skipUnsignedExpGolomb(),e.skipBits(1),u=e.readUnsignedExpGolomb(),l=e.readUnsignedExpGolomb(),0===(c=e.readBits(1))&&e.skipBits(1),e.skipBits(1),e.readBoolean()&&(f=e.readUnsignedExpGolomb(),m=e.readUnsignedExpGolomb(),g=e.readUnsignedExpGolomb(),y=e.readUnsignedExpGolomb()),e.readBoolean()&&e.readBoolean()){switch(e.readUnsignedByte()){case 1:d=[1,1];break;case 2:d=[12,11];break;case 3:d=[10,11];break;case 4:d=[16,11];break;case 5:d=[40,33];break;case 6:d=[24,11];break;case 7:d=[20,11];break;case 8:d=[32,11];break;case 9:d=[80,33];break;case 10:d=[18,11];break;case 11:d=[15,11];break;case 12:d=[64,33];break;case 13:d=[160,99];break;case 14:d=[4,3];break;case 15:d=[3,2];break;case 16:d=[2,1];break;case 255:d=[e.readUnsignedByte()<<8|e.readUnsignedByte(),e.readUnsignedByte()<<8|e.readUnsignedByte()]}d&&(v=d[0]/d[1])}return{profileIdc:i,levelIdc:r,profileCompatibility:n,width:Math.ceil((16*(u+1)-2*f-2*m)*v),height:(2-c)*(l+1)*16-2*g-2*y}}}).prototype=new z;var kt,Ct={H264Stream:vt,NalByteStream:_t};(kt=function(){var o=new Uint8Array,u=0;kt.prototype.init.call(this),this.setTimestamp=function(t){u=t},this.parseId3TagSize=function(t,e){var i=t[e+6]<<21|t[e+7]<<14|t[e+8]<<7|t[e+9];return(16&t[e+5])>>4?i+20:i+10},this.parseAdtsSize=function(t,e){var i=(224&t[e+5])>>5,r=t[e+4]<<3;return 6144&t[e+3]|r|i},this.push=function(t){var e,i,r,n,s=0,a=0;for(o.length?(n=o.length,(o=new Uint8Array(t.byteLength+n)).set(o.subarray(0,n)),o.set(t,n)):o=t;3<=o.length-a;)if(o[a]!=="I".charCodeAt(0)||o[a+1]!=="D".charCodeAt(0)||o[a+2]!=="3".charCodeAt(0))if(!0&o[a]&&240==(240&o[a+1])){if(o.length-a<7)break;if((s=this.parseAdtsSize(o,a))>o.length)break;r={type:"audio",data:o.subarray(a,a+s),pts:u,dts:u},this.trigger("data",r),a+=s}else a++;else{if(o.length-a<10)break;if((s=this.parseId3TagSize(o,a))>o.length)break;i={type:"timed-metadata",data:o.subarray(a,a+s)},this.trigger("data",i),a+=s}e=o.length-a,o=0<e?o.subarray(a):new Uint8Array}}).prototype=new z;var Et,wt,At,Lt,Pt,Ot,xt,It,Dt,Rt,Mt,Ut,Nt,Bt,jt,Ft=kt,Ht=[33,16,5,32,164,27],Vt=[33,65,108,84,1,2,4,8,168,2,4,8,17,191,252],qt=function(t){for(var e=[];t--;)e.push(0);return e},Wt={96000:[Ht,[227,64],qt(154),[56]],88200:[Ht,[231],qt(170),[56]],64000:[Ht,[248,192],qt(240),[56]],48000:[Ht,[255,192],qt(268),[55,148,128],qt(54),[112]],44100:[Ht,[255,192],qt(268),[55,163,128],qt(84),[112]],32000:[Ht,[255,192],qt(268),[55,234],qt(226),[112]],24000:[Ht,[255,192],qt(268),[55,255,128],qt(268),[111,112],qt(126),[224]],16000:[Ht,[255,192],qt(268),[55,255,128],qt(268),[111,255],qt(269),[223,108],qt(195),[1,192]],12000:[Vt,qt(268),[3,127,248],qt(268),[6,255,240],qt(268),[13,255,224],qt(268),[27,253,128],qt(259),[56]],11025:[Vt,qt(268),[3,127,248],qt(268),[6,255,240],qt(268),[13,255,224],qt(268),[27,255,192],qt(268),[55,175,128],qt(108),[112]],8000:[Vt,qt(268),[3,121,16],qt(47),[7]]},zt=(Et=Wt,Object.keys(Et).reduce(function(t,e){return t[e]=new Uint8Array(Et[e].reduce(function(t,e){return t.concat(e)},[])),t},{})),Gt=(wt=function(t){return 9e4*t},At=function(t,e){return t*e},Lt=function(t){return t/9e4},Pt=function(t,e){return t/e},function(t,e){return wt(Pt(t,e))}),Xt=function(t,e){return At(Lt(t),e)},Yt=Ct.H264Stream,$t=["audioobjecttype","channelcount","samplerate","samplingfrequencyindex","samplesize"],Kt=["width","height","profileIdc","levelIdc","profileCompatibility"];Rt=function(t){return t[0]==="I".charCodeAt(0)&&t[1]==="D".charCodeAt(0)&&t[2]==="3".charCodeAt(0)},Bt=function(t,e){var i;if(t.length!==e.length)return!1;for(i=0;i<t.length;i++)if(t[i]!==e[i])return!1;return!0},jt=function(t){var e,i=0;for(e=0;e<t.length;e++)i+=t[e].data.byteLength;return i},(xt=function(n,s){var a=[],o=0,e=0,l=0,c=1/0;s=s||{},xt.prototype.init.call(this),this.push=function(e){Mt(n,e),n&&$t.forEach(function(t){n[t]=e[t]}),a.push(e)},this.setEarliestDts=function(t){e=t-n.timelineStartInfo.baseMediaDecodeTime},this.setVideoBaseMediaDecodeTime=function(t){c=t},this.setAudioAppendStart=function(t){l=t},this.flush=function(){var t,e,i,r;0!==a.length&&(t=this.trimAdtsFramesByEarliestDts_(a),n.baseMediaDecodeTime=Nt(n,s.keepOriginalTimestamps),this.prefixWithSilence_(n,t),n.samples=this.generateSampleTable_(t),i=q.mdat(this.concatenateFrameData_(t)),a=[],e=q.moof(o,[n]),r=new Uint8Array(e.byteLength+i.byteLength),o++,r.set(e),r.set(i,e.byteLength),Ut(n),this.trigger("data",{track:n,boxes:r})),this.trigger("done","AudioSegmentStream")},this.prefixWithSilence_=function(t,e){var i,r,n,s,a=0,o=0,u=0;if(e.length&&(i=Gt(t.baseMediaDecodeTime,t.samplerate),r=Math.ceil(9e4/(t.samplerate/1024)),l&&c&&(a=i-Math.max(l,c),u=(o=Math.floor(a/r))*r),!(o<1||45e3<u))){for((n=zt[t.samplerate])||(n=e[0].data),s=0;s<o;s++)e.splice(s,0,{data:n});t.baseMediaDecodeTime-=Math.floor(Xt(u,t.samplerate))}},this.trimAdtsFramesByEarliestDts_=function(t){return n.minSegmentDts>=e?t:(n.minSegmentDts=1/0,t.filter(function(t){return t.dts>=e&&(n.minSegmentDts=Math.min(n.minSegmentDts,t.dts),n.minSegmentPts=n.minSegmentDts,!0)}))},this.generateSampleTable_=function(t){var e,i,r=[];for(e=0;e<t.length;e++)i=t[e],r.push({size:i.data.byteLength,duration:1024});return r},this.concatenateFrameData_=function(t){var e,i,r=0,n=new Uint8Array(jt(t));for(e=0;e<t.length;e++)i=t[e],n.set(i.data,r),r+=i.data.byteLength;return n}}).prototype=new z,(Ot=function(o,u){var e,i,l=0,c=[],h=[];u=u||{},Ot.prototype.init.call(this),delete o.minPTS,this.gopCache_=[],this.push=function(t){Mt(o,t),"seq_parameter_set_rbsp"!==t.nalUnitType||e||(e=t.config,o.sps=[t.data],Kt.forEach(function(t){o[t]=e[t]},this)),"pic_parameter_set_rbsp"!==t.nalUnitType||i||(i=t.data,o.pps=[t.data]),c.push(t)},this.flush=function(){for(var t,e,i,r,n,s;c.length&&"access_unit_delimiter_rbsp"!==c[0].nalUnitType;)c.shift();if(0===c.length)return this.resetStream_(),void this.trigger("done","VideoSegmentStream");if(t=this.groupNalsIntoFrames_(c),(i=this.groupFramesIntoGops_(t))[0][0].keyFrame||((e=this.getGopForFusion_(c[0],o))?(i.unshift(e),i.byteLength+=e.byteLength,i.nalCount+=e.nalCount,i.pts=e.pts,i.dts=e.dts,i.duration+=e.duration):i=this.extendFirstKeyFrame_(i)),h.length){var a;if(!(a=u.alignGopsAtEnd?this.alignGopsAtEnd_(i):this.alignGopsAtStart_(i)))return this.gopCache_.unshift({gop:i.pop(),pps:o.pps,sps:o.sps}),this.gopCache_.length=Math.min(6,this.gopCache_.length),c=[],this.resetStream_(),void this.trigger("done","VideoSegmentStream");Ut(o),i=a}Mt(o,i),o.samples=this.generateSampleTable_(i),n=q.mdat(this.concatenateNalData_(i)),o.baseMediaDecodeTime=Nt(o,u.keepOriginalTimestamps),this.trigger("processedGopsInfo",i.map(function(t){return{pts:t.pts,dts:t.dts,byteLength:t.byteLength}})),this.gopCache_.unshift({gop:i.pop(),pps:o.pps,sps:o.sps}),this.gopCache_.length=Math.min(6,this.gopCache_.length),c=[],this.trigger("baseMediaDecodeTime",o.baseMediaDecodeTime),this.trigger("timelineStartInfo",o.timelineStartInfo),r=q.moof(l,[o]),s=new Uint8Array(r.byteLength+n.byteLength),l++,s.set(r),s.set(n,r.byteLength),this.trigger("data",{track:o,boxes:s}),this.resetStream_(),this.trigger("done","VideoSegmentStream")},this.resetStream_=function(){Ut(o),i=e=void 0},this.getGopForFusion_=function(t){var e,i,r,n,s,a=1/0;for(s=0;s<this.gopCache_.length;s++)r=(n=this.gopCache_[s]).gop,o.pps&&Bt(o.pps[0],n.pps[0])&&o.sps&&Bt(o.sps[0],n.sps[0])&&(r.dts<o.timelineStartInfo.dts||-1e4<=(e=t.dts-r.dts-r.duration)&&e<=45e3&&(!i||e<a)&&(i=n,a=e));return i?i.gop:null},this.extendFirstKeyFrame_=function(t){var e;return!t[0][0].keyFrame&&1<t.length&&(e=t.shift(),t.byteLength-=e.byteLength,t.nalCount-=e.nalCount,t[0][0].dts=e.dts,t[0][0].pts=e.pts,t[0][0].duration+=e.duration),t},this.groupNalsIntoFrames_=function(t){var e,i,r=[],n=[];for(e=r.byteLength=0;e<t.length;e++)"access_unit_delimiter_rbsp"===(i=t[e]).nalUnitType?(r.length&&(r.duration=i.dts-r.dts,n.push(r)),(r=[i]).byteLength=i.data.byteLength,r.pts=i.pts,r.dts=i.dts):("slice_layer_without_partitioning_rbsp_idr"===i.nalUnitType&&(r.keyFrame=!0),r.duration=i.dts-r.dts,r.byteLength+=i.data.byteLength,r.push(i));return n.length&&(!r.duration||r.duration<=0)&&(r.duration=n[n.length-1].duration),n.push(r),n},this.groupFramesIntoGops_=function(t){var e,i,r=[],n=[];for(r.byteLength=0,r.nalCount=0,r.duration=0,r.pts=t[0].pts,r.dts=t[0].dts,n.byteLength=0,n.nalCount=0,n.duration=0,n.pts=t[0].pts,n.dts=t[0].dts,e=0;e<t.length;e++)(i=t[e]).keyFrame?(r.length&&(n.push(r),n.byteLength+=r.byteLength,n.nalCount+=r.nalCount,n.duration+=r.duration),(r=[i]).nalCount=i.length,r.byteLength=i.byteLength,r.pts=i.pts,r.dts=i.dts,r.duration=i.duration):(r.duration+=i.duration,r.nalCount+=i.length,r.byteLength+=i.byteLength,r.push(i));return n.length&&r.duration<=0&&(r.duration=n[n.length-1].duration),n.byteLength+=r.byteLength,n.nalCount+=r.nalCount,n.duration+=r.duration,n.push(r),n},this.generateSampleTable_=function(t,e){var i,r,n,s,a,o=e||0,u=[];for(i=0;i<t.length;i++)for(s=t[i],r=0;r<s.length;r++)a=s[r],(n={size:0,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0,degradationPriority:0}}).dataOffset=o,n.compositionTimeOffset=a.pts-a.dts,n.duration=a.duration,n.size=4*a.length,n.size+=a.byteLength,a.keyFrame&&(n.flags.dependsOn=2),o+=n.size,u.push(n);return u},this.concatenateNalData_=function(t){var e,i,r,n,s,a,o=0,u=t.byteLength,l=t.nalCount,c=new Uint8Array(u+4*l),h=new DataView(c.buffer);for(e=0;e<t.length;e++)for(n=t[e],i=0;i<n.length;i++)for(s=n[i],r=0;r<s.length;r++)a=s[r],h.setUint32(o,a.data.byteLength),o+=4,c.set(a.data,o),o+=a.data.byteLength;return c},this.alignGopsAtStart_=function(t){var e,i,r,n,s,a,o,u;for(s=t.byteLength,a=t.nalCount,o=t.duration,e=i=0;e<h.length&&i<t.length&&(r=h[e],n=t[i],r.pts!==n.pts);)n.pts>r.pts?e++:(i++,s-=n.byteLength,a-=n.nalCount,o-=n.duration);return 0===i?t:i===t.length?null:((u=t.slice(i)).byteLength=s,u.duration=o,u.nalCount=a,u.pts=u[0].pts,u.dts=u[0].dts,u)},this.alignGopsAtEnd_=function(t){var e,i,r,n,s,a,o;for(e=h.length-1,i=t.length-1,s=null,a=!1;0<=e&&0<=i;){if(r=h[e],n=t[i],r.pts===n.pts){a=!0;break}r.pts>n.pts?e--:(e===h.length-1&&(s=i),i--)}if(!a&&null===s)return null;if(0===(o=a?i:s))return t;var u=t.slice(o),l=u.reduce(function(t,e){return t.byteLength+=e.byteLength,t.duration+=e.duration,t.nalCount+=e.nalCount,t},{byteLength:0,duration:0,nalCount:0});return u.byteLength=l.byteLength,u.duration=l.duration,u.nalCount=l.nalCount,u.pts=u[0].pts,u.dts=u[0].dts,u},this.alignGopsWith=function(t){h=t}}).prototype=new z,Mt=function(t,e){"number"==typeof e.pts&&(void 0===t.timelineStartInfo.pts&&(t.timelineStartInfo.pts=e.pts),void 0===t.minSegmentPts?t.minSegmentPts=e.pts:t.minSegmentPts=Math.min(t.minSegmentPts,e.pts),void 0===t.maxSegmentPts?t.maxSegmentPts=e.pts:t.maxSegmentPts=Math.max(t.maxSegmentPts,e.pts)),"number"==typeof e.dts&&(void 0===t.timelineStartInfo.dts&&(t.timelineStartInfo.dts=e.dts),void 0===t.minSegmentDts?t.minSegmentDts=e.dts:t.minSegmentDts=Math.min(t.minSegmentDts,e.dts),void 0===t.maxSegmentDts?t.maxSegmentDts=e.dts:t.maxSegmentDts=Math.max(t.maxSegmentDts,e.dts))},Ut=function(t){delete t.minSegmentDts,delete t.maxSegmentDts,delete t.minSegmentPts,delete t.maxSegmentPts},Nt=function(t,e){var i,r=t.minSegmentDts;return e||(r-=t.timelineStartInfo.dts),i=t.timelineStartInfo.baseMediaDecodeTime,i+=r,i=Math.max(0,i),"audio"===t.type&&(i*=t.samplerate/9e4,i=Math.floor(i)),i},(Dt=function(t,e){this.numberOfTracks=0,this.metadataStream=e,"undefined"!=typeof t.remux?this.remuxTracks=!!t.remux:this.remuxTracks=!0,this.pendingTracks=[],this.videoTrack=null,this.pendingBoxes=[],this.pendingCaptions=[],this.pendingMetadata=[],this.pendingBytes=0,this.emittedTracks=0,Dt.prototype.init.call(this),this.push=function(t){return t.text?this.pendingCaptions.push(t):t.frames?this.pendingMetadata.push(t):(this.pendingTracks.push(t.track),this.pendingBoxes.push(t.boxes),this.pendingBytes+=t.boxes.byteLength,"video"===t.track.type&&(this.videoTrack=t.track),void("audio"===t.track.type&&(this.audioTrack=t.track)))}}).prototype=new z,Dt.prototype.flush=function(t){var e,i,r,n,s=0,a={captions:[],captionStreams:{},metadata:[],info:{}},o=0;if(this.pendingTracks.length<this.numberOfTracks){if("VideoSegmentStream"!==t&&"AudioSegmentStream"!==t)return;if(this.remuxTracks)return;if(0===this.pendingTracks.length)return this.emittedTracks++,void(this.emittedTracks>=this.numberOfTracks&&(this.trigger("done"),this.emittedTracks=0))}for(this.videoTrack?(o=this.videoTrack.timelineStartInfo.pts,Kt.forEach(function(t){a.info[t]=this.videoTrack[t]},this)):this.audioTrack&&(o=this.audioTrack.timelineStartInfo.pts,$t.forEach(function(t){a.info[t]=this.audioTrack[t]},this)),1===this.pendingTracks.length?a.type=this.pendingTracks[0].type:a.type="combined",this.emittedTracks+=this.pendingTracks.length,r=q.initSegment(this.pendingTracks),a.initSegment=new Uint8Array(r.byteLength),a.initSegment.set(r),a.data=new Uint8Array(this.pendingBytes),n=0;n<this.pendingBoxes.length;n++)a.data.set(this.pendingBoxes[n],s),s+=this.pendingBoxes[n].byteLength;for(n=0;n<this.pendingCaptions.length;n++)(e=this.pendingCaptions[n]).startTime=e.startPts-o,e.startTime/=9e4,e.endTime=e.endPts-o,e.endTime/=9e4,a.captionStreams[e.stream]=!0,a.captions.push(e);for(n=0;n<this.pendingMetadata.length;n++)(i=this.pendingMetadata[n]).cueTime=i.pts-o,i.cueTime/=9e4,a.metadata.push(i);a.metadata.dispatchType=this.metadataStream.dispatchType,this.pendingTracks.length=0,this.videoTrack=null,this.pendingBoxes.length=0,this.pendingCaptions.length=0,this.pendingBytes=0,this.pendingMetadata.length=0,this.trigger("data",a),this.emittedTracks>=this.numberOfTracks&&(this.trigger("done"),this.emittedTracks=0)},(It=function(r){var n,s,a=this,i=!0;It.prototype.init.call(this),r=r||{},this.baseMediaDecodeTime=r.baseMediaDecodeTime||0,this.transmuxPipeline_={},this.setupAacPipeline=function(){var e={};(this.transmuxPipeline_=e).type="aac",e.metadataStream=new gt.MetadataStream,e.aacStream=new Ft,e.audioTimestampRolloverStream=new gt.TimestampRolloverStream("audio"),e.timedMetadataTimestampRolloverStream=new gt.TimestampRolloverStream("timed-metadata"),e.adtsStream=new Tt,e.coalesceStream=new Dt(r,e.metadataStream),e.headOfPipeline=e.aacStream,e.aacStream.pipe(e.audioTimestampRolloverStream).pipe(e.adtsStream),e.aacStream.pipe(e.timedMetadataTimestampRolloverStream).pipe(e.metadataStream).pipe(e.coalesceStream),e.metadataStream.on("timestamp",function(t){e.aacStream.setTimestamp(t.timeStamp)}),e.aacStream.on("data",function(t){"timed-metadata"!==t.type||e.audioSegmentStream||(s=s||{timelineStartInfo:{baseMediaDecodeTime:a.baseMediaDecodeTime},codec:"adts",type:"audio"},e.coalesceStream.numberOfTracks++,e.audioSegmentStream=new xt(s,r),e.adtsStream.pipe(e.audioSegmentStream).pipe(e.coalesceStream))}),e.coalesceStream.on("data",this.trigger.bind(this,"data")),e.coalesceStream.on("done",this.trigger.bind(this,"done"))},this.setupTsPipeline=function(){var i={};(this.transmuxPipeline_=i).type="ts",i.metadataStream=new gt.MetadataStream,i.packetStream=new gt.TransportPacketStream,i.parseStream=new gt.TransportParseStream,i.elementaryStream=new gt.ElementaryStream,i.videoTimestampRolloverStream=new gt.TimestampRolloverStream("video"),i.audioTimestampRolloverStream=new gt.TimestampRolloverStream("audio"),i.timedMetadataTimestampRolloverStream=new gt.TimestampRolloverStream("timed-metadata"),i.adtsStream=new Tt,i.h264Stream=new Yt,i.captionStream=new gt.CaptionStream,i.coalesceStream=new Dt(r,i.metadataStream),i.headOfPipeline=i.packetStream,i.packetStream.pipe(i.parseStream).pipe(i.elementaryStream),i.elementaryStream.pipe(i.videoTimestampRolloverStream).pipe(i.h264Stream),i.elementaryStream.pipe(i.audioTimestampRolloverStream).pipe(i.adtsStream),i.elementaryStream.pipe(i.timedMetadataTimestampRolloverStream).pipe(i.metadataStream).pipe(i.coalesceStream),i.h264Stream.pipe(i.captionStream).pipe(i.coalesceStream),i.elementaryStream.on("data",function(t){var e;if("metadata"===t.type){for(e=t.tracks.length;e--;)n||"video"!==t.tracks[e].type?s||"audio"!==t.tracks[e].type||((s=t.tracks[e]).timelineStartInfo.baseMediaDecodeTime=a.baseMediaDecodeTime):(n=t.tracks[e]).timelineStartInfo.baseMediaDecodeTime=a.baseMediaDecodeTime;n&&!i.videoSegmentStream&&(i.coalesceStream.numberOfTracks++,i.videoSegmentStream=new Ot(n,r),i.videoSegmentStream.on("timelineStartInfo",function(t){s&&(s.timelineStartInfo=t,i.audioSegmentStream.setEarliestDts(t.dts))}),i.videoSegmentStream.on("processedGopsInfo",a.trigger.bind(a,"gopInfo")),i.videoSegmentStream.on("baseMediaDecodeTime",function(t){s&&i.audioSegmentStream.setVideoBaseMediaDecodeTime(t)}),i.h264Stream.pipe(i.videoSegmentStream).pipe(i.coalesceStream)),s&&!i.audioSegmentStream&&(i.coalesceStream.numberOfTracks++,i.audioSegmentStream=new xt(s,r),i.adtsStream.pipe(i.audioSegmentStream).pipe(i.coalesceStream))}}),i.coalesceStream.on("data",this.trigger.bind(this,"data")),i.coalesceStream.on("done",this.trigger.bind(this,"done"))},this.setBaseMediaDecodeTime=function(t){var e=this.transmuxPipeline_;this.baseMediaDecodeTime=t,s&&(s.timelineStartInfo.dts=void 0,s.timelineStartInfo.pts=void 0,Ut(s),s.timelineStartInfo.baseMediaDecodeTime=t,e.audioTimestampRolloverStream&&e.audioTimestampRolloverStream.discontinuity()),n&&(e.videoSegmentStream&&(e.videoSegmentStream.gopCache_=[],e.videoTimestampRolloverStream.discontinuity()),n.timelineStartInfo.dts=void 0,n.timelineStartInfo.pts=void 0,Ut(n),e.captionStream.reset(),n.timelineStartInfo.baseMediaDecodeTime=t),e.timedMetadataTimestampRolloverStream&&e.timedMetadataTimestampRolloverStream.discontinuity()},this.setAudioAppendStart=function(t){s&&this.transmuxPipeline_.audioSegmentStream.setAudioAppendStart(t)},this.alignGopsWith=function(t){n&&this.transmuxPipeline_.videoSegmentStream&&this.transmuxPipeline_.videoSegmentStream.alignGopsWith(t)},this.push=function(t){if(i){var e=Rt(t);e&&"aac"!==this.transmuxPipeline_.type?this.setupAacPipeline():e||"ts"===this.transmuxPipeline_.type||this.setupTsPipeline(),i=!1}this.transmuxPipeline_.headOfPipeline.push(t)},this.flush=function(){i=!0,this.transmuxPipeline_.headOfPipeline.flush()},this.resetCaptions=function(){this.transmuxPipeline_.captionStream&&this.transmuxPipeline_.captionStream.reset()}}).prototype=new z;var Qt={Transmuxer:It,VideoSegmentStream:Ot,AudioSegmentStream:xt,AUDIO_PROPERTIES:$t,VIDEO_PROPERTIES:Kt},Jt={generator:q,Transmuxer:Qt.Transmuxer,AudioSegmentStream:Qt.AudioSegmentStream,VideoSegmentStream:Qt.VideoSegmentStream},Zt=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},te=function(){function r(t,e){for(var i=0;i<e.length;i++){var r=e[i];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,e,i){return e&&r(t.prototype,e),i&&r(t,i),t}}(),ee=function(){function e(t){Zt(this,e),this.options=t||{},this.init()}return te(e,[{key:"init",value:function(){var t;this.transmuxer&&this.transmuxer.dispose(),this.transmuxer=new Jt.Transmuxer(this.options),(t=this.transmuxer).on("data",function(t){var e=t.initSegment;t.initSegment={data:e.buffer,byteOffset:e.byteOffset,byteLength:e.byteLength};var i=t.data;t.data=i.buffer,H.postMessage({action:"data",segment:t,byteOffset:i.byteOffset,byteLength:i.byteLength},[t.data])}),t.captionStream&&t.captionStream.on("data",function(t){H.postMessage({action:"caption",data:t})}),t.on("done",function(t){H.postMessage({action:"done"})}),t.on("gopInfo",function(t){H.postMessage({action:"gopInfo",gopInfo:t})})}},{key:"push",value:function(t){var e=new Uint8Array(t.data,t.byteOffset,t.byteLength);this.transmuxer.push(e)}},{key:"reset",value:function(){this.init()}},{key:"setTimestampOffset",value:function(t){var e=t.timestampOffset||0;this.transmuxer.setBaseMediaDecodeTime(Math.round(9e4*e))}},{key:"setAudioAppendStart",value:function(t){this.transmuxer.setAudioAppendStart(Math.ceil(9e4*t.appendStart))}},{key:"flush",value:function(t){this.transmuxer.flush()}},{key:"resetCaptions",value:function(){this.transmuxer.resetCaptions()}},{key:"alignGopsWith",value:function(t){this.transmuxer.alignGopsWith(t.gopsToAlignWith.slice())}}]),e}();new function(t){t.onmessage=function(t){"init"===t.data.action&&t.data.options?this.messageHandlers=new ee(t.data.options):(this.messageHandlers||(this.messageHandlers=new ee),t.data&&t.data.action&&"init"!==t.data.action&&this.messageHandlers[t.data.action]&&this.messageHandlers[t.data.action](t.data))}}(re)}()}),Mu=function(t){return/mp4a\.\d+.\d+/i.test(t)},Uu=function(t){return/avc1\.[\da-f]+/i.test(t)},Nu=function(t){return t.map(function(t){return t.replace(/avc1\.(\d+)\.(\d+)/i,function(t,e,i){return"avc1."+("00"+Number(e).toString(16)).slice(-2)+"00"+("00"+Number(i).toString(16)).slice(-2)})})},Bu=function(n){function s(t,e){y(this,s);var i=b(this,n.call(this,As.EventTarget));i.timestampOffset_=0,i.pendingBuffers_=[],i.bufferUpdating_=!1,i.mediaSource_=t,i.codecs_=e,i.audioCodec_=null,i.videoCodec_=null,i.audioDisabled_=!1,i.appendAudioInitSegment_=!0,i.gopBuffer_=[],i.timeMapping_=0,i.safeAppend_=11<=As.browser.IE_VERSION;var r={remux:!1,alignGopsAtEnd:i.safeAppend_};return i.codecs_.forEach(function(t){Mu(t)?i.audioCodec_=t:Uu(t)&&(i.videoCodec_=t)}),i.transmuxer_=new Ru,i.transmuxer_.postMessage({action:"init",options:r}),i.transmuxer_.onmessage=function(t){return"data"===t.data.action?i.data_(t):"done"===t.data.action?i.done_(t):"gopInfo"===t.data.action?i.appendGopInfo_(t):void 0},Object.defineProperty(i,"timestampOffset",{get:function(){return this.timestampOffset_},set:function(t){"number"==typeof t&&0<=t&&(this.timestampOffset_=t,this.appendAudioInitSegment_=!0,this.gopBuffer_.length=0,this.timeMapping_=0,this.transmuxer_.postMessage({action:"setTimestampOffset",timestampOffset:t}))}}),Object.defineProperty(i,"appendWindowStart",{get:function(){return(this.videoBuffer_||this.audioBuffer_).appendWindowStart},set:function(t){this.videoBuffer_&&(this.videoBuffer_.appendWindowStart=t),this.audioBuffer_&&(this.audioBuffer_.appendWindowStart=t)}}),Object.defineProperty(i,"updating",{get:function(){return!!(this.bufferUpdating_||!this.audioDisabled_&&this.audioBuffer_&&this.audioBuffer_.updating||this.videoBuffer_&&this.videoBuffer_.updating)}}),Object.defineProperty(i,"buffered",{get:function(){var t=null,e=null,i=0,r=[],n=[];if(!this.videoBuffer_&&!this.audioBuffer_)return As.createTimeRange();if(!this.videoBuffer_)return this.audioBuffer_.buffered;if(!this.audioBuffer_)return this.videoBuffer_.buffered;if(this.audioDisabled_)return this.videoBuffer_.buffered;if(0===this.videoBuffer_.buffered.length&&0===this.audioBuffer_.buffered.length)return As.createTimeRange();for(var s=this.videoBuffer_.buffered,a=this.audioBuffer_.buffered,o=s.length;o--;)r.push({time:s.start(o),type:"start"}),r.push({time:s.end(o),type:"end"});for(o=a.length;o--;)r.push({time:a.start(o),type:"start"}),r.push({time:a.end(o),type:"end"});for(r.sort(function(t,e){return t.time-e.time}),o=0;o<r.length;o++)"start"===r[o].type?2===++i&&(t=r[o].time):"end"===r[o].type&&1===--i&&(e=r[o].time),null!==t&&null!==e&&(n.push([t,e]),e=t=null);return As.createTimeRanges(n)}}),i}return _(s,n),s.prototype.data_=function(t){var e=t.data.segment;e.data=new Uint8Array(e.data,t.data.byteOffset,t.data.byteLength),e.initSegment=new Uint8Array(e.initSegment.data,e.initSegment.byteOffset,e.initSegment.byteLength),function(t,e,i){var r=e.player_;if(i.captions&&i.captions.length)for(var n in t.inbandTextTracks_||(t.inbandTextTracks_={}),i.captionStreams)if(!t.inbandTextTracks_[n]){r.tech_.trigger({type:"usage",name:"hls-608"});var s=r.textTracks().getTrackById(n);t.inbandTextTracks_[n]=s||r.addRemoteTextTrack({kind:"captions",id:n,label:n},!1).track}i.metadata&&i.metadata.length&&!t.metadataTrack_&&(t.metadataTrack_=r.addRemoteTextTrack({kind:"metadata",label:"Timed Metadata"},!1).track,t.metadataTrack_.inBandMetadataTrackDispatchType=i.metadata.dispatchType)}(this,this.mediaSource_,e),this.pendingBuffers_.push(e)},s.prototype.done_=function(t){"closed"!==this.mediaSource_.readyState?this.processPendingSegments_():this.pendingBuffers_.length=0},s.prototype.createRealSourceBuffers_=function(){var r=this,n=["audio","video"];n.forEach(function(e){if(r[e+"Codec_"]&&!r[e+"Buffer_"]){var i=null;if(r.mediaSource_[e+"Buffer_"])(i=r.mediaSource_[e+"Buffer_"]).updating=!1;else{var t=e+'/mp4;codecs="'+r[e+"Codec_"]+'"';i=function(t,e){var i=t.addSourceBuffer(e),r=Object.create(null);r.updating=!1,r.realBuffer_=i;var n=function(e){"function"==typeof i[e]?r[e]=function(){return i[e].apply(i,arguments)}:"undefined"==typeof r[e]&&Object.defineProperty(r,e,{get:function(){return i[e]},set:function(t){return i[e]=t}})};for(var s in i)n(s);return r}(r.mediaSource_.nativeMediaSource_,t),r.mediaSource_[e+"Buffer_"]=i}r[e+"Buffer_"]=i,["update","updatestart","updateend"].forEach(function(t){i.addEventListener(t,function(){if("audio"!==e||!r.audioDisabled_)return"updateend"===t&&(r[e+"Buffer_"].updating=!1),n.every(function(t){return!("audio"!==t||!r.audioDisabled_)||(e===t||!r[t+"Buffer_"]||!r[t+"Buffer_"].updating)})?r.trigger(t):void 0})})}})},s.prototype.appendBuffer=function(t){if(this.bufferUpdating_=!0,this.audioBuffer_&&this.audioBuffer_.buffered.length){var e=this.audioBuffer_.buffered;this.transmuxer_.postMessage({action:"setAudioAppendStart",appendStart:e.end(e.length-1)})}this.videoBuffer_&&this.transmuxer_.postMessage({action:"alignGopsWith",gopsToAlignWith:function(t,e,i){if(!e||!t.length)return[];var r=Math.ceil(9e4*(e.currentTime()-i+3)),n=void 0;for(n=0;n<t.length&&!(t[n].pts>r);n++);return t.slice(n)}(this.gopBuffer_,this.mediaSource_.player_,this.timeMapping_)}),this.transmuxer_.postMessage({action:"push",data:t.buffer,byteOffset:t.byteOffset,byteLength:t.byteLength},[t.buffer]),this.transmuxer_.postMessage({action:"flush"})},s.prototype.appendGopInfo_=function(t){this.gopBuffer_=function(t,e,i){if(!e.length)return t;if(i)return e.slice();for(var r=e[0].pts,n=0;n<t.length&&!(t[n].pts>=r);n++);return t.slice(0,n).concat(e)}(this.gopBuffer_,t.data.gopInfo,this.safeAppend_)},s.prototype.remove=function(t,e){if(this.videoBuffer_&&(this.videoBuffer_.updating=!0,this.videoBuffer_.remove(t,e),this.gopBuffer_=function(t,e,i,r){for(var n=Math.ceil(9e4*(e-r)),s=Math.ceil(9e4*(i-r)),a=t.slice(),o=t.length;o--&&!(t[o].pts<=s););if(-1===o)return a;for(var u=o+1;u--&&!(t[u].pts<=n););return u=Math.max(u,0),a.splice(u,o-u+1),a}(this.gopBuffer_,t,e,this.timeMapping_)),!this.audioDisabled_&&this.audioBuffer_&&(this.audioBuffer_.updating=!0,this.audioBuffer_.remove(t,e)),bu(t,e,this.metadataTrack_),this.inbandTextTracks_)for(var i in this.inbandTextTracks_)bu(t,e,this.inbandTextTracks_[i])},s.prototype.processPendingSegments_=function(){var t={video:{segments:[],bytes:0},audio:{segments:[],bytes:0},captions:[],metadata:[]};t=this.pendingBuffers_.reduce(function(t,e){var i=e.type,r=e.data,n=e.initSegment;return t[i].segments.push(r),t[i].bytes+=r.byteLength,t[i].initSegment=n,e.captions&&(t.captions=t.captions.concat(e.captions)),e.info&&(t[i].info=e.info),e.metadata&&(t.metadata=t.metadata.concat(e.metadata)),t},t),this.videoBuffer_||this.audioBuffer_||(0===t.video.bytes&&(this.videoCodec_=null),0===t.audio.bytes&&(this.audioCodec_=null),this.createRealSourceBuffers_()),t.audio.info&&this.mediaSource_.trigger({type:"audioinfo",info:t.audio.info}),t.video.info&&this.mediaSource_.trigger({type:"videoinfo",info:t.video.info}),this.appendAudioInitSegment_&&(!this.audioDisabled_&&this.audioBuffer_&&(t.audio.segments.unshift(t.audio.initSegment),t.audio.bytes+=t.audio.initSegment.byteLength),this.appendAudioInitSegment_=!1);var e=!1;this.videoBuffer_&&t.video.bytes?(t.video.segments.unshift(t.video.initSegment),t.video.bytes+=t.video.initSegment.byteLength,this.concatAndAppendSegments_(t.video,this.videoBuffer_),Su(this,t.captions,t.metadata)):!this.videoBuffer_||!this.audioDisabled_&&this.audioBuffer_||(e=!0),!this.audioDisabled_&&this.audioBuffer_&&this.concatAndAppendSegments_(t.audio,this.audioBuffer_),this.pendingBuffers_.length=0,e&&this.trigger("updateend"),this.bufferUpdating_=!1},s.prototype.concatAndAppendSegments_=function(t,e){var i=0,r=void 0;if(t.bytes){r=new Uint8Array(t.bytes),t.segments.forEach(function(t){r.set(t,i),i+=t.byteLength});try{e.updating=!0,e.appendBuffer(r)}catch(t){this.mediaSource_.player_&&this.mediaSource_.player_.error({code:-3,type:"APPEND_BUFFER_ERR",message:t.message,originalError:t})}}},s.prototype.abort=function(){this.videoBuffer_&&this.videoBuffer_.abort(),!this.audioDisabled_&&this.audioBuffer_&&this.audioBuffer_.abort(),this.transmuxer_&&this.transmuxer_.postMessage({action:"reset"}),this.pendingBuffers_.length=0,this.bufferUpdating_=!1},s}(As.EventTarget),ju=function(e){function i(){y(this,i);var s=b(this,e.call(this)),t=void 0;for(t in s.nativeMediaSource_=new g.MediaSource,s.nativeMediaSource_)t in i.prototype||"function"!=typeof s.nativeMediaSource_[t]||(s[t]=s.nativeMediaSource_[t].bind(s.nativeMediaSource_));return s.duration_=NaN,Object.defineProperty(s,"duration",{get:function(){return this.duration_===1/0?this.duration_:this.nativeMediaSource_.duration},set:function(t){(this.duration_=t)===1/0||(this.nativeMediaSource_.duration=t)}}),Object.defineProperty(s,"seekable",{get:function(){return this.duration_===1/0?As.createTimeRanges([[0,this.nativeMediaSource_.duration]]):this.nativeMediaSource_.seekable}}),Object.defineProperty(s,"readyState",{get:function(){return this.nativeMediaSource_.readyState}}),Object.defineProperty(s,"activeSourceBuffers",{get:function(){return this.activeSourceBuffers_}}),s.sourceBuffers=[],s.activeSourceBuffers_=[],s.updateActiveSourceBuffers_=function(){if(s.activeSourceBuffers_.length=0,1===s.sourceBuffers.length){var t=s.sourceBuffers[0];return t.appendAudioInitSegment_=!0,t.audioDisabled_=!t.audioCodec_,void s.activeSourceBuffers_.push(t)}for(var i=!1,r=!0,e=0;e<s.player_.audioTracks().length;e++){var n=s.player_.audioTracks()[e];if(n.enabled&&"main"!==n.kind){r=!(i=!0);break}}s.sourceBuffers.forEach(function(t,e){if(t.appendAudioInitSegment_=!0,t.videoCodec_&&t.audioCodec_)t.audioDisabled_=i;else if(t.videoCodec_&&!t.audioCodec_)t.audioDisabled_=!0,r=!1;else if(!t.videoCodec_&&t.audioCodec_&&(t.audioDisabled_=e?r:!r,t.audioDisabled_))return;s.activeSourceBuffers_.push(t)})},s.onPlayerMediachange_=function(){s.sourceBuffers.forEach(function(t){t.appendAudioInitSegment_=!0})},s.onHlsReset_=function(){s.sourceBuffers.forEach(function(t){t.transmuxer_&&t.transmuxer_.postMessage({action:"resetCaptions"})})},s.onHlsSegmentTimeMapping_=function(e){s.sourceBuffers.forEach(function(t){return t.timeMapping_=e.mapping})},["sourceopen","sourceclose","sourceended"].forEach(function(t){this.nativeMediaSource_.addEventListener(t,this.trigger.bind(this))},s),s.on("sourceopen",function(t){var e=p.querySelector('[src="'+s.url_+'"]');e&&(s.player_=As(e.parentNode),s.player_.tech_.on("hls-reset",s.onHlsReset_),s.player_.tech_.on("hls-segment-time-mapping",s.onHlsSegmentTimeMapping_),s.player_.audioTracks&&s.player_.audioTracks()&&(s.player_.audioTracks().on("change",s.updateActiveSourceBuffers_),s.player_.audioTracks().on("addtrack",s.updateActiveSourceBuffers_),s.player_.audioTracks().on("removetrack",s.updateActiveSourceBuffers_)),s.player_.on("mediachange",s.onPlayerMediachange_))}),s.on("sourceended",function(t){for(var e=Tu(s.duration),i=0;i<s.sourceBuffers.length;i++){var r=s.sourceBuffers[i],n=r.metadataTrack_&&r.metadataTrack_.cues;n&&n.length&&(n[n.length-1].endTime=e)}}),s.on("sourceclose",function(t){this.sourceBuffers.forEach(function(t){t.transmuxer_&&t.transmuxer_.terminate()}),this.sourceBuffers.length=0,this.player_&&(this.player_.audioTracks&&this.player_.audioTracks()&&(this.player_.audioTracks().off("change",this.updateActiveSourceBuffers_),this.player_.audioTracks().off("addtrack",this.updateActiveSourceBuffers_),this.player_.audioTracks().off("removetrack",this.updateActiveSourceBuffers_)),this.player_.el_&&(this.player_.off("mediachange",this.onPlayerMediachange_),this.player_.tech_.off("hls-reset",this.onHlsReset_),this.player_.tech_.off("hls-segment-time-mapping",this.onHlsSegmentTimeMapping_)))}),s}return _(i,e),i.prototype.addSeekableRange_=function(t,e){var i=void 0;if(this.duration!==1/0)throw(i=new Error("MediaSource.addSeekableRange() can only be invoked when the duration is Infinity")).name="InvalidStateError",i.code=11,i;(e>this.nativeMediaSource_.duration||isNaN(this.nativeMediaSource_.duration))&&(this.nativeMediaSource_.duration=e)},i.prototype.addSourceBuffer=function(t){var n,e,i=void 0,r=(n={type:"",parameters:{}},e=t.trim().split(";"),n.type=e.shift().trim(),e.forEach(function(t){var e=t.trim().split("=");if(1<e.length){var i=e[0].replace(/"/g,"").trim(),r=e[1].replace(/"/g,"").trim();n.parameters[i]=r}}),n);if(/^(video|audio)\/mp2t$/i.test(r.type)){var s=[];r.parameters&&r.parameters.codecs&&(s=r.parameters.codecs.split(","),s=(s=Nu(s)).filter(function(t){return Mu(t)||Uu(t)})),0===s.length&&(s=["avc1.4d400d","mp4a.40.2"]),i=new Bu(this,s),0!==this.sourceBuffers.length&&(this.sourceBuffers[0].createRealSourceBuffers_(),i.createRealSourceBuffers_(),this.sourceBuffers[0].audioDisabled_=!0)}else i=this.nativeMediaSource_.addSourceBuffer(t);return this.sourceBuffers.push(i),i},i}(As.EventTarget),Fu=0;As.mediaSources={};var Hu=function(t,e){var i=As.mediaSources[t];if(!i)throw new Error("Media Source not found (Video.js)");i.trigger({type:"sourceopen",swfId:e})},Vu=function(){return!!g.MediaSource&&!!g.MediaSource.isTypeSupported&&g.MediaSource.isTypeSupported('video/mp4;codecs="avc1.4d400d,mp4a.40.2"')},qu=function(){if(this.MediaSource={open:Hu,supportsNativeMediaSources:Vu},Vu())return new ju;throw new Error("Cannot use create a virtual MediaSource for this video")};qu.open=Hu,qu.supportsNativeMediaSources=Vu;var Wu={createObjectURL:function(t){var e=void 0;return t instanceof ju?(e=g.URL.createObjectURL(t.nativeMediaSource_),t.url_=e):t instanceof ju?(e="blob:vjs-media-source/"+Fu,Fu++,As.mediaSources[e]=t,e):(e=g.URL.createObjectURL(t),t.url_=e)}};As.MediaSource=qu,As.URL=Wu;var zu=As.mergeOptions,Gu=function(t,e){for(var a=zu(t,{duration:e.duration,minimumUpdatePeriod:e.minimumUpdatePeriod}),i=0;i<e.playlists.length;i++){var r=Bo(a,e.playlists[i]);r&&(a=r)}return No(e,function(t,e,i,r){if(t.playlists&&t.playlists.length){var n=t.playlists[0].uri,s=Bo(a,t.playlists[0]);s&&((a=s).mediaGroups[e][i][r].playlists[0]=a.playlists[n])}}),a},Xu=function(s){function a(t,e,i,r){y(this,a);var n=b(this,s.call(this));if(n.hls_=e,n.withCredentials=i,!t)throw new Error("A non-empty playlist URL or playlist is required");return n.on("minimumUpdatePeriod",function(){n.refreshXml_()}),n.on("mediaupdatetimeout",function(){n.refreshMedia_()}),"string"==typeof t?(n.srcUrl=t,n.state="HAVE_NOTHING",b(n)):(n.masterPlaylistLoader_=r,n.state="HAVE_METADATA",n.started=!0,n.media(t),g.setTimeout(function(){n.trigger("loadedmetadata")},0),n)}return _(a,s),a.prototype.dispose=function(){this.stopRequest(),g.clearTimeout(this.mediaUpdateTimeout)},a.prototype.stopRequest=function(){if(this.request){var t=this.request;this.request=null,t.onreadystatechange=null,t.abort()}},a.prototype.media=function(t){if(!t)return this.media_;if("HAVE_NOTHING"===this.state)throw new Error("Cannot switch media playlist from "+this.state);var e=this.state;if("string"==typeof t){if(!this.master.playlists[t])throw new Error("Unknown playlist URI: "+t);t=this.master.playlists[t]}var i=!this.media_||t.uri!==this.media_.uri;this.state="HAVE_METADATA",i&&(this.media_&&this.trigger("mediachanging"),this.media_=t,this.refreshMedia_(),"HAVE_MASTER"!==e&&this.trigger("mediachange"))},a.prototype.pause=function(){this.stopRequest(),"HAVE_NOTHING"===this.state&&(this.started=!1)},a.prototype.load=function(){this.started?this.trigger("loadedplaylist"):this.start()},a.prototype.parseMasterXml=function(){var s=Sa(this.masterXml_,{manifestUri:this.srcUrl,clientOffset:this.clientOffset_});s.uri=this.srcUrl;for(var t=0;t<s.playlists.length;t++){var e="placeholder-uri-"+t;s.playlists[t].uri=e,s.playlists[e]=s.playlists[t]}return No(s,function(t,e,i,r){if(t.playlists&&t.playlists.length){var n="placeholder-uri-"+e+"-"+i+"-"+r;t.playlists[0].uri=n,s.playlists[n]=t.playlists[0]}}),jo(s),Fo(s),s},a.prototype.start=function(){var i=this;this.started=!0,this.request=this.hls_.xhr({uri:this.srcUrl,withCredentials:this.withCredentials},function(t,e){if(i.request){if(i.request=null,t)return i.error={status:e.status,message:"DASH playlist request error at URL: "+i.srcUrl,responseText:e.responseText,code:2},"HAVE_NOTHING"===i.state&&(i.started=!1),i.trigger("error");i.masterXml_=e.responseText,e.responseHeaders&&e.responseHeaders.date?i.masterLoaded_=Date.parse(e.responseHeaders.date):i.masterLoaded_=Date.now(),i.syncClientServerClock_(i.onClientServerClockSync_.bind(i))}})},a.prototype.syncClientServerClock_=function(r){var n=this,s=ka(this.masterXml_);return null===s?(this.clientOffset_=this.masterLoaded_-Date.now(),r()):"DIRECT"===s.method?(this.clientOffset_=s.value-Date.now(),r()):void(this.request=this.hls_.xhr({uri:Ro(this.srcUrl,s.value),method:s.method,withCredentials:this.withCredentials},function(t,e){if(n.request){if(t)return n.clientOffset_=n.masterLoaded_-Date.now(),r();var i=void 0;i="HEAD"===s.method?e.responseHeaders&&e.responseHeaders.date?Date.parse(e.responseHeaders.date):n.masterLoaded_:Date.parse(e.responseText),n.clientOffset_=i-Date.now(),r()}}))},a.prototype.onClientServerClockSync_=function(){var t=this;this.master=this.parseMasterXml(),this.state="HAVE_MASTER",this.trigger("loadedplaylist"),this.media_||this.media(this.master.playlists[0]),g.setTimeout(function(){t.trigger("loadedmetadata")},0),this.master.minimumUpdatePeriod&&g.setTimeout(function(){t.trigger("minimumUpdatePeriod")},this.master.minimumUpdatePeriod)},a.prototype.refreshXml_=function(){var r=this;this.request=this.hls_.xhr({uri:this.srcUrl,withCredentials:this.withCredentials},function(t,e){if(r.request){if(r.request=null,t)return r.error={status:e.status,message:"DASH playlist request error at URL: "+r.srcUrl,responseText:e.responseText,code:2},"HAVE_NOTHING"===r.state&&(r.started=!1),r.trigger("error");r.masterXml_=e.responseText;var i=r.parseMasterXml();r.master=Gu(r.master,i),g.setTimeout(function(){r.trigger("minimumUpdatePeriod")},r.master.minimumUpdatePeriod)}})},a.prototype.refreshMedia_=function(){var t=this,e=void 0,i=void 0;this.masterPlaylistLoader_?(e=this.masterPlaylistLoader_.master,i=this.masterPlaylistLoader_.parseMasterXml()):(e=this.master,i=this.parseMasterXml());var r=Gu(e,i);r?(this.masterPlaylistLoader_?this.masterPlaylistLoader_.master=r:this.master=r,this.media_=r.playlists[this.media_.uri]):this.trigger("playlistunchanged"),this.media().endList||(this.mediaUpdateTimeout=g.setTimeout(function(){t.trigger("mediaupdatetimeout")},Ho(this.media(),!!r))),this.trigger("loadedplaylist")},a}(As.EventTarget),Yu=function(t){return As.log.debug?As.log.debug.bind(As,"VHS:",t+" >"):function(){}};function $u(){}var Ku=function(){function n(t,e,i,r){y(this,n),this.callbacks_=[],this.pendingCallback_=null,this.timestampOffset_=0,this.mediaSource=t,this.processedAppend_=!1,this.type_=i,this.mimeType_=e,this.logger_=Yu("SourceUpdater["+i+"]["+e+"]"),"closed"===t.readyState?t.addEventListener("sourceopen",this.createSourceBuffer_.bind(this,e,r)):this.createSourceBuffer_(e,r)}return n.prototype.createSourceBuffer_=function(t,e){var i=this;this.sourceBuffer_=this.mediaSource.addSourceBuffer(t),this.logger_("created SourceBuffer"),e&&(e.trigger("sourcebufferadded"),this.mediaSource.sourceBuffers.length<2)?e.on("sourcebufferadded",function(){i.start_()}):this.start_()},n.prototype.start_=function(){var e=this;this.started_=!0,this.onUpdateendCallback_=function(){var t=e.pendingCallback_;e.pendingCallback_=null,e.logger_("buffered ["+vu(e.buffered())+"]"),t&&t(),e.runCallback_()},this.sourceBuffer_.addEventListener("updateend",this.onUpdateendCallback_),this.runCallback_()},n.prototype.abort=function(t){var e=this;this.processedAppend_&&this.queueCallback_(function(){e.sourceBuffer_.abort()},t)},n.prototype.appendBuffer=function(t,e){var i=this;this.processedAppend_=!0,this.queueCallback_(function(){i.sourceBuffer_.appendBuffer(t)},e)},n.prototype.buffered=function(){return this.sourceBuffer_?this.sourceBuffer_.buffered:As.createTimeRanges()},n.prototype.remove=function(t,e){var i=this;this.processedAppend_&&this.queueCallback_(function(){i.logger_("remove ["+t+" => "+e+"]"),i.sourceBuffer_.remove(t,e)},$u)},n.prototype.updating=function(){return!this.sourceBuffer_||this.sourceBuffer_.updating||this.pendingCallback_},n.prototype.timestampOffset=function(t){var e=this;return"undefined"!=typeof t&&(this.queueCallback_(function(){e.sourceBuffer_.timestampOffset=t}),this.timestampOffset_=t),this.timestampOffset_},n.prototype.queueCallback_=function(t,e){this.callbacks_.push([t.bind(this),e]),this.runCallback_()},n.prototype.runCallback_=function(){var t=void 0;!this.updating()&&this.callbacks_.length&&this.started_&&(t=this.callbacks_.shift(),this.pendingCallback_=t[1],t[0]())},n.prototype.dispose=function(){this.sourceBuffer_.removeEventListener("updateend",this.onUpdateendCallback_),this.sourceBuffer_&&"open"===this.mediaSource.readyState&&this.sourceBuffer_.abort()},n}(),Qu={GOAL_BUFFER_LENGTH:30,MAX_GOAL_BUFFER_LENGTH:60,GOAL_BUFFER_LENGTH_RATE:1,BANDWIDTH_VARIANCE:1.2,BUFFER_LOW_WATER_LINE:0,MAX_BUFFER_LOW_WATER_LINE:30,BUFFER_LOW_WATER_LINE_RATE:1},Ju=2,Zu=-101,tl=-102,el=function(t){var e,i,r={};return t.byterange&&(r.Range=(e=t.byterange,i=e.offset+e.length-1,"bytes="+e.offset+"-"+i)),r},il=function(t){t.forEach(function(t){t.abort()})},rl=function(t,e){return e.timedout?{status:e.status,message:"HLS request timed-out at URL: "+e.uri,code:Zu,xhr:e}:e.aborted?{status:e.status,message:"HLS request aborted at URL: "+e.uri,code:tl,xhr:e}:t?{status:e.status,message:"HLS request errored at URL: "+e.uri,code:Ju,xhr:e}:null},nl=function(a,o,u){var l=[],c=0;return function(t,e){if(t&&(il(a),l.push(t)),(c+=1)===a.length){if(e.endOfAllRequests=Date.now(),0<l.length){var i=l.reduce(function(t,e){return e.code>t.code?e:t});return u(i,e)}return e.encryptedBytes?(n=e,s=u,(r=o).addEventListener("message",function t(e){if(e.data.source===n.requestId){r.removeEventListener("message",t);var i=e.data.decrypted;return n.bytes=new Uint8Array(i.bytes,i.byteOffset,i.byteLength),s(null,n)}}),void r.postMessage(cu({source:n.requestId,encrypted:n.encryptedBytes,key:n.key.bytes,iv:n.key.iv}),[n.encryptedBytes.buffer,n.key.bytes.buffer])):u(null,e)}var r,n,s}},sl=function(n,s){return function(t){var e,i,r;return n.stats=As.mergeOptions(n.stats,(i=(e=t).target,(r={bandwidth:1/0,bytesReceived:0,roundTripTime:Date.now()-i.requestTime||0}).bytesReceived=e.loaded,r.bandwidth=Math.floor(r.bytesReceived/r.roundTripTime*8*1e3),r)),!n.stats.firstBytesReceivedAt&&n.stats.bytesReceived&&(n.stats.firstBytesReceivedAt=Date.now()),s(t,n)}},al=function(t,e,i,r,n,s){var a,o,u,l,c=[],h=nl(c,i,s);if(r.key){var d=t(As.mergeOptions(e,{uri:r.key.resolvedUri,responseType:"arraybuffer"}),(a=r,o=h,function(t,e){var i=e.response,r=rl(t,e);if(r)return o(r,a);if(16!==i.byteLength)return o({status:e.status,message:"Invalid HLS key at URL: "+e.uri,code:Ju,xhr:e},a);var n=new DataView(i);return a.key.bytes=new Uint32Array([n.getUint32(0),n.getUint32(4),n.getUint32(8),n.getUint32(12)]),o(null,a)}));c.push(d)}if(r.map&&!r.map.bytes){var p=t(As.mergeOptions(e,{uri:r.map.resolvedUri,responseType:"arraybuffer",headers:el(r.map)}),(u=r,l=h,function(t,e){var i=e.response,r=rl(t,e);return r?l(r,u):0===i.byteLength?l({status:e.status,message:"Empty HLS segment content at URL: "+e.uri,code:Ju,xhr:e},u):(u.map.bytes=new Uint8Array(e.response),l(null,u))}));c.push(p)}var f,m,g=t(As.mergeOptions(e,{uri:r.resolvedUri,responseType:"arraybuffer",headers:el(r)}),(f=r,m=h,function(t,e){var i,r=e.response,n=rl(t,e);return n?m(n,f):0===r.byteLength?m({status:e.status,message:"Empty HLS segment content at URL: "+e.uri,code:Ju,xhr:e},f):(f.stats={bandwidth:(i=e).bandwidth,bytesReceived:i.bytesReceived||0,roundTripTime:i.roundTripTime||0},f.key?f.encryptedBytes=new Uint8Array(e.response):f.bytes=new Uint8Array(e.response),m(null,f))}));return g.addEventListener("progress",sl(r,n)),c.push(g),function(){return il(c)}},ol={videoCodec:"avc1",videoObjectTypeIndicator:".4d400d",audioProfile:"2"},ul=function(){var t,e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",i={codecCount:0};return i.codecCount=e.split(",").length,i.codecCount=i.codecCount||2,(t=/(^|\s|,)+(avc[13])([^ ,]*)/i.exec(e))&&(i.videoCodec=t[2],i.videoObjectTypeIndicator=t[3]),i.audioProfile=/(^|\s|,)+mp4a.[0-9A-Fa-f]+\.([0-9A-Fa-f]+)/i.exec(e),i.audioProfile=i.audioProfile&&i.audioProfile[2],i},ll=function(t,e,i){return t+"/"+e+'; codecs="'+i.filter(function(t){return!!t}).join(", ")+'"'},cl=function(t,e){var i,r,n=(i=e).segments&&i.segments.length&&i.segments[0].map?"mp4":"mp2t",s=(r=e.attributes||{}).CODECS?ul(r.CODECS):ol,a=e.attributes||{},o=!0,u=!1;if(!e)return[];if(t.mediaGroups.AUDIO&&a.AUDIO){var l=t.mediaGroups.AUDIO[a.AUDIO];if(l)for(var c in o=!(u=!0),l)if(!l[c].uri&&!l[c].playlists){o=!0;break}}u&&!s.audioProfile&&(o||(s.audioProfile=function(t,e){if(!t.mediaGroups.AUDIO||!e)return null;var i=t.mediaGroups.AUDIO[e];if(!i)return null;for(var r in i){var n=i[r];if(n.default&&n.playlists)return ul(n.playlists[0].attributes.CODECS).audioProfile}return null}(t,a.AUDIO)),s.audioProfile||(As.log.warn("Multiple audio tracks present but no audio codec string is specified. Attempting to use the default audio codec (mp4a.40.2)"),s.audioProfile=ol.audioProfile));var h={};s.videoCodec&&(h.video=""+s.videoCodec+s.videoObjectTypeIndicator),s.audioProfile&&(h.audio="mp4a.40."+s.audioProfile);var d=ll("audio",n,[h.audio]),p=ll("video",n,[h.video]),f=ll("video",n,[h.video,h.audio]);return u?!o&&h.video?[p,d]:o||h.video?[f,d]:[d,d]:h.video?[f]:[d]},hl=function(t,e){var i;return t&&(i=g.getComputedStyle(t))?i[e]:""},dl=function(t,r){var n=t.slice();t.sort(function(t,e){var i=r(t,e);return 0===i?n.indexOf(t)-n.indexOf(e):i})},pl=function(t,e){var i=void 0,r=void 0;return t.attributes.BANDWIDTH&&(i=t.attributes.BANDWIDTH),i=i||g.Number.MAX_VALUE,e.attributes.BANDWIDTH&&(r=e.attributes.BANDWIDTH),i-(r=r||g.Number.MAX_VALUE)},fl=function(t,e,i){if(!t||!e)return!1;var r=i===t.segments.length;return t.endList&&"open"===e.readyState&&r},ml=function(t){return"number"==typeof t&&isFinite(t)},gl=function(i){function r(t){y(this,r);var e=b(this,i.call(this));if(!t)throw new TypeError("Initialization settings are required");if("function"!=typeof t.currentTime)throw new TypeError("No currentTime getter specified");if(!t.mediaSource)throw new TypeError("No MediaSource specified");return e.bandwidth=t.bandwidth,e.throughput={rate:0,count:0},e.roundTrip=NaN,e.resetStats_(),e.mediaIndex=null,e.hasPlayed_=t.hasPlayed,e.currentTime_=t.currentTime,e.seekable_=t.seekable,e.seeking_=t.seeking,e.duration_=t.duration,e.mediaSource_=t.mediaSource,e.hls_=t.hls,e.loaderType_=t.loaderType,e.startingMedia_=void 0,e.segmentMetadataTrack_=t.segmentMetadataTrack,e.goalBufferLength_=t.goalBufferLength,e.sourceType_=t.sourceType,e.state_="INIT",e.checkBufferTimeout_=null,e.error_=void 0,e.currentTimeline_=-1,e.pendingSegment_=null,e.mimeType_=null,e.sourceUpdater_=null,e.xhrOptions_=null,e.activeInitSegmentId_=null,e.initSegments_={},e.decrypter_=t.decrypter,e.syncController_=t.syncController,e.syncPoint_={segmentIndex:0,time:0},e.syncController_.on("syncinfoupdate",function(){return e.trigger("syncinfoupdate")}),e.mediaSource_.addEventListener("sourceopen",function(){return e.ended_=!1}),e.fetchAtBuffer_=!1,e.logger_=Yu("SegmentLoader["+e.loaderType_+"]"),Object.defineProperty(e,"state",{get:function(){return this.state_},set:function(t){t!==this.state_&&(this.logger_(this.state_+" -> "+t),this.state_=t)}}),e}return _(r,i),r.prototype.resetStats_=function(){this.mediaBytesTransferred=0,this.mediaRequests=0,this.mediaRequestsAborted=0,this.mediaRequestsTimedout=0,this.mediaRequestsErrored=0,this.mediaTransferDuration=0,this.mediaSecondsLoaded=0},r.prototype.dispose=function(){this.state="DISPOSED",this.pause(),this.abort_(),this.sourceUpdater_&&this.sourceUpdater_.dispose(),this.resetStats_()},r.prototype.abort=function(){"WAITING"===this.state?(this.abort_(),this.state="READY",this.paused()||this.monitorBuffer_()):this.pendingSegment_&&(this.pendingSegment_=null)},r.prototype.abort_=function(){this.pendingSegment_&&this.pendingSegment_.abortRequests(),this.pendingSegment_=null},r.prototype.error=function(t){return"undefined"!=typeof t&&(this.error_=t),this.pendingSegment_=null,this.error_},r.prototype.endOfStream=function(){this.ended_=!0,this.pause(),this.trigger("ended")},r.prototype.buffered_=function(){return this.sourceUpdater_?this.sourceUpdater_.buffered():As.createTimeRanges()},r.prototype.initSegment=function(t){var e=1<arguments.length&&void 0!==arguments[1]&&arguments[1];if(!t)return null;var i=hu(t),r=this.initSegments_[i];return e&&!r&&t.bytes&&(this.initSegments_[i]=r={resolvedUri:t.resolvedUri,byterange:t.byterange,bytes:t.bytes}),r||t},r.prototype.couldBeginLoading_=function(){return this.playlist_&&(this.sourceUpdater_||this.mimeType_&&"INIT"===this.state)&&!this.paused()},r.prototype.load=function(){if(this.monitorBuffer_(),this.playlist_){if(this.syncController_.setDateTimeMapping(this.playlist_),"INIT"===this.state&&this.couldBeginLoading_())return this.init_();!this.couldBeginLoading_()||"READY"!==this.state&&"INIT"!==this.state||(this.state="READY")}},r.prototype.init_=function(){return this.state="READY",this.sourceUpdater_=new Ku(this.mediaSource_,this.mimeType_,this.loaderType_,this.sourceBufferEmitter_),this.resetEverything(),this.monitorBuffer_()},r.prototype.playlist=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};if(t){var i=this.playlist_,r=this.pendingSegment_;this.playlist_=t,this.xhrOptions_=e,this.hasPlayed_()||(t.syncInfo={mediaSequence:t.mediaSequence,time:0});var n=i?i.id:null;if(this.logger_("playlist update ["+n+" => "+t.id+"]"),this.trigger("syncinfoupdate"),"INIT"===this.state&&this.couldBeginLoading_())return this.init_();if(i&&i.uri===t.uri){var s=t.mediaSequence-i.mediaSequence;this.logger_("live window shift ["+s+"]"),null!==this.mediaIndex&&(this.mediaIndex-=s),r&&(r.mediaIndex-=s,0<=r.mediaIndex&&(r.segment=t.segments[r.mediaIndex])),this.syncController_.saveExpiredSegmentInfo(i,t)}else null!==this.mediaIndex&&this.resyncLoader()}},r.prototype.pause=function(){this.checkBufferTimeout_&&(g.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=null)},r.prototype.paused=function(){return null===this.checkBufferTimeout_},r.prototype.mimeType=function(t,e){this.mimeType_||(this.mimeType_=t,this.sourceBufferEmitter_=e,"INIT"===this.state&&this.couldBeginLoading_()&&this.init_())},r.prototype.resetEverything=function(){this.ended_=!1,this.resetLoader(),this.remove(0,this.duration_()),this.trigger("reseteverything")},r.prototype.resetLoader=function(){this.fetchAtBuffer_=!1,this.resyncLoader()},r.prototype.resyncLoader=function(){this.mediaIndex=null,this.syncPoint_=null,this.abort()},r.prototype.remove=function(t,e){this.sourceUpdater_&&this.sourceUpdater_.remove(t,e),bu(t,e,this.segmentMetadataTrack_)},r.prototype.monitorBuffer_=function(){this.checkBufferTimeout_&&g.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=g.setTimeout(this.monitorBufferTick_.bind(this),1)},r.prototype.monitorBufferTick_=function(){"READY"===this.state&&this.fillBuffer_(),this.checkBufferTimeout_&&g.clearTimeout(this.checkBufferTimeout_),this.checkBufferTimeout_=g.setTimeout(this.monitorBufferTick_.bind(this),500)},r.prototype.fillBuffer_=function(){if(!this.sourceUpdater_.updating()){this.syncPoint_||(this.syncPoint_=this.syncController_.getSyncPoint(this.playlist_,this.duration_(),this.currentTimeline_,this.currentTime_()));var t=this.checkBuffer_(this.buffered_(),this.playlist_,this.mediaIndex,this.hasPlayed_(),this.currentTime_(),this.syncPoint_);if(t)fl(this.playlist_,this.mediaSource_,t.mediaIndex)?this.endOfStream():(t.mediaIndex!==this.playlist_.segments.length-1||"ended"!==this.mediaSource_.readyState||this.seeking_())&&((t.timeline!==this.currentTimeline_||null!==t.startOfSegment&&t.startOfSegment<this.sourceUpdater_.timestampOffset())&&(this.syncController_.reset(),t.timestampOffset=t.startOfSegment),this.loadSegment_(t))}},r.prototype.checkBuffer_=function(t,e,i,r,n,s){var a=0,o=void 0;t.length&&(a=t.end(t.length-1));var u=Math.max(0,a-n);if(!e.segments.length)return null;if(u>=this.goalBufferLength_())return null;if(!r&&1<=u)return null;if(null===s)return i=this.getSyncSegmentCandidate_(e),this.generateSegmentInfo_(e,i,null,!0);if(null!==i){var l=e.segments[i];return o=l&&l.end?l.end:a,this.generateSegmentInfo_(e,i+1,o,!1)}if(this.fetchAtBuffer_){var c=nu.getMediaInfoForTime(e,a,s.segmentIndex,s.time);i=c.mediaIndex,o=c.startTime}else{var h=nu.getMediaInfoForTime(e,n,s.segmentIndex,s.time);i=h.mediaIndex,o=h.startTime}return this.generateSegmentInfo_(e,i,o,!1)},r.prototype.getSyncSegmentCandidate_=function(t){var e=this;if(-1===this.currentTimeline_)return 0;var i=t.segments.map(function(t,e){return{timeline:t.timeline,segmentIndex:e}}).filter(function(t){return t.timeline===e.currentTimeline_});return i.length?i[Math.min(i.length-1,1)].segmentIndex:Math.max(t.segments.length-1,0)},r.prototype.generateSegmentInfo_=function(t,e,i,r){if(e<0||e>=t.segments.length)return null;var n=t.segments[e];return{requestId:"segment-loader-"+Math.random(),uri:n.resolvedUri,mediaIndex:e,isSyncRequest:r,startOfSegment:i,playlist:t,bytes:null,encryptedBytes:null,timestampOffset:null,timeline:n.timeline,duration:n.duration,segment:n}},r.prototype.abortRequestEarly_=function(t){if(this.hls_.tech_.paused()||!this.xhrOptions_.timeout||!this.playlist_.attributes.BANDWIDTH)return!1;if(Date.now()-(t.firstBytesReceivedAt||Date.now())<1e3)return!1;var e=this.currentTime_(),i=t.bandwidth,r=this.pendingSegment_.duration,n=nu.estimateSegmentRequestTime(r,i,this.playlist_,t.bytesReceived),s=function(t,e){var i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:1;return((t.length?t.end(t.length-1):0)-e)/i}(this.buffered_(),e,this.hls_.tech_.playbackRate())-1;if(n<=s)return!1;var a=function(t){var e=t.master,i=t.currentTime,r=t.bandwidth,n=t.duration,s=t.segmentDuration,a=t.timeUntilRebuffer,o=t.currentTimeline,u=t.syncController,l=e.playlists.filter(function(t){return!nu.isIncompatible(t)}),c=l.filter(nu.isEnabled);c.length||(c=l.filter(function(t){return!nu.isDisabled(t)}));var h=c.filter(nu.hasAttribute.bind(null,"BANDWIDTH")).map(function(t){var e=u.getSyncPoint(t,n,o,i)?1:2;return{playlist:t,rebufferingImpact:nu.estimateSegmentRequestTime(s,r,t)*e-a}}),d=h.filter(function(t){return t.rebufferingImpact<=0});return dl(d,function(t,e){return pl(e.playlist,t.playlist)}),d.length?d[0]:(dl(h,function(t,e){return t.rebufferingImpact-e.rebufferingImpact}),h[0]||null)}({master:this.hls_.playlists.master,currentTime:e,bandwidth:i,duration:this.duration_(),segmentDuration:r,timeUntilRebuffer:s,currentTimeline:this.currentTimeline_,syncController:this.syncController_});if(a){var o=n-s-a.rebufferingImpact,u=.5;return s<=fu&&(u=1),!a.playlist||a.playlist.uri===this.playlist_.uri||o<u?!1:(this.bandwidth=a.playlist.attributes.BANDWIDTH*Qu.BANDWIDTH_VARIANCE+1,this.abort(),this.trigger("earlyabort"),!0)}},r.prototype.handleProgress_=function(t,e){this.pendingSegment_&&e.requestId===this.pendingSegment_.requestId&&!this.abortRequestEarly_(e.stats)&&this.trigger("progress")},r.prototype.loadSegment_=function(t){this.state="WAITING",this.pendingSegment_=t,this.trimBackBuffer_(t),t.abortRequests=al(this.hls_.xhr,this.xhrOptions_,this.decrypter_,this.createSimplifiedSegmentObj_(t),this.handleProgress_.bind(this),this.segmentRequestFinished_.bind(this))},r.prototype.trimBackBuffer_=function(t){var e,i,r,n,s=(e=this.seekable_(),i=this.currentTime_(),r=this.playlist_.targetDuration||10,n=void 0,n=e.length&&0<e.start(0)&&e.start(0)<i?e.start(0):i-30,Math.min(n,i-r));0<s&&this.remove(0,s)},r.prototype.createSimplifiedSegmentObj_=function(t){var e=t.segment,i={resolvedUri:e.resolvedUri,byterange:e.byterange,requestId:t.requestId};if(e.key){var r=e.key.iv||new Uint32Array([0,0,0,t.mediaIndex+t.playlist.mediaSequence]);i.key={resolvedUri:e.key.resolvedUri,iv:r}}return e.map&&(i.map=this.initSegment(e.map)),i},r.prototype.segmentRequestFinished_=function(t,e){if(this.mediaRequests+=1,e.stats&&(this.mediaBytesTransferred+=e.stats.bytesReceived,this.mediaTransferDuration+=e.stats.roundTripTime),this.pendingSegment_){if(e.requestId===this.pendingSegment_.requestId){if(t)return this.pendingSegment_=null,this.state="READY",t.code===tl?void(this.mediaRequestsAborted+=1):(this.pause(),t.code===Zu?(this.mediaRequestsTimedout+=1,this.bandwidth=1,this.roundTrip=NaN,void this.trigger("bandwidthupdate")):(this.mediaRequestsErrored+=1,this.error(t),void this.trigger("error")));this.bandwidth=e.stats.bandwidth,this.roundTrip=e.stats.roundTripTime,e.map&&(e.map=this.initSegment(e.map,!0)),this.processSegmentResponse_(e)}}else this.mediaRequestsAborted+=1},r.prototype.processSegmentResponse_=function(t){var e=this.pendingSegment_;e.bytes=t.bytes,t.map&&(e.segment.map.bytes=t.map.bytes),e.endOfAllRequests=t.endOfAllRequests,this.handleSegment_()},r.prototype.handleSegment_=function(){var t=this;if(this.pendingSegment_){var e=this.pendingSegment_,i=e.segment,r=this.syncController_.probeSegmentInfo(e);"undefined"==typeof this.startingMedia_&&r&&(r.containsAudio||r.containsVideo)&&(this.startingMedia_={containsAudio:r.containsAudio,containsVideo:r.containsVideo});var n,s,a,o=(n=this.loaderType_,s=this.startingMedia_,a=r,"main"===n&&s&&a?a.containsAudio||a.containsVideo?s.containsVideo&&!a.containsVideo?"Only audio found in segment when we expected video. We can't switch to audio only from a stream that had video. To get rid of this message, please add codec information to the manifest.":!s.containsVideo&&a.containsVideo?"Video found in segment when we expected only audio. We can't switch to a stream with video from an audio only stream. To get rid of this message, please add codec information to the manifest.":null:"Neither audio nor video found in segment.":null);if(o)return this.error({message:o,blacklistDuration:1/0}),void this.trigger("error");if(e.isSyncRequest)return this.trigger("syncinfoupdate"),this.pendingSegment_=null,void(this.state="READY");null!==e.timestampOffset&&e.timestampOffset!==this.sourceUpdater_.timestampOffset()&&(this.sourceUpdater_.timestampOffset(e.timestampOffset),this.trigger("timestampoffset"));var u,l,c,h,d,p,f,m,g,y,v,_=this.syncController_.mappingForTimeline(e.timeline);if(null!==_&&this.trigger({type:"segmenttimemapping",mapping:_}),this.state="APPENDING",i.map){var b=hu(i.map);if(!this.activeInitSegmentId_||this.activeInitSegmentId_!==b){var T=this.initSegment(i.map);this.sourceUpdater_.appendBuffer(T.bytes,function(){t.activeInitSegmentId_=b})}}e.byteLength=e.bytes.byteLength,"number"==typeof i.start&&"number"==typeof i.end?this.mediaSecondsLoaded+=i.end-i.start:this.mediaSecondsLoaded+=i.duration,this.logger_((l=(u=e).segment,c=l.start,h=l.end,d=u.playlist,p=d.mediaSequence,f=d.id,m=d.segments,g=void 0===m?[]:m,y=u.mediaIndex,v=u.timeline,["appending ["+y+"] of ["+p+", "+(p+g.length)+"] from playlist ["+f+"]","["+c+" => "+h+"] in timeline ["+v+"]"].join(" "))),this.sourceUpdater_.appendBuffer(e.bytes,this.handleUpdateEnd_.bind(this))}else this.state="READY"},r.prototype.handleUpdateEnd_=function(){if(!this.pendingSegment_)return this.state="READY",void(this.paused()||this.monitorBuffer_());var t=this.pendingSegment_,e=t.segment,i=null!==this.mediaIndex;(this.pendingSegment_=null,this.recordThroughput_(t),this.addSegmentMetadataCue_(t),this.state="READY",this.mediaIndex=t.mediaIndex,this.fetchAtBuffer_=!0,this.currentTimeline_=t.timeline,this.trigger("syncinfoupdate"),e.end&&this.currentTime_()-e.end>3*t.playlist.targetDuration)?this.resetEverything():(i&&this.trigger("bandwidthupdate"),this.trigger("progress"),fl(t.playlist,this.mediaSource_,t.mediaIndex+1)&&this.endOfStream(),this.paused()||this.monitorBuffer_())},r.prototype.recordThroughput_=function(t){var e=this.throughput.rate,i=Date.now()-t.endOfAllRequests+1,r=Math.floor(t.byteLength/i*8*1e3);this.throughput.rate+=(r-e)/++this.throughput.count},r.prototype.addSegmentMetadataCue_=function(t){if(this.segmentMetadataTrack_){var e=t.segment,i=e.start,r=e.end;if(ml(i)&&ml(r)){bu(i,r,this.segmentMetadataTrack_);var n=g.WebKitDataCue||g.VTTCue,s={bandwidth:t.playlist.attributes.BANDWIDTH,resolution:t.playlist.attributes.RESOLUTION,codecs:t.playlist.attributes.CODECS,byteLength:t.byteLength,uri:t.uri,timeline:t.timeline,playlist:t.playlist.uri,start:i,end:r},a=new n(i,r,JSON.stringify(s));a.value=s,this.segmentMetadataTrack_.addCue(a)}}},r}(As.EventTarget),yl=new Uint8Array("\n\n".split("").map(function(t){return t.charCodeAt(0)})),vl=function(t){return String.fromCharCode.apply(null,t)},_l=function(r){function n(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};y(this,n);var i=b(this,r.call(this,t,e));return i.mediaSource_=null,i.subtitlesTrack_=null,i}return _(n,r),n.prototype.buffered_=function(){if(!this.subtitlesTrack_||!this.subtitlesTrack_.cues.length)return As.createTimeRanges();var t=this.subtitlesTrack_.cues,e=t[0].startTime,i=t[t.length-1].startTime;return As.createTimeRanges([[e,i]])},n.prototype.initSegment=function(t){var e=1<arguments.length&&void 0!==arguments[1]&&arguments[1];if(!t)return null;var i=hu(t),r=this.initSegments_[i];if(e&&!r&&t.bytes){var n=yl.byteLength+t.bytes.byteLength,s=new Uint8Array(n);s.set(t.bytes),s.set(yl,t.bytes.byteLength),this.initSegments_[i]=r={resolvedUri:t.resolvedUri,byterange:t.byterange,bytes:s}}return r||t},n.prototype.couldBeginLoading_=function(){return this.playlist_&&this.subtitlesTrack_&&!this.paused()},n.prototype.init_=function(){return this.state="READY",this.resetEverything(),this.monitorBuffer_()},n.prototype.track=function(t){return"undefined"==typeof t||(this.subtitlesTrack_=t,"INIT"===this.state&&this.couldBeginLoading_()&&this.init_()),this.subtitlesTrack_},n.prototype.remove=function(t,e){bu(t,e,this.subtitlesTrack_)},n.prototype.fillBuffer_=function(){var t=this;this.syncPoint_||(this.syncPoint_=this.syncController_.getSyncPoint(this.playlist_,this.duration_(),this.currentTimeline_,this.currentTime_()));var e=this.checkBuffer_(this.buffered_(),this.playlist_,this.mediaIndex,this.hasPlayed_(),this.currentTime_(),this.syncPoint_);if(e=this.skipEmptySegments_(e)){if(null===this.syncController_.timestampOffsetForTimeline(e.timeline)){return this.syncController_.one("timestampoffset",function(){t.state="READY",t.paused()||t.monitorBuffer_()}),void(this.state="WAITING_ON_TIMELINE")}this.loadSegment_(e)}},n.prototype.skipEmptySegments_=function(t){for(;t&&t.segment.empty;)t=this.generateSegmentInfo_(t.playlist,t.mediaIndex+1,t.startOfSegment+t.duration,t.isSyncRequest);return t},n.prototype.handleSegment_=function(){var e=this;if(this.pendingSegment_&&this.subtitlesTrack_){this.state="APPENDING";var t=this.pendingSegment_,i=t.segment;if("function"!=typeof g.WebVTT&&this.subtitlesTrack_&&this.subtitlesTrack_.tech_){var r=function(){e.handleSegment_()};return this.state="WAITING_ON_VTTJS",this.subtitlesTrack_.tech_.one("vttjsloaded",r),void this.subtitlesTrack_.tech_.one("vttjserror",function(){e.subtitlesTrack_.tech_.off("vttjsloaded",r),e.error({message:"Error loading vtt.js"}),e.state="READY",e.pause(),e.trigger("error")})}i.requested=!0;try{this.parseVTTCues_(t)}catch(t){return this.error({message:t.message}),this.state="READY",this.pause(),this.trigger("error")}if(this.updateTimeMapping_(t,this.syncController_.timelines[t.timeline],this.playlist_),t.isSyncRequest)return this.trigger("syncinfoupdate"),this.pendingSegment_=null,void(this.state="READY");t.byteLength=t.bytes.byteLength,this.mediaSecondsLoaded+=i.duration,t.cues.length&&this.remove(t.cues[0].endTime,t.cues[t.cues.length-1].endTime),t.cues.forEach(function(t){e.subtitlesTrack_.addCue(t)}),this.handleUpdateEnd_()}else this.state="READY"},n.prototype.parseVTTCues_=function(e){var t=void 0,i=!1;"function"==typeof g.TextDecoder?t=new g.TextDecoder("utf8"):(t=g.WebVTT.StringDecoder(),i=!0);var r=new g.WebVTT.Parser(g,g.vttjs,t);if(e.cues=[],e.timestampmap={MPEGTS:0,LOCAL:0},r.oncue=e.cues.push.bind(e.cues),r.ontimestampmap=function(t){return e.timestampmap=t},r.onparsingerror=function(t){As.log.warn("Error encountered when parsing cues: "+t.message)},e.segment.map){var n=e.segment.map.bytes;i&&(n=vl(n)),r.parse(n)}var s=e.bytes;i&&(s=vl(s)),r.parse(s),r.flush()},n.prototype.updateTimeMapping_=function(t,e,i){var r=t.segment;if(e)if(t.cues.length){var n=t.timestampmap,s=n.MPEGTS/9e4-n.LOCAL+e.mapping;if(t.cues.forEach(function(t){t.startTime+=s,t.endTime+=s}),!i.syncInfo){var a=t.cues[0].startTime,o=t.cues[t.cues.length-1].startTime;i.syncInfo={mediaSequence:i.mediaSequence+t.mediaIndex,time:Math.min(a,o-r.duration)}}}else r.empty=!0},n}(gl),bl=function(t,e){for(var i=t.cues,r=0;r<i.length;r++){var n=i[r];if(e>=n.adStartTime&&e<=n.adEndTime)return n}return null},Tl=So,Sl=[{name:"VOD",run:function(t,e,i,r,n){if(i!==1/0){return{time:0,segmentIndex:0}}return null}},{name:"ProgramDateTime",run:function(t,e,i,r,n){if(!t.datetimeToDisplayTime)return null;var s=e.segments||[],a=null,o=null;n=n||0;for(var u=0;u<s.length;u++){var l=s[u];if(l.dateTimeObject){var c=l.dateTimeObject.getTime()/1e3+t.datetimeToDisplayTime,h=Math.abs(n-c);if(null!==o&&o<h)break;o=h,a={time:c,segmentIndex:u}}}return a}},{name:"Segment",run:function(t,e,i,r,n){var s=e.segments||[],a=null,o=null;n=n||0;for(var u=0;u<s.length;u++){var l=s[u];if(l.timeline===r&&"undefined"!=typeof l.start){var c=Math.abs(n-l.start);if(null!==o&&o<c)break;(!a||null===o||c<=o)&&(o=c,a={time:l.start,segmentIndex:u})}}return a}},{name:"Discontinuity",run:function(t,e,i,r,n){var s=null;if(n=n||0,e.discontinuityStarts&&e.discontinuityStarts.length)for(var a=null,o=0;o<e.discontinuityStarts.length;o++){var u=e.discontinuityStarts[o],l=e.discontinuitySequence+o+1,c=t.discontinuities[l];if(c){var h=Math.abs(n-c.time);if(null!==a&&a<h)break;(!s||null===a||h<=a)&&(a=h,s={time:c.time,segmentIndex:u})}}return s}},{name:"Playlist",run:function(t,e,i,r,n){return e.syncInfo?{time:e.syncInfo.time,segmentIndex:e.syncInfo.mediaSequence-e.mediaSequence}:null}}],kl=function(e){function i(){y(this,i);var t=b(this,e.call(this));return t.inspectCache_=void 0,t.timelines=[],t.discontinuities=[],t.datetimeToDisplayTime=null,t.logger_=Yu("SyncController"),t}return _(i,e),i.prototype.getSyncPoint=function(t,e,i,r){var n=this.runStrategies_(t,e,i,r);return n.length?this.selectSyncPoint_(n,{key:"time",value:r}):null},i.prototype.getExpiredTime=function(t,e){if(!t||!t.segments)return null;var i=this.runStrategies_(t,e,t.discontinuitySequence,0);if(!i.length)return null;var r=this.selectSyncPoint_(i,{key:"segmentIndex",value:0});return 0<r.segmentIndex&&(r.time*=-1),Math.abs(r.time+Go(t,r.segmentIndex,0))},i.prototype.runStrategies_=function(t,e,i,r){for(var n=[],s=0;s<Sl.length;s++){var a=Sl[s],o=a.run(this,t,e,i,r);o&&(o.strategy=a.name,n.push({strategy:a.name,syncPoint:o}))}return n},i.prototype.selectSyncPoint_=function(t,e){for(var i=t[0].syncPoint,r=Math.abs(t[0].syncPoint[e.key]-e.value),n=t[0].strategy,s=1;s<t.length;s++){var a=Math.abs(t[s].syncPoint[e.key]-e.value);a<r&&(r=a,i=t[s].syncPoint,n=t[s].strategy)}return this.logger_("syncPoint for ["+e.key+": "+e.value+"] chosen with strategy ["+n+"]: [time:"+i.time+", segmentIndex:"+i.segmentIndex+"]"),i},i.prototype.saveExpiredSegmentInfo=function(t,e){for(var i=e.mediaSequence-t.mediaSequence-1;0<=i;i--){var r=t.segments[i];if(r&&"undefined"!=typeof r.start){e.syncInfo={mediaSequence:t.mediaSequence+i,time:r.start},this.logger_("playlist refresh sync: [time:"+e.syncInfo.time+", mediaSequence: "+e.syncInfo.mediaSequence+"]"),this.trigger("syncinfoupdate");break}}},i.prototype.setDateTimeMapping=function(t){if(!this.datetimeToDisplayTime&&t.segments&&t.segments.length&&t.segments[0].dateTimeObject){var e=t.segments[0].dateTimeObject.getTime()/1e3;this.datetimeToDisplayTime=-e}},i.prototype.reset=function(){this.inspectCache_=void 0},i.prototype.probeSegmentInfo=function(t){var e=t.segment,i=t.playlist,r=void 0;return(r=e.map?this.probeMp4Segment_(t):this.probeTsSegment_(t))&&this.calculateSegmentTimeMapping_(t,r)&&(this.saveDiscontinuitySyncInfo_(t),i.syncInfo||(i.syncInfo={mediaSequence:i.mediaSequence+t.mediaIndex,time:e.start})),r},i.prototype.probeMp4Segment_=function(t){var e=t.segment,i=La(e.map.bytes),r=Pa(i,t.bytes);return null!==t.timestampOffset&&(t.timestampOffset-=r),{start:r,end:r+e.duration}},i.prototype.probeTsSegment_=function(t){var e=Tl(t.bytes,this.inspectCache_),i=void 0,r=void 0;return e?(e.video&&2===e.video.length?(this.inspectCache_=e.video[1].dts,i=e.video[0].dtsTime,r=e.video[1].dtsTime):e.audio&&2===e.audio.length&&(this.inspectCache_=e.audio[1].dts,i=e.audio[0].dtsTime,r=e.audio[1].dtsTime),{start:i,end:r,containsVideo:e.video&&2===e.video.length,containsAudio:e.audio&&2===e.audio.length}):null},i.prototype.timestampOffsetForTimeline=function(t){return"undefined"==typeof this.timelines[t]?null:this.timelines[t].time},i.prototype.mappingForTimeline=function(t){return"undefined"==typeof this.timelines[t]?null:this.timelines[t].mapping},i.prototype.calculateSegmentTimeMapping_=function(t,e){var i=t.segment,r=this.timelines[t.timeline];if(null!==t.timestampOffset)r={time:t.startOfSegment,mapping:t.startOfSegment-e.start},this.timelines[t.timeline]=r,this.trigger("timestampoffset"),this.logger_("time mapping for timeline "+t.timeline+": [time: "+r.time+"] [mapping: "+r.mapping+"]"),i.start=t.startOfSegment,i.end=e.end+r.mapping;else{if(!r)return!1;i.start=e.start+r.mapping,i.end=e.end+r.mapping}return!0},i.prototype.saveDiscontinuitySyncInfo_=function(t){var e=t.playlist,i=t.segment;if(i.discontinuity)this.discontinuities[i.timeline]={time:i.start,accuracy:0};else if(e.discontinuityStarts&&e.discontinuityStarts.length)for(var r=0;r<e.discontinuityStarts.length;r++){var n=e.discontinuityStarts[r],s=e.discontinuitySequence+r+1,a=n-t.mediaIndex,o=Math.abs(a);if(!this.discontinuities[s]||this.discontinuities[s].accuracy>o){var u=void 0;u=a<0?i.start-Go(e,t.mediaIndex,n):i.end+Go(e,t.mediaIndex+1,n),this.discontinuities[s]={time:u,accuracy:o}}}},i}(As.EventTarget),Cl=new Pu("./decrypter-worker.worker.js",function(t,e){var i,s,h,r,n,d,p,g,a,l,y,o,u=this;i="undefined"!=typeof t?t:"undefined"!=typeof global?global:"undefined"!=typeof u?u:{},s="undefined"!=typeof t?t:"undefined"!=typeof i?i:"undefined"!=typeof u?u:{},h=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},r=function(){function r(t,e){for(var i=0;i<e.length;i++){var r=e[i];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,e,i){return e&&r(t.prototype,e),i&&r(t,i),t}}(),n=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!==("undefined"==typeof e?"undefined":v(e))&&"function"!=typeof e?t:e},d=function(){var t=[[[],[],[],[],[]],[[],[],[],[],[]]],e=t[0],i=t[1],r=e[4],n=i[4],s=void 0,a=void 0,o=void 0,u=[],l=[],c=void 0,h=void 0,d=void 0,p=void 0,f=void 0;for(s=0;s<256;s++)l[(u[s]=s<<1^283*(s>>7))^s]=s;for(a=o=0;!r[a];a^=c||1,o=l[o]||1)for(d=(d=o^o<<1^o<<2^o<<3^o<<4)>>8^255&d^99,f=16843009*u[h=u[c=u[n[r[a]=d]=a]]]^65537*h^257*c^16843008*a,p=257*u[d]^16843008*d,s=0;s<4;s++)e[s][a]=p=p<<24^p>>>8,i[s][d]=f=f<<24^f>>>8;for(s=0;s<5;s++)e[s]=e[s].slice(0),i[s]=i[s].slice(0);return t},p=null,g=function(){function c(t){h(this,c),p||(p=d()),this._tables=[[p[0][0].slice(),p[0][1].slice(),p[0][2].slice(),p[0][3].slice(),p[0][4].slice()],[p[1][0].slice(),p[1][1].slice(),p[1][2].slice(),p[1][3].slice(),p[1][4].slice()]];var e=void 0,i=void 0,r=void 0,n=void 0,s=void 0,a=this._tables[0][4],o=this._tables[1],u=t.length,l=1;if(4!==u&&6!==u&&8!==u)throw new Error("Invalid aes key size");for(n=t.slice(0),s=[],this._key=[n,s],e=u;e<4*u+28;e++)r=n[e-1],(e%u==0||8===u&&e%u==4)&&(r=a[r>>>24]<<24^a[r>>16&255]<<16^a[r>>8&255]<<8^a[255&r],e%u==0&&(r=r<<8^r>>>24^l<<24,l=l<<1^283*(l>>7))),n[e]=n[e-u]^r;for(i=0;e;i++,e--)r=n[3&i?e:e-4],s[i]=e<=4||i<4?r:o[0][a[r>>>24]]^o[1][a[r>>16&255]]^o[2][a[r>>8&255]]^o[3][a[255&r]]}return c.prototype.decrypt=function(t,e,i,r,n,s){var a=this._key[1],o=t^a[0],u=r^a[1],l=i^a[2],c=e^a[3],h=void 0,d=void 0,p=void 0,f=a.length/4-2,m=void 0,g=4,y=this._tables[1],v=y[0],_=y[1],b=y[2],T=y[3],S=y[4];for(m=0;m<f;m++)h=v[o>>>24]^_[u>>16&255]^b[l>>8&255]^T[255&c]^a[g],d=v[u>>>24]^_[l>>16&255]^b[c>>8&255]^T[255&o]^a[g+1],p=v[l>>>24]^_[c>>16&255]^b[o>>8&255]^T[255&u]^a[g+2],c=v[c>>>24]^_[o>>16&255]^b[u>>8&255]^T[255&l]^a[g+3],g+=4,o=h,u=d,l=p;for(m=0;m<4;m++)n[(3&-m)+s]=S[o>>>24]<<24^S[u>>16&255]<<16^S[l>>8&255]<<8^S[255&c]^a[g++],h=o,o=u,u=l,l=c,c=h},c}(),a=function(){function t(){h(this,t),this.listeners={}}return t.prototype.on=function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},t.prototype.off=function(t,e){if(!this.listeners[t])return!1;var i=this.listeners[t].indexOf(e);return this.listeners[t].splice(i,1),-1<i},t.prototype.trigger=function(t){var e=this.listeners[t];if(e)if(2===arguments.length)for(var i=e.length,r=0;r<i;++r)e[r].call(this,arguments[1]);else for(var n=Array.prototype.slice.call(arguments,1),s=e.length,a=0;a<s;++a)e[a].apply(this,n)},t.prototype.dispose=function(){this.listeners={}},t.prototype.pipe=function(e){this.on("data",function(t){e.push(t)})},t}(),l=function(e){function i(){h(this,i);var t=n(this,e.call(this,a));return t.jobs=[],t.delay=1,t.timeout_=null,t}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+("undefined"==typeof e?"undefined":v(e)));t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(i,e),i.prototype.processJob_=function(){this.jobs.shift()(),this.jobs.length?this.timeout_=setTimeout(this.processJob_.bind(this),this.delay):this.timeout_=null},i.prototype.push=function(t){this.jobs.push(t),this.timeout_||(this.timeout_=setTimeout(this.processJob_.bind(this),this.delay))},i}(a),y=function(t){return t<<24|(65280&t)<<8|(16711680&t)>>8|t>>>24},o=function(){function u(t,e,i,r){h(this,u);var n=u.STEP,s=new Int32Array(t.buffer),a=new Uint8Array(t.byteLength),o=0;for(this.asyncStream_=new l,this.asyncStream_.push(this.decryptChunk_(s.subarray(o,o+n),e,i,a)),o=n;o<s.length;o+=n)i=new Uint32Array([y(s[o-4]),y(s[o-3]),y(s[o-2]),y(s[o-1])]),this.asyncStream_.push(this.decryptChunk_(s.subarray(o,o+n),e,i,a));this.asyncStream_.push(function(){var t;r(null,(t=a).subarray(0,t.byteLength-t[t.byteLength-1]))})}return u.prototype.decryptChunk_=function(e,i,r,n){return function(){var t=function(t,e,i){var r=new Int32Array(t.buffer,t.byteOffset,t.byteLength>>2),n=new g(Array.prototype.slice.call(e)),s=new Uint8Array(t.byteLength),a=new Int32Array(s.buffer),o=void 0,u=void 0,l=void 0,c=void 0,h=void 0,d=void 0,p=void 0,f=void 0,m=void 0;for(o=i[0],u=i[1],l=i[2],c=i[3],m=0;m<r.length;m+=4)h=y(r[m]),d=y(r[m+1]),p=y(r[m+2]),f=y(r[m+3]),n.decrypt(h,d,p,f,a,m),a[m]=y(a[m]^o),a[m+1]=y(a[m+1]^u),a[m+2]=y(a[m+2]^l),a[m+3]=y(a[m+3]^c),o=h,u=d,l=p,c=f;return s}(e,i,r);n.set(t,e.byteOffset)}},r(u,null,[{key:"STEP",get:function(){return 32e3}}]),u}(),new function(t){t.onmessage=function(t){var n=t.data,e=new Uint8Array(n.encrypted.bytes,n.encrypted.byteOffset,n.encrypted.byteLength),i=new Uint32Array(n.key.bytes,n.key.byteOffset,n.key.byteLength/4),r=new Uint32Array(n.iv.bytes,n.iv.byteOffset,n.iv.byteLength/4);new o(e,i,r,function(t,e){var i,r;s.postMessage((i={source:n.source,decrypted:e},r={},Object.keys(i).forEach(function(t){var e=i[t];ArrayBuffer.isView(e)?r[t]={bytes:e.buffer,byteOffset:e.byteOffset,byteLength:e.byteLength}:r[t]=e}),r),[e.buffer])})}}(u)}),El=function(t,e){t.abort(),t.pause(),e&&e.activePlaylistLoader&&(e.activePlaylistLoader.pause(),e.activePlaylistLoader=null)},wl=function(t,e){(e.activePlaylistLoader=t).load()},Al={AUDIO:function(u,l){return function(){var t=l.segmentLoaders[u],e=l.mediaTypes[u],i=l.blacklistCurrentPlaylist;El(t,e);var r=e.activeTrack(),n=e.activeGroup(),s=(n.filter(function(t){return t.default})[0]||n[0]).id,a=e.tracks[s];if(r!==a){for(var o in As.log.warn("Problem encountered loading the alternate audio track.Switching back to default."),e.tracks)e.tracks[o].enabled=e.tracks[o]===a;e.onTrackChanged()}else i({message:"Problem encountered loading the default audio track."})}},SUBTITLES:function(r,n){return function(){var t=n.segmentLoaders[r],e=n.mediaTypes[r];As.log.warn("Problem encountered loading the subtitle track.Disabling subtitle track."),El(t,e);var i=e.activeTrack();i&&(i.mode="disabled"),e.onTrackChanged()}}},Ll={AUDIO:function(t,e,i){if(e){var r=i.tech,n=i.requestOptions,s=i.segmentLoaders[t];e.on("loadedmetadata",function(){var t=e.media();s.playlist(t,n),(!r.paused()||t.endList&&"none"!==r.preload())&&s.load()}),e.on("loadedplaylist",function(){s.playlist(e.media(),n),r.paused()||s.load()}),e.on("error",Al[t](t,i))}},SUBTITLES:function(t,e,i){var r=i.tech,n=i.requestOptions,s=i.segmentLoaders[t],a=i.mediaTypes[t];e.on("loadedmetadata",function(){var t=e.media();s.playlist(t,n),s.track(a.activeTrack()),(!r.paused()||t.endList&&"none"!==r.preload())&&s.load()}),e.on("loadedplaylist",function(){s.playlist(e.media(),n),r.paused()||s.load()}),e.on("error",Al[t](t,i))}},Pl=function(e,i){return function(t){return t.attributes[e]===i}},Ol=function(e){return function(t){return t.resolvedUri===e}},xl={AUDIO:function(t,e){var i,r,n=e.hls,s=e.sourceType,a=e.segmentLoaders[t],o=e.requestOptions.withCredentials,u=e.master,l=u.mediaGroups,c=u.playlists,h=e.mediaTypes[t],d=h.groups,p=h.tracks,f=e.masterPlaylistLoader;for(var m in l[t]&&0!==Object.keys(l[t]).length||(l[t]={main:{default:{default:!0}}}),l[t]){d[m]||(d[m]=[]);var g=c.filter(Pl(t,m));for(var y in l[t][m]){var v=l[t][m][y];g.filter(Ol(v.resolvedUri)).length&&delete v.resolvedUri;var _=void 0;if(_=v.resolvedUri?new Vo(v.resolvedUri,n,o):v.playlists&&"dash"===s?new Xu(v.playlists[0],n,o,f):null,v=As.mergeOptions({id:y,playlistLoader:_},v),Ll[t](t,v.playlistLoader,e),d[m].push(v),"undefined"==typeof p[y]){var b=new As.AudioTrack({id:y,kind:(i=v,r=void 0,r=i.default?"main":"alternative",i.characteristics&&0<=i.characteristics.indexOf("public.accessibility.describes-video")&&(r="main-desc"),r),enabled:!1,language:v.language,default:v.default,label:y});p[y]=b}}}a.on("error",Al[t](t,e))},SUBTITLES:function(t,e){var i=e.tech,r=e.hls,n=e.sourceType,s=e.segmentLoaders[t],a=e.requestOptions.withCredentials,o=e.master.mediaGroups,u=e.mediaTypes[t],l=u.groups,c=u.tracks,h=e.masterPlaylistLoader;for(var d in o[t])for(var p in l[d]||(l[d]=[]),o[t][d])if(!o[t][d][p].forced){var f=o[t][d][p],m=void 0;if("hls"===n?m=new Vo(f.resolvedUri,r,a):"dash"===n&&(m=new Xu(f.playlists[0],r,a,h)),f=As.mergeOptions({id:p,playlistLoader:m},f),Ll[t](t,f.playlistLoader,e),l[d].push(f),"undefined"==typeof c[p]){var g=i.addRemoteTextTrack({id:p,kind:"subtitles",enabled:!1,language:f.language,label:p},!1).track;c[p]=g}}s.on("error",Al[t](t,e))},"CLOSED-CAPTIONS":function(t,e){var i=e.tech,r=e.master.mediaGroups,n=e.mediaTypes[t],s=n.groups,a=n.tracks;for(var o in r[t])for(var u in s[o]||(s[o]=[]),r[t][o]){var l=r[t][o][u];if(l.instreamId.match(/CC\d/)&&(s[o].push(As.mergeOptions({id:u},l)),"undefined"==typeof a[u])){var c=i.addRemoteTextTrack({id:l.instreamId,kind:"captions",enabled:!1,language:l.language,label:u},!1).track;a[u]=c}}}},Il={AUDIO:function(i,r){return function(){var t=r.mediaTypes[i].tracks;for(var e in t)if(t[e].enabled)return t[e];return null}},SUBTITLES:function(i,r){return function(){var t=r.mediaTypes[i].tracks;for(var e in t)if("showing"===t[e].mode)return t[e];return null}}},Dl=function(e){["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(function(t){xl[t](t,e)});var i=e.mediaTypes,t=e.masterPlaylistLoader,r=e.tech,n=e.hls;["AUDIO","SUBTITLES"].forEach(function(t){var s,a,o,u,l,c;i[t].activeGroup=(s=t,a=e,function(e){var t=a.masterPlaylistLoader,i=a.mediaTypes[s].groups,r=t.media();if(!r)return null;var n=null;return r.attributes[s]&&(n=i[r.attributes[s]]),n=n||i.main,"undefined"==typeof e?n:null===e?null:n.filter(function(t){return t.id===e.id})[0]||null}),i[t].activeTrack=Il[t](t,e),i[t].onGroupChanged=(o=t,u=e,function(){var t=u.segmentLoaders,e=t[o],i=t.main,r=u.mediaTypes[o],n=r.activeTrack(),s=r.activeGroup(n),a=r.activePlaylistLoader;El(e,r),s&&(s.playlistLoader?(e.resyncLoader(),wl(s.playlistLoader,r)):a&&i.resetEverything())}),i[t].onTrackChanged=(l=t,c=e,function(){var t=c.segmentLoaders,e=t[l],i=t.main,r=c.mediaTypes[l],n=r.activeTrack(),s=r.activeGroup(n),a=r.activePlaylistLoader;El(e,r),s&&(s.playlistLoader?(a!==s.playlistLoader&&(e.track&&e.track(n),e.resetEverything()),wl(s.playlistLoader,r)):i.resetEverything())})});var s=i.AUDIO.activeGroup(),a=(s.filter(function(t){return t.default})[0]||s[0]).id;i.AUDIO.tracks[a].enabled=!0,i.AUDIO.onTrackChanged(),t.on("mediachange",function(){["AUDIO","SUBTITLES"].forEach(function(t){return i[t].onGroupChanged()})});var o=function(){i.AUDIO.onTrackChanged(),r.trigger({type:"usage",name:"hls-audio-change"})};for(var u in r.audioTracks().addEventListener("change",o),r.remoteTextTracks().addEventListener("change",i.SUBTITLES.onTrackChanged),n.on("dispose",function(){r.audioTracks().removeEventListener("change",o),r.remoteTextTracks().removeEventListener("change",i.SUBTITLES.onTrackChanged)}),r.clearTracks("audio"),i.AUDIO.tracks)r.audioTracks().addTrack(i.AUDIO.tracks[u])},Rl=function(){var e={};return["AUDIO","SUBTITLES","CLOSED-CAPTIONS"].forEach(function(t){e[t]={groups:{},tracks:{},activePlaylistLoader:null,activeGroup:$u,activeTrack:$u,onGroupChanged:$u,onTrackChanged:$u}}),e},Ml=void 0,Ul=["mediaRequests","mediaRequestsAborted","mediaRequestsTimedout","mediaRequestsErrored","mediaTransferDuration","mediaBytesTransferred"],Nl=function(t){return this.audioSegmentLoader_[t]+this.mainSegmentLoader_[t]},Bl=function(d){function p(t){y(this,p);var e=b(this,d.call(this)),i=t.url,r=t.withCredentials,n=t.tech,s=t.bandwidth,a=t.externHls,o=t.useCueTags,u=t.blacklistDuration,l=t.enableLowInitialPlaylist,c=t.sourceType;if(!i)throw new Error("A non-empty playlist URL is required");Ml=a,e.withCredentials=r,e.tech_=n,e.hls_=n.hls,e.sourceType_=c,e.useCueTags_=o,e.blacklistDuration=u,e.enableLowInitialPlaylist=l,e.useCueTags_&&(e.cueTagsTrack_=e.tech_.addTextTrack("metadata","ad-cues"),e.cueTagsTrack_.inBandMetadataTrackDispatchType=""),e.requestOptions_={withCredentials:e.withCredentials,timeout:null},e.mediaTypes_=Rl(),e.mediaSource=new As.MediaSource,e.mediaSource.addEventListener("sourceopen",e.handleSourceOpen_.bind(e)),e.seekable_=As.createTimeRanges(),e.hasPlayed_=function(){return!1},e.syncController_=new kl(t),e.segmentMetadataTrack_=n.addRemoteTextTrack({kind:"metadata",label:"segment-metadata"},!1).track,e.decrypter_=new Cl;var h={hls:e.hls_,mediaSource:e.mediaSource,currentTime:e.tech_.currentTime.bind(e.tech_),seekable:function(){return e.seekable()},seeking:function(){return e.tech_.seeking()},duration:function(){return e.mediaSource.duration},hasPlayed:function(){return e.hasPlayed_()},goalBufferLength:function(){return e.goalBufferLength()},bandwidth:s,syncController:e.syncController_,decrypter:e.decrypter_,sourceType:e.sourceType_};return e.masterPlaylistLoader_="dash"===e.sourceType_?new Xu(i,e.hls_,e.withCredentials):new Vo(i,e.hls_,e.withCredentials),e.setupMasterPlaylistLoaderListeners_(),e.mainSegmentLoader_=new gl(As.mergeOptions(h,{segmentMetadataTrack:e.segmentMetadataTrack_,loaderType:"main"}),t),e.audioSegmentLoader_=new gl(As.mergeOptions(h,{loaderType:"audio"}),t),e.subtitleSegmentLoader_=new _l(As.mergeOptions(h,{loaderType:"vtt"}),t),e.setupSegmentLoaderListeners_(),Ul.forEach(function(t){e[t+"_"]=Nl.bind(e,t)}),e.logger_=Yu("MPC"),e.masterPlaylistLoader_.load(),e}return _(p,d),p.prototype.setupMasterPlaylistLoaderListeners_=function(){var r=this;this.masterPlaylistLoader_.on("loadedmetadata",function(){var t=r.masterPlaylistLoader_.media(),e=1.5*r.masterPlaylistLoader_.targetDuration*1e3;ru(r.masterPlaylistLoader_.master,r.masterPlaylistLoader_.media())?r.requestOptions_.timeout=0:r.requestOptions_.timeout=e,t.endList&&"none"!==r.tech_.preload()&&(r.mainSegmentLoader_.playlist(t,r.requestOptions_),r.mainSegmentLoader_.load()),Dl({sourceType:r.sourceType_,segmentLoaders:{AUDIO:r.audioSegmentLoader_,SUBTITLES:r.subtitleSegmentLoader_,main:r.mainSegmentLoader_},tech:r.tech_,requestOptions:r.requestOptions_,masterPlaylistLoader:r.masterPlaylistLoader_,hls:r.hls_,master:r.master(),mediaTypes:r.mediaTypes_,blacklistCurrentPlaylist:r.blacklistCurrentPlaylist.bind(r)}),r.triggerPresenceUsage_(r.master(),t);try{r.setupSourceBuffers_()}catch(t){return As.log.warn("Failed to create SourceBuffers",t),r.mediaSource.endOfStream("decode")}r.setupFirstPlay(),r.trigger("selectedinitialmedia")}),this.masterPlaylistLoader_.on("loadedplaylist",function(){var t=r.masterPlaylistLoader_.media();if(!t){r.excludeUnsupportedVariants_();var e=void 0;return r.enableLowInitialPlaylist&&(e=r.selectInitialPlaylist()),e||(e=r.selectPlaylist()),r.initialMedia_=e,void r.masterPlaylistLoader_.media(r.initialMedia_)}if(r.useCueTags_&&r.updateAdCues_(t),r.mainSegmentLoader_.playlist(t,r.requestOptions_),r.updateDuration(),r.tech_.paused()||r.mainSegmentLoader_.load(),!t.endList){var i=function(){var t=r.seekable();0!==t.length&&r.mediaSource.addSeekableRange_(t.start(0),t.end(0))};if(r.duration()!==1/0){r.tech_.one("durationchange",function t(){r.duration()===1/0?i():r.tech_.one("durationchange",t)})}else i()}}),this.masterPlaylistLoader_.on("error",function(){r.blacklistCurrentPlaylist(r.masterPlaylistLoader_.error)}),this.masterPlaylistLoader_.on("mediachanging",function(){r.mainSegmentLoader_.abort(),r.mainSegmentLoader_.pause()}),this.masterPlaylistLoader_.on("mediachange",function(){var t=r.masterPlaylistLoader_.media(),e=1.5*r.masterPlaylistLoader_.targetDuration*1e3;ru(r.masterPlaylistLoader_.master,r.masterPlaylistLoader_.media())?r.requestOptions_.timeout=0:r.requestOptions_.timeout=e,r.mainSegmentLoader_.playlist(t,r.requestOptions_),r.mainSegmentLoader_.load(),r.tech_.trigger({type:"mediachange",bubbles:!0})}),this.masterPlaylistLoader_.on("playlistunchanged",function(){var t=r.masterPlaylistLoader_.media();r.stuckAtPlaylistEnd_(t)&&(r.blacklistCurrentPlaylist({message:"Playlist no longer updating."}),r.tech_.trigger("playliststuck"))}),this.masterPlaylistLoader_.on("renditiondisabled",function(){r.tech_.trigger({type:"usage",name:"hls-rendition-disabled"})}),this.masterPlaylistLoader_.on("renditionenabled",function(){r.tech_.trigger({type:"usage",name:"hls-rendition-enabled"})})},p.prototype.triggerPresenceUsage_=function(t,e){var i=t.mediaGroups||{},r=!0,n=Object.keys(i.AUDIO);for(var s in i.AUDIO)for(var a in i.AUDIO[s]){i.AUDIO[s][a].uri||(r=!1)}r&&this.tech_.trigger({type:"usage",name:"hls-demuxed"}),Object.keys(i.SUBTITLES).length&&this.tech_.trigger({type:"usage",name:"hls-webvtt"}),Ml.Playlist.isAes(e)&&this.tech_.trigger({type:"usage",name:"hls-aes"}),Ml.Playlist.isFmp4(e)&&this.tech_.trigger({type:"usage",name:"hls-fmp4"}),n.length&&1<Object.keys(i.AUDIO[n[0]]).length&&this.tech_.trigger({type:"usage",name:"hls-alternate-audio"}),this.useCueTags_&&this.tech_.trigger({type:"usage",name:"hls-playlist-cue-tags"})},p.prototype.setupSegmentLoaderListeners_=function(){var s=this;this.mainSegmentLoader_.on("bandwidthupdate",function(){var t=s.selectPlaylist(),e=s.masterPlaylistLoader_.media(),i=s.tech_.buffered(),r=i.length?i.end(i.length-1)-s.tech_.currentTime():0,n=s.bufferLowWaterLine();(!e.endList||s.duration()<Qu.MAX_BUFFER_LOW_WATER_LINE||t.attributes.BANDWIDTH<e.attributes.BANDWIDTH||n<=r)&&s.masterPlaylistLoader_.media(t),s.tech_.trigger("bandwidthupdate")}),this.mainSegmentLoader_.on("progress",function(){s.trigger("progress")}),this.mainSegmentLoader_.on("error",function(){s.blacklistCurrentPlaylist(s.mainSegmentLoader_.error())}),this.mainSegmentLoader_.on("syncinfoupdate",function(){s.onSyncInfoUpdate_()}),this.mainSegmentLoader_.on("timestampoffset",function(){s.tech_.trigger({type:"usage",name:"hls-timestamp-offset"})}),this.audioSegmentLoader_.on("syncinfoupdate",function(){s.onSyncInfoUpdate_()}),this.mainSegmentLoader_.on("ended",function(){s.onEndOfStream()}),this.mainSegmentLoader_.on("earlyabort",function(){s.blacklistCurrentPlaylist({message:"Aborted early because there isn't enough bandwidth to complete the request without rebuffering."},120)}),this.mainSegmentLoader_.on("reseteverything",function(){s.tech_.trigger("hls-reset")}),this.mainSegmentLoader_.on("segmenttimemapping",function(t){s.tech_.trigger({type:"hls-segment-time-mapping",mapping:t.mapping})}),this.audioSegmentLoader_.on("ended",function(){s.onEndOfStream()})},p.prototype.mediaSecondsLoaded_=function(){return Math.max(this.audioSegmentLoader_.mediaSecondsLoaded+this.mainSegmentLoader_.mediaSecondsLoaded)},p.prototype.load=function(){this.mainSegmentLoader_.load(),this.mediaTypes_.AUDIO.activePlaylistLoader&&this.audioSegmentLoader_.load(),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&this.subtitleSegmentLoader_.load()},p.prototype.fastQualityChange_=function(){var t=this.selectPlaylist();t!==this.masterPlaylistLoader_.media()&&(this.masterPlaylistLoader_.media(t),this.mainSegmentLoader_.resetLoader())},p.prototype.play=function(){if(!this.setupFirstPlay()){this.tech_.ended()&&this.tech_.setCurrentTime(0),this.hasPlayed_()&&this.load();var t=this.tech_.seekable();return this.tech_.duration()===1/0&&this.tech_.currentTime()<t.start(0)?this.tech_.setCurrentTime(t.end(t.length-1)):void 0}},p.prototype.setupFirstPlay=function(){var t=this,e=this.masterPlaylistLoader_.media();if(!e||this.tech_.paused()||this.hasPlayed_())return!1;if(!e.endList){var i=this.seekable();if(!i.length)return!1;if(As.browser.IE_VERSION&&0===this.tech_.readyState())return this.tech_.one("loadedmetadata",function(){t.trigger("firstplay"),t.tech_.setCurrentTime(i.end(0)),t.hasPlayed_=function(){return!0}}),!1;this.trigger("firstplay"),this.tech_.setCurrentTime(i.end(0))}return this.hasPlayed_=function(){return!0},this.load(),!0},p.prototype.handleSourceOpen_=function(){try{this.setupSourceBuffers_()}catch(t){return As.log.warn("Failed to create Source Buffers",t),this.mediaSource.endOfStream("decode")}if(this.tech_.autoplay()){var t=this.tech_.play();"undefined"!=typeof t&&"function"==typeof t.then&&t.then(null,function(t){})}this.trigger("sourceopen")},p.prototype.onEndOfStream=function(){var t=this.mainSegmentLoader_.ended_;this.mediaTypes_.AUDIO.activePlaylistLoader&&(t=!this.mainSegmentLoader_.startingMedia_||this.mainSegmentLoader_.startingMedia_.containsVideo?t&&this.audioSegmentLoader_.ended_:this.audioSegmentLoader_.ended_),t&&this.mediaSource.endOfStream()},p.prototype.stuckAtPlaylistEnd_=function(t){if(!this.seekable().length)return!1;var e=this.syncController_.getExpiredTime(t,this.mediaSource.duration);if(null===e)return!1;var i=Ml.Playlist.playlistEnd(t,e),r=this.tech_.currentTime(),n=this.tech_.buffered();if(!n.length)return i-r<=.1;var s=n.end(n.length-1);return s-r<=.1&&i-s<=.1},p.prototype.blacklistCurrentPlaylist=function(){var t,e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{},i=arguments[1],r=void 0;if(r=e.playlist||this.masterPlaylistLoader_.media(),i=i||e.blacklistDuration||this.blacklistDuration,!r){this.error=e;try{return this.mediaSource.endOfStream("network")}catch(t){return this.trigger("error")}}var n=1===this.masterPlaylistLoader_.master.playlists.filter(eu).length;return n?(As.log.warn("Problem encountered with the current HLS playlist. Trying again since it is the final playlist."),this.tech_.trigger("retryplaylist"),this.masterPlaylistLoader_.load(n)):(r.excludeUntil=Date.now()+1e3*i,this.tech_.trigger("blacklistplaylist"),this.tech_.trigger({type:"usage",name:"hls-rendition-blacklisted"}),t=this.selectPlaylist(),As.log.warn("Problem encountered with the current HLS playlist."+(e.message?" "+e.message:"")+" Switching to another playlist."),this.masterPlaylistLoader_.media(t))},p.prototype.pauseLoading=function(){this.mainSegmentLoader_.pause(),this.mediaTypes_.AUDIO.activePlaylistLoader&&this.audioSegmentLoader_.pause(),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&this.subtitleSegmentLoader_.pause()},p.prototype.setCurrentTime=function(t){var e=gu(this.tech_.buffered(),t);return this.masterPlaylistLoader_&&this.masterPlaylistLoader_.media()&&this.masterPlaylistLoader_.media().segments?e&&e.length?t:(this.mainSegmentLoader_.resetEverything(),this.mainSegmentLoader_.abort(),this.mediaTypes_.AUDIO.activePlaylistLoader&&(this.audioSegmentLoader_.resetEverything(),this.audioSegmentLoader_.abort()),this.mediaTypes_.SUBTITLES.activePlaylistLoader&&(this.subtitleSegmentLoader_.resetEverything(),this.subtitleSegmentLoader_.abort()),void this.load()):0},p.prototype.duration=function(){return this.masterPlaylistLoader_?this.mediaSource?this.mediaSource.duration:Ml.Playlist.duration(this.masterPlaylistLoader_.media()):0},p.prototype.seekable=function(){return this.seekable_},p.prototype.onSyncInfoUpdate_=function(){var t=void 0,e=void 0;if(this.masterPlaylistLoader_){var i=this.masterPlaylistLoader_.media();if(i){var r=this.syncController_.getExpiredTime(i,this.mediaSource.duration);if(null!==r&&0!==(t=Ml.Playlist.seekable(i,r)).length){if(this.mediaTypes_.AUDIO.activePlaylistLoader){if(i=this.mediaTypes_.AUDIO.activePlaylistLoader.media(),null===(r=this.syncController_.getExpiredTime(i,this.mediaSource.duration)))return;if(0===(e=Ml.Playlist.seekable(i,r)).length)return}e?e.start(0)>t.end(0)||t.start(0)>e.end(0)?this.seekable_=t:this.seekable_=As.createTimeRanges([[e.start(0)>t.start(0)?e.start(0):t.start(0),e.end(0)<t.end(0)?e.end(0):t.end(0)]]):this.seekable_=t,this.logger_("seekable updated ["+vu(this.seekable_)+"]"),this.tech_.trigger("seekablechanged")}}}},p.prototype.updateDuration=function(){var e=this,t=this.mediaSource.duration,i=Ml.Playlist.duration(this.masterPlaylistLoader_.media()),r=this.tech_.buffered(),n=function t(){e.mediaSource.duration=i,e.tech_.trigger("durationchange"),e.mediaSource.removeEventListener("sourceopen",t)};0<r.length&&(i=Math.max(i,r.end(r.length-1))),t!==i&&("open"!==this.mediaSource.readyState?this.mediaSource.addEventListener("sourceopen",n):n())},p.prototype.dispose=function(){var r=this;this.decrypter_.terminate(),this.masterPlaylistLoader_.dispose(),this.mainSegmentLoader_.dispose(),["AUDIO","SUBTITLES"].forEach(function(t){var e=r.mediaTypes_[t].groups;for(var i in e)e[i].forEach(function(t){t.playlistLoader&&t.playlistLoader.dispose()})}),this.audioSegmentLoader_.dispose(),this.subtitleSegmentLoader_.dispose()},p.prototype.master=function(){return this.masterPlaylistLoader_.master},p.prototype.media=function(){return this.masterPlaylistLoader_.media()||this.initialMedia_},p.prototype.setupSourceBuffers_=function(){var t,e=this.masterPlaylistLoader_.media();if(e&&"open"===this.mediaSource.readyState){if((t=cl(this.masterPlaylistLoader_.master,e)).length<1)return this.error="No compatible SourceBuffer configuration for the variant stream:"+e.resolvedUri,this.mediaSource.endOfStream("decode");this.configureLoaderMimeTypes_(t),this.excludeIncompatibleVariants_(e)}},p.prototype.configureLoaderMimeTypes_=function(t){var e=1<t.length&&-1===t[0].indexOf(",")&&t[0]!==t[1]?new As.EventTarget:null;this.mainSegmentLoader_.mimeType(t[0],e),t[1]&&this.audioSegmentLoader_.mimeType(t[1],e)},p.prototype.excludeUnsupportedVariants_=function(){this.master().playlists.forEach(function(t){t.attributes.CODECS&&g.MediaSource&&g.MediaSource.isTypeSupported&&!g.MediaSource.isTypeSupported('video/mp4; codecs="'+t.attributes.CODECS.replace(/avc1\.(\d+)\.(\d+)/i,function(t){return Nu([t])[0]})+'"')&&(t.excludeUntil=1/0)})},p.prototype.excludeIncompatibleVariants_=function(t){var i=2,r=null,e=void 0;t.attributes.CODECS&&(e=ul(t.attributes.CODECS),r=e.videoCodec,i=e.codecCount),this.master().playlists.forEach(function(t){var e={codecCount:2,videoCodec:null};t.attributes.CODECS&&(e=ul(t.attributes.CODECS)),e.codecCount!==i&&(t.excludeUntil=1/0),e.videoCodec!==r&&(t.excludeUntil=1/0)})},p.prototype.updateAdCues_=function(t){var e=0,i=this.seekable();i.length&&(e=i.start(0)),function(t,e){var i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:0;if(t.segments)for(var r=i,n=void 0,s=0;s<t.segments.length;s++){var a=t.segments[s];if(n||(n=bl(e,r+a.duration/2)),n){if("cueIn"in a){n.endTime=r,n.adEndTime=r,r+=a.duration,n=null;continue}if(r<n.endTime){r+=a.duration;continue}n.endTime+=a.duration}else if("cueOut"in a&&((n=new g.VTTCue(r,r+a.duration,a.cueOut)).adStartTime=r,n.adEndTime=r+parseFloat(a.cueOut),e.addCue(n)),"cueOutCont"in a){var o,u,l=a.cueOutCont.split("/").map(parseFloat);o=l[0],u=l[1],(n=new g.VTTCue(r,r+a.duration,"")).adStartTime=r-o,n.adEndTime=n.adStartTime+u,e.addCue(n)}r+=a.duration}}(t,this.cueTagsTrack_,e)},p.prototype.goalBufferLength=function(){var t=this.tech_.currentTime(),e=Qu.GOAL_BUFFER_LENGTH,i=Qu.GOAL_BUFFER_LENGTH_RATE,r=Math.max(e,Qu.MAX_GOAL_BUFFER_LENGTH);return Math.min(e+t*i,r)},p.prototype.bufferLowWaterLine=function(){var t=this.tech_.currentTime(),e=Qu.BUFFER_LOW_WATER_LINE,i=Qu.BUFFER_LOW_WATER_LINE_RATE,r=Math.max(e,Qu.MAX_BUFFER_LOW_WATER_LINE);return Math.min(e+t*i,r)},p}(As.EventTarget),jl=function t(e,i,r){y(this,t);var n,s,a,o=e.masterPlaylistController_.fastQualityChange_.bind(e.masterPlaylistController_);if(i.attributes.RESOLUTION){var u=i.attributes.RESOLUTION;this.width=u.width,this.height=u.height}this.bandwidth=i.attributes.BANDWIDTH,this.id=r,this.enabled=(n=e.playlists,s=i.uri,a=o,function(t){var e=n.master.playlists[s],i=tu(e),r=eu(e);return"undefined"==typeof t?r:(t?delete e.disabled:e.disabled=!0,t===r||i||(a(),t?n.trigger("renditionenabled"):n.trigger("renditiondisabled")),t)})},Fl=["seeking","seeked","pause","playing","error"],Hl=function(){function a(t){var e=this;y(this,a),this.tech_=t.tech,this.seekable=t.seekable,this.consecutiveUpdates=0,this.lastRecordedTime=null,this.timer_=null,this.checkCurrentTimeTimeout_=null,this.logger_=Yu("PlaybackWatcher"),this.logger_("initialize");var i=function(){return e.monitorCurrentTime_()},r=function(){return e.techWaiting_()},n=function(){return e.cancelTimer_()},s=function(){return e.fixesBadSeeks_()};this.tech_.on("seekablechanged",s),this.tech_.on("waiting",r),this.tech_.on(Fl,n),this.tech_.on("canplay",i),this.dispose=function(){e.logger_("dispose"),e.tech_.off("seekablechanged",s),e.tech_.off("waiting",r),e.tech_.off(Fl,n),e.tech_.off("canplay",i),e.checkCurrentTimeTimeout_&&g.clearTimeout(e.checkCurrentTimeTimeout_),e.cancelTimer_()}}return a.prototype.monitorCurrentTime_=function(){this.checkCurrentTime_(),this.checkCurrentTimeTimeout_&&g.clearTimeout(this.checkCurrentTimeTimeout_),this.checkCurrentTimeTimeout_=g.setTimeout(this.monitorCurrentTime_.bind(this),250)},a.prototype.checkCurrentTime_=function(){if(this.tech_.seeking()&&this.fixesBadSeeks_())return this.consecutiveUpdates=0,void(this.lastRecordedTime=this.tech_.currentTime());if(!this.tech_.paused()&&!this.tech_.seeking()){var t=this.tech_.currentTime(),e=this.tech_.buffered();if(this.lastRecordedTime===t&&(!e.length||t+.1>=e.end(e.length-1)))return this.techWaiting_();5<=this.consecutiveUpdates&&t===this.lastRecordedTime?(this.consecutiveUpdates++,this.waiting_()):t===this.lastRecordedTime?this.consecutiveUpdates++:(this.consecutiveUpdates=0,this.lastRecordedTime=t)}},a.prototype.cancelTimer_=function(){this.consecutiveUpdates=0,this.timer_&&(this.logger_("cancelTimer_"),clearTimeout(this.timer_)),this.timer_=null},a.prototype.fixesBadSeeks_=function(){var t=this.tech_.seeking(),e=this.seekable(),i=this.tech_.currentTime(),r=void 0;t&&this.afterSeekableWindow_(e,i)&&(r=e.end(e.length-1));t&&this.beforeSeekableWindow_(e,i)&&(r=e.start(0)+.1);return"undefined"!=typeof r&&(this.logger_("Trying to seek outside of seekable at time "+i+" with seekable range "+vu(e)+". Seeking to "+r+"."),this.tech_.setCurrentTime(r),!0)},a.prototype.waiting_=function(){if(!this.techWaiting_()){var t=this.tech_.currentTime(),e=this.tech_.buffered(),i=gu(e,t);return i.length&&t+3<=i.end(0)?(this.cancelTimer_(),this.tech_.setCurrentTime(t),this.logger_("Stopped at "+t+" while inside a buffered region ["+i.start(0)+" -> "+i.end(0)+"]. Attempting to resume playback by seeking to the current time."),void this.tech_.trigger({type:"usage",name:"hls-unknown-waiting"})):void 0}},a.prototype.techWaiting_=function(){var t=this.seekable(),e=this.tech_.currentTime();if(this.tech_.seeking()&&this.fixesBadSeeks_())return!0;if(this.tech_.seeking()||null!==this.timer_)return!0;if(this.beforeSeekableWindow_(t,e)){var i=t.end(t.length-1);return this.logger_("Fell out of live window at time "+e+". Seeking to live point (seekable end) "+i),this.cancelTimer_(),this.tech_.setCurrentTime(i),this.tech_.trigger({type:"usage",name:"hls-live-resync"}),!0}var r=this.tech_.buffered(),n=yu(r,e);if(this.videoUnderflow_(n,r,e))return this.cancelTimer_(),this.tech_.setCurrentTime(e),this.tech_.trigger({type:"usage",name:"hls-video-underflow"}),!0;if(0<n.length){var s=n.start(0)-e;return this.logger_("Stopped at "+e+", setting timer for "+s+", seeking to "+n.start(0)),this.timer_=setTimeout(this.skipTheGap_.bind(this),1e3*s,e),!0}return!1},a.prototype.afterSeekableWindow_=function(t,e){return!!t.length&&e>t.end(t.length-1)+.1},a.prototype.beforeSeekableWindow_=function(t,e){return!!(t.length&&0<t.start(0)&&e<t.start(0)-.1)},a.prototype.videoUnderflow_=function(t,e,i){if(0===t.length){var r=this.gapFromVideoUnderflow_(e,i);if(r)return this.logger_("Encountered a gap in video from "+r.start+" to "+r.end+". Seeking to current time "+i),!0}return!1},a.prototype.skipTheGap_=function(t){var e=this.tech_.buffered(),i=this.tech_.currentTime(),r=yu(e,i);this.cancelTimer_(),0!==r.length&&i===t&&(this.logger_("skipTheGap_:","currentTime:",i,"scheduled currentTime:",t,"nextRange start:",r.start(0)),this.tech_.setCurrentTime(r.start(0)+fu),this.tech_.trigger({type:"usage",name:"hls-gap-skip"}))},a.prototype.gapFromVideoUnderflow_=function(t,e){for(var i=function(t){if(t.length<2)return As.createTimeRanges();for(var e=[],i=1;i<t.length;i++){var r=t.end(i-1),n=t.start(i);e.push([r,n])}return As.createTimeRanges(e)}(t),r=0;r<i.length;r++){var n=i.start(r),s=i.end(r);if(e-n<4&&2<e-n)return{start:n,end:s}}return null},a}(),Vl={errorInterval:30,getSource:function(t){return t(this.tech({IWillNotUseThisInPlugins:!0}).currentSource_)}},ql=function(t){!function e(i,t){var r=0,n=0,s=As.mergeOptions(Vl,t);i.ready(function(){i.trigger({type:"usage",name:"hls-error-reload-initialized"})});var a=function(){n&&i.currentTime(n)},o=function(t){null!=t&&(n=i.duration()!==1/0&&i.currentTime()||0,i.one("loadedmetadata",a),i.src(t),i.trigger({type:"usage",name:"hls-error-reload"}),i.play())},u=function(){if(Date.now()-r<1e3*s.errorInterval)i.trigger({type:"usage",name:"hls-error-reload-canceled"});else{if(s.getSource&&"function"==typeof s.getSource)return r=Date.now(),s.getSource.call(i,o);As.log.error("ERROR: reloadSourceOnError - The option getSource must be a function!")}},l=function t(){i.off("loadedmetadata",a),i.off("error",u),i.off("dispose",t)};i.on("error",u),i.on("dispose",l),i.reloadSourceOnError=function(t){l(),e(i,t)}}(this,t)},Wl={PlaylistLoader:Vo,Playlist:nu,Decrypter:Do,AsyncStream:Oo,decrypt:Io,utils:pu,STANDARD_PLAYLIST_SELECTOR:function(){return function(t,e,i,r){var n=t.playlists.map(function(t){var e,i;return e=t.attributes.RESOLUTION&&t.attributes.RESOLUTION.width,i=t.attributes.RESOLUTION&&t.attributes.RESOLUTION.height,{bandwidth:t.attributes.BANDWIDTH||g.Number.MAX_VALUE,width:e,height:i,playlist:t}});dl(n,function(t,e){return t.bandwidth-e.bandwidth});var s=(n=n.filter(function(t){return!nu.isIncompatible(t.playlist)})).filter(function(t){return nu.isEnabled(t.playlist)});s.length||(s=n.filter(function(t){return!nu.isDisabled(t.playlist)}));var a=s.filter(function(t){return t.bandwidth*Qu.BANDWIDTH_VARIANCE<e}),o=a[a.length-1],u=a.filter(function(t){return t.bandwidth===o.bandwidth})[0],l=a.filter(function(t){return t.width&&t.height});dl(l,function(t,e){return t.width-e.width});var c=l.filter(function(t){return t.width===i&&t.height===r});o=c[c.length-1];var h=c.filter(function(t){return t.bandwidth===o.bandwidth})[0],d=void 0,p=void 0,f=void 0;h||(p=(d=l.filter(function(t){return t.width>i||t.height>r})).filter(function(t){return t.width===d[0].width&&t.height===d[0].height}),o=p[p.length-1],f=p.filter(function(t){return t.bandwidth===o.bandwidth})[0]);var m=f||h||u||s[0]||n[0];return m?m.playlist:null}(this.playlists.master,this.systemBandwidth,parseInt(hl(this.tech_.el(),"width"),10),parseInt(hl(this.tech_.el(),"height"),10))},INITIAL_PLAYLIST_SELECTOR:function(){var t=this.playlists.master.playlists.filter(nu.isEnabled);return dl(t,function(t,e){return pl(t,e)}),t.filter(function(t){return ul(t.attributes.CODECS).videoCodec})[0]||null},comparePlaylistBandwidth:pl,comparePlaylistResolution:function(t,e){var i=void 0,r=void 0;return t.attributes.RESOLUTION&&t.attributes.RESOLUTION.width&&(i=t.attributes.RESOLUTION.width),i=i||g.Number.MAX_VALUE,e.attributes.RESOLUTION&&e.attributes.RESOLUTION.width&&(r=e.attributes.RESOLUTION.width),i===(r=r||g.Number.MAX_VALUE)&&t.attributes.BANDWIDTH&&e.attributes.BANDWIDTH?t.attributes.BANDWIDTH-e.attributes.BANDWIDTH:i-r},xhr:ou()};["GOAL_BUFFER_LENGTH","MAX_GOAL_BUFFER_LENGTH","GOAL_BUFFER_LENGTH_RATE","BUFFER_LOW_WATER_LINE","MAX_BUFFER_LOW_WATER_LINE","BUFFER_LOW_WATER_LINE_RATE","BANDWIDTH_VARIANCE"].forEach(function(e){Object.defineProperty(Wl,e,{get:function(){return As.log.warn("using Hls."+e+" is UNSAFE be sure you know what you are doing"),Qu[e]},set:function(t){As.log.warn("using Hls."+e+" is UNSAFE be sure you know what you are doing"),"number"!=typeof t||t<0?As.log.warn("value of Hls."+e+" must be greater than or equal to 0"):Qu[e]=t}})});var zl=function(t){if(/^(audio|video|application)\/(x-|vnd\.apple\.)?mpegurl/i.test(t))return"hls";return/^application\/dash\+xml/i.test(t)?"dash":null},Gl=function(t,e){for(var i=e.media(),r=-1,n=0;n<t.length;n++)if(t[n].id===i.uri){r=n;break}t.selectedIndex_=r,t.trigger({selectedIndex:r,type:"change"})};Wl.canPlaySource=function(){return As.log.warn("HLS is no longer a tech. Please remove it from your player's techOrder.")};var Xl=function(t){if("dash"===t.options_.sourceType){var e=As.players[t.tech_.options_.playerId];if(e.eme){var i=function(t,e,i){if(!t)return t;var r={};for(var n in t)r[n]={audioContentType:'audio/mp4; codecs="'+i.attributes.CODECS+'"',videoContentType:'video/mp4; codecs="'+e.attributes.CODECS+'"'},e.contentProtection&&e.contentProtection[n]&&e.contentProtection[n].pssh&&(r[n].pssh=e.contentProtection[n].pssh),"string"==typeof t[n]&&(r[n].url=t[n]);return As.mergeOptions(t,r)}(t.source_.keySystems,t.playlists.media(),t.masterPlaylistController_.mediaTypes_.AUDIO.activePlaylistLoader.media());i&&(e.currentSource().keySystems=i)}}};Wl.supportsNativeHls=function(){var e=p.createElement("video");if(!As.getTech("Html5").isSupported())return!1;return["application/vnd.apple.mpegurl","audio/mpegurl","audio/x-mpegurl","application/x-mpegurl","video/x-mpegurl","video/mpegurl","application/mpegurl"].some(function(t){return/maybe|probably/i.test(e.canPlayType(t))})}(),Wl.supportsNativeDash=!!As.getTech("Html5").isSupported()&&/maybe|probably/i.test(p.createElement("video").canPlayType("application/dash+xml")),Wl.supportsTypeNatively=function(t){return"hls"===t?Wl.supportsNativeHls:"dash"===t&&Wl.supportsNativeDash},Wl.isSupported=function(){return As.log.warn("HLS is no longer a tech. Please remove it from your player's techOrder.")};var Yl=function(s){function a(t,e,i){y(this,a);var r=b(this,s.call(this,e,i.hls));if(e.options_&&e.options_.playerId){var n=As(e.options_.playerId);n.hasOwnProperty("hls")||Object.defineProperty(n,"hls",{get:function(){return As.log.warn("player.hls is deprecated. Use player.tech_.hls instead."),e.trigger({type:"usage",name:"hls-player-access"}),r}}),n.vhs=r,n.dash=r}if(r.tech_=e,r.source_=t,r.stats={},r.ignoreNextSeekingEvent_=!1,r.setOptions_(),r.options_.overrideNative&&(e.featuresNativeVideoTracks||e.featuresNativeAudioTracks))throw new Error("Overriding native HLS requires emulated tracks. See https://git.io/vMpjB");return r.on(p,["fullscreenchange","webkitfullscreenchange","mozfullscreenchange","MSFullscreenChange"],function(t){var e=p.fullscreenElement||p.webkitFullscreenElement||p.mozFullScreenElement||p.msFullscreenElement;e&&e.contains(r.tech_.el())&&r.masterPlaylistController_.fastQualityChange_()}),r.on(r.tech_,"seeking",function(){this.ignoreNextSeekingEvent_?this.ignoreNextSeekingEvent_=!1:this.setCurrentTime(this.tech_.currentTime())}),r.on(r.tech_,"error",function(){this.masterPlaylistController_&&this.masterPlaylistController_.pauseLoading()}),r.on(r.tech_,"play",r.play),r}return _(a,s),a.prototype.setOptions_=function(){var e=this;this.options_.withCredentials=this.options_.withCredentials||!1,"number"!=typeof this.options_.blacklistDuration&&(this.options_.blacklistDuration=300),"number"!=typeof this.options_.bandwidth&&(this.options_.bandwidth=4194304),this.options_.enableLowInitialPlaylist=this.options_.enableLowInitialPlaylist&&4194304===this.options_.bandwidth,["withCredentials","bandwidth"].forEach(function(t){"undefined"!=typeof e.source_[t]&&(e.options_[t]=e.source_[t])}),this.bandwidth=this.options_.bandwidth},a.prototype.src=function(t,e){var r=this;t&&(this.setOptions_(),this.options_.url=this.source_.src,this.options_.tech=this.tech_,this.options_.externHls=Wl,this.options_.sourceType=zl(e),this.masterPlaylistController_=new Bl(this.options_),this.playbackWatcher_=new Hl(As.mergeOptions(this.options_,{seekable:function(){return r.seekable()}})),this.masterPlaylistController_.on("error",function(){As.players[r.tech_.options_.playerId].error(r.masterPlaylistController_.error)}),this.masterPlaylistController_.selectPlaylist=this.selectPlaylist?this.selectPlaylist.bind(this):Wl.STANDARD_PLAYLIST_SELECTOR.bind(this),this.masterPlaylistController_.selectInitialPlaylist=Wl.INITIAL_PLAYLIST_SELECTOR.bind(this),this.playlists=this.masterPlaylistController_.masterPlaylistLoader_,this.mediaSource=this.masterPlaylistController_.mediaSource,Object.defineProperties(this,{selectPlaylist:{get:function(){return this.masterPlaylistController_.selectPlaylist},set:function(t){this.masterPlaylistController_.selectPlaylist=t.bind(this)}},throughput:{get:function(){return this.masterPlaylistController_.mainSegmentLoader_.throughput.rate},set:function(t){this.masterPlaylistController_.mainSegmentLoader_.throughput.rate=t,this.masterPlaylistController_.mainSegmentLoader_.throughput.count=1}},bandwidth:{get:function(){return this.masterPlaylistController_.mainSegmentLoader_.bandwidth},set:function(t){this.masterPlaylistController_.mainSegmentLoader_.bandwidth=t,this.masterPlaylistController_.mainSegmentLoader_.throughput={rate:0,count:0}}},systemBandwidth:{get:function(){var t=1/(this.bandwidth||1),e=void 0;return e=0<this.throughput?1/this.throughput:0,Math.floor(1/(t+e))},set:function(){As.log.error('The "systemBandwidth" property is read-only')}}}),Object.defineProperties(this.stats,{bandwidth:{get:function(){return r.bandwidth||0},enumerable:!0},mediaRequests:{get:function(){return r.masterPlaylistController_.mediaRequests_()||0},enumerable:!0},mediaRequestsAborted:{get:function(){return r.masterPlaylistController_.mediaRequestsAborted_()||0},enumerable:!0},mediaRequestsTimedout:{get:function(){return r.masterPlaylistController_.mediaRequestsTimedout_()||0},enumerable:!0},mediaRequestsErrored:{get:function(){return r.masterPlaylistController_.mediaRequestsErrored_()||0},enumerable:!0},mediaTransferDuration:{get:function(){return r.masterPlaylistController_.mediaTransferDuration_()||0},enumerable:!0},mediaBytesTransferred:{get:function(){return r.masterPlaylistController_.mediaBytesTransferred_()||0},enumerable:!0},mediaSecondsLoaded:{get:function(){return r.masterPlaylistController_.mediaSecondsLoaded_()||0},enumerable:!0},buffered:{get:function(){return _u(r.tech_.buffered())},enumerable:!0},currentTime:{get:function(){return r.tech_.currentTime()},enumerable:!0},currentSource:{get:function(){return r.tech_.currentSource_},enumerable:!0},currentTech:{get:function(){return r.tech_.name_},enumerable:!0},duration:{get:function(){return r.tech_.duration()},enumerable:!0},master:{get:function(){return r.playlists.master},enumerable:!0},playerDimensions:{get:function(){return r.tech_.currentDimensions()},enumerable:!0},seekable:{get:function(){return _u(r.tech_.seekable())},enumerable:!0},timestamp:{get:function(){return Date.now()},enumerable:!0},videoPlaybackQuality:{get:function(){return r.tech_.getVideoPlaybackQuality()},enumerable:!0}}),this.tech_.one("canplay",this.masterPlaylistController_.setupFirstPlay.bind(this.masterPlaylistController_)),this.masterPlaylistController_.on("selectedinitialmedia",function(){var i,t;t=(i=r).playlists,i.representations=function(){return t.master.playlists.filter(function(t){return!tu(t)}).map(function(t,e){return new jl(i,t,t.uri)})},Xl(r)}),this.on(this.masterPlaylistController_,"progress",function(){this.tech_.trigger("progress")}),this.on(this.masterPlaylistController_,"firstplay",function(){this.ignoreNextSeekingEvent_=!0}),this.tech_.ready(function(){return r.setupQualityLevels_()}),this.tech_.el()&&this.tech_.src(As.URL.createObjectURL(this.masterPlaylistController_.mediaSource)))},a.prototype.setupQualityLevels_=function(){var i=this,t=As.players[this.tech_.options_.playerId];t&&t.qualityLevels&&(this.qualityLevels_=t.qualityLevels(),this.masterPlaylistController_.on("selectedinitialmedia",function(){var e,t;e=i.qualityLevels_,(t=i).representations().forEach(function(t){e.addQualityLevel(t)}),Gl(e,t.playlists)}),this.playlists.on("mediachange",function(){Gl(i.qualityLevels_,i.playlists)}))},a.prototype.play=function(){this.masterPlaylistController_.play()},a.prototype.setCurrentTime=function(t){this.masterPlaylistController_.setCurrentTime(t)},a.prototype.duration=function(){return this.masterPlaylistController_.duration()},a.prototype.seekable=function(){return this.masterPlaylistController_.seekable()},a.prototype.dispose=function(){this.playbackWatcher_&&this.playbackWatcher_.dispose(),this.masterPlaylistController_&&this.masterPlaylistController_.dispose(),this.qualityLevels_&&this.qualityLevels_.dispose(),s.prototype.dispose.call(this)},a}(As.getComponent("Component")),$l={name:"videojs-http-streaming",VERSION:"1.0.0",canHandleSource:function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=As.mergeOptions(As.options,e);return $l.canPlayType(t.type,i)},handleSource:function(t,e){var i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{},r=As.mergeOptions(As.options,i);return e.hls=new Yl(t,e,r),e.hls.xhr=ou(),e.hls.src(t.src,t.type),e.hls},canPlayType:function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=As.mergeOptions(As.options,e).hls.overrideNative,r=zl(t);return r&&(!Wl.supportsTypeNatively(r)||i)?"maybe":""}};return"undefined"!=typeof As.MediaSource&&"undefined"!=typeof As.URL||(As.MediaSource=qu,As.URL=Wu),qu.supportsNativeMediaSources()&&As.getTech("Html5").registerSourceHandler($l,0),As.HlsHandler=Yl,As.HlsSourceHandler=$l,As.Hls=Wl,As.use||As.registerComponent("Hls",Wl),As.options.hls=As.options.hls||{},As.registerPlugin?As.registerPlugin("reloadSourceOnError",ql):As.plugin("reloadSourceOnError",ql),As}); diff --git a/form/src/assets/play/bg.jpg b/form/src/assets/play/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..701c49c4c716d9e48412993f87f47d0fdcfbbe44 GIT binary patch literal 26413 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/play/btn_left.png b/form/src/assets/play/btn_left.png new file mode 100644 index 0000000000000000000000000000000000000000..e3428fd5bcda4bad311e87c5aa5669fdb7e96a60 GIT binary patch literal 2022 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/play/btn_right.png b/form/src/assets/play/btn_right.png new file mode 100644 index 0000000000000000000000000000000000000000..db0f274024b4ad41d5219acf3936ec2b2f79459c GIT binary patch literal 1921 zcmZ`)`#0428y6Lk?V_xdd?mh>Ti>me8ER>mI4)rl7EQLI5hl0XGGf=YGrLi3xwLjA zv#W+!Ix12sF|N6cW@Kh$G-k#OhRN;oe!jDRK(BM2*K<41^TX>r=RCP5J&C&7hT3Xs zYPzl`2tF$Bpt9py8Y(upiBZ(l)KgEolbluQ*RX2U*E(OVue94K-`T-@$#RE^i$tPS zP~4eow*y7NVBL2h&w$x1Gm~}G)A1lLLZ9g{{~OHTlDx8oxq^`=2Vss5it8|&mltn> z&HNN|*2tTvw=|QvAj?onulDp5VI!F^abvOF4t-2m>Ljl85f_GIU@{-Zug&(I0ZHC? z^C5BTVKhNo9QGS|?t;dzv^}tSec!6F*kb&}!MfWPWjSW=8-0JzHpgV?*x02NS;orr zPs>y3%ZkinINj8!T^BAGf*21Ico5;SHXI1>AjD(sI5bAbcu8o)4L;$qP8@tZibl@B zBp&8UV6GVJ#-RZmjN;J<9u4789}dJ0*c%+i!hzx@8pgqF37RYhJ|6X|VmgTJ5l1z9 z2jo<c5KuoJeZawVsY))4M~9i8VLBbAld$0=m<j}`Cx{&p7Y~XXAPYm>5Ue*Cq&^^V z0|^nt$FO$}AT2=?cd_w8m3lCn4e|&Ohk+~<Yj?$ZPhfBDVH5{bcVOl!Hj)I>aWEAE zQa?0w6lQONyZ}w!K*CHkmIPyDj2(jYdjtO@h`bQn6+XGZgd==9igi1nejFOl2XP(} zWP>CPaiS1E3>ze4eIXzs!l)xiGvRXrh+@%r4B|z?L?Gh%f$$XKl7L6VSk8z`Km!D< z+Y!BYFgqLY@BIbE`FQ%OscUNMuGzBP)P0lfHiz#B`*u27pTN18yZr}~V~bz3rujpS z^mM<C3o_9dhxPgyvoz)6g&z;?HdJ3$D(B}Xh5TW5PtWVt$2C=dm6zPPotvGWNC`US z^1YqembRw0N;S3B{;mW^l7DN{kg#~O_m;I(9sP<^1gT7gs5Lq|*UmfYlL-FtkLrUR zolmn>RVM9Stn7SakTovT*q%o#QG6pm&_fFC|1+}Kwkyz<Ip=i%N4?Kr)YQ1Lnjt-G zHN!fnKkb4n*+67kW<);}fm3#L`7uY1ZQNt?A~mU}BEEP>gkjudp&oOG&TFQ9nr~20 z>LraO7b`<no3^uMf>6vQ?0S6o`PJ<+Q%_lKr$T3{<kht1tII9jdV;AqTHS}3%YzH$ z5$x!XO;@57e+1*dWcBRe)~y-4BC|TK!PKYC3i{d0`QKXOo^Qt*$I3<9<0GvqHnDTg zq@+peb>}iNT8lUAJVLYIX3Q~d3T%w~@VAg;Gn|87<!bZNZjV!R#kWZ1Z3-{)N<1xk zLvU%^#W~BPyq(@`{=w1=_07ii?491N0vE?0Q^y*WIfmb`{a1VR@SaQ5UuP?ilsUxK zhHu9E9`NGElEOE<AypB&R#wd}3`Jhv5}Gm|u|pr;>nDD3?{Tf<=$SV&!U++3t?mJZ z{WD=<vVkQO60>Z(J*q>R82r&HuCbo{-qGgGTGtCJ?gsxu6=2I(<fBi~3TKcw({M`| z5&A7R(vjUEXT5ls+#qfDNi1yd?c_vSU&)2BH^zsfn-gtMt_pIhEAM;i_UB^vyCuzI ztSFhWud~UczW3!`&)l3AJ%0(C(mr!>^2tj@)vn)q<80O@WUnl4=(7$8t+y>bU2Z6# z^>0my44)CzTlCtNoEzBVZBa|<e$^MXUb;%6@k8`LP-X|?rEpua@nBT|c~}xdyvW~5 ze&mtDh_COwZGT=jCiy`_=316I5$itT%wOuCJLEwz3Pzeudj{$KyZ8GWCOUoOEENUn zS%y`{;<PF&pO{)vE5(D7A!a$dXn=7mATF16;f%YLt~)YYKk`Rdd@t?8)dXJYulVpf zZr{DP350@_ruk>r-VB!2eI89#zAeo+IlVtzr=aDbk%swc{}$=pe2#I<Cqh5RyV|b) z+~ajM3pC$gCF`#I7j=&mf72f-EL%g_4YEXUWsBbBR|INwt&udG(v>qw33*|eQj_o~ z%;BMP{?wgU0ky*gZPYB~qTjDGHxjOU1+Fg%EYY-0I$ZtbcgtX>w!Ep0>g5&rn-out zDHcYmHJ1DFMPxyf?dtk31AFCrZ5ocRzeHf^E0Xtxr|;MO?*mQqp-ZkiJvM7}4`c~Q zu~YA~I_diVL`lnhBCv@^;be4n9WkGCe~`_zu%RXdYaR*vUyYBJWg6ZfjuPp?pRU=h zk<YWr3S`Wmt0s|Wira&9Jge80Z{?Wy3sSnYUJjaDx$mo4tKrM4VO*s8Gv5j{^8E%9 zpLSegRAd&u$u|46{Vvs@?s~SF^=ZoNb^Tjz=LMGJy`|&)vj@qIE$<EOl6Q=-)LBCQ z<(Ar(S-V7ovd)eP(c~U~@?yz~+KtYMC5=76U0J(Gr&}!g4O9Ppi>}U|1f~-?<Nrq` B7k>Z% literal 0 HcmV?d00001 diff --git a/form/src/assets/play/default/audio.mp3 b/form/src/assets/play/default/audio.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..66313dcf084aa98da69908cb6ee9da2d0d4a451e GIT binary patch literal 2520 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 U*#Fnbg&<*b2#$Z=?x!pN1+rgoTmS$7 literal 0 HcmV?d00001 diff --git a/form/src/assets/play/default/pic.jpg b/form/src/assets/play/default/pic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1da3c1135cc324bf3ec67cc0c7b4c19caeef08f1 GIT binary patch literal 29421 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 H{@(-uMQ%#v literal 0 HcmV?d00001 diff --git a/form/src/assets/play/music/click.mp3 b/form/src/assets/play/music/click.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f551dc50e89af2d63b79892af8bf1d61ae92f7a5 GIT binary patch literal 10054 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 literal 0 HcmV?d00001 diff --git a/form/src/assets/play/text_bg.png b/form/src/assets/play/text_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..6084daeadcb2cec320328e7e1f362d104b7ffbaa GIT binary patch literal 293 zcmeAS@N?(olHy`uVBq!ia0vp^kwC1-!VDxGLZl3UluCe4h%1mL2$n@KxdRpPlmz(& z`!YDX*_oSZsmO`*$SgeH3>07D>Eak-aeC?%L#{&(0<90*m6En|DP2s{-Fixp<zQ6) z1HmtBVP<hoK*n5OgVay|_W$eJFjMlZ_w46^w!QxA+m^b8M>@Z?+Ivna@Bejk%e&Eg zr(9ifHN7&nEAC`Y)R*YI`4?_pyS>D#Z1a-V_3obW@$I!gEZ$r_p2%;<7tPG8^Ud^k z-Z!;3dvES{DL#}o;jH;>*)7v^o?o<0+|G5^u`c=M-+zo}B%~%PKIN(fdDhd_&t;uc GLK6ToDQ1BH literal 0 HcmV?d00001 diff --git a/form/src/environments/environment.prod.ts b/form/src/environments/environment.prod.ts new file mode 100644 index 0000000..3612073 --- /dev/null +++ b/form/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git a/form/src/environments/environment.ts b/form/src/environments/environment.ts new file mode 100644 index 0000000..7b4f817 --- /dev/null +++ b/form/src/environments/environment.ts @@ -0,0 +1,16 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. + +export const environment = { + production: false +}; + +/* + * For easier debugging in development mode, you can import the following file + * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. + * + * This import should be commented out in production mode because it will have a negative impact + * on performance if an error is thrown. + */ +// import 'zone.js/dist/zone-error'; // Included with Angular CLI. diff --git a/form/src/favicon.ico b/form/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8081c7ceaf2be08bf59010158c586170d9d2d517 GIT binary patch literal 5430 zcmc(je{54#6vvCoAI3i*G5%$U7!sA3wtMZ$fH6V9C`=eXGJb@R1%(I_{vnZtpD{6n z5Pl{DmxzBDbrB>}`90e12m8T*36WoeDLA&SD_hw{H^wM!cl_RWcVA!I+x87ee975; z@4kD^=bYPn&pmG@(+JZ`rqQEKxW<}RzhW}I!|ulN=fmjVi@x{p$cC`)5$a!)X&U<D zFCrQtlPskre}dB7oMCp>+blKNvN5tg=uLvuLnuqRM;Yc*swiexsoh#XPNu{9F#c`G zQLe{yWA(Y6(;>y|-e<R78l|^`vH6ft-mErSG~Y`TZF2qm1=W=MNd^2V3)n2xIl=~X zcQ9VjzHW38ty|rZz+bkcR(-c)`wbqC#l0CF>fAy11k<09(@Oo1B2@0`PtZSkqK&${ zgEY}`W@t{%?9u5rF?}Y7OL{338l<M%K~-+w4iJ-2C_>*JY#P!%MVQY@oqnItpZ}?s z!r?*kwuR{A@jg2Chlf0^{q*>8n5Ir~YWf*wmsh7B5&EpHfd5@xVaj&gqsdui^spyL zB|kUoblGoO7G(MuKTfa9?pGH0@QP^b#!lM1yHWLh*2iq#`C1TdrnO-d#?Oh@XV2HK zKA{`eo{--^K&MW66Lgsktfvn#cCAc*(}qsfhrvOjMGLE?`dHVipu1J3Kgr%g?cNa8 z)pkmC8DGH~fG+dlrp(5^-QBeEvkOvv#q7MBVLtm2oD^$lJZx--_=K&Ttd=-krx(Bb zcEoKJda@S!%%@`P-##$>*u%T*mh+QjV@)Qa=Mk1?#zLk+M4tIt%}wagT{5<jKE$zW zf^v7jW~uUE-%mB7^CHH8TL1|_urI~hKTTLO4e;Zw7r~I(052QT!nq=k3BK4rWn{P1 zm1bHmzb3QsEPddOfehts!4+*he<-J0Tp_H*ozKD(I$*vEIRc5vL3kd@p{$kjMIKQs z<pI0(Vu7$}v<2fENHCVA=ZgE(eBp=9a;_O`BkfrU-cm?UdhYP}+z)k)*4wQOW0K7S zxLV9h7PeF2dOvMg->J%!tXAE;r{@=bb%nNVxvI+C+$t?!VJ@0d@HIyMJTI{vEw0Ul ze(ha!e&qANbTL1ZneNl45t=#Ot??C0MHjjgY8%*mGisN|S6%g3;Hlx#fMNcL<87MW zZ>6moo1YD?P!fJ#Jb(4)_cc50X5n0KoDYfdPoL^iV`k&o{LPyaoqMqk92wVM#_O0l z09$(A-D+gVIlq4TA&{1T@BsUH`Bm=r#l$Z51J<A&BjWib@$s|gZJQqmbJQD%pmuqr zlRi3r%o8I$s7b`Nd|6!*{)IIXevOQu?P#Tr`(a_yaC`Z3mz2%s0J*VP!oMryv%aGJ zJ%+hr;JUR9N%=NQUAcsxH1Ev(z=Jw5x*3ZP^w64B9T1;d$FN#v|K3{yO?U3}p#~CX zQeul5J0S-k&QP-WS^uxU^lJ9qPEkik*MChluj|;LEt~#I8atbRn<NLMVzYM(P(Mc^ z+=Vcf!|a)D*bAJ$B)>-U&F32+hfUP-iLo=jg7Xmy+WLq6_tWv&`wDlz#`&)Jp~iQf zZP)tu>}pIIJKuw+$&t}GQuqMd%Z>0?t%&BM&W<om&b&wS^Ui5`y0`bK`dz>o^4P^Y z)c6h^f2R>X8*}q|bblAF?@;%?2>$y+cMQbN{X$)^R>v<j%HOoXFL3nF-$ASizAu7L zA~a)K^qdiKCTsOM0PF^%{K=Uu<ZEZkC-ypeB>tNq_5AB|0N5U*d^T?X9{xQnJYeU{ zoZL#obI;~Pp95f1`%X3D$Mh*4^?O?IT~7HqlWguezmg?Ybq|7>qQ(@pPHbE9V?f|( z+0xo!#m@Np9PljsyxBY-UA*{U*la#8Wz2sO|48_-5t8%_!n?S$zlGe+NA%?vmxjS- zHE5O3ZarU=X}$7>;Okp(UWXJxI%G_J-@IH;%5#Rt$(WUX?6*Ux!IRd$dLP6+SmPn= z8zjm4jGjN772R{FGkXwcNv8GBcZI#@Y2m{RNF_w8(Z%^A*!bS*!}s6sh*NnURytky humW;*g7R+&|Ledvc-<M)bUEqtWbbwV3iw}c{{uEu@7@3a literal 0 HcmV?d00001 diff --git a/form/src/index.html b/form/src/index.html new file mode 100644 index 0000000..e556416 --- /dev/null +++ b/form/src/index.html @@ -0,0 +1,16 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>NgOne</title> + <base href="/"> +<!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">--> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="icon" type="image/x-icon" href="favicon.ico"> + <script type="text/javascript" src="https://staging-teach.cdn.ireadabc.com/h5template/h5-static-lib/js/air.js"></script> + +</head> +<body> +<app-root></app-root> +</body> +</html> diff --git a/form/src/main.ts b/form/src/main.ts new file mode 100644 index 0000000..c7b673c --- /dev/null +++ b/form/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); diff --git a/form/src/online.html b/form/src/online.html new file mode 100644 index 0000000..91956f8 --- /dev/null +++ b/form/src/online.html @@ -0,0 +1,16 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>NgOne</title> + <base href="/"> +<!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">--> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="icon" type="image/x-icon" href="favicon.ico"> + <script type="text/javascript" src="https://staging-teach.cdn.ireadabc.com/h5template/h5-static-lib/js/air.js"></script> + +</head> +<body> + Hello World!! +</body> +</html> diff --git a/form/src/polyfills.ts b/form/src/polyfills.ts new file mode 100644 index 0000000..aa665d6 --- /dev/null +++ b/form/src/polyfills.ts @@ -0,0 +1,63 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/guide/browser-support + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + */ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags.ts'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/form/src/styles.css b/form/src/styles.css new file mode 100644 index 0000000..90d4ee0 --- /dev/null +++ b/form/src/styles.css @@ -0,0 +1 @@ +/* You can add global styles to this file, and also import other style files */ diff --git a/form/src/test.ts b/form/src/test.ts new file mode 100644 index 0000000..1631789 --- /dev/null +++ b/form/src/test.ts @@ -0,0 +1,20 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/zone-testing'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +declare const require: any; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); diff --git a/form/tsconfig.app.json b/form/tsconfig.app.json new file mode 100644 index 0000000..8fe350f --- /dev/null +++ b/form/tsconfig.app.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [ + "node" + ] + }, + "files": [ + "src/main.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "src/test.ts", + "src/**/*.spec.ts" + ] +} diff --git a/form/tsconfig.json b/form/tsconfig.json new file mode 100644 index 0000000..b4f6b3c --- /dev/null +++ b/form/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "module": "esnext", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "importHelpers": true, + "target": "es2015", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2018", + "dom" + ] + }, + "angularCompilerOptions": { + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true + } +} diff --git a/form/tsconfig.spec.json b/form/tsconfig.spec.json new file mode 100644 index 0000000..6400fde --- /dev/null +++ b/form/tsconfig.spec.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/form/tslint.json b/form/tslint.json new file mode 100644 index 0000000..4fcb4b1 --- /dev/null +++ b/form/tslint.json @@ -0,0 +1,100 @@ +{ + "extends": "tslint:recommended", + "rules": { + "array-type": false, + "arrow-parens": false, + "deprecation": { + "severity": "warning" + }, + "component-class-suffix": true, + "contextual-lifecycle": true, + "directive-class-suffix": true, + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ], + "import-blacklist": [ + true, + "rxjs/Rx" + ], + "interface-name": false, + "max-classes-per-file": false, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-consecutive-blank-lines": false, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-empty": false, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-non-null-assertion": true, + "no-redundant-jsdoc": true, + "no-switch-case-fall-through": true, + "no-use-before-declare": true, + "no-var-requires": false, + + "no-shadowed-variable": false, + + "object-literal-key-quotes": [ + true, + "as-needed" + ], + "object-literal-sort-keys": false, + "ordered-imports": false, + "quotemark": [ + true, + "single" + ], + "trailing-comma": false, + "no-conflicting-lifecycle": true, + "no-host-metadata-property": true, + "no-input-rename": true, + "no-inputs-metadata-property": true, + "no-output-native": true, + "no-output-on-prefix": true, + "no-output-rename": true, + "no-outputs-metadata-property": true, + "template-banana-in-box": true, + "template-no-negated-async": true, + "use-lifecycle-interface": true, + "use-pipe-transform-interface": true, + "no-trailing-whitespace": false, + "variable-name": false, + + "no-unused-expression": false, + "align": false + }, + "rulesDirectory": [ + "codelyzer" + ] +} -- 2.21.0