Repository: ciderapp/Cider
Branch: main
Commit: 953bb5a9e260
Files: 238
Total size: 7.8 MB
Directory structure:
gitextract_auu_ugs8/
├── .editorconfig
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yaml
│ │ ├── config.yml
│ │ └── translation.yaml
│ ├── PULL_REQUEST_TEMPLATE/
│ │ └── translations.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── auto-project.yml
│ ├── cider-chores.yml
│ ├── dev-chores.yml
│ ├── stale-issues.yml
│ └── support-notice.yml
├── .gitignore
├── .npmrc
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── .yarnrc.yml
├── Assets/
│ ├── AppChromeBtn.afdesign
│ ├── Install On Cider/
│ │ └── install on cider.afdesign
│ ├── MissingArtwork.afdesign
│ └── Sources/
│ ├── Cider with text.afdesign
│ ├── Release.afdesign
│ ├── cider-vinyl no raster.afdesign
│ ├── cider-vinyl-no raster 2.afdesign
│ └── cider-vinyl.afdesign
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── docs/
│ └── plugins/
│ ├── example/
│ │ └── examplePlugin.ts
│ └── sendSongToTitlebar.ts
├── flatpak/
│ ├── cider-wrapper
│ ├── flathub.json
│ ├── org.cidercollective.cider.yml
│ ├── sh.cider.Cider.metainfo.xml
│ └── sh.cider.Cider.yml
├── msft-test.json
├── package.json
├── resources/
│ ├── afterPack.cjs
│ ├── bg.tiff
│ ├── entitlements.mac.plist
│ ├── icons/
│ │ ├── icon-old.icns
│ │ └── icon.icns
│ ├── license.json
│ ├── license.txt
│ ├── macPackager.cjs
│ ├── notarize.cjs
│ ├── verror-types
│ └── version.sh
├── src/
│ ├── ciderkit/
│ │ └── public.js
│ ├── main/
│ │ ├── base/
│ │ │ ├── app.ts
│ │ │ ├── browserwindow.ts
│ │ │ ├── castcontroller.ts
│ │ │ ├── castreceiver.ts
│ │ │ ├── plugins.ts
│ │ │ ├── store.ts
│ │ │ ├── utils.ts
│ │ │ ├── vcomponents.json
│ │ │ ├── vrouting.json
│ │ │ └── wsapi.ts
│ │ ├── index.ts
│ │ ├── plugins/
│ │ │ ├── chromecast.ts
│ │ │ ├── discordrpc.ts
│ │ │ ├── lastfm.ts
│ │ │ ├── menubar.ts
│ │ │ ├── mpris.ts
│ │ │ ├── playbackNotifications.ts
│ │ │ ├── raop.ts
│ │ │ ├── thumbar.ts
│ │ │ └── webNowPlaying.ts
│ │ └── providers/
│ │ └── local/
│ │ └── index.ts
│ ├── preload/
│ │ └── cider-preload.js
│ ├── renderer/
│ │ ├── apple-hls-old.js
│ │ ├── apple-hls.js
│ │ ├── assets/
│ │ │ └── fonts/
│ │ │ ├── Inter/
│ │ │ │ └── inter.css
│ │ │ └── Pretendard/
│ │ │ └── pretendardvariable.css
│ │ ├── audio/
│ │ │ ├── audio.js
│ │ │ └── cloud/
│ │ │ └── audio.js
│ │ ├── hlscider.js
│ │ ├── index.js
│ │ ├── less/
│ │ │ ├── ameframework.less
│ │ │ ├── appvars.less
│ │ │ ├── bootstrap-vue.min.less
│ │ │ ├── bootstrap.less
│ │ │ ├── codicon.css
│ │ │ ├── compact.less
│ │ │ ├── directives.less
│ │ │ ├── elements.less
│ │ │ ├── fullscreen.less
│ │ │ ├── helpers.css
│ │ │ ├── helpers.less
│ │ │ ├── linux.less
│ │ │ ├── macos.less
│ │ │ ├── macosemu.less
│ │ │ ├── miniplayer.less
│ │ │ ├── notyf.less
│ │ │ ├── pages.css
│ │ │ └── pages.less
│ │ ├── lib/
│ │ │ ├── fast-plural-rules.js
│ │ │ ├── less.js
│ │ │ ├── marked.js
│ │ │ ├── smoothscroll.js
│ │ │ ├── vue-horizontal.js
│ │ │ ├── vue.dev.js
│ │ │ └── vue.js
│ │ ├── main/
│ │ │ ├── app.js
│ │ │ ├── cidercache.js
│ │ │ ├── ciderfrontapi.js
│ │ │ ├── components/
│ │ │ │ ├── i18n-editor.js
│ │ │ │ ├── sidebar-library-item.js
│ │ │ │ └── svg-icon.js
│ │ │ ├── events.js
│ │ │ ├── gamepad.js
│ │ │ ├── html.js
│ │ │ ├── mica.js
│ │ │ ├── musickittools.js
│ │ │ ├── vueapp.js
│ │ │ ├── vuex-store.js
│ │ │ └── wsapi_interop.js
│ │ ├── sounds/
│ │ │ ├── btn1.ogg
│ │ │ ├── confirm.ogg
│ │ │ └── hover.ogg
│ │ ├── style.less
│ │ ├── sw.js
│ │ ├── themes/
│ │ │ ├── WIP.md
│ │ │ ├── compactui.less
│ │ │ ├── dark.less
│ │ │ ├── default.less
│ │ │ ├── grain.less
│ │ │ ├── inline_drawer.less
│ │ │ ├── reduce_visuals.less
│ │ │ └── sweetener.less
│ │ ├── todo.js
│ │ ├── views/
│ │ │ ├── app/
│ │ │ │ ├── app-navigation.ejs
│ │ │ │ ├── chrome-bottom.ejs
│ │ │ │ ├── chrome-top.ejs
│ │ │ │ └── panels.ejs
│ │ │ ├── components/
│ │ │ │ ├── add-to-playlist.ejs
│ │ │ │ ├── airplay-modal.ejs
│ │ │ │ ├── animatedartwork-view.ejs
│ │ │ │ ├── app-content.ejs
│ │ │ │ ├── artist-chip.ejs
│ │ │ │ ├── artwork-material.ejs
│ │ │ │ ├── audio-controls.ejs
│ │ │ │ ├── audio-playbackrate.ejs
│ │ │ │ ├── audio-settings.ejs
│ │ │ │ ├── c2-upgrade.ejs
│ │ │ │ ├── castmenu.ejs
│ │ │ │ ├── cider-modal.ejs
│ │ │ │ ├── editorialNotes.ejs
│ │ │ │ ├── equalizer.ejs
│ │ │ │ ├── fullscreen.ejs
│ │ │ │ ├── hello-world.ejs
│ │ │ │ ├── inline-collection-list.ejs
│ │ │ │ ├── karaoke-in.ejs
│ │ │ │ ├── libraryartist-item.ejs
│ │ │ │ ├── listennow-child.ejs
│ │ │ │ ├── listitem-horizontal.ejs
│ │ │ │ ├── lyrics-view.ejs
│ │ │ │ ├── mediaitem-artwork.ejs
│ │ │ │ ├── mediaitem-hrect.ejs
│ │ │ │ ├── mediaitem-info.ejs
│ │ │ │ ├── mediaitem-list-item.ejs
│ │ │ │ ├── mediaitem-mvview-sp.ejs
│ │ │ │ ├── mediaitem-mvview.ejs
│ │ │ │ ├── mediaitem-scroller-horizontal-large.ejs
│ │ │ │ ├── mediaitem-scroller-horizontal-mvview.ejs
│ │ │ │ ├── mediaitem-scroller-horizontal-sp.ejs
│ │ │ │ ├── mediaitem-scroller-horizontal.ejs
│ │ │ │ ├── mediaitem-square.ejs
│ │ │ │ ├── menu-panel.ejs
│ │ │ │ ├── miniplayer.ejs
│ │ │ │ ├── moreinfo-modal.ejs
│ │ │ │ ├── pagination.ejs
│ │ │ │ ├── pathmenu.ejs
│ │ │ │ ├── playlists.ejs
│ │ │ │ ├── plugin-menu.ejs
│ │ │ │ ├── qrcode-modal.ejs
│ │ │ │ ├── queue.ejs
│ │ │ │ ├── settings-keybinds.ejs
│ │ │ │ ├── settings-plugins-github.ejs
│ │ │ │ ├── settings-themes-github.ejs
│ │ │ │ ├── settings-themes.ejs
│ │ │ │ ├── settings-window.ejs
│ │ │ │ ├── share-sheet.ejs
│ │ │ │ ├── sidebar-playlist.ejs
│ │ │ │ ├── sidebar.ejs
│ │ │ │ └── smarthints.ejs
│ │ │ ├── main.ejs
│ │ │ └── pages/
│ │ │ ├── about.ejs
│ │ │ ├── apple-account-settings.ejs
│ │ │ ├── apple-curator.ejs
│ │ │ ├── artist-feed.ejs
│ │ │ ├── artist.ejs
│ │ │ ├── audiolabs.ejs
│ │ │ ├── browse.ejs
│ │ │ ├── charts.ejs
│ │ │ ├── cider-multiroom.ejs
│ │ │ ├── cider-playlist.ejs
│ │ │ ├── cider-profile.ejs
│ │ │ ├── collection-list.ejs
│ │ │ ├── connect-linked.ejs
│ │ │ ├── groupings.ejs
│ │ │ ├── home.ejs
│ │ │ ├── installed-themes.ejs
│ │ │ ├── library-albums.ejs
│ │ │ ├── library-artists.ejs
│ │ │ ├── library-recentlyadded.ejs
│ │ │ ├── library-songs.ejs
│ │ │ ├── library-videos.ejs
│ │ │ ├── listen_now.ejs
│ │ │ ├── madeforyou.ejs
│ │ │ ├── oobe.ejs
│ │ │ ├── playlist-inline.ejs
│ │ │ ├── plugin-renderer.ejs
│ │ │ ├── podcasts.ejs
│ │ │ ├── radio.ejs
│ │ │ ├── recordLabel.ejs
│ │ │ ├── remote-pair.ejs
│ │ │ ├── replay.ejs
│ │ │ ├── search.ejs
│ │ │ ├── themes-github.ejs
│ │ │ ├── webview.ejs
│ │ │ └── zoo.ejs
│ │ └── workbox-962786f2.js
│ └── web-remote/
│ ├── ciderframework.css
│ ├── index.js
│ ├── manifest.json
│ ├── style.css
│ ├── views/
│ │ ├── components/
│ │ │ ├── animatedartwork-view.ejs
│ │ │ ├── mediaitem-artwork.ejs
│ │ │ └── mediaitem-square.ejs
│ │ └── index.ejs
│ └── vue.js
├── steam-deck.json
├── tsconfig.json
├── winget.json
└── workbox-config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
================================================
FILE: .github/FUNDING.yml
================================================
github: ciderapp
ko_fi: cryptofyre
open_collective: ciderapp
custom: "https://opencollective.com/ciderapp/donate/10/month/Support%20Development?redirect=https://cidercollective.dev/thanks"
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yaml
================================================
name: Bug Report
description: If you encounter an issue whilst using our app, please use this template to help improve the app.
title: "[Bug]: "
labels: ["bug", "needs-triage"]
assignees: []
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: checkboxes
attributes:
label: Preflight Checklist
description: Please ensure you've completed all of the following.
options:
- label: I have read the [Support Disclaimer](https://docs.cider.sh/support/disclaimer) for this project.
required: true
- label: I agree to follow the [Code of Conduct](https://github.com/ciderapp/Cider/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
required: true
- label: I have searched the [issue tracker](https://www.github.com/ciderapp/Cider/issues) for a bug report that matches the one I want to file, without success.
required: true
- label: I have read the [troublshooting FAQs](https://cider.gitbook.io/welcome-to-gitbook/support/faqs#why-is-my-discordrpc-status-not-appearing) and none solved my issue.
required: true
- type: input
attributes:
label: Cider Version
description: |
What version of Cider are you using?
Note: Please only report issues for [currently supported versions of Cider](hhttps://cider.gitbook.io/welcome-to-gitbook/support/version-information). You can find your version on the About Page.
placeholder: 1.6.0
validations:
required: true
- type: dropdown
attributes:
label: What operating system are you using?
options:
- Windows
- macOS
- Ubuntu
- Other Linux
- Other (specify below)
validations:
required: true
- type: input
attributes:
label: Operating System Version
description: What operating system version are you using? On Windows, click Start button > Settings > System > About. On macOS, click the Apple Menu > About This Mac. On Linux, use lsb_release or uname -a.
placeholder: "e.g. Windows 10 version 1909, macOS Catalina 10.15.7, or Ubuntu 20.04"
validations:
required: true
- type: dropdown
id: download
attributes:
label: Where did you download Cider from?
options:
- Microsoft Store
- GitHub
- Winget
- Winget (Nightly)
- Chocolatey
- Flathub
- AUR
validations:
required: true
- type: textarea
id: description
attributes:
label: Describe the Bug
description: A clear and concise description of the bug you encountered. Tell us what did you expect to happen?
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: replication
attributes:
label: Steps to Reproduce
description: How did you produce this bug, tell us how you did it so we can do it ourselves.
placeholder: 1. Clicked on...
validations:
required: true
- type: textarea
attributes:
label: Anything else?
description: |
Links? References? Anything that will give us more context about the issue you are encountering!
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Support Disclaimer
url: https://docs.cider.sh/support/disclaimer
about: Please read this before creating any issue.
- name: Feature Request
url: https://github.com/ciderapp/Cider/discussions/new?category=feature-request
about: Have a feature you would like to have in the app? Make a request.
- name: Discord Support
url: https://discord.com/invite/AppleMusic
about: For quick support, make a ticket or ask for community support here.
- name: Cider Documentation
url: https://docs.cider.sh/support/faqs
about: In most cases, these troubleshooting tips can resolve basic issues. Try them out before opening an issue.
- name: GitHub Issues
url: https://github.com/ciderapp/Cider/issues
about: Check to make sure there is not an issues already open that is related to your issue.
================================================
FILE: .github/ISSUE_TEMPLATE/translation.yaml
================================================
name: Translation Report/Request
description: Request a language or report an issue with one.
title: "[Translation]: "
labels: ["🌐 Translations"]
assignees: []
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this report!
- type: input
id: language
attributes:
label: Relevant Language
description: The language you would like to request for or have an issue with.
placeholder: en_US
validations:
required: true
- type: dropdown
id: requestType
attributes:
label: Change or Addition or Both
multiple: true
options:
- Change a Language
- Add a Language
validations:
required: true
- type: textarea
id: description
attributes:
label: Change Requested / Any Additional Information
description: If you are requesting a change, place all the information here, or you can provide additional information to additions if you want.
placeholder: I would like ... changed to ...
validations:
required: false
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/ciderapp/Cider/blob/main/CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
================================================
FILE: .github/PULL_REQUEST_TEMPLATE/translations.md
================================================
---
name: Translations
about: Improvement to our tranlations
title: ""
labels: 🌐 Translations
assignees: ''
---
================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "monthly"
================================================
FILE: .github/workflows/auto-project.yml
================================================
name: Add bugs to bugs project
on:
issues:
types:
- opened
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/ciderapp/projects/5
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
labeled: bug, needs-triage
label-operator: OR
================================================
FILE: .github/workflows/cider-chores.yml
================================================
name: Cider Chores
on:
push:
branches:
- main
jobs:
compile-and-post:
runs-on: ubuntu-latest
container:
image: electronuserland/builder:wine
steps:
- name: Checkout 🛎
uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- name: Install Dependencies 📦
run: pnpm install
- name: Build 🏗
run: pnpm dist:all
- name: Upload Release 🚀
uses: softprops/action-gh-release@v2.0.5
with:
files: |
./dist/*.exe
./dist/*.deb
./dist/*.AppImage
./dist/*.rpm
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/dev-chores.yml
================================================
name: Developer Chores
on: [pull_request]
jobs:
linter-check:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node: [18]
steps:
- name: Checkout 🛎
uses: actions/checkout@v3
- name: Setup node env 🏗
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
check-latest: true
- name: Install dependencies 👨🏻💻
run: npm run bootstrap
- name: Run linter 👀
run: npm run format:write
- name: Comment Suggestions 🗒️
uses: getsentry/action-git-diff-suggestions@main
with:
message: Prettier Suggestion
================================================
FILE: .github/workflows/stale-issues.yml
================================================
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
with:
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
days-before-stale: 30
days-before-close: 7
stale-issue-label: "stale"
stale-pr-label: "stale"
exempt-all-assignees: true
exempt-issue-labels: 'more-info,work-in-progress,accessibility-feature,help-wanted,persist/priority'
================================================
FILE: .github/workflows/support-notice.yml
================================================
name: Support Notice
on:
issues:
types: [opened]
jobs:
post-notice:
runs-on: ubuntu-latest
steps:
- uses: derekprior/add-autoresponse@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
respondableId: ${{ github.event.issue.node_id }}
response: "Cider 1.x is no longer actively maintained. We highly suggest moving to the newer version versions of the app available at https://cider.sh through official storefronts ex. Itch.io, or the Microsoft Store."
author: ${{ github.event.issue.user.login }}
================================================
FILE: .gitignore
================================================
# Building
dist
build
.flatpak*
yarn-cache
src/renderer/style.css
.pnpm-store
# Misc
.idea
.vscode
auth.json
musickit.js
# Microsoft Store Package Configs
msft-package.json
## Node GitIgnore ##
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.pnp.*
.yarn/*
.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
## JetBrains GitIgnore ##
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
## macOS GitIgnore ##
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
## VSCode GitIgnore ##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
## Sublime Text GitIgnore ##
# Cache files for Sublime Text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# Workspace files are user-specific
*.sublime-workspace
# Project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using Sublime Text
# *.sublime-project
# SFTP configuration file
sftp-config.json
sftp-config-alt*.json
# Package control specific files
Package Control.last-run
Package Control.ca-list
Package Control.ca-bundle
Package Control.system-ca-bundle
Package Control.cache/
Package Control.ca-certs/
Package Control.merged-ca-bundle
Package Control.user-ca-bundle
oscrypto-ca-bundle.crt
bh_unicode_properties.cache
# Sublime-github package stores a github token in this file
# https://packagecontrol.io/packages/sublime-github
GitHub.sublime-settings
#Service Worker mappings
src/renderer/sw.js.map
src/renderer/workbox-962786f2.js.map
/src/renderer/musickit-dev.js
#Mac certs
*.p12
keys.sh
package-lock.json
resources/b64.txt
savedconfig/cider-config.json
savedconfig/config.json
savedconfig/session.json
savedconfig/window-state.json
src/main/base/sample.json
# yeet circleci ci for now
.circleci/
================================================
FILE: .npmrc
================================================
node-linker=hoisted
public-hoist-pattern=*
shamefully-hoist=true
================================================
FILE: .nvmrc
================================================
20.2.0
================================================
FILE: .prettierignore
================================================
src/renderer/*hls*.js
build/*
dist/*
src/renderer/lib/*
*.min.*
.pnpm-store
================================================
FILE: .prettierrc
================================================
{
"printWidth": 600,
"singleAttributePerLine": true,
"bracketSameLine": true,
"overrides": [
{
"files": "src/renderer/main/**/*.js",
"options": {
"singleAttributePerLine": false
}
}
]
}
================================================
FILE: .yarnrc.yml
================================================
compressionLevel: mixed
enableGlobalCache: false
nodeLinker: node-modules
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
> Threats made to someone's wellbeing, especially towards self-harm or sucide, will be automatically be dealt with as a maximum level offense, no matter the reasoning.
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
cryptofyre@cider.sh.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
================================================
FILE: LICENSE
================================================
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
.
================================================
FILE: README.md
================================================
Cider 1
> [!WARNING]
>This project has been archived, and no further updates or support will be provided under any circumstances. We highly recommend switching to [Cider v2](https://cider.sh/downloads/client) for the latest features, improvements, and continued support.
This repository contains the source code for **Cider v1.x**, a cross-platform Apple Music client built from the ground up by the development team.
Cider v1 was developed using [Electron.js](https://electronjs.org), [Vue.js 2](https://vuejs.org), and [Webpack](https://webpack.js.org).
**Note:** While distributions may still be available through various third-party sources, first-party builds are no longer provided due to the high volume of support requests for v1. You can compile it following the [insructions outlined in our legacy documentation](https://cider.sh/docs) from our website. Support will not be provided for compiling.
================================================
FILE: docs/plugins/example/examplePlugin.ts
================================================
let i = 1,
k = 1;
class ExamplePlugin {
/**
* Private variables for interaction in plugins
*/
private _win: any;
private _app: any;
private _store: any;
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "examplePlugin";
public description: string = "Example plugin";
public version: string = "1.0.0";
public author: string = "Example author";
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(app: any, store: any) {
this._app = app;
this._store = store;
console.debug(`[Plugin][${this.name}] Loading Complete.`);
}
/**
* Runs on app ready
*/
onReady(win: any): void {
this._win = win;
console.debug(`[Plugin][${this.name}] Ready.`);
}
/**
* Runs on app stop
*/
onBeforeQuit(): void {
console.debug(`[Plugin][${this.name}] Stopped.`);
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
onPlaybackStateDidChange(attributes: object): void {
console.log("onPlaybackStateDidChange has been called " + i + " times");
i++;
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
onNowPlayingItemDidChange(attributes: object): void {
console.log("onNowPlayingDidChange has been called " + k + " times");
k++;
}
}
module.exports = ExamplePlugin;
================================================
FILE: docs/plugins/sendSongToTitlebar.ts
================================================
class sendSongToTitlebar {
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "sendSongToTitlebar";
public description: string = "Sets the app's titlebar to the Song title";
public version: string = "0.0.1";
public author: string = "Cider Collective (credit to 8times9 via #147)";
/**
* Runs on plugin load (Currently run on application start)
*/
private _win: any;
private _app: any;
constructor() {}
/**
* Runs on app ready
*/
onReady(win: any): void {
this._win = win;
}
/**
* Runs on app stop
*/
onBeforeQuit(): void {}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
onPlaybackStateDidChange(attributes: any): void {
this._win.setTitle(`${attributes != null && attributes.name != null && attributes.name.length > 0 ? attributes.name + " - " : ""}Cider`);
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
onNowPlayingItemDidChange(attributes: object): void {}
}
module.exports = sendSongToTitlebar;
================================================
FILE: flatpak/cider-wrapper
================================================
#!/bin/sh
for i in {0..9}; do
test -S $XDG_RUNTIME_DIR/discord-ipc-$i || ln -sf {app/com.discordapp.Discord,$XDG_RUNTIME_DIR}/discord-ipc-$i;
done
cider "$@"
================================================
FILE: flatpak/flathub.json
================================================
{
"only-arches": ["x86_64"],
"publish-delay-hours": 2
}
================================================
FILE: flatpak/org.cidercollective.cider.yml
================================================
app-id: org.cidercollective.cider
runtime: org.freedesktop.Platform
runtime-version: '21.08'
sdk: org.freedesktop.Sdk
base: org.electronjs.Electron2.BaseApp
base-version: '21.08'
command: cider
rename-desktop-file: cider.desktop
rename-icon: cider
finish-args:
- --device=dri
- --filesystem=xdg-music
- --own-name=org.mpris.MediaPlayer2.Cider
- --share=ipc
- --share=network
- --socket=pulseaudio
# needs electron v11 (chromium v87) or newer with ozone enabled
# https://github.com/electron/electron/issues/10915
# - --socket=wayland
- --socket=x11
- --system-talk-name=org.freedesktop.UPower
- --talk-name=com.canonical.AppMenu.Registrar
- --talk-name=com.canonical.dbusmenu
- --talk-name=org.freedesktop.Notifications
- --talk-name=org.kde.StatusNotifierWatcher
modules:
- name: cider
buildsystem: simple
build-commands:
- install -dm755 ${FLATPAK_DEST}/cider
- |
bsdtar -Oxf cider.deb 'data.tar*' |
bsdtar -xf - \
-C ${FLATPAK_DEST}/cider \
--strip-components=3 \
./opt/Cider
- |
bsdtar -Oxf cider.deb 'data.tar*' |
bsdtar -xf - \
-C ${FLATPAK_DEST} \
--strip-components=2 \
--exclude=./usr/share/doc \
./usr/share
- desktop-file-edit --set-key=Exec --set-value=cider ${FLATPAK_DEST}/share/applications/cider.desktop
- install -Dm755 stub_sandbox ${FLATPAK_DEST}/cider/chrome-sandbox
- install -Dm755 cider -t ${FLATPAK_DEST}/bin/
sources:
- type: file
dest-filename: cider.deb
url: https://1308-429851205-gh.circle-artifacts.com/0/~/Cider/dist/artifacts/cider_1.3.1308_amd64.deb
sha256: 342abde96bac9668e7238860ba435171edd72077ed9f4b385a3546c4d8f96995
x-checker-data:
type: html
url: https://circleci.com/api/v1.1/project/gh/ciderapp/Cider/latest/artifacts?branch=main&filter=successful
pattern: (https://.*circle-artifacts.com/.+/cider_([\d\.]+)_amd64.deb)
- type: script
dest-filename: cider
commands:
# share chromium singleton between multiple session, needed for flatpak<1.11.1
- export TMPDIR=$XDG_RUNTIME_DIR/app/$FLATPAK_ID
- exec zypak-wrapper /app/cider/cider "$@"
- type: script
dest-filename: stub_sandbox
commands:
- |
echo Stub sandbox ignoring command: $@
exit 1
================================================
FILE: flatpak/sh.cider.Cider.metainfo.xml
================================================
sh.cider.CiderCiderAn open source and community oriented Apple Music clientCC0-1.0AGPL-1.0-or-laterCider Collectivehttps://cider.sh/?utm_source=flathub%26utm_medium=link%26utm_campaign=product-pagehttps://github.com/ciderapp/Cider/issueshttps://ko-fi.com/cryptofyre
Project Cider. A new look into listening and enjoying Apple Music in style and performance with Features such as Discord and Last.fm integration, spatial audio support, equalizers, and remote controllable using companion app
cider.desktophttps://github.com/ciderapp/cider.sh/blob/main/assets/img/frontpage-scn.png?raw=true
================================================
FILE: flatpak/sh.cider.Cider.yml
================================================
app-id: sh.cider.Cider
runtime: org.freedesktop.Platform
runtime-version: '21.08'
sdk: org.freedesktop.Sdk
base: org.electronjs.Electron2.BaseApp
base-version: '21.08'
command: cider-wrapper
rename-desktop-file: cider.desktop
rename-icon: cider
finish-args:
- --device=dri
- --filesystem=xdg-music
- --filesystem=xdg-run/app/com.discordapp.Discord:create
- --own-name=org.mpris.MediaPlayer2.cider
- --share=ipc
- --share=network
- --socket=pulseaudio
# needs electron v11 (chromium v87) or newer with ozone enabled
# https://github.com/electron/electron/issues/10915
#- --socket=wayland
- --socket=x11
- --system-talk-name=org.freedesktop.UPower
- --talk-name=com.canonical.AppMenu.Registrar
- --talk-name=com.canonical.dbusmenu
- --talk-name=org.freedesktop.Notifications
- --talk-name=org.kde.StatusNotifierWatcher
modules:
- name: cider
buildsystem: simple
build-commands:
- install -dm755 ${FLATPAK_DEST}/cider
- |
bsdtar -Oxf cider.deb 'data.tar*' |
bsdtar -xf - \
-C ${FLATPAK_DEST}/cider \
--strip-components=3 \
./opt/Cider
- |
bsdtar -Oxf cider.deb 'data.tar*' |
bsdtar -xf - \
-C ${FLATPAK_DEST} \
--strip-components=2 \
--exclude=./usr/share/doc \
./usr/share
- install -Dm755 cider-wrapper /app/bin/cider-wrapper
- desktop-file-edit --set-key=Exec --set-value=cider-wrapper ${FLATPAK_DEST}/share/applications/cider.desktop
- install -Dm755 stub_sandbox ${FLATPAK_DEST}/cider/chrome-sandbox
- install -Dm755 cider -t ${FLATPAK_DEST}/bin/
- install -Dm644 -t /app/share/metainfo ${FLATPAK_ID}.metainfo.xml
sources:
- type: file
dest-filename: cider.deb
url: https://github.com/ciderapp/cider-releases/releases/download/v1.3.0.1555/cider_1.3.0-alpha.1555_amd64.deb
sha256: 8a582ca2758d556cc2d5fad73e05ed3e2f27076e13bf377d1d83d9494aaef9c2
x-checker-data:
type: json
url: https://api.github.com/repos/ciderapp/cider-releases/releases/latest
version-query: .tag_name
url-query: .assets[] | select(.name | match("(amd64.deb)")) | .browser_download_url
- type: script
dest-filename: cider
commands:
# share chromium singleton between multiple session, needed for flatpak<1.11.1
- export TMPDIR=$XDG_RUNTIME_DIR/app/$FLATPAK_ID
- exec zypak-wrapper /app/cider/cider "$@"
- type: script
dest-filename: stub_sandbox
commands:
- |
echo Stub sandbox ignoring command: $@
exit 1
- type: file
path: cider-wrapper
- type: file
path: sh.cider.Cider.metainfo.xml
================================================
FILE: msft-test.json
================================================
{
"electronVersion": "16.2.8",
"electronDownload": {
"version": "16.2.8+wvcus",
"mirror": "https://github.com/castlabs/electron-releases/releases/download/v"
},
"appId": "cider",
"protocols": [
{
"name": "Cider",
"schemes": ["ame", "cider", "itms", "itmss", "musics", "music"]
}
],
"extends": null,
"files": ["**/*", "./src/**/*", "./resources/icons/icon.*"],
"linux": {
"target": ["AppImage", "deb", "snap", "rpm"],
"synopsis": "A new look into listening and enjoying music in style and performance. ",
"category": "AudioVideo",
"icon": "cider",
"executableName": "cider"
},
"appx": {
"applicationId": "CiderAlpha",
"publisher": "CN=CiderCollective, OID.2.25.311729368913984317654407730594956997722=1",
"displayName": "Cider",
"identityName": "CiderCollective.CiderAlpha",
"backgroundColor": "transparent",
"setBuildNumber": true
},
"win": {
"target": ["appx"],
"icon": "resources/icons/icon.ico"
},
"directories": {
"buildResources": ".",
"output": "dist"
},
"mac": {
"icon": "./resources/icons/icon.icns",
"category": "public.app-category.music",
"entitlements": "resources/entitlements.mac.plist",
"darkModeSupport": true
}
}
================================================
FILE: package.json
================================================
{
"name": "cider",
"applicationId": "Cider",
"productName": "Cider",
"version": "1.6.4",
"description": "A new cross-platform Apple Music experience based on Electron and Vue.js written from scratch with performance in mind.",
"license": "AGPL-3.0",
"exports": "./build/index.js",
"main": "./build/index.js",
"author": "Cider Collective (https://cider.sh)",
"repository": "github:ciderapp/Cider",
"type": "module",
"bugs": {
"url": "https://github.com/ciderapp/Cider/issues?q=is%3Aopen+is%3Aissue+label%3Abug"
},
"homepage": "https://cider.sh/",
"buildResources": "resources",
"scripts": {
"bootstrap": "npx -y check-engine && pnpm i",
"build": "tsc && lessc ./src/renderer/style.less ./src/renderer/style.css",
"start": "npm run build && electron ./build/index.js",
"dist": "npm run build && electron-builder --publish=never",
"dist:win": "npm run build && electron-builder --win --publish=never",
"dist:linux": "npm run build && electron-builder --linux --publish=never",
"dist:all": "npm run build && electron-builder -wl --publish=never",
"dist:universalNotWorking": "npm run build && electron-builder --mac --universal --publish:never",
"winget": "npm run build && electron-builder --win -c winget.json",
"msft": "npm run build && electron-builder -c msft-package.json",
"mstest": "npm run build && electron-builder -c msft-test.json",
"steamdeck": "npm run build && electron-builder --linux -c steam-deck.json",
"format:check": "npx prettier --check \"src/**/*.{js,json,ts,less}\"",
"format:write": "npx prettier --write \"src/**/*.{js,json,ts,less}\""
},
"dependencies": {
"@achingbrain/ssdp": "^4.2.1",
"@crowdin/ota-client": "^1.1.3",
"adm-zip": "^0.5.16",
"airtunes2": "github:ciderapp/node_airtunes2",
"castv2-client": "github:ciderapp/node-castv2-client",
"chokidar": "^3.6.0",
"discord-auto-rpc": "^1.0.17",
"ejs": "^3.1.10",
"electron-log": "^5.2.4",
"electron-notarize": "^1.2.2",
"electron-store": "^9.0.0",
"electron-updater": "6.2.1",
"electron-window-state": "^5.0.3",
"express": "^4.21.2",
"get-port": "7.1.0",
"jimp": "^0.22.12",
"lastfmapi": "^0.1.1",
"mdns-js": "github:ciderapp/node-mdns-js",
"mpris-service": "github:ciderapp/mpris-service",
"music-metadata": "7.14.0",
"node-fetch": "^3.3.2",
"node-ssdp": "^4.0.1",
"node-ssdp-js": "^0.9.6",
"qrcode": "^1.5.4",
"request": "^2.88.2",
"simple-ssdp": "^1.0.2",
"source-map-support": "^0.5.21",
"ssdp-js": "^1.0.1",
"ts-md5": "1.3.1",
"upnp-mediarenderer-client": "github:vapormusic/node-upnp-mediarenderer-client",
"v8-compile-cache": "^2.4.0",
"wallpaper": "7.2.1",
"ws": "^8.18.0",
"xml2js": "^0.6.2",
"youtube-search-without-api-key": "^2.0.1"
},
"devDependencies": {
"@types/adm-zip": "^0.5.7",
"@types/discord-rpc": "4.0.8",
"@types/express": "^4.17.21",
"@types/musickit": "github:ciderapp/musickit-types",
"@types/node": "^20.17.9",
"@types/node-ssdp": "^4.0.4",
"@types/qrcode-terminal": "^0.12.2",
"@types/request": "^2.48.12",
"@types/upnp-mediarenderer-client": "^1.4.3",
"@types/ws": "^8.5.13",
"@types/xml2js": "^0.4.14",
"electron": "github:castlabs/electron-releases#v32.2.6+wvcus",
"electron-builder": "^24.13.3",
"electron-builder-notarize-pkg": "^1.2.0",
"electron-webpack": "^2.8.2",
"less": "^4.2.1",
"node-gyp": "^10.3.1",
"prettier": "3.2.5",
"typescript": "^5.7.2",
"vue-devtools": "^5.1.4",
"webpack": "~5.91.0"
},
"fileAssociations": [
{
"name": "Cider",
"mimeType": "x-scheme-handler/ame;x-scheme-handler/itms;x-scheme-handler/itmss;x-scheme-handler/musics;x-scheme-handler/music;",
"schemes": [
"ame",
"cider",
"itms",
"itmss",
"musics",
"music"
],
"protocols": [
"ame",
"cider",
"itms",
"itmss",
"musics",
"music"
]
}
],
"build": {
"electronDownload": {
"mirror": "https://github.com/castlabs/electron-releases/releases/download/v"
},
"appId": "cider",
"afterPack": "./resources/afterPack.cjs",
"afterSign": "./resources/notarize.cjs",
"protocols": [
{
"name": "Cider",
"schemes": [
"ame",
"cider",
"itms",
"itmss",
"musics",
"music"
]
}
],
"extends": null,
"files": [
"./build/**/*",
"./src/**/*",
"./resources/icons/**/*"
],
"linux": {
"target": [
"AppImage",
"deb",
"rpm"
],
"synopsis": "A new look into listening and enjoying music in style and performance. ",
"category": "AudioVideo",
"icon": "cider",
"executableName": "cider"
},
"appx": {
"applicationId": "Cider",
"displayName": "Cider",
"identityName": "Cider",
"publisherDisplayName": "Cider Collective",
"backgroundColor": "transparent",
"setBuildNumber": true
},
"nsis": {
"oneClick": false,
"perMachine": false,
"allowToChangeInstallationDirectory": true,
"license": "LICENSE",
"deleteAppDataOnUninstall": true,
"artifactName": "${productName}-Setup-${version}.${ext}"
},
"pkg": {
"installLocation": "/Applications",
"background": {
"file": "./resources/bg.png",
"alignment": "bottomleft"
},
"allowAnywhere": true,
"allowCurrentUserHome": true,
"allowRootDirectory": true,
"license": "./LICENSE",
"isVersionChecked": false,
"isRelocatable": false,
"overwriteAction": "upgrade"
},
"snap": {
"slots": [
{
"mpris": {
"interface": "mpris"
}
}
]
},
"dmg": {
"background": "./resources/bg.tiff",
"icon": "resources/icons/icon.ico"
},
"mas": {
"entitlements": "./resources/entitlements.mac.plist",
"entitlementsInherit": "./resources/entitlements.mac.plist"
},
"win": {
"target": [
"nsis"
],
"icon": "resources/icons/icon.ico"
},
"directories": {
"buildResources": ".",
"output": "dist"
},
"mac": {
"hardenedRuntime": true,
"gatekeeperAssess": false,
"icon": "./resources/icons/icon.icns",
"category": "public.app-category.music",
"entitlements": "./resources/entitlements.mac.plist",
"entitlementsInherit": "./resources/entitlements.mac.plist",
"darkModeSupport": true,
"target": [
"dmg"
],
"extendInfo": {
"NSUserNotificationAlertStyle": "alert"
}
}
},
"electronWebpack": {
"devtool": "source-map"
},
"packageManager": "pnpm@9.15.0"
}
================================================
FILE: resources/afterPack.cjs
================================================
exports.default = function (context) {
const { execSync } = require("child_process");
const fs = require("fs");
if (process.platform !== "darwin") return;
if (fs.existsSync("dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig"))
fs.unlinkSync("dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig");
if (fs.existsSync("dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig"))
fs.unlinkSync("dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig");
console.log('Castlabs-evs update start')
execSync('python3 -m pip install --upgrade castlabs-evs')
console.log('Castlabs-evs update complete')
// xcode 13
if (
fs.existsSync("dist/mac-universal--x64") &&
fs.existsSync("dist/mac-universal--arm64") &&
fs.existsSync("dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib")
)
execSync(
"cp 'dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib' 'dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib'",
{ stdio: "inherit" }
);
console.log('VMP signing start')
if (fs.existsSync('dist/mac-universal'))
execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac-universal',{stdio: 'inherit'})
if (fs.existsSync('dist/mac'))
execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac',{stdio: 'inherit'})
if (fs.existsSync('dist/mac-arm64'))
execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac-arm64 -z',{stdio: 'inherit'})
console.log('VMP signing complete')
};
================================================
FILE: resources/entitlements.mac.plist
================================================
com.apple.security.cs.allow-jitcom.apple.security.cs.allow-unsigned-executable-memorycom.apple.security.cs.disable-library-validation
================================================
FILE: resources/license.json
================================================
{
"$schema": "https://github.com/argv-minus-one/dmg-license/raw/master/schema.json",
"body": [
{
"file": "license.txt",
"lang": ["en-US"]
}
]
}
================================================
FILE: resources/license.txt
================================================
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
.
================================================
FILE: resources/macPackager.cjs
================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const bluebird_lst_1 = require("bluebird-lst");
const builder_util_1 = require("builder-util");
const electron_osx_sign_1 = require("electron-osx-sign");
const promises_1 = require("fs/promises");
const lazy_val_1 = require("lazy-val");
const path = require("path");
const fs_1 = require("builder-util/out/fs");
const promise_1 = require("builder-util/out/promise");
const appInfo_1 = require("./appInfo");
const macCodeSign_1 = require("./codeSign/macCodeSign");
const core_1 = require("./core");
const platformPackager_1 = require("./platformPackager");
const ArchiveTarget_1 = require("./targets/ArchiveTarget");
const pkg_1 = require("./targets/pkg");
const targetFactory_1 = require("./targets/targetFactory");
const macosVersion_1 = require("./util/macosVersion");
const pathManager_1 = require("./util/pathManager");
const fs = require("fs/promises");
class MacPackager extends platformPackager_1.PlatformPackager {
constructor(info) {
super(info, core_1.Platform.MAC);
this.codeSigningInfo = new lazy_val_1.Lazy(() => {
const cscLink = this.getCscLink();
if (cscLink == null || process.platform !== "darwin") {
return Promise.resolve({
keychainFile: process.env.CSC_KEYCHAIN || null,
});
}
return macCodeSign_1
.createKeychain({
tmpDir: this.info.tempDirManager,
cscLink,
cscKeyPassword: this.getCscPassword(),
cscILink: platformPackager_1.chooseNotNull(this.platformSpecificBuildOptions.cscInstallerLink, process.env.CSC_INSTALLER_LINK),
cscIKeyPassword: platformPackager_1.chooseNotNull(this.platformSpecificBuildOptions.cscInstallerKeyPassword, process.env.CSC_INSTALLER_KEY_PASSWORD),
currentDir: this.projectDir,
})
.then((result) => {
const keychainFile = result.keychainFile;
if (keychainFile != null) {
this.info.disposeOnBuildFinish(() => macCodeSign_1.removeKeychain(keychainFile));
}
return result;
});
});
this._iconPath = new lazy_val_1.Lazy(() => this.getOrConvertIcon("icns"));
}
get defaultTarget() {
return this.info.framework.macOsDefaultTargets;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
prepareAppInfo(appInfo) {
return new appInfo_1.AppInfo(this.info, this.platformSpecificBuildOptions.bundleVersion, this.platformSpecificBuildOptions);
}
async getIconPath() {
return this._iconPath.value;
}
createTargets(targets, mapper) {
for (const name of targets) {
switch (name) {
case core_1.DIR_TARGET:
break;
case "dmg": {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { DmgTarget } = require("dmg-builder");
mapper(name, (outDir) => new DmgTarget(this, outDir));
break;
}
case "zip":
// https://github.com/electron-userland/electron-builder/issues/2313
mapper(name, (outDir) => new ArchiveTarget_1.ArchiveTarget(name, outDir, this, true));
break;
case "pkg":
mapper(name, (outDir) => new pkg_1.PkgTarget(this, outDir));
break;
default:
mapper(name, (outDir) => (name === "mas" || name === "mas-dev" ? new targetFactory_1.NoOpTarget(name) : targetFactory_1.createCommonTarget(name, outDir, this)));
break;
}
}
}
async doPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets) {
switch (arch) {
default: {
return super.doPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets);
}
case builder_util_1.Arch.universal: {
const x64Arch = builder_util_1.Arch.x64;
const x64AppOutDir = appOutDir + "--" + builder_util_1.Arch[x64Arch];
await super.doPack(outDir, x64AppOutDir, platformName, x64Arch, platformSpecificBuildOptions, targets, false, true);
const arm64Arch = builder_util_1.Arch.arm64;
const arm64AppOutPath = appOutDir + "--" + builder_util_1.Arch[arm64Arch];
await super.doPack(outDir, arm64AppOutPath, platformName, arm64Arch, platformSpecificBuildOptions, targets, false, true);
const framework = this.info.framework;
builder_util_1.log.info(
{
platform: platformName,
arch: builder_util_1.Arch[arch],
[`${framework.name}`]: framework.version,
appOutDir: builder_util_1.log.filePath(appOutDir),
},
`packaging`
);
const appFile = `${this.appInfo.productFilename}.app`;
const { makeUniversalApp } = require("@electron/universal");
await makeUniversalApp({
x64AppPath: path.join(x64AppOutDir, appFile),
arm64AppPath: path.join(arm64AppOutPath, appFile),
outAppPath: path.join(appOutDir, appFile),
force: true,
});
await fs.rm(x64AppOutDir, { recursive: true, force: true });
await fs.rm(arm64AppOutPath, { recursive: true, force: true });
const packContext = {
appOutDir,
outDir,
arch,
targets,
packager: this,
electronPlatformName: platformName,
};
await this.info.afterPack(packContext);
if (framework.afterPack != null) {
await framework.afterPack(packContext);
}
await this.doSignAfterPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets);
break;
}
}
}
async pack(outDir, arch, targets, taskManager) {
let nonMasPromise = null;
const hasMas = targets.length !== 0 && targets.some((it) => it.name === "mas" || it.name === "mas-dev");
const prepackaged = this.packagerOptions.prepackaged;
if (!hasMas || targets.length > 1) {
const appPath = prepackaged == null ? path.join(this.computeAppOutDir(outDir, arch), `${this.appInfo.productFilename}.app`) : prepackaged;
nonMasPromise = (prepackaged ? Promise.resolve() : this.doPack(outDir, path.dirname(appPath), this.platform.nodeName, arch, this.platformSpecificBuildOptions, targets)).then(() =>
this.packageInDistributableFormat(appPath, arch, targets, taskManager)
);
}
for (const target of targets) {
const targetName = target.name;
if (!(targetName === "mas" || targetName === "mas-dev")) {
continue;
}
const masBuildOptions = builder_util_1.deepAssign({}, this.platformSpecificBuildOptions, this.config.mas);
if (targetName === "mas-dev") {
builder_util_1.deepAssign(masBuildOptions, this.config.masDev, {
type: "development",
});
}
const targetOutDir = path.join(outDir, `${targetName}${builder_util_1.getArchSuffix(arch)}`);
if (prepackaged == null) {
await this.doPack(outDir, targetOutDir, "mas", arch, masBuildOptions, [target]);
await this.sign(path.join(targetOutDir, `${this.appInfo.productFilename}.app`), targetOutDir, masBuildOptions, arch);
} else {
await this.sign(prepackaged, targetOutDir, masBuildOptions, arch);
}
}
if (nonMasPromise != null) {
await nonMasPromise;
}
}
async sign(appPath, outDir, masOptions, arch) {
if (!macCodeSign_1.isSignAllowed()) {
return;
}
const isMas = masOptions != null;
const options = masOptions == null ? this.platformSpecificBuildOptions : masOptions;
const qualifier = options.identity;
if (!isMas && qualifier === null) {
if (this.forceCodeSigning) {
throw new builder_util_1.InvalidConfigurationError("identity explicitly is set to null, but forceCodeSigning is set to true");
}
builder_util_1.log.info({ reason: "identity explicitly is set to null" }, "skipped macOS code signing");
return;
}
const keychainFile = (await this.codeSigningInfo.value).keychainFile;
const explicitType = options.type;
const type = explicitType || "distribution";
const isDevelopment = type === "development";
const certificateTypes = getCertificateTypes(isMas, isDevelopment);
let identity = null;
for (const certificateType of certificateTypes) {
identity = await macCodeSign_1.findIdentity(certificateType, qualifier, keychainFile);
if (identity != null) {
break;
}
}
if (identity == null) {
if (!isMas && !isDevelopment && explicitType !== "distribution") {
identity = await macCodeSign_1.findIdentity("Mac Developer", qualifier, keychainFile);
if (identity != null) {
builder_util_1.log.warn("Mac Developer is used to sign app — it is only for development and testing, not for production");
}
}
if (identity == null) {
await macCodeSign_1.reportError(isMas, certificateTypes, qualifier, keychainFile, this.forceCodeSigning);
return;
}
}
if (!macosVersion_1.isMacOsHighSierra()) {
throw new builder_util_1.InvalidConfigurationError("macOS High Sierra 10.13.6 is required to sign");
}
let filter = options.signIgnore;
if (Array.isArray(filter)) {
if (filter.length == 0) {
filter = null;
}
} else if (filter != null) {
filter = filter.length === 0 ? null : [filter];
}
const filterRe = filter == null ? null : filter.map((it) => new RegExp(it));
let binaries = options.binaries || undefined;
if (binaries) {
// Accept absolute paths for external binaries, else resolve relative paths from the artifact's app Contents path.
const userDefinedBinaries = await Promise.all(
binaries.map(async (destination) => {
if (await fs_1.statOrNull(destination)) {
return destination;
}
return path.resolve(appPath, destination);
})
);
// Insert at front to prioritize signing. We still sort by depth next
binaries = userDefinedBinaries.concat(binaries);
builder_util_1.log.info("Signing addtional user-defined binaries: " + JSON.stringify(userDefinedBinaries, null, 1));
}
const signOptions = {
"identity-validation": false,
// https://github.com/electron-userland/electron-builder/issues/1699
// kext are signed by the chipset manufacturers. You need a special certificate (only available on request) from Apple to be able to sign kext.
ignore: (file) => {
if (filterRe != null) {
for (const regExp of filterRe) {
if (regExp.test(file)) {
return true;
}
}
}
return (
file.endsWith(".kext") ||
file.startsWith("/Contents/PlugIns", appPath.length) ||
file.includes("/node_modules/puppeteer/.local-chromium") ||
file.includes("/node_modules/playwright-firefox/.local-browsers") ||
file.includes("/node_modules/playwright/.local-browsers")
);
/* Those are browser automating modules, browser (chromium, nightly) cannot be signed
https://github.com/electron-userland/electron-builder/issues/2010
https://github.com/electron-userland/electron-builder/issues/5383
*/
},
identity: identity,
type,
platform: isMas ? "mas" : "darwin",
version: this.config.electronVersion,
app: appPath,
keychain: keychainFile || undefined,
binaries,
timestamp: isMas ? (masOptions === null || masOptions === void 0 ? void 0 : masOptions.timestamp) : options.timestamp,
requirements: isMas || this.platformSpecificBuildOptions.requirements == null ? undefined : await this.getResource(this.platformSpecificBuildOptions.requirements),
// https://github.com/electron-userland/electron-osx-sign/issues/196
// will fail on 10.14.5+ because a signed but unnotarized app is also rejected.
"gatekeeper-assess": options.gatekeeperAssess === true,
// https://github.com/electron-userland/electron-builder/issues/1480
"strict-verify": options.strictVerify,
hardenedRuntime: isMas ? masOptions && masOptions.hardenedRuntime === true : options.hardenedRuntime !== false,
};
await this.adjustSignOptions(signOptions, masOptions);
builder_util_1.log.info(
{
file: builder_util_1.log.filePath(appPath),
identityName: identity.name,
identityHash: identity.hash,
provisioningProfile: signOptions["provisioning-profile"] || "none",
},
"signing"
);
await this.doSign(signOptions);
// https://github.com/electron-userland/electron-builder/issues/1196#issuecomment-312310209
if (masOptions != null && !isDevelopment) {
const certType = isDevelopment ? "Mac Developer" : "3rd Party Mac Developer Installer";
const masInstallerIdentity = await macCodeSign_1.findIdentity(certType, masOptions.identity, keychainFile);
if (masInstallerIdentity == null) {
throw new builder_util_1.InvalidConfigurationError(`Cannot find valid "${certType}" identity to sign MAS installer, please see https://electron.build/code-signing`);
}
// mas uploaded to AppStore, so, use "-" instead of space for name
const artifactName = this.expandArtifactNamePattern(masOptions, "pkg", arch);
const artifactPath = path.join(outDir, artifactName);
await this.doFlat(appPath, artifactPath, masInstallerIdentity, keychainFile);
await this.dispatchArtifactCreated(artifactPath, null, builder_util_1.Arch.x64, this.computeSafeArtifactName(artifactName, "pkg", arch, true, this.platformSpecificBuildOptions.defaultArch));
}
}
async adjustSignOptions(signOptions, masOptions) {
const resourceList = await this.resourceList;
const customSignOptions = masOptions || this.platformSpecificBuildOptions;
const entitlementsSuffix = masOptions == null ? "mac" : "mas";
let entitlements = customSignOptions.entitlements;
if (entitlements == null) {
const p = `entitlements.${entitlementsSuffix}.plist`;
if (resourceList.includes(p)) {
entitlements = path.join(this.info.buildResourcesDir, p);
} else {
entitlements = pathManager_1.getTemplatePath("entitlements.mac.plist");
}
}
signOptions.entitlements = entitlements;
let entitlementsInherit = customSignOptions.entitlementsInherit;
if (entitlementsInherit == null) {
const p = `entitlements.${entitlementsSuffix}.inherit.plist`;
if (resourceList.includes(p)) {
entitlementsInherit = path.join(this.info.buildResourcesDir, p);
} else {
entitlementsInherit = pathManager_1.getTemplatePath("entitlements.mac.plist");
}
}
signOptions["entitlements-inherit"] = entitlementsInherit;
if (customSignOptions.provisioningProfile != null) {
signOptions["provisioning-profile"] = customSignOptions.provisioningProfile;
}
signOptions["entitlements-loginhelper"] = customSignOptions.entitlementsLoginHelper;
}
//noinspection JSMethodCanBeStatic
async doSign(opts) {
return electron_osx_sign_1.signAsync(opts);
}
//noinspection JSMethodCanBeStatic
async doFlat(appPath, outFile, identity, keychain) {
// productbuild doesn't created directory for out file
await promises_1.mkdir(path.dirname(outFile), { recursive: true });
const args = pkg_1.prepareProductBuildArgs(identity, keychain);
args.push("--component", appPath, "/Applications");
args.push(outFile);
return await builder_util_1.exec("productbuild", args);
}
getElectronSrcDir(dist) {
return path.resolve(this.projectDir, dist, this.info.framework.distMacOsAppName);
}
getElectronDestinationDir(appOutDir) {
return path.join(appOutDir, this.info.framework.distMacOsAppName);
}
// todo fileAssociations
async applyCommonInfo(appPlist, contentsPath) {
const appInfo = this.appInfo;
const appFilename = appInfo.productFilename;
// https://github.com/electron-userland/electron-builder/issues/1278
appPlist.CFBundleExecutable = appFilename.endsWith(" Helper") ? appFilename.substring(0, appFilename.length - " Helper".length) : appFilename;
const icon = await this.getIconPath();
if (icon != null) {
const oldIcon = appPlist.CFBundleIconFile;
const resourcesPath = path.join(contentsPath, "Resources");
if (oldIcon != null) {
await fs_1.unlinkIfExists(path.join(resourcesPath, oldIcon));
}
const iconFileName = "icon.icns";
appPlist.CFBundleIconFile = iconFileName;
await fs_1.copyFile(icon, path.join(resourcesPath, iconFileName));
}
appPlist.CFBundleName = appInfo.productName;
appPlist.CFBundleDisplayName = appInfo.productName;
const minimumSystemVersion = this.platformSpecificBuildOptions.minimumSystemVersion;
if (minimumSystemVersion != null) {
appPlist.LSMinimumSystemVersion = minimumSystemVersion;
}
appPlist.CFBundleIdentifier = appInfo.macBundleIdentifier;
appPlist.CFBundleShortVersionString = this.platformSpecificBuildOptions.bundleShortVersion || appInfo.version;
appPlist.CFBundleVersion = appInfo.buildVersion;
builder_util_1.use(this.platformSpecificBuildOptions.category || this.config.category, (it) => (appPlist.LSApplicationCategoryType = it));
appPlist.NSHumanReadableCopyright = appInfo.copyright;
if (this.platformSpecificBuildOptions.darkModeSupport) {
appPlist.NSRequiresAquaSystemAppearance = false;
}
const extendInfo = this.platformSpecificBuildOptions.extendInfo;
if (extendInfo != null) {
Object.assign(appPlist, extendInfo);
}
}
async signApp(packContext, isAsar) {
const appFileName = `${this.appInfo.productFilename}.app`;
await bluebird_lst_1.default.map(promises_1.readdir(packContext.appOutDir), (file) => {
if (file === appFileName) {
return this.sign(path.join(packContext.appOutDir, file), null, null, null);
}
return null;
});
if (!isAsar) {
return;
}
const outResourcesDir = path.join(packContext.appOutDir, "resources", "app.asar.unpacked");
await bluebird_lst_1.default.map(promise_1.orIfFileNotExist(promises_1.readdir(outResourcesDir), []), (file) => {
if (file.endsWith(".app")) {
return this.sign(path.join(outResourcesDir, file), null, null, null);
} else {
return null;
}
});
}
}
exports.default = MacPackager;
function getCertificateTypes(isMas, isDevelopment) {
if (isDevelopment) {
return isMas ? ["Mac Developer", "Apple Development"] : ["Developer ID Application"];
}
return isMas ? ["Apple Distribution"] : ["Developer ID Application"];
}
//# sourceMappingURL=macPackager.js.map
================================================
FILE: resources/notarize.cjs
================================================
require("dotenv").config();
const { notarize } = require("electron-notarize");
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== "darwin") {
return;
}
const appName = context.packager.appInfo.productFilename;
return await notarize({
appBundleId: "com.ciderapp.cider",
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLEID,
appleIdPassword: process.env.APPLEIDPASS,
});
};
================================================
FILE: resources/verror-types
================================================
// Type definitions for verror 1.10
// Project: https://github.com/davepacheco/node-verror
// Definitions by: Sven Reglitzki , Maxime Toumi-M
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/*
* VError([cause], fmt[, arg...]): Like JavaScript's built-in Error class, but
* supports a "cause" argument (another error) and a printf-style message. The
* cause argument can be null or omitted entirely.
*
* Examples:
*
* CODE MESSAGE
* new VError('something bad happened') "something bad happened"
* new VError('missing file: "%s"', file) "missing file: "/etc/passwd"
* with file = '/etc/passwd'
* new VError(err, 'open failed') "open failed: file not found"
* with err.message = 'file not found'
*/
declare class VError extends Error {
static VError: typeof VError;
static cause(err: Error): Error | null;
static info(err: Error): VError.Info;
static fullStack(err: Error): string;
static findCauseByName(err: Error, name: string): Error | null;
static hasCauseWithName(err: Error, name: string): boolean;
static errorFromList(errors: T[]): null | T | VError.MultiError;
static errorForEach(err: Error, func: (err: Error) => void): void;
//@ts-ignore
cause(): Error | undefined;
constructor(options: VError.Options | Error, message: string, ...params: any[]);
constructor(message?: string, ...params: any[]);
}
declare namespace VError {
interface Info {
[key: string]: any;
}
interface Options {
cause?: Error | null | undefined;
name?: string | undefined;
strict?: boolean | undefined;
constructorOpt?(...args: any[]): void;
info?: Info | undefined;
}
/*
* SError is like VError, but stricter about types. You cannot pass "null" or
* "undefined" as string arguments to the formatter. Since SError is only a
* different function, not really a different class, we don't set
* SError.prototype.name.
*/
class SError extends VError {}
/*
* Represents a collection of errors for the purpose of consumers that generally
* only deal with one error. Callers can extract the individual errors
* contained in this object, but may also just treat it as a normal single
* error, in which case a summary message will be printed.
*/
class MultiError extends VError {
constructor(errors: Error[]);
errors(): Error[];
}
/*
* Like JavaScript's built-in Error class, but supports a "cause" argument which
* is wrapped, not "folded in" as with VError. Accepts a printf-style message.
* The cause argument can be null.
*/
class WError extends VError {}
}
export = VError;
================================================
FILE: resources/version.sh
================================================
#!/bin/bash
# Setup the variables needed
if [[ $GH_REQUEST_TOKEN != "" ]]; then
STABLE_SHA=$(curl -H "Authorization: token ${GH_REQUEST_TOKEN}" -s https://api.github.com/repos/ciderapp/Cider/branches/stable | grep '"sha"' | head -1 | cut -d '"' -f 4)
elif [[ $GITHUB_TOKEN != "" ]]; then
STABLE_SHA=$(curl -H "Authorization: token ${GITHUB_TOKEN}" -s https://api.github.com/repos/ciderapp/Cider/branches/stable | grep '"sha"' | head -1 | cut -d '"' -f 4)
else
STABLE_SHA=$(curl -s https://api.github.com/repos/ciderapp/Cider/branches/stable | grep '"sha"' | head -1 | cut -d '"' -f 4)
fi
SHA_DATE=$(git show -s --format=%ci $STABLE_SHA)
VERSION_POSTFIX=$(git rev-list $STABLE_SHA..HEAD --count --since="$SHA_DATE")
CURRENT_VERSION=$(node -p -e "require('./package.json').version" | cut -d '-' -f 1)
# Set the version number for commits on main branch
if [[ ($CIRCLE_BRANCH == "main" || $GITHUB_REF_NAME == "main") && $VERSION_POSTFIX -gt 0 ]]; then
NEW_VERSION_NUMBERED="$CURRENT_VERSION-beta.$(printf "%03d\n" $VERSION_POSTFIX)"
NEW_VERSION="${CURRENT_VERSION}-beta.${VERSION_POSTFIX}"
# Update the version in package.json
if [[ $NO_WRITE_VER == "" && $(node -p -e "require('./package.json').version" | cut -d '.' -f 4) != $VERSION_POSTFIX ]]; then
if [[ $RUNNER_OS == "macOS" ]]; then
sed -i "" -e "s/$CURRENT_VERSION/$NEW_VERSION/" package.json
else
sed -i "0,/$CURRENT_VERSION/s//$NEW_VERSION/" package.json
fi
fi
else
NEW_VERSION_NUMBERED=$CURRENT_VERSION
NEW_VERSION=$CURRENT_VERSION
fi
echo $NEW_VERSION
# Add the version to the environment for CI usage
if [[ $GITHUB_REF_NAME != "" ]] && [[ "$GITHUB_ENV" ]]; then
echo "APP_VERSION=$NEW_VERSION" >>$GITHUB_ENV
echo "RELEASE_VERSION=$NEW_VERSION_NUMBERED" >>$GITHUB_ENV
elif [[ $CIRCLE_BRANCH != "" ]] && [[ "$BASH_ENV" ]]; then
echo "export APP_VERSION=$NEW_VERSION" >>$BASH_ENV
echo "export RELEASE_VERSION=$NEW_VERSION_NUMBERED" >>$BASH_ENV
fi
================================================
FILE: src/ciderkit/public.js
================================================
const CiderKit = {
v1: {
musickit: {
async mkv3(route, body, options) {
let opts = {
method: "POST",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
redirect: "follow",
referrerPolicy: "no-referrer",
body: {},
};
opts.body = JSON.stringify({
route: route,
body: body,
options: options,
});
let response = await fetch("./api/musickit/v3", opts);
return response.json();
},
},
},
};
================================================
FILE: src/main/base/app.ts
================================================
import { Menu, Tray, app, clipboard, ipcMain, nativeImage, shell } from "electron";
import log from "electron-log";
import { readFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import os from "os";
import { utils } from "../base/utils.js";
/**
* @file Creates App instance
* @author CiderCollective
*/
/** @namespace */
export class AppEvents {
private protocols: string[] = ["ame", "cider", "itms", "itmss", "musics", "music"];
private plugin: any = undefined;
private tray: any = undefined;
private i18n: any = undefined;
/** @constructor */
constructor() {
this.start();
}
/**
* Handles all actions that occur for the app on start (Mainly commandline arguments)
* @returns {void}
*/
private start(): void {
AppEvents.initLogging();
console.info("[AppEvents] App started");
/**********************************************************************************************************************
* Startup arguments handling
**********************************************************************************************************************/
if (app.commandLine.hasSwitch("version") || app.commandLine.hasSwitch("v")) {
console.log(app.getVersion());
app.exit();
}
// Verbose Check
if (app.commandLine.hasSwitch("verbose")) {
console.log("[Cider] User has launched the application with --verbose");
}
// Log File Location
if (app.commandLine.hasSwitch("log") || app.commandLine.hasSwitch("l")) {
console.log(join(app.getPath("userData"), "logs"));
app.exit();
}
// Try limiting JS memory to 350MB.
app.commandLine.appendSwitch("js-flags", "--max-old-space-size=350");
// Expose GC
app.commandLine.appendSwitch("js-flags", "--expose_gc");
if (process.platform === "win32") {
app.setAppUserModelId(app.getName()); // For notification name
}
/***********************************************************************************************************************
* Commandline arguments
**********************************************************************************************************************/
switch (utils.getStoreValue("visual.hw_acceleration") as string) {
default:
case "default":
app.commandLine.appendSwitch("enable-accelerated-mjpeg-decode");
app.commandLine.appendSwitch("enable-accelerated-video");
app.commandLine.appendSwitch("disable-gpu-driver-bug-workarounds");
app.commandLine.appendSwitch("ignore-gpu-blacklist");
app.commandLine.appendSwitch("enable-native-gpu-memory-buffers");
app.commandLine.appendSwitch("enable-accelerated-video-decode");
app.commandLine.appendSwitch("enable-gpu-rasterization");
app.commandLine.appendSwitch("enable-native-gpu-memory-buffers");
app.commandLine.appendSwitch("enable-oop-rasterization");
break;
case "webgpu":
console.info("[AppEvents] WebGPU is enabled.");
app.commandLine.appendSwitch("enable-unsafe-webgpu");
if (process.platform === "linux") {
app.commandLine.appendSwitch("enable-features", "Vulkan");
}
break;
case "disabled":
console.info("[AppEvents] Hardware acceleration is disabled.");
app.commandLine.appendSwitch("disable-gpu");
app.disableHardwareAcceleration();
break;
}
if (process.platform === "linux") {
app.commandLine.appendSwitch("disable-features", "MediaSessionService");
if (os.version().includes("SteamOS")) {
app.commandLine.appendSwitch("enable-features", "UseOzonePlatform");
app.commandLine.appendSwitch("ozone-platform", "x11");
}
}
/***********************************************************************************************************************
* Protocols
**********************************************************************************************************************/
/** */
if (process.defaultApp) {
if (process.argv.length >= 2) {
this.protocols.forEach((protocol: string) => {
app.setAsDefaultProtocolClient(protocol, process.execPath, [resolve(process.argv[1])]);
});
}
} else {
this.protocols.forEach((protocol: string) => {
app.setAsDefaultProtocolClient(protocol);
});
}
}
public quit() {
console.log("[AppEvents] App quit");
}
public ready(plug: any) {
this.plugin = plug;
console.log("[AppEvents] App ready");
AppEvents.setLoginSettings();
}
public bwCreated() {
app.on("open-url", (event, url) => {
event.preventDefault();
if (this.protocols.some((protocol: string) => url.includes(protocol))) {
this.LinkHandler(url);
console.log(url);
}
});
if (process.platform === "darwin") {
app.setUserActivity(
"8R23J2835D.com.ciderapp.webremote.play",
{
title: "Web Remote",
description: "Connect to your Web Remote",
},
"https://webremote.cider.sh",
);
}
this.InstanceHandler();
if (process.platform !== "darwin") {
this.InitTray();
}
}
/***********************************************************************************************************************
* Private methods
**********************************************************************************************************************/
/**
* Handles links (URI) and protocols for the application
* @param arg
*/
private LinkHandler(arg: string) {
if (!arg) return;
// LastFM Auth URL
if (arg.includes("auth")) {
const authURI = arg.split("/auth/")[1];
if (authURI.startsWith("lastfm")) {
// If we wanted more auth options
console.log("token: ", authURI.split("lastfm?token=")[1]);
utils
.getWindow()
.webContents.executeJavaScript(`ipcRenderer.send('lastfm:auth', ${JSON.stringify(authURI.split("lastfm?token=")[1])})`)
.catch(console.error);
}
} else if (arg.includes("playpause")) {
//language=JS
utils.getWindow().webContents.executeJavaScript("MusicKitInterop.playPause()");
} else if (arg.includes("nextitem")) {
//language=JS
utils.getWindow().webContents.executeJavaScript("app.mk.skipToNextItem()");
}
// Play
else if (arg.includes("/play/")) {
//Steer away from protocol:// specific conditionals
const playParam = arg.split("/play/")[1];
const mediaType = {
"s/": "song",
"a/": "album",
"p/": "playlist",
};
for (const [key, value] of Object.entries(mediaType)) {
if (playParam.includes(key)) {
const id = playParam.split(key)[1];
utils.getWindow().webContents.send("play", value, id);
console.debug(`[LinkHandler] Attempting to load ${value} by id: ${id}`);
}
}
} else if (arg.includes("music.apple.com")) {
// URL (used with itms/itmss/music/musics uris)
console.log(arg);
let url = arg.split("//")[1];
console.warn(`[LinkHandler] Attempting to load url: ${url}`);
utils.getWindow().webContents.send("play", "url", url);
} else if (arg.includes("/debug/appdata")) {
shell.openPath(app.getPath("userData"));
} else if (arg.includes("/debug/logs")) {
shell.openPath(app.getPath("logs"));
} else if (arg.includes("/discord")) {
shell.openExternal("https://discord.gg/applemusic");
} else if (arg.includes("/github")) {
shell.openExternal("https://github.com/ciderapp/cider");
} else if (arg.includes("/donate")) {
shell.openExternal("https://opencollective.com/ciderapp");
} else if (arg.includes("/beep")) {
shell.beep();
} else {
utils.getWindow().webContents.executeJavaScript(`app.appRoute(${JSON.stringify(arg.split("//")[1])})`);
}
}
/**
* Handles the creation of a new instance of the app
*/
private InstanceHandler() {
// Detects of an existing instance is running (So if the lock has been achieved, no existing instance has been found)
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
// Runs on the new instance if another instance has been found
console.log("[Cider] Another instance has been found, quitting.");
app.quit();
} else {
// Runs on the first instance if no other instance has been found
app.on("second-instance", (_event, startArgs) => {
console.log("[InstanceHandler] (second-instance) Instance started with " + startArgs.toString());
startArgs.forEach((arg) => {
console.log(arg);
if (arg.includes("cider://") || arg.includes("itms://") || arg.includes("itmss://") || arg.includes("music://") || arg.includes("musics://")) {
console.debug("[InstanceHandler] (second-instance) Link detected with " + arg);
this.LinkHandler(arg);
} else if (arg.includes("--force-quit")) {
console.warn("[InstanceHandler] (second-instance) Force Quit found. Quitting App.");
app.quit();
} else if (utils.getWindow()) {
if (utils.getWindow().isMinimized()) utils.getWindow().restore();
utils.getWindow().show();
utils.getWindow().focus();
}
});
});
}
}
/**
* Initializes the applications tray
*/
private InitTray() {
const icons = {
win32: nativeImage.createFromPath(join(dirname(fileURLToPath(import.meta.url)), `../../resources/icons/icon.ico`)).resize({
width: 32,
height: 32,
}),
linux: nativeImage.createFromPath(join(dirname(fileURLToPath(import.meta.url)), `../../resources/icons/icon.png`)).resize({
width: 32,
height: 32,
}),
darwin: nativeImage.createFromPath(join(dirname(fileURLToPath(import.meta.url)), `../../resources/icons/icon.png`)).resize({
width: 20,
height: 20,
}),
};
this.tray = new Tray(process.platform === "win32" ? icons.win32 : process.platform === "darwin" ? icons.darwin : icons.linux);
this.tray.setToolTip(app.getName());
this.setTray(false);
this.tray.on("double-click", () => { // supports windows and mac only
if (utils.getWindow()) {
if (utils.getWindow().isVisible()) {
utils.getWindow().focus();
} else {
utils.getWindow().show();
}
}
});
this.tray.on("click", () => {
if (utils.getWindow() && process.platform === "linux") { // use single click to open when double doesn't work
if (utils.getWindow().isVisible()) {
utils.getWindow().focus();
} else {
utils.getWindow().show();
}
}
});
utils.getWindow().on("show", () => {
this.setTray(true);
});
utils.getWindow().on("restore", () => {
this.setTray(true);
});
utils.getWindow().on("hide", () => {
this.setTray(false);
});
utils.getWindow().on("minimize", () => {
this.setTray(false);
});
}
/**
* Sets the tray context menu to a given state
* @param visible - BrowserWindow Visibility
*/
private setTray(visible: boolean = utils.getWindow().isVisible()) {
this.i18n = utils.getLocale(utils.getStoreValue("general.language"));
const ciderIcon = nativeImage.createFromPath(join(dirname(fileURLToPath(import.meta.url)), `../../resources/icons/icon.png`)).resize({
width: 24,
height: 24,
});
const menu = Menu.buildFromTemplate([
{
label: app.getName(),
enabled: false,
icon: ciderIcon,
},
{ type: "separator" },
/* For now only idea i dont know if posible to implement
this could be implemented in a plugin if you would like track info, it would be impractical to put listeners in this file. -Core
{
label: this.i18n['action.tray.listento'],
enabled: false,
},
{
visible: visible,
label: 'track info',
enabled: false,
},
{type: 'separator'},
*/
{
visible: !visible,
label: this.i18n["term.playpause"],
click: () => {
utils.getWindow().webContents.executeJavaScript("MusicKitInterop.playPause()");
},
},
{
visible: !visible,
label: this.i18n["term.next"],
click: () => {
utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.next()`);
},
},
{
visible: !visible,
label: this.i18n["term.previous"],
click: () => {
utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.previous()`);
},
},
{ type: "separator", visible: !visible },
{
label: visible ? this.i18n["action.tray.minimize"] : `${this.i18n["action.tray.show"]}`,
click: () => {
if (utils.getWindow()) {
if (visible) {
utils.getWindow().hide();
} else {
utils.getWindow().show();
}
}
},
},
{
label: this.i18n["term.quit"],
click: () => {
app.quit();
},
},
]);
this.tray.setContextMenu(menu);
}
/**
* Initializes logging in the application
* @private
*/
private static initLogging() {
log.transports.console.format = "[{h}:{i}:{s}.{ms}] [{level}] {text}";
Object.assign(console, log.functions);
console.debug = function (...args: any[]) {
if (!app.isPackaged) {
log.debug(...args);
}
};
ipcMain.on("fetch-log", (_event) => {
const data = readFileSync(log.transports.file.getFile().path, {
encoding: "utf8",
flag: "r",
});
clipboard.writeText(data);
});
}
/**
* Set login settings
* @private
*/
private static setLoginSettings() {
if (utils.getStoreValue("general.onStartup.enabled")) {
app.setLoginItemSettings({
openAtLogin: true,
path: app.getPath("exe"),
args: [`${utils.getStoreValue("general.onStartup.hidden") ? "--hidden" : ""}`],
});
} else {
app.setLoginItemSettings({
openAtLogin: false,
path: app.getPath("exe"),
});
}
}
}
================================================
FILE: src/main/base/browserwindow.ts
================================================
import AdmZip from "adm-zip";
import { watch } from "chokidar";
import { ShareMenu, app, BrowserWindow as bw, dialog, ipcMain, nativeTheme, screen, shell } from "electron";
import windowStateKeeper from "electron-window-state";
import express from "express";
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "fs";
import getPort from "get-port";
import { LocalFiles } from "../providers/local/index.js";
import mm from "music-metadata";
import fetch from "node-fetch";
import os, { networkInterfaces } from "os";
import { join } from "path";
import { Stream } from "stream";
import { getWallpaper } from "wallpaper";
import { search } from "youtube-search-without-api-key";
import { Plugins } from "./plugins.js";
import { utils } from "./utils.js";
import { wsapi } from "./wsapi.js";
/**
* @file Creates the BrowserWindow
* @author CiderCollective
*/
/** @namespace */
export class BrowserWindow {
public static win: any | undefined = null;
private devMode: boolean = !app.isPackaged;
public static express: any | undefined = null;
private audioStream: any = new Stream.PassThrough();
private headerSent: any = false;
private chromecastIP: any = [];
private clientPort: number = 0;
private remotePort: number = 6942;
private EnvironmentVariables: object = {
env: {
platform: process.platform,
dev: app.isPackaged,
osRelease: os.release(),
updatable: !process.windowsStore || !process.mas,
useV3: utils.getStoreValue("advanced.experiments").includes("ampv3"),
components: [
"pages/podcasts",
"pages/apple-account-settings",
"pages/library-songs",
"pages/library-albums",
"pages/library-artists",
"pages/library-recentlyadded",
"pages/browse",
"pages/groupings",
"pages/charts",
//"pages/installed-themes",
"pages/listen_now",
"pages/radio",
"pages/home",
"pages/artist-feed",
"pages/cider-playlist",
"pages/playlist-inline",
"pages/recordLabel",
"pages/cider-multiroom",
"pages/collection-list",
"pages/apple-curator",
"pages/artist",
"pages/search",
"pages/about",
"pages/library-videos",
"pages/remote-pair",
//"pages/themes-github",
//"pages/plugins-github",
"pages/replay",
"pages/audiolabs",
"pages/zoo",
"pages/plugin-renderer",
"pages/oobe",
"pages/cider-profile",
"components/c2-upgrade",
"components/app-content",
"components/sidebar",
"components/mediaitem-artwork",
"components/artwork-material",
"components/menu-panel",
"components/sidebar-playlist",
"components/audio-settings",
"components/plugin-menu",
"components/audio-controls",
"components/audio-playbackrate",
"components/qrcode-modal",
"components/moreinfo-modal",
"components/equalizer",
"components/add-to-playlist",
"components/queue",
"components/smarthints",
"components/mediaitem-scroller-horizontal",
"components/mediaitem-scroller-horizontal-large",
"components/mediaitem-scroller-horizontal-sp",
"components/mediaitem-scroller-horizontal-mvview",
"components/mediaitem-list-item",
"components/mediaitem-hrect",
"components/mediaitem-square",
"components/mediaitem-mvview",
// "components/libraryartist-item",
"components/listennow-child",
"components/mediaitem-mvview-sp",
"components/animatedartwork-view",
"components/listitem-horizontal",
"components/lyrics-view",
"components/fullscreen",
"components/miniplayer",
"components/castmenu",
"components/pathmenu",
"components/airplay-modal",
"components/artist-chip",
"components/hello-world",
"components/inline-collection-list",
"components/settings-window",
"components/pagination",
"components/settings-keybinds",
"components/settings-themes",
"components/settings-themes-github",
"components/settings-plugins-github",
],
appRoutes: [
{
page: "lzedit",
component: ``,
condition: "$root.page == 'lzedit'",
},
{
page: "library-recentlyadded",
component: ``,
condition: "$root.page == 'library-recentlyadded'",
},
{
page: "plugin-renderer",
component: ``,
condition: "$root.page == 'plugin-renderer'",
},
{
page: "zoo",
component: "",
condition: "$root.page == 'zoo'",
},
{
page: "podcasts",
component: ``,
condition: `$root.page == 'podcasts'`,
},
{
page: "library-videos",
component: ``,
condition: `$root.page == 'library-videos'`,
},
{
page: "apple-account-settings",
component: ``,
condition: `$root.page == 'apple-account-settings'`,
},
{
page: "about",
component: ``,
condition: `$root.page == 'about'`,
},
{
page: "cider-artist",
component: ``,
condition: `$root.page == 'artist-page' && $root.artistPage.data.attributes`,
},
{
page: "collection-list",
component: ``,
condition: `$root.page == 'collection-list'`,
},
{
page: "home",
component: ``,
condition: `$root.page == 'home'`,
},
{
page: "artist-feed",
component: ``,
condition: `$root.page == 'artist-feed'`,
},
{
page: "playlist-inline",
component: ``,
condition: `$root.modals.showPlaylist`,
},
{
page: "playlist_",
component: ``,
condition: `$root.page.includes('playlist_')`,
},
{
page: "album_",
component: ``,
condition: `$root.page.includes('album_')`,
},
{
page: "recordLabel_",
component: ``,
condition: `$root.page.includes('recordLabel_')`,
},
{
page: "social-profiles_",
component: ``,
condition: `$root.page.includes('social-profiles_')`,
},
{
page: "multiroom",
component: ``,
condition: `$root.page.includes('multiroom')`,
},
{
page: "curator_",
component: ``,
condition: `$root.page.includes('curator_')`,
},
{
page: "browsepage",
component: ``,
condition: `$root.page == 'browse'`,
onEnter: ``,
},
{
page: "groupings",
component: ``,
condition: `$root.page == 'groupings'`,
onEnter: ``,
},
{
page: "charts",
component: ``,
condition: `$root.page == 'charts'`,
onEnter: ``,
},
{
page: "listen_now",
component: ``,
condition: `$root.page == 'listen_now'`,
onEnter: ``,
},
{
page: "radio",
component: ``,
condition: `$root.page == 'radio'`,
onEnter: ``,
},
{
page: "settings",
component: ``,
condition: `$root.page == 'settings'`,
},
{
page: "installed-themes",
component: ``,
condition: `$root.page == 'installed-themes'`,
},
{
page: "search",
component: ``,
condition: `$root.page == 'search'`,
},
{
page: "library-songs",
component: ``,
condition: `$root.page == 'library-songs'`,
onEnter: ``,
},
{
page: "library-albums",
component: ``,
condition: `$root.page == 'library-albums'`,
onEnter: ``,
},
{
page: "library-artists",
component: ``,
condition: `$root.page == 'library-artists'`,
onEnter: ``,
},
{
page: "appleCurator",
component: ``,
condition: `$root.page.includes('appleCurator')`,
},
{
page: "themes-github",
component: ``,
condition: `$root.page == 'themes-github'`,
},
{
page: "plugins-github",
component: ``,
condition: `$root.page == 'plugins-github'`,
},
{
page: "remote-pair",
component: ``,
condition: `$root.page == 'remote-pair'`,
},
{
page: "audiolabs",
component: ``,
condition: `$root.page == 'audiolabs'`,
},
{
page: "replay",
component: ``,
condition: `$root.page == 'replay'`,
},
{
page: "keydinds",
component: ``,
condition: `$root.page == 'keybinds-settings'`,
},
],
},
};
private options: any = {
icon: join(utils.getPath("resourcePath"), `icons/icon.` + (process.platform === "win32" ? "ico" : "png")),
width: 1024,
height: 600,
x: undefined,
y: undefined,
minWidth: 900,
minHeight: 390,
frame: false,
title: "Cider",
show: false,
// backgroundColor: "#1E1E1E",
titleBarStyle: "hidden",
trafficLightPosition: { x: 15, y: 20 },
webPreferences: {
experimentalFeatures: true,
nodeIntegration: true,
sandbox: true,
allowRunningInsecureContent: true,
contextIsolation: false,
webviewTag: true,
plugins: true,
nodeIntegrationInWorker: true,
webSecurity: false,
preload: join(utils.getPath("srcPath"), "./preload/cider-preload.js"),
},
};
public static watcher: any;
StartWatcher(path: string) {
BrowserWindow.watcher = watch(path, {
ignored: /[\/\\]\./,
persistent: true,
});
function onWatcherReady() {
console.info("From here can you check for real changes, the initial scan has been completed.");
}
// Declare the listeners of the watcher
BrowserWindow.watcher
.on("add", function (path: string) {
// console.log('File', path, 'has been added');
})
.on("addDir", function (path: string) {
// console.log('Directory', path, 'has been added');
})
.on("change", function (path: string) {
console.log("File", path, "has been changed");
BrowserWindow.win.webContents.send("theme-update", "");
})
.on("unlink", function (path: string) {
// console.log('File', path, 'has been removed');
})
.on("unlinkDir", function (path: string) {
// console.log('Directory', path, 'has been removed');
})
.on("error", function (error: string) {
// console.log('Error happened', error);
})
.on("ready", onWatcherReady)
.on("raw", function (event: any, path: any, details: any) {
// This event should be triggered everytime something happens.
// console.log('Raw event info:', event, path, details);
});
}
async StopWatcher() {
await BrowserWindow.watcher.close();
}
/**
* Creates the browser window
* @generator
* @function createWindow
* @yields {object} Electron browser window
*/
async createWindow(): Promise {
const envPort = process.env?.CIDER_PORT || "9000";
this.clientPort = await getPort({ port: parseInt(envPort, 10) || 9000 });
BrowserWindow.verifyFiles();
this.StartWatcher(utils.getPath("themes"));
// Load the previous state with fallback to defaults
const windowState = windowStateKeeper({
defaultWidth: 1024,
defaultHeight: 600,
fullScreen: false,
});
this.options.width = windowState.width;
this.options.height = windowState.height;
this.options.x = windowState.x;
this.options.y = windowState.y;
switch (process.platform) {
default:
break;
case "win32":
if (!(utils.getStoreValue("visual.transparent") ?? false)) {
this.options.backgroundColor = "#1E1E1E";
} else {
this.options.transparent = true;
}
this.options.autoHideMenuBar = true;
if (utils.getStoreValue("visual.nativeTitleBar")) {
this.options.titleBarStyle = "visible";
this.options.frame = true;
}
break;
case "linux":
this.options.autoHideMenuBar = true;
if (!(utils.getStoreValue("visual.transparent") ?? false)) {
this.options.backgroundColor = "#1E1E1E";
} else {
this.options.transparent = true;
}
if (utils.getStoreValue("visual.nativeTitleBar")) {
this.options.titleBarStyle = "visible";
this.options.frame = true;
}
break;
case "darwin":
this.options.transparent = true;
this.options.vibrancy = "dark";
this.options.hasShadow = true;
break;
}
nativeTheme.themeSource = utils.getStoreValue("visual.overrideDisplayTheme");
// Start the webserver for the browser window to load
// LocalFiles.DB.init()
this.startWebServer();
BrowserWindow.win = new bw(this.options);
// cant be built in CI
// if (process.platform === "win32" && (utils.getStoreValue('visual.transparent') ?? false)) {
// var electronVibrancy = require('electron-vibrancy-updated');
// electronVibrancy.SetVibrancy(BrowserWindow.win, 0);
// }
const ws = new wsapi(BrowserWindow.win);
ws.InitWebSockets();
// and load the renderer.
this.startSession();
this.startHandlers();
// Register listeners on Window to track size and position of the Window.
windowState.manage(BrowserWindow.win);
return BrowserWindow.win;
}
/**
* Verifies the files for the renderer to use (Cache, library info, etc.)
*/
private static verifyFiles(): void {
const expectedDirectories = ["CiderCache"];
const expectedFiles = ["library-songs.json", "library-artists.json", "library-albums.json", "library-playlists.json", "library-recentlyAdded.json"];
for (let i = 0; i < expectedDirectories.length; i++) {
if (!existsSync(join(app.getPath("userData"), expectedDirectories[i]))) {
mkdirSync(join(app.getPath("userData"), expectedDirectories[i]));
}
}
for (let i = 0; i < expectedFiles.length; i++) {
const file = join(join(app.getPath("userData"), "CiderCache"), expectedFiles[i]);
if (!existsSync(file)) {
writeFileSync(file, JSON.stringify([]));
}
}
}
/**
* Starts the webserver for the renderer process.
*/
private startWebServer(): void {
const app = express();
BrowserWindow.express = app;
app.use(express.static(join(utils.getPath("srcPath"), "./renderer/")));
app.set("views", join(utils.getPath("srcPath"), "./renderer/views"));
app.set("view engine", "ejs");
let firstRequest = true;
app.use((req, res, next) => {
if (!req || !req.headers || !req.headers.host || !req.headers["user-agent"]) {
console.error("Req not defined");
return;
}
if (req.url.includes("api") || req.url.includes("audio.wav") || (req.headers.host.includes("localhost") && (this.devMode || req.headers["user-agent"].includes("Electron"))) || req.url.includes("/connect")) {
next();
} else {
res.redirect("https://discord.gg/applemusic");
}
});
app.get("/", (_req, res) => {
res.render("main", this.EnvironmentVariables);
});
app.get("/audio/cideraudio.js", (_req, res) => {
if (existsSync(join(utils.getPath("externals"), "/audio.js"))) {
if (utils.getStoreValue("audio.maikiwiAudio.cloud") == true) {
res.sendFile(join(utils.getPath("externals"), "/cloud/audio.js"));
} else {
res.sendFile(join(utils.getPath("externals"), "/audio.js"));
}
} else {
res.sendFile(join(utils.getPath("srcPath"), "./renderer/audio/audio.js"));
}
});
app.get("/cideraudio/impulses/:file", (req, res) => {
const impulseExternals = join(utils.getPath("externals"), "/impulses/");
const impulseFile = join(impulseExternals, req.params.file);
if (existsSync(impulseFile)) {
res.sendFile(impulseFile);
} else {
res.sendFile(join(utils.getPath("srcPath"), "./renderer/audio/impulses/" + req.params.file));
}
});
app.get("/api/playback/:action", (req, res) => {
const action = req.params.action;
switch (action) {
case "playpause":
BrowserWindow.win.webContents.executeJavaScript("wsapi.togglePlayPause()");
res.send("Play/Pause toggle");
break;
case "play":
BrowserWindow.win.webContents.executeJavaScript("MusicKit.getInstance().play()");
res.send("Playing");
break;
case "pause":
BrowserWindow.win.webContents.executeJavaScript("MusicKit.getInstance().pause()");
res.send("Paused");
break;
case "stop":
BrowserWindow.win.webContents.executeJavaScript("MusicKit.getInstance().stop()");
res.send("Stopped");
break;
case "next":
BrowserWindow.win.webContents.executeJavaScript("if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);}");
res.send("Next");
break;
case "previous":
BrowserWindow.win.webContents.executeJavaScript("if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex);}");
res.send("Previous");
break;
default: {
res.send("Invalid action");
}
}
});
app.get("/themes/:theme", (req, res) => {
const theme = req.params.theme;
const themePath = join(utils.getPath("srcPath"), "./renderer/themes/", theme);
const userThemePath = join(utils.getPath("themes"), theme);
if (existsSync(userThemePath)) {
res.sendFile(userThemePath);
} else if (existsSync(themePath)) {
res.sendFile(themePath);
} else {
res.send(`// Theme not found - ${userThemePath}`);
}
});
app.get("/themes/:theme/*", (req: { params: { theme: string; 0: string } }, res) => {
const theme = req.params.theme;
const file = req.params[0];
const themePath = join(utils.getPath("srcPath"), "./renderer/themes/", theme);
const userThemePath = join(utils.getPath("themes"), theme);
if (existsSync(userThemePath)) {
res.sendFile(join(userThemePath, file));
} else if (existsSync(themePath)) {
res.sendFile(join(themePath, file));
} else {
res.send(`// File not found - ${userThemePath}`);
}
});
app.get("/plugins/:plugin/*", (req: { params: { plugin: string; 0: string } }, res) => {
let plugin = req.params.plugin;
if (Plugins.getPluginFromMap(plugin)) {
plugin = Plugins.getPluginFromMap(plugin);
}
const file = req.params[0];
const pluginPath = join(utils.getPath("plugins"), plugin);
console.log(pluginPath);
if (existsSync(pluginPath)) {
res.sendFile(join(pluginPath, file));
} else {
res.send(`// Plugin not found - ${pluginPath}`);
}
});
app.get("/audio.wav", (req, res) => {
try {
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
if (!this.chromecastIP.includes(ip)) {
this.headerSent = false;
this.audioStream._readableState.buffer.clear();
this.audioStream._readableState.length = 0;
this.chromecastIP.push(ip);
}
req.socket.setTimeout(Number.MAX_SAFE_INTEGER);
// CiderBase.requests.push({req: req, res: res});
// var pos = CiderBase.requests.length - 1;
req.on("close", () => {
console.log("disconnected");
this.headerSent = false;
this.chromecastIP = this.chromecastIP.filter((item: any) => item !== ip);
});
this.audioStream.on("data", (data: any) => {
try {
res.write(data);
} catch (ex) {
console.log(ex);
}
});
} catch (ex) {
console.log(ex);
}
});
//region Connect Integration
app.get("/connect/set-cc-user/:data", (req, res) => {
//utils.getStoreValue('connectUser', JSON.parse()) // [Connect] Save user in store
utils.getWindow().webContents.send("setStoreValue", "connectUser", JSON.parse(req.params.data));
res.redirect(`https://connect.cidercollective.dev/linked.html`);
});
LocalFiles.setupHandlers();
// [Connect] Set auth URL in store for `shell.openExternal`
utils.setStoreValue("cc_authURL", `https://connect.cidercollective.dev/callback/discord?app=cider&appPort=${this.clientPort}`);
console.log(`[Connect] Auth URL: ${utils.getStoreValue("cc_authURL")}`);
//endregion
app.listen(this.clientPort, () => {
console.log(`Cider client port: ${this.clientPort}`);
});
/*
* Remote Client -@quacksire
* https://github.com/ciderapp/Apple-Music-Electron/blob/818189ed40ff600d76eb59d22016723a75885cd5/resources/functions/handler.js#L1173
*/
const remote = express();
remote.use(express.static(join(utils.getPath("srcPath"), "./web-remote/")));
remote.set("views", join(utils.getPath("srcPath"), "./web-remote/views"));
remote.set("view engine", "ejs");
getPort({ port: 6942 }).then((port: number) => {
this.remotePort = port;
// Start Remote Discovery
this.broadcastRemote();
remote.listen(this.remotePort, () => {
console.log(`Cider remote port: ${this.remotePort}`);
firstRequest = false;
});
remote.get("/", (_req, res) => {
res.render("index", this.EnvironmentVariables);
});
});
}
/**
* Starts the session for the renderer process.
*/
private startSession(): void {
// intercept "https://js-cdn.music.apple.com/hls.js/2.141.1/hls.js/hls.js" and redirect to local file "./apple-hls.js" instead
BrowserWindow.win.webContents.session.webRequest.onBeforeRequest(
{
urls: ["https://*/*"],
},
(details: { url: string | string[] }, callback: (arg0: { redirectURL?: string; cancel?: boolean }) => void) => {
if (details.url.includes("hls.js")) {
callback({
redirectURL: `http://localhost:${this.clientPort}/apple-hls.js`,
});
} else if (details.url.includes("ciderlocal") && !details.url.includes("https://apic-desktop.musixmatch.com")) {
let text = details.url.toString().includes("ids=") ? decodeURIComponent(details.url.toString()).split("?ids=")[1] : decodeURIComponent(details.url.toString().substring(details.url.toString().lastIndexOf("/") + 1));
//console.log('localurl',text)
callback({
redirectURL: `http://localhost:${this.clientPort}/ciderlocal/${Buffer.from(text).toString("base64url")}`,
});
} else {
callback({
cancel: false,
});
}
},
);
BrowserWindow.win.webContents.session.webRequest.onBeforeSendHeaders(async (details: { url: string; requestHeaders: { [x: string]: string } }, callback: (arg0: { requestHeaders: any }) => void) => {
if (details.url === "https://buy.itunes.apple.com/account/web/info") {
details.requestHeaders["sec-fetch-site"] = "same-site";
details.requestHeaders["DNT"] = "1";
let itspod = await BrowserWindow.win.webContents.executeJavaScript(`window.localStorage.getItem("music.ampwebplay.itspod")`);
if (itspod != null) details.requestHeaders["Cookie"] = `itspod=${itspod}`;
}
if (details.url.includes("apple.com")) {
details.requestHeaders["DNT"] = "1";
details.requestHeaders["authority"] = "amp-api.music.apple.com";
details.requestHeaders["origin"] = "https://beta.music.apple.com";
details.requestHeaders["referer"] = "https://beta.music.apple.com";
details.requestHeaders["sec-fetch-dest"] = "empty";
details.requestHeaders["sec-fetch-mode"] = "cors";
details.requestHeaders["sec-fetch-site"] = "same-site";
}
if (details.url.startsWith("https://music.163.com")) {
details.requestHeaders["Referer"] = "https://music.163.com/";
details.requestHeaders["user-agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cider/1.0.0 Chrome/96.0.4664.45 Electron/16.0.0 Safari/537.36";
}
if (details.url.includes("https://qq.com")) {
(details.requestHeaders["Accept"] = "*/*"), (details.requestHeaders["Accept-Encoding"] = "gzip, deflate, br"), (details.requestHeaders["Accept-Language"] = "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"), (details.requestHeaders["Referer"] = "https://y.qq.com/"), (details.requestHeaders["User-Agent"] = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X; zh-CN) AppleWebKit/537.51.1 (");
("KHTML, like Gecko) Mobile/17D50 UCBrowser/12.8.2.1268 Mobile AliApp(TUnionSDK/0.1.20.3) ");
}
if (details.url.includes("https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg")) {
(details.requestHeaders["Accept"] = "*/*"), (details.requestHeaders["Accept-Encoding"] = "gzip, deflate, br"), (details.requestHeaders["Accept-Language"] = "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"), (details.requestHeaders["User-Agent"] = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X; zh-CN) AppleWebKit/537.51.1 (");
("KHTML, like Gecko) Mobile/17D50 UCBrowser/12.8.2.1268 Mobile AliApp(TUnionSDK/0.1.20.3) ");
details.requestHeaders["Referer"] = "https://y.qq.com/portal/player.html";
}
callback({ requestHeaders: details.requestHeaders });
});
let location = `http://localhost:${this.clientPort}/`;
if (app.isPackaged) {
BrowserWindow.win.loadURL(location);
} else {
BrowserWindow.win.loadURL(location, {
userAgent: "Cider Development Environment",
});
}
}
/**
* Initializes the window handlers
*/
private startHandlers(): void {
/**********************************************************************************************************************
* ipcMain Events
****************************************************************************************************************** */
ipcMain.handle("mkv3", async (event, args) => {
const options = {
route: "",
token: "",
mediaToken: "",
GETBody: {},
};
Object.assign(options, args);
let res = await fetch(
`https://amp-api.music.apple.com/${options.route}?${new URLSearchParams({
...options.GETBody,
}).toString()}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
authorization: `Bearer ${options.token}`,
path: options.route,
authority: "amp-api.music.apple.com",
"media-user-token": options.mediaToken,
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cider/1.4.2 Chrome/100.0.4896.75 Electron/18.0.3 Safari/537.36",
},
},
);
let json = await res.json();
return json;
});
ipcMain.on("get-wallpaper", async (event, args) => {
const wpPath: string = await getWallpaper();
const Jimp = (await import("jimp")).default;
const img = await Jimp.read(wpPath);
const blurAmount = args.blurAmount ?? 256;
if (blurAmount) {
img.blur(blurAmount);
}
const screens = await screen.getAllDisplays();
const width = screens.reduce((a, b) => a + b.size.width, 0);
const height = screens.reduce((a, b) => a + b.size.height, 0);
img.cover(width, height, Jimp.HORIZONTAL_ALIGN_LEFT | Jimp.VERTICAL_ALIGN_MIDDLE);
const result = await img.getBase64Async(Jimp.MIME_PNG);
event.returnValue = {
path: wpPath,
data: result,
res: {
width: width,
height: height,
},
};
});
ipcMain.handle("uninstall-theme", async (event, path) => {
await this.StopWatcher();
const themesDir = utils.getPath("themes");
// validate the path is in the themes directory
try {
if (path.startsWith(themesDir)) {
// get last dir in path, can be either / or \ and may have a trailing slash
const themeName = path.split(/[\\\/]/).pop();
if (themeName == "Themes" || themeName == "themes") {
BrowserWindow.win.webContents.send("theme-uninstalled", {
path: path,
status: 3,
});
return;
}
// if path is directory, delete it
if (lstatSync(path).isDirectory()) {
await rmdirSync(path, { recursive: true });
} else {
// if path is file, delete it
await unlinkSync(path);
}
// return the path
BrowserWindow.win.webContents.send("theme-uninstalled", {
path: path,
status: 0,
});
} else {
BrowserWindow.win.webContents.send("theme-uninstalled", {
path: path,
status: 1,
});
}
} catch (e: any) {
BrowserWindow.win.webContents.send("theme-uninstalled", {
path: path,
message: e.message,
status: 2,
});
}
this.StartWatcher(utils.getPath("themes"));
});
ipcMain.handle("reinstall-widevine-cdm", () => {
// remove WidevineCDM from appdata folder
const widevineCdmPath = join(app.getPath("userData"), "./WidevineCdm");
if (existsSync(widevineCdmPath)) {
rmSync(widevineCdmPath, { recursive: true, force: true });
}
// reinstall WidevineCDM
app.relaunch();
app.exit();
});
ipcMain.handle("get-github-plugin", async (event, url) => {
await this.StopWatcher();
const returnVal = {
success: true,
theme: null,
message: "",
};
try {
if (!existsSync(utils.getPath("plugins"))) {
mkdirSync(utils.getPath("plugins"));
}
if (url.endsWith("/")) url = url.slice(0, -1);
let response = await utils.fetch(`${url}/archive/refs/heads/main.zip`);
let repo = url.split("/").slice(-2).join("/");
let apiRepo = await utils.fetch(`https://api.github.com/repos/${repo}`).then((res) => res.json()) as { id: number };
console.debug(`REPO ID: ${apiRepo.id}`);
// extract the files from the first folder in the zip response
let zip = new AdmZip(await response.buffer());
let entry = zip.getEntries()[0];
if (!existsSync(join(utils.getPath("plugins"), "gh_" + apiRepo.id))) {
mkdirSync(join(utils.getPath("plugins"), "gh_" + apiRepo.id));
}
console.log(join(utils.getPath("plugins"), "gh_" + apiRepo.id));
zip.extractEntryTo(entry, join(utils.getPath("plugins"), "gh_" + apiRepo.id), false, true);
let commit = await utils.fetch(`https://api.github.com/repos/${repo}/commits`).then((res) => res.json()) as { sha: string }[];
console.debug(`COMMIT SHA: ${commit[0].sha}`);
let theme = JSON.parse(readFileSync(join(utils.getPath("plugins"), "gh_" + apiRepo.id, "package.json"), "utf8"));
theme.id = apiRepo.id;
theme.commit = commit[0].sha;
writeFileSync(join(utils.getPath("plugins"), "gh_" + apiRepo.id, "package.json"), JSON.stringify(theme, null, 4), "utf8");
} catch (e) {
returnVal.success = false;
}
BrowserWindow.win.webContents.send("plugin-installed", returnVal);
this.StartWatcher(utils.getPath("themes"));
});
ipcMain.handle("get-github-theme", async (event, url) => {
await this.StopWatcher();
const returnVal = {
success: true,
theme: null,
message: "",
};
try {
if (!existsSync(utils.getPath("themes"))) {
mkdirSync(utils.getPath("themes"));
}
if (url.endsWith("/")) url = url.slice(0, -1);
let response = await utils.fetch(`${url}/archive/refs/heads/main.zip`);
let repo = url.split("/").slice(-2).join("/");
let apiRepo = await utils
.fetch(`https://api.github.com/repos/${repo}`, {
headers: {
"User-Agent": utils.getWindow().webContents.getUserAgent(),
},
})
.then((res) => res.json()) as { id: number }
console.error(apiRepo);
console.debug(`REPO ID: ${apiRepo.id}`);
// extract the files from the first folder in the zip response
let zip = new AdmZip(await response.buffer());
if (!existsSync(join(utils.getPath("themes"), "gh_" + apiRepo.id))) {
mkdirSync(join(utils.getPath("themes"), "gh_" + apiRepo.id));
}
console.log(join(utils.getPath("themes"), "gh_" + apiRepo.id));
zip.getEntries().forEach((entry) => {
if (entry.entryName.endsWith("/")) return;
let subFolder = entry.entryName.split("/").slice(1, -1).join("/");
zip.extractEntryTo(entry, join(utils.getPath("themes"), "gh_" + apiRepo.id, "/", subFolder), false, true);
});
let commit = await utils.fetch(`https://api.github.com/repos/${repo}/commits`).then((res) => res.json()) as { sha: string }[];
console.debug(`COMMIT SHA: ${commit[0].sha}`);
let theme = JSON.parse(readFileSync(join(utils.getPath("themes"), "gh_" + apiRepo.id, "theme.json"), "utf8"));
theme.id = apiRepo.id;
theme.commit = commit[0].sha;
writeFileSync(join(utils.getPath("themes"), "gh_" + apiRepo.id, "theme.json"), JSON.stringify(theme, null, 4), "utf8");
} catch (e) {
console.error(e);
returnVal.success = false;
}
BrowserWindow.win.webContents.send("theme-installed", returnVal);
this.StartWatcher(utils.getPath("themes"));
BrowserWindow.win.webContents.send("theme-update", "");
});
ipcMain.on("get-themes", (event, _key) => {
if (existsSync(utils.getPath("themes"))) {
let files = readdirSync(utils.getPath("themes"));
let themes = [];
for (let file of files) {
if (file.endsWith(".less")) {
themes.push(file);
} else if (statSync(join(utils.getPath("themes"), file)).isDirectory()) {
let subFiles = readdirSync(join(utils.getPath("themes"), file));
for (let subFile of subFiles) {
if (subFile.endsWith("index.less")) {
themes.push(join(file, subFile));
}
}
}
}
let themeObjects = [];
for (let theme of themes) {
let themePath = join(utils.getPath("themes"), theme);
let themeName = theme;
let themeDescription = "";
if (theme.includes("/")) {
themeName = theme.split("/")[1];
themeDescription = theme.split("/")[0];
}
if (themePath.endsWith("index.less")) {
themePath = themePath.slice(0, -10);
}
if (existsSync(join(themePath, "theme.json"))) {
try {
let themeJson = JSON.parse(readFileSync(join(themePath, "theme.json"), "utf8"));
themeObjects.push({
name: themeJson.name || themeName,
description: themeJson.description || themeDescription,
path: themePath,
file: theme,
github_repo: themeJson.github_repo || "",
commit: themeJson.commit || "",
pack: themeJson.pack || false,
});
} catch (e) {
console.error(e);
}
} else {
themeObjects.push({
name: themeName,
description: themeDescription,
path: themePath,
file: theme,
github_repo: "",
commit: "",
pack: false,
});
}
}
event.returnValue = themeObjects;
} else {
event.returnValue = [];
}
});
ipcMain.handle("open-path", async (event, path) => {
switch (path) {
default:
case "plugins":
if (existsSync(utils.getPath("plugins"))) {
shell.openPath(utils.getPath("plugins"));
} else {
mkdirSync(utils.getPath("plugins"));
shell.openPath(utils.getPath("plugins"));
}
break;
case "userdata":
shell.openPath(app.getPath("userData"));
break;
case "themes":
if (existsSync(utils.getPath("themes"))) {
shell.openPath(utils.getPath("themes"));
} else {
mkdirSync(utils.getPath("themes"));
shell.openPath(utils.getPath("themes"));
}
break;
}
});
ipcMain.on("get-i18n", (event, key) => {
event.returnValue = utils.getLocale(key);
});
ipcMain.on("get-i18n-listing", (event) => {
const translations = utils.i18n;
const i18nListing: any = [];
for (const lang in translations) {
i18nListing.push({
code: lang,
nameNative: translations[lang][0].content["i18n.languageName"] ?? lang,
nameEnglish: translations[lang][0].content["i18n.languageNameEnglish"] ?? lang,
category: translations[lang][0].content["i18n.category"] ?? "",
authors: translations[lang][0].content["i18n.authors"] ?? "",
});
}
event.returnValue = i18nListing;
});
ipcMain.on("get-gpu-mode", (event) => {
event.returnValue = process.platform;
});
ipcMain.on("get-port", (event) => {
event.returnValue = this.clientPort;
});
ipcMain.on("is-dev", (event) => {
event.returnValue = this.devMode;
});
ipcMain.handle("put-cache", (_event, arg) => {
writeFileSync(join(join(app.getPath("userData"), "CiderCache"), `${arg.file}.json`), arg.data);
});
ipcMain.on("get-cache", (event, arg) => {
let read = "";
if (existsSync(join(join(app.getPath("userData"), "CiderCache"), `${arg}.json`))) {
read = readFileSync(join(join(app.getPath("userData"), "CiderCache"), `${arg}.json`), "utf8");
}
event.returnValue = read;
});
ipcMain.handle("getYTLyrics", async (_event, track, artist) => {
const u = track + " " + artist + " official video";
return await search(u);
});
ipcMain.on("close", (_event) => {
BrowserWindow.win.close();
});
ipcMain.on("maximize", (_event) => {
// listen for maximize event
if (BrowserWindow.win.isMaximized()) {
BrowserWindow.win.unmaximize();
} else {
BrowserWindow.win.maximize();
}
});
ipcMain.on("unmaximize", () => {
// listen for maximize event
BrowserWindow.win.unmaximize();
});
ipcMain.on("minimize", () => {
// listen for minimize event
BrowserWindow.win.minimize();
});
// Set scale
ipcMain.on("setScreenScale", (_event, scale) => {
BrowserWindow.win.webContents.setZoomFactor(parseFloat(scale));
});
ipcMain.on("windowmin", (_event, width, height) => {
BrowserWindow.win.setMinimumSize(width, height);
});
ipcMain.on("windowontop", (_event, ontop) => {
BrowserWindow.win.setAlwaysOnTop(ontop);
});
// Set scale
ipcMain.on("windowresize", (_event, width, height, lock = false) => {
BrowserWindow.win.setContentSize(width, height);
BrowserWindow.win.setResizable(!lock);
});
// Move window
ipcMain.on("windowmove", (_event, x, y) => {
BrowserWindow.win.setBounds({ x, y });
});
// Override light, dark
ipcMain.on("changeDisplayTheme", (event, theme) => {
nativeTheme.themeSource = theme;
});
//Fullscreen
ipcMain.on("setFullScreen", (_event, flag) => {
BrowserWindow.win.setFullScreen(flag);
});
//Fullscreen
ipcMain.on("getFullScreen", (event, flag) => {
event.returnValue = BrowserWindow.win.isFullScreen();
});
//Fullscreen
ipcMain.on("detachDT", (_event, _) => {
BrowserWindow.win.webContents.openDevTools({ mode: "detach" });
});
ipcMain.handle("relaunchApp", (_event, _) => {
const opt: Electron.RelaunchOptions = {};
opt.args = process.argv.slice(1).concat(["--relaunch"]);
opt.execPath = process.execPath;
if (app.isPackaged && process.env.PORTABLE_EXECUTABLE_FILE != undefined) {
opt.execPath = process.env.PORTABLE_EXECUTABLE_FILE;
} else if (app.isPackaged && process.env.APPIMAGE != undefined) {
opt.execPath = process.env.APPIMAGE;
opt.args.unshift("--appimage-extract-and-run");
} else if (app.isPackaged && process.env.CHROME_DESKTOP != undefined && process.env.PLATFORM == "Linux") {
opt.execPath = "cider";
}
app.relaunch(opt);
app.quit();
});
ipcMain.handle("quit-app", (_event, _) => {
app.quit();
});
ipcMain.on("play", (_event, type, id) => {
BrowserWindow.win.webContents.executeJavaScript(`
MusicKit.getInstance().setQueue({ ${type}: '${id}', parameters : {l : app.mklang}}).then(function(queue) {
MusicKit.getInstance().play();
});
`);
});
// ipcMain.handle("scanLibrary", async (event, folders) => {
// // const oldmetadatalist = await LocalFiles.sendOldLibrary();
// // BrowserWindow.win.webContents.send("getUpdatedLocalList", oldmetadatalist);
// const metadatalist = await LocalFiles.scanLibrary();
// BrowserWindow.win.webContents.send("getUpdatedLocalList", metadatalist);
// LocalFiles.localSongs = metadatalist;
// // LocalFiles.cleanUpDB();
// });
LocalFiles.eventEmitter.on("newtracks", (data) => {
BrowserWindow.win.webContents.send("getUpdatedLocalList", data);
});
ipcMain.on("writeWAV", (event, leftpcm, rightpcm, bufferlength) => {
function interleave16(leftChannel: any, rightChannel: any) {
var length = leftChannel.length + rightChannel.length;
var result = new Int16Array(length);
var inputIndex = 0;
for (var index = 0; index < length;) {
result[index++] = leftChannel[inputIndex];
result[index++] = rightChannel[inputIndex];
inputIndex++;
}
return result;
}
//https://github.com/HSU-ANT/jsdafx
function quantization(audiobufferleft: any, audiobufferright: any) {
let h = Float32Array.from([1]);
let nsState = new Array(0);
let ditherstate = new Float32Array(0);
let qt = Math.pow(2, 1 - 16);
//noise shifting order 3
h = Float32Array.from([1.623, -0.982, 0.109]);
for (let i = 0; i < nsState.length; i++) {
nsState[i] = new Float32Array(h.length);
}
function setChannelCount(nc: any) {
if (ditherstate.length !== nc) {
ditherstate = new Float32Array(nc);
}
if (nsState.length !== nc) {
nsState = new Array(nc);
for (let i = 0; i < nsState.length; i++) {
nsState[i] = new Float32Array(h.length);
}
}
}
function hpDither(channel: any) {
const rnd = Math.random() - 0.5;
const d = rnd - ditherstate[channel];
ditherstate[channel] = rnd;
return d;
}
setChannelCount(2);
const inputs = [audiobufferleft, audiobufferright];
const outputs = [audiobufferleft, audiobufferright];
for (let channel = 0; channel < inputs.length; channel++) {
const inputData = inputs[channel];
const outputData = outputs[channel];
for (let sample = 0; sample < bufferlength; sample++) {
let input = inputData[sample];
// console.log('a2',inputData.length);
for (let i = 0; i < h.length; i++) {
input -= h[i] * nsState[channel][i];
}
// console.log('a3',input);
let d_rand = 0.0;
// ditherstate = new Float32Array(h.length);
// d_rand = hpDither(channel);
const tmpOutput = qt * Math.round(input / qt + d_rand);
for (let i = h.length - 1; i >= 0; i--) {
nsState[channel][i] = nsState[channel][i - 1];
}
nsState[channel][0] = tmpOutput - input;
outputData[sample] = tmpOutput;
}
}
return outputs;
}
function convert(n: any) {
var v = n < 0 ? n * 32768 : n * 32767; // convert in range [-32768, 32767]
return Math.max(-32768, Math.min(32768, v)); // clamp
}
function bitratechange(e: any) {
var t = e.length;
let sampleRate = 96.0;
let outputSampleRate = 48.0;
var s = 0,
o = sampleRate / outputSampleRate,
u = Math.ceil((t * outputSampleRate) / sampleRate),
a = new Int16Array(u);
for (let i = 0; i < u; i++) {
a[i] = e[Math.floor(s)];
s += o;
}
return a;
}
let newaudio = quantization(leftpcm, rightpcm);
//let newaudio = [leftpcm, rightpcm];
// console.log(newaudio.length);
const pcmData = Buffer.from(new Uint8Array(interleave16(
bitratechange(Int16Array.from(newaudio[0], (x) => convert(x))),
bitratechange(Int16Array.from(newaudio[1], (x) => convert(x)))
).buffer));
if (!this.headerSent) {
console.log("new header");
const header = Buffer.alloc(44);
header.write("RIFF", 0);
header.writeUInt32LE(2147483600, 4);
header.write("WAVE", 8);
header.write("fmt ", 12);
header.writeUInt8(16, 16);
header.writeUInt8(1, 20);
header.writeUInt8(2, 22);
header.writeUInt32LE(48000, 24);
header.writeUInt32LE(16, 28);
header.writeUInt8(4, 32);
header.writeUInt8(16, 34);
header.write("data", 36);
header.writeUInt32LE(2147483600 + 44 - 8, 40);
this.audioStream.write(Buffer.concat([header, pcmData]));
this.headerSent = true;
} else {
this.audioStream.write(pcmData);
}
});
//QR Code
ipcMain.handle("showQR", async (_event, _) => {
//macOS
let url = `http://${BrowserWindow.getIP()}:${this.remotePort}`;
BrowserWindow.win.webContents.send("send-remote-pair-url", `https://cider.sh/remote/pair?url=${Buffer.from(encodeURI(url)).toString("base64")}`.toString());
});
ipcMain.on("get-remote-pair-url", (_event, _) => {
// Linux and Windows
let url = `http://${BrowserWindow.getIP()}:${this.remotePort}`;
//if (app.isPackaged) {
BrowserWindow.win.webContents.send("send-remote-pair-url", `https://cider.sh/remote/pair?url=${Buffer.from(encodeURI(url)).toString("base64")}`.toString());
//} else {
// BrowserWindow.win.webContents.send('send-remote-pair-url', (`http://127.0.0.1:5500/pair-remote.html?url=${Buffer.from(encodeURI(url)).toString('base64')}`).toString());
//}
});
if (process.platform === "darwin") {
//macOS
app.setUserActivity(
"com.CiderCollective.remote.pair",
{
ip: `${BrowserWindow.getIP()}`,
},
`http://${BrowserWindow.getIP()}:${this.remotePort}`,
);
}
// Get previews for normalization
ipcMain.on("getPreviewURL", (_event, url) => {
fetch(url)
.then((res) => res.buffer())
.then(async (buffer) => {
const metadata = await mm.parseBuffer(buffer, "audio/x-m4a");
let SoundCheckTag = metadata.native.iTunes[1].value;
console.debug("sc", SoundCheckTag);
BrowserWindow.win.webContents.send("SoundCheckTag", SoundCheckTag);
})
.catch((err) => {
console.log(err);
});
});
ipcMain.on("share-menu", async (_event, url) => {
if (process.platform !== "darwin") return;
//https://www.electronjs.org/docs/latest/api/share-menu
console.log("[Share Sheet - App.ts]", url);
const options = {
title: "Share",
urls: [url],
};
const shareMenu = new ShareMenu(options);
shareMenu.popup();
});
ipcMain.on("get-version", (_event) => {
if (app.isPackaged) {
_event.returnValue = app.getVersion();
} else {
_event.returnValue = `Experimental running on Electron ${app.getVersion()}`;
}
});
ipcMain.on("open-appdata", (_event) => {
shell.openPath(app.getPath("userData"));
});
ipcMain.handle("folderSelector", async (_event) => {
let u = await dialog.showOpenDialog({
properties: ["openDirectory", "multiSelections"],
});
return u.filePaths;
});
//#region Cider Connect
ipcMain.on("cc-auth", (_event) => {
shell.openExternal(String(utils.getStoreValue("cc_authURL")));
});
ipcMain.on("auth-window", (_event) => {
AuthWindow(BrowserWindow.win);
});
function AuthWindow(win: bw) {
// create a BrowserWindow
const authWindow = new bw({
width: 500,
height: 600,
show: false,
titleBarOverlay: {
color: "#1d1d1f",
symbolColor: "#ffffff",
},
titleBarStyle: "hidden",
darkTheme: true,
resizable: false,
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
sandbox: true,
allowRunningInsecureContent: true,
webSecurity: false,
preload: join(utils.getPath("srcPath"), "./preload/cider-preload.js"),
nodeIntegrationInWorker: false,
experimentalFeatures: true,
},
});
// authWindow.webContents.openDevTools();
// remove all local storage data
authWindow.webContents.session.clearStorageData();
// set user agent
authWindow.webContents.setUserAgent(`Mozilla/5.0 (Macintosh; Intel Mac OS X 13_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15`);
// show the window
authWindow.loadURL("https://beta.music.apple.com/");
const cookieKeys = ["itspod", "pltvcid", "pldfltcid", "itua", "media-user-token", "acn1", "dslang"];
ipcMain.on("auth-window-ready", async (_event) => {
authWindow.show();
});
ipcMain.on("auth-completed", async (_event) => {
const cookies = await getCookies();
console.log("cookies", cookies);
win.webContents.send("recv-cookies", cookies);
authWindow.close();
});
const overlayStyling = `
.hehehe {
position: fixed;
top:0;
left:0;
width: 100px;
height: 100px;
background: #1d1d1f;
z-index: 99999;
}
.titlebar {
height: 30px;
position: fixed;
top:0;
left:0;
right:0;
-webkit-app-region: drag;
z-index: 99999;
}`;
// on content loaded
authWindow.webContents.on("did-finish-load", () => {
authWindow.webContents.executeJavaScript(`
let tOut = setInterval(async ()=>{
try {
if(typeof MusicKit === 'undefined') return;
MusicKit.getInstance().addEventListener(MusicKit.Events.authorizationStatusDidChange, ()=>{
if(MusicKit.getInstance().isAuthorized) {
ipcRenderer.send('auth-completed')
}
})
clearInterval(tOut)
}catch(e) {}
}, 500)
let tOut2 = setInterval(()=>{
try {
const el = document.querySelector('.signin')
if(el) {
el.click()
ipcRenderer.send('auth-window-ready')
clearInterval(tOut2)
}
}catch(e) {}
}, 500)
let styling = \`${overlayStyling}\`;
(()=>{
const titleBarEl = document.createElement('div')
const overlayEl = document.createElement('div')
titleBarEl.classList.add('titlebar')
overlayEl.classList.add('hehehe')
const styleTag = document.createElement('style')
styleTag.innerHTML = styling
document.head.appendChild(styleTag)
document.body.appendChild(overlayEl)
document.body.appendChild(titleBarEl)
})()
`);
});
async function getCookies(): Promise<{ [key: string]: string }> {
return new Promise((res, rej) => {
authWindow.webContents.session.cookies
.get({})
.then((cookies) => {
// for each cookie
const toRenderer: {
[key: string]: string;
} = {};
for (let i = 0; i < cookieKeys.length; i++) {
const key = cookieKeys[i];
// find the cookie
const cookie = cookies.find((cookie) => cookie.name === key);
// if cookie exists
if (cookie) {
toRenderer[`music.ampwebplay.${cookie.name}`] = cookie.value;
}
}
res(toRenderer);
})
.catch((error) => {
console.log(error);
rej();
});
});
}
}
ipcMain.on("cc-logout", (_event) => {
//Make sure to update the default store
utils.setStoreValue("connectUser", {
auth: null,
sync: {
themes: false,
plugins: false,
settings: false,
},
});
utils.getWindow().reload();
});
ipcMain.on("cc-push", (_event) => {
utils.pushStoreToConnect();
});
/* *********************************************************************************************
* Window Events
* **********************************************************************************************/
let WND_STATE = {
MINIMIZED: 0,
NORMAL: 1,
MAXIMIZED: 2,
FULL_SCREEN: 3,
};
let wndState = WND_STATE.NORMAL;
const win = BrowserWindow.win;
let isQuitting = false;
win.on("resize", (_: any) => {
const isMaximized = win.isMaximized();
const isMinimized = win.isMinimized();
const isFullScreen = win.isFullScreen();
const state = wndState;
if (isMinimized && state !== WND_STATE.MINIMIZED) {
wndState = WND_STATE.MINIMIZED;
win.webContents.send("window-state-changed", "minimized");
} else if (isFullScreen && state !== WND_STATE.FULL_SCREEN) {
wndState = WND_STATE.FULL_SCREEN;
win.webContents.send("window-state-changed", "fullscreen");
} else if (isMaximized && state !== WND_STATE.MAXIMIZED) {
wndState = WND_STATE.MAXIMIZED;
win.webContents.send("window-state-changed", "maximized");
win.webContents.executeJavaScript(`app.chrome.maximized = true`);
} else if (state !== WND_STATE.NORMAL) {
wndState = WND_STATE.NORMAL;
win.webContents.send("window-state-changed", "normal");
win.webContents.executeJavaScript(`app.chrome.maximized = false`);
}
});
win.on("close", async (e: any) => {
if ((process.platform === "darwin" || utils.getStoreValue("general.close_button_hide")) && !isQuitting) {
e.preventDefault();
win.hide();
} else {
await win.webContents.executeJavaScript(`
window.localStorage.setItem("currentTrack", JSON.stringify(app.mk.nowPlayingItem));
window.localStorage.setItem("currentTime", JSON.stringify(app.mk.currentPlaybackTime));
window.localStorage.setItem("currentQueue", JSON.stringify(app.mk.queue._unplayedQueueItems));
ipcRenderer.send('stopGCast','');
MusicKit.getInstance().stop();
`);
}
});
app.on("before-quit", () => {
isQuitting = true;
});
app.on("activate", function () {
win.show();
});
// Quit when all windows are closed.
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
// Set window Handler
BrowserWindow.win.webContents.setWindowOpenHandler((x: any) => {
if (x.url.includes("apple.com") || x.url.includes("localhost")) {
return { action: "allow" };
}
shell.openExternal(x.url).catch(console.error);
return { action: "deny" };
});
}
/**
* Gets ip
* @private
*/
private static getIP(): string {
let ip: string = "";
let ip2: any = [];
let alias = 0;
const ifaces: any = networkInterfaces();
for (let dev in ifaces) {
ifaces[dev].forEach((details: any) => {
if (details.family === "IPv4" && !details.internal) {
if (!/(loopback|vmware|internal|hamachi|vboxnet|virtualbox)/gi.test(dev + (alias ? ":" + alias : ""))) {
if (details.address.substring(0, 8) === "192.168." || details.address.substring(0, 7) === "172.16." || details.address.substring(0, 3) === "10.") {
if (!ip.startsWith("192.168.") || (String(ip2).startsWith("192.168.") && !ip.startsWith("192.168.") && String(ip2).startsWith("172.16.") && !ip.startsWith("192.168.") && !ip.startsWith("172.16.")) || (String(ip2).startsWith("10.") && !ip.startsWith("192.168.") && !ip.startsWith("172.16.") && !ip.startsWith("10."))) {
ip = details.address;
}
++alias;
}
}
}
});
}
return ip;
}
/**
* Broadcast the remote to the IP
* @private
*/
private async broadcastRemote() {
const myString = `http://${BrowserWindow.getIP()}:${this.remotePort}`;
const mdns = (await import("mdns-js")).default;
const encoded = Buffer.from(myString).toString("base64");
const x = mdns.tcp("cider-remote");
const txt_record = {
Ver: "131077",
DvSv: "3689",
DbId: "D41D8CD98F00B205",
DvTy: "Cider",
OSsi: "0x212F0",
txtvers: "1",
CtlN: "Cider",
iV: "196623",
};
let server2 = mdns.createAdvertisement(x, `${await getPort({ port: 3839 })}`, {
name: encoded,
txt: txt_record,
});
server2.start();
console.log("remote broadcasted");
}
}
================================================
FILE: src/main/base/castcontroller.ts
================================================
// @ts-nocheck
import castv2Cli from "castv2-client";
const RequestResponseController = castv2Cli.RequestResponseController;
export class CiderCastController extends RequestResponseController {
constructor(client: string, sourceId: string, destinationId: string) {
super(client, sourceId, destinationId, "urn:x-cast:com.ciderapp.customdata");
this.once("close", onclose);
var self = this;
function onclose() {
self.stop();
}
}
sendIp(ip: string) {
// TODO: Implement Callback
let data = {
ip: ip,
};
this.request(data);
}
kill() {
// TODO: Implement Callback
let data = {
action: "stop",
};
this.request(data);
}
}
================================================
FILE: src/main/base/castreceiver.ts
================================================
// @ts-nocheck
import castv2Cli from "castv2-client";
import { CiderCastController } from "./castcontroller.js";
const Application = castv2Cli.Application;
const MediaController = castv2Cli.MediaController;
export class CiderReceiver extends Application {
// FE96A351
// 27E1334F
public APP_ID = "FE96A351";
constructor(_client: unknown, _session: unknown) {
super();
super.apply(this, arguments);
this.media = this.createController(MediaController);
this.mediaReceiver = this.createController(CiderCastController);
this.media.on("status", onstatus);
var self = this;
function onstatus(status: string) {
self.emit("status", status);
}
}
getStatus(callback: unknown) {
this.media.getStatus.apply(this.media, arguments);
}
load(media: unknown, options: unknown, callback: unknown) {
this.media.load.apply(this.media, arguments);
}
play(callback: unknown) {
this.media.play.apply(this.media, arguments);
}
pause(callback: unknown) {
this.media.pause.apply(this.media, arguments);
}
stop(callback: unknown) {
this.media.stop.apply(this.media, arguments);
}
seek(currentTime: unknown, callback: unknown) {
this.media.seek.apply(this.media, arguments);
}
queueLoad(items: unknown, options: unknown, callback: unknown) {
this.media.queueLoad.apply(this.media, arguments);
}
queueInsert(items: unknown, options: unknown, callback: unknown) {
this.media.queueInsert.apply(this.media, arguments);
}
queueRemove(itemIds: unknown, options: unknown, callback: unknown) {
this.media.queueRemove.apply(this.media, arguments);
}
queueReorder(itemIds: unknown, options: unknown, callback: unknown) {
this.media.queueReorder.apply(this.media, arguments);
}
queueUpdate(items: unknown, callback: unknown) {
this.media.queueUpdate.apply(this.media, arguments);
}
sendIp(opts: unknown) {
this.mediaReceiver.sendIp.apply(this.mediaReceiver, arguments);
}
kill(opts: unknown) {
this.mediaReceiver.kill.apply(this.mediaReceiver, arguments);
}
}
================================================
FILE: src/main/base/plugins.ts
================================================
import {app} from "electron";
import { existsSync, lstatSync, readdirSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { utils } from "./utils.js";
//
// Hello, this is our loader for the various plugins that the Cider Development Team built for our
// numerous plugins internally and ones made by the community
//
// To learn how to make your own, visit https://github.com/ciderapp/Cider/wiki/Plugins
//
/**
* @class
* Plugin Loading
* @author booploops#7139
* @see {@link https://github.com/ciderapp/Cider/wiki/Plugins|Documentation}
*/
export class Plugins {
private static PluginMap: any = {};
private basePluginsPath = join(dirname(fileURLToPath(import.meta.url)), "../plugins");
private userPluginsPath = join(app.getPath("userData"), "Plugins");
private readonly pluginsList: any = {};
constructor() {
this.pluginsList = this.getPlugins();
}
public static getPluginFromMap(plugin: string): any {
if (Plugins.PluginMap[plugin]) {
return Plugins.PluginMap[plugin];
} else {
return plugin;
}
}
public getPlugins(): any {
let plugins: any = {};
if (existsSync(this.basePluginsPath)) {
readdirSync(this.basePluginsPath).forEach(async (file) => {
if (file.endsWith(".ts") || file.endsWith(".js")) {
const plugin = (await import(join(this.basePluginsPath, file))).default;
if (plugins[file] || plugin.name in plugins) {
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
} else {
plugins[file] = new plugin(utils);
}
}
});
}
if (existsSync(this.userPluginsPath)) {
readdirSync(this.userPluginsPath).forEach(async (file) => {
// Plugins V1
if (file.endsWith(".ts") || file.endsWith(".js")) {
if (!app.isPackaged) {
const plugin = (await import(join(this.userPluginsPath, file))).default;
file = file.replace(".ts", "").replace(".js", "");
if (plugins[file] || plugin in plugins) {
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
} else {
plugins[file] = new plugin(utils);
}
} else {
const plugin = await import(join(this.userPluginsPath, file));
file = file.replace(".ts", "").replace(".js", "");
if (plugins[file] || plugin in plugins) {
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
} else {
plugins[file] = new plugin(utils);
}
}
}
// Plugins V2
else if (lstatSync(join(this.userPluginsPath, file)).isDirectory()) {
const pluginPath = join(this.userPluginsPath, file);
if (existsSync(join(pluginPath, "package.json"))) {
const pluginPackage = await import(join(pluginPath, "package.json"));
const plugin = await import(join(pluginPath, pluginPackage.main));
if (plugins[plugin.name] || plugin.name in plugins) {
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
} else {
Plugins.PluginMap[pluginPackage.name] = file;
const pluginEnv = {
app: app,
store: utils.getStore(),
utils: utils,
win: utils.getWindow(),
dir: pluginPath,
dirName: file,
express: utils.getExpress(),
};
plugins[plugin.name] = new plugin(pluginEnv);
}
}
}
});
}
console.log("[PluginHandler] Loaded plugins:", Object.keys(plugins));
return plugins;
}
public callPlugins(event: string, ...args: any[]) {
for (const plugin in this.pluginsList) {
if (this.pluginsList[plugin][event]) {
try {
this.pluginsList[plugin][event](...args);
} catch (e) {
console.error(`[${plugin}] An error was encountered: ${e}`);
console.error(e);
}
}
}
}
public callPlugin(plugin: string, event: string, ...args: any[]) {
if (this.pluginsList[plugin][event]) {
this.pluginsList[plugin][event](...args);
}
}
}
================================================
FILE: src/main/base/store.ts
================================================
import ElectronStore from "electron-store";
import { app, ipcMain } from "electron";
import fetch from "node-fetch";
export class Store {
static cfg: ElectronStore;
private defaults = {
main: {
PLATFORM: process.platform,
UPDATABLE: app.isPackaged && (!process.mas || !process.windowsStore || !process.env.FLATPAK_ID),
},
general: {
close_button_hide: false,
language: "en_US",
playbackNotifications: true,
resumeOnStartupBehavior: "local",
privateEnabled: false,
themeUpdateNotification: true,
sidebarItems: {
recentlyAdded: true,
songs: true,
albums: true,
artists: true,
videos: true,
podcasts: true,
},
sidebarCollapsed: {
cider: false,
applemusic: false,
library: false,
amplaylists: false,
playlists: false,
localLibrary: false,
},
onStartup: {
enabled: false,
hidden: false,
},
resumeTabs: {
tab: "home",
dynamicData: "",
},
keybindings: {
search: ["CommandOrControl", "F"],
listnow: ["CommandOrControl", "L"],
browse: ["CommandOrControl", "B"],
recentAdd: ["CommandOrControl", "G"],
songs: ["CommandOrControl", "J"],
albums: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "A"],
artists: ["CommandOrControl", "D"],
togglePrivateSession: ["CommandOrControl", "P"],
webRemote: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "W"],
audioSettings: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "A"],
pluginMenu: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "P"],
castToDevices: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "C"],
settings: [
"CommandOrControl", // Who the hell uses a different key for this? Fucking Option?
",",
],
zoomn: ["Control", "numadd"],
zoomt: ["Control", "numsub"],
zoomrst: ["Control", "num0"],
openDeveloperTools: ["CommandOrControl", "Shift", "I"],
},
showLovedTracksInline: true,
},
connectivity: {
discord_rpc: {
enabled: true,
client: "Cider",
activity: {
state_format: "by {artist}",
details_format: "{title}",
hide_timestamp: false,
buttons: {
enabled: true,
first: "listenOnCider",
second: "viewOnAppleMusic",
options: ["listenOnCider", "viewOnAppleMusic", "viewOnOtherMusicServices"],
},
},
clear_on_pause: true,
},
lastfm: {
enabled: false,
scrobble_after: 50,
filter_loop: false,
filter_types: {},
remove_featured: true,
secrets: {
username: "",
key: "",
},
},
},
home: {
followedArtists: [],
favoriteItems: [],
},
libraryPrefs: {
songs: {
scroll: "paged",
sort: "name",
sortOrder: "asc",
size: "normal",
},
albums: {
scroll: "paged",
sort: "name",
sortOrder: "asc",
viewAs: "covers",
},
playlists: {
scroll: "infinite",
},
localPaths: [],
pageSize: 250,
},
audio: {
volume: 1,
volumeStep: 0.01,
maxVolume: 1,
lastVolume: 1,
muted: false,
playbackRate: 1,
quality: "HIGH",
seamless_audio: true,
normalization: true,
dBSPL: false,
dBSPLcalibration: 90,
maikiwiAudio: {
ciderPPE: true,
ciderPPE_value: "MAIKIWI",
staticOptimizer: {
state: false,
lock: false,
},
opportunisticCorrection_state: "OFF",
atmosphereRealizer1: false,
atmosphereRealizer1_value: "NATURAL_STANDARD",
atmosphereRealizer2: false,
atmosphereRealizer2_value: "NATURAL_STANDARD",
spatial: false,
spatialProfile: "BPLK",
vibrantBass: {
// Hard coded into the app. Don't include any of this config into exporting presets in store.ts
frequencies: [17.182, 42.169, 53.763, 112.69, 119.65, 264.59, 336.57, 400.65, 505.48, 612.7, 838.7, 1155.3, 1175.6, 3406.8, 5158.6, 5968.1, 6999.9, 7468.6, 8862.9, 9666, 10109],
Q: [2.5, 0.388, 5, 5, 2.5, 7.071, 14.14, 10, 7.071, 14.14, 8.409, 0.372, 7.071, 10, 16.82, 7.071, 28.28, 20, 8.409, 40, 40],
gain: [-0.34, 2.49, 0.23, -0.49, 0.23, -0.12, 0.32, -0.29, 0.33, 0.19, -0.18, -1.27, -0.11, 0.25, -0.18, -0.53, 0.34, 1.32, 1.78, 0.41, -0.28],
},
cloud: false,
},
spatial: false,
spatial_properties: {
presets: [],
gain: 0.8,
listener_position: [0, 0, 0],
audio_position: [0, 0, 0],
room_dimensions: {
width: 32,
height: 12,
depth: 32,
},
room_materials: {
left: "metal",
right: "metal",
front: "brick-bare",
back: "brick-bare",
down: "acoustic-ceiling-tiles",
up: "acoustic-ceiling-tiles",
},
},
equalizer: {
preset: "default",
frequencies: [32, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
gain: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
Q: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
mix: 1,
vibrantBass: 0,
presets: [],
userGenerated: false,
},
},
visual: {
theme: "",
styles: [],
scrollbars: 0, // 0 = show on hover, 2 = always hide, 3 = always show
refresh_rate: 0,
window_background_style: "none", // "none", "artwork", "color"
animated_artwork: "limited", // 0 = always, 1 = limited, 2 = never
animated_artwork_qualityLevel: 1,
bg_artwork_rotation: false,
hw_acceleration: "default", // default, webgpu, disabled
showuserinfo: true,
transparent: false,
miniplayer_top_toggle: true,
directives: {
windowLayout: "twopanel",
},
windowControlPosition: 0, // 0 default right
nativeTitleBar: false,
windowColor: "#000000",
customAccentColor: false,
accentColor: "#fc3c44",
purplePodcastPlaybackBar: false,
maxElementScale: -1, // -1 default, anything else is a custom scale
overrideDisplayTheme: "system", // system , dark, light
artworkDisplayLayout: "default",
},
lyrics: {
enable_mxm: true,
mxm_karaoke: false,
mxm_language: "disabled",
enable_qq: false,
enable_yt: false,
},
advanced: {
AudioContext: true,
experiments: [],
playlistTrackMapping: true,
ffmpegLocation: "",
disableLogging: true,
},
connectUser: {
auth: null,
sync: {
themes: false,
plugins: false,
settings: false,
},
},
musickit: {
"stored-attributes": {
autoplayEnabled: "",
},
},
};
private migrations = {};
constructor() {
Store.cfg = new ElectronStore({
name: "cider-config",
defaults: this.defaults,
migrations: this.migrations,
clearInvalidConfig: false, //disabled for now
});
Store.cfg.set(this.mergeStore(this.defaults, Store.cfg.store));
this.ipcHandler();
}
static pushToCloud(): void {
if (Store.cfg.get("connectUser.auth") === null) return;
var syncData = Object();
if (Store.cfg.get("connectUser.sync.themes")) {
syncData.push({
themes: Store.cfg.store.themes,
});
}
if (Store.cfg.get("connectUser.sync.plugins")) {
syncData.push({
plugins: Store.cfg.store.plugins,
});
}
if (Store.cfg.get("connectUser.sync.settings")) {
syncData.push({
general: Store.cfg.get("general"),
home: Store.cfg.get("home"),
libraryPrefs: Store.cfg.get("libraryPrefs"),
advanced: Store.cfg.get("advanced"),
});
}
let postBody = {
id: Store.cfg.get("connectUser.id"),
app: app.getName(),
version: app.isPackaged ? app.getVersion() : "dev",
syncData: syncData,
};
fetch("https://connect.cidercollective.dev/api/v1/setttings/set", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(postBody),
});
}
/**
* Merge Configurations
* @param target The target configuration
* @param source The source configuration
*/
private mergeStore = (target: { [x: string]: any }, source: { [x: string]: any }) => {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (const key of Object.keys(source)) {
if (key.includes("migrations")) {
continue;
}
if (source[key] instanceof Array) {
continue;
}
if (source[key] instanceof Object) Object.assign(source[key], this.mergeStore(target[key], source[key]));
}
// Join `target` and modified `source`
Object.assign(target || {}, source);
return target;
};
/**
* IPC Handler
*/
private ipcHandler(): void {
ipcMain.handle("getStoreValue", (_event, key, defaultValue) => {
return defaultValue ? Store.cfg.get(key, true) : Store.cfg.get(key);
});
ipcMain.handle("setStoreValue", (_event, key, value) => {
Store.cfg.set(key, value);
});
ipcMain.on("getStore", (event) => {
event.returnValue = Store.cfg.store;
});
ipcMain.on("setStore", (_event, store) => {
Store.cfg.store = store;
});
}
}
================================================
FILE: src/main/base/utils.ts
================================================
import { BrowserWindow, app, ipcMain } from "electron";
import ElectronStore from "electron-store";
import fetch from "node-fetch";
import { readFileSync } from "node:fs";
import { join, resolve,dirname } from "node:path";
import { BrowserWindow as bw } from "./browserwindow.js";
import { Store } from "./store.js";
import { fileURLToPath } from "node:url";
export class utils {
static hash = "fda9a6528649ea90dee35390wog"
static i18n: any = {};
/**
* Playback Functions
*/
static playback = {
pause: () => {
bw.win.webContents.executeJavaScript("MusicKitInterop.pause()");
},
play: () => {
bw.win.webContents.executeJavaScript("MusicKitInterop.play()");
},
playPause: () => {
bw.win.webContents.executeJavaScript("MusicKitInterop.playPause()");
},
next: () => {
bw.win.webContents.executeJavaScript("MusicKitInterop.next()");
},
previous: () => {
bw.win.webContents.executeJavaScript("MusicKitInterop.previous()");
},
seek: (seconds: number) => {
bw.win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${seconds})`);
},
};
/**
* Paths for the application to use
*/
static paths: any = {
srcPath: join(dirname(fileURLToPath(import.meta.url)), "../../src"),
rendererPath: join(dirname(fileURLToPath(import.meta.url)), "../../src/renderer"),
mainPath: join(dirname(fileURLToPath(import.meta.url)), "../../src/main"),
resourcePath: join(dirname(fileURLToPath(import.meta.url)), "../../resources"),
ciderCache: resolve(app.getPath("userData"), "CiderCache"),
themes: resolve(app.getPath("userData"), "Themes"),
plugins: resolve(app.getPath("userData"), "Plugins"),
externals: resolve(app.getPath("userData"), "externals"),
};
/**
* Get the path
* @returns {string}
* @param name
*/
static getPath(name: string): string {
return this.paths[name];
}
/**
* Get the app
* @returns {Electron.App}
*/
static getApp(): Electron.App {
return app;
}
/**
* Get the IPCMain
*/
static getIPCMain(): Electron.IpcMain {
return ipcMain;
}
/*
* Get the Express instance
* @returns {any}
*/
static getExpress(): any {
return bw.express;
}
/**
* MitM the electron fetch for a function that proxies github.
* Written in TS so Maikiwi doesn't fuck up
*/
static async fetch(url: string, opts: object = {}) {
Object.assign(opts, {
headers: {
"User-Agent": utils.getWindow().webContents.getUserAgent(),
},
});
if (this.getStoreValue("advanced.experiments").includes("cider_mirror") === true) {
if (url.includes("api.github.com/")) {
return await fetch(url.replace("api.github.com/", "mirror.api.cider.sh/v2/api/"), opts);
} else if (url.includes("raw.githubusercontent.com/")) {
return await fetch(url.replace("raw.githubusercontent.com/", "mirror.api.cider.sh/v2/raw/"), opts);
} else {
return await fetch(url, opts);
}
} else {
return await fetch(url, opts);
}
}
static async initializeTranslations() {
const otaClient = (await import('@crowdin/ota-client')).default.default;
const crowdin = new otaClient(this.hash)
this.i18n = await crowdin.getTranslations();
}
/**
* Fetches the i18n locale for the given language.
* @param language {string} The language to fetch the locale for.
* @param key {string} The key to search for.
* @returns {string | Object} The locale value.
*/
static getLocale(language: string, key?: string): string | object {
let i18n: any = {};
if (!this.i18n[language]) {
i18n = this.i18n["en-US"][0].content;
} else {
i18n = this.i18n[language ?? "en-US"][0].content;
}
if (key) {
return i18n[key];
} else {
return i18n;
}
}
/**
* Gets a store value
* @param key
* @returns store value
*/
static getStoreValue(key: string): any {
return Store.cfg.get(key);
}
/**
* Sets a store
* @returns store
*/
static getStore(): Object {
return Store.cfg.store;
}
/**
* Get the store instance
* @returns {Store}
*/
static getStoreInstance(): ElectronStore {
return Store.cfg;
}
/**
* Sets a store value
* @param key
* @param value
*/
static setStoreValue(key: string, value: any): void {
Store.cfg.set(key, value);
}
/**
* Pushes Store to Connect
* @return Function
*/
static pushStoreToConnect(): Function {
return Store.pushToCloud;
}
/**
* Gets the browser window
*/
static getWindow(): Electron.BrowserWindow {
if (bw.win) {
return bw.win;
} else {
return BrowserWindow.getAllWindows()[0];
}
}
static loadPluginFrontend(path: string): void {}
static loadJSFrontend(path: string): void {
bw.win.webContents.executeJavaScript(readFileSync(path, "utf8"));
}
}
================================================
FILE: src/main/base/vcomponents.json
================================================
[
"pages/podcasts",
"pages/apple-account-settings",
"pages/library-songs",
"pages/library-albums",
"pages/library-artists",
"pages/browse",
"pages/groupings",
"pages/installed-themes",
"pages/listen_now",
"pages/radio",
"pages/home",
"pages/artist-feed",
"pages/cider-playlist",
"pages/playlist-inline",
"pages/recordLabel",
"pages/cider-multiroom",
"pages/collection-list",
"pages/apple-curator",
"pages/artist",
"pages/search",
"pages/about",
"pages/library-videos",
"pages/remote-pair",
"pages/themes-github",
"pages/plugins-github",
"pages/replay",
"pages/audiolabs",
"pages/zoo",
"pages/plugin-renderer",
"pages/keybinds",
"pages/oobe",
"components/mediaitem-artwork",
"components/artwork-material",
"components/menu-panel",
"components/sidebar-playlist",
"components/audio-settings",
"components/plugin-menu",
"components/audio-controls",
"components/audio-playbackrate",
"components/qrcode-modal",
"components/moreinfo-modal",
"components/equalizer",
"components/add-to-playlist",
"components/smarthints",
"components/queue",
"components/mediaitem-scroller-horizontal",
"components/mediaitem-scroller-horizontal-large",
"components/mediaitem-scroller-horizontal-sp",
"components/mediaitem-scroller-horizontal-mvview",
"components/mediaitem-list-item",
"components/mediaitem-hrect",
"components/mediaitem-square",
"components/mediaitem-mvview",
"components/listennow-child",
"components/mediaitem-mvview-sp",
"components/animatedartwork-view",
"components/listitem-horizontal",
"components/lyrics-view",
"components/fullscreen",
"components/miniplayer",
"components/castmenu",
"components/pathmenu",
"components/airplay-modal",
"components/artist-chip",
"components/hello-world",
"components/inline-collection-list"
]
================================================
FILE: src/main/base/vrouting.json
================================================
[
{
"page": "plugin-renderer",
"component": "",
"condition": "page == 'plugin-renderer'"
},
{
"page": "zoo",
"component": "",
"condition": "page == 'zoo'"
},
{
"page": "podcasts",
"component": "",
"condition": "page == 'podcasts'"
},
{
"page": "library-videos",
"component": "",
"condition": "page == 'library-videos'"
},
{
"page": "apple-account-settings",
"component": "",
"condition": "page == 'apple-account-settings'"
},
{
"page": "about",
"component": "",
"condition": "page == 'about'"
},
{
"page": "cider-artist",
"component": "",
"condition": "page == 'artist-page' && artistPage.data.attributes"
},
{
"page": "collection-list",
"component": "",
"condition": "page == 'collection-list'"
},
{
"page": "home",
"component": "",
"condition": "page == 'home'"
},
{
"page": "artist-feed",
"component": "",
"condition": "page == 'artist-feed'"
},
{
"page": "playlist-inline",
"component": "",
"condition": "modals.showPlaylist"
},
{
"page": "playlist_",
"component": "",
"condition": "page.includes('playlist_')"
},
{
"page": "oobe",
"component": "",
"condition": "page == 'oobe'"
},
{
"page": "album_",
"component": "",
"condition": "page.includes('album_')"
},
{
"page": "social-profiles_",
"component": "",
"condition": "$root.page.includes('social-profiles_')"
},
{
"page": "recordLabel_",
"component": "",
"condition": "page.includes('recordLabel_')"
},
{
"page": "multiroom",
"component": "",
"condition": "page.includes('multiroom')"
},
{
"page": "curator_",
"component": "",
"condition": "page.includes('curator_')"
},
{
"page": "browsepage",
"component": "",
"condition": "page == 'browse'",
"onEnter": ""
},
{
"page": "groupings",
"component": "",
"condition": "page == 'groupings'",
"onEnter": ""
},
{
"page": "charts",
"component": "",
"condition": "page == 'charts'",
"onEnter": ""
},
{
"page": "listen_now",
"component": "",
"condition": "page == 'listen_now'",
"onEnter": ""
},
{
"page": "radio",
"component": "",
"condition": "page == 'radio'",
"onEnter": ""
},
{
"page": "settings",
"component": "",
"condition": "page == 'settings'"
},
{
"page": "installed-themes",
"component": "",
"condition": "page == 'installed-themes'"
},
{
"page": "search",
"component": "",
"condition": "page == 'search'"
},
{
"page": "library-songs",
"component": "",
"condition": "page == 'library-songs'",
"onEnter": ""
},
{
"page": "library-albums",
"component": "",
"condition": "page == 'library-albums'",
"onEnter": ""
},
{
"page": "library-artists",
"component": "",
"condition": "page == 'library-artists'",
"onEnter": ""
},
{
"page": "appleCurator",
"component": "",
"condition": "page.includes('appleCurator')"
},
{
"page": "themes-github",
"component": "",
"condition": "page == 'themes-github'"
},
{
"page": "plugins-github",
"component": "",
"condition": "page == 'plugins-github'"
},
{
"page": "remote-pair",
"component": "",
"condition": "page == 'remote-pair'"
},
{
"page": "audiolabs",
"component": "",
"condition": "page == 'audiolabs'"
},
{
"page": "replay",
"component": "",
"condition": "page == 'replay'"
}
]
================================================
FILE: src/main/base/wsapi.ts
================================================
import WebSocket, { WebSocketServer } from 'ws';
import electron from "electron";
interface standardResponse {
status?: Number;
message?: String;
data?: any;
type?: string;
}
export class wsapi {
static clients: any;
port: any = 26369;
wss: any = null;
clients: any = [];
private _win: any;
constructor(win: any) {
this._win = win;
}
createId() {
// create random guid
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
public async InitWebSockets() {
electron.ipcMain.on("wsapi-updatePlaybackState", (_event: any, arg: any) => {
this.updatePlaybackState(arg);
});
electron.ipcMain.on("wsapi-returnQueue", (_event: any, arg: any) => {
this.returnQueue(JSON.parse(arg));
});
electron.ipcMain.on("wsapi-returnSearch", (_event: any, arg: any) => {
console.log("SEARCH");
this.returnSearch(JSON.parse(arg));
});
electron.ipcMain.on("wsapi-returnSearchLibrary", (_event: any, arg: any) => {
this.returnSearchLibrary(JSON.parse(arg));
});
electron.ipcMain.on("wsapi-returnDynamic", (_event: any, arg: any, type: any) => {
this.returnDynamic(JSON.parse(arg), type);
});
electron.ipcMain.on("wsapi-returnMusicKitApi", (_event: any, arg: any, method: any) => {
this.returnMusicKitApi(JSON.parse(arg), method);
});
electron.ipcMain.on("wsapi-returnLyrics", (_event: any, arg: any) => {
this.returnLyrics(JSON.parse(arg));
});
electron.ipcMain.on("wsapi-returnvolumeMax", (_event: any, arg: any) => {
this.returnmaxVolume(JSON.parse(arg));
});
electron.ipcMain.on("wsapi-libraryStatus", (_event: any, inLibrary: boolean, rating: number) => {
this.returnLibraryStatus(inLibrary, rating);
});
electron.ipcMain.on("wsapi-rate", (_event: any, kind: string, id: string, rating: number) => {
this.returnRatingStatus(kind, id, rating);
});
electron.ipcMain.on("wsapi-change-library", (_event: any, kind: string, id: string, shouldAdd: boolean) => {
this.returnLibraryChange(kind, id, shouldAdd);
});
this.wss = new WebSocketServer({
port: this.port,
perMessageDeflate: {
zlibDeflateOptions: {
// See zlib defaults.
chunkSize: 1024,
memLevel: 7,
level: 3,
},
zlibInflateOptions: {
chunkSize: 10 * 1024,
},
// Other options settable:
clientNoContextTakeover: true, // Defaults to negotiated value.
serverNoContextTakeover: true, // Defaults to negotiated value.
serverMaxWindowBits: 10, // Defaults to negotiated value.
// Below options specified as default values.
concurrencyLimit: 10, // Limits zlib concurrency for perf.
threshold: 1024, // Size (in bytes) below which messages
// should not be compressed if context takeover is disabled.
},
});
console.log(`WebSocketServer started on port: ${this.port}`);
const defaultResponse: standardResponse = {
status: 0,
data: {},
message: "OK",
type: "generic",
};
this.wss.on("connection", (ws: any) => {
ws.id = this.createId();
console.log(`Client ${ws.id} connected`);
this.clients.push(ws);
ws.on("message", function incoming(_message: any) {});
// ws on message
ws.on("message", (message: any) => {
let data = JSON.parse(message);
let response: standardResponse = {
status: 0,
data: {},
message: "OK",
type: "generic",
};
if (data.action) {
data.action.toLowerCase();
}
switch (data.action) {
default:
response.message = "Action not found";
break;
case "identify":
response.message = "Thanks for identifying!";
response.data = {
id: ws.id,
};
ws.identity = {
name: data.name,
author: data.author,
description: data.description,
version: data.version,
};
break;
case "play-next":
this._win.webContents.executeJavaScript(`wsapi.playNext(\`${data.type}\`,\`${data.id}\`)`);
response.message = "Play Next";
break;
case "play-later":
this._win.webContents.executeJavaScript(`wsapi.playLater(\`${data.type}\`,\`${data.id}\`)`);
response.message = "Play Later";
break;
case "quick-play":
this._win.webContents.executeJavaScript(`wsapi.quickPlay(\`${data.term}\`)`);
response.message = "Quick Play";
break;
case "get-lyrics":
this._win.webContents.executeJavaScript(`wsapi.getLyrics()`);
break;
case "shuffle":
this._win.webContents.executeJavaScript(`wsapi.toggleShuffle()`);
break;
case "set-shuffle":
if (data.shuffle == true) {
this._win.webContents.executeJavaScript(`MusicKit.getInstance().shuffleMode = 1`);
} else {
this._win.webContents.executeJavaScript(`MusicKit.getInstance().shuffleMode = 0`);
}
break;
case "repeat":
this._win.webContents.executeJavaScript(`wsapi.toggleRepeat()`);
break;
case "set-repeat":
if (data.repeat === 0 || data.repeat === 1 || data.repeat === 2) {
this._win.webContents.executeJavaScript(`MusicKit.getInstance().repeatMode = ${data.repeat}`);
response.message = "Repeat " + data.repeat;
} else {
this._win.webContents.executeJavaScript(`wsapi.toggleRepeat()`);
response.message = "Invalid Repeat, toggling";
}
break;
case "seek":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${parseFloat(data.time)})`);
response.message = "Seek";
break;
case "pause":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().pause()`);
response.message = "Paused";
break;
case "playpause":
this._win.webContents.executeJavaScript(`MusicKitInterop.playPause()`);
response.message = "Play/Pause";
break;
case "play":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().play()`);
response.message = "Playing";
break;
case "stop":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().stop()`);
response.message = "Stopped";
break;
case "volumeMax":
this._win.webContents.executeJavaScript(`wsapi.getmaxVolume()`);
response.message = "maxVolume";
break;
case "volume":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().volume = ${parseFloat(data.volume)}`);
response.message = "Volume";
break;
case "mute":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().mute()`);
response.message = "Muted";
break;
case "unmute":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().unmute()`);
response.message = "Unmuted";
break;
case "next":
this._win.webContents.executeJavaScript(`MusicKitInterop.next()`);
response.message = "Next";
break;
case "previous":
this._win.webContents.executeJavaScript(`MusicKitInterop.previous()`);
response.message = "Previous";
break;
case "musickit-api":
this._win.webContents.executeJavaScript(`wsapi.musickitApi(\`${data.method}\`, \`${data.id}\`, ${JSON.stringify(data.params)} , ${data.library})`);
break;
case "musickit-library-api":
break;
case "set-autoplay":
this._win.webContents.executeJavaScript(`wsapi.setAutoplay(${data.autoplay})`);
break;
case "queue-move":
this._win.webContents.executeJavaScript(`wsapi.moveQueueItem(${data.from},${data.to})`);
break;
case "get-queue":
this._win.webContents.executeJavaScript(`wsapi.getQueue()`);
break;
case "search":
if (!data.limit) {
data.limit = 10;
}
this._win.webContents.executeJavaScript(`wsapi.search(\`${data.term}\`, \`${data.limit}\`)`);
break;
case "library-search":
if (!data.limit) {
data.limit = 10;
}
this._win.webContents.executeJavaScript(`wsapi.searchLibrary(\`${data.term}\`, \`${data.limit}\`)`);
break;
case "show-window":
this._win.show();
break;
case "hide-window":
this._win.hide();
break;
case "play-mediaitem":
this._win.webContents.executeJavaScript(`wsapi.playTrackById("${data.id}", \`${data.kind}\`)`);
response.message = "Playing track";
break;
case "get-status":
response.data = {
isAuthorized: true,
};
response.message = "Status";
break;
case "get-currentmediaitem":
this._win.webContents.executeJavaScript(`wsapi.getPlaybackState()`);
break;
case "library-status":
this._win.webContents.executeJavaScript(`wsapi.getLibraryStatus("${data.type}", "${data.id}")`);
break;
case "rating":
this._win.webContents.executeJavaScript(`wsapi.rate("${data.type}", "${data.id}", ${data.rating})`);
break;
case "change-library":
this._win.webContents.executeJavaScript(`wsapi.changeLibrary("${data.type}", "${data.id}", ${data.add})`);
break;
case "quit":
electron.app.quit();
break;
}
ws.send(JSON.stringify(response));
});
ws.on("close", () => {
// remove client from list
this.clients.splice(wsapi.clients.indexOf(ws), 1);
console.log(`Client ${ws.id} disconnected`);
});
ws.send(JSON.stringify(defaultResponse));
});
}
sendToClient(_id: any) {
// replace the clients.forEach with a filter to find the client that requested
}
updatePlaybackState(attr: any) {
const response: standardResponse = {
status: 0,
data: attr,
message: "OK",
type: "playbackStateUpdate",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnMusicKitApi(results: any, method: any) {
const response: standardResponse = {
status: 0,
data: results,
message: "OK",
type: `musickitapi.${method}`,
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnDynamic(results: any, type: any) {
const response: standardResponse = {
status: 0,
data: results,
message: "OK",
type: type,
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnLyrics(results: any) {
const response: standardResponse = {
status: 0,
data: results,
message: "OK",
type: "lyrics",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnSearch(results: any) {
const response: standardResponse = {
status: 0,
data: results,
message: "OK",
type: "searchResults",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnSearchLibrary(results: any) {
const response: standardResponse = {
status: 0,
data: results,
message: "OK",
type: "searchResultsLibrary",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnQueue(queue: any) {
const response: standardResponse = {
status: 0,
data: queue,
message: "OK",
type: "queue",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnmaxVolume(vol: any) {
const response: standardResponse = {
status: 0,
data: vol,
message: "OK",
type: "maxVolume",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnLibraryStatus(inLibrary: boolean, rating: number) {
const response: standardResponse = {
status: 0,
data: {
inLibrary,
rating,
},
message: "OK",
type: "libraryStatus",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnRatingStatus(kind: string, id: string, rating: number) {
const response: standardResponse = {
status: 0,
data: { kind, id, rating },
message: "OK",
type: "rate",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
returnLibraryChange(kind: string, id: string, shouldAdd: boolean) {
const response: standardResponse = {
status: 0,
data: { kind, id, add: shouldAdd },
message: "OK",
type: "change-library",
};
this.clients.forEach(function each(client: any) {
client.send(JSON.stringify(response));
});
}
}
================================================
FILE: src/main/index.ts
================================================
// @ts-ignore
await import("v8-compile-cache");
import { app, components, ipcMain } from "electron";
import { join } from "path";
import { Store } from "./base/store.js";
import { AppEvents } from "./base/app.js";
import { Plugins } from "./base/plugins.js";
import { BrowserWindow } from "./base/browserwindow.js";
import { utils } from "./base/utils.js";
const appName = 'sh.cider.classic';
if (!app.isPackaged) {
app.setPath('userData', join(app.getPath('appData'), `${appName}.dev`));
} else {
app.setPath('userData', join(app.getPath('appData'), appName));
}
new Store();
const Cider = new AppEvents();
const CiderPlug = new Plugins();
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* App Event Handlers
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
app.on("ready", async () => {
await utils.initializeTranslations();
Cider.ready(CiderPlug);
console.log("[Cider] Application is Ready. Creating Window.");
if (!app.isPackaged) {
console.info("[Cider] Running in development mode.");
// @ts-ignore
(await import("vue-devtools")).default.install();
}
components.whenReady().then(async () => {
const bw = new BrowserWindow();
console.log("[Cider] Creating Window.");
const win = await bw.createWindow();
app.getGPUInfo("complete").then((gpuInfo) => {
console.log(gpuInfo);
});
console.log("[Cider][Widevine] Status:", components.status());
Cider.bwCreated();
win.on("ready-to-show", () => {
console.debug("[Cider] Window is Ready.");
CiderPlug.callPlugins("onReady", win);
if (!app.commandLine.hasSwitch("hidden")) {
win.show();
}
});
});
});
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Renderer Event Handlers
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
let rendererInitialized = false;
ipcMain.handle("renderer-ready", (event) => {
if (rendererInitialized) return;
CiderPlug.callPlugins("onRendererReady", event);
rendererInitialized = true;
});
ipcMain.on("playbackStateDidChange", (_event, attributes) => {
CiderPlug.callPlugins("onPlaybackStateDidChange", attributes);
});
ipcMain.on("nowPlayingItemDidChange", (_event, attributes) => {
CiderPlug.callPlugins("onNowPlayingItemDidChange", attributes);
});
ipcMain.on("playbackTimeDidChange", (_event, attributes) => {
CiderPlug.callPlugins("playbackTimeDidChange", attributes);
});
app.on("before-quit", () => {
CiderPlug.callPlugins("onBeforeQuit");
console.warn(`${app.getName()} exited.`);
});
================================================
FILE: src/main/plugins/chromecast.ts
================================================
import electron from "electron";
import os from "os";
import { CiderReceiver } from "../base/castreceiver.js";
import MediaRendererClient from "upnp-mediarenderer-client";
import request from "request";
// @ts-expect-error
import castv2 from "castv2-client";
import mdnsjs from "mdns-js";
export default class ChromecastPlugin {
/**
* Private variables for interaction in plugins
*/
private _win: any;
private _app: any;
private _lastfm: any;
private _store: any;
private _timer: any;
private audioClient = castv2.Client;
private mdns = mdnsjs;
private devices: any = [];
private castDevices: any = [];
// private GCRunning = false;
// private GCBuffer: any;
// private expectedConnections = 0;
// private currentConnections = 0;
private activeConnections: any = [];
// private requests = [];
// private GCstream = new Stream.PassThrough(),
private connectedHosts: any = {};
private connectedPlayer: any;
private ciderPort: any = 9000;
private scanCount: any = 0;
// private server = false;
// private bufcount = 0;
// private bufcount2 = 0;
// private headerSent = false;
private async searchForGCDevices() {
try {
let browser = this.mdns.createBrowser(this.mdns.tcp("googlecast"));
browser.on("ready", browser.discover);
browser.on("update", (service: any) => {
if (service.addresses && service.fullname && service.fullname.includes("_googlecast._tcp")) {
let a = service.txt.filter((u: any) => String(u).startsWith("fn="));
let name = (a[0] ?? "").substring(3) != "" ? (a[0] ?? "").substring(3) : service.fullname.substring(0, service.fullname.indexOf("._googlecast"));
this.ondeviceup(service.addresses[0], name + " (" + (service.type[0]?.description ?? "") + ")", "", "googlecast");
}
});
const Client = (await import("node-ssdp")).Client;
// also do a SSDP/UPnP search
let ssdpBrowser = new Client();
ssdpBrowser.on("response", (headers: any, statusCode: any, rinfo: any) => {
var location = getLocation(headers);
if (location != null) {
this.getServiceDescription(location, rinfo.address);
}
});
function getLocation(headers: any) {
let location = null;
if (headers["LOCATION"] != null) {
location = headers["LOCATION"];
} else if (headers["Location"] != null) {
location = headers["Location"];
}
return location;
}
ssdpBrowser.search("urn:dial-multiscreen-org:device:dial:1");
// actual upnp devices
let ssdpBrowser2 = new Client();
ssdpBrowser2.on("response", (headers: any, statusCode: any, rinfo: any) => {
var location = getLocation(headers);
if (location != null) {
this.getServiceDescription(location, rinfo.address);
}
});
ssdpBrowser2.search("urn:schemas-upnp-org:device:MediaRenderer:1");
} catch (e) {
console.log("Search GC err", e);
}
}
private getServiceDescription(url: any, address: any) {
request.get(url, (error: any, response: any, body: any) => {
if (!error && response.statusCode === 200) {
this.parseServiceDescription(body, address, url);
}
});
}
private ondeviceup(host: any, name: any, location: any, type: any) {
if (this.castDevices.findIndex((item: any) => item.host === host && item.name === name && item.location === location && item.type === type) === -1) {
this.castDevices.push({
name: name,
host: host,
location: location,
type: type,
});
if (this.devices.indexOf(host) === -1) {
this.devices.push(host);
}
if (name) {
this._win.webContents.executeJavaScript(`console.log('deviceFound','ip: ${host} name:${name}')`).catch((err: any) => console.error(err));
console.log("deviceFound", host, name);
}
} else {
this._win.webContents.executeJavaScript(`console.log('deviceFound (added)','ip: ${host} name:${name}')`).catch((err: any) => console.error(err));
console.log("deviceFound (added)", host, name);
}
}
private async parseServiceDescription(body: any, address: any, url: any) {
const parseString = (await import("xml2js")).parseString;
parseString(body, (err: any, result: any) => {
if (!err && result && result.root && result.root.device) {
const device = result.root.device[0];
console.log("device", device);
let devicetype = "googlecast";
console.log();
if (device.deviceType && device.deviceType.toString() === "urn:schemas-upnp-org:device:MediaRenderer:1") {
devicetype = "upnp";
}
this.ondeviceup(address, device.friendlyName.toString(), url, devicetype);
}
});
}
private loadMedia(client: any, song: any, artist: any, album: any, albumart: any, cb?: any) {
// const u = 'http://' + this.getIp() + ':' + server.address().port + '/';
// const DefaultMediaReceiver : any = require('castv2-client').DefaultMediaReceiver;
client.launch(CiderReceiver, (err: any, player: any) => {
if (err) {
console.log(err);
return;
}
let media = {
// Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
contentId: "http://" + this.getIp() + ":" + this.ciderPort + "/audio.wav",
contentType: "audio/wav",
streamType: "LIVE", // or LIVE
// Title and cover displayed while buffering
metadata: {
type: 0,
metadataType: 3,
title: song ?? "",
albumName: album ?? "",
artist: artist ?? "",
images: [{ url: albumart ?? "" }],
},
};
player.on("status", (status: any) => {
console.log("status broadcast playerState=%s", status);
});
console.log('app "%s" launched, loading media %s ...', player, media);
player.load(
media,
{
autoplay: true,
},
(err: any, status: any) => {
console.log("media loaded playerState=%s", status);
},
);
client.getStatus((x: any, status: any) => {
if (status && status.volume) {
client.volume = status.volume.level;
client.muted = status.volume.muted;
client.stepInterval = status.volume.stepInterval;
}
});
// send websocket ip
player.sendIp("ws://" + this.getIp() + ":26369");
electron.ipcMain.on("stopGCast", (_event) => {
player.kill();
});
electron.app.on("before-quit", (_event) => {
player.kill();
});
});
}
private getIp() {
let ip: string = "";
let ip2: any = [];
let alias = 0;
const ifaces: any = os.networkInterfaces();
for (let dev in ifaces) {
ifaces[dev].forEach((details: any) => {
if (details.family === "IPv4" && !details.internal) {
if (!/(loopback|vmware|internal|hamachi|vboxnet|virtualbox)/gi.test(dev + (alias ? ":" + alias : ""))) {
if (details.address.substring(0, 8) === "192.168." || details.address.substring(0, 7) === "172.16." || details.address.substring(0, 3) === "10.") {
if (!ip.startsWith("192.168.") || (ip2.startsWith("192.168.") && !ip.startsWith("192.168.") && ip2.startsWith("172.16.") && !ip.startsWith("192.168.") && !ip.startsWith("172.16.")) || (ip2.startsWith("10.") && !ip.startsWith("192.168.") && !ip.startsWith("172.16.") && !ip.startsWith("10."))) {
ip = details.address;
}
++alias;
}
}
}
});
}
return ip;
}
private stream(device: any, song: any, artist: any, album: any, albumart: any) {
let castMode = "googlecast";
let UPNPDesc = "";
castMode = device.type;
UPNPDesc = device.location;
let client;
if (castMode === "googlecast") {
let client = new this.audioClient();
client.volume = 100;
client.stepInterval = 0.5;
client.muted = false;
client.connect(device.host, () => {
// console.log('connected, launching app ...', 'http://' + this.getIp() + ':' + server.address().port + '/');
if (!this.connectedHosts[device.host]) {
this.connectedHosts[device.host] = client;
this.activeConnections.push(client);
}
this.loadMedia(client, song, artist, album, albumart);
});
client.on("close", () => {
console.info("Client Closed");
for (let i = this.activeConnections.length - 1; i >= 0; i--) {
if (this.activeConnections[i] === client) {
this.activeConnections.splice(i, 1);
return;
}
}
});
client.on("error", (err: any) => {
console.log("Error: %s", err.message);
client.close();
delete this.connectedHosts[device.host];
});
} else {
// upnp devices
try {
let client = new MediaRendererClient(UPNPDesc);
const options = {
autoplay: true,
contentType: "audio/x-wav",
dlnaFeatures: "DLNA.ORG_PN=-;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01700000000000000000000000000000",
metadata: {
title: "Cider",
creator: "Streaming ...",
type: "audio", // can be 'video', 'audio' or 'image'
// url: 'http://' + getIp() + ':' + server.address().port + '/',
// protocolInfo: 'DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000;
},
};
client.load("http://" + this.getIp() + ":" + this.ciderPort + "/audio.wav", options, function (err: any, _result: any) {
if (err) throw err;
console.log("playing ...");
});
if (!this.connectedHosts[device.host]) {
this.connectedHosts[device.host] = client;
this.activeConnections.push(client);
}
} catch (e) { }
}
}
private async setupGCServer() {
return "";
}
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "Chromecast";
public description: string = "LastFM plugin for Cider";
public version: string = "0.0.1";
public author: string = "vapormusic / Cider Collective";
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(utils: { getApp: () => any; getStore: () => any }) {
this._app = utils.getApp();
this._store = utils.getStore();
}
/**
* Runs on app ready
*/
onReady(win: any): void {
this._win = win;
electron.ipcMain.on("getKnownCastDevices", (event) => {
event.returnValue = this.castDevices;
});
electron.ipcMain.on("performGCCast", (event, device, song, artist, album, albumart) => {
// this.setupGCServer().then( () => {
this._win.webContents.setAudioMuted(true);
console.log(device);
this.stream(device, song, artist, album, albumart);
// })
});
electron.ipcMain.on("getChromeCastDevices", (_event, _data) => {
if (this.scanCount++ == 2) {
this.scanCount = 0;
this.castDevices = [];
}
this.searchForGCDevices();
});
electron.ipcMain.on("stopGCast", (_event) => {
this._win.webContents.setAudioMuted(false);
this.activeConnections.forEach((client: any) => {
try {
client.stop();
} catch (e) { }
});
this.activeConnections = [];
this.connectedHosts = {};
});
}
/**
* Runs on app stop
*/
onBeforeQuit(): void { }
/**
* Runs on song change
* @param attributes Music Attributes
*/
onNowPlayingItemDidChange(attributes: any): void { }
onRendererReady(): void {
this._win.webContents.executeJavaScript(`ipcRenderer.sendSync('get-port')`).then((result: any) => {
this.ciderPort = result;
});
}
}
================================================
FILE: src/main/plugins/discordrpc.ts
================================================
import { AutoClient } from "discord-auto-rpc";
import { ipcMain } from "electron";
import fetch from "node-fetch";
export default class DiscordRPC {
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "Discord Rich Presence";
public description: string = "Discord RPC plugin for Cider";
public version: string = "1.1.0";
public author: string = "vapormusic/Core/cryptofyre (Cider Collective)";
/**
* Private variables for interaction in plugins
*/
private _utils: any;
private _attributes: any;
private ready: boolean = false;
/**
* Plugin Initialization
*/
private _client: any = null;
private _activityCache: any = {
details: "",
state: "",
largeImageKey: "",
largeImageText: "",
smallImageKey: "",
smallImageText: "",
instance: false,
};
/*******************************************************************************************
* Public Methods
* ****************************************************************************************/
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(utils: any) {
this._utils = utils;
console.debug(`[Plugin][${this.name}] Loading Complete.`);
}
/**
* Runs on app ready
*/
onReady(_win: any): void {
this.connect();
console.debug(`[Plugin][${this.name}] Ready.`);
}
/**
* Set up ipc listeners for the plugin
*/
onRendererReady() {
const self = this;
ipcMain.on("discordrpc:updateImage", async (_event, artworkUrl) => {
if (this._utils.getStoreValue("general.privateEnabled")) return;
fetch("https://api.cider.sh/v1/images", {
method: "POST",
headers: {
"User-Agent": this._utils.getWindow().webContents.getUserAgent(),
url: artworkUrl,
},
})
.then(async (res) => {
const json = await res.json() as { imageUrl: string };
self._activityCache.largeImageKey = "https://images.weserv.nl/?url=" + json.imageUrl + "&w=1024&h=1024&output=jpg";
self._client.setActivity(self._activityCache);
});
});
ipcMain.on("discordrpc:reload", (_event, configUpdate = null) => {
console.log(`[DiscordRPC][reload] Reloading DiscordRPC.`);
if (this._client) {
this._client.destroy();
}
if (!this._utils.getStoreValue("connectivity.discord_rpc.enabled")) return;
this._client
.endlessLogin({
clientId: this._utils.getStoreValue("connectivity.discord_rpc.client") === "Cider" ? "911790844204437504" : "886578863147192350",
})
.then(() => {
console.log(`[DiscordRPC][reload] DiscordRPC Reloaded.`);
this.ready = true;
if (configUpdate == null) this._utils.getWindow().webContents.send("rpcReloaded", this._client.user);
if (this._activityCache && this._activityCache.details && this._activityCache.state) {
console.info(`[DiscordRPC][reload] Restoring activity cache.`);
this._client.setActivity(this._activityCache);
}
})
.catch((e: any) => console.error(`[DiscordRPC][reload] ${e}`));
// this.connect(true)
});
ipcMain.on("onPrivacyModeChange", (_event, enabled) => {
if (enabled && this._client) {
this._client.clearActivity();
} else if (!enabled && this._activityCache && this._activityCache.details && this._activityCache.state) {
this._client.setActivity(this._activityCache);
}
});
}
/**
* Runs on app stop
*/
onBeforeQuit(): void {
console.debug(`[Plugin][${this.name}] Stopped.`);
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
onPlaybackStateDidChange(attributes: object): void {
this._attributes = attributes;
this.setActivity(attributes);
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
playbackTimeDidChange(attributes: object): void {
this._attributes = attributes;
this.setActivity(attributes);
}
/*******************************************************************************************
* Private Methods
* ****************************************************************************************/
/**
* Connect to Discord RPC
* @private
*/
private connect() {
if (!this._utils.getStoreValue("connectivity.discord_rpc.enabled")) {
return;
}
// Create the client
this._client = new AutoClient({ transport: "ipc" });
// Runs on Ready
this._client.once("ready", () => {
console.info(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${this._client.user.id}.`);
if (this._activityCache && this._activityCache.details && this._activityCache.state && !this._utils.getStoreValue("general.privateEnabled")) {
console.info(`[DiscordRPC][connect] Restoring activity cache.`);
this._client.setActivity(this._activityCache);
}
});
// Login to Discord
this._client
.endlessLogin({
clientId: this._utils.getStoreValue("connectivity.discord_rpc.client") === "Cider" ? "911790844204437504" : "886578863147192350",
})
.then(() => {
this.ready = true;
})
.catch((e: any) => console.error(`[DiscordRPC][connect] ${e}`));
}
/**
* Sets the activity
* @param attributes Music Attributes
*/
private setActivity(attributes: any) {
if (!this._client || !attributes) {
return;
}
// Check if show buttons is (true) or (false)
let activity: Object = {
details: this._utils.getStoreValue("connectivity.discord_rpc.activity.details_format"),
state: this._utils.getStoreValue("connectivity.discord_rpc.activity.state_format"),
largeImageKey: attributes?.artwork?.url?.replace("{w}", "1024").replace("{h}", "1024"),
largeImageText: attributes.albumName,
instance: false, // Whether the activity is in a game session
};
// Filter the activity
activity = this.filterActivity(activity, attributes);
if (!this.ready) {
this._activityCache = activity;
return;
}
if (!activity) {
return;
}
if (!attributes.status && this._utils.getStoreValue("connectivity.discord_rpc.clear_on_pause")) {
this._client.clearActivity();
} else if (activity && this._activityCache !== activity) {
if (this._utils.getStoreValue("general.privateEnabled")) return;
this._client.setActivity(activity);
}
this._activityCache = activity;
}
/**
* Filter the Discord activity object
*/
private filterActivity(activity: any, attributes: any): Object {
// Handling Activity Buttons
if (this._utils.getStoreValue("connectivity.discord_rpc.activity.buttons.enabled") && this._utils.getStoreValue("connectivity.discord_rpc.activity.buttons.first") != "disabled") {
const activityUrls: { [key: string]: any } = {
listenOnCider: "cider",
viewOnAppleMusic: "appleMusic",
viewOnOtherMusicServices: "songLink",
};
const firstActivity = this._utils.getLocale(this._utils.getStoreValue("general.language"), `settings.option.connectivity.discordRPC.buttons.${this._utils.getStoreValue("connectivity.discord_rpc.activity.buttons.first")}`);
const secondActivity = this._utils.getLocale(this._utils.getStoreValue("general.language"), `settings.option.connectivity.discordRPC.buttons.${this._utils.getStoreValue("connectivity.discord_rpc.activity.buttons.second")}`);
if (this._utils.getStoreValue("connectivity.discord_rpc.activity.buttons.second") != "disabled") {
activity.buttons = [
{ label: firstActivity, url: attributes.url[activityUrls[this._utils.getStoreValue("connectivity.discord_rpc.activity.buttons.first")]] },
{ label: secondActivity, url: attributes.url[activityUrls[this._utils.getStoreValue("connectivity.discord_rpc.activity.buttons.second")]] },
];
} else {
activity.buttons = [{ label: firstActivity, url: attributes.url[activityUrls[this._utils.getStoreValue("connectivity.discord_rpc.activity.buttons.first")]] }];
}
}
// Add the timestamp if its playing and people want them
if (!this._utils.getStoreValue("connectivity.discord_rpc.hide_timestamp") && attributes.status && new Date(attributes.endTime).getTime() > 0 && isFinite(attributes.endTime) && isFinite(attributes.startTime)) {
activity.startTimestamp = Date.now() - (attributes?.durationInMillis - attributes?.remainingTime);
activity.endTimestamp = attributes.endTime;
}
// If the user wants to keep the activity when paused
if (!this._utils.getStoreValue("connectivity.discord_rpc.clear_on_pause")) {
activity.smallImageKey = attributes.status ? "play" : "pause";
activity.smallImageText = attributes.status ? "Playing" : "Paused";
}
/**
* Works with:
* {artist}
* {composer}
* {title}
* {album}
* {trackNumber}
*/
const rpcVars: any = {
artist: attributes.artistName,
composer: attributes.composerName,
title: attributes.name,
album: attributes.albumName,
trackNumber: attributes.trackNumber,
};
// Replace the variables
Object.keys(rpcVars).forEach((key) => {
if (activity.details.includes(`{${key}}`)) {
activity.details = activity.details.replace(`{${key}}`, rpcVars[key]);
}
if (activity.state.includes(`{${key}}`)) {
activity.state = activity.state.replace(`{${key}}`, rpcVars[key]);
}
});
// Checks if the details is greater than 128 because some songs can be that long
if (activity.details && activity.details.length >= 128) {
activity.details = activity.details.substring(0, 125) + "...";
}
// Checks if the state is greater than 128 because some songs can be that long
if (activity.state && activity.state.length >= 128) {
activity.state = activity.state.substring(0, 125) + "...";
}
// Checks if the state is greater than 128 because some songs can be that long
if (activity.largeImageText && activity.largeImageText.length >= 128) {
activity.largeImageText = activity.largeImageText.substring(0, 125) + "...";
}
// Check large image
if (activity.largeImageKey == null || activity.largeImageKey === "" || activity.largeImageKey.length > 256) {
activity.largeImageKey = "cider";
}
// not sure
if (!attributes.artistName) {
delete activity.state;
}
if (!activity.largeImageText || activity.largeImageText.length < 2) {
delete activity.largeImageText;
}
if (activity.status === "" || activity.details === "") {
return false;
}
return activity;
}
}
================================================
FILE: src/main/plugins/lastfm.ts
================================================
// @ts-ignore
import LastfmAPI from "lastfmapi";
export default class lastfm {
/**
* Base Plugin Information
*/
public name: string = "LastFM Plugin";
public version: string = "2.0.0";
public author: string = "Core (Cider Collective)";
private _apiCredentials = {
key: "f9986d12aab5a0fe66193c559435ede3",
secret: "acba3c29bd5973efa38cc2f0b63cc625",
};
/**
* Plugin Initialization
*/
private _lfm: any = null;
private _authenticated: boolean = false;
private _utils: any = null;
private _scrobbleCache: any = {};
private _nowPlayingCache: any = {};
/**
* Public Methods
*/
constructor(utils: any) {
this._utils = utils;
}
onReady(_win: Electron.BrowserWindow): void {
this.initializeLastFM("", this._apiCredentials);
}
onRendererReady(): void {
// Register the ipcMain handlers
this._utils.getIPCMain().handle("lastfm:url", (event: any) => {
console.debug(`[${lastfm.name}:url] Called.`);
return this._lfm.getAuthenticationUrl({ cb: "cider://auth/lastfm" });
});
this._utils.getIPCMain().on("lastfm:auth", (event: any, token: string) => {
console.debug(`[${lastfm.name}:auth] Token: `, token);
this.authenticateLastFM(token);
});
this._utils.getIPCMain().on("lastfm:disconnect", (_event: any) => {
this._lfm.setSessionCredentials(null, null);
this._authenticated = false;
console.debug(`[${lastfm.name}:disconnect] Disconnected`);
});
this._utils.getIPCMain().on("lastfm:nowPlayingChange", (event: any, attributes: any) => {
if (this._utils.getStoreValue("connectivity.lastfm.filter_loop") || this._utils.getStoreValue("general.privateEnabled") || attributes.kind === "radioStation") return;
this.updateNowPlayingTrack(attributes);
});
this._utils.getIPCMain().on("lastfm:FilteredNowPlayingItemDidChange", (event: any, attributes: any) => {
if (this._utils.getStoreValue("general.privateEnabled") || attributes.kind === "radioStation") return;
this.updateNowPlayingTrack(attributes);
});
this._utils.getIPCMain().on("lastfm:scrobbleTrack", (event: any, attributes: any) => {
if (this._utils.getStoreValue("general.privateEnabled") || attributes.kind === "radioStation") return;
this.scrobbleTrack(attributes);
});
}
/**
* Initialize LastFM
* @param token
* @param api
* @private
*/
private initializeLastFM(token: string, api: { key: string; secret: string }): void {
console.debug(`[${lastfm.name}:initialize] Initializing LastFM`);
this._lfm = new LastfmAPI({
api_key: api.key,
secret: api.secret,
});
if (this._utils.getStoreValue("connectivity.lastfm.secrets.username") && this._utils.getStoreValue("connectivity.lastfm.secrets.key")) {
this._lfm.setSessionCredentials(this._utils.getStoreValue("connectivity.lastfm.secrets.username"), this._utils.getStoreValue("connectivity.lastfm.secrets.key"));
this._authenticated = true;
} else {
this.authenticateLastFM(token);
}
}
/**
* Authenticate the user with the given token
* @param token
* @private
*/
private authenticateLastFM(token: string): void {
if (!token) return;
this._lfm.authenticate(token, (err: any, session: any) => {
if (err) {
console.error(`[${lastfm.name}:authenticate] Error: ${typeof err === "string" ? err : err.message}`);
this._utils.getWindow().webContents.executeJavaScript(`app.notyf.error("${err.message}");`);
return;
}
this._utils.getWindow().webContents.send("lastfm:authenticated", session);
this._authenticated = true;
console.debug(`[${lastfm.name}:authenticate] Authenticated as ${session.username}`);
});
}
/**
* Verifies the track information with lastfm
* @param attributes
* @param callback
* @private
*/
private verifyTrack(attributes: any, callback: Function): void {
if (!attributes) return attributes;
if (!attributes.lfmAlbum) {
this._lfm.album.getInfo(
{
artist: attributes.primaryArtist,
album: attributes.albumName.replace(/ - Single| - EP/g, ""),
},
(err: any, data: any) => {
if (err) {
console.error(`[${lastfm.name}] [album.getInfo] Error: ${typeof err === "string" ? err : err.message}`);
attributes.lfmAlbum = {
name: attributes.albumName.replace(/ - Single| - EP/g, ""),
artist: attributes.primaryArtist,
};
callback(attributes);
}
if (data) {
attributes.lfmAlbum = data;
callback(attributes);
}
},
);
} else {
this._lfm.track.getCorrection(attributes.primaryArtist, attributes.name, (err: any, data: any) => {
if (err) {
console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`);
attributes.lfmTrack = {
name: attributes.name,
artist: {
name: attributes.primaryArtist,
},
};
callback(attributes);
}
if (data) {
attributes.lfmTrack = data.correction.track;
callback(attributes);
}
});
}
}
/**
* Scrobbles the track to lastfm
* @param attributes
* @private
*/
private scrobbleTrack(attributes: any): void {
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
this.verifyTrack(attributes, (a: any) => {
this.scrobbleTrack(a);
});
return;
}
if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._scrobbleCache.track === attributes.lfmTrack.name)) return;
// Scrobble
const scrobble = {
artist: attributes.lfmTrack.artist.name,
track: attributes.lfmTrack.name,
album: attributes.lfmAlbum.name,
albumArtist: attributes.lfmAlbum.artist,
timestamp: new Date().getTime() / 1000,
trackNumber: attributes.trackNumber,
duration: attributes.durationInMillis / 1000,
};
// Easy Debugging
console.debug(`[${lastfm.name}:scrobble] Scrobbling ${scrobble.artist} - ${scrobble.track}`);
// Scrobble the track
this._lfm.track.scrobble(scrobble, (err: any, _res: any) => {
if (err) {
console.error(`[${lastfm.name}:scrobble] Scrobble failed: ${err.message}`);
} else {
console.debug(`[${lastfm.name}:scrobble] Track scrobbled: ${scrobble.artist} - ${scrobble.track}`);
this._scrobbleCache = scrobble;
}
});
}
/**
* Updates the now playing track
* @param attributes
* @private
*/
private updateNowPlayingTrack(attributes: any): void {
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
this.verifyTrack(attributes, (a: any) => {
this.updateNowPlayingTrack(a);
});
return;
}
if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._nowPlayingCache.track === attributes.lfmTrack.name)) return;
console.log(this._utils.getStoreValue("connectivity.lastfm.filter_types"));
const nowPlaying = {
artist: attributes.lfmTrack.artist.name,
track: attributes.lfmTrack.name,
album: attributes.lfmAlbum.name,
trackNumber: attributes.trackNumber,
duration: attributes.durationInMillis / 1000,
albumArtist: attributes.lfmAlbum.artist,
};
this._lfm.track.updateNowPlaying(nowPlaying, (err: any, res: any) => {
if (err) {
console.error(`[${lastfm.name}:updateNowPlaying] Now Playing Update failed: ${err.message}`);
} else {
console.debug(`[${lastfm.name}:updateNowPlaying] Now Playing Updated: ${nowPlaying.artist} - ${nowPlaying.track}`);
this._nowPlayingCache = nowPlaying;
}
});
}
}
================================================
FILE: src/main/plugins/menubar.ts
================================================
import { app, Menu, shell } from "electron";
import { utils } from "../base/utils.js";
export default class Thumbar {
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "Menubar Plugin";
public description: string = "Creates the menubar";
public version: string = "1.0.0";
public author: string = "Core";
public contributors: string[] = ["Core", "Qwack", "Monochromish"];
/**
* Menubar Assets
* @private
*/
private isNotMac: boolean = process.platform !== "darwin";
private isMac: boolean = process.platform === "darwin";
private _menuTemplate: any = [];
/*******************************************************************************************
* Public Methods
* ****************************************************************************************/
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(_utils: utils) {
console.debug(`[Plugin][${this.name}] Loading Complete.`);
}
/**
* Runs on app ready
*/
onReady(_win: Electron.BrowserWindow): void {
this._menuTemplate = [
{
label: app.getName(),
submenu: [
{
label: `${utils.getLocale(utils.getStoreValue("general.language"), "term.about")} ${app.getName()}`,
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('about')`),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.toggleprivate"),
accelerator: utils.getStoreValue("general.keybindings.togglePrivateSession").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.cfg.general.privateEnabled = !app.cfg.general.privateEnabled`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.settings"),
accelerator: utils.getStoreValue("general.keybindings.settings").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.openSettingsPage()`),
},
...(this.isMac ? [{ type: "separator" }, { role: "services" }, { type: "separator" }, { role: "hide" }, { role: "hideOthers" }, { role: "unhide" }, { type: "separator" }, { role: "quit" }] : []),
...(this.isNotMac
? [
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.quit"),
accelerator: "Control+Q",
click: () => app.quit(),
},
]
: []),
],
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.view"),
submenu: [
...(this.isMac ? [{ role: "reload" }, { role: "forceReload" }, { role: "toggleDevTools" }, { type: "separator" }, { role: "resetZoom" }, { role: "zoomIn" }, { role: "zoomOut" }, { type: "separator" }, { role: "togglefullscreen" }, { type: "separator" }] : []),
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.search"),
accelerator: utils.getStoreValue("general.keybindings.search").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript("app.focusSearch()"),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.listenNow"),
accelerator: utils.getStoreValue("general.keybindings.listnow").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('listen_now')`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.browse"),
accelerator: utils.getStoreValue("general.keybindings.browse").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('browse')`),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.recentlyAdded"),
accelerator: utils.getStoreValue("general.keybindings.recentAdd").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-recentlyadded')`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.songs"),
accelerator: utils.getStoreValue("general.keybindings.songs").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-songs')`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.albums"),
accelerator: utils.getStoreValue("general.keybindings.albums").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-albums')`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.artists"),
accelerator: utils.getStoreValue("general.keybindings.artists").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-artists')`),
},
],
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.window"),
submenu: [
{
role: "minimize",
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.minimize"),
},
{ type: "separator" },
...(this.isMac
? [
{
label: "Show",
click: () => utils.getWindow().show(),
},
{ role: "zoom" },
{ type: "separator" },
{ role: "front" },
{ role: "close" },
{
label: "Edit",
submenu: [{ role: "undo" }, { role: "redo" }, { type: "separator" }, { role: "cut" }, { role: "copy" }, { role: "paste" }],
},
{ type: "separator" },
]
: []),
...(this.isNotMac
? [
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.zoom"),
submenu: [
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.zoomin"),
role: "zoomIn",
accelerator: utils.getStoreValue("general.keybindings.zoomn").join("+"),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.zoomout"),
role: "zoomOut",
accelerator: utils.getStoreValue("general.keybindings.zoomt").join("+"),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.zoomreset"),
role: "resetZoom",
accelerator: utils.getStoreValue("general.keybindings.zoomrst").join("+"),
},
],
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.fullscreen"),
accelerator: "Control+Enter",
role: "togglefullscreen",
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "action.close"),
accelerator: "Control+W",
role: "close",
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.reload"),
accelerator: "Control+R",
role: "reload",
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.forcereload"),
accelerator: "Control+Shift+R",
role: "forceReload",
},
]
: []),
],
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.controls"),
submenu: [
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.playpause"),
accelerator: "Space",
click: () => utils.getWindow().webContents.executeJavaScript(`app.SpacePause()`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.next"),
accelerator: "CommandOrControl+Right",
click: () => utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.next()`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.previous"),
accelerator: "CommandOrControl+Left",
click: () => utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.previous()`),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.volumeup"),
accelerator: "CommandOrControl+Up",
click: () => utils.getWindow().webContents.executeJavaScript(`app.volumeUp()`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.volumedown"),
accelerator: "CommandOrControl+Down",
click: () => utils.getWindow().webContents.executeJavaScript(`app.volumeDown()`),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.cast2"),
accelerator: utils.getStoreValue("general.keybindings.castToDevices").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.castMenu = true`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.webremote"),
accelerator: utils.getStoreValue("general.keybindings.webRemote").join("+"),
sublabel: "Opens in external window",
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('remote-pair')`),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.audioSettings"),
accelerator: utils.getStoreValue("general.keybindings.audioSettings").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.audioSettings = true`),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.plugins"),
accelerator: utils.getStoreValue("general.keybindings.pluginMenu").join("+"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.pluginMenu = true`),
},
],
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.account"),
submenu: [
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.accountSettings"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('apple-account-settings')`),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.signout"),
click: () => utils.getWindow().webContents.executeJavaScript(`app.unauthorize()`),
},
],
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.support"),
role: "help",
submenu: [
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.discord"),
click: () => shell.openExternal("https://discord.gg/AppleMusic").catch(console.error),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "term.github"),
click: () => shell.openExternal("https://github.com/ciderapp/Cider/wiki/Troubleshooting").catch(console.error),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.report"),
submenu: [
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.bug"),
click: () => shell.openExternal("https://github.com/ciderapp/Cider/issues/new?assignees=&labels=bug%2Ctriage&template=bug_report.yaml&title=%5BBug%5D%3A+").catch(console.error),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.feature"),
click: () => shell.openExternal("https://github.com/ciderapp/Cider/discussions/new?category=feature-request").catch(console.error),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.trans"),
click: () => shell.openExternal("https://github.com/ciderapp/Cider/issues/new?assignees=&labels=%F0%9F%8C%90+Translations&template=translation.yaml&title=%5BTranslation%5D%3A+").catch(console.error),
},
],
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.license"),
click: () => shell.openExternal("https://github.com/ciderapp/Cider/blob/main/LICENSE").catch(console.error),
},
{ type: "separator" },
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.toggledevtools"),
accelerator: utils.getStoreValue("general.keybindings.openDeveloperTools").join("+"),
click: () => utils.getWindow().webContents.openDevTools(),
},
{
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.conf"),
click: () => utils.getStoreInstance().openInEditor(),
},
],
},
];
const menu = Menu.buildFromTemplate(this._menuTemplate);
Menu.setApplicationMenu(menu);
}
/**
* Runs on app stop
*/
onBeforeQuit(): void {
console.debug(`[Plugin][${this.name}] Stopped.`);
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
onPlaybackStateDidChange(attributes: object): void {}
/**
* Runs on song change
* @param attributes Music Attributes
*/
onNowPlayingItemDidChange(attributes: object): void {}
}
================================================
FILE: src/main/plugins/mpris.ts
================================================
import Player from 'mpris-service';
export default class mpris {
/**
* Private variables for interaction in plugins
*/
private static utils: any;
/**
* MPRIS Service
*/
private static player: Player;
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "MPRIS Service";
public description: string = "Handles MPRIS service calls for Linux systems.";
public version: string = "1.0.0";
public author: string = "Core";
/*******************************************************************************************
* Private Methods
* ****************************************************************************************/
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(utils: any) {
mpris.utils = utils;
console.debug(`[Plugin][${mpris.name}] Loading Complete.`);
}
/**
* Blocks non-linux systems from running this plugin
* @private
* @decorator
*/
private static linuxOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
if (process.platform !== "linux") {
descriptor.value = function () {
return;
};
}
}
/**
* Connects to MPRIS Service
*/
private static connect() {
const player = new Player({
name: "cider",
identity: "Cider",
supportedInterfaces: ["player"],
});
console.debug(`[${mpris.name}:connect] Successfully connected.`);
const renderer = mpris.utils.getWindow().webContents;
const loopType: { [key: string]: number } = {
none: 0,
track: 1,
playlist: 2,
};
player.on("next", () => mpris.utils.playback.next());
player.on("previous", () => mpris.utils.playback.previous());
player.on("playpause", () => mpris.utils.playback.playPause());
player.on("play", () => mpris.utils.playback.play());
player.on("pause", () => mpris.utils.playback.pause());
player.on("quit", () => mpris.utils.getApp().exit());
player.on("position", (args: { position: any }) => mpris.utils.playback.seek(args.position / 1000 / 1000));
player.on("loopStatus", (status: string) => renderer.executeJavaScript(`app.mk.repeatMode = ${loopType[status.toLowerCase()]}`));
player.on("shuffle", () => renderer.executeJavaScript("app.mk.shuffleMode = (app.mk.shuffleMode === 0) ? 1 : 0"));
player.on("volume", (volume: string) => {
renderer.executeJavaScript(`app.mk.volume = ${parseFloat(volume)}`);
});
player.on("raise", () => {
mpris.utils.getWindow().show();
mpris.utils.getWindow().focus();
});
mpris.utils.getIPCMain().on("mpris:playbackTimeDidChange", (event: any, time: number) => {
player.getPosition = () => time;
});
mpris.utils.getIPCMain().on("repeatModeDidChange", (_e: any, mode: number) => {
switch (mode) {
case 0:
player.loopStatus = Player.LOOP_STATUS_NONE;
break;
case 1:
player.loopStatus = Player.LOOP_STATUS_TRACK;
break;
case 2:
player.loopStatus = Player.LOOP_STATUS_PLAYLIST;
break;
}
});
mpris.utils.getIPCMain().on("mpris:volumeChange", (_e: any, volume: number) => {
player.volume = volume;
});
mpris.utils.getIPCMain().on("shuffleModeDidChange", (_e: any, mode: number) => {
player.shuffle = mode === 1;
});
mpris.player = player;
}
/**
* Update M.P.R.I.S Player Attributes
*/
private static updateMetaData(attributes: any) {
mpris.player.metadata = {
"mpris:trackid": mpris.player.objectPath(`track/${attributes.playParams.id.replace(/[^a-zA-Z 0-9]+/g, "")}`),
"mpris:length": attributes.durationInMillis * 1000, // In microseconds
"mpris:artUrl": attributes.artwork.url.replace("/{w}x{h}bb", "/512x512bb").replace("/2000x2000bb", "/35x35bb"),
"xesam:title": `${attributes.name}`,
"xesam:album": `${attributes.albumName}`,
"xesam:artist": [`${attributes.artistName}`],
"xesam:genre": attributes.genreNames,
};
}
/*******************************************************************************************
* Public Methods
* ****************************************************************************************/
/**
* Clear state
* @private
*/
private static clearState() {
if (!mpris.player) {
return;
}
mpris.player.metadata = {
"mpris:trackid": "/org/mpris/MediaPlayer2/TrackList/NoTrack",
};
mpris.player.playbackStatus = Player.PLAYBACK_STATUS_STOPPED;
}
/**
* Runs on app ready
*/
@mpris.linuxOnly
onReady(_: any): void {
console.debug(`[${mpris.name}:onReady] Ready.`);
}
/**
* Renderer ready
*/
@mpris.linuxOnly
onRendererReady(): void {
mpris.connect();
}
/**
* Runs on app stop
*/
@mpris.linuxOnly
onBeforeQuit(): void {
console.debug(`[Plugin][${mpris.name}] Stopped.`);
mpris.clearState();
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
@mpris.linuxOnly
onPlaybackStateDidChange(attributes: any): void {
mpris.player.playbackStatus = attributes?.status ? Player.PLAYBACK_STATUS_PLAYING : Player.PLAYBACK_STATUS_PAUSED;
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
@mpris.linuxOnly
playbackTimeDidChange(attributes: object): void {
mpris.updateMetaData(attributes);
}
}
================================================
FILE: src/main/plugins/playbackNotifications.ts
================================================
import fetch from "node-fetch";
import { app, nativeImage, Notification } from "electron";
import NativeImage = Electron.NativeImage;
import { createWriteStream } from "fs";
import { join } from "path";
export default class playbackNotifications {
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "Playback Notifications";
public description: string = "Creates notifications on playback.";
public version: string = "1.0.0";
public author: string = "Core";
public contributors: string[] = ["Core", "Monochromish"];
private _utils: any;
private _notification: Notification | undefined;
private _artworkImage: { [key: string]: NativeImage } = {};
private _artworkNums: string[] = [];
/**
* Creates playback notification
* @param a: Music Attributes
*/
createNotification(a: any): void {
if (this._notification) {
this._notification.close();
}
this._notification = new Notification({
title: a.name,
body: `${a.artistName} — ${a.albumName}`,
silent: true,
icon: this._artworkImage[a.artwork.url],
urgency: "low",
actions: [
{
type: "button",
text: `${this._utils.getLocale(this._utils.getStoreValue("general.language"), "term.skip")}`,
},
],
toastXml: `
${a?.name.replace(/&/g, "&")}${a?.artistName.replace(/&/g, "&")} — ${a?.albumName.replace(/&/g, "&")}`,
});
this._notification.on("click", (_: any) => {
this._utils.getWindow().show();
this._utils.getWindow().focus();
});
this._notification.on("close", (_: any) => {
this._notification = undefined;
});
this._notification.on("action", (event: any, action: any) => {
this._utils.playback.next();
});
this._notification.show();
}
/*******************************************************************************************
* Public Methods
* ****************************************************************************************/
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(utils: any) {
this._utils = utils;
console.debug(`[Plugin][${this.name}] Loading Complete.`);
utils.getIPCMain().on("playbackNotifications:create", (event: any, a: any) => {
a.artwork.url = a.artwork.url.replace("/{w}x{h}bb", "/512x512bb").replace("/2000x2000bb", "/35x35bb");
if (this._artworkNums.length > 20) {
delete this._artworkImage[this._artworkNums[0]];
this._artworkNums.shift();
}
if (this._artworkImage[a.artwork.url]) {
this.createNotification(a);
} else {
if (process.platform === "win32") {
fetch(a.artwork.url).then((res) => {
console.log(join(app.getPath("temp"), `${a.songId}-${a.artwork.url.split("/").pop()}`));
const dest = createWriteStream(join(app.getPath("temp"), `${a.songId}-${a.artwork.url.split("/").pop()}`));
// @ts-ignore
let stream = res.body.pipe(dest);
stream.on("finish", () => {
this.createNotification(a);
});
});
} else {
fetch(a.artwork.url).then(async (blob) => {
this._artworkImage[a.artwork.url] = nativeImage.createFromBuffer(Buffer.from(await blob.arrayBuffer()));
this._artworkNums[this._artworkNums.length] = a.artwork.url;
this.createNotification(a);
});
}
}
});
}
}
================================================
FILE: src/main/plugins/raop.ts
================================================
import electron from "electron";
import fetch from "node-fetch";
import { Stream } from "stream";
import { Worker } from "worker_threads";
import mdnsjs from "mdns-js";
export default class RAOP {
/**
* Private variables for interaction in plugins
*/
private _utils: any;
private _win: any;
private _app: any;
private _store: any;
private _cacheAttr: any;
private u: any;
private ipairplay: any = "";
private portairplay: any = "";
private airtunes: any;
// private device: any;
private mdns = mdnsjs;
private ok: any = 1;
private devices: any = [];
private castDevices: any = [];
private i: any = false;
private audioStream: any = new Stream.PassThrough();
private ffmpeg: any = null;
private worker: any = null;
private processNode = `
const {
Worker, isMainThread, parentPort, workerData
} = require('node:worker_threads');
function getAudioConv (buffers) {
function interleave16(leftChannel, rightChannel) {
var length = leftChannel.length + rightChannel.length;
var result = new Int16Array(length);
var inputIndex = 0;
for (var index = 0; index < length;) {
result[index++] = leftChannel[inputIndex];
result[index++] = rightChannel[inputIndex];
inputIndex++;
}
return result;
}
function convert(n) {
var v = n < 0 ? n * 32768 : n * 32767; // convert in range [-32768, 32767]
return Math.max(-32768, Math.min(32768, v)); // clamp
}
function bitratechange(e) {
var t = e.length;
let sampleRate = 96.0;
let outputSampleRate = 44.1;
var s = 0,
o = sampleRate / outputSampleRate,
u = Math.ceil(t * outputSampleRate / sampleRate),
a = new Int16Array(u);
for (let i = 0; i < u; i++) {
a[i] = e[Math.floor(s)];
s += o;
}
return a;
}
let newaudio = buffers;
let pcmData = new Int8Array(interleave16(bitratechange(Int16Array.from(newaudio[0], x => convert(x))), bitratechange(Int16Array.from(newaudio[1], x => convert(x)))).buffer);
return pcmData;
}
parentPort.on("message", data => {
parentPort.postMessage({buffer: data.buffer, outbuffer: getAudioConv(data.buffer)});
});
`;
private ondeviceup(name: any, host: any, port: any, addresses: any, text: any, airplay2: any = null) {
// console.log(this.castDevices.findIndex((item: any) => {return (item.name == host.replace(".local","") && item.port == port )}))
let d = "";
let audiook = true;
try {
d = text.filter((u: any) => String(u).startsWith("features="));
if (d.length == 0) d = text.filter((u: any) => String(u).startsWith("ft="));
let features_set = d.length > 0 ? d[0].substring(d[0].indexOf("=") + 1).split(",") : [];
let features = [...(features_set.length > 0 ? parseInt(features_set[0]).toString(2).split("") : []), ...(features_set.length > 1 ? parseInt(features_set[1]).toString(2).split("") : [])];
if (features.length > 0) {
audiook = features[features.length - 1 - 9] == "1";
}
} catch (_) {}
if (audiook) {
let shown_name = name;
try {
let model = text.filter((u: any) => String(u).startsWith("model="));
let manufacturer = text.filter((u: any) => String(u).startsWith("manufacturer="));
let name1 = text.filter((u: any) => String(u).startsWith("name="));
if (name1.length > 0) {
shown_name = name1[0].split("=")[1];
} else if (manufacturer.length > 0) {
shown_name = (manufacturer.length > 0 ? manufacturer[0].substring(13) : "") + " " + (model.length > 0 ? model[0].substring(6) : "");
shown_name = shown_name.trim().length > 1 ? shown_name : (host ?? "Unknown").replace(".local", "");
}
} catch (e) {}
let host_name = addresses != null && typeof addresses == "object" && addresses.length > 0 ? addresses[0] : typeof addresses == "string" ? addresses : "";
if (
this.castDevices.findIndex((item: any) => {
return item != null && item.name == shown_name && item.host == host_name && item.host != "Unknown";
}) == -1
) {
this.castDevices.push({
name: shown_name,
host: host_name,
port: port,
addresses: addresses,
txt: text,
airplay2: airplay2,
});
// if (this.devices.indexOf(host_name) === -1) {
// this.devices.push(host_name);
// }
if (shown_name) {
this._win.webContents.executeJavaScript(`console.log('deviceFound','ip: ${host_name} name:${shown_name}')`).catch((err: any) => console.error(err));
console.log("deviceFound", host_name, shown_name);
}
} else {
this._win.webContents.executeJavaScript(`console.log('deviceFound (added)','ip: ${host_name} name:${shown_name}')`).catch((err: any) => console.error(err));
console.log("deviceFound (added)", host_name, shown_name);
}
}
}
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "RAOP";
public description: string = "RAOP Plugin";
public version: string = "0.0.1";
public author: string = "vapormusic / Cider Collective";
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(utils: { getStore: () => any; getApp: () => any }) {
this._utils = utils;
console.debug(`[Plugin][${this.name}] Loading Complete.`);
this._app = utils.getApp();
}
/**
* Runs on app ready
*/
async onReady(win: any): Promise {
this.u = (await import("airtunes2")).default;
this._win = win;
electron.ipcMain.on("getKnownAirplayDevices", (event) => {
event.returnValue = this.castDevices;
});
electron.ipcMain.on("getAirplayDevice", (event, data) => {
this.castDevices = [];
console.debug("scan for airplay devices");
const browser = this.mdns.createBrowser(this.mdns.tcp("raop"));
browser.on("ready", browser.discover);
browser.on("update", (service: any) => {
if (service.addresses && service.fullname && service.fullname.includes("_raop._tcp")) {
// console.log(service.txt)
this._win.webContents.executeJavaScript(`console.log(
"${service.name} ${service.host}:${service.port} ${service.addresses} ${service.fullname}"
)`);
let itemname = service.fullname.substring(service.fullname.indexOf("@") + 1, service.fullname.indexOf("._raop._tcp"));
this.ondeviceup(itemname, service.host, service.port, service.addresses, service.txt);
}
});
const browser2 = this.mdns.createBrowser(this.mdns.tcp("airplay"));
browser2.on("ready", browser2.discover);
browser2.on("update", (service: any) => {
if (service.addresses && service.fullname && service.fullname.includes("_airplay._tcp")) {
// console.log(service.txt)
this._win.webContents.executeJavaScript(`console.log(
"${service.name} ${service.host}:${service.port} ${service.addresses}"
)`);
let itemname = service.fullname.substring(service.fullname.indexOf("@") + 1, service.fullname.indexOf("._airplay._tcp"));
this.ondeviceup(itemname, service.host, service.port, service.addresses, service.txt, true);
}
});
// const browser2 = this.mdns.createBrowser(this.mdns.tcp('airplay'));
// browser2.on('ready', browser2.discover);
// browser2.on('update', (service: any) => {
// if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp') || service.fullname.includes('_airplay._tcp'))) {
// // console.log(service.txt)
// this._win.webContents.executeJavaScript(`console.log(
// "${service.name} ${service.host}:${service.port} ${service.addresses}"
// )`);
// this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);
// }
// });
});
electron.ipcMain.on("performAirplayPCM", (event, ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv, silent) => {
if (ipv4 != this.ipairplay || ipport != this.portairplay) {
if (this.airtunes == null) {
this.airtunes = new this.u();
}
this.ipairplay = ipv4;
this.portairplay = ipport;
let identifier = ipv4 + ":" + ipport + "ap";
let idx = this.devices.findIndex((a: any) => {
return a.id == identifier;
});
if (idx != -1) {
delete this.devices[idx];
this.devices = this.devices.filter((n: any) => n); // remove old controller
}
this.devices.push({
id: identifier,
ip: ipv4,
port: ipport,
state: 0,
controller: this.airtunes.add(ipv4, {
port: ipport,
volume: airplay2dv ? 30 : 50,
password: sepassword,
txt: txt,
airplay2: airplay2dv,
debug: false,
forceAlac: false,
}),
});
idx = this.devices.findIndex((a: any) => {
return a.id == identifier;
});
// console.log('lol', this.devices)
this.devices[idx].controller.on("status", (status: any) => {
console.log("device status", status);
if (status == "ready") {
this._win.webContents.setAudioMuted(true);
this._win.webContents.executeJavaScript(`CiderAudio.sendAudio()`).catch((err: any) => console.error(err));
}
if (status == "need_password") {
this._win.webContents.executeJavaScript(`app.setAirPlayCodeUI('${this.devices[idx].id}')`);
}
if (status == "pair_success") {
this._win.webContents.executeJavaScript(`app.sendAirPlaySuccess(${silent},'${this.devices[idx].id}')`);
}
if (status == "pair_failed") {
this._win.webContents.executeJavaScript(`app.sendAirPlayFailed()`);
this.disconnectAirplay(this.devices[idx].id);
}
if (status == "stopped") {
// this.airtunes.stopAll(() => {
// console.log("end");
// });
if (this.devices[idx]?.state != null && this.devices[idx].state != -1) this._win.webContents.executeJavaScript(`app.airplayDisconnect(true, ${JSON.stringify([ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv])})`).catch((err: any) => console.error(err));
// this.airtunes = null;
// this.device = null;
// this.ipairplay = "";
// this.portairplay = "";
// this.ok = 1;
} else {
setTimeout(() => {
if (this.ok == 1) {
console.log(this.devices[idx].controller.key, title ?? "", artist ?? "", album ?? "");
this.airtunes.setTrackInfo(this.devices[idx].controller.key, title ?? "", artist ?? "", album ?? "");
this.uploadImageAirplay(artworkURL);
console.log("done", status);
this.ok == 2;
}
}, 1000);
}
});
}
});
electron.ipcMain.on("setAirPlayPasscode", (event, passcode, identifier) => {
if (this.devices.length > 0) {
let idx = this.devices.findIndex((a: any) => {
return a.id == identifier;
});
if (idx != -1) {
this.devices[idx].controller.setPasscode(passcode);
}
}
});
electron.ipcMain.on("setAirPlayVolume", (event, volume, identifier) => {
if (this.devices.length > 0) {
let idx = this.devices.findIndex((a: any) => {
return a.id == identifier;
});
if (idx != -1) {
this.devices[idx].controller.setVolume(volume);
}
}
});
electron.ipcMain.on("writeWAV", (event, leftbuffer, rightbuffer) => {
if (this.airtunes != null) {
if (this.worker == null) {
try {
// const toDataUrl = (js: any) => new URL(`data:text/javascript,${encodeURIComponent(js)}`);
// let blob = new Blob([this.processNode], { type: 'application/javascript' });
//Create new worker
this.worker = new Worker(this.processNode, { eval: true });
//Listen for a message from worker
this.worker.on("message", (result: any) => {
// fs.writeFile(join(electron.app.getPath('userData'), 'buffer.raw'), Buffer.from(Int8Array.from(result.outbuffer)),{flag: 'a+'}, function (err) {
// if (err) throw err;
// console.log('It\'s saved!');
// });
this.airtunes.circularBuffer.write(Buffer.from(new Uint8Array(result.outbuffer)));
});
this.worker.on("error", (error: any) => {
console.log("worker err", error);
});
this.worker.postMessage({ buffer: [leftbuffer, rightbuffer] });
} catch (e) {
console.log(e);
}
// this.ffmpeg != null ? this.ffmpeg.kill() : null;
// this.ffmpeg = spawn(this._utils.getStoreValue("advanced.ffmpegLocation"), [
// '-f', 's16le', // PCM 16bits, little-endian
// '-ar', '48000',
// '-ac', "2",
// '-err_detect','ignore_err',
// '-i', "http://localhost:9000/audio.wav",
// '-acodec', 'pcm_s16le',
// '-f', 's16le', // PCM 16bits, little-endian
// '-ar', '44100', // Sampling rate
// '-ac', "2", // Stereo
// 'pipe:1' // Output on stdout
// ]);
// // pipe data to AirTunes
// this.ffmpeg.stdout.pipe(this.airtunes);
// this.i = true;
} else {
this.worker.postMessage({ buffer: [leftbuffer, rightbuffer] });
}
}
});
electron.ipcMain.on("disconnectAirplay", (event, identifier = "") => {
console.log("iden", identifier);
this.disconnectAirplay(identifier);
});
electron.ipcMain.on("updateAirplayInfo", (event, title, artist, album, artworkURL) => {
if (this.airtunes && this.devices.length > 0) {
for (let i in this.devices) {
console.log(this.devices[i].controller.key, title, artist, album);
this.airtunes.setTrackInfo(this.devices[i].controller.key, title, artist, album);
}
this.uploadImageAirplay(artworkURL);
}
});
electron.ipcMain.on("discordrpc:updateImage", (_event, imageurl) => {
this.uploadImageAirplay(imageurl);
});
}
private disconnectAirplay(identifier: any = "") {
console.log("awdas");
this._win.webContents
.executeJavaScript(`app.airplayDisconnect(false, [], '${identifier}')`)
.then(() => {
if (identifier == "") {
if (this.airtunes) {
for (let i in this.devices) {
this.devices[i].state = -1;
}
this.airtunes.stopAll(() => {
console.log("endAll");
this.airtunes = null;
this.devices = [];
this.airtunes = null;
this.ipairplay = "";
this.portairplay = "";
this.ok = 1;
this.i = false;
});
} else {
this.devices = [];
}
} else {
let idx = this.devices.findIndex((a: any) => {
return a.id == identifier;
});
if (idx != -1) {
this.devices[idx].state = -1;
this.devices[idx].controller.stop(() => {
console.log(this.devices[idx].id, "stopped");
});
delete this.devices[idx];
this.devices = this.devices.filter((n: any) => n);
}
}
if (this.devices.length == 0) {
console.log("cleanup airtunes");
this._win.webContents.setAudioMuted(false);
this.airtunes = null;
this.ipairplay = "";
this.portairplay = "";
this.ok = 1;
this.i = false;
this.devices = [];
}
})
.catch((err: any) => console.error("lsdsd", err));
}
private uploadImageAirplay = (url: any) => {
try {
if (url != null && url != "") {
//console.log(join(this._app.getPath('userData'), 'temp.png'), url);
fetch(url)
.then((res) => res.buffer())
.then((buffer) => {
if (this.airtunes && this.devices.length > 0) {
for (let i in this.devices) {
this.airtunes.setArtwork(this.devices[i].controller.key, buffer, "image/png");
}
}
})
.catch((err) => {
console.log(err);
});
}
} catch (e) {
console.log(e);
}
};
/**
* Runs on app stop
*/
onBeforeQuit(): void {}
/**
* Runs on song change
* @param attributes Music Attributes
*/
onNowPlayingItemDidChange(attributes: any): void {
if (this.airtunes && this.devices.length > 0) {
let title = attributes?.name ?? "";
let artist = attributes?.artistName ?? "";
let album = attributes?.albumName ?? "";
for (let i in this.devices) {
console.log(this.devices[i].controller.key, title, artist, album);
this.airtunes.setTrackInfo(this.devices[i].controller.key, title, artist, album);
}
let artworkURL = attributes?.artwork?.url ?? null;
if (artworkURL != null) {
this.uploadImageAirplay(artworkURL.replace("{w}", "1024").replace("{h}", "1024"));
}
}
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
onPlaybackStateDidChange(attributes: any): void {
if (this.airtunes && this.devices.length > 0) {
let title = attributes?.name ?? "";
let artist = attributes?.artistName ?? "";
let album = attributes?.albumName ?? "";
for (let i in this.devices) {
console.log(this.devices[i].controller.key, title, artist, album);
this.airtunes.setTrackInfo(this.devices[i].controller.key, title, artist, album);
}
let artworkURL = attributes?.artwork?.url ?? null;
if (artworkURL != null) {
this.uploadImageAirplay(artworkURL.replace("{w}", "1024").replace("{h}", "1024"));
}
}
}
playbackTimeDidChange(attributes: any): void {
// console.log(attributes)
if (this.airtunes && this.devices.length > 0 && attributes?.currentPlaybackTime != null && attributes?.durationInMillis != null) {
for (let i in this.devices) {
this.airtunes.setProgress(this.devices[i].controller.key, Math.round(attributes.currentPlaybackTime), Math.floor(attributes.durationInMillis / 1000));
}
}
}
}
================================================
FILE: src/main/plugins/thumbar.ts
================================================
import { nativeImage, nativeTheme } from "electron";
import { utils } from "../base/utils.js";
import { join } from "path";
export default class Thumbar {
/**
* Private variables for interaction in plugins
*/
private _win: any;
private _app: any;
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "Thumbnail Toolbar Plugin";
public description: string = "Creates and managed the thumbnail toolbar buttons and their events";
public version: string = "1.0.0";
public author: string = "Core";
/**
* Thumbnail Toolbar Assets
*/
private icons: { [key: string]: Electron.NativeImage } = {
pause: nativeImage.createFromPath(join(utils.getPath("resourcePath"), "icons/thumbar", `${nativeTheme.shouldUseDarkColors ? "light" : "dark"}_pause.png`)),
play: nativeImage.createFromPath(join(utils.getPath("resourcePath"), "icons/thumbar", `${nativeTheme.shouldUseDarkColors ? "light" : "dark"}_play.png`)),
next: nativeImage.createFromPath(join(utils.getPath("resourcePath"), "icons/thumbar", `${nativeTheme.shouldUseDarkColors ? "light" : "dark"}_next.png`)),
previous: nativeImage.createFromPath(join(utils.getPath("resourcePath"), "icons/thumbar", `${nativeTheme.shouldUseDarkColors ? "light" : "dark"}_previous.png`)),
};
/*******************************************************************************************
* Private Methods
* ****************************************************************************************/
/**
* Blocks non-windows systems from running this plugin
* @private
* @decorator
*/
private static windowsOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
if (process.platform !== "win32") {
descriptor.value = function () {
return;
};
}
}
/**
* Update the thumbnail toolbar
*/
private updateButtons(attributes: any) {
console.log(attributes);
if (!attributes) {
return;
}
const buttons = [
{
tooltip: "Previous",
icon: this.icons.previous,
click() {
utils.playback.previous();
},
},
{
tooltip: attributes.status ? "Pause" : "Play",
icon: attributes.status ? this.icons.pause : this.icons.play,
click() {
utils.playback.playPause();
},
},
{
tooltip: "Next",
icon: this.icons.next,
click() {
utils.playback.next();
},
},
];
if (!attributes.playParams || attributes.playParams.id === "no-id-found") {
this._win.setThumbarButtons([]);
} else {
this._win.setThumbarButtons(buttons);
}
}
/*******************************************************************************************
* Public Methods
* ****************************************************************************************/
/**
* Runs on plugin load (Currently run on application start)
*/
constructor(a: { getApp: () => any }) {
this._app = utils.getApp();
console.debug(`[Plugin][${this.name}] Loading Complete.`);
}
/**
* Runs on app ready
*/
@Thumbar.windowsOnly
onReady(win: Electron.BrowserWindow): void {
this._win = win;
console.debug(`[Plugin][${this.name}] Ready.`);
}
/**
* Runs on app stop
*/
@Thumbar.windowsOnly
onBeforeQuit(): void {
console.debug(`[Plugin][${this.name}] Stopped.`);
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
@Thumbar.windowsOnly
onPlaybackStateDidChange(attributes: object): void {
this.updateButtons(attributes);
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
@Thumbar.windowsOnly
onNowPlayingItemDidChange(attributes: object): void {
this.updateButtons(attributes);
}
}
================================================
FILE: src/main/plugins/webNowPlaying.ts
================================================
import WebSocket from "ws";
/**
* 0-pad a number.
* @param {Number} number
* @param {Number} length
* @returns String
*/
const pad = (number: number, length: number) => String(number).padStart(length, "0");
/**
* Convert seconds to a time string acceptable to Rainmeter
* https://github.com/tjhrulz/WebNowPlaying-BrowserExtension/blob/master/WebNowPlaying.js#L50-L59
* @param {Number} timeInSeconds
* @returns String
*/
const convertTimeToString = (timeInSeconds: number) => {
const timeInMinutes = Math.floor(timeInSeconds / 60);
if (timeInMinutes < 60) {
return timeInMinutes + ":" + pad(Math.floor(timeInSeconds % 60), 2);
}
return Math.floor(timeInMinutes / 60) + ":" + pad(Math.floor(timeInMinutes % 60), 2) + ":" + pad(Math.floor(timeInSeconds % 60), 2);
};
export default class WebNowPlaying {
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
public name: string = "WebNowPlaying";
public description: string = "Song info and playback control for the Rainmeter WebNowPlaying plugin.";
public version: string = "1.0.1";
public author: string = "Zennn ";
private _win: any;
private ws?: WebSocket;
private wsapiConn?: WebSocket;
private playerName: string = "Cider";
constructor() {
console.debug(`[Plugin][${this.name}] Loading Complete.`);
}
/**
* Blocks non-windows systems from running this plugin
* @private
* @decorator
*/
private static windowsOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
if (process.platform !== "win32") {
descriptor.value = () => void 0;
}
}
private sendSongInfo(attributes: any) {
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
const fields = ["STATE", "TITLE", "ARTIST", "ALBUM", "COVER", "DURATION", "POSITION", "VOLUME", "REPEAT", "SHUFFLE"];
fields.forEach((field) => {
try {
let value: any = "";
switch (field) {
case "STATE":
value = attributes.status ? 1 : 2;
break;
case "TITLE":
value = attributes.name;
break;
case "ARTIST":
value = attributes.artistName;
break;
case "ALBUM":
value = attributes.albumName;
break;
case "COVER":
value = attributes.artwork.url.replace("{w}", attributes.artwork.width).replace("{h}", attributes.artwork.height);
break;
case "DURATION":
value = convertTimeToString(attributes.durationInMillis / 1000);
break;
case "POSITION":
value = convertTimeToString((attributes.durationInMillis - attributes.remainingTime) / 1000);
break;
case "VOLUME":
value = attributes.volume * 100;
break;
case "REPEAT":
value = attributes.repeatMode;
break;
case "SHUFFLE":
value = attributes.shuffleMode;
break;
}
this.ws?.send(`${field}:${value}`);
} catch (error) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(`Error:Error updating ${field} for ${this.playerName}`);
this.ws.send(`ErrorD:${error}`);
}
}
});
}
private fireEvent(evt: WebSocket.MessageEvent) {
if (!evt.data) return;
const data = evt.data;
let value: string = "";
if (data.split(/ (.+)/).length > 1) {
value = data.split(/ (.+)/)[1];
}
const eventName = data.split(" ")[0].toLowerCase();
try {
switch (eventName) {
case "playpause":
this._win.webContents.executeJavaScript("MusicKitInterop.playPause()").catch(console.error);
break;
case "next":
this._win.webContents.executeJavaScript("MusicKitInterop.next()").catch(console.error);
break;
case "previous":
this._win.webContents.executeJavaScript("MusicKitInterop.previous()").catch(console.error);
break;
case "setposition":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${parseFloat(value)})`);
break;
case "setvolume":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().volume = ${parseFloat(value) / 100}`);
break;
case "repeat":
this._win.webContents.executeJavaScript("wsapi.toggleRepeat()").catch(console.error);
break;
case "shuffle":
this._win.webContents.executeJavaScript("wsapi.toggleShuffle()").catch(console.error);
break;
case "togglethumbsup":
// not implemented
break;
case "togglethumbsdown":
// not implemented
break;
case "rating":
// not implemented
break;
}
} catch (error) {
console.debug(error);
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(`Error:Error sending event to ${this.playerName}`);
this.ws.send(`ErrorD:${error}`);
}
}
}
/**
* Runs on app ready
*/
@WebNowPlaying.windowsOnly
public onReady(win: any) {
this._win = win;
// Connect to Rainmeter plugin and retry on disconnect.
const init = () => {
try {
this.ws = new WebSocket("ws://127.0.0.1:8974/");
let retry: NodeJS.Timeout;
this.ws.onopen = () => {
console.info("[WebNowPlaying] Connected to Rainmeter");
this.ws?.send(`PLAYER:${this.playerName}`);
};
this.ws.onclose = () => {
clearTimeout(retry);
retry = setTimeout(init, 2000);
};
this.ws.onerror = () => {
clearTimeout(retry);
this.ws?.close();
};
this.ws.onmessage = this.fireEvent?.bind(this);
} catch (error) {
console.error(error);
}
};
init();
// Connect to wsapi. Only used to update progress.
try {
this.wsapiConn = new WebSocket("ws://127.0.0.1:26369/");
this.wsapiConn.onopen = () => {
console.info("[WebNowPlaying] Connected to wsapi");
};
this.wsapiConn.onmessage = (evt: WebSocket.MessageEvent) => {
const response = JSON.parse(evt.data);
if (response.type === "playbackStateUpdate") {
this.sendSongInfo(response.data);
}
};
} catch (error) {
console.error(error);
}
console.debug(`[Plugin][${this.name}] Ready.`);
}
/**
* Runs on app stop
*/
@WebNowPlaying.windowsOnly
public onBeforeQuit() {
if (this.ws) {
this.ws.send("STATE:0");
this.ws.onclose = () => void 0; // disable onclose handler first to stop it from retrying
this.ws.close();
}
if (this.wsapiConn) {
this.wsapiConn.close();
}
console.debug(`[Plugin][${this.name}] Stopped.`);
}
/**
* Runs on playback State Change
* @param attributes Music Attributes (attributes.status = current state)
*/
@WebNowPlaying.windowsOnly
public onPlaybackStateDidChange(attributes: any) {
this.sendSongInfo(attributes);
}
/**
* Runs on song change
* @param attributes Music Attributes
*/
@WebNowPlaying.windowsOnly
public onNowPlayingItemDidChange(attributes: any) {
this.sendSongInfo(attributes);
}
}
================================================
FILE: src/main/providers/local/index.ts
================================================
// import { ProviderDB } from "./db";
import { EventEmitter } from "events";
import mm from "music-metadata";
import { resolve } from "node:path";
import { Md5 } from "ts-md5";
import { utils } from "../../base/utils.js";
import { readdirSync } from "node:fs";
export class LocalFiles {
static localSongs: any = [];
static localSongsArts: any = [];
// public static DB = ProviderDB.db;
static eventEmitter = new EventEmitter();
static getDataType(item_id: String | any) {
if ((item_id ?? "").startsWith("ciderlocalart")) return "artwork";
else if ((item_id ?? "").startsWith("ciderlocal")) return "track";
}
// static async sendOldLibrary() {
// ProviderDB.init();
// let rows = (await ProviderDB.db.allDocs({ include_docs: true, attachments: true })).rows.map((item: any) => {
// return item.doc;
// });
// let tracks = rows.filter((item: any) => {
// return this.getDataType(item._id) == "track";
// });
// let arts = rows.filter((item: any) => {
// return this.getDataType(item._id) == "artwork";
// });
// this.localSongs = tracks;
// this.localSongsArts = arts;
// return tracks;
// }
static async scanLibrary() {
// ProviderDB.init();
let folders = utils.getStoreValue("libraryPrefs.localPaths");
if (folders == null || folders.length == null || folders.length == 0) folders = [];
let files: any[] = [];
for (var folder of folders) {
// get files from the Music folder
files = files.concat(await LocalFiles.getFiles(folder));
}
let supporttedformats = ["mp3", "aac", "webm", "flac", "m4a", "ogg", "wav", "opus"];
let audiofiles = files.filter((f) => supporttedformats.includes(f.substring(f.lastIndexOf(".") + 1)));
let metadatalist = [];
let metadatalistart = [];
let numid = 0;
for (var audio of audiofiles) {
try {
const metadata = await mm.parseFile(audio);
let lochash = Md5.hashStr(audio) ?? numid;
if (metadata != null) {
let form = {
id: "ciderlocal" + lochash,
_id: "ciderlocal" + lochash,
type: "podcast-episodes",
href: audio,
attributes: {
artwork: {
width: 3000,
height: 3000,
url: "/ciderlocalart/" + "ciderlocal" + lochash,
},
topics: [],
url: "",
subscribable: true,
mediaKind: "audio",
genreNames: [""],
// "playParams": {
// "id": "ciderlocal" + numid,
// "kind": "podcast",
// "isLibrary": true,
// "reporting": false },
trackNumber: metadata.common.track?.no ?? 0,
discNumber: metadata.common.disk?.no ?? 0,
name: metadata.common.title ?? audio.substring(audio.lastIndexOf("\\") + 1),
albumName: metadata.common.album,
artistName: metadata.common.artist,
copyright: metadata.common.copyright ?? "",
assetUrl: "file:///" + audio,
contentAdvisory: "",
releaseDateTime: `${metadata?.common?.year ?? "2022"}-05-13T00:23:00Z`,
durationInMillis: Math.floor((metadata.format.duration ?? 0) * 1000),
bitrate: Math.floor((metadata.format?.bitrate ?? 0) / 1000),
offers: [
{
kind: "get",
type: "STDQ",
},
],
contentRating: "clean",
},
flavor: Math.floor((metadata.format?.bitrate ?? 0) / 1000),
localFilesMetadata: {
lossless: metadata.format?.lossless,
container: metadata.format?.container,
bitDepth: metadata.format?.bitsPerSample ?? 0,
sampleRate: metadata.format?.sampleRate ?? 0,
},
};
let art = {
id: "ciderlocal" + lochash,
_id: "ciderlocalart" + lochash,
url: metadata.common.picture != undefined ? metadata.common.picture[0].data.toString("base64") : "",
};
metadatalistart.push(art);
numid += 1;
// ProviderDB.db.putIfNotExists(form);
// ProviderDB.db.putIfNotExists(art);
metadatalist.push(form);
if (this.localSongs.length === 0 && numid % 10 === 0) {
// send updated chunks only if there is no previous database
this.eventEmitter.emit("newtracks", metadatalist);
}
}
} catch (e) {
console.error("localfiles error:", e);
}
}
// console.log('metadatalist', metadatalist);
this.localSongs = metadatalist;
this.localSongsArts = metadatalistart;
return metadatalist;
}
static async getFiles(dir: string): Promise {
const dirents = readdirSync(dir, { withFileTypes: true });
const files = await Promise.all(
dirents.map((dirent: any) => {
const res = resolve(dir, dirent.name);
return dirent.isDirectory() ? this.getFiles(res) : res;
}),
);
return Array.prototype.concat(...files);
}
// static async cleanUpDB() {
// let folders = utils.getStoreValue("libraryPrefs.localPaths");
// let rows = (await ProviderDB.db.allDocs({ include_docs: true, attachments: true })).rows.map((item: any) => {
// return item.doc;
// });
// let tracks = rows.filter((item: any) => {
// return (
// this.getDataType(item._id) == "track" &&
// !folders.some((i: String) => {
// return item["attributes"]["assetUrl"].startsWith("file:///" + i);
// })
// );
// });
// let hashs = tracks.map((i: any) => {
// return i._id;
// });
// for (let hash of hashs) {
// try {
// ProviderDB.db.get(hash).then(function (doc: any) {
// return ProviderDB.db.remove(doc);
// });
// } catch (e) {}
// try {
// ProviderDB.db.get(hash.replace("ciderlocal", "ciderlocalart")).then(function (doc: any) {
// return ProviderDB.db.remove(doc);
// });
// } catch (e) {}
// }
// }
static setupHandlers() {
const app = utils.getExpress();
console.log("Setting up handlers for local files");
app.get("/ciderlocal/:songs", (req: any, res: any) => {
const audio = atob(req.params.songs.replace(/_/g, "/").replace(/-/g, "+"));
// console.log('auss', LocalFiles.localSongs)
let data = {
data: LocalFiles.localSongs.filter((f: any) => audio.split(",").includes(f.id)),
};
res.send(data);
});
app.get("/ciderlocalart/:songs", (req: any, res: any) => {
const audio = req.params.songs;
// metadata.common.picture[0].data.toString('base64')
res.setHeader("Cache-Control", "public, max-age=31536000");
res.setHeader("Expires", new Date(Date.now() + 31536000000).toUTCString());
res.setHeader("Content-Type", "image/jpeg");
let data = LocalFiles.localSongsArts.filter((f: any) => f.id == audio);
res.status(200).send(Buffer.from(data[0]?.url, "base64"));
});
return app;
}
}
================================================
FILE: src/preload/cider-preload.js
================================================
global.ipcRenderer = require("electron").ipcRenderer;
console.info("Loaded Preload");
let cache = { playParams: { id: 0 }, status: null, remainingTime: 0 },
playbackCache = { status: null, time: Date.now() };
const MusicKitInterop = {
init: function () {
/* MusicKit.Events.playbackStateDidChange */
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackStateDidChange, () => {
const attributes = MusicKitInterop.getAttributes();
if (!attributes) return;
MusicKitInterop.updateMediaState(attributes);
if (MusicKitInterop.filterTrack(attributes, true, false)) {
global.ipcRenderer.send("playbackStateDidChange", attributes);
global.ipcRenderer.send("wsapi-updatePlaybackState", attributes);
}
});
/* MusicKit.Events.playbackProgressDidChange */
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackProgressDidChange, async () => {
const attributes = MusicKitInterop.getAttributes();
if (!attributes) return;
// wsapi call
ipcRenderer.send("wsapi-updatePlaybackState", attributes);
// lastfm call
if (app.mk.currentPlaybackProgress === app.cfg.connectivity.lastfm.scrobble_after / 100) {
attributes.primaryArtist = app.cfg.connectivity.lastfm.remove_featured ? await this.fetchSongRelationships() : attributes.artistName;
ipcRenderer.send("lastfm:scrobbleTrack", attributes);
}
});
/* MusicKit.Events.playbackTimeDidChange */
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackTimeDidChange, () => {
ipcRenderer.send("mpris:playbackTimeDidChange", MusicKit.getInstance()?.currentPlaybackTime * 1000 * 1000 ?? 0);
const attributes = MusicKitInterop.getAttributes();
if (!attributes) return;
ipcRenderer.send("playbackTimeDidChange", attributes);
MusicKitInterop.updatePositionState(attributes);
});
/* MusicKit.Events.nowPlayingItemDidChange */
MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, async () => {
if (window?.localStorage) {
window.localStorage.setItem("currentTrack", JSON.stringify(MusicKit.getInstance().nowPlayingItem));
window.localStorage.setItem("currentTime", JSON.stringify(MusicKit.getInstance().currentPlaybackTime));
window.localStorage.setItem("currentQueue", JSON.stringify(MusicKit.getInstance().queue?._unplayedQueueItems));
}
const attributes = MusicKitInterop.getAttributes();
if (!attributes) return;
attributes.primaryArtist = app.cfg.connectivity.lastfm.remove_featured ? await this.fetchSongRelationships() : attributes.artistName;
MusicKitInterop.updateMediaSession(attributes);
global.ipcRenderer.send("nowPlayingItemDidChange", attributes);
if (MusicKitInterop.filterTrack(attributes, false, true)) {
global.ipcRenderer.send("lastfm:FilteredNowPlayingItemDidChange", attributes);
} else if (attributes.name !== "no-title-found" && attributes.playParams.id !== "no-id-found") {
global.ipcRenderer.send("lastfm:nowPlayingChange", attributes);
}
if (app.cfg.general.playbackNotifications && !document.hasFocus() && attributes.artistName && attributes.artwork && attributes.name) {
global.ipcRenderer.send("playbackNotifications:create", attributes);
}
if (MusicKit.getInstance().nowPlayingItem) {
await this.sleep(750);
MusicKit.getInstance().playbackRate = app.cfg.audio.playbackRate;
}
console.debug("[cider:preload] nowPlayingItemDidChange");
});
/* MusicKit.Events.authorizationStatusDidChange */
MusicKit.getInstance().addEventListener(MusicKit.Events.authorizationStatusDidChange, () => {
global.ipcRenderer.send("authorizationStatusDidChange", MusicKit.getInstance().authorizationStatus);
});
/* MusicKit.Events.mediaPlaybackError */
MusicKit.getInstance().addEventListener(MusicKit.Events.mediaPlaybackError, (e) => {
console.warn(`[cider:preload] mediaPlaybackError] ${e}`);
});
/* MusicKit.Events.shuffleModeDidChange */
MusicKit.getInstance().addEventListener(MusicKit.Events.shuffleModeDidChange, () => {
global.ipcRenderer.send("shuffleModeDidChange", MusicKit.getInstance().shuffleMode);
});
/* MusicKit.Events.repeatModeDidChange */
MusicKit.getInstance().addEventListener(MusicKit.Events.repeatModeDidChange, () => {
global.ipcRenderer.send("repeatModeDidChange", MusicKit.getInstance().repeatMode);
});
},
sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
},
async fetchSongRelationships({ id = this.getAttributes().songId, relationship = "primaryName" } = {}) {
if (!id) return null;
const res = await MusicKit.getInstance().api.v3.music("/v1/catalog/" + MusicKit.getInstance().storefrontId + `/songs/${id}`, {
include: {
songs: ["artists"],
},
});
if (!res || !res.data) {
console.warn("[cider:preload] fetchSongRelationships: no response");
if (id === this.getAttributes().songId) {
return this.getAttributes().artistName;
}
}
if (!res.data.data.length) {
console.error(`[cider:preload] fetchSongRelationships: Unable to locate song with id of ${id}`);
if (id === this.getAttributes().songId) {
return this.getAttributes().artistName;
}
}
const songData = res.data.data[0];
const artistData = songData.relationships.artists.data;
const albumData = songData.relationships.albums.data;
const primaryArtist = artistData[0];
switch (relationship) {
default:
case "primaryName":
if (artistData.length < 1) {
console.error(`[cider:preload] fetchSongRelationships: Unable to find artists related to the song with id of ${id}`);
return app.mk.nowPlayingItem.attributes.artistName;
}
return primaryArtist.attributes.name;
case "primaryArtist":
return primaryArtist;
case "album":
return albumData[0];
}
},
getAttributes: function () {
const mk = MusicKit.getInstance();
const nowPlayingItem = mk.nowPlayingItem;
const isPlayingExport = mk.isPlaying;
const remainingTimeExport = mk.currentPlaybackTimeRemaining;
const currentPlaybackProgress = mk.currentPlaybackProgress;
const attributes = nowPlayingItem != null ? nowPlayingItem.attributes : {};
attributes.songId = attributes.songId ?? attributes.playParams?.catalogId ?? attributes.playParams?.id;
attributes.kind = nowPlayingItem?.type ?? attributes?.type ?? attributes.playParams?.kind ?? "";
attributes.status = nowPlayingItem == null ? null : !!isPlayingExport;
attributes.name = attributes?.name ?? "no-title-found";
attributes.artwork = attributes?.artwork ?? { url: "" };
attributes.artwork.url = (attributes?.artwork?.url ?? "").replace(`{f}`, "png");
attributes.playParams = attributes?.playParams ?? { id: "no-id-found" };
attributes.playParams.id = attributes?.playParams?.id ?? "no-id-found";
attributes.url = {
cider: `https://cider.sh/link?play/s/${nowPlayingItem?._songId ?? nowPlayingItem?.songId ?? "no-id-found"}`,
appleMusic: attributes.websiteUrl ? attributes.websiteUrl : `https://music.apple.com/${mk.storefrontId}/song/${nowPlayingItem?._songId ?? nowPlayingItem?.songId ?? "no-id-found"}`,
songLink: "https://song.link/i/" + attributes.songId,
};
if (attributes.playParams.id === "no-id-found") {
attributes.playParams.id = nowPlayingItem?.id ?? "no-id-found";
}
attributes.albumName = attributes?.albumName ?? "";
attributes.artistName = attributes?.artistName ?? "";
attributes.genreNames = attributes?.genreNames ?? [];
attributes.remainingTime = remainingTimeExport ? remainingTimeExport * 1000 : 0;
attributes.durationInMillis = attributes?.durationInMillis ?? 0;
attributes.currentPlaybackTime = mk?.currentPlaybackTime ?? 0;
attributes.currentPlaybackProgress = currentPlaybackProgress ?? 0;
attributes.startTime = Date.now();
attributes.endTime = Math.round(attributes?.playParams?.id === cache.playParams.id ? Date.now() + attributes?.remainingTime : attributes?.startTime + attributes?.durationInMillis);
if (attributes.name === "no-title-found") {
return;
}
return attributes;
},
filterTrack: function (a, playbackCheck, mediaCheck) {
if (a.name === "no-title-found" || a.playParams.id === "no-id-found") {
return;
} else if (mediaCheck && a.playParams.id === cache.playParams.id) {
return;
} else if (playbackCheck && a.status === playbackCache.status) {
return;
} else if (playbackCheck && !a.status && a.remainingTime === playbackCache.time) {
/* Pretty much have to do this to prevent multiple runs when a song starts playing */
return;
}
cache = a;
if (playbackCheck) playbackCache = { status: a.status, time: a.remainingTime };
return true;
},
play: () => {
MusicKit.getInstance().play().catch(console.error);
},
pause: () => {
MusicKit.getInstance().pause();
},
playPause: () => {
if (MusicKit.getInstance().isPlaying) {
MusicKit.getInstance().pause();
} else if (MusicKit.getInstance().nowPlayingItem != null) {
MusicKit.getInstance().play().catch(console.error);
}
},
next: () => {
if (app) {
app.skipToNextItem();
} else {
MusicKit.getInstance()
.skipToNextItem()
.then((r) => console.debug(`[cider:preload] [next] Skipping to Next ${r}`));
}
},
previous: () => {
if (app) {
app.skipToPreviousItem();
} else {
MusicKit.getInstance()
.skipToPreviousItem()
.then((r) => console.debug(`[cider:preload] [previous] Skipping to Previous ${r}`));
}
},
initMediaSession: () => {
if ("mediaSession" in navigator) {
console.debug("[cider:preload] [initMediaSession] Media Session API supported");
navigator.mediaSession.setActionHandler("play", () => {
MusicKitInterop.play();
});
navigator.mediaSession.setActionHandler("pause", () => {
MusicKitInterop.pause();
});
navigator.mediaSession.setActionHandler("stop", () => {
MusicKit.getInstance().stop();
});
navigator.mediaSession.setActionHandler("seekbackward", (details) => {
if (details.seekOffset) {
MusicKit.getInstance().seekToTime(Math.max(MusicKit.getInstance().currentPlaybackTime - details.seekOffset, 0));
} else {
MusicKit.getInstance().seekBackward();
}
});
navigator.mediaSession.setActionHandler("seekforward", (details) => {
if (details.seekOffset) {
MusicKit.getInstance().seekToTime(Math.max(MusicKit.getInstance().currentPlaybackTime + details.seekOffset, 0));
} else {
MusicKit.getInstance().seekForward();
}
});
navigator.mediaSession.setActionHandler("seekto", ({ seekTime, fastSeek }) => {
MusicKit.getInstance().seekToTime(seekTime);
});
navigator.mediaSession.setActionHandler("previoustrack", () => {
MusicKitInterop.previous();
});
navigator.mediaSession.setActionHandler("nexttrack", () => {
MusicKitInterop.next();
});
} else {
console.debug("[cider:preload] [initMediaSession] Media Session API not supported");
}
},
updateMediaSession: (a) => {
if ("mediaSession" in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: a.name,
artist: a.artistName,
album: a.albumName,
artwork: [
{
src: a.artwork.url.replace("/{w}x{h}bb", "/96x96bb").replace("/2000x2000bb", "/35x35bb"),
sizes: "96x96",
type: "image/jpeg",
},
{
src: a.artwork.url.replace("/{w}x{h}bb", "/128x128bb").replace("/2000x2000bb", "/35x35bb"),
sizes: "128x128",
type: "image/jpeg",
},
{
src: a.artwork.url.replace("/{w}x{h}bb", "/192x192bb").replace("/2000x2000bb", "/35x35bb"),
sizes: "192x192",
type: "image/jpeg",
},
{
src: a.artwork.url.replace("/{w}x{h}bb", "/256x256bb").replace("/2000x2000bb", "/35x35bb"),
sizes: "256x256",
type: "image/jpeg",
},
{
src: a.artwork.url.replace("/{w}x{h}bb", "/384x384bb").replace("/2000x2000bb", "/35x35bb"),
sizes: "384x384",
type: "image/jpeg",
},
{
src: a.artwork.url.replace("/{w}x{h}bb", "/512x512bb").replace("/2000x2000bb", "/35x35bb"),
sizes: "512x512",
type: "image/jpeg",
},
],
});
}
},
updateMediaState: (a) => {
if ("mediaSession" in navigator) {
console.debug("[cider:preload] [updateMediaState] Updating Media State to " + a.status);
switch (a.status) {
default:
case null:
navigator.mediaSession.playbackState = "none";
break;
case false:
navigator.mediaSession.playbackState = "paused";
break;
case true:
navigator.mediaSession.playbackState = "playing";
break;
}
}
},
updatePositionState: (a) => {
if ("mediaSession" in navigator && a.currentPlaybackTime <= a.durationInMillis / 1000 && a.currentPlaybackTime >= 0) {
navigator.mediaSession.setPositionState({
duration: a.durationInMillis / 1000,
playbackRate: app?.cfg?.audio?.playbackRate ?? 1,
position: a.currentPlaybackTime,
});
}
},
};
process.once("loaded", () => {
console.debug("[cider:preload] IPC Listeners Created!");
global.MusicKitInterop = MusicKitInterop;
});
================================================
FILE: src/renderer/apple-hls-old.js
================================================
/*! For license information please see hls.js.LICENSE.txt */ ! function Xy(Yy) {
const Jy = this;
var e, t;
e = this, t = function() {
"use strict";
var P, e = e => e && e.Math === Math && e,
l = e("object" == typeof globalThis && globalThis) || e("object" == typeof window && window) || e("object" == typeof Jy && Jy) || e("object" == typeof global && global) || Function("return this")();
class d {
constructor() {
this.keySize = null, this.ksRows = null, this.keySchedule = null, this.invKeySchedule = null, this.rcon = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], this.subMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)], this.invSubMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)], this.sBox = new Uint32Array(256), this.invSBox = new Uint32Array(256), this.key = new Uint32Array(0), this.initTable()
}
uint8ArrayToUint32Array_(e) {
const t = new DataView(e),
i = Math.floor(t.byteLength / 4),
r = new Uint32Array(i);
for (let e = 0; e < i; e++) r[e] = t.getUint32(4 * e);
return r
}
initTable() {
const e = this["sBox"],
t = this["invSBox"],
i = this["subMix"],
r = i[0],
n = i[1],
s = i[2],
a = i[3],
o = this["invSubMix"],
l = o[0],
d = o[1],
u = o[2],
c = o[3],
h = new Uint32Array(256);
let p = 0,
f = 0,
m = 0;
for (m = 0; m < 256; m++) h[m] = m < 128 ? m << 1 : m << 1 ^ 283;
for (m = 0; m < 256; m++) {
var g = (g = f ^ f << 1 ^ f << 2 ^ f << 3 ^ f << 4) >>> 8 ^ 255 & g ^ 99;
e[p] = g, t[g] = p;
const o = h[p],
m = h[o],
v = h[m];
var y = 257 * h[g] ^ 16843008 * g;
r[p] = y << 24 | y >>> 8, n[p] = y << 16 | y >>> 16, s[p] = y << 8 | y >>> 24, a[p] = y, y = 16843009 * v ^ 65537 * m ^ 257 * o ^ 16843008 * p, l[g] = y << 24 | y >>> 8, d[g] = y << 16 | y >>> 16, u[g] = y << 8 | y >>> 24, c[g] = y, p ? (p = o ^ h[h[h[v ^ o]]], f ^= h[h[f]]) : p = f = 1
}
}
expandKey(e) {
var n = this.uint8ArrayToUint32Array_(e);
let t = !0,
i = 0;
for (; i < n.length && t;) t = n[i] === this.key[i], i++;
if (!t) {
this.key = n;
var s = this.keySize = n.length;
if (4 !== s && 6 !== s && 8 !== s) throw new Error("Invalid aes key size=" + s);
var a = this.ksRows = 4 * (s + 6 + 1);
let e, t;
const o = this.keySchedule = new Uint32Array(a),
l = this.invKeySchedule = new Uint32Array(a),
d = this.sBox,
u = this["rcon"],
c = this["invSubMix"],
h = c[0],
p = c[1],
f = c[2],
m = c[3];
let i, r;
for (e = 0; e < a; e++) e < s ? i = o[e] = n[e] : (r = i, e % s == 0 ? (r = r << 8 | r >>> 24, r = d[r >>> 24] << 24 | d[r >>> 16 & 255] << 16 | d[r >>> 8 & 255] << 8 | d[255 & r], r ^= u[e / s | 0] << 24) : 6 < s && e % s == 4 && (r = d[r >>> 24] << 24 | d[r >>> 16 & 255] << 16 | d[r >>> 8 & 255] << 8 | d[255 & r]), o[e] = i = (o[e - s] ^ r) >>> 0);
for (t = 0; t < a; t++) e = a - t, r = 3 & t ? o[e] : o[e - 4], l[t] = t < 4 || e <= 4 ? r : h[d[r >>> 24]] ^ p[d[r >>> 16 & 255]] ^ f[d[r >>> 8 & 255]] ^ m[d[255 & r]], l[t] = l[t] >>> 0
}
}
networkToHostOrderSwap(e) {
return e << 24 | (65280 & e) << 8 | (16711680 & e) >> 8 | e >>> 24
}
decrypt(e, t, i) {
var r = this.keySize + 6,
n = this["invKeySchedule"],
s = this.invSBox,
a = this["invSubMix"],
o = a[0],
l = a[1],
d = a[2],
u = a[3],
i = this.uint8ArrayToUint32Array_(i);
let c = i[0],
h = i[1],
p = i[2],
f = i[3];
const m = new Int32Array(e),
g = new Int32Array(m.length);
let y, v, S, b, T, E, I, w, A, O, k, C, D, M;
const x = this.networkToHostOrderSwap;
for (; t < m.length;) {
for (A = x(m[t]), O = x(m[t + 1]), k = x(m[t + 2]), C = x(m[t + 3]), T = A ^ n[0], E = C ^ n[1], I = k ^ n[2], w = O ^ n[3], D = 4, M = 1; M < r; M++) y = o[T >>> 24] ^ l[E >> 16 & 255] ^ d[I >> 8 & 255] ^ u[255 & w] ^ n[D], v = o[E >>> 24] ^ l[I >> 16 & 255] ^ d[w >> 8 & 255] ^ u[255 & T] ^ n[D + 1], S = o[I >>> 24] ^ l[w >> 16 & 255] ^ d[T >> 8 & 255] ^ u[255 & E] ^ n[D + 2], b = o[w >>> 24] ^ l[T >> 16 & 255] ^ d[E >> 8 & 255] ^ u[255 & I] ^ n[D + 3], T = y, E = v, I = S, w = b, D += 4;
y = s[T >>> 24] << 24 ^ s[E >> 16 & 255] << 16 ^ s[I >> 8 & 255] << 8 ^ s[255 & w] ^ n[D], v = s[E >>> 24] << 24 ^ s[I >> 16 & 255] << 16 ^ s[w >> 8 & 255] << 8 ^ s[255 & T] ^ n[D + 1], S = s[I >>> 24] << 24 ^ s[w >> 16 & 255] << 16 ^ s[T >> 8 & 255] << 8 ^ s[255 & E] ^ n[D + 2], b = s[w >>> 24] << 24 ^ s[T >> 16 & 255] << 16 ^ s[E >> 8 & 255] << 8 ^ s[255 & I] ^ n[D + 3], D += 3, g[t] = x(y ^ c), g[t + 1] = x(b ^ h), g[t + 2] = x(S ^ p), g[t + 3] = x(v ^ f), c = A, h = O, p = k, f = C, t += 4
}
return g.buffer
}
destroy() {
this.key = void 0, this.keySize = void 0, this.ksRows = void 0, this.sBox = void 0, this.invSBox = void 0, this.subMix = void 0, this.invSubMix = void 0, this.keySchedule = void 0, this.invKeySchedule = void 0, this.rcon = void 0
}
}
class i {
constructor(e, t) {
this.rpc = e, this.logger = t, this.decrypt = (r, n, s, a, o) => t => {
const i = l.crypto;
if (null != o && o.useJSCrypto || null == i || !i.subtle) {
const s = new d;
var e;
s.expandKey(r);
const i = s.decrypt(a, 0, n);
e = o.plainTextLength ? i.slice(0, o.plainTextLength) : function(e) {
var t = new Uint8Array(e),
i = t[e.byteLength - 1],
r = e.byteLength - 1;
let n = 0;
if (1 <= i && i <= 16)
for (let e = r; e > r - i && t[e] === i; e--) n++;
return e = n === i ? e.slice(0, r - i + 1) : e
}(i), t(e, void 0, [e])
} else i.subtle.importKey("raw", r, s, !1, ["decrypt"]).then(e => i.subtle.decrypt({
name: s,
iv: n
}, e, a)).then(e => {
t(e, void 0, [e])
}).catch(e => t(void 0, e))
}, e.register("decrypt", this.decrypt)
}
}(vr = P = P || {}).MEDIA_ATTACHING = "hlsMediaAttaching", vr.MEDIA_ATTACHED = "hlsMediaAttached", vr.MEDIA_DETACHING = "hlsMediaDetaching", vr.MEDIA_DETACHED = "hlsMediaDetached", vr.BUFFER_CREATED = "hlsBufferCreated", vr.BUFFER_APPENDING = "hlsBufferAppending", vr.BUFFER_APPENDED = "hlsBufferAppended", vr.BUFFER_FLUSHED = "hlsBufferFlushed", vr.MANIFEST_LOADING = "hlsManifestLoading", vr.MANIFEST_LOADED = "hlsManifestLoaded", vr.MANIFEST_PARSED = "hlsManifestParsed", vr.LEVEL_SWITCHING = "hlsLevelSwitching", vr.LEVEL_SWITCHED = "hlsLevelSwitched", vr.LEVEL_LOADING = "hlsLevelLoading", vr.LEVEL_LOADED = "hlsLevelLoaded", vr.LEVEL_UPDATED = "hlsLevelUpdated", vr.LEVELS_CHANGED = "hlsLevelsChanged", vr.AUDIO_TRACKS_UPDATED = "hlsAudioTracksUpdated", vr.AUDIO_TRACK_SWITCH = "hlsAudioTrackSwitch", vr.AUDIO_TRACK_SWITCHED = "hlsAudioTrackSwitched", vr.AUDIO_TRACK_LOADED = "hlsAudioTrackLoaded", vr.SUBTITLE_TRACKS_UPDATED = "hlsSubtitleTracksUpdated", vr.SUBTITLE_TRACKS_CREATED = "hlsSubtitleTracksCreated", vr.SUBTITLE_TRACK_SWITCH = "hlsSubtitleTrackSwitch", vr.INLINE_STYLES_PARSED = "hlsInlineStylesParsed", vr.SESSION_DATA_COMPLETE = "hlsSessionDataComplete", vr.FRAG_LOADING = "hlsFragLoading", vr.FRAG_LOADED = "hlsFragLoaded", vr.FRAG_BUFFERED = "hlsFragBuffered", vr.FRAG_CHANGED = "hlsFragChanged", vr.INTERNAL_ERROR = "hlsInternalError", vr.ERROR = "hlsError", vr.DESTROYING = "hlsDestroying", vr.KEY_REQUEST_STARTED = "hlsKeyRequestStarted", vr.LICENSE_CHALLENGE_CREATED = "hlsLicenseChallengeCreated", vr.LICENSE_RELEASED = "hlsLicenseReleased", vr.KEY_LOADED = "hlsKeyLoaded", vr.UNRESOLVED_URI_LOADING = "hlsUnresolvedUriLoading", vr.DESIRED_RATE_CHANGED = "hlsDesiredRateChanged", vr.PLAYER_STATE_CHANGE = "hlsPlayerStateChange", vr.SEEKING = "hlsSeeking", vr.SEEKED = "hlsSeeked", vr.STALLED = "hlsStalled", vr.RESUME_FROM_STALL = "hlsResumeFromStall", vr.READY_FOR_NEXT_ITEM = "hlsReadyForNextItem", vr.ITEM_TRANSITIONED = "hlsItemTransitioned", vr.ITEM_EVICTED = "hlsItemEvicted", vr.DATERANGE_UPDATED = "hlsDaterangeUpdated";
var v, x = P;
(dl = v = v || {}).FRAG_PARSING_INIT_SEGMENT = "hlsFragParsingInitSegment", dl.FRAG_PARSING_DATA = "hlsFragParsingData", dl.FRAG_PARSED = "hlsFragParsed", dl.INIT_PTS_FOUND = "hlsInitPtsFound";
class p extends Error {
constructor(e, t, i, r, n) {
super(r), this.type = e, this.details = t, this.fatal = i, this.reason = r, this.response = n, this.handled = !1
}
}
class R extends p {
constructor(e, t, i, r, n) {
super(e, t, i, r, n), this.response = n
}
}
const $ = {
PlaylistNotReceived: {
code: -12884,
text: "Playlist not received"
},
CryptResponseReceivedSlowly: {
code: -16833,
text: "Crypt key received slowly"
},
LivePlaylistUpdateError: {
code: -12888,
text: "Live playlist not updated"
},
NoResponseFromMediaRequest: {
code: -12889,
text: "No response for fragment"
},
IncompatibleAsset: {
code: -12927,
text: "IncompatibleAsset"
},
CorruptStream: {
code: -16041,
text: "Corrupt fragment"
},
InternalError: {
code: -12645,
text: "InternalException"
},
CantSwitchInTime: {
code: -12644,
text: "CantSwitchInTime"
},
VideoDecoderBadDataErr: {
code: -12909,
text: "Buffer error"
},
InsufficientDataAvailable: {
code: -12928,
text: "Incomplete data"
},
AllocationFailed: {
code: -12862,
text: "AllocationFailed"
},
PlaylistErrorMissingEXTM3U: {
code: -12269,
text: "Response doesnt have #EXTM3U tag"
},
PlaylistErrorInvalidEntry: {
code: -12264,
text: "Invalid entry"
},
PlaylistErrorBadTargetDuration: {
code: -12271,
text: "Invalid targetduration"
},
NoValidAlternates: {
code: -12925,
text: "No valid alternates"
},
FormatError: {
code: -12642,
text: "Incorrect playlist format"
},
UnsupportedKeySystemError: {
code: -6e4,
text: "Unsupported Key System"
},
EmptyLoadSourceError: {
code: -60001,
text: "Empty loadSource url"
},
UndefinedItemIdError: {
code: -60002,
text: "Undefined itemId"
},
ManifestParseError: {
code: -60003,
text: "Manifest parse error"
},
DemuxWorkerError: {
code: -60004,
text: "Demux worker error"
},
DecryptWorkerError: {
code: -60005,
text: "Decrypt worker error"
},
OutOfRangeSeekError: {
code: -60006,
text: "Seeked out of playable range"
},
ExceptionInKeyLoadError: {
code: -60007,
text: "Exception in Key load"
},
FragmentAbortError: {
code: -60008,
text: "Fragment abort error"
},
ManifestTimeoutError: {
code: -60009,
text: "Manifest Timeout Error"
},
PlaylistTimeoutError: {
code: -60010,
text: "Playlist Timeout Error"
},
FragmentTimeoutError: {
code: -60011,
text: "Fragment Timeout Error"
},
IncompleteSessionData: {
code: -60012,
text: "Session data not complete after loading all items"
},
SessionDataLoadTimeout: {
code: -60013,
text: "Session data load timeout"
},
FailedDemuxerSanityCheck: {
code: -60014,
text: "Failed demuxer sanity check"
},
InvalidADTSSamplingIndex: {
code: -60015,
text: "Invalid ADTS sampling index"
},
DemuxerNotFound: {
code: -60016,
text: "No demux matching with content found"
},
InvalidAC3Magic: {
code: -60029,
text: "Invalid ac-3 magic"
},
InvalidInitTimestamp: {
code: -60017,
text: "Invalid initPTS or initDTS"
},
NoAVSamplesFound: {
code: -60018,
text: "no audio/video samples found"
},
NoTSSyncByteFound: {
code: -60019,
text: "TS packet did not start with 0x47"
},
PESDidNotStartWithADTS: {
code: -60020,
text: "AAC PES did not start with ADTS header"
},
NoADTSHeaderInPES: {
code: -60021,
text: "No ADTS header found in AAC PES"
},
InvalidDolbyAudioMagic: {
code: -60022,
text: "Invalid dolby audio magic"
},
FailedToAllocateVideoMdat: {
code: -60023,
text: "Fail allocating video mdat"
},
FailedToAllocateAudioMdat: {
code: -60024,
text: "Fail allocating audio mdat"
},
InsufficientEC3Data: {
code: -60025,
text: "Error parsing ec-3, not enough data"
},
InvalidEC3Magic: {
code: -60026,
text: "Invalid ec-3 magic"
},
ReservedStreamType: {
code: -60027,
text: "Reserved stream type"
},
InsufficientAC3Data: {
code: -60028,
text: "error parsing ac-3, not enough data"
},
InvalidAC3SamplingRateCode: {
code: -60030,
text: "Invalid ac-3 samplingRateCode"
},
PlaylistErrorInvalidEXTXDEFINE: {
code: -61e3,
text: "Encountered undefined/not imported EXT-X-DEFINE property"
},
PlaylistErrorMissingImportReference: {
code: -61001,
text: "IMPORT references variable not in master playlist and/or NAME"
},
PlaylistErrorInvalidSERVERURI: {
code: -61002,
text: "Encountered undefined/invalid SERVER-URI attribute for EXT-X-CONTENT-STEERING tag"
},
PlaylistErrorInvalidPATHWAYID: {
code: -61003,
text: "Encountered invalid PATHWAY-ID attribute for EXT-X-CONTENT-STEERING tag"
},
PlaylistErrorInvalidSCORE: {
code: -61004,
text: "Encountered negative/non-number SCORE property"
},
KeySystemFailedToUpdateSession: {
code: -62e3,
text: "KeySystem: Promise Rejected while updating session"
},
KeySystemFailedToGenerateLicenseRenewal: {
code: -62001,
text: "KeySystem: Failed to generate license renewal"
},
KeySystemFailedToGenerateLicenseRequest: {
code: -62002,
text: "KeySystem: Failed to generate license request"
},
KeySystemAbort: {
code: -62003,
text: "KeySystem: Aborted"
},
KeySystemUnexpectedStateTransition: {
code: -62004,
text: "KeySystem: Unexpected state transition"
},
KeySystemUnexpectedState: {
code: -62005,
text: "KeySystem: Unexpected state"
},
KeySystemCDMUnknownError: {
code: -62006,
text: "KeySystem: Unknown error from CDM"
},
KeySystemRequestTimedOut: {
code: -62007,
text: "Key request timed out"
},
KeySystemUnexpectedMETHOD: {
code: -62008,
text: "Unexpected METHOD attribute"
},
KeySystemUnmatchedString: {
code: -62009,
text: "KeySystem: string does not match"
},
KeySystemInternalError: {
code: -62010,
text: "KeySystem: internal-error"
},
KeySystemOutputRestricted: {
code: -62011,
text: "KeySystem: output-restricted"
},
KeySystemSetupError: {
code: -62012,
text: "KeySystem: setup error"
},
KeySystemFailedToInitialize: {
code: -62013,
text: "KeySystem: could not initialize"
},
KeySystemFailedToCreateSession: {
code: -62014,
text: "KeySystem: could not create session"
},
KeySystemUndefinedNavigator: {
code: -62015,
text: "KeySystem: navigator undefined"
},
KeySystemNoKeySystemsToTry: {
code: -62016,
text: "KeySystem: no key systems to try"
},
KeySystemNoConstructor: {
code: -62017,
text: "KeySystem: No constructor"
},
KeySystemNoKeySystemAccess: {
code: -62018,
text: "KeySystem: No KeySystemAccess"
},
KeySystemCertificateLoadError: {
code: -62019,
text: "KeySystem: Certificate Load Error"
}
},
o = "networkError",
L = "mediaError",
s = "otherError",
_ = "manifestParsingError",
f = "manifestIncompatibleCodecsError",
N = "levelLoadError",
n = "bufferAppendError",
r = "internalException";
class V extends p {
constructor(e, t, i) {
super(s, r, e, t, i)
}
}
class D extends p {
constructor(e, t, i) {
super(L, "fragParsingError", e, t, i)
}
}
class F extends p {
constructor(e, t, i, r) {
super("muxError", "remuxAllocError", e, t, i), this.bytes = r
}
}
function S(e) {
return e.baseTime / e.timescale
}
function B(e, t) {
return {
baseTime: Math.floor(e * t),
timescale: t
}
}
function g(e, t) {
return S(e) < S(t) ? e : t
}
function y(e, t) {
return S(e) > S(t) ? e : t
}
function b(e, t) {
return S(e) - S(t)
}
var t = void 0 !== l.Buffer ? require("events").EventEmitter : class {
constructor() {
this.eventMap = {}
}
_on(e, t, i = !1) {
return null == this.eventMap[e] && (this.eventMap[e] = []), i ? this.eventMap[e].splice(0, 0, t) : this.eventMap[e].push(t), this
}
_off(e, t) {
return null != this.eventMap[e] && (this.eventMap[e] = this.eventMap[e].filter(e => e.listener !== t.listener), 0 === this.eventMap[e].length && delete this.eventMap[e]), this
}
on(e, t) {
return this._on(e, {
listener: t,
once: !1
})
}
off(e, t) {
return this._off(e, {
listener: t
})
}
addListener(e, t) {
return this.on(e, t)
}
once(e, t) {
return this._on(e, {
listener: t,
once: !0
})
}
removeListener(e, t) {
return this.off(e, t)
}
removeAllListeners(e) {
return delete this.eventMap[e], this
}
setMaxListeners(e) {
return this
}
getMaxListeners() {
return 1 / 0
}
listeners(e) {
return null == this.eventMap[e] ? [] : this.eventMap[e].map(e => e.listener)
}
rawListeners(e) {
return this.listeners(e)
}
emit(e, ...t) {
if (null == this.eventMap[e]) return !1;
let i = !1;
for (const r of this.eventMap[e]) {
try {
r.listener.apply(this, t)
} catch (e) {}
i = !0
}
return i
}
listenerCount(e) {
return null == this.eventMap[e] ? 0 : this.eventMap[e].length
}
prependListener(e, t) {
return this._on(e, {
listener: t,
once: !1
}, !0)
}
prependOnceListener(e, t) {
return this._on(e, {
listener: t,
once: !0
}, !0)
}
eventNames() {
return Object.keys(this.eventMap)
}
};
class a extends t {
trigger(e, t) {
this.emit(e, t)
}
}
function E(e, t, i, r, n) {
let s, a, o, l;
const d = navigator.userAgent.toLowerCase(),
u = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350];
s = 1 + ((192 & t[i + 2]) >>> 6);
var c = (60 & t[i + 2]) >>> 2;
if (!(u.length - 1 < c)) return o = (1 & t[i + 2]) << 2, o |= (192 & t[i + 3]) >>> 6, /firefox/i.test(d) ? 6 <= c ? (s = 5, l = new Array(4), a = c - 3) : (s = 2, l = new Array(2)) : -1 !== d.indexOf("android") ? (s = 2, l = new Array(2)) : (s = 5, l = new Array(4), a = r && (-1 !== r.indexOf("mp4a.40.29") || -1 !== r.indexOf("mp4a.40.5")) || !r && 6 <= c ? c - 3 : ((r && -1 !== r.indexOf("mp4a.40.2") || !r && 1 == o) && (s = 2, l = new Array(2)), c)), l[0] = s << 3, l[0] |= (14 & c) >> 1, l[1] |= (1 & c) << 7, l[1] |= o << 3, 5 === s && (l[1] |= (14 & a) >> 1, l[2] = (1 & a) << 7, l[2] |= 8, l[3] = 0), {
esdsConfig: l,
samplerate: u[c],
channelCount: o,
segmentCodec: "aac",
codec: "mp4a.40." + s
}; {
const t = new D(!0, `invalid ADTS sampling index:${c}`, $.InvalidADTSSamplingIndex);
e.trigger(x.INTERNAL_ERROR, t)
}
}
class u {
constructor(e, t, i, r, n) {
this.observer = e, this.remuxer = t, this.config = i, this.typeSupported = r, this.logger = n
}
static probe(e, t) {
throw new Error("Method not implemented")
}
resetTimeStamp(e) {}
resetInitSegment(e, t, i, r) {}
destroy() {}
}
class c extends u {
constructor(e, t, i, r, n) {
super(e, t, i, r, n), this.observer = e, this.remuxer = t, this.config = i, this.typeSupported = r, this.logger = n, this.esRemuxer = t
}
}
class h {
constructor(e, t, i) {
this.observer = e, this.config = t, this.logger = i
}
resetInitSegment() {}
resetTimeStamp(e) {}
destroy() {}
}
let m, I;
var w = {
strToUtf8array: e => (m = m || new TextEncoder, m.encode(e)),
utf8arrayToStr: e => (I = I || new TextDecoder("utf-8"), I.decode(e))
},
A = {
strToUtf8array(e) {
e = l.Buffer.from(e, "utf-8");
return new Uint8Array(e.buffer, e.byteOffset, e.byteLength)
},
utf8arrayToStr: e => l.Buffer.from(e).toString("utf-8")
};
let O = {
strToUtf8array(e) {
const t = unescape(encodeURIComponent(e)),
i = new Uint8Array(t.length);
for (let e = 0; e < t.length; e++) i[e] = t.charCodeAt(e);
return i
},
utf8arrayToStr: e => String.fromCharCode.apply(null, Array.from(e))
};
"undefined" != typeof TextEncoder && "undefined" != typeof TextDecoder ? O = w : "function" == typeof(null === (fl = l.Buffer) || void 0 === fl ? void 0 : fl.from) && (O = A);
const k = {
name: "ID3"
};
class C {
constructor(e, t) {
this.logger = t, this._hasTimeStamp = !1, this._audioType = null, this._length = 0, this._frames = [];
let i, r, n, s, a = 0;
for (;;)
if (n = C.readUTF(e, a, 3), a += 3, "ID3" === n) {
this._minor = e[a++], this._revision = e[a++];
const t = e[a++];
if (128 & t && (this._unsynchronized = !0, this.logger.error(k, "id3 tag is unsynchronized")), 64 & t && (this._hasExtendedHeader = !0, this.logger.warn(k, "id3 tag has extended header")), i = C.readSynchSafeUint32(e.subarray(a, a + 4)), a += 4, r = a + i, this._hasExtendedHeader) {
const t = C.readSynchSafeUint32(e.subarray(a, a + 4));
this.logger.warn(k, `id3 tag has ${t}-byte extended header. usually 6 or 10 bytes`), a += t
}
2 < this.minor ? this._parseID3Frames(e, a, r) : this.logger.error(k, "[id3] doesn't support older than v2.3 tags"), a = r
} else {
if ("3DI" !== n) return a -= 3, void((s = a) && (this.hasTimeStamp || this.logger.warn(k, "ID3 tag found, but no timestamp"), this._length = s, this._payload = e.slice(0, s)));
a += 7
}
}
static isHeader(e, t) {
return 73 === e[t] && 68 === e[t + 1] && 51 === e[t + 2] && e[t + 3] < 255 && e[t + 4] < 255 && e[t + 6] < 128 && e[t + 7] < 128 && e[t + 8] < 128 && e[t + 9] < 128
}
static readSynchSafeUint32(e) {
return 2097152 * (127 & e[0]) + 16384 * (127 & e[1]) + 128 * (127 & e[2]) + (127 & e[3])
}
static readUTF(e, t, i) {
let r = "",
n = t;
for (var s = t + i; r += String.fromCharCode(e[n++]), n < s;);
return r
}
isID3Frame(e, t) {
return e[t + 4] < 128 && e[t + 5] < 128 && e[t + 6] < 128 && e[t + 7] < 128
}
decodeID3Frame(e) {
return "TXXX" === e.type ? this.decodeTxxxFrame(e) : "WXXX" === e.type ? this.decodeWxxxFrame(e) : "PRIV" === e.type ? this.decodePrivFrame(e) : "T" === e.type[0] ? this.decodeTextFrame(e) : {
key: e.type,
data: e.data
}
}
decodeTxxxFrame(e) {
if (!(e.size < 2) && 3 === e.data[0]) {
var t = 1,
i = this.id3utf8ArrayToStr(e.data.subarray(1));
return t += i.length + 1, {
key: "TXXX",
description: i,
data: this.id3utf8ArrayToStr(e.data.subarray(t))
}
}
}
decodeWxxxFrame(e) {
if (!(e.size < 2) && 3 === e.data[0]) {
var t = 1,
i = this.id3utf8ArrayToStr(e.data.subarray(1));
return t += i.length + 1, {
key: "WXXX",
description: i,
data: O.utf8arrayToStr(e.data.subarray(t))
}
}
}
decodeTextFrame(e) {
if (!(e.size < 2) && 3 === e.data[0]) {
var t = e.data.subarray(1);
return {
key: e.type,
data: this.id3utf8ArrayToStr(t)
}
}
}
decodePrivFrame(e) {
if (!(e.size < 2)) {
var t = this.id3utf8ArrayToStr(e.data);
return {
key: "PRIV",
info: t,
data: e.data.slice(t.length + 1)
}
}
}
_extractID3Frame(e, t, i, r, n) {
var s = r + i;
let a;
return s <= n ? a = {
type: t,
data: e.slice(r, s)
} : this.logger.error(k, `id3 frame ${t} size ${i} exceeded ${n}`), a
}
_parseID3Frames(e, t, i) {
let r, n, s, a;
for (; t + 8 <= i;) {
if (!this.isID3Frame(e, t)) return void this.logger.error(k, `[id3] illegal id3 frame @ offset ${t}. skip this id3 tag`);
if (r = C.readUTF(e, t, 4), t += 4, "" === r) return;
if (0 === (n = C.readSynchSafeUint32(e.subarray(t, t + 4)))) return;
t += 4, e[t++], e[t++], s = t;
var o = this._extractID3Frame(e, r, n, s, i);
if (o) {
const e = this.decodeID3Frame(o);
this._frames.push(e)
}
if ("PRIV" === r)
if (53 === n && "com.apple.streaming.transportStreamTimestamp" === C.readUTF(e, t, 44)) {
t += 44, t += 4;
const i = 1 & e[t++];
this._hasTimeStamp = !0, a = ((e[t++] << 23) + (e[t++] << 15) + (e[t++] << 7) + e[t++]) / 45, i && (a += 47721858.84), a = Math.round(a), this._timeStamp = a
} else 45 <= n && "com.apple.streaming.audioDescription" === C.readUTF(e, t, 36) ? (t += 37, this._audioType = C.readUTF(e, t, 4), t += 4, t += n - 41) : t += n;
else t += n
}
}
id3utf8ArrayToStr(e) {
let t, i, r = "",
n = 0;
const s = e.length;
for (; n < s;) {
const s = e[n++];
switch (s >> 4) {
case 0:
return r;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
r += String.fromCharCode(s);
break;
case 12:
case 13:
t = e[n++], r += String.fromCharCode((31 & s) << 6 | 63 & t);
break;
case 14:
t = e[n++], i = e[n++], r += String.fromCharCode((15 & s) << 12 | (63 & t) << 6 | (63 & i) << 0)
}
}
}
get hasTimeStamp() {
return this._hasTimeStamp
}
get timeStamp() {
return this._timeStamp
}
get audioType() {
return this._audioType
}
get length() {
return this._length
}
get payload() {
return this._payload
}
get frames() {
return this._frames
}
get minor() {
return this._minor
}
get revision() {
return this._revision
}
}
var M = C;
const U = {
name: "AACDemuxer"
};
class K extends c {
resetInitSegment(e, t) {
this.audioConfig = void 0, this.audioTrack = void 0, this.duration = t
}
static probe(e, t) {
let i, r;
for (i = new M(e, t).length, r = Math.min(e.length - 1, i + 100); i < r; i++)
if (255 === e[i] && 240 == (246 & e[i + 1])) return !0;
return !1
}
append(e, t, i, r, n) {
var s = new M(e, this.logger),
a = s.hasTimeStamp ? 90 * s.timeStamp : 9e4 * t;
let o, l, d, u, c, h, p, f, m, g;
for (s.length && (g = s.payload, s.frames.length && (m = s.frames), f = {
id3Samples: [{
pts: a,
dts: a,
data: g,
frames: m
}],
inputTimescale: 9e4
}), d = s.length, h = e.length; d < h - 1 && (255 !== e[d] || 240 != (246 & e[d + 1])); d++);
if (!this.audioConfig && (this.audioConfig = E(this.observer, e, d, void 0, this.logger), !this.audioConfig)) throw "failed to parse adts config";
if (!this.audioTrack) {
const e = {
id: 258,
inputTimescale: 9e4,
timescale: NaN,
duration: this.duration,
encrypted: !1,
keyTagInfo: n
},
t = {
len: 0,
sequenceNumber: 0,
esSamples: []
};
this.audioTrack = {
info: e,
parsingData: t,
type: "audio",
config: this.audioConfig
}
}
"zaac" !== s.audioType && "zach" !== s.audioType && "zacp" !== s.audioType || (this.audioTrack.info.encrypted = !0), l = 0;
for (var y = 9216e4 / this.audioConfig.samplerate; d + 5 < h && (u = 1 & e[d + 1] ? 7 : 9, o = (3 & e[d + 3]) << 11 | e[d + 4] << 3 | (224 & e[d + 5]) >>> 5, o -= u, 0 < o && d + u + o <= h);)
for (c = a + l * y, p = {
unit: e.subarray(d + u, d + u + o),
pts: c,
dts: c,
keyTagInfo: n
}, this.audioTrack.parsingData.esSamples.push(p), this.audioTrack.parsingData.len += o, d += o + u, l++; d < h - 1; d++) {
if (M.isHeader(e, d)) {
const t = new M(e.subarray(d), this.logger);
if (0 < t.length) {
d += t.length;
const e = t.hasTimeStamp ? 90 * t.timeStamp : a;
f.id3Samples.push({
pts: e,
dts: e,
data: t.payload,
frames: t.frames
})
} else this.logger.error(U, `[id3] invalid length ${h}`)
}
if (255 === e[d] && 240 == (246 & e[d + 1])) break
}
this.esRemuxer.remuxEsTracks(this.audioTrack, void 0, f, void 0, t, i, r, n)
}
}
class q {
bsReadAndUpdate(e, t, i) {
e = this.readBits(e, t, i);
return this.updateOffset(t, i), e
}
bsWriteAndUpdate(e, t, i, r) {
r = this.writeBits(e, t, i, r);
return this.updateOffset(t, i), r
}
bsSkip(e, t) {
this.updateOffset(e, t)
}
readBits(i, r, n) {
if (i && r) {
let t = r.byteOffset;
const s = r["usedBits"];
if (!(8 <= s || 32 < s + n)) {
let e;
const a = new Uint32Array(1),
o = new Uint32Array(1),
l = new Uint8Array(1);
if (!(8 <= s || 32 < n)) {
if (s) {
const r = 8 - s,
a = n < r ? r - n : 0;
o[0] = 4278190080 >>> 32 - r, e = (i[t] & o[0]) >>> a, t += 1, n -= r
}
for (; 0 < n;) {
l[0] = i[t];
const r = Math.min(n, 8),
s = 8 - r;
o[0] = 4278190080 >>> 24 + s << s, a[0] = (l[0] & o[0]) >> s, e = e ? e << r | a[0] : a[0], t += 1, n -= r
}
return e
}
}
}
}
writeBits(t, i, r, n) {
if (t && i) {
let e = i.byteOffset;
var i = i["usedBits"];
if (!(8 <= i || 32 < i + r)) {
const s = new Uint32Array(1),
a = new Uint32Array(1),
o = new Uint32Array(1),
l = new Uint8Array(1);
for (s[0] = n, i && (a[0] = s[0] << 32 - r, o[0] = 4278190080, l[0] = (a[0] & o[0]) >>> 24 + i, t[e] &= ~(o[0] >>> 24 + i), t[e] |= l[0], e += 1, r -= 8 - i); 0 < r;) {
a[0] = s[0] << 32 - r, o[0] = 4278190080, l[0] = (a[0] & o[0]) >>> 24;
const d = r < 0 ? 8 - r : 0;
t[e] &= ~(o[0] >>> 24 >>> d << d), t[e] |= l[0], r -= 8, e += 1
}
return 0
}
}
}
updateOffset(e, t) {
var i, r;
!e || !t || 32 < e.usedBits + t || (i = e.usedBits % 8, r = Math.floor((i + t) / 8), t = (i + t) % 8, e.byteOffset += r, e.usedBits = t)
}
}
function H(e, t) {
return 1536 / e.samplerate * t
}
function j(e, t, i, r) {
let n;
if (i + 8 > t.length) return n = new D(!0, "error parsing ac-3, not enough data", $.InsufficientAC3Data), void e.trigger(x.INTERNAL_ERROR, n);
if (11 !== t[i] || 119 !== t[i + 1]) return n = new D(!0, "invalid ac-3 magic", $.InvalidAC3Magic), void e.trigger(x.INTERNAL_ERROR, n);
var s = t[i + 4] >> 6;
if (3 <= s) return n = new D(!0, `invalid ac-3 samplingRateCode:${s}`, $.InvalidAC3SamplingRateCode), void e.trigger(x.INTERNAL_ERROR, n);
var a = 63 & t[i + 4],
o = t[i + 6] >> 5;
let l = 0;
2 == o ? l += 2 : (1 & o && 1 != o && (l += 2), 4 & o && (l += 2));
var d = (t[i + 6] << 8 | t[i + 7]) >> 12 - l & 1,
u = [2, 1, 2, 3, 3, 4, 4, 5][o] + d,
e = t[i + 5] >> 3,
i = 7 & t[i + 5];
return {
samplerate: W[s],
channelCount: u,
segmentCodec: "ac3",
codec: "ac-3",
extraData: s << 22 | e << 17 | i << 14 | o << 11 | d << 10 | a >> 1 << 5
}
}
function Q(e, t, i) {
let r;
if (i + 8 > t.length) return r = new D(!0, "error parsing ac-3, not enough data", $.InsufficientAC3Data), void e.trigger(x.INTERNAL_ERROR, r);
if (11 !== t[i] || 119 !== t[i + 1]) return r = new D(!0, "invalid ac-3 magic", $.InvalidAC3Magic), void e.trigger(x.INTERNAL_ERROR, r);
var n = t[i + 4] >> 6;
return 3 <= n ? (r = new D(!0, `invalid ac-3 samplingRateCode:${n}`, $.InvalidAC3SamplingRateCode), void e.trigger(x.INTERNAL_ERROR, r)) : (i = 63 & t[i + 4], 2 * G[3 * i + n])
}
const W = [48e3, 44100, 32e3],
G = [64, 69, 96, 64, 70, 96, 80, 87, 120, 80, 88, 120, 96, 104, 144, 96, 105, 144, 112, 121, 168, 112, 122, 168, 128, 139, 192, 128, 140, 192, 160, 174, 240, 160, 175, 240, 192, 208, 288, 192, 209, 288, 224, 243, 336, 224, 244, 336, 256, 278, 384, 256, 279, 384, 320, 348, 480, 320, 349, 480, 384, 417, 576, 384, 418, 576, 448, 487, 672, 448, 488, 672, 512, 557, 768, 512, 558, 768, 640, 696, 960, 640, 697, 960, 768, 835, 1152, 768, 836, 1152, 896, 975, 1344, 896, 976, 1344, 1024, 1114, 1536, 1024, 1115, 1536, 1152, 1253, 1728, 1152, 1254, 1728, 1280, 1393, 1920, 1280, 1394, 1920];
class z extends c {
resetInitSegment(e, t) {
this.audioConfig = void 0, this.audioTrack = void 0, this.duration = t
}
static probe(e, t) {
var i = new M(e, t),
t = i.length;
return !!(i.hasTimeStamp && 11 === e[t] && 119 === e[t + 1] && (new q).bsReadAndUpdate(e, {
byteOffset: t + 5,
usedBits: 0
}, 5) < 16)
}
append(e, t, i, r, n) {
var s = new M(e, this.logger),
a = 90 * s.timeStamp,
o = e.byteLength;
let l = 0,
d = s.length;
if (this.audioConfig || (this.audioConfig = j(this.observer, e, d, this.logger)), !this.audioConfig) throw "failed to parse ac3 config";
if (!this.audioTrack) {
const e = {
id: 258,
inputTimescale: 9e4,
timescale: NaN,
duration: this.duration,
encrypted: !1,
keyTagInfo: n
},
t = {
len: 0,
sequenceNumber: 0,
esSamples: []
};
this.audioTrack = {
info: e,
parsingData: t,
type: "audio",
config: this.audioConfig
}
}
var u = H(this.audioConfig, this.audioTrack.info.inputTimescale);
for ("zac3" === s.audioType && (this.audioTrack.info.encrypted = !0); d < o;) {
if (M.isHeader(e, d) && (d += new M(e.subarray(d), this.logger).length), 11 !== e[d] || 119 !== e[d + 1]) {
const e = new D(!0, "invalid ac-3 magic", $.InvalidAC3Magic);
return void this.observer.trigger(x.INTERNAL_ERROR, e)
}
const t = Q(this.observer, e, d),
i = a + l * u,
r = {
unit: e.subarray(d, d + t),
pts: i,
dts: i,
keyTagInfo: n
};
this.audioTrack.parsingData.esSamples.push(r), this.audioTrack.parsingData.len += t, d += t, l++
}
this.esRemuxer.remuxEsTracks(this.audioTrack, void 0, {
id3Samples: [{
pts: a,
dts: a,
data: s.payload,
frames: s.frames
}],
inputTimescale: this.audioTrack.info.inputTimescale
}, void 0, t, i, r, n)
}
}
var X = function(t, i, r, n) {
const s = new q;
let a, o = !1,
l = 0;
for (; r < i.length;) {
if (r + 8 > i.length) return a = new D(!0, "error parsing ec-3, not enough data", $.InsufficientEC3Data), void t.trigger(x.INTERNAL_ERROR, a);
let e = 0;
if (M.isHeader(i, r) && (e = new M(i.subarray(r), n).length || 0, r += e), 11 !== i[r] || 119 !== i[r + 1]) return a = new D(!0, "invalid ec-3 magic", $.InvalidEC3Magic), void t.trigger(x.INTERNAL_ERROR, a);
var d = {
byteOffset: r + 2,
usedBits: 0
},
u = s.bsReadAndUpdate(i, d, 2),
c = s.bsReadAndUpdate(i, d, 3);
if (0 === u || 2 === u)
if (!0 === o) {
if (0 === c) break
} else o = !0;
else if (1 !== u) return a = new D(!0, "reserved stream type", $.ReservedStreamType), void t.trigger(x.INTERNAL_ERROR, a);
d = 2 * (s.bsReadAndUpdate(i, d, 11) + 1);
r += d, l += d + (e || 0)
}
return l
},
Y = function(t, i, r, n) {
const s = {
frmsiz: 0,
fscod: 0,
numblkscod: 0,
acmod: 0,
lfeon: 0,
bsid: 0,
strmtyp: 0,
substreamid: 0,
chanmape: 0,
chanmap: 0,
mixdef: 0,
mixdeflen: 0,
bsmod: 0
},
a = {
fscod: 0,
acmod: 0,
lfeon: 0,
bsid: 0,
bsmod: 0,
chan_loc: 0,
data_rate: 0,
num_ind_sub: 0,
num_dep_sub: [],
complexity_index_type_a: 0
},
o = new q;
let l, d = !1,
u = 0;
for (; r < i.length;) {
if (r + 8 > i.length) return l = new D(!0, "error parsing ec-3, not enough data", $.InsufficientEC3Data), void t.trigger(x.INTERNAL_ERROR, l);
let e = 0;
if (M.isHeader(i, r) && (e = new M(i.subarray(r), n).length || 0, r += e), 11 !== i[r] || 119 !== i[r + 1]) return l = new D(!0, "invalid ec-3 magic", $.InvalidEC3Magic), void t.trigger(x.INTERNAL_ERROR, l);
const h = {
byteOffset: r + 2,
usedBits: 0
};
if (s.strmtyp = o.bsReadAndUpdate(i, h, 2), s.substreamid = o.bsReadAndUpdate(i, h, 3), 0 === s.strmtyp || 2 === s.strmtyp) {
if (!0 === d) {
if (0 === s.substreamid) break
} else d = !0;
a.num_ind_sub++, a.num_dep_sub.push(0)
} else {
if (1 !== s.strmtyp) return l = new D(!0, "reserved stream type", $.ReservedStreamType), void t.trigger(x.INTERNAL_ERROR, l);
a.num_dep_sub[a.num_ind_sub - 1]++
}
if (s.frmsiz = o.bsReadAndUpdate(i, h, 11), s.fscod = o.bsReadAndUpdate(i, h, 2), 3 === s.fscod ? (o.bsSkip(h, 2), s.numblkscod = 3) : s.numblkscod = o.bsReadAndUpdate(i, h, 2), s.acmod = o.bsReadAndUpdate(i, h, 3), s.lfeon = o.bsReadAndUpdate(i, h, 1), s.bsid = o.bsReadAndUpdate(i, h, 5), o.bsSkip(h, 5), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 8), 0 === s.acmod && (o.bsSkip(h, 5), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 8)), 1 === s.strmtyp && (s.chanmape = o.bsReadAndUpdate(i, h, 1), s.chanmape && (s.chanmap = o.bsReadAndUpdate(i, h, 16))), o.bsReadAndUpdate(i, h, 1) && (2 < s.acmod && o.bsSkip(h, 2), 1 & s.acmod && 2 < s.acmod && o.bsSkip(h, 6), 4 & s.acmod && o.bsSkip(h, 6), s.lfeon && o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 5), 0 === s.strmtyp)) {
if (o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 6), 0 === s.acmod && o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 6), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 6), s.mixdef = o.bsReadAndUpdate(i, h, 2), 1 === s.mixdef) o.bsSkip(h, 5);
else if (2 === s.mixdef) o.bsSkip(h, 12);
else if (3 === s.mixdef) {
s.mixdeflen = o.bsReadAndUpdate(i, h, 5), o.bsReadAndUpdate(i, h, 1) && (o.bsSkip(h, 5), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4), o.bsReadAndUpdate(i, h, 1) && (o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 4))), o.bsReadAndUpdate(i, h, 1) && (o.bsSkip(h, 5), o.bsReadAndUpdate(i, h, 1) && (o.bsSkip(h, 7), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 8)));
const t = s.mixdeflen + 2 + (h.usedBits ? 1 : 0);
h.byteOffset += t
}
if (s.acmod < 2 && (o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 14), 0 === s.acmod && o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 14)), o.bsReadAndUpdate(i, h, 1))
if (0 === s.numblkscod) o.bsSkip(h, 5);
else
for (let e = 0; e < s.numblkscod; e++) o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 5)
}
if (s.bsmod = 0, o.bsReadAndUpdate(i, h, 1) && (s.bsmod = o.bsReadAndUpdate(i, h, 3), o.bsSkip(h, 2), 2 === s.acmod && o.bsSkip(h, 4), 6 <= s.acmod && o.bsSkip(h, 2), o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 8), 0 === s.acmod && o.bsReadAndUpdate(i, h, 1) && o.bsSkip(h, 8), s.fscod < 3 && o.bsSkip(h, 1)), 0 === s.strmtyp && 3 !== s.numblkscod && o.bsSkip(h, 1), 2 !== s.strmtyp || (3 === s.numblkscod ? 1 : o.bsReadAndUpdate(i, h, 1)) && o.bsReadAndUpdate(i, h, 6), o.bsReadAndUpdate(i, h, 1)) {
const t = o.bsReadAndUpdate(i, h, 6);
if (0 === s.strmtyp && 0 === s.substreamid && 1 === t) {
const t = o.bsReadAndUpdate(i, h, 7),
r = o.bsReadAndUpdate(i, h, 1),
n = o.bsReadAndUpdate(i, h, 8);
0 === t && 1 === r && 1 <= n && n <= 16 && (a.complexity_index_type_a = n)
}
}
if (s.chanmape) a.chan_loc |= s.chanmap;
else {
const t = [40960, 16384, 40960, 57344, 41472, 57856, 47104, 63488];
a.chan_loc |= t[s.acmod]
}
0 === s.strmtyp && (a.fscod = s.fscod, a.bsid = s.bsid, a.bsmod = s.bsmod, a.acmod = s.acmod, a.lfeon = s.lfeon), a.chan_loc |= s.lfeon ? 1 : 0;
const p = 2 * (s.frmsiz + 1);
r += p, u += p + (e || 0)
}
let c = 0;
for (let e = 0; e < 16; e++) a.chan_loc & 1 << e && c++;
a.lfeon && c++;
let h = 10 + 3 * a.num_ind_sub;
const p = [48e3, 44100, 32e3][a.fscod];
a.data_rate = p / 1536 * u * 8, h = 10 + 3 * a.num_ind_sub;
for (let e = 0; e < a.num_ind_sub; e++) 0 < a.num_dep_sub[e] && h++;
0 < a.complexity_index_type_a && (h += 2);
var f = new Uint8Array(h),
m = {
byteOffset: 0,
usedBits: 0
};
o.bsWriteAndUpdate(f, m, 32, h), o.bsWriteAndUpdate(f, m, 32, 1684366131), o.bsWriteAndUpdate(f, m, 13, a.data_rate), o.bsWriteAndUpdate(f, m, 3, a.num_ind_sub);
for (let e = 0; e < a.num_ind_sub; e++) o.bsWriteAndUpdate(f, m, 2, a.fscod), o.bsWriteAndUpdate(f, m, 5, a.bsid), o.bsWriteAndUpdate(f, m, 1, 0), o.bsWriteAndUpdate(f, m, 1, 0 === e ? 0 : 1), o.bsWriteAndUpdate(f, m, 3, a.bsmod), o.bsWriteAndUpdate(f, m, 3, a.acmod), o.bsWriteAndUpdate(f, m, 1, a.lfeon), o.bsWriteAndUpdate(f, m, 3, 0), o.bsWriteAndUpdate(f, m, 4, a.num_dep_sub[e]), 0 < a.num_dep_sub[e] ? o.bsWriteAndUpdate(f, m, 9, a.chan_loc) : o.bsWriteAndUpdate(f, m, 1, 0);
return 0 < a.complexity_index_type_a && (o.bsWriteAndUpdate(f, m, 7, 0), o.bsWriteAndUpdate(f, m, 1, 1), o.bsWriteAndUpdate(f, m, 8, a.complexity_index_type_a)), {
samplerate: p,
channelCount: c,
segmentCodec: "ec3",
codec: "ec-3",
extraDataBytes: f
}
};
class J extends c {
resetInitSegment(e, t) {
this.audioConfig = void 0, this.audioTrack = void 0, this.duration = t
}
static probe(e, t) {
var i = new M(e, t),
t = i.length;
return !(!i.hasTimeStamp || 11 !== e[t] || 119 !== e[t + 1] || 16 !== (new q).bsReadAndUpdate(e, {
byteOffset: t + 5,
usedBits: 0
}, 5))
}
append(e, t, i, r, n) {
var s = new M(e, this.logger),
a = 90 * s.timeStamp,
o = e.length;
let l = 0,
d = s.length;
if (this.audioConfig || (this.audioConfig = Y(this.observer, e, d, this.logger)), !this.audioConfig) throw "failed to parse ec-3 config";
if (!this.audioTrack) {
const e = {
id: 258,
inputTimescale: 9e4,
timescale: NaN,
duration: this.duration,
encrypted: !1,
keyTagInfo: n
},
t = {
len: 0,
sequenceNumber: 0,
esSamples: []
};
this.audioTrack = {
info: e,
parsingData: t,
type: "audio",
config: this.audioConfig
}
}
var u = H(this.audioConfig, this.audioTrack.info.inputTimescale);
for ("zec3" === s.audioType && (this.audioTrack.info.encrypted = !0); d < o;) {
const t = X(this.observer, e, d, this.logger),
i = a + l * u,
r = {
unit: e.subarray(d, d + t),
pts: i,
dts: i,
keyTagInfo: n
};
this.audioTrack.parsingData.esSamples.push(r), this.audioTrack.parsingData.len += t, d += t, l++
}
this.esRemuxer.remuxEsTracks(this.audioTrack, void 0, {
id3Samples: [{
pts: a,
dts: a,
data: s.payload,
frames: s.frames
}],
inputTimescale: this.audioTrack.info.inputTimescale
}, void 0, t, i, r, n)
}
}
const Z = {
BitratesMap: [32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
SamplingRateMap: [44100, 48e3, 32e3, 22050, 24e3, 16e3, 11025, 12e3, 8e3],
SamplesCoefficients: [
[0, 72, 144, 12],
[0, 0, 0, 0],
[0, 72, 144, 12],
[0, 144, 144, 12]
],
BytesInSlot: [0, 1, 1, 4],
onFrame: function(e, t, i, r, n, s, a) {
r = a + s * (10368e4 / r);
e.esSamples.push({
unit: t,
pts: r,
dts: r
}), e.len += t.length
},
onNoise: function(e, t) {
t.warn("mpeg audio has noise: " + e.length + " bytes")
},
parseFrames: function(e, t, i, r, n, s, a) {
if (r < i + 2) return -1;
if (255 === t[i] || 224 == (224 & t[i + 1])) {
if (r < i + 24) return -1;
const a = t[i + 1] >> 3 & 3,
c = t[i + 1] >> 1 & 3,
h = t[i + 2] >> 4 & 15,
p = t[i + 2] >> 2 & 3,
f = !!(2 & t[i + 2]);
if (1 != a && 0 != h && 15 != h && 3 != p) {
var o = 1e3 * [32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160][14 * (3 == a ? 3 - c : 3 == c ? 3 : 4) + h - 1],
l = [44100, 48e3, 32e3, 22050, 24e3, 16e3, 11025, 12e3, 8e3][3 * (3 == a ? 0 : 2 == a ? 1 : 2) + p],
d = f ? 1 : 0,
u = t[i + 3] >> 6 == 3 ? 1 : 2,
d = 3 == c ? (3 == a ? 12 : 6) * o / l + d << 2 : (3 == a ? 144 : 72) * o / l + d | 0;
return r < i + d ? -1 : (Z.onFrame(e, t.subarray(i, i + d), o, l, u, n, s), d)
}
}
let c = i + 2;
for (; c < r;) {
if (255 === t[c - 1] && 224 == (224 & t[c])) return Z.onNoise(t.subarray(i, c - 1), a), c - i - 1;
c++
}
return -1
},
parse: function(e, t, i, r, n) {
var s = t.length;
let a, o = 0;
for (; i < s && 0 < (a = Z.parseFrames(e, t, i, s, o++, r, n));) i += a
},
getAudioConfig: function(e, t) {
var i = e[t + 1] >> 3 & 3,
r = e[t + 1] >> 1 & 3,
n = e[t + 2] >> 4 & 15,
s = e[t + 2] >> 2 & 3,
a = e[t + 2] >> 1 & 1;
if (1 != i && 0 != n && 15 != n && 3 != s) {
var o = 3 == i ? 3 - r : 3 == r ? 3 : 4,
o = 1e3 * Z.BitratesMap[14 * o + n - 1],
n = 3 == i ? 0 : 2 == i ? 1 : 2,
s = Z.SamplingRateMap[3 * n + s],
t = e[t + 3] >> 6 == 3 ? 1 : 2,
i = Z.SamplesCoefficients[i][r],
r = Z.BytesInSlot[r];
return {
segmentCodec: "mp3",
codec: "mp3",
samplerate: s,
channelCount: t,
frameLength: parseInt(i * o / s + a, 10) * r
}
}
},
isHeaderPattern: function(e, t) {
return 255 === e[t] && 224 == (224 & e[t + 1]) && 0 != (6 & e[t + 1])
},
probe: function(t, i) {
if (i + 1 < t.length && Z.isHeaderPattern(t, i)) {
var r = Z.getAudioConfig(t, i);
let e = 4;
r && r.frameLength && (e = r.frameLength);
i = i + e;
if (i === t.length || i + 1 < t.length && Z.isHeaderPattern(t, i)) return !0
}
return !1
}
};
var ee = Z;
const te = {
name: "MP3Demuxer"
};
class ie extends c {
resetInitSegment(e, t) {
this.audioConfig = void 0, this.audioTrack = void 0, this.duration = t
}
static probe(e, t) {
var i = new M(e, t);
let r, n;
if (i.hasTimeStamp)
for (r = i.length, n = Math.min(e.length - 1, r + 100); r < n; r++)
if (ee.probe(e, r)) return t.warn(te, "MPEG Audio sync word found !"), !0;
return !1
}
append(e, t, i, r, n) {
var s = new M(e, this.logger),
a = 90 * s.timeStamp;
if (this.audioConfig || (this.audioConfig = ee.getAudioConfig(e, s.length)), !this.audioConfig) throw "unable to parse mp3 header";
if (!this.audioTrack) {
const e = {
id: 258,
inputTimescale: 9e4,
timescale: NaN,
duration: this.duration,
encrypted: !1,
keyTagInfo: n
},
t = {
len: 0,
sequenceNumber: 0,
esSamples: []
};
this.audioTrack = {
info: e,
parsingData: t,
type: "audio",
config: this.audioConfig
}
}
ee.parse(this.audioTrack.parsingData, e, s.length, a, this.logger), this.esRemuxer.remuxEsTracks(this.audioTrack, void 0, {
id3Samples: [{
pts: a,
dts: a,
data: s.payload,
frames: s.frames
}],
inputTimescale: 9e4
}, void 0, t, i, r)
}
}
function re(e, t) {
if ("mp4a.40.2" === e) {
if (1 === t) return new Uint8Array([0, 200, 0, 128, 35, 128]);
if (2 === t) return new Uint8Array([33, 0, 73, 144, 2, 25, 0, 35, 128]);
if (3 === t) return new Uint8Array([0, 200, 0, 128, 32, 132, 1, 38, 64, 8, 100, 0, 142]);
if (4 === t) return new Uint8Array([0, 200, 0, 128, 32, 132, 1, 38, 64, 8, 100, 0, 128, 44, 128, 8, 2, 56]);
if (5 === t) return new Uint8Array([0, 200, 0, 128, 32, 132, 1, 38, 64, 8, 100, 0, 130, 48, 4, 153, 0, 33, 144, 2, 56]);
if (6 === t) return new Uint8Array([0, 200, 0, 128, 32, 132, 1, 38, 64, 8, 100, 0, 130, 48, 4, 153, 0, 33, 144, 2, 0, 178, 0, 32, 8, 224])
} else {
if (1 === t) return new Uint8Array([1, 64, 34, 128, 163, 78, 230, 128, 186, 8, 0, 0, 0, 28, 6, 241, 193, 10, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 94]);
if (2 === t) return new Uint8Array([1, 64, 34, 128, 163, 94, 230, 128, 186, 8, 0, 0, 0, 0, 149, 0, 6, 241, 161, 10, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 94]);
if (3 === t) return new Uint8Array([1, 64, 34, 128, 163, 94, 230, 128, 186, 8, 0, 0, 0, 0, 149, 0, 6, 241, 161, 10, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 94])
}
return null
}
function ne(e) {
return "number" == typeof e && isFinite(e)
}
function se(e, t) {
return ne(e) ? e.toFixed(t) : `${e}`
}
function ae(e, i = 3) {
return JSON.stringify(e, (e, t) => !isNaN(t) && null != t && t.toFixed ? Number(null == t ? void 0 : t.toFixed(i)) : t)
}
let oe = !0;
function le(e) {
return oe ? "" : e
}
function de(e) {
if (!e) return e;
if ("object" != typeof e) return e; {
if (Array.isArray(e)) return e.map(de);
const r = {};
for (var [t, i] of Object.entries(e)) r[t] = de(i);
return r
}
}
function ue(e) {
const t = [...e];
for (let e = 0; e < t.length; e++) t[e] = Object.assign({}, t[e]), t[e].url = le(t[e].url), t[e].attrs && (t[e].attrs = Object.assign({}, t[e].attrs), t[e].attrs.URI = le(t[e].attrs.URI));
return t
}
function ce(e) {
const t = [...e];
for (let e = 0; e < t.length; e++) t[e] = Object.assign({}, t[e]), t[e].url = le(t[e].url);
return t
}
const he = Math.pow(2, 32) - 1;
class pe {
static init() {
let e;
for (e in pe.types = {
avc1: [],
avcC: [],
btrt: [],
dinf: [],
dref: [],
esds: [],
free: [],
ftyp: [],
hdlr: [],
mdat: [],
mdhd: [],
mdia: [],
mfhd: [],
minf: [],
moof: [],
moov: [],
mp4a: [],
".mp3": [],
dac3: [],
"ac-3": [],
dec3: [],
"ec-3": [],
mvex: [],
mvhd: [],
pasp: [],
sdtp: [],
stbl: [],
stco: [],
stsc: [],
stsd: [],
stsz: [],
stts: [],
tfdt: [],
tfhd: [],
traf: [],
trak: [],
trun: [],
trex: [],
tkhd: [],
vmhd: [],
smhd: [],
uuid: [],
encv: [],
enca: [],
frma: [],
schm: [],
schi: [],
senc: [],
saio: [],
saiz: [],
sinf: [],
tenc: [],
sbgp: [],
seig: [],
sgpd: [],
pssh: []
}, pe.types) pe.types.hasOwnProperty(e) && (pe.types[e] = [e.charCodeAt(0), e.charCodeAt(1), e.charCodeAt(2), e.charCodeAt(3)]);
var t = 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]),
i = 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]);
pe.HDLR_TYPES = {
video: t,
audio: i
};
var r = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 117, 114, 108, 32, 0, 0, 0, 1]),
n = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]);
pe.STTS = pe.STSC = pe.STCO = n, pe.STSZ = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), pe.VMHD = new Uint8Array([0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]), pe.SMHD = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]), pe.STSD = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1]);
t = new Uint8Array([105, 115, 111, 109]), i = new Uint8Array([97, 118, 99, 49]), n = new Uint8Array([0, 0, 0, 1]);
pe.FTYP = pe.box(pe.types.ftyp, t, n, t, i), pe.DINF = pe.box(pe.types.dinf, pe.box(pe.types.dref, r))
}
static set16(e, t, i) {
return t[i] = e >> 8 & 255, t[i + 1] = 255 & e, i + 2
}
static set32(e, t, i) {
return t[i] = e >> 24 & 255, t[i + 1] = e >> 16 & 255, t[i + 2] = e >> 8 & 255, t[i + 3] = 255 & e, i + 4
}
static box(e) {
var t = Array.prototype.slice.call(arguments, 1);
let i = 8,
r = t.length;
for (var n = r; r--;) i += t[r].byteLength;
const s = new Uint8Array(i);
for (s[0] = i >> 24 & 255, s[1] = i >> 16 & 255, s[2] = i >> 8 & 255, s[3] = 255 & i, s.set(e, 4), r = 0, i = 8; r < n; r++) s.set(t[r], i), i += t[r].byteLength;
return s
}
static hdlr(e) {
return pe.box(pe.types.hdlr, pe.HDLR_TYPES[e])
}
static mdat(e) {
return pe.box(pe.types.mdat, e)
}
static mdhd(e, t) {
t *= e;
var i = Math.floor(t / (1 + he)),
t = Math.floor(t % (1 + he));
return pe.box(pe.types.mdhd, new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, e >> 24 & 255, e >> 16 & 255, e >> 8 & 255, 255 & e, i >> 24, i >> 16 & 255, i >> 8 & 255, 255 & i, t >> 24, t >> 16 & 255, t >> 8 & 255, 255 & t, 85, 196, 0, 0]))
}
static mdia(e) {
var t = pe.mdhd(e.info.timescale, e.info.duration),
i = pe.hdlr(e.type),
e = pe.minf(e);
return pe.box(pe.types.mdia, t, i, e)
}
static mfhd(e) {
return pe.box(pe.types.mfhd, new Uint8Array([0, 0, 0, 0, e >> 24, e >> 16 & 255, e >> 8 & 255, 255 & e]))
}
static minf(e) {
return "audio" === e.type ? pe.box(pe.types.minf, pe.box(pe.types.smhd, pe.SMHD), pe.DINF, pe.stbl(e)) : pe.box(pe.types.minf, pe.box(pe.types.vmhd, pe.VMHD), pe.DINF, pe.stbl(e))
}
static moof(e, t) {
pe.types || pe.init();
e = pe.traf(t, e);
return pe.box(pe.types.moof, pe.mfhd(t.sequenceNumber), e)
}
static moov(e) {
let t = e.length;
const i = [];
for (; t--;) i[t] = pe.trak(e[t]);
return pe.box.apply(null, [pe.types.moov, pe.mvhd(e[0].info.timescale, e[0].info.duration)].concat(i).concat(pe.mvex(e)))
}
static mvex(e) {
let t = e.length;
const i = [];
for (; t--;) i[t] = pe.trex(e[t]);
return pe.box(pe.types.mvex, ...i)
}
static mvhd(e, t) {
t *= e;
var i = Math.floor(t / (1 + he)),
t = Math.floor(t % (1 + he)),
t = new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, e >> 24 & 255, e >> 16 & 255, e >> 8 & 255, 255 & e, i >> 24, i >> 16 & 255, i >> 8 & 255, 255 & i, t >> 24, t >> 16 & 255, t >> 8 & 255, 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 pe.box(pe.types.mvhd, t)
}
static sdtp(e) {
const t = e.samples || [],
i = new Uint8Array(4 + t.length);
let r, n;
for (n = 0; n < t.length; n++) r = t[n].flags, i[n + 4] = r.dependsOn << 4 | r.isDependedOn << 2 | r.hasRedundancy;
return pe.box(pe.types.sdtp, i)
}
static stbl(e) {
var t = pe.stsd(e),
i = pe.box(pe.types.stts, pe.STTS),
r = pe.box(pe.types.stsc, pe.STSC),
n = pe.box(pe.types.stsz, pe.STSZ),
e = pe.box(pe.types.stco, pe.STCO);
return pe.box(pe.types.stbl, t, i, r, n, e)
}
static avc1(e) {
let t, i, r, n = [],
s = [];
var a = e.info.encrypted ? pe.types.encv : pe.types.avc1;
for (t = 0; t < e.config.sps.length; t++) i = e.config.sps[t], r = i.byteLength, n.push(r >>> 8 & 255), n.push(255 & r), n = n.concat(Array.prototype.slice.call(i));
for (t = 0; t < e.config.pps.length; t++) i = e.config.pps[t], r = i.byteLength, s.push(r >>> 8 & 255), s.push(255 & r), s = s.concat(Array.prototype.slice.call(i));
var o = pe.box(pe.types.avcC, new Uint8Array([1, n[3], n[4], n[5], 255, 224 | e.config.sps.length].concat(n).concat([e.config.pps.length]).concat(s))),
l = e.config.width,
d = e.config.height,
u = e.config.pixelRatio[0],
c = e.config.pixelRatio[1],
h = e.info.encrypted && e.info.keyTagInfo ? pe.sinf(e.info.keyTagInfo, e.type, pe.types.avc1) : new Uint8Array;
return pe.box(a, 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, l >> 8 & 255, 255 & l, d >> 8 & 255, 255 & d, 0, 72, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 1, 18, 100, 97, 105, 108, 121, 109, 111, 116, 105, 111, 110, 47, 104, 108, 115, 46, 106, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 17, 17]), o, h, pe.box(pe.types.btrt, new Uint8Array([0, 28, 156, 128, 0, 45, 198, 192, 0, 45, 198, 192])), pe.box(pe.types.pasp, new Uint8Array([u >> 24, u >> 16 & 255, u >> 8 & 255, 255 & u, c >> 24, c >> 16 & 255, c >> 8 & 255, 255 & c])))
}
static esds(e) {
var t = e.esdsConfig.length;
return new Uint8Array([0, 0, 0, 0, 3, 23 + t, 0, 1, 0, 4, 15 + t, 64, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5].concat([t]).concat(e.esdsConfig).concat([6, 1, 2]))
}
static audioStsd(e) {
var t = e.samplerate;
return new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, e.channelCount, 0, 16, 0, 0, 0, 0, t >> 8 & 255, 255 & t, 0, 0])
}
static dac3(e) {
e = e.extraData;
return new Uint8Array([e >> 16 & 255, e >> 8 & 255, 255 & e])
}
static dec3(e) {
return e.extraDataBytes
}
static mp4a(e, t) {
let i = pe.types.mp4a,
r = null;
r = e.encrypted && e.keyTagInfo ? (i = pe.types.enca, pe.sinf(e.keyTagInfo, "audio", pe.types.mp4a)) : new Uint8Array;
e = pe.audioStsd(t), t = pe.box(pe.types.esds, pe.esds(t));
return pe.box(i, e, t, r)
}
static mp3(e) {
return pe.box(pe.types[".mp3"], pe.audioStsd(e))
}
static ac3(e, t) {
let i = pe.types["ac-3"],
r = null;
return r = e.encrypted && e.keyTagInfo ? (i = pe.types.enca, pe.sinf(e.keyTagInfo, "audio", pe.types["ac-3"])) : new Uint8Array, pe.box(i, pe.audioStsd(t), pe.box(pe.types.dac3, pe.dac3(t)), r)
}
static ec3(e, t) {
let i = pe.types["ec-3"],
r = null;
return r = e.encrypted && e.keyTagInfo ? (i = pe.types.enca, pe.sinf(e.keyTagInfo, "audio", pe.types["ec-3"])) : new Uint8Array, pe.box(i, pe.audioStsd(t), pe.box(pe.types.dec3, pe.dec3(t)), r)
}
static stsd(e) {
if ("audio" !== e.type) return pe.box(pe.types.stsd, pe.STSD, pe.avc1(e));
if ("mp3" === e.config.segmentCodec && "mp3" === e.config.codec) return pe.box(pe.types.stsd, pe.STSD, pe.mp3(e.config));
if ("ac3" === e.config.segmentCodec) return pe.box(pe.types.stsd, pe.STSD, pe.ac3(e.info, e.config));
if ("ec3" === e.config.segmentCodec) return pe.box(pe.types.stsd, pe.STSD, pe.ec3(e.info, e.config));
if ("aac" === e.config.segmentCodec) return pe.box(pe.types.stsd, pe.STSD, pe.mp4a(e.info, e.config));
throw `unknown segmentCodec ${e.config.segmentCodec}`
}
static tkhd(e) {
var t = e.info.id,
i = e.info.duration * e.info.timescale,
r = Math.floor(i / (1 + he)),
i = Math.floor(i % (1 + he));
let n = 0,
s = 0;
return "video" === e.type && (n = e.config.width, s = e.config.height), pe.box(pe.types.tkhd, new Uint8Array([1, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, t >> 24 & 255, t >> 16 & 255, t >> 8 & 255, 255 & t, 0, 0, 0, 0, r >> 24, r >> 16 & 255, r >> 8 & 255, 255 & r, i >> 24, i >> 16 & 255, i >> 8 & 255, 255 & i, 0, 0, 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, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, n >> 8 & 255, 255 & n, 0, 0, s >> 8 & 255, 255 & s, 0, 0]))
}
static traf(e, t) {
var i = pe.senc(e),
r = pe.sdtp(e),
n = i.boxData,
s = n.length ? pe.saio(76) : new Uint8Array,
a = n.length ? pe.saiz(i.defaultSampleInfoSize, i.sampleInfoSizes) : new Uint8Array,
o = pe.sbgp(e),
l = pe.sgpd(e),
d = e.id,
i = Math.floor(t / (1 + he)),
t = Math.floor(t % (1 + he));
return pe.box(pe.types.traf, pe.box(pe.types.tfhd, new Uint8Array([0, 2, 0, 0, d >> 24, d >> 16 & 255, d >> 8 & 255, 255 & d])), pe.box(pe.types.tfdt, new Uint8Array([1, 0, 0, 0, i >> 24, i >> 16 & 255, i >> 8 & 255, 255 & i, t >> 24, t >> 16 & 255, t >> 8 & 255, 255 & t])), n, s, a, o, l, pe.trun(e, r.length + n.length + o.length + l.length + s.length + a.length + 16 + 20 + 8 + 16 + 8 + 8), r)
}
static trak(e) {
if ("trakData" in e) return e.trakData;
e.info.duration = e.info.duration || 4294967295;
var t = pe.types.trak,
i = pe.tkhd(e),
e = pe.mdia(e);
return pe.box(t, i, e)
}
static trex(e) {
e = e.info.id;
return pe.box(pe.types.trex, new Uint8Array([0, 0, 0, 0, e >> 24, e >> 16 & 255, e >> 8 & 255, 255 & e, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1]))
}
static trun(e, t) {
const i = e.samples || [],
r = i.length,
n = 12 + 16 * r,
s = new Uint8Array(n);
let a, o, l, d, u, c;
for (t += 8 + n, s.set([0, 0, 15, 1, r >>> 24 & 255, r >>> 16 & 255, r >>> 8 & 255, 255 & r, t >>> 24 & 255, t >>> 16 & 255, t >>> 8 & 255, 255 & t], 0), a = 0; a < r; a++) l = (o = i[a]).duration, d = o.size, u = o.flags, c = o.cts, s.set([l >>> 24 & 255, l >>> 16 & 255, l >>> 8 & 255, 255 & l, d >>> 24 & 255, d >>> 16 & 255, d >>> 8 & 255, 255 & d, u.isLeading << 2 | u.dependsOn, u.isDependedOn << 6 | u.hasRedundancy << 4 | u.paddingValue << 1 | u.isNonSync, 61440 & u.degradPrio, 15 & u.degradPrio, c >>> 24 & 255, c >>> 16 & 255, c >>> 8 & 255, 255 & c], 12 + 16 * a);
return pe.box(pe.types.trun, s)
}
static initSegment(e) {
pe.types || pe.init();
const t = pe.moov(e),
i = new Uint8Array(pe.FTYP.byteLength + t.byteLength);
return i.set(pe.FTYP), i.set(t, pe.FTYP.byteLength), i
}
static saio(e) {
e = e + 4 + 4;
return pe.box(pe.types.saio, new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1, e >> 24 & 255, e >> 16 & 255, e >> 8 & 255, 255 & e]))
}
static saiz(e, t) {
ne(e) || (e = 0);
var i = t.length,
t = 0 === e ? new Uint8Array(t) : new Uint8Array;
return pe.box(pe.types.saiz, new Uint8Array([0, 0, 0, 0, e, i >> 24 & 255, i >> 16 & 255, i >> 8 & 255, 255 & i]), t)
}
static senc(e) {
const t = e.samples || [],
i = t.length;
let r = 0,
n = NaN,
s = !0;
const a = [];
if (!e.encrypted || i <= 0) return {
boxData: new Uint8Array,
sampleInfoSizes: a,
defaultSampleInfoSize: 0
};
e = e.defaultPerSampleIVSize || 0;
for (const d of t) d.subsamples && (r += d.subsamples.length);
if (r <= 0) return {
boxData: new Uint8Array,
sampleInfoSizes: a,
defaultSampleInfoSize: 0
};
const o = new Uint8Array(2 * i + i * e + 6 * r + 4);
let l = this.set32(i, o, 0);
for (const d of t) {
const t = d.subsamples || [];
let e = 2;
d.iv && (o.set(d.iv, l), l += d.iv.byteLength, e += d.iv.byteLength), l = this.set16(t.length, o, l);
for (const d of t) l = this.set16(d[0], o, l), l = this.set32(d[1], o, l), e += 6;
a.push(e), ne(n) || (n = e), s = s && n === e, n = e
}
return {
boxData: pe.box(pe.types.senc, new Uint8Array([0, 0, 0, 2]), o),
defaultSampleInfoSize: s ? n : 0,
sampleInfoSizes: a
}
}
static sinf(e, t, i) {
return pe.box(pe.types.sinf, pe.frma(i), pe.schm(), pe.schi(e, t))
}
static frma(e) {
return pe.box(pe.types.frma, new Uint8Array(e))
}
static schm() {
return pe.box(pe.types.schm, new Uint8Array([0, 0, 0, 0, 99, 98, 99, 115, 0, 1, 0, 0]))
}
static schi(e, t) {
return pe.box(pe.types.schi, pe.tenc(e, t))
}
static tenc(e, t) {
let i = 0;
"video" === t && (i = 25);
const r = new Uint8Array(17);
if (r[0] = 16, e.iv && 16 === e.iv.byteLength && r.set(e.iv, 1), !e.keyId) throw "tenc: no key id found in decryptdata";
return pe.box(pe.types.tenc, new Uint8Array([1, 0, 0, 0, 0, i, 1, 0]), e.keyId, r)
}
static sbgp(e) {
if (!e.encrypted || 0 === e.samples.length || !e.samples[0].keyTagInfo) return new Uint8Array;
e = e.samples.length;
return pe.box(pe.types.sbgp, new Uint8Array([0, 0, 0, 0]), new Uint8Array(pe.types.seig), new Uint8Array([0, 0, 0, 1, e >> 24 & 255, e >> 16 & 255, e >> 8 & 255, 255 & e, 0, 1, 0, 1]))
}
static sgpd(e) {
if (!e.encrypted || 0 === e.samples.length || !e.samples[0].keyTagInfo) return new Uint8Array;
var t = e.samples[0].keyTagInfo;
let i = 0;
"video" === e.type && (i = 25);
const r = new Uint8Array(17);
if (r[0] = 16, t.iv && r.set(t.iv, 1), !t.keyId) throw "sgpd: no keyid in decryptdata";
return pe.box(pe.types.sgpd, new Uint8Array([1, 0, 0, 0]), new Uint8Array(pe.types.seig), new Uint8Array([0, 0, 0, 37, 0, 0, 0, 1]), new Uint8Array([0, i, 1, 0]), t.keyId, r)
}
static pssh(e, t, i) {
if (pe.types || pe.init(), !e) throw new TypeError("Bad system id");
if (16 !== e.byteLength) throw new RangeError("Invalid system id");
let r, n, s;
if (t) {
r = 1, n = new Uint8Array(16 * t.length);
for (let e = 0; e < t.length; e++) {
const i = t[e];
if (16 !== i.byteLength) throw new RangeError("Invalid key");
n.set(i, 16 * e)
}
} else r = 0, n = new Uint8Array;
0 < r ? (s = new Uint8Array(4), 0 < t.length && new DataView(s.buffer).setUint32(0, t.length, !1)) : s = new Uint8Array;
var a = new Uint8Array(4);
return i && 0 < i.byteLength && new DataView(a.buffer).setUint32(0, i.byteLength, !1), pe.box(pe.types.pssh, new Uint8Array([r, 0, 0, 0]), e, s, n, a, i || new Uint8Array)
}
}
var fe, me, ge = pe;
(vi = fe = fe || {})[vi.SDR = 0] = "SDR", vi[vi.HDR = 1] = "HDR", vi[vi.HDR10 = 2] = "HDR10", vi[vi.DolbyVision = 3] = "DolbyVision", vi[vi.HLG = 4] = "HLG", (bi = me = me || {})[bi.H264 = 16] = "H264", bi[bi.HEVC = 64] = "HEVC", bi[bi.VP09 = 65] = "VP09";
const ye = new Set(["ac-3", "mp4a.a5", "mp4a.A5"]),
ve = new Set(["ec-3", "mp4a.a6", "mp4a.A6"]),
Se = {
aac: 1024,
mp3: 1024,
ac3: 1536,
ec3: 1536
},
be = {
isAC3: e => Boolean(e && ye.has(e)),
isEC3: e => Boolean(e && ve.has(e)),
isDolbyAtmos(e, t) {
const i = t.split("/");
return Boolean(be.isEC3(e) && 1 < i.length && i[1].split(",").find(e => "JOC" === e))
},
isAAC(e) {
return Boolean(e && ("aac" === e || null !== (e = e.match(/^mp4a\.40\.(.*)/)) && "34" !== e[1]))
},
isMP3(e) {
return Boolean(e && ("mp3" === e || null !== (e = e.match(/^mp4a\.40\.(.*)/)) && "34" === e[1]))
},
isAVC: e => Boolean(e && e.match(/^avc[13]\.(.*)/)),
isXHEAAC: function(e) {
return Boolean("mp4a.40.42" === e)
},
isALAC: function(e) {
return Boolean("alac" === e)
},
isFLAC: function(e) {
return Boolean("fLaC" === e)
},
isHEVC: e => Boolean(e && e.match(/^(hev|hvc)1\..*/)),
isDolby: e => Boolean(e && e.match(/^dv(h1|he|a1|av)\..*/)),
isVP09: e => Boolean(e && e.match(/^vp09\..*/)),
isCompatibleCodecString(e, t) {
const i = e.split(","),
r = t.split(","),
n = i.filter(e => be.isVideoCodec(e)),
s = r.filter(e => be.isVideoCodec(e)),
a = i.filter(e => be.isAudioCodec(e)),
o = r.filter(e => be.isAudioCodec(e)),
l = 0 === n.length && 0 === s.length || n.length === s.length && be.isCompatibleVideoCodec(n[0], s[0]),
d = 0 === a.length && 0 === o.length || a.length === o.length && be.isCompatibleAudioCodec(a[0], o[0]);
return l && d
},
isVideoCodec: e => be.isAVC(e) || be.isDolby(e) || be.isHEVC(e) || be.isVP09(e),
isAudioCodec: e => be.isAC3(e) || be.isEC3(e) || be.isAAC(e) || be.isMP3(e),
isCompatibleVideoCodec: (e, t) => Boolean(e && t && (e === t || be.isDolby(e) && be.isDolby(t) || be.isHEVC(e) && be.isHEVC(t) || be.isAVC(e) && be.isAVC(t) || be.isVP09(e) && be.isVP09(t))),
isCompatibleAudioCodec: (e, t) => Boolean(e && t && (e === t || be.isAAC(e) && be.isAAC(t) || be.isAC3(e) && be.isAC3(t) || be.isEC3(e) && be.isEC3(t) || be.isMP3(e) && be.isMP3(t))),
getSegmentCodec(e) {
let t;
if (be.isAAC(e)) t = "aac";
else if (be.isAC3(e)) t = "ac3";
else if (be.isEC3(e)) t = "ec3";
else {
if ("mp3" !== e) throw new Error(`invalid audio config, codec ${e}`);
t = "mp3"
}
return t
},
getChannelCount(e) {
if (!e) return 0;
e = e.split("/"), e = parseInt(e[0]);
return ne(e) ? e : 0
},
avc1toavcoti(e) {
var t;
const i = e.split(".");
let r;
return 2 < i.length ? (r = i.shift() + ".", r += parseInt(null !== (t = i.shift()) && void 0 !== t ? t : "").toString(16), r += ("000" + parseInt(null !== (t = i.shift()) && void 0 !== t ? t : "").toString(16)).substr(-4)) : r = e, r
},
getDynamicRangeType(e, t) {
let i = fe.SDR;
return "PQ" === e && be.isDolby(t) ? i = fe.DolbyVision : "PQ" === e && (be.isHEVC(t) || be.isVP09(t)) ? i = fe.HDR10 : "HLG" !== e || -1 === t.indexOf("hvc1") && !be.isVP09(t) || (i = fe.HLG), i
},
getCompressionType(e) {
let t = me.H264;
return be.isHEVC(e) || be.isDolby(e) ? t = me.HEVC : be.isVP09(e) && (t = me.VP09), t
},
isHigherCodecByFamily(e, t) {
if (!e) return !0;
const i = e.split("."),
r = t.split(".");
if (i[0] !== r[0]) throw new Error(`mismatch in codec family current/new: ${i[0]}/${r[0]}`);
switch (i[0]) {
case "avc1":
case "avc3":
return r[1] > i[1];
case "vp09":
return e < t;
case "hvc1":
case "hev1":
var n = "H" === i[3].substring(0, 1) ? 1 : 0,
s = i[3].substring(1),
a = "H" === r[3].substring(0, 1) ? 1 : 0,
o = r[3].substring(1);
return r[1] > i[1] || r[2] > i[2] || n < a || s < o;
case "dvh1":
return r[1] > i[1] || r[2] > i[2]
}
}
};
class Te {
static getTrack(e, t, i, r, n) {
let s;
switch (be.getSegmentCodec(i)) {
case "aac":
var a;
(a = E(e, 1 === r ? new Uint8Array([255, 241, 92, 64, 1, 127, 252]) : new Uint8Array([255, 241, 92, 128, 1, 191, 252]), 0, i)) && (s = {
type: "audio",
info: {
id: t,
timescale: a.samplerate,
duration: 0,
encrypted: !1,
keyTagInfo: void 0
},
config: a
});
break;
case "ac3":
case "ec3": {
const i = j(e, new Uint8Array([11, 119, 69, 17, 128, 64, 47, 132]), 0);
i && (s = {
type: "audio",
info: {
id: t,
timescale: i.samplerate,
duration: 0,
encrypted: !1,
keyTagInfo: void 0
},
config: i
})
}
}
return s
}
static getSample(e, t) {
let i;
switch (e) {
case "mp4a.40.2":
case "mp4a.40.5":
i = 1 === t ? new Uint8Array([0, 208, 0, 7]) : new Uint8Array([33, 0, 3, 64, 104, 28]);
break;
case "ac-3":
case "ec-3":
i = new Uint8Array([11, 119, 69, 17, 128, 64, 47, 132, 41, 3, 253, 214, 124, 253, 243, 215, 233, 95, 185, 123, 78, 20, 40, 106, 97, 190, 74, 253, 43, 218, 208, 140, 191, 176, 144, 120, 214, 181, 44, 124, 129, 251, 91, 109, 187, 109, 198, 225, 43, 172, 116, 140, 176, 123, 38, 144, 211, 247, 225, 64, 29, 53, 175, 96, 16, 57, 121, 87, 78, 203, 81, 37, 7, 72, 228, 132, 37, 169, 38, 231, 97, 229, 247, 194, 208, 8, 12, 83, 74, 139, 137, 17, 22, 26, 221, 203, 107, 113, 94, 93, 75, 33, 208, 247, 146, 105, 39, 143, 6, 36, 1, 227, 108, 70, 11, 180, 152, 218, 182, 218, 209, 59, 85, 104, 201, 70, 37, 82, 219, 68, 55, 225, 144, 99, 149, 0, 119, 26, 14, 69, 164, 241, 204, 222, 81, 177, 142, 80, 20, 100, 97, 143, 101, 221, 140, 113, 31, 208, 124, 25, 64, 29, 49, 77, 140, 30, 155, 74, 214, 204, 138, 229, 109, 172, 95, 130, 70, 230, 134, 88, 59, 179, 212, 155, 232, 0, 0, 0, 0, 0, 173, 234])
}
return i
}
static getSegment(e, i, r, n) {
if (e) {
var s = e.info["timescale"],
a = e.config["segmentCodec"],
o = Te.getSample(e.config.codec, e.config.channelCount);
if (o) {
const l = [],
d = {
id: e.info.id,
sequenceNumber: i,
type: "audio",
encrypted: !1,
samples: l,
defaultPerSampleIVSize: 0
},
u = Se[a],
c = Math.ceil(n * s / u),
h = {
baseTime: Math.round(c * u + r),
timescale: s
};
let t = 0;
const p = c * o.byteLength + 8,
f = new Uint8Array(p);
f[0] = p >> 24 & 255, f[1] = p >> 16 & 255, f[2] = p >> 8 & 255, f[3] = 255 & p, ge.types || ge.init(), f.set(ge.types.mdat, 4), t += 8;
for (let e = 0; e < c; e++) l.push({
duration: u,
size: o.byteLength,
cts: 0,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: 1,
isNonSync: 0,
paddingValue: 0
}
}), f.set(o, t), t += o.byteLength;
const m = ge.moof(r, d),
g = new Uint8Array(m.byteLength + f.byteLength);
return g.set(m), g.set(f, m.byteLength), {
silentFragData: g,
endTs: h
}
}
}
}
}
class Ee extends h {
constructor(e, t, i, r, n) {
super(e, t, n), this.typeSupported = i, this.isVideoContiguous = !1, this.logger = n.child({
name: "EsRemuxer"
});
const s = navigator.userAgent;
this.isSafari = r && -1 < r.indexOf("Apple") && s && !s.match("CriOS")
}
resetTimeStamp(e) {
this._initPTS = this._initDTS = e
}
resetInitSegment() {
this.currentInitTrack = void 0, this._silentAudioTrack = void 0
}
remuxEsTracks(r, n, s, a, o, l, d, u, c, h) {
let p;
l || (this.isVideoContiguous = !1);
c = void 0 === c ? o : c;
if (!this.currentInitTrack) {
if (r && r.config.codec && (this._audioTrackInfo = {
id: r.info.id,
codec: r.config.codec,
channelCount: r.config.channelCount
}), n && h && this._audioTrackInfo) {
const r = Te.getTrack(this.observer, this._audioTrackInfo.id, this._audioTrackInfo.codec, this._audioTrackInfo.channelCount, this.logger);
if (r) {
this._silentAudioTrack = Object.assign(Object.assign({}, r), {
info: Object.assign(Object.assign({}, r.info), {
inputTimescale: 9e4
}),
parsingData: {
len: 0,
sequenceNumber: 0,
esSamples: []
}
});
const s = this._initPTS + Math.round(c * this._silentAudioTrack.info.timescale);
p = Te.getSegment(this._silentAudioTrack, n.parsingData.sequenceNumber, s, h), n.parsingData.sequenceNumber++
}
} else this._silentAudioTrack = void 0;
this.updateInitPTSDTS(n, r, o), this.generateIS(this._silentAudioTrack || r, n)
}
if (this.currentInitTrack) {
const f = n && n.parsingData.esSamples.length,
m = this.isVideoContiguous;
let t, i, e;
if (n && h && this._silentAudioTrack && !p) {
const r = this._initPTS + Math.round((c + this.config.audioPrimingDelay) * this._silentAudioTrack.info.timescale);
p = Te.getSegment(this._silentAudioTrack, n.parsingData.sequenceNumber, r, h)
}
if (r && r.parsingData.esSamples.length) {
if (ne(r.info.timescale) || (this.logger.warn("regenerate InitSegment as audio detected"), this.updateInitPTSDTS(n, r, o), this.generateIS(r, n)), t = this.remuxAudio(r, c, l, d, u), f) {
let e;
t && (e = S(t.endPTS) - S(t.startPTS)), ne(n.info.timescale) || (this.logger.warn("regenerate InitSegment as video detected"), this.updateInitPTSDTS(n, r, o), this.generateIS(r, n)), i = this.remuxVideo(n, c, m, e, h)
}
} else f && (i = this.remuxVideo(n, c, m, void 0, h)), i && r && r.config.codec && (t = this.remuxEmptyAudio(r, c, l, d, i, u));
p ? e = {
data1: i.data1,
data2: p.silentFragData,
startDTS: i.startDTS,
startPTS: i.startPTS,
endDTS: y(i.endDTS, p.endTs),
endPTS: y(i.endPTS, p.endTs),
type: "audiovideo",
track: this.currentInitTrack
} : i && t ? e = {
data1: i.data1,
data2: t.data1,
startDTS: g(i.startDTS, t.startDTS),
startPTS: g(i.startPTS, t.startPTS),
endDTS: y(i.endDTS, t.endDTS),
endPTS: y(i.endPTS, t.endPTS),
type: "audiovideo",
track: this.currentInitTrack,
dropped: i.dropped,
framesWithoutIDR: i.framesWithoutIDR,
firstKeyframePts: i.firstKeyframePts
} : i ? e = {
data1: i.data1,
startDTS: i.startDTS,
startPTS: i.startPTS,
endDTS: i.endDTS,
endPTS: i.endPTS,
type: "video",
track: this.currentInitTrack,
dropped: i.dropped,
framesWithoutIDR: i.framesWithoutIDR,
firstKeyframePts: i.firstKeyframePts
} : t ? e = {
data1: t.data1,
startDTS: t.startDTS,
startPTS: t.startPTS,
endDTS: t.endDTS,
endPTS: t.endPTS,
type: "audio",
track: this.currentInitTrack
} : this.logger.error("Missing video and audio data"), a && a.captionSamples.length && this.remuxText(a, e), null !== (a = null == s ? void 0 : s.id3Samples) && void 0 !== a && a.length && this.remuxID3(s, e), this.observer.trigger(v.FRAG_PARSING_DATA, e)
} else this.logger.error("failed to generate IS");
this.observer.trigger(v.FRAG_PARSED)
}
updateInitPTSDTS(e, t, i) {
let r = 1 / 0,
n = 1 / 0;
var s = e ? e.parsingData.esSamples : [],
a = t ? t.parsingData.esSamples : [];
if (!ne(this._initPTS)) {
if (t && a.length && (r = n = a[0].pts - t.info.inputTimescale * i), e && s.length) {
const t = e.info.inputTimescale;
e.info.timescale = t, r = Math.min(r, s.reduce((e, t) => {
var i = t.pts - e;
return i < -4294967296 ? Ie(e, t.pts) : 0 < i ? e : t.pts
}, s[0].pts) - t * i), n = Math.min(n, s[0].dts - t * i), this.observer.trigger(v.INIT_PTS_FOUND, {
initPTS: B(r, t)
})
}
if (ne(r) && ne(n)) this._initPTS = r, this._initDTS = n;
else {
const e = new D(!1, "invalid initPTS or initDTS", $.InvalidInitTimestamp);
this.observer.trigger(x.INTERNAL_ERROR, e)
}
}
}
generateIS(e, t) {
const i = t ? t.parsingData.esSamples : [],
r = this.typeSupported;
let n, s = "audio/mp4";
if (e && t && i.length) {
const i = t.info.inputTimescale;
t.info.timescale = i, e.info.timescale = e.config.samplerate;
const r = pe.initSegment([t, e]);
n = {
type: "audiovideo",
container: "video/mp4",
codec: `${t.config.codec},${e.config.codec}`,
initSegment: r
}
} else if (e) {
"mp3" === (e.info.timescale = e.config.samplerate, e.config.segmentCodec) && (r.mpeg ? (s = "audio/mpeg", e.config.codec = "") : r.mp3 && (e.config.codec = "mp3"));
const t = "mp3" === e.config.segmentCodec && r.mpeg ? new Uint8Array : pe.initSegment([e]);
n = {
type: "audio",
container: s,
codec: e.config.codec,
initSegment: t
}
} else if (t && i.length) {
const e = t.info.inputTimescale;
t.info.timescale = e;
const i = pe.initSegment([t]);
n = {
type: "video",
container: "video/mp4",
codec: t.config.codec,
initSegment: i
}
}
if (n) {
this.currentInitTrack = n;
const e = {
track: n
};
this.observer.trigger(v.FRAG_PARSING_INIT_SEGMENT, e)
} else {
const e = new D(!1, "no audio/video samples found", $.NoAVSamplesFound);
this.observer.trigger(x.INTERNAL_ERROR, e)
}
}
remuxVideo(n, e, s, a, o) {
let l, d, u, c, h, t, p = 8,
i = n.parsingData.dropped;
const r = !s && this.config.forceKeyFrameOnDiscontinuity,
f = n.parsingData.esSamples,
m = n.info.inputTimescale,
g = [],
y = n.info.encrypted;
let v, S;
v = s ? this.nextAvcDts : Ie(f[0].dts, f[0].pts), f.forEach(function(e) {
e.pts = Ie(e.pts, v), e.dts = Ie(e.dts, v)
}), f.sort(function(e, t) {
var i = e.dts - t.dts,
r = e.pts - t.pts;
return i || r || e.id - t.id
});
var b = f.findIndex(e => e.key);
f[b] && (S = f[b].pts), r && (0 < b ? (this.logger.warn(`Dropped ${b} out of ${f.length} video samples due to a missing keyframe`), f.splice(0, b), i += b) : -1 === b && (this.logger.warn(`No keyframe found out of ${f.length} video samples`), i += f.length));
var T = f[0],
E = f[f.length - 1],
I = f.reduce((e, t) => Math.max(Math.min(e, t.pts - t.dts), -18e3), 0);
if (I < 0) {
this.logger.warn(`PTS < DTS detected in video samples, shifting DTS by ${Math.round(I/90)} ms to overcome this issue`);
for (let e = 0; e < f.length; e++) f[e].dts += I
}
var w = this.isSafari;
if (l = Math.round((E.dts - T.dts) / (f.length - 1)), c = Math.max(T.dts, 0), u = Math.max(T.pts, 0), ne(o) && (c = e * m, u = e * m), s) {
const n = c - v,
M = n > l,
s = n < -1;
(M || s) && (M ? this.logger.warn(`AVC: ${n}/90000 hole between fragments detected`) : this.logger.warn(`AVC: ${n}/90000 overlapping between fragments detected`))
}
let A = 0,
O = 0;
var k = f.length;
for (let e = 0; e < k; e++) {
const M = f[e],
s = M.units,
a = s.length;
let t = 0;
for (let e = 0; e < a; e++) t += s[e].data.length;
O += t, A += a, M.length = t, M.dts = w ? c + e * l : Math.max(M.dts, c), M.pts = Math.max(M.pts, M.dts)
}
t = Math.max(E.dts, 0), h = Math.max(E.pts, 0, t), ne(o) && (t = e * m, h = e * m);
e = O + 4 * A + 8;
try {
d = new Uint8Array(e)
} catch (n) {
const M = new F(!1, `fail allocating video mdat ${e}`, $.FailedToAllocateVideoMdat, e);
return void this.observer.trigger(x.INTERNAL_ERROR, M)
}
const C = new DataView(d.buffer);
C.setUint32(0, e), d.set(pe.types.mdat, 4);
for (let t = 0; t < k; t++) {
const M = f[t],
s = M.units;
let e, i = 0;
const x = [];
let r = 0;
for (let e = 0, t = s.length; e < t; e++) {
const M = s[e],
a = M.data,
o = M.data.byteLength;
if (C.setUint32(p, o), p += 4, d.set(a, p), p += o, i += 4 + o, y)
if (o <= 48 || 1 !== M.type && 5 !== M.type) r += 4 + o;
else {
let e = o - 32;
e % 16 == 0 && (e -= 16), x.push([r + 36, e]), r = o - 32 - e
}
}
if (0 < r && x.push([r, 0]), w) e = Math.max(0, l * Math.round((M.pts - M.dts) / l));
else {
if (t < k - 1) l = f[t + 1].dts - M.dts;
else {
const s = this.config,
o = M.dts - f[0 < t ? t - 1 : t].dts;
if (s.stretchShortVideoTrack) {
const n = s.maxBufferHole,
d = s.maxSeekHole,
c = Math.floor(Math.min(n, d) * m),
h = (a ? u + a * m : this.nextAudioPts) - M.pts;
h > c ? (l = h - o, l < 0 && (l = o)) : l = o
} else l = o
}
e = Math.round(M.pts - M.dts)
}
ne(o) && (e = 0, l = o * m), g.push({
size: i,
duration: l,
cts: e,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: M.key ? 2 : 1,
isNonSync: M.key ? 0 : 1,
paddingValue: 0
},
keyTagInfo: M.keyTagInfo,
subsamples: x
})
}
if (this.nextAvcDts = t + l, this.isVideoContiguous = !0, g.length && -1 < navigator.userAgent.toLowerCase().indexOf("chrome")) {
const n = g[0].flags;
n.dependsOn = 2, n.isNonSync = 0
}
e = {
sequenceNumber: n.parsingData.sequenceNumber++,
id: n.info.id,
type: n.type,
encrypted: n.info.encrypted,
samples: g,
defaultPerSampleIVSize: 0
}, e = pe.moof(c + this.config.audioPrimingDelay * m, e);
n.parsingData.esSamples = [];
const D = new Uint8Array(e.byteLength + d.byteLength);
return D.set(e), D.set(d, e.byteLength), {
data1: D,
startPTS: B(u / m, m),
endPTS: B((h + l) / m, m),
startDTS: B(c / m, m),
endDTS: B(this.nextAvcDts / m, m),
type: "video",
dropped: i,
framesWithoutIDR: b,
firstKeyframePts: B(S / m, m)
}
}
remuxAudio(r, i, n, e, s) {
const a = r.info.inputTimescale,
o = a / r.info.timescale,
l = ("aac" === r.config.segmentCodec ? 1024 : "mp3" === r.config.segmentCodec ? 1152 : 1536) * o,
d = "mp3" === r.config.segmentCodec && this.typeSupported.mpeg,
u = [],
c = r.info.encrypted,
t = this._initPTS + i * a;
let h, p, f, m, g, y, v, S, b, T, E, I, w, A, O = d ? 0 : 8;
const k = new q,
C = r.parsingData.esSamples;
if (A = this.nextAudioPts, (n = n || C.length && A && (e && Math.abs(t - A) < 9e3 || Math.abs(Ie(C[0].pts - A, t)) < 20 * l)) || (A = Ie(C[0].pts, this._initPTS)), C.forEach(function(e) {
e.pts = e.dts = Ie(e.pts, A)
}), e && "aac" === r.config.segmentCodec)
for (let t = 0, i = A; t < C.length;) {
const M = C[t];
T = M.pts;
const o = T - i,
d = Math.abs(1e3 * o / a);
if (o <= -l) this.logger.warn(`Dropping 1 audio frame @ ${(i/a).toFixed(3)}s due to ${d} ms overlap.`), C.splice(t, 1), r.parsingData.len -= M.unit.length;
else if (o >= l && d < 1e4 && i) {
const d = Math.round(o / l);
this.logger.warn(`Injecting ${d} audio frame @ ${(i/a).toFixed(3)}s due to ${Math.round(1e3*o/a)} ms gap.`);
for (let e = 0; e < d; e++) w = Math.max(i, 0), I = re(r.config.codec, r.config.channelCount), I || (this.logger.warn("Unable to get silent frame for given audio codec; duplicating last frame instead."), I = M.unit.subarray(0)), C.splice(t, 0, {
unit: I,
pts: w,
dts: w,
keyTagInfo: s
}), r.parsingData.len += I.length, i += l, t += 1;
M.pts = M.dts = i, i += l, t += 1
} else i += l, M.pts = M.dts = 0 === t ? A : C[t - 1].pts + l, t += 1
}
for (let e = 0, t = C.length; e < t; e++) {
if (p = C[e], m = p.unit, T = p.pts, E = p.dts, void 0 !== b) f.duration = Math.round((E - b) / o);
else {
const i = Math.round(1e3 * (T - A) / a);
let t = 0;
if (n && "aac" === r.config.segmentCodec && i) {
if (0 < i && i < 1e4) t = Math.round((T - A) / l), 0 < t && (I = re(r.config.codec, r.config.channelCount), I = I || m.subarray(0), r.parsingData.len += t * I.length);
else if (i < -12) {
r.parsingData.len -= m.byteLength;
continue
}
T = E = A
}
if (v = Math.max(0, T), S = Math.max(0, E), !(0 < r.parsingData.len)) return; {
const i = d ? r.parsingData.len : r.parsingData.len + 8;
try {
g = new Uint8Array(i)
} catch (r) {
const n = new F(!1, `fail allocating audio mdat ${i}`, $.FailedToAllocateAudioMdat, i);
return void this.observer.trigger(x.INTERNAL_ERROR, n)
}
d || (h = new DataView(g.buffer), h.setUint32(0, i), g.set(pe.types.mdat, 4))
}
for (let e = 0; e < t; e++) w = T - (t - e) * l, I = re(r.config.codec, r.config.channelCount), I || (this.logger.warn("Unable to get silent frame for given audio codec; duplicating this frame instead."), I = m.subarray(0)), g.set(I, O), O += I.byteLength, f = {
size: I.byteLength,
cts: 0,
duration: 1024,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: 1,
paddingValue: 0,
isNonSync: 0
},
keyTagInfo: p.keyTagInfo,
subsamples: c ? [
[I.byteLength, 0]
] : []
}, u.push(f)
}
g.set(m, O);
const M = m.byteLength;
O += M;
const s = [];
if (c)
if ("ec3" === r.config.segmentCodec) {
let e = 0;
for (; e < m.byteLength;) {
const i = 2 * (k.bsReadAndUpdate(m, {
byteOffset: e + 2,
usedBits: 5
}, 11) + 1);
e += i;
const n = Math.min(i, 16);
s.push([n, i - n])
}
} else {
const r = Math.min(M, 16);
s.push([r, M - r])
} f = {
size: M,
cts: 0,
duration: 0,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: 1,
paddingValue: 0,
isNonSync: 0
},
keyTagInfo: p.keyTagInfo,
subsamples: s
}, u.push(f), b = E
}
let D = 0;
e = u.length;
if (2 <= e && (D = u[e - 2].duration, f.duration = D), e) {
if (this.nextAudioPts = T + o * D, r.parsingData.len = 0, d) y = new Uint8Array;
else {
const i = {
sequenceNumber: r.parsingData.sequenceNumber++,
id: r.info.id,
type: r.type,
encrypted: r.info.encrypted,
samples: u,
defaultPerSampleIVSize: 0
};
y = pe.moof((S + this.config.audioPrimingDelay * a) / o, i)
}
const i = new Uint8Array(y.byteLength + g.byteLength);
return i.set(y), i.set(g, y.byteLength), r.parsingData.esSamples = [], {
data1: i,
startPTS: B(v / a, a),
endPTS: B(this.nextAudioPts / a, a),
startDTS: B(S / a, a),
endDTS: B((E + o * D) / a, a),
type: "audio"
}
}
return null
}
remuxEmptyAudio(t, e, i, r, n, s) {
var a = t.info.inputTimescale,
o = a / (t.config.samplerate || a),
l = this.nextAudioPts,
d = (void 0 !== l ? l : S(n.startDTS) * a) + this._initDTS,
a = S(n.endDTS) * a + this._initDTS,
u = 1024 * o,
c = Math.ceil((a - d) / u),
h = re(t.config.codec, t.config.channelCount);
if (this.logger.warn("remux empty Audio"), !h) return this.logger.error("Unable to remuxEmptyAudio since we were unable to get a silent frame for given audio codec!"), null;
const p = [];
for (let e = 0; e < c; e++) {
const i = d + e * u;
p.push({
unit: h,
pts: i,
dts: i,
keyTagInfo: s
}), t.parsingData.len += h.length
}
return t.parsingData.esSamples = p, this.remuxAudio(t, e, i, r, s)
}
remuxID3(t, e) {
var i = t.id3Samples.length;
let r;
var n = t.inputTimescale;
if (i) {
for (let e = 0; e < i; e++) r = t.id3Samples[e], r.pts = r.pts / n, r.dts = r.dts / n;
e.id3Samples = t.id3Samples
}
t.id3Samples = []
}
remuxText(t, e) {
t.captionSamples.sort(function(e, t) {
return e.pts - t.pts
});
var i = t.captionSamples.length;
let r;
var n = t.inputTimescale;
if (i) {
for (let e = 0; e < i; e++) r = t.captionSamples[e], r.pts = r.pts / n;
e.captionData || (e.captionData = {}), e.captionData.ts = t.captionSamples
}
t.captionSamples = []
}
}
function Ie(e, t) {
var i;
if (void 0 === t) return e;
for (i = t < e ? -8589934592 : 8589934592; 4294967296 < Math.abs(e - t);) e += i;
return e
}
e = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : void 0 !== Jy ? Jy : {};
function we(e) {
try {
return JSON.stringify(e)
} catch (e) {
return '"[Circular]"'
}
}
function Ae(e, t, i) {
var r = i && i.stringify || we;
if ("object" == typeof e && null !== e) {
var n = t.length + 1;
if (1 === n) return e;
var s = new Array(n);
s[0] = r(e);
for (var a = 1; a < n; a++) s[a] = r(t[a]);
return s.join(" ")
}
if ("string" != typeof e) return e;
var o = t.length;
if (0 === o) return e;
for (var l = "", d = 0, u = -1, c = e && e.length || 0, h = 0; h < c;) {
if (37 === e.charCodeAt(h) && h + 1 < c) {
switch (u = -1 < u ? u : 0, e.charCodeAt(h + 1)) {
case 100:
if (o <= d) break;
if (u < h && (l += e.slice(u, h)), null == t[d]) break;
l += Number(t[d]), u = h += 2;
break;
case 79:
case 111:
case 106:
if (o <= d) break;
if (u < h && (l += e.slice(u, h)), void 0 === t[d]) break;
var p = typeof t[d];
if ("string" == p) {
l += "'" + t[d] + "'", u = h + 2, h++;
break
}
if ("function" == p) {
l += t[d].name || "", u = h + 2, h++;
break
}
l += r(t[d]), u = h + 2, h++;
break;
case 115:
if (o <= d) break;
u < h && (l += e.slice(u, h)), l += String(t[d]), u = h + 2, h++;
break;
case 37:
u < h && (l += e.slice(u, h)), l += "%", u = h + 2, h++
}++d
}++h
}
return -1 === u ? e : (u < c && (l += e.slice(u)), l)
}
var Oe = De;
const ke = function() {
function t(e) {
return void 0 !== e && e
}
try {
return "undefined" != typeof globalThis || Object.defineProperty(Object.prototype, "globalThis", {
get: function() {
return delete Object.prototype.globalThis, this.globalThis = this
},
configurable: !0
}), globalThis
} catch (e) {
return t(Jy) || t(window) || t(this) || {}
}
}().console || {},
Ce = {
mapHttpRequest: Le,
mapHttpResponse: Le,
wrapRequestSerializer: _e,
wrapResponseSerializer: _e,
wrapErrorSerializer: _e,
req: Le,
res: Le,
err: function(e) {
const t = {
type: e.constructor.name,
msg: e.message,
stack: e.stack
};
for (const i in e) void 0 === t[i] && (t[i] = e[i]);
return t
}
};
function De(s) {
(s = s || {}).browser = s.browser || {};
const a = s.browser.transmit;
if (a && "function" != typeof a.send) throw Error("pino: transmit option must have a send function");
const e = s.browser.write || ke;
s.browser.write && (s.browser.asObject = !0);
const o = s.serializers || {},
l = (t = s.browser.serialize, i = o, Array.isArray(t) ? t.filter(function(e) {
return "!stdSerializers.err" !== e
}) : !0 === t && Object.keys(i));
var t, i;
let r = s.browser.serialize;
Array.isArray(s.browser.serialize) && -1 < s.browser.serialize.indexOf("!stdSerializers.err") && (r = !1), "function" == typeof e && (e.error = e.fatal = e.warn = e.info = e.debug = e.trace = e), !1 === s.enabled && (s.level = "silent");
const n = s.level || "info",
d = Object.create(e);
d.log || (d.log = Ne), Object.defineProperty(d, "levelVal", {
get: function() {
return "silent" === this.level ? 1 / 0 : this.levels.values[this.level]
}
}), Object.defineProperty(d, "level", {
get: function() {
return this._level
},
set: function(e) {
if ("silent" !== e && !this.levels.values[e]) throw Error("unknown level " + e);
this._level = e, Me(u, d, "error", "log"), Me(u, d, "fatal", "error"), Me(u, d, "warn", "error"), Me(u, d, "info", "log"), Me(u, d, "debug", "log"), Me(u, d, "trace", "log")
}
});
const u = {
transmit: a,
serialize: l,
asObject: s.browser.asObject,
levels: ["error", "fatal", "warn", "info", "debug", "trace"],
timestamp: "function" == typeof(i = s).timestamp ? i.timestamp : !1 === i.timestamp ? Fe : Be
};
return d.levels = De.levels, d.level = n, d.setMaxListeners = d.getMaxListeners = d.emit = d.addListener = d.on = d.prependListener = d.once = d.prependOnceListener = d.removeListener = d.removeAllListeners = d.listeners = d.listenerCount = d.eventNames = d.write = d.flush = Ne, d.serializers = o, d._serialize = l, d._stdErrSerialize = r, d.child = function(t) {
if (!t) throw new Error("missing bindings for child Pino");
var i, r, e = t.serializers;
function n(e) {
this._childLevel = 1 + (0 | e._childLevel), this.error = Pe(e, t, "error"), this.fatal = Pe(e, t, "fatal"), this.warn = Pe(e, t, "warn"), this.info = Pe(e, t, "info"), this.debug = Pe(e, t, "debug"), this.trace = Pe(e, t, "trace"), i && (this.serializers = i, this._serialize = r), a && (this._logEvent = Re([].concat(e._logEvent.bindings, t)))
}
return l && e && (i = Object.assign({}, o, e), r = !0 === s.browser.serialize ? Object.keys(i) : l, delete t.serializers, xe([t], r, i, this._stdErrSerialize)), n.prototype = this, new n(this)
}, a && (d._logEvent = Re()), d
}
function Me(e, t, i, r) {
var n, s, a, o, l = Object.getPrototypeOf(t);
t[i] = !(t.levelVal > t.levels.values[i]) && (l[i] || ke[i] || ke[r]) || Ne, s = t, a = i, !(n = e).transmit && s[a] === Ne || (s[a] = (o = s[a], function() {
const e = n.timestamp(),
t = new Array(arguments.length),
i = Object.getPrototypeOf && Object.getPrototypeOf(this) === ke ? ke : this;
for (var r = 0; r < t.length; r++) t[r] = arguments[r];
if (n.serialize && !n.asObject && xe(t, this._serialize, this.serializers, this._stdErrSerialize), n.asObject ? o.call(i, function(e, t, i, r) {
e._serialize && xe(i, e._serialize, e.serializers, e._stdErrSerialize);
const n = i.slice();
let s = n[0];
const a = {};
r && (a.time = r), a.level = De.levels.values[t];
let o = 1 + (0 | e._childLevel);
if (o < 1 && (o = 1), null !== s && "object" == typeof s) {
for (; o-- && "object" == typeof n[0];) Object.assign(a, n.shift());
s = n.length ? Ae(n.shift(), n) : void 0
} else "string" == typeof s && (s = Ae(n.shift(), n));
return void 0 !== s && (a.msg = s), a
}(this, a, t, e)) : o.apply(i, t), n.transmit) {
const o = n.transmit.level || s.level,
i = De.levels.values[o],
r = De.levels.values[a];
r < i || function(e, t, i) {
const r = t.send,
n = t.ts,
s = t.methodLevel,
a = t.methodValue,
o = t.val,
l = e._logEvent.bindings;
xe(i, e._serialize || Object.keys(e.serializers), e.serializers, void 0 === e._stdErrSerialize || e._stdErrSerialize), e._logEvent.ts = n, e._logEvent.messages = i.filter(function(e) {
return -1 === l.indexOf(e)
}), e._logEvent.level.label = s, e._logEvent.level.value = a, r(s, e._logEvent, o), e._logEvent = Re(l)
}(this, {
ts: e,
methodLevel: a,
methodValue: r,
transmitLevel: o,
transmitValue: De.levels.values[n.transmit.level || s.level],
send: n.transmit.send,
val: s.levelVal
}, t)
}
}))
}
function xe(e, t, i, r) {
for (const n in e)
if (r && e[n] instanceof Error) e[n] = De.stdSerializers.err(e[n]);
else if ("object" == typeof e[n] && !Array.isArray(e[n]))
for (const r in e[n]) t && -1 < t.indexOf(r) && r in i && (e[n][r] = i[r](e[n][r]))
}
function Pe(i, r, n) {
return function() {
try{ const e = new Array(1 + arguments.length);
e[0] = r;
for (var t = 1; t < e.length; t++)
e[t] = arguments[t - 1];
return i[n].apply(this, e) } catch (e){}
}
}
function Re(e) {
return {
ts: 0,
messages: [],
bindings: e || [],
level: {
label: "",
value: 0
}
}
}
function Le() {
return {}
}
function _e(e) {
return e
}
function Ne() {}
function Fe() {
return !1
}
function Be() {
return Date.now()
}
let Ue;
function $e(e = {}) {
return Object.assign(Object.assign({}, e), {
customLevels: Object.assign(Object.assign({}, e.customLevels || {}), {
qe: 35
})
})
}
De.levels = {
values: {
fatal: 60,
error: 50,
warn: 40,
info: 30,
debug: 20,
trace: 10
},
labels: {
10: "trace",
20: "debug",
30: "info",
40: "warn",
50: "error",
60: "fatal"
}
}, De.stdSerializers = Ce, De.stdTimeFunctions = Object.assign({}, {
nullTime: Fe,
epochTime: Be,
unixTime: function() {
return Math.round(Date.now() / 1e3)
},
isoTime: function() {
return new Date(Date.now()).toISOString()
}
});
const Ve = () => {};
function Ke(e, t) {
const i = (e = t in e ? e : console)[t] || e.log;
return i ? i.bind(e) : Ve
}
function qe(r, n, e) {
var {
time: s,
sessionId: t,
critical: i,
name: a,
msg: o
} = e;
let l = "";
if ("data" in e) try {
const r = [],
n = [];
l = JSON.stringify(e.data, (e, t) => {
if ("object" == typeof t && null !== t) {
var i = n.indexOf(t);
if (-1 !== i) return `[Circular object reference: '${r[i]}']`;
r.push(e), n.push(t)
}
return t
})
} catch (r) {
l = `Log serialization error: "${r}"`
}
r(`${function(){const e=new Date(s),t=e.getTimezoneOffset(),i=He(Math.floor(Math.abs(t)/60)),r=He(Math.abs(t)%60);let n=t<=0?"UTC+"+i:"UTC-"+i;return n=r?n+":"+r:n,e.getFullYear()+"-"+He(e.getMonth()+1)+"-"+He(e.getDate())+" "+He(e.getHours())+":"+He(e.getMinutes())+":"+He(e.getSeconds())+"."+(e.getMilliseconds()/1e3).toFixed(3).slice(2,5)+" "+n}()}| [SessionID: ${t}] | [${n}] >${i?" [QE Critical]":""} [${a}] ${o||""} ${l}`)
}
function He(e) {
return e < 10 ? "0" + e : e.toString()
}
function je(e, t = 1 / 0) {
if (!e) return "";
const i = new Uint8Array(e);
let r, n = "";
for (r = 0; r < i.length && r < t; r++) {
let e = i[r].toString(16);
e.length < 2 && (e = "0" + e), n += e
}
return n
}
const Qe = () => (Ue || (Ue = Oe($e()).child({
name: "hls"
}), Ue.qe = e => Ue.info(e), Ue.warn("getLogger called without hls object instantiated, returning a logger that is not configured")), Ue),
We = {
bin2str: e => String.fromCharCode.apply(null, Array.from(e)),
readUint16(e, t) {
t = e[t] << 8 | e[t + 1];
return t < 0 ? 65536 + t : t
},
readSint32: (e, t) => e[t] << 24 | e[t + 1] << 16 | e[t + 2] << 8 | e[t + 3],
readUint32(e, t) {
t = We.readSint32(e, t);
return t < 0 ? 4294967296 + t : t
},
writeUint32(e, t, i) {
e[t] = i >> 24, e[t + 1] = i >> 16 & 255, e[t + 2] = i >> 8 & 255, e[t + 3] = 255 & i
},
readUint64(e, t) {
var i = We.readUint32(e, t);
return i *= Math.pow(2, 32), i += We.readUint32(e, t + 4)
},
writeUint64(e, t, i) {
var r = Math.pow(2, 32) - 1,
n = Math.floor(i / (1 + r)),
r = Math.floor(i % (1 + r));
We.writeUint32(e, t, n), We.writeUint32(e, t + 4, r)
},
findBox(e, t) {
let i, r, n, s, a, o = [];
if (!t.length) return [];
for (i = 0; i < e.byteLength;) r = We.readUint32(e, i), n = We.bin2str(e.subarray(i + 4, i + 8)), s = 1 < r ? i + r : e.byteLength, n === t[0] && (1 === t.length ? o.push(e.subarray(i + 8, s)) : (a = We.findBox(e.subarray(i + 8, s), t.slice(1))).length && (o = o.concat(a))), i = s;
return o
},
findBoxWithOffset(e, t, i, r) {
let n, s, a, o, l, d = [];
if (!i.length) return [];
for (n = 0; n < e.byteLength;) s = We.readUint32(e, n), a = We.bin2str(e.subarray(n + 4, n + 8)), o = 1 < s ? n + s : e.byteLength, a === i[0] && (r && r.push({
offset: n + t,
type: a,
size: s
}), 1 === i.length ? d.push({
offset: n + t,
type: a,
data: e.subarray(n + 8, o),
boxSize: s,
walkedPath: r ? r.slice(0) : void 0
}) : (l = We.findBoxWithOffset(e.subarray(n + 8, o), n + t + 8, i.slice(1), r ? r.slice(0) : void 0)).length && (d = d.concat(l), r = r ? r.slice(0, -1) : void 0)), n = o;
return d
}
},
Ge = {
name: "MP4EncryptionRemuxer"
};
class ze extends h {
constructor(e, t, i, r, n) {
super(e, t, n)
}
static _isCommonEncryptionInternal(e) {
return Boolean(e && !("NONE" === e || "AES-128" === e))
}
static remuxInitSegment(c, h, p, f) {
if (!p) return c;
let e = c;
if (ze._isCommonEncryptionInternal(p.method)) {
const m = p.keyId;
let u = !1;
const g = [];
if (We.findBoxWithOffset(c, 0, ["moov", "trak"]).forEach(t => {
const o = t.data;
let l, i = 0;
const d = We.findBoxWithOffset(o, 0, ["mdia", "minf", "stbl", "stsd"], [])[0],
e = d.data.subarray(8);
let r = !0,
n = We.findBoxWithOffset(e, d.offset + 16, ["enca"]);
0 === n.length && (r = !1, n = We.findBoxWithOffset(e, d.offset + 16, ["encv"])), n.forEach(s => {
let e = null,
a = null;
i = r ? (e = s.data.subarray(28), l = "audio", d.offset + 16 + 8 + 28) : (e = s.data.subarray(78), l = "video", d.offset + 16 + 8 + 78), e && We.findBoxWithOffset(e, i, ["sinf"]).forEach(e => {
const t = e.data,
i = We.findBox(t, ["frma"])[0],
r = We.findBox(t, ["schm"])[0];
if (i)
if (r) {
var n = We.bin2str(r.subarray(4, 8));
if ("aac " === We.bin2str(i.subarray(0, 4)) && (ge.types || ge.init(), i.set(ge.types.mp4a, 0)), "cbcs" === n || "cenc" === n) {
f && f.push(t);
const e = We.findBox(t, ["schi", "tenc"])[0];
if (e) {
const h = 8;
e.subarray(8, 24), e.set(m, 8);
const f = e[6],
t = e[7];
if (1 === f && 0 === t) {
const h = e[24];
0 < h && p.iv && h === p.iv.length && e.set(p.iv, 25)
}
}
} else if ("cbc2" === n) {
u = !0, ge.types || ge.init();
const h = We.findBoxWithOffset(t, 0, ["frma"])[0],
f = ge.box(ge.types.schi, ge.tenc(p, l)),
m = ge.box(ge.types.sinf, t.subarray(h.offset, h.boxSize), ge.schm(), f);
a = ge.box(ge.types.trak, o.subarray(0, e.offset), m, o.subarray(e.offset + e.boxSize));
const i = a.subarray(8),
r = m.byteLength - e.boxSize;
d.walkedPath && (d.walkedPath.push({
type: "stsd",
offset: s.offset,
size: s.boxSize
}), d.walkedPath.forEach(e => {
We.writeUint32(i, e.offset, e.size + r)
}))
}
} else h.error(Ge, "missing schm box");
else h.error(Ge, "missing frma box")
}), a = a || c.subarray(t.offset, t.offset + t.boxSize), g.push(a)
});
var s = We.findBoxWithOffset(o, 0, ["edts"])[0];
s && (ge.types || ge.init(), o.set(ge.types.free, s.offset + 4))
}), u) {
const p = ze.remuxCbc2InitSegment(c, g, h);
e = p || c
}
}
return e
}
static remuxCbc2InitSegment(i, r, n) {
const s = We.findBoxWithOffset(i, 0, ["ftyp"])[0];
if (s) {
const a = We.findBoxWithOffset(i, s.boxSize, ["moov"])[0];
let e = [],
t = 0;
for (; t < a.data.byteLength;) {
const i = We.readUint32(a.data, t),
n = We.bin2str(a.data.subarray(t + 4, t + 8)),
s = 1 < i ? t + i : a.data.byteLength;
"trak" === n ? r && (e = e.concat(r), r = void 0) : e.push(a.data.subarray(t, s)), t = s
}
const o = ge.box(ge.types.moov, ...e),
l = new Uint8Array(s.boxSize + o.byteLength);
return l.set(i.subarray(0, s.boxSize)), l.set(o, s.boxSize), l
}
n.error(Ge, "no ftyp found")
}
static remuxOverflowSegment(i, e) {
ge.types || ge.init();
const t = We.findBoxWithOffset(i, 0, ["moof", "traf", "tfdt"], []);
let r, n = i.byteLength;
if (t.forEach(e => {
0 === e.data[0] && (n += 4)
}), n > i.byteLength) {
r = new Uint8Array(n);
let e = 0,
t = 0;
for (; t < i.byteLength;) {
const n = We.readUint32(i, t),
s = We.bin2str(i.subarray(t + 4, t + 8)),
a = 1 < n ? t + n : i.byteLength;
if ("moof" === s) {
const n = ze.remuxOverflowMoof(i.subarray(t + 8, a));
r.set(n, e), e += n.byteLength
} else r.set(i.subarray(t, a), e), e += n;
t = a
}
} else e.warn(Ge, "no increase in size");
return r || i
}
static remuxOverflowMoof(e) {
let t = 0;
const i = [];
for (; t < e.byteLength;) {
const r = We.readUint32(e, t);
if ("traf" === We.bin2str(e.subarray(t + 4, t + 8))) {
const s = ze.remuxOverflowTraf(e.subarray(t + 8, t + r));
i.push(s)
} else i.push(e.subarray(t, t + r));
t = 1 < r ? t + r : e.byteLength
}
const r = ge.box(ge.types.moof, ...i),
s = r.byteLength - e.byteLength - 8;
return We.findBoxWithOffset(r, 0, ["moof", "traf", "trun"], []).forEach(e => {
var t;
0 != (1 & e.data[3]) && (t = We.readUint32(e.data, 8), We.writeUint32(e.data, 8, t + s))
}), We.findBoxWithOffset(r, 0, ["moof", "traf", "saio"], []).forEach(t => {
const i = 1 & t.data[0];
let r = 4;
1 & t.data[3] && (r += 8);
var n = We.readUint32(t.data, r);
if (r += 4, i)
for (let e = 0; e < n; e++) {
const i = We.readUint64(t.data, r);
We.writeUint64(t.data, r, i + s), r += 8
} else
for (let e = 0; e < n; e++) {
const i = We.readUint32(t.data, r);
We.writeUint32(t.data, r, i + s), r += 4
}
}), r
}
static remuxOverflowTraf(e) {
let t = 0;
const i = [];
for (; t < e.byteLength;) {
var r, n = We.readUint32(e, t);
"tfdt" === We.bin2str(e.subarray(t + 4, t + 8)) && 0 === e[t + 8] ? (r = We.readUint32(e, t + 12), r = ge.box(ge.types.tfdt, new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0, r >> 24, r >> 16 & 255, r >> 8 & 255, 255 & r])), i.push(r)) : i.push(e.subarray(t, t + n)), t = 1 < n ? t + n : e.byteLength
}
return ge.box(ge.types.traf, ...i)
}
remuxText(e, t) {
e.captionSamples.sort(function(e, t) {
return e.pts - t.pts
}), e.captionSamples.length && (t.captionData || (t.captionData = {}), t.captionData.mp4 = e.captionSamples), e.captionSamples = []
}
remuxIFrame(e, t, i, r, n) {
if (!t.samples || !t.samples.length || !t.samples[0].data) return null;
let s;
const a = ge.moof(e * t.timescale, t),
o = new Uint8Array(a.byteLength + t.samples[0].data.byteLength + 8);
o.set(a), We.writeUint32(o, a.byteLength, t.samples[0].data.byteLength + 8), o.set(ge.types.mdat, a.byteLength + 4), o.set(t.samples[0].data, a.byteLength + 8), t.sequenceNumber++;
var l = t.timescale,
d = B(e + r, l),
l = B(e, l);
let u, c;
u = i ? (s = "audiovideo", i.sequenceNumber = t.sequenceNumber, t.sequenceNumber++, c = Te.getSegment(i, i.sequenceNumber, e * i.info.timescale, r), y(c.endTs, d)) : (s = "video", d);
n = {
data1: o,
data2: null == c ? void 0 : c.silentFragData,
startPTS: l,
startDTS: l,
endPTS: u,
endDTS: u,
type: s,
dropped: 0,
track: n
};
this.observer.trigger(v.FRAG_PARSING_DATA, n), this.observer.trigger(v.FRAG_PARSED)
}
remuxEmsgAndRawData(e, t, i, r, n, s, a, o, l, d) {
let u;
t && r ? u = "audiovideo" : t ? u = "audio" : r && (u = "video");
const c = Math.max(i, e),
h = {
data1: l,
track: d,
startPTS: B(a, o),
startDTS: B(a, o),
endPTS: void 0,
endDTS: void 0,
type: u,
dropped: 0
};
return c && (h.endPTS = B(a + c, o), h.endDTS = B(a + c, o)), n && n.captionSamples.length && this.remuxText(n, h), s && 0 < s.id3Samples.length && this.remuxID3(s, h), this.observer.trigger(v.FRAG_PARSING_DATA, h), this.observer.trigger(v.FRAG_PARSED), h
}
remuxID3(t, e) {
let i;
var r = t.id3Samples.length;
if (r) {
for (let e = 0; e < r; e++) i = t.id3Samples[e], i.pts = i.pts - 10, i.dts = i.dts - 10;
e.id3Samples = [...t.id3Samples]
}
t.id3Samples = []
}
}
const Xe = Math.pow(2, 32) - 1,
Ye = Math.pow(2, 20) - 1,
Je = {
name: "MP4Demuxer"
};
class Ze extends u {
constructor(e, t, i, r, n) {
super(e, t, i, {}, n), this.mp4Remuxer = t, this.audioPrimingDelay = i.audioPrimingDelay
}
resetTimeStamp(e) {
ne(e) ? this.initData.audio && !this.initData.video ? this.initPtsTs = {
baseTime: Math.round(e * this.initData.audio.timescale / 9e4),
timescale: this.initData.audio.timescale
} : this.initPtsTs = {
baseTime: e,
timescale: 9e4
} : this.initPtsTs = void 0
}
static isHEVCFlavor(e) {
if (!e) return !1;
var t = e.indexOf("."),
t = t < 0 ? e : e.substring(0, t);
return "hvc1" === t || "hev1" === t || "chvc" === t || "qhvc" === t || "qhev" === t || "muxa" === t || "dvh1" === t || "dvhe" === t || "cdh1" === t || "qdh1" === t || "qdhe" === t
}
resetInitSegment(t, i, r) {
if (this._silentAudioTrack = void 0, t && t.byteLength) {
var n = ze.remuxInitSegment(t, this.logger, r),
s = this.initData = Ze.parseInitSegment(n);
let e;
s.foundLargeTimescale && this.logger.warn(Je, "large timescale found, will check for 32 bit tfdts");
var a = s.audioCodec,
r = s.videoCodec;
if (s.audio && s.video ? e = {
type: "audiovideo",
container: "video/mp4",
codec: a + "," + r,
initSegment: n
} : (s.audio && a && (e = {
type: "audio",
container: "audio/mp4",
codec: a,
initSegment: n
}), s.video && r && (e = {
type: "video",
container: "video/mp4",
codec: r,
initSegment: n
})), s.video) {
const o = s.video,
l = t.subarray(o.trakOffset, o.trakOffset + o.trakSize);
this._videoTrack = Object.assign(Object.assign({}, o), {
info: {
id: o.id,
timescale: o.timescale,
duration: i
},
trakData: l,
sequenceNumber: 0,
samples: []
}), this.trySEICaptions = !be.isVP09(r), this._captionTrack = Object.assign(Object.assign({}, s.caption), {
sequenceNumber: 0,
captionSamples: []
})
}
s.audio && a && (this._audioTrack = Object.assign({}, s.audio)), s.caption && (this.trySEICaptions = !1, this._captionTrack = Object.assign(Object.assign({}, s.caption), {
sequenceNumber: 0,
captionSamples: []
})), this.remuxedInitDataTrack = e;
s = {
track: e
};
this.observer.trigger(v.FRAG_PARSING_INIT_SEGMENT, s)
}
}
static probe(e, t) {
return 0 < We.findBox(e.subarray(0, Math.min(e.length, 512e3)), ["moof"]).length
}
static parseHvcC(e) {
let t;
var i, r;
return e ? 1 === (i = e[0]) ? (r = e[1], t = {
profileSpace: r >> 6,
tierFlag: (32 & r) >> 5 ? "H" : "L",
profileIDC: 31 & r,
profileCompat: We.readUint32(e, 2),
constraintIndicator: e.subarray(6, 12),
levelIDC: e[12]
}) : Qe().warn(Je, `Unhandled version ${i} in hvcC box`) : Qe().warn(Je, "No hvcC box"), t
}
static hvcCToCodecString(t, i) {
const r = t + "." + (i.profileSpace ? String.fromCharCode(i.profileSpace + "A" - 1) : "") + i.profileIDC + "." + i.profileCompat.toString(16).toUpperCase() + "." + i.tierFlag + i.levelIDC;
let n = "";
for (let e = i.constraintIndicator.length - 1; 0 <= e; --e) {
const r = i.constraintIndicator[e];
if (0 !== r || "" !== n) {
const t = r.toString(16).toUpperCase();
n = "." + ("" === n ? t : t + n)
}
}
return r + n
}
static parseDvcC(e) {
let t;
return e ? t = {
versionMajor: e[0],
versionMinor: e[1],
profile: e[2] >> 1 & 127,
level: e[2] << 5 & 32 | e[3] >> 3 & 31
} : Qe().warn(Je, "No dvcC box"), t
}
static dvcCToCodecString(e, t) {
return e + "." + Ze.checkAndAddLeadingZero(t.profile) + "." + Ze.checkAndAddLeadingZero(t.level)
}
static parseVpcC(e) {
let t;
return e ? t = {
profile: e[4],
level: e[5],
bitDepth: e[6] >> 4 & 15
} : Qe().warn(Je, "No vpcC box"), t
}
static vpcCToCodecString(e, t) {
return e + "." + Ze.checkAndAddLeadingZero(t.profile) + "." + Ze.checkAndAddLeadingZero(t.level) + "." + Ze.checkAndAddLeadingZero(t.bitDepth)
}
static checkAndAddLeadingZero(e) {
return (e < 10 ? "0" : "") + e
}
static parseInitSegment(e) {
const c = {
foundLargeTimescale: !1,
tracksById: {}
};
return We.findBoxWithOffset(e, 0, ["moov", "trak"]).forEach(t => {
const i = t.data,
r = We.findBox(i, ["tkhd"])[0];
if (r) {
var n = 0 === (a = r[0]) ? 12 : 20,
s = We.readUint32(r, n),
e = We.findBox(i, ["mdia", "mdhd"])[0];
if (e) {
var a, o = 0 === (a = e[0]) ? 12 : 20,
n = We.readUint32(e, o);
o += 4, 1e6 <= n && (c.foundLargeTimescale = !0);
const l = 0 === a ? We.readUint32(e, o) : 0,
d = We.findBox(i, ["mdia", "hdlr"])[0];
if (d) {
const r = We.bin2str(d.subarray(8, 12)),
u = {
soun: "audio",
vide: "video",
clcp: "caption"
} [r] || r;
if (u) {
const r = We.findBox(i, ["mdia", "minf", "stbl", "stsd"]);
if (r.length) {
const i = r[0];
We.bin2str(i.subarray(12, 16));
o = Ze.parseStsd(i);
let e;
if ("caption" === u) {
const t = Object.assign({
id: s,
type: u,
timescale: n,
duration: l,
isTimingTrack: !1,
sequenceNumber: 0,
captionSamples: []
}, o);
c.caption = t, e = t
} else {
const i = Object.assign({
id: s,
type: u,
timescale: n,
duration: l,
isTimingTrack: !0,
trakOffset: t.offset,
trakSize: t.boxSize,
sequenceNumber: 0,
samples: [],
fragmentDuration: 0
}, o);
"video" === u ? (c.video = i, c.videoCodec = i.codec) : (c.audio = i, c.audioCodec = i.codec), e = i
}
c.tracksById[s] = e
}
}
}
}
}
}), We.findBoxWithOffset(e, 0, ["moov", "mvex", "trex"]).forEach(e => {
var t = e.data,
e = We.readUint32(t, 4),
t = We.readUint32(t, 16);
c.tracksById[e].defaultSampleSize = t
}), c
}
static parseStsd(e) {
let r, t;
const i = e.subarray(8);
let n = We.bin2str(i.subarray(4, 8)),
s = null,
a = null;
"enca" === n ? (s = We.findBox(i, ["enca"])[0], a = s.subarray(28)) : "encv" === n && (s = We.findBox(i, ["encv"])[0], a = s.subarray(78));
e = !!a;
r = 0, a && We.findBox(a, ["sinf"]).forEach(e => {
const t = We.findBox(e, ["schm"])[0];
if (t) {
var i = We.bin2str(t.subarray(4, 8));
if ("cbcs" === i || "cenc" === i) {
const t = We.findBox(e, ["frma"])[0];
t && (n = We.bin2str(t));
e = We.findBox(e, ["schi", "tenc"])[0];
e && (r = e[7])
}
}
});
let o;
var l = i.subarray(86);
switch (n) {
case "mp4a":
t = "mp4a.40.5";
break;
case "ac-3":
case "ec-3":
case "alac":
case "fLaC":
t = n;
break;
case "avc1":
case "avc3":
t = n + ".640028";
break;
case "hvc1":
case "hev1":
const d = We.findBox(l, ["hvcC"])[0];
o = Ze.parseHvcC(d), t = o ? Ze.hvcCToCodecString(n, o) : n + ".2.4.H150.B0";
break;
case "dvh1":
case "dvhe":
const r = We.findBox(l, ["dvcC"])[0];
o = Ze.parseDvcC(r), t = o ? Ze.dvcCToCodecString(n, o) : n + ".05.01";
break;
case "c608":
t = n;
break;
case "vp09":
const i = We.findBox(l, ["vpcC"])[0];
o = Ze.parseVpcC(i), t = Ze.vpcCToCodecString(n, o);
break;
default:
t = n
}
return {
codec: t,
encrypted: e,
defaultPerSampleIVSize: r
}
}
static has32BitTfdts(e) {
const t = We.findBox(e, ["moof", "traf", "tfdt"]);
let i = !1;
return t.forEach(e => {
0 === e[0] && (i = !0)
}), i
}
static getStartDtsTs(r, e) {
const t = We.findBox(e, ["moof", "traf"]);
let n, s = Number.MAX_SAFE_INTEGER;
return t.map(function(i) {
return We.findBox(i, ["tfhd"]).forEach(e => {
var t = We.readUint32(e, 4),
e = r.tracksById[t];
if (e) {
if (!e.isTimingTrack) return 1 / 0;
t = e.timescale || 9e4, e = We.findBox(i, ["tfdt"]).map(function(e) {
let t;
var i = e[0];
return t = We.readUint32(e, 4), 1 === i && (t > Ye && Qe().warn(Je, `Value larger than can be represented by float for upper 32 bits ${t}`), t *= Math.pow(2, 32), t += We.readUint32(e, 8)), t
}), e = 0 < e.length ? e[0] : 1 / 0;
isFinite(e) && e / t < s && (s = e / t, n = {
baseTime: e,
timescale: t
})
}
})
}), n
}
static offsetStartDTS(r, e, l, n) {
We.findBox(e, ["moof", "traf"]).map(function(i) {
return We.findBox(i, ["tfhd"]).map(function(e) {
const t = We.readUint32(e, 4),
s = r.tracksById[t];
if (s) {
const a = s.timescale || 9e4,
o = "caption" === s.type ? 0 : n;
We.findBox(i, ["tfdt"]).map(function(t) {
const i = t[0],
r = s.type;
if (0 === i) {
let e = We.readUint32(t, 4) - Math.round(l.baseTime * a / l.timescale);
"video" === r && e < 0 && (Qe().warn(Je, `video tdft would have gone negative by ${e/a} seconds`), e = 0), e += Math.round(o * a), e = Math.max(e, 0), We.writeUint32(t, 4, e)
} else {
const i = We.readUint32(t, 4);
i > Ye && Qe().error(Je, `baseMediaDecodeTime larger than can be represented by float for upper 32 bits ${i}`);
let e = i;
e *= Math.pow(2, 32), e += We.readUint32(t, 8), e -= Math.round(l.baseTime * a / l.timescale), "video" === r && e < 0 && (Qe().warn(Je, `video tdft would have gone negative by ${e/a} seconds`), e = 0), e += Math.round(o * a), e = Math.max(e, 0);
const n = Math.floor(e / (1 + Xe)),
s = Math.floor(e % (1 + Xe));
We.writeUint32(t, 4, n), We.writeUint32(t, 8, s)
}
})
}
})
})
}
static writeStartDTS(i, e, s) {
We.findBox(e, ["moof", "traf"]).map(function(t) {
return We.findBox(t, ["tfhd"]).map(function(e) {
e = We.readUint32(e, 4), e = i.tracksById[e];
if (e) {
const r = e.timescale || 9e4,
n = Math.round(s * r) / r;
.01 < Math.abs(n - s) && Qe().warn(Je, `[iframes] large rounding error when adjusting timestamps, startDTS: ${s}, roundedStartDTS: ${n}`), We.findBox(t, ["tfdt"]).map(function(e) {
var t, i;
0 === e[0] ? We.writeUint32(e, 4, n * r) : (i = n * r, i = Math.max(i, 0), t = Math.floor(i / (1 + Xe)), i = Math.floor(i % (1 + Xe)), We.writeUint32(e, 4, t), We.writeUint32(e, 8, i))
})
}
})
})
}
static parseSAIO(e) {
let t = 0,
i = 0;
var r = e[0];
i += 4, 0 != (1 & We.readUint32(e, 0)) && (i += 8);
var n = 16777215 & We.readUint32(e, i);
return 1 == n ? (i += 4, t = We.readUint32(e, i), 1 === r && (i += 4, t *= Math.pow(2, 32), t += We.readUint32(e, i))) : Qe().error(Je, `saio entry count error, count is: ${n}`), t
}
static parseSAIZ(e) {
let t = 0,
i = 0;
return i += 4, 0 != (1 & We.readUint32(e, 0)) && (i += 8), t = e[i], i++, i += 4, 0 === t && (t = e[i]), t
}
static parseSubsample(e, t) {
const i = {
subsamples: []
};
let r = 0;
for (e && (i.iv = t.subarray(0, e), r += e), r += 2; r + 6 <= t.byteLength;) {
const e = We.readUint16(t, r);
r += 2;
var n = We.readUint32(t, r);
r += 4, i.subsamples.push([e, n])
}
return i
}
static isSEIMessage(e, t) {
return e ? 39 === t || 40 === t : 6 === t
}
static parseCLCPSample(e, t, i) {
let r = 0;
const n = [];
let s = 0;
for (; r < i;) {
var a = t + r,
o = We.readUint32(e, a);
a += 4;
var l = We.bin2str(e.subarray(a, a + 4));
if (a += 4, "cdat" !== l) break; {
const t = o - 8,
d = e.subarray(a, a + t);
s += t, n.push(d), r += o
}
}
return {
cdatList: n,
cdatTotalSize: s
}
}
static parseSamples(e, S, b, T, E, I) {
const w = b.timescale,
d = b.id;
let A, O = e,
k = 0,
C = !1;
We.findBoxWithOffset(S, 0, ["moof"]).map(function(e) {
const t = e.data,
v = e.offset;
We.findBox(t, ["traf"]).map(function(l) {
var e = We.findBox(l, ["tfdt"]).map(function(e) {
let t;
var i = e[0];
return t = We.readUint32(e, 4), 1 === i && (t *= Math.pow(2, 32), t += We.readUint32(e, 8)), t / w
})[0];
return void 0 !== e && (O = e), We.findBox(l, ["tfhd"]).map(function(e) {
var t = We.readUint32(e, 4),
i = 16777215 & We.readUint32(e, 0),
r = 0 != (1 & i),
n = 0 != (2 & i),
s = 0 != (8 & i);
let g = 0;
var a = 0 != (16 & i);
let y = 0;
i = 0 != (32 & i);
let o = 8;
if (ne(b.defaultSampleSize) && (y = b.defaultSampleSize), t === d) {
if (r && (We.readUint32(e, o), o += 4, We.readUint32(e, o), o += 4), n && (We.readUint32(e, o), o += 4), s && (g = We.readUint32(e, o), o += 4), a && (y = We.readUint32(e, o), o += 4), i && (We.readUint32(e, o), o += 4), "video" === b.type) {
let t = 0,
i = 0;
We.findBox(l, ["saio"]).map(function(e) {
t = Ze.parseSAIO(e)
}), We.findBox(l, ["saiz"]).map(function(e) {
i = Ze.parseSAIZ(e)
}), t && i && (A = Ze.parseSubsample(b.defaultPerSampleIVSize, S.subarray(t, t + i))), C = Ze.isHEVCFlavor(b.codec)
}
We.findBox(l, ["trun"]).map(function(i) {
var t = i[0],
e = 16777215 & We.readUint32(i, 0),
r = 0 != (1 & e);
let n = 0;
var s = 0 != (4 & e),
a = 0 != (256 & e);
let o = 0;
var l = 0 != (512 & e);
let d = 0;
var u = 0 != (1024 & e),
c = 0 != (2048 & e);
let h = 0;
var p = We.readUint32(i, 4);
let f = 8;
r && (n = We.readUint32(i, f), f += 4), s && (f += 4);
let m = n + v;
for (let e = 0; e < p && (I < 0 || k < I); e++) {
if (a ? (o = We.readUint32(i, f), f += 4) : o = g, l ? (d = We.readUint32(i, f), f += 4) : d = y, u && (f += 4), c && (h = 0 === t ? We.readUint32(i, f) : We.readSint32(i, f), f += 4), "video" === b.type) {
if (ne(T)) b.samples.push({
data: S.subarray(m, m + d),
size: d,
duration: T * w,
cts: 0,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: 2,
isNonSync: 0,
paddingValue: 0
},
subsamples: A ? A.subsamples : [],
iv: A ? A.iv : void 0
});
else if (b.fragmentDuration += o, E) {
let e = 0;
for (; e < d;) {
const T = We.readUint32(S, m);
m += 4;
const E = 31 & S[m];
if (b.seiSamples || (b.seiSamples = []), Ze.isSEIMessage(C, E)) {
const i = S.subarray(m, m + T);
b.seiSamples.push({
pts: O + h / w,
type: E,
data: i,
sampleOffset: m,
naluSize: T
})
}
m += T, e += T + 4
}
}
} else if ("audio" === b.type) b.fragmentDuration += o;
else if ("caption" === b.type) {
const {
cdatList: i,
cdatTotalSize: T
} = Ze.parseCLCPSample(S, m, d);
if (m += d, i.length) {
let t;
if (1 === i.length) t = new Uint8Array(i[0]);
else if (1 < i.length) {
let e = 0;
t = new Uint8Array(T);
for (const T of i) t.set(T, e), e += T.length
}
b.captionSamples.push({
type: 3,
pts: O,
bytes: t
})
}
}
k++, O += o / w
}
})
}
})
})
})
}
static parseEmsg(e) {
let t, i, r, n, s, a = "",
o = "",
l = 0;
if (0 === e[0]) {
for (;
"\0" !== We.bin2str(e.subarray(l, l + 1));) a += We.bin2str(e.subarray(l, l + 1)), l += 1;
for (a += We.bin2str(e.subarray(l, l + 1)), l += 1;
"\0" !== We.bin2str(e.subarray(l, l + 1));) o += We.bin2str(e.subarray(l, l + 1)), l += 1;
o += We.bin2str(e.subarray(l, l + 1)), l += 1, t = We.readUint32(e, 12), i = We.readUint32(e, 16), n = We.readUint32(e, 20), s = We.readUint32(e, 24), l = 28
} else {
l += 4, t = We.readUint32(e, l), l += 4;
const i = We.readUint32(e, l);
l += 4;
var d = We.readUint32(e, l);
for (l += 4, r = Math.pow(2, 32) * i + d, Number.isSafeInteger(r) || (r = Number.MAX_SAFE_INTEGER, Qe().warn(Je, "Presentation time exceeds safe integer limit and wrapped to max safe integer in parsing emsg box")), n = We.readUint32(e, l), l += 4, s = We.readUint32(e, l), l += 4;
"\0" !== We.bin2str(e.subarray(l, l + 1));) a += We.bin2str(e.subarray(l, l + 1)), l += 1;
for (a += We.bin2str(e.subarray(l, l + 1)), l += 1;
"\0" !== We.bin2str(e.subarray(l, l + 1));) o += We.bin2str(e.subarray(l, l + 1)), l += 1;
o += We.bin2str(e.subarray(l, l + 1)), l += 1
}
return {
schemeIdUri: a,
value: o,
timeScale: t,
presentationTime: r,
presentationTimeDelta: i,
eventDuration: n,
id: s,
payload: e.subarray(l, e.byteLength)
}
}
static extractID3PayloadCreateID3Track(e, t, i, r) {
const n = new M(e.payload, r),
s = new Uint8Array(e.payload),
a = s.byteLength;
let o = 0,
l = 0;
var d = ne(e.presentationTime) ? e.presentationTime / e.timeScale : t + e.presentationTimeDelta / e.timeScale;
if (ne(d)) {
const c = e.eventDuration,
h = s.subarray(0, 10),
p = We.bin2str(h.subarray(l, l + 3));
l += 3, "ID3" !== p && Qe().error(Je, "No ID3 tag found when extracting ID3 payload"), l += 2;
var t = s.subarray(l, l + 1),
e = 64 & t[0],
u = 16 & t[0];
if (l += 1, M.readSynchSafeUint32(s.subarray(l, l + 4)), l += 4, e) {
const f = M.readSynchSafeUint32(s.subarray(l, l + 4));
l += 4, l += f
}
for (; l + 2 < a;) {
We.bin2str(s.subarray(l, l + 4)), l += 4;
const m = M.readSynchSafeUint32(s.subarray(l, l + 4));
l += 4;
const r = d + o * c,
a = {
data: s,
pts: r,
dts: r,
keyTagInfo: void 0,
frames: n.frames
};
i.id3Samples.push(a), l += m, o++, u && ("DI3" !== We.bin2str(s.subarray(l, l + 3)) && Qe().error(Je, "End should be DI3 if footer present in extracting ID3 payload"), l += 3, l += 7)
}
l + 2 === a && 0 !== We.readUint16(s, l) && Qe().warn(Je, "Padding should be 0 when extracting ID3 payload")
} else Qe().error(Je, "No pts found in emsg info when extracting ID3 payload")
}
append(e, t, i, r, n, s, a) {
let o = this.initData,
l = 0,
d = 0,
u = !1,
c = !1;
void 0 === o && (this.resetInitSegment(e, 0), o = this.initData);
let h, p = this.initPtsTs;
p || (h = Ze.getStartDtsTs(o, e), this.initPtsTs = p = {
baseTime: h.baseTime - Math.round(t * h.timescale),
timescale: h.timescale
}, this.observer.trigger(v.INIT_PTS_FOUND, {
initPTS: p
})), o.foundLargeTimescale && Ze.has32BitTfdts(e) && !a && (e = ze.remuxOverflowSegment(e, this.logger)), h = Ze.getStartDtsTs(o, e);
const f = We.findBox(e, ["emsg"]);
if (o.video && o.video.encrypted && (We.findBox(e, ["moof", "traf"]).find(function(e) {
return Boolean(We.findBox(e, ["senc"])[0] || We.findBox(e, ["saiz"])[0] && We.findBox(e, ["saio"])[0])
}) || this.logger.warn(Je, `Missing subsample information for encrypted content codec=${o.videoCodec}`)), a) {
const t = this._videoTrack.timescale;
a = Math.ceil(a * t) / t;
const i = (h.baseTime + this.audioPrimingDelay * h.timescale) / h.timescale;
if (this._videoTrack && this._audioTrack && !this._silentAudioTrack) {
const e = Te.getTrack(this.observer, this._audioTrack.id, this._audioTrack.codec, 2, this.logger);
if (!e) throw `unable to create silent audio track for codec ${this._audioTrack.codec}`;
this._silentAudioTrack = Object.assign(Object.assign({}, e), {
sequenceNumber: 0
});
const t = ge.initSegment([this._videoTrack, this._silentAudioTrack]);
this.remuxedInitDataTrack = {
type: "audiovideo",
container: "video/mp4",
codec: this._silentAudioTrack.config.codec + "," + this._videoTrack.codec,
initSegment: t
};
const i = {
track: this.remuxedInitDataTrack
};
this.observer.trigger(v.FRAG_PARSING_INIT_SEGMENT, i)
}
Ze.parseSamples(i, e, this._videoTrack, a, !1, 1), this.mp4Remuxer.remuxIFrame(i, this._videoTrack, this._silentAudioTrack, a, this.remuxedInitDataTrack), this._videoTrack.samples = []
} else {
a = (h.baseTime - this.audioPrimingDelay * h.timescale) / h.timescale, a = Math.max(0, a);
if (f && 0 < f.length) {
const e = f.map(e => {
e = Ze.parseEmsg(e);
return "https://aomedia.org/emsg/ID3\0" !== e.schemeIdUri || this._id3Track || (this._id3Track = {
id3Samples: [],
inputTimescale: 9e4
}), e
});
this._id3Track && e.map(e => {
Ze.extractID3PayloadCreateID3Track(e, t, this._id3Track, this.logger)
})
}
this._videoTrack && (Ze.parseSamples(a, e, this._videoTrack, void 0, this.trySEICaptions, -1), l = this._videoTrack.fragmentDuration / this._videoTrack.timescale, u = !0, this._videoTrack.fragmentDuration = 0, this.trySEICaptions ? (Ze.extractSEICaptionsFromNALu(this._videoTrack.seiSamples, this._captionTrack), this._videoTrack.seiSamples = []) : this._captionTrack && Ze.parseSamples(a, e, this._captionTrack, void 0, !1, Number.MAX_SAFE_INTEGER)), this._audioTrack && (Ze.parseSamples(a, e, this._audioTrack, void 0, !1, -1), d = this._audioTrack.fragmentDuration / this._audioTrack.timescale, c = !0, this._audioTrack.fragmentDuration = 0), this.mp4Remuxer.remuxEmsgAndRawData(d, c, l, u, this._captionTrack, this._id3Track, a, h.timescale, e, this.remuxedInitDataTrack), this._id3Track && (this._id3Track.id3Samples = [])
}
}
static extractSEICaptionsFromNALu(a, o) {
if (a) {
for (let s = 0; s < a.length; ++s) {
var l = a[s],
d = l.pts;
let t = 0;
t++;
let e = 0,
i = 0,
r = !1,
n = 0;
for (; !r && t < l.data.length;) {
for (e = 0; !(t >= l.data.length) && (n = l.data[t++], e += n, 255 === n););
for (i = 0; !(t >= l.data.length) && (n = l.data[t++], i += n, 255 === n););
const a = l.data.length - t;
if (4 === e && t < l.data.length) {
if (r = !0, 181 === l.data[t++]) {
const a = We.readUint16(l.data, t);
if (t += 2, 49 === a) {
const a = We.readUint32(l.data, t);
if (t += 4, 1195456820 === a && 3 === l.data[t++]) {
const a = l.data[t++];
t++;
const u = 31 & a,
c = [];
if (64 & a)
for (let e = 0; e < u; e++) {
const a = l.data[t++];
if (a === (252 & a)) {
const o = 3 & a;
if (0 == o || 1 == o) {
const a = l.data[t++],
o = l.data[t++];
c.push(a), c.push(o)
}
} else t += 2
}
0 < c.length && o.captionSamples.push({
type: 3,
pts: d,
bytes: c
})
}
}
}
} else if (i < a) t += i;
else if (i > a) break
}
}
return o
}
}
}
const et = {
name: "ExpGolomb"
};
class tt {
constructor(e, t) {
this.data = e, this.logger = t, this._bytesAvailable = e.byteLength, this.word = 0, this.bitsAvailable = 0
}
get bytesAvailable() {
return this._bytesAvailable
}
loadWord() {
const e = this.data,
t = this._bytesAvailable,
i = e.byteLength - t,
r = new Uint8Array(4),
n = Math.min(4, t);
if (0 === n) throw new Error("no bytes available");
r.set(e.subarray(i, i + n)), this.word = new DataView(r.buffer).getUint32(0), this.bitsAvailable = 8 * n, this._bytesAvailable -= n
}
skipBits(e) {
var t;
this.bitsAvailable > e || (t = (e -= this.bitsAvailable) >> 3, e -= t >> 3, this._bytesAvailable -= t, this.loadWord()), this.word <<= e, this.bitsAvailable -= e
}
readBits(e) {
let t = Math.min(this.bitsAvailable, e);
var i = this.word >>> 32 - t;
return 32 < e && this.logger.error(et, "Cannot read more than 32 bits at a time"), this.bitsAvailable -= t, 0 < this.bitsAvailable ? this.word <<= t : 0 < this._bytesAvailable && this.loadWord(), t = e - t, 0 < t && this.bitsAvailable ? i << t | this.readBits(t) : i
}
skipLZ() {
let e;
for (e = 0; e < this.bitsAvailable; ++e)
if (0 != (this.word & 2147483648 >>> e)) return this.word <<= e, this.bitsAvailable -= e, e;
return this.loadWord(), e + this.skipLZ()
}
skipUEG() {
this.skipBits(1 + this.skipLZ())
}
skipEG() {
this.skipBits(1 + this.skipLZ())
}
readUEG() {
var e = this.skipLZ();
return this.readBits(e + 1) - 1
}
readEG() {
var e = this.readUEG();
return 1 & e ? 1 + e >>> 1 : -1 * (e >>> 1)
}
readBoolean() {
return 1 === this.readBits(1)
}
readUByte() {
return this.readBits(8)
}
readUShort() {
return this.readBits(16)
}
readUInt() {
return this.readBits(32)
}
skipScalingList(e) {
let t, i, r = 8,
n = 8;
for (t = 0; t < e; t++) 0 !== n && (i = this.readEG(), n = (r + i + 256) % 256), r = 0 === n ? r : n
}
readSPS() {
let e, t, i, r = 0,
n = 0,
s = 0,
a = 0;
const o = this.readUByte.bind(this),
l = this.readBits.bind(this),
d = this.readUEG.bind(this),
u = this.readBoolean.bind(this),
c = this.skipBits.bind(this),
h = this.skipEG.bind(this),
p = this.skipUEG.bind(this),
f = this.skipScalingList.bind(this);
o();
var m = o();
if (l(5), c(3), o(), p(), 100 === m || 110 === m || 122 === m || 244 === m || 44 === m || 83 === m || 86 === m || 118 === m || 128 === m) {
const e = d();
if (3 === e && c(1), p(), p(), c(1), u())
for (t = 3 !== e ? 8 : 12, i = 0; i < t; i++) u() && f(i < 6 ? 16 : 64)
}
p();
var g = d();
if (0 === g) d();
else if (1 === g)
for (c(1), h(), h(), e = d(), i = 0; i < e; i++) h();
p(), c(1);
var y = d(),
m = d(),
g = l(1);
0 === g && c(1), c(1), u() && (r = d(), n = d(), s = d(), a = d());
let v = [1, 1];
if (u() && u()) switch (o()) {
case 1:
v = [1, 1];
break;
case 2:
v = [12, 11];
break;
case 3:
v = [10, 11];
break;
case 4:
v = [16, 11];
break;
case 5:
v = [40, 33];
break;
case 6:
v = [24, 11];
break;
case 7:
v = [20, 11];
break;
case 8:
v = [32, 11];
break;
case 9:
v = [80, 33];
break;
case 10:
v = [18, 11];
break;
case 11:
v = [15, 11];
break;
case 12:
v = [64, 33];
break;
case 13:
v = [160, 99];
break;
case 14:
v = [4, 3];
break;
case 15:
v = [3, 2];
break;
case 16:
v = [2, 1];
break;
case 255:
v = [o() << 8 | o(), o() << 8 | o()]
}
return {
width: Math.ceil(16 * (y + 1) - 2 * r - 2 * n),
height: (2 - g) * (m + 1) * 16 - (g ? 2 : 4) * (s + a),
pixelRatio: v
}
}
readSliceType() {
return this.readUByte(), this.readUEG(), this.readUEG()
}
}
const it = {
name: "TS Demuxer"
};
var rt, nt = class extends c {
constructor(e, t, i, r, n) {
super(e, t, i, r, n)
}
static probe(e, t) {
return 564 <= e.length && 71 === e[0] && 71 === e[188] && 71 === e[376]
}
resetInitSegment(e, t, i) {
this.pmtParsed = !1;
var r = {
id: this._pmtId = -1,
inputTimescale: 9e4,
timescale: NaN,
duration: 0,
encrypted: i && i.isEncrypted,
keyTagInfo: i
},
i = {
len: 0,
sequenceNumber: 0
};
this._avcContext = {
info: Object.assign({}, r),
parsingData: Object.assign(Object.assign({}, i), {
esSamples: new Array,
dropped: 0
}),
config: {},
container: "video/mp2t",
type: "video"
}, this._audioContext = {
info: Object.assign({}, r),
parsingData: Object.assign(Object.assign({}, i), {
esSamples: new Array
}),
container: "video/mp2t",
type: "audio"
}, this._id3Track = {
id: -1,
inputTimescale: 9e4,
id3Samples: []
}, this._txtTrack = {
inputTimescale: 9e4,
captionSamples: []
}, this._duration = t, this._initSegment = e
}
append(e, t, i, r, n, s, a) {
let o, l, d, u, c, h = !1;
this.contiguous = i;
const p = this._avcContext,
f = this._audioContext,
m = this._id3Track;
let g = this.pmtParsed,
y = p.info.id,
v = f.info.id,
S = m.id,
b = this._pmtId,
T = p.pesData,
E = f.pesData,
I = m.pesData;
if (this.iframeMode = void 0 !== a, this._initSegment && 0 < this._initSegment.byteLength) {
const t = new Uint8Array(this._initSegment.byteLength + e.byteLength);
t.set(this._initSegment), t.set(e, this._initSegment.byteLength), this._initSegment = void 0, 71 === t[0] && (e = t)
}
let w, A, O = e.length;
for (O -= O % 188, o = 0; o < O; o += 188) {
if (71 !== e[o]) {
const e = new D(!1, "TS packet did not start with 0x47", $.NoTSSyncByteFound);
return void this.observer.trigger(x.INTERNAL_ERROR, e)
}
if (l = !!(64 & e[o + 1]), d = ((31 & e[o + 1]) << 8) + e[o + 2], 1 < (48 & e[o + 3]) >> 4) {
if (u = o + 5 + e[o + 4], u === o + 188) continue
} else u = o + 4;
switch (d) {
case y:
l && (T && (c = this._parsePES(T)) && this._parseAVCPES(c, !1), T = {
data: [],
size: 0,
keyTagInfo: n
}), T && (T.data.push(e.subarray(u, o + 188)), T.size += o + 188 - u);
break;
case v:
if (l && !this.iframeMode) {
if (E && (c = this._parsePES(E))) switch (f.segmentCodec) {
case "aac":
this._parseAACPES(c);
break;
case "mp3":
this._parseMPEGPES(c);
break;
case "ac3":
case "ec3":
this._parseDolbyPES(c)
}
E = {
data: [],
size: 0,
keyTagInfo: n
}
}
E && (E.data.push(e.subarray(u, o + 188)), E.size += o + 188 - u);
break;
case S:
l && (I && (c = this._parsePES(I)) && m.id3Samples.push(c), I = {
data: [],
size: 0
}), I && (I.data.push(e.subarray(u, o + 188)), I.size += o + 188 - u);
break;
case 0:
l && (u += e[u] + 1), b = this._pmtId = this._parsePAT(e, u);
break;
case b:
l && (u += e[u] + 1);
const t = this._parsePMT(e, u, this.typeSupported);
y = t.avcId, 0 < y && (p.info.id = y, p.info.encrypted = t.videoEncrypted), v = t.audioId, 0 < v && (f.info.id = v, f.segmentCodec = t.audioSegmentCodec, f.info.encrypted = t.audioEncrypted), S = t.id3Id, 0 < S && (m.id = S), h && !g && (h = !1, o = -188), g = this.pmtParsed = !0;
break;
case 17:
case 8191:
break;
default:
h = !0
}
}
if (T && (c = this._parsePES(T)) ? (this._parseAVCPES(c, !0), p.pesData = void 0) : p.pesData = T, E && (c = this._parsePES(E))) {
switch (f.segmentCodec) {
case "aac":
this._parseAACPES(c);
break;
case "mp3":
this._parseMPEGPES(c);
break;
case "ac3":
case "ec3":
this._parseDolbyPES(c)
}
f.pesData = void 0
} else E && E.size && this.logger.warn(it, "last AAC PES packet truncated,might overlap between fragments"), f.pesData = E;
I && (c = this._parsePES(I)) ? (m.id3Samples.push(c), m.pesData = void 0) : m.pesData = I, f.config && f.segmentCodec && (w = {
type: "audio",
info: f.info,
config: f.config,
parsingData: f.parsingData
});
var k, C = p.config;
"string" == typeof(k = C).codec && Array.isArray(k.sps) && Array.isArray(k.pps) && "number" == typeof k.width && "number" == typeof k.height && Array.isArray(k.pixelRatio) && (A = {
type: "video",
info: p.info,
config: C,
parsingData: p.parsingData
}), this.esRemuxer.remuxEsTracks(w, A, m, this._txtTrack, t, i, r, n, s, a)
}
destroy() {
this._duration = 0
}
_parsePAT(e, t) {
return (31 & e[t + 10]) << 8 | e[t + 11]
}
_parsePMT(e, t, i) {
var r;
const n = {
audioId: -1,
avcId: -1,
id3Id: -1,
audioEncrypted: !1,
videoEncrypted: !1
},
s = t + 3 + ((15 & e[t + 1]) << 8 | e[t + 2]) - 4;
for (t += 12 + ((15 & e[t + 10]) << 8 | e[t + 11]); t < s;) {
switch (r = (31 & e[t + 1]) << 8 | e[t + 2], e[t]) {
case 207:
n.audioEncrypted = !0;
case 15:
-1 === n.audioId && (n.audioId = r, n.audioSegmentCodec = "aac");
break;
case 21:
-1 === n.id3Id && (n.id3Id = r);
break;
case 219:
n.videoEncrypted = !0;
case 27:
-1 === n.avcId && (n.avcId = r);
break;
case 3:
case 4:
!0 !== i.mpeg && !0 !== i.mp3 ? this.logger.warn(it, "MPEG audio found, not supported in this browser for now") : -1 === n.audioId && (n.audioId = r, n.audioSegmentCodec = "mp3");
break;
case 193:
n.audioEncrypted = !0;
case 129:
!0 !== i.ac3 ? this.logger.warn(it, "AC-3 audio found, not supported in this browser for now") : -1 === n.audioId && (n.audioId = r, n.audioSegmentCodec = "ac3");
break;
case 194:
n.audioEncrypted = !0;
case 135:
!0 !== i.ec3 ? this.logger.warn(it, "EC-3 audio found, not supported in this browser for now") : -1 === n.audioId && (n.audioId = r, n.audioSegmentCodec = "ec3");
break;
case 36:
this.logger.warn(it, "HEVC stream type found, not supported for now");
break;
default:
this.logger.warn(it, "unkown stream type:" + e[t])
}
t += 5 + ((15 & e[t + 3]) << 8 | e[t + 4])
}
return n
}
_parsePES(e) {
let i, t, r, n, s, a, o = 0;
const l = e.data,
d = e.keyTagInfo;
let u = NaN,
c = NaN;
if (e && 0 !== e.size) {
for (; l[0].length < 19 && 1 < l.length;) {
const e = new Uint8Array(l[0].length + l[1].length);
e.set(l[0]), e.set(l[1], l[0].length), l[0] = e, l.splice(1, 1)
}
if (i = l[0], 1 === (i[0] << 16) + (i[1] << 8) + i[2] && (r = (i[4] << 8) + i[5], !(r && r > e.size - 6))) {
192 & (t = i[7]) && (u = 536870912 * (14 & i[9]) + 4194304 * (255 & i[10]) + 16384 * (254 & i[11]) + 128 * (255 & i[12]) + (254 & i[13]) / 2, 64 & t ? (c = 536870912 * (14 & i[14]) + 4194304 * (255 & i[15]) + 16384 * (254 & i[16]) + 128 * (255 & i[17]) + (254 & i[18]) / 2, 54e5 < u - c && (this.logger.warn(it, `${Math.round((u-c)/9e4)}s delta between PTS and DTS, align them`), u = c)) : c = u), n = i[8], a = n + 9, e.size -= a, s = new Uint8Array(e.size);
for (let t = 0, e = l.length; t < e; t++) {
i = l[t];
let e = i.byteLength;
if (a) {
if (a > e) {
a -= e;
continue
}
i = i.subarray(a), e -= a, a = 0
}
s.set(i, o), o += e
}
return r && (r -= n + 3), {
data: s,
pts: u,
dts: c,
len: r,
keyTagInfo: d
}
}
}
}
pushAccesUnit(e, t) {
const i = e.avcSample;
if (i && i.units.length && i.frame) {
const r = e.parsingData.esSamples,
n = r.length;
(!0 === i.key || e.config.sps && (n || this.contiguous)) && (i.id = n, i.keyTagInfo = t, e.info.encrypted) && i.units.forEach(e => {
if (48 < e.data.byteLength) switch (e.type) {
case 1:
case 5:
e.data = this.discardEPB(e.data)
}
}), n || isFinite(i.pts) ? r.push(i) : e.parsingData.dropped++
}
}
_parseAVCPES(o, e) {
if (!o.data) throw "invalid pes data";
const l = this._avcContext,
t = this._parseAVCNALu(o.data);
let d, u, c, h = l.avcSample;
const p = o.keyTagInfo;
o.data = void 0, t.forEach(n => {
switch (n.type) {
case 1:
if (h && !this.iframeMode) {
u = !0, h.frame = !0;
const o = n.data;
if (4 < o.length) {
const n = new tt(o, this.logger).readSliceType();
2 !== n && 4 !== n && 7 !== n && 9 !== n || (h.key = !0)
}
}
break;
case 5:
u = !0, h && (h = h || (l.avcSample = this._createAVCSample(!0, o.pts, o.dts, "")), h.key = !0, h.frame = !0);
break;
case 6:
u = !0, d = new tt(this.discardEPB(n.data), this.logger), d.readUByte();
let e = 0,
t = 0,
i = !1,
r = 0;
for (; !i && 1 < d.bytesAvailable;) {
for (e = 0; r = d.readUByte(), e += r, 255 === r;);
for (t = 0; r = d.readUByte(), t += r, 255 === r;);
if (4 === e && 0 !== d.bytesAvailable) {
if (i = !0, 181 === d.readUByte() && 49 === d.readUShort() && 1195456820 === d.readUInt() && 3 === d.readUByte()) {
const n = d.readUByte(),
l = 31 & n,
s = [n, d.readUByte()];
for (c = 0; c < l; c++) s.push(d.readUByte()), s.push(d.readUByte()), s.push(d.readUByte());
this._insertSampleInOrder(this._txtTrack.captionSamples, {
type: 3,
pts: o.pts,
bytes: s
})
}
} else if (t < d.bytesAvailable)
for (c = 0; c < t; c++) d.readUByte()
}
break;
case 7:
if (u = !0, !l.config.sps) {
d = new tt(n.data, this.logger);
const o = d.readSPS();
l.config.width = o.width, l.config.height = o.height, l.config.pixelRatio = o.pixelRatio, l.config.sps = [n.data], l.info.duration = this._duration;
const a = n.data.subarray(1, 4);
let t = "avc1.";
for (c = 0; c < 3; c++) {
let e = a[c].toString(16);
e.length < 2 && (e = "0" + e), t += e
}
l.config.codec = t
}
break;
case 8:
u = !0, l.config.pps || (l.config.pps = [n.data]);
break;
case 9:
u = !1, h && this.pushAccesUnit(l, p), h = l.avcSample = this._createAVCSample(!1, o.pts, o.dts, "");
break;
case 12:
u = !1;
break;
default:
u = !1, h && (h.debug += "unknown NAL " + n.type + " ")
}
h && u && h.units.push(n)
}), e && h && (this.pushAccesUnit(l, p), l.avcSample = void 0)
}
_createAVCSample(e, t, i, r) {
return {
id: NaN,
key: e,
pts: t,
dts: i,
units: new Array,
debug: r
}
}
_insertSampleInOrder(t, i) {
var r = t.length;
if (0 < r) {
if (i.pts >= t[r - 1].pts) t.push(i);
else
for (let e = r - 1; 0 <= e; e--)
if (i.pts < t[e].pts) {
t.splice(e, 0, i);
break
}
} else t.push(i)
}
_getLastNalUnit() {
const e = this._avcContext;
let t, i = e.avcSample;
if (!i || 0 === i.units.length) {
const t = e.parsingData.esSamples;
i = t[t.length - 1]
}
if (i) {
const e = i.units;
t = e[e.length - 1]
}
return t
}
_parseAVCNALu(e) {
const t = e.byteLength;
let i, r, n = 0;
const s = this._avcContext;
let a = s.naluState || 0;
const o = a,
l = [];
let d, u, c, h = -1;
for (-1 === a && (h = 0, c = 31 & e[0], a = 0, n = 1); n < t;)
if (i = e[n++], a)
if (1 !== a)
if (i)
if (1 === i) {
if (0 <= h) d = {
data: e.subarray(h, n - a - 1),
type: c
}, l.push(d);
else {
const t = this._getLastNalUnit();
if (t && (o && n <= 4 - o && t.state && (t.data = t.data.subarray(0, t.data.byteLength - o)), r = n - a - 1, 0 < r)) {
const i = new Uint8Array(t.data.byteLength + r);
i.set(t.data, 0), i.set(e.subarray(0, r), t.data.byteLength), t.data = i, t.state = 0
}
}
a = n < t ? (u = 31 & e[n], h = n, c = u, 0) : -1
} else a = 0;
else a = 3;
else a = i ? 0 : 2;
else a = i ? 0 : 1;
if (0 <= h && 0 <= a && (d = {
data: e.subarray(h, t),
type: c,
state: a
}, l.push(d)), 0 === l.length) {
const t = this._getLastNalUnit();
if (t) {
const i = new Uint8Array(t.data.byteLength + e.byteLength);
i.set(t.data, 0), i.set(e, t.data.byteLength), t.data = i
}
}
return s.naluState = a, l
}
discardEPB(e) {
const t = e.byteLength,
i = [];
let r = 1;
for (; r < t - 2;) 0 === e[r] && 0 === e[r + 1] && 3 === e[r + 2] ? (i.push(r + 2), r += 2) : r++;
if (0 === i.length) return e;
const n = t - i.length,
s = new Uint8Array(n);
let a = 0;
for (r = 0; r < n; a++, r++) a === i[0] && (a++, i.shift()), s[r] = e[a];
return s
}
_parseAACPES(e) {
const t = this._audioContext,
i = t.audioLastPTS,
r = e.keyTagInfo;
let n, s, a, o, l, d, u, c = e.data,
h = e.pts,
p = t.audioOverFlow;
if (p) {
const e = new Uint8Array(p.byteLength + c.byteLength);
e.set(p, 0), e.set(c, p.byteLength), c = e
}
for (a = 0, d = c.length; a < d - 1 && (255 !== c[a] || 240 != (240 & c[a + 1])); a++);
if (a) {
let e, t, i;
i = a < d - 1 ? (e = `AAC PES did not start with ADTS header,offset:${a}`, t = !1, $.PESDidNotStartWithADTS) : (e = "no ADTS header found in AAC PES", t = !0, $.NoADTSHeaderInPES), this.logger.warn(it, `parsing error:${e}`);
const r = new D(t, e, i);
if (this.observer.trigger(x.INTERNAL_ERROR, r), t) return
}
if (!t.config) {
const e = E(this.observer, c, a, void 0, this.logger);
if (!e) throw "unable to parse adts header";
t.config = e
}
s = 0;
var f = 9216e4 / t.config.samplerate;
if (p && i) {
const e = i + f;
1 < Math.abs(e - h) && (h = e)
}
for (; a + 5 < d && (o = 1 & c[a + 1] ? 7 : 9, n = (3 & c[a + 3]) << 11 | c[a + 4] << 3 | (224 & c[a + 5]) >>> 5, n -= o, 0 < n && a + o + n <= d);)
for (l = h + s * f, u = {
unit: c.subarray(a + o, a + o + n),
pts: l,
dts: l,
keyTagInfo: r
}, t.parsingData.esSamples.push(u), t.parsingData.len += n, a += n + o, s++; a < d - 1 && (255 !== c[a] || 240 != (240 & c[a + 1])); a++);
p = a < d ? c.subarray(a, d) : void 0, t.audioOverFlow = p, t.audioLastPTS = l
}
_parseMPEGPES(e) {
"mp3" === this._audioContext.segmentCodec && ee.parse(this._audioContext.parsingData, e.data, 0, e.pts, this.logger)
}
_parseDolbyPES(e) {
const t = this._audioContext;
let i = e.data,
r = e.pts;
var n = e.keyTagInfo;
let s = 0,
a = 0,
o = t.audioOverFlow;
e = t.audioLastPTS;
if (!t.config) {
let e;
if ("ac3" === t.segmentCodec ? e = j(this.observer, i, a, this.logger) : "ec3" === t.segmentCodec && (e = Y(this.observer, i, a, this.logger)), !e) throw "unable to parse dolby header";
t.config = e
}
if ("ac3" !== t.config.segmentCodec && "ec3" !== t.config.segmentCodec) throw "unexpected config type";
var l = 1536 / t.config.samplerate * t.info.inputTimescale;
if (o) {
const c = new Uint8Array(o.byteLength + i.byteLength);
c.set(o, 0), c.set(i, o.byteLength), i = c
}
var d = i.length;
if (o && e) {
const c = e + l;
1 < Math.abs(c - r) && (r = c)
}
let u = 0;
for (; a + u <= d;) {
if (11 !== i[a] || 119 !== i[a + 1]) {
const c = new D(!0, "invalid dolby audio magic", $.InvalidDolbyAudioMagic);
return void this.observer.trigger(x.INTERNAL_ERROR, c)
}
"ac3" === t.segmentCodec ? u = Q(this.observer, i, a) : "ec3" === t.segmentCodec && (u = X(this.observer, i, a, this.logger));
const c = r + s * l;
t.audioLastPTS = c;
const o = {
unit: i.subarray(a, a + u),
pts: c,
dts: c,
keyTagInfo: n
};
t.parsingData.esSamples.push(o), t.info.duration = this._duration, t.parsingData.len += u, a += u, s++
}
o = a < d ? i.subarray(a, d) : void 0, t.audioOverFlow = o
}
};
class st extends a {
constructor(e, t, i, r) {
super(), this.typeSupported = e, this.config = t, this.vendor = i, this.logger = r
}
destroy() {
this.removeAllListeners();
const e = this.demuxer,
t = this.remuxer;
e && e.destroy(), t && t.destroy()
}
push(t, i, r, n, s, a, o, l, d, u, c, h) {
if (t) {
let e = this.demuxer;
var p = new Uint8Array(t);
if (!e || (s || a) && !this.probeFn(p, this.logger)) {
const {
typeSupported: t,
config: i
} = this, r = [{
demux: Ze,
remux: ze
}, {
demux: nt,
remux: Ee
}, {
demux: J,
remux: Ee
}, {
demux: z,
remux: Ee
}, {
demux: K,
remux: Ee
}, {
demux: ie,
remux: Ee
}];
for (const n of r) {
const r = n.demux["probe"];
if (r(p, this.logger)) {
this.remuxer = new n.remux(this, i, t, this.vendor, this.logger), e = new n.demux(this, this.remuxer, i, t, this.logger), this.probeFn = r;
break
}
}
if (!e) {
const t = new D(!0, "no demux matching with content found", $.DemuxerNotFound);
return void this.trigger(x.INTERNAL_ERROR, t)
}
this.demuxer = e
}
const f = this.remuxer,
m = !this.lastKeyTagInfo || i && "NONE" !== i.method && this.lastKeyTagInfo.uri !== i.uri;
if (this.lastKeyTagInfo = i, (s || a || m) && (e.resetInitSegment(new Uint8Array(r), l, i, s), f.resetInitSegment()), s) {
const t = u ? S(u) : void 0;
e.resetTimeStamp(t), f.resetTimeStamp(t)
}
e.append(p, n, o, d, i, c, h)
}
}
}
function at() {
let e = `${Date.now()}-${Math.random()}`;
return "undefined" != typeof performance && "function" == typeof performance.now && (e += `-${performance.now()}`), e
}
class ot {
constructor(e, t) {
this.rpc = e, this.logger = t, this.init = (t, n, s) => e => {
const i = at(),
r = this.demuxers[i] = new st(t, n, s, this.logger);
[v.INIT_PTS_FOUND, v.FRAG_PARSING_INIT_SEGMENT, v.FRAG_PARSING_DATA, v.FRAG_PARSED, x.INTERNAL_ERROR].forEach(t => {
r.on(t, e => this.rpc.invoke("demuxer.event", [i, t, e])(() => {}))
}), e(i)
}, this.push = (i, r, n, s, a, o, l, d, u, c, h, p, f) => e => {
const t = this.demuxers[i];
t ? (t.push(r, n, s, a, o, l, d, u, c, h, p, f), e()) : e(void 0, `Demuxer with id "${i}" does not exist on push`)
}, this.destroy = i => e => {
const t = this.demuxers[i];
t ? (t.destroy(), delete this.demuxers[i], e()) : this.logger.error(`Demuxer with id "${i}" does not exist on destroy`)
}, this.demuxers = {}, e.register("demuxer.init", this.init), e.register("demuxer.push", this.push), e.register("demuxer.destroy", this.destroy)
}
}
class lt {
constructor(e) {
this.worker = e, this.handlers = {}, this.deferers = {}, this._messageHandler = e => {
var {
type: t,
id: i,
command: r,
args: n,
result: e,
error: s
} = e.data;
if (t === rt.Invoke) try {
if (null == this.handlers[r]) throw new Error(`command ${r} not found`);
this.handlers[r](...n)(this._respond.bind(this, i, r))
} catch (s) {
this._respond(i, r, null, new Error(`command ${r} not found`))
} else t === rt.Result && null != this.deferers[i] && (this.deferers[i](e, s), delete this.deferers[i])
}, e.addEventListener("message", this._messageHandler)
}
register(e, t) {
if (null != this.handlers[e]) return !1;
this.handlers[e] = t
}
unregister(e) {
if (null != this.handlers[e]) return !1;
delete this.handlers[e]
}
invoke(i, r, n) {
return (e = lt._fallbackCallback) => {
var t = at();
this.deferers[t] = e;
t = {
type: rt.Invoke,
id: t,
command: i,
args: r
};
this._send(t, n)
}
}
teardown(e) {
this.worker.removeEventListener("message", this._messageHandler), e()
}
_respond(e, t, i, r, n) {
r instanceof Error && (r = `[${r.name}] ${r.message}\n${r.stack}`);
r = {
type: rt.Result,
id: e,
command: t,
result: i,
error: r
};
this._send(r, n)
}
_send(e, t = []) {
this.worker.postMessage(e, t.map(e => ArrayBuffer.isView(e) ? e.buffer : e).filter(e => void 0 !== e))
}
}
lt._fallbackCallback = (e, t) => {
if (null != t) throw t
}, (vr = rt = rt || {})[vr.Invoke = 0] = "Invoke", vr[vr.Result = 1] = "Result", ArrayBuffer.isView || (ArrayBuffer.isView = function(e) {
return null !== e && "object" == typeof e && e.buffer instanceof ArrayBuffer
}), void 0 !== Yy && Yy && (Vr = new lt(l), iu = (n => {
const t = (i = []) => {
const r = {};
return ["fatal", "error", "warn", "info", "debug", "trace", "qe"].forEach(e => {
return r[e] = (t = e, (...e) => {
n.invoke("logger.log", [i, t, ...e])((e, t) => {
if (null != t) throw t
})
});
var t
}), r.child = e => t([...i, e]), r
};
return t()
})(Vr), new i(Vr, iu), new ot(Vr, iu));
var dt = function(e, t) {
return (dt = Object.setPrototypeOf || {
__proto__: []
}
instanceof Array && function(e, t) {
e.__proto__ = t
} || function(e, t) {
for (var i in t) Object.prototype.hasOwnProperty.call(t, i) && (e[i] = t[i])
})(e, t)
};
function ut(e, t) {
if ("function" != typeof t && null !== t) throw new TypeError("Class extends value " + String(t) + " is not a constructor or null");
function i() {
this.constructor = e
}
dt(e, t), e.prototype = null === t ? Object.create(t) : (i.prototype = t.prototype, new i)
}
var ct = function() {
return (ct = Object.assign || function(e) {
for (var t, i = 1, r = arguments.length; i < r; i++)
for (var n in t = arguments[i]) Object.prototype.hasOwnProperty.call(t, n) && (e[n] = t[n]);
return e
}).apply(this, arguments)
};
function ht(e, t, i, r) {
var n, s = arguments.length,
a = s < 3 ? t : null === r ? r = Object.getOwnPropertyDescriptor(t, i) : r;
if ("object" == typeof Reflect && "function" == typeof Reflect.decorate) a = Reflect.decorate(e, t, i, r);
else
for (var o = e.length - 1; 0 <= o; o--)(n = e[o]) && (a = (s < 3 ? n(a) : 3 < s ? n(t, i, a) : n(t, i)) || a);
return 3 < s && a && Object.defineProperty(t, i, a), a
}
function pt(e, t) {
if ("object" == typeof Reflect && "function" == typeof Reflect.metadata) return Reflect.metadata(e, t)
}
function ft(e) {
var t = "function" == typeof Symbol && Symbol.iterator,
i = t && e[t],
r = 0;
if (i) return i.call(e);
if (e && "number" == typeof e.length) return {
next: function() {
return {
value: (e = e && r >= e.length ? void 0 : e) && e[r++],
done: !e
}
}
};
throw new TypeError(t ? "Object is not iterable." : "Symbol.iterator is not defined.")
}
function mt(e, t) {
var i = "function" == typeof Symbol && e[Symbol.iterator];
if (!i) return e;
var r, n, s = i.call(e),
a = [];
try {
for (;
(void 0 === t || 0 < t--) && !(r = s.next()).done;) a.push(r.value)
} catch (e) {
n = {
error: e
}
} finally {
try {
r && !r.done && (i = s.return) && i.call(s)
} finally {
if (n) throw n.error
}
}
return a
}
function gt() {
for (var e = [], t = 0; t < arguments.length; t++) e = e.concat(mt(arguments[t]));
return e
}
function yt(e) {
return "function" == typeof e
}
var vt = !1,
St = {
Promise: void 0,
set useDeprecatedSynchronousErrorHandling(e) {
vt = e
},
get useDeprecatedSynchronousErrorHandling() {
return vt
}
};
function bt(e) {
setTimeout(function() {
throw e
}, 0)
}
var Tt = {
closed: !0,
next: function(e) {},
error: function(e) {
if (St.useDeprecatedSynchronousErrorHandling) throw e;
bt(e)
},
complete: function() {}
},
Et = Array.isArray || function(e) {
return e && "number" == typeof e.length
};
function It(e) {
return null !== e && "object" == typeof e
}
var wt = (kt.prototype = Object.create(Error.prototype), kt),
At = (Ot.prototype.unsubscribe = function() {
var t;
if (!this.closed) {
var e = this._parentOrParents,
i = this._ctorUnsubscribe,
r = this._unsubscribe,
n = this._subscriptions;
if (this.closed = !0, this._parentOrParents = null, this._subscriptions = null, e instanceof Ot) e.remove(this);
else if (null !== e)
for (var s = 0; s < e.length; ++s) e[s].remove(this);
if (yt(r)) {
i && (this._unsubscribe = void 0);
try {
r.call(this)
} catch (e) {
t = e instanceof wt ? Ct(e.errors) : [e]
}
}
if (Et(n))
for (var s = -1, a = n.length; ++s < a;) {
var o = n[s];
if (It(o)) try {
o.unsubscribe()
} catch (e) {
t = t || [], e instanceof wt ? t = t.concat(Ct(e.errors)) : t.push(e)
}
}
if (t) throw new wt(t)
}
}, Ot.prototype.add = function(e) {
var t, i = e;
if (!e) return Ot.EMPTY;
switch (typeof e) {
case "function":
i = new Ot(e);
case "object":
if (i === this || i.closed || "function" != typeof i.unsubscribe) return i;
if (this.closed) return i.unsubscribe(), i;
i instanceof Ot || (t = i, (i = new Ot)._subscriptions = [t]);
break;
default:
throw new Error("unrecognized teardown " + e + " added to Subscription.")
}
var r = i._parentOrParents;
if (null === r) i._parentOrParents = this;
else if (r instanceof Ot) {
if (r === this) return i;
i._parentOrParents = [r, this]
} else {
if (-1 !== r.indexOf(this)) return i;
r.push(this)
}
r = this._subscriptions;
return null === r ? this._subscriptions = [i] : r.push(i), i
}, Ot.prototype.remove = function(e) {
var t = this._subscriptions;
!t || -1 !== (e = t.indexOf(e)) && t.splice(e, 1)
}, Ot.EMPTY = ((dl = new Ot).closed = !0, dl), Ot);
function Ot(e) {
this.closed = !1, this._parentOrParents = null, this._subscriptions = null, e && (this._ctorUnsubscribe = !0, this._unsubscribe = e)
}
function kt(e) {
return Error.call(this), this.message = e ? e.length + " errors occurred during unsubscription:\n" + e.map(function(e, t) {
return t + 1 + ") " + e.toString()
}).join("\n ") : "", this.name = "UnsubscriptionError", this.errors = e, this
}
function Ct(e) {
return e.reduce(function(e, t) {
return e.concat(t instanceof wt ? t.errors : t)
}, [])
}
var Dt, Mt, xt = "function" == typeof Symbol ? Symbol("rxSubscriber") : "@@rxSubscriber_" + Math.random(),
Pt = (ut(_t, Mt = At), _t.prototype[xt] = function() {
return this
}, _t.create = function(e, t, i) {
i = new _t(e, t, i);
return i.syncErrorThrowable = !1, i
}, _t.prototype.next = function(e) {
this.isStopped || this._next(e)
}, _t.prototype.error = function(e) {
this.isStopped || (this.isStopped = !0, this._error(e))
}, _t.prototype.complete = function() {
this.isStopped || (this.isStopped = !0, this._complete())
}, _t.prototype.unsubscribe = function() {
this.closed || (this.isStopped = !0, Mt.prototype.unsubscribe.call(this))
}, _t.prototype._next = function(e) {
this.destination.next(e)
}, _t.prototype._error = function(e) {
this.destination.error(e), this.unsubscribe()
}, _t.prototype._complete = function() {
this.destination.complete(), this.unsubscribe()
}, _t.prototype._unsubscribeAndRecycle = function() {
var e = this._parentOrParents;
return this._parentOrParents = null, this.unsubscribe(), this.closed = !1, this.isStopped = !1, this._parentOrParents = e, this
}, _t),
Rt = (ut(Lt, Dt = Pt), Lt.prototype.next = function(e) {
var t;
!this.isStopped && this._next && (t = this._parentSubscriber, St.useDeprecatedSynchronousErrorHandling && t.syncErrorThrowable ? this.__tryOrSetError(t, this._next, e) && this.unsubscribe() : this.__tryOrUnsub(this._next, e))
}, Lt.prototype.error = function(e) {
if (!this.isStopped) {
var t = this._parentSubscriber,
i = St.useDeprecatedSynchronousErrorHandling;
if (this._error) i && t.syncErrorThrowable ? this.__tryOrSetError(t, this._error, e) : this.__tryOrUnsub(this._error, e), this.unsubscribe();
else if (t.syncErrorThrowable) i ? (t.syncErrorValue = e, t.syncErrorThrown = !0) : bt(e), this.unsubscribe();
else {
if (this.unsubscribe(), i) throw e;
bt(e)
}
}
}, Lt.prototype.complete = function() {
var e, t, i = this;
this.isStopped || (e = this._parentSubscriber, this._complete && (t = function() {
return i._complete.call(i._context)
}, St.useDeprecatedSynchronousErrorHandling && e.syncErrorThrowable ? this.__tryOrSetError(e, t) : this.__tryOrUnsub(t)), this.unsubscribe())
}, Lt.prototype.__tryOrUnsub = function(e, t) {
try {
e.call(this._context, t)
} catch (e) {
if (this.unsubscribe(), St.useDeprecatedSynchronousErrorHandling) throw e;
bt(e)
}
}, Lt.prototype.__tryOrSetError = function(e, t, i) {
if (!St.useDeprecatedSynchronousErrorHandling) throw new Error("bad call");
try {
t.call(this._context, i)
} catch (t) {
return St.useDeprecatedSynchronousErrorHandling ? (e.syncErrorValue = t, e.syncErrorThrown = !0) : bt(t), !0
}
return !1
}, Lt.prototype._unsubscribe = function() {
var e = this._parentSubscriber;
this._context = null, this._parentSubscriber = null, e.unsubscribe()
}, Lt);
function Lt(e, t, i, r) {
var n, s = Dt.call(this) || this;
s._parentSubscriber = e;
e = s;
return yt(t) ? n = t : t && (n = t.next, i = t.error, r = t.complete, t !== Tt && (yt((e = Object.create(t)).unsubscribe) && s.add(e.unsubscribe.bind(e)), e.unsubscribe = s.unsubscribe.bind(s))), s._context = e, s._next = n, s._error = i, s._complete = r, s
}
function _t(e, t, i) {
var r = Mt.call(this) || this;
switch (r.syncErrorValue = null, r.syncErrorThrown = !1, r.syncErrorThrowable = !1, r.isStopped = !1, arguments.length) {
case 0:
r.destination = Tt;
break;
case 1:
if (!e) {
r.destination = Tt;
break
}
if ("object" == typeof e) {
e instanceof _t ? (r.syncErrorThrowable = e.syncErrorThrowable, (r.destination = e).add(r)) : (r.syncErrorThrowable = !0, r.destination = new Rt(r, e));
break
}
default:
r.syncErrorThrowable = !0, r.destination = new Rt(r, e, t, i)
}
return r
}
var Nt = "function" == typeof Symbol && Symbol.observable || "@@observable";
function Ft(e) {
return e
}
function Bt() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
return Ut(e)
}
function Ut(t) {
return 0 === t.length ? Ft : 1 === t.length ? t[0] : function(e) {
return t.reduce(function(e, t) {
return t(e)
}, e)
}
}
var $t = (Vt.prototype.lift = function(e) {
var t = new Vt;
return t.source = this, t.operator = e, t
}, Vt.prototype.subscribe = function(e, t, i) {
var r = this.operator,
i = function(e, t, i) {
if (e) {
if (e instanceof Pt) return e;
if (e[xt]) return e[xt]()
}
return e || t || i ? new Pt(e, t, i) : new Pt(Tt)
}(e, t, i);
if (r ? i.add(r.call(i, this.source)) : i.add(this.source || St.useDeprecatedSynchronousErrorHandling && !i.syncErrorThrowable ? this._subscribe(i) : this._trySubscribe(i)), St.useDeprecatedSynchronousErrorHandling && i.syncErrorThrowable && (i.syncErrorThrowable = !1, i.syncErrorThrown)) throw i.syncErrorValue;
return i
}, Vt.prototype._trySubscribe = function(t) {
try {
return this._subscribe(t)
} catch (e) {
St.useDeprecatedSynchronousErrorHandling && (t.syncErrorThrown = !0, t.syncErrorValue = e),
function(e) {
for (; e;) {
var t = e,
i = t.closed,
r = t.destination,
t = t.isStopped;
if (i || t) return;
e = r && r instanceof Pt ? r : null
}
return 1
}(t) ? t.error(e) : console.warn(e)
}
}, Vt.prototype.forEach = function(r, e) {
var n = this;
return new(e = Kt(e))(function(e, t) {
var i = n.subscribe(function(e) {
try {
r(e)
} catch (e) {
t(e), i && i.unsubscribe()
}
}, t, e)
})
}, Vt.prototype._subscribe = function(e) {
var t = this.source;
return t && t.subscribe(e)
}, Vt.prototype[Nt] = function() {
return this
}, Vt.prototype.pipe = function() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
return 0 === e.length ? this : Ut(e)(this)
}, Vt.prototype.toPromise = function(e) {
var r = this;
return new(e = Kt(e))(function(e, t) {
var i;
r.subscribe(function(e) {
return i = e
}, function(e) {
return t(e)
}, function() {
return e(i)
})
})
}, Vt.create = function(e) {
return new Vt(e)
}, Vt);
function Vt(e) {
this._isScalar = !1, e && (this._subscribe = e)
}
function Kt(e) {
if (!(e = e || (St.Promise || Promise))) throw new Error("no Promise impl found");
return e
}
var qt, Ht, jt, Qt, Wt = (ii.prototype = Object.create(Error.prototype), ii),
Gt = (ut(ti, Qt = At), ti.prototype.unsubscribe = function() {
var e, t;
this.closed || (this.closed = !0, e = (t = this.subject).observers, this.subject = null, !e || 0 === e.length || t.isStopped || t.closed || -1 !== (t = e.indexOf(this.subscriber)) && e.splice(t, 1))
}, ti),
zt = (ut(ei, jt = Pt), ei),
Xt = (ut(Zt, Ht = $t), Zt.prototype[xt] = function() {
return new zt(this)
}, Zt.prototype.lift = function(e) {
var t = new Yt(this, this);
return t.operator = e, t
}, Zt.prototype.next = function(e) {
if (this.closed) throw new Wt;
if (!this.isStopped)
for (var t = this.observers, i = t.length, r = t.slice(), n = 0; n < i; n++) r[n].next(e)
}, Zt.prototype.error = function(e) {
if (this.closed) throw new Wt;
this.hasError = !0, this.thrownError = e, this.isStopped = !0;
for (var t = this.observers, i = t.length, r = t.slice(), n = 0; n < i; n++) r[n].error(e);
this.observers.length = 0
}, Zt.prototype.complete = function() {
if (this.closed) throw new Wt;
this.isStopped = !0;
for (var e = this.observers, t = e.length, i = e.slice(), r = 0; r < t; r++) i[r].complete();
this.observers.length = 0
}, Zt.prototype.unsubscribe = function() {
this.isStopped = !0, this.closed = !0, this.observers = null
}, Zt.prototype._trySubscribe = function(e) {
if (this.closed) throw new Wt;
return Ht.prototype._trySubscribe.call(this, e)
}, Zt.prototype._subscribe = function(e) {
if (this.closed) throw new Wt;
return this.hasError ? (e.error(this.thrownError), At.EMPTY) : this.isStopped ? (e.complete(), At.EMPTY) : (this.observers.push(e), new Gt(this, e))
}, Zt.prototype.asObservable = function() {
var e = new $t;
return e.source = this, e
}, Zt.create = function(e, t) {
return new Yt(e, t)
}, Zt),
Yt = (ut(Jt, qt = Xt), Jt.prototype.next = function(e) {
var t = this.destination;
t && t.next && t.next(e)
}, Jt.prototype.error = function(e) {
var t = this.destination;
t && t.error && this.destination.error(e)
}, Jt.prototype.complete = function() {
var e = this.destination;
e && e.complete && this.destination.complete()
}, Jt.prototype._subscribe = function(e) {
return this.source ? this.source.subscribe(e) : At.EMPTY
}, Jt);
function Jt(e, t) {
var i = qt.call(this) || this;
return i.destination = e, i.source = t, i
}
function Zt() {
var e = Ht.call(this) || this;
return e.observers = [], e.closed = !1, e.isStopped = !1, e.hasError = !1, e.thrownError = null, e
}
function ei(e) {
var t = jt.call(this, e) || this;
return t.destination = e, t
}
function ti(e, t) {
var i = Qt.call(this) || this;
return i.subject = e, i.subscriber = t, i.closed = !1, i
}
function ii() {
return Error.call(this), this.message = "object unsubscribed", this.name = "ObjectUnsubscribedError", this
}
function ri() {
return function(e) {
return e.lift(new pi(e))
}
}
var ni, si, ai, oi, li, di, ui, ci, hi, pi = (Li.prototype.call = function(e, t) {
var i = this.connectable;
i._refCount++;
e = new fi(e, i), t = t.subscribe(e);
return e.closed || (e.connection = i.connect()), t
}, Li),
fi = (ut(Ri, hi = Pt), Ri.prototype._unsubscribe = function() {
var e, t = this.connectable;
t ? (this.connectable = null, (e = t._refCount) <= 0 ? this.connection = null : (t._refCount = e - 1, 1 < e ? this.connection = null : (e = this.connection, t = t._connection, this.connection = null, !t || e && t !== e || t.unsubscribe()))) : this.connection = null
}, Ri),
w = (ut(Pi, ci = $t), Pi.prototype._subscribe = function(e) {
return this.getSubject().subscribe(e)
}, Pi.prototype.getSubject = function() {
var e = this._subject;
return e && !e.isStopped || (this._subject = this.subjectFactory()), this._subject
}, Pi.prototype.connect = function() {
var e = this._connection;
return e || (this._isComplete = !1, (e = this._connection = new At).add(this.source.subscribe(new gi(this.getSubject(), this))), e.closed && (this._connection = null, e = At.EMPTY)), e
}, Pi.prototype.refCount = function() {
return ri()(this)
}, Pi),
mi = {
operator: {
value: null
},
_refCount: {
value: 0,
writable: !0
},
_subject: {
value: null,
writable: !0
},
_connection: {
value: null,
writable: !0
},
_subscribe: {
value: (fl = w.prototype)._subscribe
},
_isComplete: {
value: fl._isComplete,
writable: !0
},
getSubject: {
value: fl.getSubject
},
connect: {
value: fl.connect
},
refCount: {
value: fl.refCount
}
},
gi = (ut(xi, ui = zt), xi.prototype._error = function(e) {
this._unsubscribe(), ui.prototype._error.call(this, e)
}, xi.prototype._complete = function() {
this.connectable._isComplete = !0, this._unsubscribe(), ui.prototype._complete.call(this)
}, xi.prototype._unsubscribe = function() {
var e, t = this.connectable;
t && (this.connectable = null, e = t._connection, t._refCount = 0, t._subject = null, t._connection = null, e && e.unsubscribe())
}, xi),
yi = (ut(Mi, di = Xt), Object.defineProperty(Mi.prototype, "value", {
get: function() {
return this.getValue()
},
enumerable: !0,
configurable: !0
}), Mi.prototype._subscribe = function(e) {
var t = di.prototype._subscribe.call(this, e);
return t && !t.closed && e.next(this._value), t
}, Mi.prototype.getValue = function() {
if (this.hasError) throw this.thrownError;
if (this.closed) throw new Wt;
return this._value
}, Mi.prototype.next = function(e) {
di.prototype.next.call(this, this._value = e)
}, Mi),
A = (ut(Di, li = At), Di.prototype.schedule = function(e, t) {
return this
}, ut(Ci, oi = Di), Ci.prototype.schedule = function(e, t) {
if (void 0 === t && (t = 0), this.closed) return this;
this.state = e;
var i = this.id,
e = this.scheduler;
return null != i && (this.id = this.recycleAsyncId(e, i, t)), this.pending = !0, this.delay = t, this.id = this.id || this.requestAsyncId(e, this.id, t), this
}, Ci.prototype.requestAsyncId = function(e, t, i) {
return void 0 === i && (i = 0), setInterval(e.flush.bind(e, this), i)
}, Ci.prototype.recycleAsyncId = function(e, t, i) {
if (null !== (i = void 0 === i ? 0 : i) && this.delay === i && !1 === this.pending) return t;
clearInterval(t)
}, Ci.prototype.execute = function(e, t) {
if (this.closed) return new Error("executing a cancelled action");
this.pending = !1;
t = this._execute(e, t);
if (t) return t;
!1 === this.pending && null != this.id && (this.id = this.recycleAsyncId(this.scheduler, this.id, null))
}, Ci.prototype._execute = function(e, t) {
var i = !1,
r = void 0;
try {
this.work(e)
} catch (e) {
i = !0, r = !!e && e || new Error(e)
}
if (i) return this.unsubscribe(), r
}, Ci.prototype._unsubscribe = function() {
var e = this.id,
t = this.scheduler,
i = t.actions,
r = i.indexOf(this);
this.work = null, this.state = null, this.pending = !1, this.scheduler = null, -1 !== r && i.splice(r, 1), null != e && (this.id = this.recycleAsyncId(t, e, null)), this.delay = null
}, Ci),
vi = (ut(ki, ai = A), ki.prototype.schedule = function(e, t) {
return 0 < (t = void 0 === t ? 0 : t) ? ai.prototype.schedule.call(this, e, t) : (this.delay = t, this.state = e, this.scheduler.flush(this), this)
}, ki.prototype.execute = function(e, t) {
return 0 < t || this.closed ? ai.prototype.execute.call(this, e, t) : this._execute(e, t)
}, ki.prototype.requestAsyncId = function(e, t, i) {
return null !== (i = void 0 === i ? 0 : i) && 0 < i || null === i && 0 < this.delay ? ai.prototype.requestAsyncId.call(this, e, t, i) : e.flush(this)
}, ki),
Si = (Oi.prototype.schedule = function(e, t, i) {
return void 0 === t && (t = 0), new this.SchedulerAction(this, e).schedule(i, t)
}, Oi.now = function() {
return Date.now()
}, Oi),
bi = (ut(Ai, si = Si), Ai.prototype.schedule = function(e, t, i) {
return void 0 === t && (t = 0), Ai.delegate && Ai.delegate !== this ? Ai.delegate.schedule(e, t, i) : si.prototype.schedule.call(this, e, t, i)
}, Ai.prototype.flush = function(e) {
var t, i = this.actions;
if (this.active) i.push(e);
else {
this.active = !0;
do {
if (t = e.execute(e.state, e.delay)) break
} while (e = i.shift());
if (this.active = !1, t) {
for (; e = i.shift();) e.unsubscribe();
throw t
}
}
}, Ai),
Ti = (ut(wi, ni = bi), new wi(vi)),
Ei = Ti,
Ii = new $t(function(e) {
return e.complete()
});
function wi() {
return null !== ni && ni.apply(this, arguments) || this
}
function Ai(e, t) {
void 0 === t && (t = Si.now);
var i = si.call(this, e, function() {
return Ai.delegate && Ai.delegate !== i ? Ai.delegate.now() : t()
}) || this;
return i.actions = [], i.active = !1, i.scheduled = void 0, i
}
function Oi(e, t) {
void 0 === t && (t = Oi.now), this.SchedulerAction = e, this.now = t
}
function ki(e, t) {
var i = ai.call(this, e, t) || this;
return i.scheduler = e, i.work = t, i
}
function Ci(e, t) {
var i = oi.call(this, e, t) || this;
return i.scheduler = e, i.work = t, i.pending = !1, i
}
function Di(e, t) {
return li.call(this) || this
}
function Mi(e) {
var t = di.call(this) || this;
return t._value = e, t
}
function xi(e, t) {
e = ui.call(this, e) || this;
return e.connectable = t, e
}
function Pi(e, t) {
var i = ci.call(this) || this;
return i.source = e, i.subjectFactory = t, i._refCount = 0, i._isComplete = !1, i
}
function Ri(e, t) {
e = hi.call(this, e) || this;
return e.connectable = t, e
}
function Li(e) {
this.connectable = e
}
function _i(e) {
return e ? (t = e, new $t(function(e) {
return t.schedule(function() {
return e.complete()
})
})) : Ii;
var t
}
function Ni(e) {
return e && "function" == typeof e.schedule
}
var Fi = function(r) {
return function(e) {
for (var t = 0, i = r.length; t < i && !e.closed; t++) e.next(r[t]);
e.complete()
}
};
function Bi(r, n) {
return new $t(function(e) {
var t = new At,
i = 0;
return t.add(n.schedule(function() {
i !== r.length ? (e.next(r[i++]), e.closed || t.add(this.schedule())) : e.complete()
})), t
})
}
function Ui(e, t) {
return t ? Bi(e, t) : new $t(Fi(e))
}
function $i() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
var i = e[e.length - 1];
return Ni(i) ? (e.pop(), Bi(e, i)) : Ui(e)
}
function Vi(t, i) {
return new $t(i ? function(e) {
return i.schedule(Ki, 0, {
error: t,
subscriber: e
})
} : function(e) {
return e.error(t)
})
}
function Ki(e) {
var t = e.error;
e.subscriber.error(t)
}
var qi = (Hi.prototype.observe = function(e) {
switch (this.kind) {
case "N":
return e.next && e.next(this.value);
case "E":
return e.error && e.error(this.error);
case "C":
return e.complete && e.complete()
}
}, Hi.prototype.do = function(e, t, i) {
switch (this.kind) {
case "N":
return e && e(this.value);
case "E":
return t && t(this.error);
case "C":
return i && i()
}
}, Hi.prototype.accept = function(e, t, i) {
return e && "function" == typeof e.next ? this.observe(e) : this.do(e, t, i)
}, Hi.prototype.toObservable = function() {
switch (this.kind) {
case "N":
return $i(this.value);
case "E":
return Vi(this.error);
case "C":
return _i()
}
throw new Error("unexpected notification kind value")
}, Hi.createNext = function(e) {
return void 0 !== e ? new Hi("N", e) : Hi.undefinedValueNotification
}, Hi.createError = function(e) {
return new Hi("E", void 0, e)
}, Hi.createComplete = function() {
return Hi.completeNotification
}, Hi.completeNotification = new Hi("C"), Hi.undefinedValueNotification = new Hi("N", void 0), Hi);
function Hi(e, t, i) {
this.kind = e, this.value = t, this.error = i, this.hasValue = "N" === e
}
function ji(t, i) {
return void 0 === i && (i = 0),
function(e) {
return e.lift(new zi(t, i))
}
}
var Qi, Wi, Gi, zi = (ar.prototype.call = function(e, t) {
return t.subscribe(new Xi(e, this.scheduler, this.delay))
}, ar),
Xi = (ut(sr, Gi = Pt), sr.dispatch = function(e) {
var t = e.notification,
e = e.destination;
t.observe(e), this.unsubscribe()
}, sr.prototype.scheduleMessage = function(e) {
this.destination.add(this.scheduler.schedule(sr.dispatch, this.delay, new Yi(e, this.destination)))
}, sr.prototype._next = function(e) {
this.scheduleMessage(qi.createNext(e))
}, sr.prototype._error = function(e) {
this.scheduleMessage(qi.createError(e)), this.unsubscribe()
}, sr.prototype._complete = function() {
this.scheduleMessage(qi.createComplete()), this.unsubscribe()
}, sr),
Yi = function(e, t) {
this.notification = e, this.destination = t
},
Ji = (ut(nr, Wi = Xt), nr.prototype.nextInfiniteTimeWindow = function(e) {
var t;
this.isStopped || ((t = this._events).push(e), t.length > this._bufferSize && t.shift()), Wi.prototype.next.call(this, e)
}, nr.prototype.nextTimeWindow = function(e) {
this.isStopped || (this._events.push(new Zi(this._getNow(), e)), this._trimBufferThenGetEvents()), Wi.prototype.next.call(this, e)
}, nr.prototype._subscribe = function(e) {
var t, i = this._infiniteTimeWindow,
r = i ? this._events : this._trimBufferThenGetEvents(),
n = this.scheduler,
s = r.length;
if (this.closed) throw new Wt;
if (t = this.isStopped || this.hasError ? At.EMPTY : (this.observers.push(e), new Gt(this, e)), n && e.add(e = new Xi(e, n)), i)
for (var a = 0; a < s && !e.closed; a++) e.next(r[a]);
else
for (a = 0; a < s && !e.closed; a++) e.next(r[a].value);
return this.hasError ? e.error(this.thrownError) : this.isStopped && e.complete(), t
}, nr.prototype._getNow = function() {
return (this.scheduler || Ei).now()
}, nr.prototype._trimBufferThenGetEvents = function() {
for (var e = this._getNow(), t = this._bufferSize, i = this._windowTime, r = this._events, n = r.length, s = 0; s < n && !(e - r[s].time < i);) s++;
return 0 < (s = t < n ? Math.max(s, n - t) : s) && r.splice(0, s), r
}, nr),
Zi = function(e, t) {
this.time = e, this.value = t
},
er = (ut(rr, Qi = Xt), rr.prototype._subscribe = function(e) {
return this.hasError ? (e.error(this.thrownError), At.EMPTY) : this.hasCompleted && this.hasNext ? (e.next(this.value), e.complete(), At.EMPTY) : Qi.prototype._subscribe.call(this, e)
}, rr.prototype.next = function(e) {
this.hasCompleted || (this.value = e, this.hasNext = !0)
}, rr.prototype.error = function(e) {
this.hasCompleted || Qi.prototype.error.call(this, e)
}, rr.prototype.complete = function() {
this.hasCompleted = !0, this.hasNext && Qi.prototype.next.call(this, this.value), Qi.prototype.complete.call(this)
}, rr),
tr = new bi(A),
ir = tr;
function rr() {
var e = null !== Qi && Qi.apply(this, arguments) || this;
return e.value = null, e.hasNext = !1, e.hasCompleted = !1, e
}
function nr(e, t, i) {
void 0 === e && (e = Number.POSITIVE_INFINITY), void 0 === t && (t = Number.POSITIVE_INFINITY);
var r = Wi.call(this) || this;
return r.scheduler = i, r._events = [], r._infiniteTimeWindow = !1, r._bufferSize = e < 1 ? 1 : e, r._windowTime = t < 1 ? 1 : t, t === Number.POSITIVE_INFINITY ? (r._infiniteTimeWindow = !0, r.next = r.nextInfiniteTimeWindow) : r.next = r.nextTimeWindow, r
}
function sr(e, t, i) {
void 0 === i && (i = 0);
e = Gi.call(this, e) || this;
return e.scheduler = t, e.delay = i, e
}
function ar(e, t) {
void 0 === t && (t = 0), this.scheduler = e, this.delay = t
}
function or() {}
var lr = (cr.prototype = Object.create(Error.prototype), cr),
dr = (ur.prototype = Object.create(Error.prototype), ur);
function ur() {
return Error.call(this), this.message = "Timeout has occurred", this.name = "TimeoutError", this
}
function cr() {
return Error.call(this), this.message = "argument out of range", this.name = "ArgumentOutOfRangeError", this
}
function hr(t, i) {
return function(e) {
if ("function" != typeof t) throw new TypeError("argument is not a function. Are you looking for `mapTo()`?");
return e.lift(new gr(t, i))
}
}
var pr, fr, mr, gr = (Ir.prototype.call = function(e, t) {
return t.subscribe(new yr(e, this.project, this.thisArg))
}, Ir),
yr = (ut(Er, mr = Pt), Er.prototype._next = function(e) {
var t;
try {
t = this.project.call(this.thisArg, e, this.count++)
} catch (e) {
return void this.destination.error(e)
}
this.destination.next(t)
}, Er),
vr = (ut(Tr, fr = Pt), Tr.prototype.notifyNext = function(e, t, i, r, n) {
this.destination.next(t)
}, Tr.prototype.notifyError = function(e, t) {
this.destination.error(e)
}, Tr.prototype.notifyComplete = function(e) {
this.destination.complete()
}, Tr),
Sr = (ut(br, pr = Pt), br.prototype._next = function(e) {
this.parent.notifyNext(this.outerValue, e, this.outerIndex, this.index++, this)
}, br.prototype._error = function(e) {
this.parent.notifyError(e, this), this.unsubscribe()
}, br.prototype._complete = function() {
this.parent.notifyComplete(this), this.unsubscribe()
}, br);
function br(e, t, i) {
var r = pr.call(this) || this;
return r.parent = e, r.outerValue = t, r.outerIndex = i, r.index = 0, r
}
function Tr() {
return null !== fr && fr.apply(this, arguments) || this
}
function Er(e, t, i) {
e = mr.call(this, e) || this;
return e.project = t, e.count = 0, e.thisArg = i || e, e
}
function Ir(e, t) {
this.project = e, this.thisArg = t
}
var wr = "function" == typeof Symbol && Symbol.iterator ? Symbol.iterator : "@@iterator",
Ar = function(e) {
return e && "number" == typeof e.length && "function" != typeof e
};
function Or(e) {
return e && "function" != typeof e.subscribe && "function" == typeof e.then
}
var kr = function(e) {
if (e && "function" == typeof e[Nt]) return n = e,
function(e) {
var t = n[Nt]();
if ("function" != typeof t.subscribe) throw new TypeError("Provided object does not correctly implement Symbol.observable");
return t.subscribe(e)
};
if (Ar(e)) return Fi(e);
if (Or(e)) return i = e,
function(t) {
return i.then(function(e) {
t.closed || (t.next(e), t.complete())
}, function(e) {
return t.error(e)
}).then(null, bt), t
};
if (e && "function" == typeof e[wr]) return r = e,
function(t) {
for (var e = r[wr]();;) {
var i = void 0;
try {
i = e.next()
} catch (e) {
return t.error(e), t
}
if (i.done) {
t.complete();
break
}
if (t.next(i.value), t.closed) break
}
return "function" == typeof e.return && t.add(function() {
e.return && e.return()
}), t
};
var r, i, n, e = It(e) ? "an invalid object" : "'" + e + "'";
throw new TypeError("You provided " + e + " where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.")
};
function Cr(e, t, i, r, n) {
if (!(n = void 0 === n ? new Sr(e, i, r) : n).closed) return t instanceof $t ? t.subscribe(n) : kr(t)(n)
}
var Dr = {};
function Mr() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
var i = void 0,
r = void 0;
return Ni(e[e.length - 1]) && (r = e.pop()), "function" == typeof e[e.length - 1] && (i = e.pop()), Ui(e = 1 === e.length && Et(e[0]) ? e[0] : e, r).lift(new Pr(i))
}
var xr, Pr = (_r.prototype.call = function(e, t) {
return t.subscribe(new Rr(e, this.resultSelector))
}, _r),
Rr = (ut(Lr, xr = vr), Lr.prototype._next = function(e) {
this.values.push(Dr), this.observables.push(e)
}, Lr.prototype._complete = function() {
var e = this.observables,
t = e.length;
if (0 === t) this.destination.complete();
else {
this.active = t, this.toRespond = t;
for (var i = 0; i < t; i++) {
var r = e[i];
this.add(Cr(this, r, void 0, i))
}
}
}, Lr.prototype.notifyComplete = function(e) {
0 == --this.active && this.destination.complete()
}, Lr.prototype.notifyNext = function(e, t, i) {
var r = this.values,
n = r[i],
n = this.toRespond ? n === Dr ? --this.toRespond : this.toRespond : 0;
r[i] = t, 0 === n && (this.resultSelector ? this._tryResultSelector(r) : this.destination.next(r.slice()))
}, Lr.prototype._tryResultSelector = function(e) {
var t;
try {
t = this.resultSelector.apply(this, e)
} catch (e) {
return void this.destination.error(e)
}
this.destination.next(t)
}, Lr);
function Lr(e, t) {
e = xr.call(this, e) || this;
return e.resultSelector = t, e.active = 0, e.values = [], e.observables = [], e
}
function _r(e) {
this.resultSelector = e
}
function Nr(e, t) {
if (null != e) {
if (e && "function" == typeof e[Nt]) return s = e, a = t, new $t(function(t) {
var i = new At;
return i.add(a.schedule(function() {
var e = s[Nt]();
i.add(e.subscribe({
next: function(e) {
i.add(a.schedule(function() {
return t.next(e)
}))
},
error: function(e) {
i.add(a.schedule(function() {
return t.error(e)
}))
},
complete: function() {
i.add(a.schedule(function() {
return t.complete()
}))
}
}))
})), i
});
if (Or(e)) return r = e, n = t, new $t(function(t) {
var i = new At;
return i.add(n.schedule(function() {
return r.then(function(e) {
i.add(n.schedule(function() {
t.next(e), i.add(n.schedule(function() {
return t.complete()
}))
}))
}, function(e) {
i.add(n.schedule(function() {
return t.error(e)
}))
})
})), i
});
if (Ar(e)) return Bi(e, t);
if (e && "function" == typeof e[wr] || "string" == typeof e) return function(t, i) {
if (!t) throw new Error("Iterable cannot be null");
return new $t(function(r) {
var n, e = new At;
return e.add(function() {
n && "function" == typeof n.return && n.return()
}), e.add(i.schedule(function() {
n = t[wr](), e.add(i.schedule(function() {
if (!r.closed) {
try {
var e = n.next(),
t = e.value,
i = e.done
} catch (t) {
return void r.error(t)
}
i ? r.complete() : (r.next(t), this.schedule())
}
}))
})), e
})
}(e, t)
}
var r, n, s, a;
throw new TypeError((null !== e && typeof e || e) + " is not observable")
}
function Fr(e, t) {
return t ? Nr(e, t) : e instanceof $t ? e : new $t(kr(e))
}
var Br, Ur, $r = (ut(qr, Ur = Pt), qr.prototype._next = function(e) {
this.parent.notifyNext(e)
}, qr.prototype._error = function(e) {
this.parent.notifyError(e), this.unsubscribe()
}, qr.prototype._complete = function() {
this.parent.notifyComplete(), this.unsubscribe()
}, qr),
Vr = (ut(Kr, Br = Pt), Kr.prototype.notifyNext = function(e) {
this.destination.next(e)
}, Kr.prototype.notifyError = function(e) {
this.destination.error(e)
}, Kr.prototype.notifyComplete = function() {
this.destination.complete()
}, Kr);
function Kr() {
return null !== Br && Br.apply(this, arguments) || this
}
function qr(e) {
var t = Ur.call(this) || this;
return t.parent = e, t
}
function Hr(e, t) {
if (!t.closed) return e instanceof $t ? e.subscribe(t) : kr(e)(t)
}
function jr(t, n, i) {
return void 0 === i && (i = Number.POSITIVE_INFINITY), "function" == typeof n ? function(e) {
return e.pipe(jr(function(i, r) {
return Fr(t(i, r)).pipe(hr(function(e, t) {
return n(i, e, r, t)
}))
}, i))
} : ("number" == typeof n && (i = n), function(e) {
return e.lift(new Wr(t, i))
})
}
var Qr, Wr = (Xr.prototype.call = function(e, t) {
return t.subscribe(new Gr(e, this.project, this.concurrent))
}, Xr),
Gr = (ut(zr, Qr = Vr), zr.prototype._next = function(e) {
this.active < this.concurrent ? this._tryNext(e) : this.buffer.push(e)
}, zr.prototype._tryNext = function(e) {
var t, i = this.index++;
try {
t = this.project(e, i)
} catch (e) {
return void this.destination.error(e)
}
this.active++, this._innerSub(t)
}, zr.prototype._innerSub = function(e) {
var t = new $r(this),
i = this.destination;
i.add(t);
e = Hr(e, t);
e !== t && i.add(e)
}, zr.prototype._complete = function() {
this.hasCompleted = !0, 0 === this.active && 0 === this.buffer.length && this.destination.complete(), this.unsubscribe()
}, zr.prototype.notifyNext = function(e) {
this.destination.next(e)
}, zr.prototype.notifyComplete = function() {
var e = this.buffer;
this.active--, 0 < e.length ? this._next(e.shift()) : 0 === this.active && this.hasCompleted && this.destination.complete()
}, zr);
function zr(e, t, i) {
void 0 === i && (i = Number.POSITIVE_INFINITY);
e = Qr.call(this, e) || this;
return e.project = t, e.concurrent = i, e.hasCompleted = !1, e.buffer = [], e.active = 0, e.index = 0, e
}
function Xr(e, t) {
void 0 === t && (t = Number.POSITIVE_INFINITY), this.project = e, this.concurrent = t
}
function Yr(e) {
return jr(Ft, e = void 0 === e ? Number.POSITIVE_INFINITY : e)
}
function Jr() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
return Yr(1)($i.apply(void 0, e))
}
function Zr(i) {
return new $t(function(t) {
var e;
try {
e = i()
} catch (e) {
return void t.error(e)
}
return (e ? Fr(e) : _i()).subscribe(t)
})
}
function en() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
if (1 === e.length) {
var i = e[0];
if (Et(i)) return tn(i, null);
if (It(i) && Object.getPrototypeOf(i) === Object.prototype) {
var r = Object.keys(i);
return tn(r.map(function(e) {
return i[e]
}), r)
}
}
if ("function" != typeof e[e.length - 1]) return tn(e, null);
var n = e.pop();
return tn(e = 1 === e.length && Et(e[0]) ? e[0] : e, null).pipe(hr(function(e) {
return n.apply(void 0, e)
}))
}
function tn(l, d) {
return new $t(function(r) {
var n = l.length;
if (0 !== n)
for (var s = new Array(n), a = 0, o = 0, e = 0; e < n; e++) ! function(t) {
var e = Fr(l[t]),
i = !1;
r.add(e.subscribe({
next: function(e) {
i || (i = !0, o++), s[t] = e
},
error: function(e) {
return r.error(e)
},
complete: function() {
++a !== n && i || (o === n && r.next(d ? d.reduce(function(e, t, i) {
return e[t] = s[i], e
}, {}) : s), r.complete())
}
}))
}(e);
else r.complete()
})
}
function rn(e, i, r, t) {
return yt(r) && (t = r, r = void 0), t ? rn(e, i, r).pipe(hr(function(e) {
return Et(e) ? t.apply(void 0, e) : t(e)
})) : new $t(function(t) {
! function e(t, i, r, n, s) {
var a;
if (function(e) {
return e && "function" == typeof e.addEventListener && "function" == typeof e.removeEventListener
}(t)) {
var o = t;
t.addEventListener(i, r, s), a = function() {
return o.removeEventListener(i, r, s)
}
} else if (function(e) {
return e && "function" == typeof e.on && "function" == typeof e.off
}(t)) {
var l = t;
t.on(i, r), a = function() {
return l.off(i, r)
}
} else if (function(e) {
return e && "function" == typeof e.addListener && "function" == typeof e.removeListener
}(t)) {
var d = t;
t.addListener(i, r), a = function() {
return d.removeListener(i, r)
}
} else {
if (!t || !t.length) throw new TypeError("Invalid event target");
for (var u = 0, c = t.length; u < c; u++) e(t[u], i, r, n, s)
}
n.add(a)
}(e, i, function(e) {
1 < arguments.length ? t.next(Array.prototype.slice.call(arguments)) : t.next(e)
}, t, r)
})
}
function nn(e, t, i) {
return void 0 === t && (t = Ii), void 0 === i && (i = Ii), Zr(function() {
return e() ? t : i
})
}
function sn(e) {
return !Et(e) && 0 <= e - parseFloat(e) + 1
}
function an() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
var i = Number.POSITIVE_INFINITY,
r = null,
n = e[e.length - 1];
return Ni(n) ? (r = e.pop(), 1 < e.length && "number" == typeof e[e.length - 1] && (i = e.pop())) : "number" == typeof n && (i = e.pop()), null === r && 1 === e.length && e[0] instanceof $t ? e[0] : Yr(i)(Ui(e, r))
}
var on = new $t(or);
function ln(t, i) {
return function(e) {
return e.lift(new un(t, i))
}
}
var dn, un = (pn.prototype.call = function(e, t) {
return t.subscribe(new cn(e, this.predicate, this.thisArg))
}, pn),
cn = (ut(hn, dn = Pt), hn.prototype._next = function(e) {
var t;
try {
t = this.predicate.call(this.thisArg, e, this.count++)
} catch (e) {
return void this.destination.error(e)
}
t && this.destination.next(e)
}, hn);
function hn(e, t, i) {
e = dn.call(this, e) || this;
return e.predicate = t, e.thisArg = i, e.count = 0, e
}
function pn(e, t) {
this.predicate = e, this.thisArg = t
}
function fn() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
if (1 === e.length) {
if (!Et(e[0])) return e[0];
e = e[0]
}
return Ui(e, void 0).lift(new gn)
}
var mn, gn = (Sn.prototype.call = function(e, t) {
return t.subscribe(new yn(e))
}, Sn),
yn = (ut(vn, mn = vr), vn.prototype._next = function(e) {
this.observables.push(e)
}, vn.prototype._complete = function() {
var e = this.observables,
t = e.length;
if (0 === t) this.destination.complete();
else {
for (var i = 0; i < t && !this.hasFirst; i++) {
var r = Cr(this, e[i], void 0, i);
this.subscriptions && this.subscriptions.push(r), this.add(r)
}
this.observables = null
}
}, vn.prototype.notifyNext = function(e, t, i) {
if (!this.hasFirst) {
this.hasFirst = !0;
for (var r, n = 0; n < this.subscriptions.length; n++) n !== i && ((r = this.subscriptions[n]).unsubscribe(), this.remove(r));
this.subscriptions = null
}
this.destination.next(t)
}, vn);
function vn(e) {
e = mn.call(this, e) || this;
return e.hasFirst = !1, e.observables = [], e.subscriptions = [], e
}
function Sn() {}
function bn(i, e, r) {
void 0 === i && (i = 0);
var n = -1;
return sn(e) ? n = Number(e) < 1 ? 1 : Number(e) : Ni(e) && (r = e), Ni(r) || (r = ir), new $t(function(e) {
var t = sn(i) ? i : +i - r.now();
return r.schedule(Tn, t, {
index: 0,
period: n,
subscriber: e
})
})
}
function Tn(e) {
var t = e.index,
i = e.period,
r = e.subscriber;
if (r.next(t), !r.closed) {
if (-1 === i) return r.complete();
e.index = t + 1, this.schedule(e, i)
}
}
function En() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
var i = e[e.length - 1];
return "function" == typeof i && e.pop(), Ui(e, void 0).lift(new An(i))
}
var In, wn, An = (Ln.prototype.call = function(e, t) {
return t.subscribe(new On(e, this.resultSelector))
}, Ln),
On = (ut(Rn, wn = Pt), Rn.prototype._next = function(e) {
var t = this.iterators;
Et(e) ? t.push(new Cn(e)) : "function" == typeof e[wr] ? t.push(new kn(e[wr]())) : t.push(new Dn(this.destination, this, e))
}, Rn.prototype._complete = function() {
var e = this.iterators,
t = e.length;
if (this.unsubscribe(), 0 !== t) {
this.active = t;
for (var i = 0; i < t; i++) {
var r = e[i];
r.stillUnsubscribed ? this.destination.add(r.subscribe()) : this.active--
}
} else this.destination.complete()
}, Rn.prototype.notifyInactive = function() {
this.active--, 0 === this.active && this.destination.complete()
}, Rn.prototype.checkIterators = function() {
for (var e = this.iterators, t = e.length, i = this.destination, r = 0; r < t; r++)
if ("function" == typeof(a = e[r]).hasValue && !a.hasValue()) return;
for (var n = !1, s = [], r = 0; r < t; r++) {
var a, o = (a = e[r]).next();
if (a.hasCompleted() && (n = !0), o.done) return void i.complete();
s.push(o.value)
}
this.resultSelector ? this._tryresultSelector(s) : i.next(s), n && i.complete()
}, Rn.prototype._tryresultSelector = function(e) {
var t;
try {
t = this.resultSelector.apply(this, e)
} catch (e) {
return void this.destination.error(e)
}
this.destination.next(t)
}, Rn),
kn = (Pn.prototype.hasValue = function() {
return !0
}, Pn.prototype.next = function() {
var e = this.nextResult;
return this.nextResult = this.iterator.next(), e
}, Pn.prototype.hasCompleted = function() {
var e = this.nextResult;
return Boolean(e && e.done)
}, Pn),
Cn = (xn.prototype[wr] = function() {
return this
}, xn.prototype.next = function(e) {
var t = this.index++,
i = this.array;
return t < this.length ? {
value: i[t],
done: !1
} : {
value: null,
done: !0
}
}, xn.prototype.hasValue = function() {
return this.array.length > this.index
}, xn.prototype.hasCompleted = function() {
return this.array.length === this.index
}, xn),
Dn = (ut(Mn, In = Vr), Mn.prototype[wr] = function() {
return this
}, Mn.prototype.next = function() {
var e = this.buffer;
return 0 === e.length && this.isComplete ? {
value: null,
done: !0
} : {
value: e.shift(),
done: !1
}
}, Mn.prototype.hasValue = function() {
return 0 < this.buffer.length
}, Mn.prototype.hasCompleted = function() {
return 0 === this.buffer.length && this.isComplete
}, Mn.prototype.notifyComplete = function() {
0 < this.buffer.length ? (this.isComplete = !0, this.parent.notifyInactive()) : this.destination.complete()
}, Mn.prototype.notifyNext = function(e) {
this.buffer.push(e), this.parent.checkIterators()
}, Mn.prototype.subscribe = function() {
return Hr(this.observable, new $r(this))
}, Mn);
function Mn(e, t, i) {
e = In.call(this, e) || this;
return e.parent = t, e.observable = i, e.stillUnsubscribed = !0, e.buffer = [], e.isComplete = !1, e
}
function xn(e) {
this.array = e, this.index = 0, this.length = 0, this.length = e.length
}
function Pn(e) {
this.iterator = e, this.nextResult = e.next()
}
function Rn(e, t, i) {
e = wn.call(this, e) || this;
return e.resultSelector = t, e.iterators = [], e.active = 0, e.resultSelector = "function" == typeof t ? t : void 0, e
}
function Ln(e) {
this.resultSelector = e
}
var _n, Nn = (Un.prototype.call = function(e, t) {
return t.subscribe(new Fn(e, this.durationSelector))
}, Un),
Fn = (ut(Bn, _n = Vr), Bn.prototype._next = function(e) {
if (this.value = e, this.hasValue = !0, !this.throttled) {
var t = void 0;
try {
t = (0, this.durationSelector)(e)
} catch (e) {
return this.destination.error(e)
}
t = Hr(t, new $r(this));
!t || t.closed ? this.clearThrottle() : this.add(this.throttled = t)
}
}, Bn.prototype.clearThrottle = function() {
var e = this.value,
t = this.hasValue,
i = this.throttled;
i && (this.remove(i), this.throttled = void 0, i.unsubscribe()), t && (this.value = void 0, this.hasValue = !1, this.destination.next(e))
}, Bn.prototype.notifyNext = function() {
this.clearThrottle()
}, Bn.prototype.notifyComplete = function() {
this.clearThrottle()
}, Bn);
function Bn(e, t) {
e = _n.call(this, e) || this;
return e.durationSelector = t, e.hasValue = !1, e
}
function Un(e) {
this.durationSelector = e
}
function $n(e, t) {
return void 0 === t && (t = ir), i = function() {
return bn(e, t)
},
function(e) {
return e.lift(new Nn(i))
};
var i
}
function Vn(i) {
return function(e) {
var t = new qn(i),
e = e.lift(t);
return t.caught = e
}
}
var Kn, qn = (Qn.prototype.call = function(e, t) {
return t.subscribe(new Hn(e, this.selector, this.caught))
}, Qn),
Hn = (ut(jn, Kn = Vr), jn.prototype.error = function(e) {
if (!this.isStopped) {
var t = void 0;
try {
t = this.selector(e, this.caught)
} catch (e) {
return void Kn.prototype.error.call(this, e)
}
this._unsubscribeAndRecycle();
var i = new $r(this);
this.add(i);
t = Hr(t, i);
t !== i && this.add(t)
}
}, jn);
function jn(e, t, i) {
e = Kn.call(this, e) || this;
return e.selector = t, e.caught = i, e
}
function Qn(e) {
this.selector = e
}
function Wn(e, t) {
return jr(e, t, 1)
}
function Gn(t, i) {
return void 0 === i && (i = ir),
function(e) {
return e.lift(new Xn(t, i))
}
}
var zn, Xn = (Zn.prototype.call = function(e, t) {
return t.subscribe(new Yn(e, this.dueTime, this.scheduler))
}, Zn),
Yn = (ut(Jn, zn = Pt), Jn.prototype._next = function(e) {
this.clearDebounce(), this.lastValue = e, this.hasValue = !0, this.add(this.debouncedSubscription = this.scheduler.schedule(es, this.dueTime, this))
}, Jn.prototype._complete = function() {
this.debouncedNext(), this.destination.complete()
}, Jn.prototype.debouncedNext = function() {
var e;
this.clearDebounce(), this.hasValue && (e = this.lastValue, this.lastValue = null, this.hasValue = !1, this.destination.next(e))
}, Jn.prototype.clearDebounce = function() {
var e = this.debouncedSubscription;
null !== e && (this.remove(e), e.unsubscribe(), this.debouncedSubscription = null)
}, Jn);
function Jn(e, t, i) {
e = zn.call(this, e) || this;
return e.dueTime = t, e.scheduler = i, e.debouncedSubscription = null, e.lastValue = null, e.hasValue = !1, e
}
function Zn(e, t) {
this.dueTime = e, this.scheduler = t
}
function es(e) {
e.debouncedNext()
}
var ts, is = (ss.prototype.call = function(e, t) {
return t.subscribe(new rs(e, this.defaultValue))
}, ss),
rs = (ut(ns, ts = Pt), ns.prototype._next = function(e) {
this.isEmpty = !1, this.destination.next(e)
}, ns.prototype._complete = function() {
this.isEmpty && this.destination.next(this.defaultValue), this.destination.complete()
}, ns);
function ns(e, t) {
e = ts.call(this, e) || this;
return e.defaultValue = t, e.isEmpty = !0, e
}
function ss(e) {
this.defaultValue = e
}
function as(e) {
return e instanceof Date && !isNaN(+e)
}
var os, ls = (hs.prototype.call = function(e, t) {
return t.subscribe(new ds(e, this.delay, this.scheduler))
}, hs),
ds = (ut(cs, os = Pt), cs.dispatch = function(e) {
for (var t, i = e.source, r = i.queue, n = e.scheduler, s = e.destination; 0 < r.length && r[0].time - n.now() <= 0;) r.shift().notification.observe(s);
0 < r.length ? (t = Math.max(0, r[0].time - n.now()), this.schedule(e, t)) : (this.unsubscribe(), i.active = !1)
}, cs.prototype._schedule = function(e) {
this.active = !0, this.destination.add(e.schedule(cs.dispatch, this.delay, {
source: this,
destination: this.destination,
scheduler: e
}))
}, cs.prototype.scheduleNotification = function(e) {
var t;
!0 !== this.errored && (t = this.scheduler, e = new us(t.now() + this.delay, e), this.queue.push(e), !1 === this.active && this._schedule(t))
}, cs.prototype._next = function(e) {
this.scheduleNotification(qi.createNext(e))
}, cs.prototype._error = function(e) {
this.errored = !0, this.queue = [], this.destination.error(e), this.unsubscribe()
}, cs.prototype._complete = function() {
this.scheduleNotification(qi.createComplete()), this.unsubscribe()
}, cs),
us = function(e, t) {
this.time = e, this.notification = t
};
function cs(e, t, i) {
e = os.call(this, e) || this;
return e.delay = t, e.scheduler = i, e.queue = [], e.active = !1, e.errored = !1, e
}
function hs(e, t) {
this.delay = e, this.scheduler = t
}
var ps, fs, ms, gs = (Es.prototype.call = function(e, t) {
return t.subscribe(new ys(e, this.delayDurationSelector))
}, Es),
ys = (ut(Ts, ms = vr), Ts.prototype.notifyNext = function(e, t, i, r, n) {
this.destination.next(e), this.removeSubscription(n), this.tryComplete()
}, Ts.prototype.notifyError = function(e, t) {
this._error(e)
}, Ts.prototype.notifyComplete = function(e) {
e = this.removeSubscription(e);
e && this.destination.next(e), this.tryComplete()
}, Ts.prototype._next = function(e) {
var t = this.index++;
try {
var i = this.delayDurationSelector(e, t);
i && this.tryDelay(i, e)
} catch (e) {
this.destination.error(e)
}
}, Ts.prototype._complete = function() {
this.completed = !0, this.tryComplete(), this.unsubscribe()
}, Ts.prototype.removeSubscription = function(e) {
e.unsubscribe();
var t = this.delayNotifierSubscriptions.indexOf(e);
return -1 !== t && this.delayNotifierSubscriptions.splice(t, 1), e.outerValue
}, Ts.prototype.tryDelay = function(e, t) {
t = Cr(this, e, t);
t && !t.closed && (this.destination.add(t), this.delayNotifierSubscriptions.push(t))
}, Ts.prototype.tryComplete = function() {
this.completed && 0 === this.delayNotifierSubscriptions.length && this.destination.complete()
}, Ts),
vs = (ut(bs, fs = $t), bs.prototype._subscribe = function(e) {
this.subscriptionDelay.subscribe(new vs(e, this.source))
}, ut(Ss, ps = Pt), Ss.prototype._next = function(e) {
this.subscribeToSource()
}, Ss.prototype._error = function(e) {
this.unsubscribe(), this.parent.error(e)
}, Ss.prototype._complete = function() {
this.unsubscribe(), this.subscribeToSource()
}, Ss.prototype.subscribeToSource = function() {
this.sourceSubscribed || (this.sourceSubscribed = !0, this.unsubscribe(), this.source.subscribe(this.parent))
}, Ss);
function Ss(e, t) {
var i = ps.call(this) || this;
return i.parent = e, i.source = t, i.sourceSubscribed = !1, i
}
function bs(e, t) {
var i = fs.call(this) || this;
return i.source = e, i.subscriptionDelay = t, i
}
function Ts(e, t) {
e = ms.call(this, e) || this;
return e.delayDurationSelector = t, e.completed = !1, e.delayNotifierSubscriptions = [], e.index = 0, e
}
function Es(e) {
this.delayDurationSelector = e
}
function Is(t, i) {
return function(e) {
return e.lift(new As(t, i))
}
}
var ws, As = (Cs.prototype.call = function(e, t) {
return t.subscribe(new Os(e, this.compare, this.keySelector))
}, Cs),
Os = (ut(ks, ws = Pt), ks.prototype.compare = function(e, t) {
return e === t
}, ks.prototype._next = function(e) {
try {
var t = this.keySelector,
i = t ? t(e) : e
} catch (e) {
return this.destination.error(e)
}
t = !1;
if (this.hasKey) try {
t = (0, this.compare)(this.key, i)
} catch (e) {
return this.destination.error(e)
} else this.hasKey = !0;
t || (this.key = i, this.destination.next(e))
}, ks);
function ks(e, t, i) {
e = ws.call(this, e) || this;
return e.keySelector = i, e.hasKey = !1, "function" == typeof t && (e.compare = t), e
}
function Cs(e, t) {
this.compare = e, this.keySelector = t
}
function Ds(t) {
return function(e) {
return 0 === t ? _i() : e.lift(new xs(t))
}
}
var Ms, xs = (Ls.prototype.call = function(e, t) {
return t.subscribe(new Ps(e, this.total))
}, Ls),
Ps = (ut(Rs, Ms = Pt), Rs.prototype._next = function(e) {
var t = this.total,
i = ++this.count;
i <= t && (this.destination.next(e), i === t && (this.destination.complete(), this.unsubscribe()))
}, Rs);
function Rs(e, t) {
e = Ms.call(this, e) || this;
return e.total = t, e.count = 0, e
}
function Ls(e) {
if (this.total = e, this.total < 0) throw new lr
}
function _s(t, n) {
return n ? function(e) {
return e.pipe(_s(function(i, r) {
return Fr(t(i, r)).pipe(hr(function(e, t) {
return n(i, e, r, t)
}))
}))
} : function(e) {
return e.lift(new Fs(t))
}
}
var Ns, Fs = ($s.prototype.call = function(e, t) {
return t.subscribe(new Bs(e, this.project))
}, $s),
Bs = (ut(Us, Ns = Vr), Us.prototype._next = function(e) {
this.hasSubscription || this.tryNext(e)
}, Us.prototype.tryNext = function(e) {
var t, i = this.index++;
try {
t = this.project(e, i)
} catch (e) {
return void this.destination.error(e)
}
this.hasSubscription = !0, this._innerSub(t)
}, Us.prototype._innerSub = function(e) {
var t = new $r(this),
i = this.destination;
i.add(t);
e = Hr(e, t);
e !== t && i.add(e)
}, Us.prototype._complete = function() {
this.hasCompleted = !0, this.hasSubscription || this.destination.complete(), this.unsubscribe()
}, Us.prototype.notifyNext = function(e) {
this.destination.next(e)
}, Us.prototype.notifyError = function(e) {
this.destination.error(e)
}, Us.prototype.notifyComplete = function() {
this.hasSubscription = !1, this.hasCompleted && this.destination.complete()
}, Us);
function Us(e, t) {
e = Ns.call(this, e) || this;
return e.project = t, e.hasSubscription = !1, e.hasCompleted = !1, e.index = 0, e
}
function $s(e) {
this.project = e
}
function Vs(t) {
return function(e) {
return e.lift(new qs(t))
}
}
var Ks, qs = (Qs.prototype.call = function(e, t) {
return t.subscribe(new Hs(e, this.callback))
}, Qs),
Hs = (ut(js, Ks = Pt), js);
function js(e, t) {
e = Ks.call(this, e) || this;
return e.add(new At(t)), e
}
function Qs(e) {
this.callback = e
}
function Ws(t) {
return function(e) {
return 0 === t ? _i() : e.lift(new zs(t))
}
}
var Gs, zs = (Js.prototype.call = function(e, t) {
return t.subscribe(new Xs(e, this.total))
}, Js),
Xs = (ut(Ys, Gs = Pt), Ys.prototype._next = function(e) {
var t = this.ring,
i = this.total,
r = this.count++;
t.length < i ? t.push(e) : t[r % i] = e
}, Ys.prototype._complete = function() {
var e = this.destination,
t = this.count;
if (0 < t)
for (var i = this.count >= this.total ? this.total : this.count, r = this.ring, n = 0; n < i; n++) {
var s = t++ % i;
e.next(r[s])
}
e.complete()
}, Ys);
function Ys(e, t) {
e = Gs.call(this, e) || this;
return e.total = t, e.ring = new Array, e.count = 0, e
}
function Js(e) {
if (this.total = e, this.total < 0) throw new lr
}
function Zs(t) {
return function(e) {
return e.lift(new ta(t))
}
}
var ea, ta = (na.prototype.call = function(e, t) {
return t.subscribe(new ia(e, this.value))
}, na),
ia = (ut(ra, ea = Pt), ra.prototype._next = function(e) {
this.destination.next(this.value)
}, ra);
function ra(e, t) {
e = ea.call(this, e) || this;
return e.value = t, e
}
function na(e) {
this.value = e
}
function sa(t, i) {
var r = 2 <= arguments.length ? !0 : !1;
return function(e) {
return e.lift(new oa(t, i, r))
}
}
var aa, oa = (ua.prototype.call = function(e, t) {
return t.subscribe(new la(e, this.accumulator, this.seed, this.hasSeed))
}, ua),
la = (ut(da, aa = Pt), Object.defineProperty(da.prototype, "seed", {
get: function() {
return this._seed
},
set: function(e) {
this.hasSeed = !0, this._seed = e
},
enumerable: !0,
configurable: !0
}), da.prototype._next = function(e) {
if (this.hasSeed) return this._tryNext(e);
this.seed = e, this.destination.next(e)
}, da.prototype._tryNext = function(e) {
var t, i = this.index++;
try {
t = this.accumulator(this.seed, e, i)
} catch (e) {
this.destination.error(e)
}
this.seed = t, this.destination.next(t)
}, da);
function da(e, t, i, r) {
e = aa.call(this, e) || this;
return e.accumulator = t, e._seed = i, e.hasSeed = r, e.index = 0, e
}
function ua(e, t, i) {
void 0 === i && (i = !1), this.accumulator = e, this.seed = t, this.hasSeed = i
}
ca.prototype.call = function(e, t) {
var i = this.selector,
r = this.subjectFactory(),
e = i(r).subscribe(e);
return e.add(t.subscribe(r)), e
};
function ca(e, t) {
this.subjectFactory = e, this.selector = t
}
function ha() {
return function(e) {
return e.lift(new fa)
}
}
var pa, fa = (ya.prototype.call = function(e, t) {
return t.subscribe(new ma(e))
}, ya),
ma = (ut(ga, pa = Pt), ga.prototype._next = function(e) {
var t;
this.hasPrev ? t = [this.prev, e] : this.hasPrev = !0, this.prev = e, t && this.destination.next(t)
}, ga);
function ga(e) {
e = pa.call(this, e) || this;
return e.hasPrev = !1, e
}
function ya() {}
function va(t) {
return function(e) {
return e.lift(new ba(t, e))
}
}
var Sa, ba = (Ia.prototype.call = function(e, t) {
return t.subscribe(new Ta(e, this.notifier, this.source))
}, Ia),
Ta = (ut(Ea, Sa = Vr), Ea.prototype.error = function(e) {
if (!this.isStopped) {
var t = this.errors,
i = this.retries,
r = this.retriesSubscription;
if (i) this.errors = void 0, this.retriesSubscription = void 0;
else {
t = new Xt;
try {
i = (0, this.notifier)(t)
} catch (e) {
return Sa.prototype.error.call(this, e)
}
r = Hr(i, new $r(this))
}
this._unsubscribeAndRecycle(), this.errors = t, this.retries = i, this.retriesSubscription = r, t.next(e)
}
}, Ea.prototype._unsubscribe = function() {
var e = this.errors,
t = this.retriesSubscription;
e && (e.unsubscribe(), this.errors = void 0), t && (t.unsubscribe(), this.retriesSubscription = void 0), this.retries = void 0
}, Ea.prototype.notifyNext = function() {
var e = this._unsubscribe;
this._unsubscribe = null, this._unsubscribeAndRecycle(), this._unsubscribe = e, this.source.subscribe(this)
}, Ea);
function Ea(e, t, i) {
e = Sa.call(this, e) || this;
return e.notifier = t, e.source = i, e
}
function Ia(e, t) {
this.notifier = e, this.source = t
}
function wa() {
return new Xt
}
function Aa() {
return function(e) {
return ri()((t = e, i = "function" == typeof(r = wa) ? r : function() {
return r
}, (e = Object.create(t, mi)).source = t, e.subjectFactory = i, e));
var t, i, r
}
}
function Oa(e, t, i) {
var c = e && "object" == typeof e ? e : {
bufferSize: e,
windowTime: t,
refCount: !1,
scheduler: i
};
return function(e) {
return e.lift((e = c.bufferSize, n = void 0 === e ? Number.POSITIVE_INFINITY : e, e = c.windowTime, s = void 0 === e ? Number.POSITIVE_INFINITY : e, a = c.refCount, o = c.scheduler, l = 0, u = d = !1, function(e) {
var t;
l++, !i || d ? (d = !1, i = new Ji(n, s, o), t = i.subscribe(this), r = e.subscribe({
next: function(e) {
i.next(e)
},
error: function(e) {
d = !0, i.error(e)
},
complete: function() {
u = !0, r = void 0, i.complete()
}
}), u && (r = void 0)) : t = i.subscribe(this), this.add(function() {
l--, t.unsubscribe(), t = void 0, r && !u && a && 0 === l && (r.unsubscribe(), i = r = void 0)
})
}));
var i, r, n, s, a, o, l, d, u
}
}
function ka(t) {
return function(e) {
return e.lift(new Da(t))
}
}
var Ca, Da = (Pa.prototype.call = function(e, t) {
return t.subscribe(new Ma(e, this.total))
}, Pa),
Ma = (ut(xa, Ca = Pt), xa.prototype._next = function(e) {
++this.count > this.total && this.destination.next(e)
}, xa);
function xa(e, t) {
e = Ca.call(this, e) || this;
return e.total = t, e.count = 0, e
}
function Pa(e) {
this.total = e
}
function Ra() {
for (var t = [], e = 0; e < arguments.length; e++) t[e] = arguments[e];
var i = t[t.length - 1];
return Ni(i) ? (t.pop(), function(e) {
return Jr(t, e, i)
}) : function(e) {
return Jr(t, e)
}
}
function La(t, n) {
return "function" == typeof n ? function(e) {
return e.pipe(La(function(i, r) {
return Fr(t(i, r)).pipe(hr(function(e, t) {
return n(i, e, r, t)
}))
}))
} : function(e) {
return e.lift(new Na(t))
}
}
var _a, Na = (Ua.prototype.call = function(e, t) {
return t.subscribe(new Fa(e, this.project))
}, Ua),
Fa = (ut(Ba, _a = Vr), Ba.prototype._next = function(e) {
var t, i = this.index++;
try {
t = this.project(e, i)
} catch (e) {
return void this.destination.error(e)
}
this._innerSub(t)
}, Ba.prototype._innerSub = function(e) {
var t = this.innerSubscription;
t && t.unsubscribe();
var i = new $r(this),
t = this.destination;
t.add(i), this.innerSubscription = Hr(e, i), this.innerSubscription !== i && t.add(this.innerSubscription)
}, Ba.prototype._complete = function() {
var e = this.innerSubscription;
e && !e.closed || _a.prototype._complete.call(this), this.unsubscribe()
}, Ba.prototype._unsubscribe = function() {
this.innerSubscription = void 0
}, Ba.prototype.notifyComplete = function() {
this.innerSubscription = void 0, this.isStopped && _a.prototype._complete.call(this)
}, Ba.prototype.notifyNext = function(e) {
this.destination.next(e)
}, Ba);
function Ba(e, t) {
e = _a.call(this, e) || this;
return e.project = t, e.index = 0, e
}
function Ua(e) {
this.project = e
}
function $a(e, t) {
return t ? La(function() {
return e
}, t) : La(function() {
return e
})
}
function Va(t) {
return function(e) {
return e.lift(new qa(t))
}
}
var Ka, qa = (Qa.prototype.call = function(e, t) {
var i = new Ha(e),
e = Hr(this.notifier, new $r(i));
return e && !i.seenValue ? (i.add(e), t.subscribe(i)) : i
}, Qa),
Ha = (ut(ja, Ka = Vr), ja.prototype.notifyNext = function() {
this.seenValue = !0, this.complete()
}, ja.prototype.notifyComplete = function() {}, ja);
function ja(e) {
e = Ka.call(this, e) || this;
return e.seenValue = !1, e
}
function Qa(e) {
this.notifier = e
}
function Wa(t, i) {
return void 0 === i && (i = !1),
function(e) {
return e.lift(new za(t, i))
}
}
var Ga, za = (Ja.prototype.call = function(e, t) {
return t.subscribe(new Xa(e, this.predicate, this.inclusive))
}, Ja),
Xa = (ut(Ya, Ga = Pt), Ya.prototype._next = function(e) {
var t, i = this.destination;
try {
t = this.predicate(e, this.index++)
} catch (e) {
return void i.error(e)
}
this.nextOrComplete(e, t)
}, Ya.prototype.nextOrComplete = function(e, t) {
var i = this.destination;
Boolean(t) ? i.next(e) : (this.inclusive && i.next(e), i.complete())
}, Ya);
function Ya(e, t, i) {
e = Ga.call(this, e) || this;
return e.predicate = t, e.inclusive = i, e.index = 0, e
}
function Ja(e, t) {
this.predicate = e, this.inclusive = t
}
function Za(t, i, r) {
return function(e) {
return e.lift(new to(t, i, r))
}
}
var eo, to = (so.prototype.call = function(e, t) {
return t.subscribe(new io(e, this.nextOrObserver, this.error, this.complete))
}, so),
io = (ut(no, eo = Pt), no.prototype._next = function(e) {
try {
this._tapNext.call(this._context, e)
} catch (e) {
return void this.destination.error(e)
}
this.destination.next(e)
}, no.prototype._error = function(e) {
try {
this._tapError.call(this._context, e)
} catch (e) {
return void this.destination.error(e)
}
this.destination.error(e)
}, no.prototype._complete = function() {
try {
this._tapComplete.call(this._context)
} catch (e) {
return void this.destination.error(e)
}
return this.destination.complete()
}, no),
ro = {
leading: !0,
trailing: !1
};
function no(e, t, i, r) {
e = eo.call(this, e) || this;
return e._tapNext = or, e._tapError = or, e._tapComplete = or, e._tapError = i || or, e._tapComplete = r || or, yt(t) ? (e._context = e)._tapNext = t : t && (e._context = t, e._tapNext = t.next || or, e._tapError = t.error || or, e._tapComplete = t.complete || or), e
}
function so(e, t, i) {
this.nextOrObserver = e, this.error = t, this.complete = i
}
function ao(t, i, r) {
return void 0 === i && (i = ir), void 0 === r && (r = ro),
function(e) {
return e.lift(new lo(t, i, r.leading, r.trailing))
}
}
var oo, lo = (ho.prototype.call = function(e, t) {
return t.subscribe(new uo(e, this.duration, this.scheduler, this.leading, this.trailing))
}, ho),
uo = (ut(co, oo = Pt), co.prototype._next = function(e) {
this.throttled ? this.trailing && (this._trailingValue = e, this._hasTrailingValue = !0) : (this.add(this.throttled = this.scheduler.schedule(po, this.duration, {
subscriber: this
})), this.leading ? this.destination.next(e) : this.trailing && (this._trailingValue = e, this._hasTrailingValue = !0))
}, co.prototype._complete = function() {
this._hasTrailingValue && this.destination.next(this._trailingValue), this.destination.complete()
}, co.prototype.clearThrottle = function() {
var e = this.throttled;
e && (this.trailing && this._hasTrailingValue && (this.destination.next(this._trailingValue), this._trailingValue = null, this._hasTrailingValue = !1), e.unsubscribe(), this.remove(e), this.throttled = null)
}, co);
function co(e, t, i, r, n) {
e = oo.call(this, e) || this;
return e.duration = t, e.scheduler = i, e.leading = r, e.trailing = n, e._hasTrailingValue = !1, e._trailingValue = null, e
}
function ho(e, t, i, r) {
this.duration = e, this.scheduler = t, this.leading = i, this.trailing = r
}
function po(e) {
e.subscriber.clearThrottle()
}
var fo, mo = (vo.prototype.call = function(e, t) {
return t.subscribe(new go(e, this.absoluteTimeout, this.waitFor, this.withObservable, this.scheduler))
}, vo),
go = (ut(yo, fo = Vr), yo.dispatchTimeout = function(e) {
var t = e.withObservable;
e._unsubscribeAndRecycle(), e.add(Hr(t, new $r(e)))
}, yo.prototype.scheduleTimeout = function() {
var e = this.action;
e ? this.action = e.schedule(this, this.waitFor) : this.add(this.action = this.scheduler.schedule(yo.dispatchTimeout, this.waitFor, this))
}, yo.prototype._next = function(e) {
this.absoluteTimeout || this.scheduleTimeout(), fo.prototype._next.call(this, e)
}, yo.prototype._unsubscribe = function() {
this.action = void 0, this.scheduler = null, this.withObservable = null
}, yo);
function yo(e, t, i, r, n) {
e = fo.call(this, e) || this;
return e.absoluteTimeout = t, e.waitFor = i, e.withObservable = r, e.scheduler = n, e.scheduleTimeout(), e
}
function vo(e, t, i, r) {
this.waitFor = e, this.absoluteTimeout = t, this.withObservable = i, this.scheduler = r
}
function So(e, t) {
return void 0 === t && (t = ir), r = e, n = Vi(new dr), void 0 === (s = t) && (s = ir),
function(e) {
var t = as(r),
i = t ? +r - s.now() : Math.abs(r);
return e.lift(new mo(i, t, n, s))
};
var r, n, s
}
function bo() {
for (var i = [], e = 0; e < arguments.length; e++) i[e] = arguments[e];
return function(e) {
var t;
return "function" == typeof i[i.length - 1] && (t = i.pop()), e.lift(new Io(i, t))
}
}
var To, Eo, Io = (Co.prototype.call = function(e, t) {
return t.subscribe(new wo(e, this.observables, this.project))
}, Co),
wo = (ut(ko, To = vr), ko.prototype.notifyNext = function(e, t, i) {
this.values[i] = t;
t = this.toRespond;
0 < t.length && (-1 !== (i = t.indexOf(i)) && t.splice(i, 1))
}, ko.prototype.notifyComplete = function() {}, ko.prototype._next = function(e) {
0 === this.toRespond.length && (e = [e].concat(this.values), this.project ? this._tryProject(e) : this.destination.next(e))
}, ko.prototype._tryProject = function(e) {
var t;
try {
t = this.project.apply(this, e)
} catch (e) {
return void this.destination.error(e)
}
this.destination.next(t)
}, ko),
Ao = {
type: null,
entityIds: null,
skip: !1
},
Oo = !1;
function ko(e, t, i) {
var r = To.call(this, e) || this;
r.observables = t, r.project = i, r.toRespond = [];
var n = t.length;
r.values = new Array(n);
for (var s = 0; s < n; s++) r.toRespond.push(s);
for (s = 0; s < n; s++) {
var a = t[s];
r.add(Cr(r, a, void 0, s))
}
return r
}
function Co(e, t) {
this.observables = e, this.project = t
}
function Do(e, t) {
Mo(e, t), Oo = !0
}
function Mo(e, t) {
!1 === Oo && (Ao.type = e, Ao.entityIds = t)
}
function xo(e, t) {
return e.hasOwnProperty(t)
}
function Po(e) {
return null == e
}
function Ro(e) {
return Po(e) ? [] : Array.isArray(e) ? e : [e]
}(iu = Eo = Eo || {}).Set = "Set", iu.Add = "Add", iu.Update = "Update", iu.Remove = "Remove";
var Lo = "undefined" != typeof window,
_o = !0;
function No(e) {
var t = typeof e;
return null != e && ("object" == t || "function" == t)
}
function Fo(e) {
return Array.isArray(e)
}
function Bo(e) {
return !1 === Po(e)
}
function Uo(e) {
return Fo(e) && 0 === e.length
}
function $o(e) {
return "function" == typeof e
}
function Vo(e) {
return void 0 === e
}
function Ko(e) {
return e.hasOwnProperty("active")
}
function qo(e) {
return Fo(e)
}
function Ho(e) {
var t, i = e.active,
r = e.ids,
n = e.entities;
return qo(i) ? (t = r, (r = (e = i).filter(function(e) {
return -1 < t.indexOf(e)
})).length === e.length ? e : r) : !1 === xo(n, i) ? null : i
}
function jo(e, t) {
var i, r, n = {};
try {
for (var s = ft(Object.keys(e)), a = s.next(); !a.done; a = s.next()) {
var o = a.value;
n[o] = t(e[o])
}
} catch (e) {
i = {
error: e
}
} finally {
try {
a && !a.done && (r = s.return) && r.call(s)
} finally {
if (i) throw i.error
}
}
return n
}
var Qo = {
resettable: !1,
ttl: null,
producerFn: void 0
};
function Wo(t) {
Object.freeze(t);
var i = "function" == typeof t,
r = Object.prototype.hasOwnProperty;
return Object.getOwnPropertyNames(t).forEach(function(e) {
!r.call(t, e) || i && ("caller" === e || "callee" === e || "arguments" === e) || null === t[e] || "object" != typeof t[e] && "function" != typeof t[e] || Object.isFrozen(t[e]) || Wo(t[e])
}), t
}
var Go, zo = new Xt,
Xo = new Ji(50, 5e3),
Yo = new Xt;
function Jo(e) {
return null != e && "" + e != "false"
}
function Zo(e) {
return Jo(e) && "Object" === e.constructor.name
}
ut(function(e) {
return Go.call(this, e) || this
}, Go = Error);
var el = {},
tl = {};
Lo && (window.$$stores = el, window.$$queries = tl);
var il = new Xt,
rl = new yi(!1),
nl = {
activeTransactions: 0,
batchTransaction: null
};
function sl() {
return 0 < nl.activeTransactions
}
function al(e, t) {
void 0 === t && (t = void 0), sl() || (nl.batchTransaction = new Xt), nl.activeTransactions++, rl.next(!0);
try {
return e.apply(t)
} finally {
Do("@Transaction"), 0 == --nl.activeTransactions && (nl.batchTransaction.next(!0), nl.batchTransaction.complete(), rl.next(!1), il.next(!0))
}
}
function ol() {
return function(e, t, i) {
var r = i.value;
return i.value = function() {
for (var e = this, t = [], i = 0; i < arguments.length; i++) t[i] = arguments[i];
return al(function() {
return r.apply(e, t)
}, this)
}, i
}
}
function ll(t) {
return function(e) {
return e.pipe(Za(function(e) {
return al(function() {
return t(e)
})
}))
}
}
var dl = (ul.prototype.setLoading = function(t) {
(t = void 0 === t ? !1 : t) !== this._value().loading && (_o && Mo("Set Loading"), this._setState(function(e) {
return ct({}, e, {
loading: t
})
}))
}, ul.prototype.setHasCache = function(e, t) {
var i, r = this;
void 0 === t && (t = {
restartTTL: !1
}), e !== this.cache.active.value && this.cache.active.next(e), t.restartTTL && (i = this.getCacheTTL()) && (null !== this.cache.ttl && clearTimeout(this.cache.ttl), this.cache.ttl = setTimeout(function() {
return r.setHasCache(!1)
}, i))
}, ul.prototype.getValue = function() {
return this.storeValue
}, ul.prototype.setError = function(t) {
t !== this._value().error && (_o && Mo("Set Error"), this._setState(function(e) {
return ct({}, e, {
error: t
})
}))
}, ul.prototype._select = function(t) {
return this.store.asObservable().pipe(hr(function(e) {
return t(e.state)
}), Is())
}, ul.prototype._value = function() {
return this.storeValue
}, ul.prototype._cache = function() {
return this.cache.active
}, Object.defineProperty(ul.prototype, "config", {
get: function() {
return this.constructor.akitaConfig || {}
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(ul.prototype, "storeName", {
get: function() {
return this.config.storeName || this.options.storeName || this.options.name
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(ul.prototype, "deepFreeze", {
get: function() {
return this.config.deepFreezeFn || this.options.deepFreezeFn || Wo
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(ul.prototype, "cacheConfig", {
get: function() {
return this.config.cache || this.options.cache
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(ul.prototype, "_producerFn", {
get: function() {
return this.config.producerFn || this.options.producerFn || Qo.producerFn
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(ul.prototype, "resettable", {
get: function() {
return (Bo(this.config.resettable) ? this.config : this.options).resettable
},
enumerable: !0,
configurable: !0
}), ul.prototype._setState = function(e, t) {
var i, r = this;
if (void 0 === t && (t = !0), $o(e) ? (i = e(this._value()), this.storeValue = _o ? this.deepFreeze(i) : i) : this.storeValue = e, !this.store) return this.store = new yi({
state: this.storeValue
}), void(_o && this.store.subscribe(function(e) {
var t = e.action;
t && (e = r.storeName, Yo.next({
storeName: e,
action: t
}))
}));
sl() ? this.handleTransaction() : this.dispatch(this.storeValue, t)
}, ul.prototype.reset = function() {
var e = this;
this.isResettable() ? (_o && Mo("Reset"), this._setState(function() {
return Object.assign({}, e._initialState)
}), this.setHasCache(!1)) : _o && console.warn("You need to enable the reset functionality")
}, ul.prototype.update = function(e) {
_o && Mo("Update");
var t = this._value(),
e = $o(e) ? $o(this._producerFn) ? this._producerFn(t, e) : e(t) : e,
e = this.akitaPreUpdate(t, ct({}, t, e)),
e = Zo(t) ? e : new t.constructor(e);
this._setState(e)
}, ul.prototype.updateStoreConfig = function(e) {
this.options = ct({}, this.options, e)
}, ul.prototype.akitaPreUpdate = function(e, t) {
return t
}, ul.prototype.ngOnDestroy = function() {
this.destroy()
}, ul.prototype.destroy = function() {
var e;
Lo && window.hmrEnabled || this !== el[this.storeName] || (delete el[this.storeName], e = this.storeName, zo.next(e), this.setHasCache(!1), this.cache.active.complete(), this.store.complete())
}, ul.prototype.onInit = function(e) {
var t, i;
(el[this.storeName] = this)._setState(function() {
return e
}), i = this.storeName, Xo.next(i), this.isResettable() && (this._initialState = e), _o && (t = this.storeName, i = this.constructor.name, t || console.error("@StoreConfig({ name }) is missing in " + i))
}, ul.prototype.dispatch = function(e, t) {
var i = void 0;
(t = void 0 === t ? !0 : t) && (i = Ao, Oo = !1), this.store.next({
state: e,
action: i
})
}, ul.prototype.watchTransaction = function() {
var e = this;
(nl.batchTransaction ? nl.batchTransaction.asObservable() : $i(!0)).subscribe(function() {
e.inTransaction = !1, e.dispatch(e._value())
})
}, ul.prototype.isResettable = function() {
return !1 !== this.resettable && (this.resettable || Qo.resettable)
}, ul.prototype.handleTransaction = function() {
this.inTransaction || (this.watchTransaction(), this.inTransaction = !0)
}, ul.prototype.getCacheTTL = function() {
return this.cacheConfig && this.cacheConfig.ttl || Qo.ttl
}, ul);
function ul(e, t) {
this.options = t = void 0 === t ? {} : t, this.inTransaction = !1, this.cache = {
active: new yi(!1),
ttl: null
}, this.onInit(e)
}
var cl, hl, pl, fl = (ut(yl, pl = dl), Object.defineProperty(yl.prototype, "selectEntityAction$", {
get: function() {
return this.entityActions.asObservable()
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(yl.prototype, "selectEntityIdChanges$", {
get: function() {
return this.entityIdChanges.asObservable()
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(yl.prototype, "idKey", {
get: function() {
return this.config.idKey || this.options.idKey || "id"
},
enumerable: !0,
configurable: !0
}), yl.prototype.set = function(a, o) {
var l, d = this;
void 0 === o && (o = {}), Po(a) || (_o && Mo("Set Entity"), l = this.akitaPreAddEntity === yl.prototype.akitaPreAddEntity, this.setHasCache(!0, {
restartTTL: !0
}), this._setState(function(e) {
var t, i, r, n, s, e = (t = {
state: e,
entities: a,
idKey: d.idKey,
preAddEntity: d.akitaPreAddEntity,
isNativePreAdd: l
}, r = t.state, n = t.entities, s = t.idKey, e = t.preAddEntity, t = t.isNativePreAdd, e = Fo(n) ? (i = (s = function(e, t, i) {
var r, n, s = {
entities: {},
ids: []
};
try {
for (var a = ft(e), o = a.next(); !o.done; o = a.next()) {
var l = i(o.value);
s.entities[l[t]] = l, s.ids.push(l[t])
}
} catch (e) {
r = {
error: e
}
} finally {
try {
o && !o.done && (n = a.return) && n.call(a)
} finally {
if (r) throw r.error
}
}
return s
}(n, s, e)).entities, s.ids) : n.entities && n.ids ? (i = t ? n.entities : jo(n.entities, e), n.ids) : (i = t ? n : jo(n, e), Object.keys(i).map(function(e) {
return isNaN(e) ? e : Number(e)
})), e = ct({}, r, {
entities: i,
ids: e,
loading: !1
}), Ko(r) && (e.active = Ho(e)), e);
return !1 === Vo(o.activeId) && (e.active = o.activeId), e
}), this.hasInitialUIState() && this.handleUICreation(), this.entityActions.next({
type: Eo.Set,
ids: this.ids
}))
}, yl.prototype.add = function(e, t) {
void 0 === t && (t = {
loading: !1
});
var i, e = Ro(e);
Uo(e) || (i = function(e) {
var t, i, r = e.state,
n = e.entities,
s = e.idKey,
a = e.options,
o = void 0 === a ? {} : a,
l = e.preAddEntity,
d = {},
u = [],
c = !1;
try {
for (var h = ft(n), p = h.next(); !p.done; p = h.next()) {
var f, m, g = p.value;
!1 === xo(r.entities, g[s]) && (d[m = (f = l(g))[s]] = f, o.prepend ? u.unshift(m) : u.push(m), c = !0)
}
} catch (e) {
t = {
error: e
}
} finally {
try {
p && !p.done && (i = h.return) && i.call(h)
} finally {
if (t) throw t.error
}
}
return c ? {
newState: ct({}, r, {
entities: ct({}, r.entities, d),
ids: o.prepend ? gt(u, r.ids) : gt(r.ids, u)
}),
newIds: u
} : null
}({
state: this._value(),
preAddEntity: this.akitaPreAddEntity,
entities: e,
idKey: this.idKey,
options: t
})) && (_o && Mo("Add Entity"), i.newState.loading = t.loading, this._setState(function() {
return i.newState
}), this.hasInitialUIState() && this.handleUICreation(!0), this.entityActions.next({
type: Eo.Add,
ids: i.newIds
}))
}, yl.prototype.update = function(t, i) {
var r, n, s = this;
Vo(i) ? pl.prototype.update.call(this, t) : (n = [], Uo(n = $o(t) ? this.ids.filter(function(e) {
return t(s.entities[e])
}) : Po(t) ? this.ids : Ro(t)) || (_o && Mo("Update Entity", n), this._setState(function(e) {
return function(e) {
var t = e.state,
i = e.ids,
r = e.idKey,
n = e.newStateOrFn,
s = e.preUpdateEntity,
a = e.producerFn,
o = e.onEntityIdChanges,
l = {},
d = !1;
try {
for (var u = ft(i), c = u.next(); !c.done; c = u.next()) {
var h, p, f, m, g, y, v = c.value;
!1 !== xo(t.entities, v) && (h = t.entities[v], p = void 0, f = (p = $o(n) ? $o(a) ? a(h, n) : n(h) : n).hasOwnProperty(r) && p[r] !== h[r], y = void 0, m = v, f && (d = !0, m = p[r]), g = ct({}, h, p), y = Zo(h) ? g : new(Zo(p) ? h : p).constructor(g), l[m] = s(h, y))
}
} catch (e) {
T = {
error: e
}
} finally {
try {
c && !c.done && (b = u.return) && b.call(u)
} finally {
if (T) throw T.error
}
}
var S, b = t.ids,
T = t.entities;
return d && (S = mt(i, 1)[0], T = function(e, t) {
var i = {};
for (n in e) Object.prototype.hasOwnProperty.call(e, n) && t.indexOf(n) < 0 && (i[n] = e[n]);
if (null != e && "function" == typeof Object.getOwnPropertySymbols)
for (var r = 0, n = Object.getOwnPropertySymbols(e); r < n.length; r++) t.indexOf(n[r]) < 0 && Object.prototype.propertyIsEnumerable.call(e, n[r]) && (i[n[r]] = e[n[r]]);
return i
}(t.entities, ["symbol" == typeof S ? S : S + ""]), b = t.ids.map(function(e) {
return e === S ? m : e
}), o(S, m)), ct({}, t, {
entities: ct({}, T, l),
ids: b
})
}({
idKey: s.idKey,
ids: n,
preUpdateEntity: s.akitaPreUpdateEntity,
state: e,
newStateOrFn: i,
producerFn: s._producerFn,
onEntityIdChanges: function(e, t) {
r = {
oldId: e,
newId: t
}, s.entityIdChanges.next(ct({}, r, {
pending: !0
}))
}
})
}), r && this.entityIdChanges.next(ct({}, r, {
pending: !1
})), this.entityActions.next({
type: Eo.Update,
ids: n
})))
}, yl.prototype.upsert = function(e, i, r, t) {
var n = this;
void 0 === t && (t = {});
var s = Ro(e),
e = function(t) {
return function(e) {
return xo(n.entities, e) === t
}
},
a = $o(r) ? t.baseClass : r ? r.baseClass : void 0,
o = $o(a),
t = s.filter(e(!0)),
e = s.filter(e(!1)).map(function(e) {
var t = "function" == typeof i ? i({}) : i,
t = $o(r) ? r(e, t) : t,
t = ct({}, t, ((t = {})[n.idKey] = e, t));
return o ? new a(t) : t
});
this.update(t, i), this.add(e), _o && Do("Upsert Entity")
}, yl.prototype.upsertMany = function(e, t) {
var i, r;
void 0 === t && (t = {});
var n = [],
s = [],
a = {};
try {
for (var o = ft(e), l = o.next(); !l.done; l = o.next()) {
var d, u, c, h, p, f, m = l.value,
g = this.akitaPreCheckEntity(m),
y = g[this.idKey];
xo(this.entities, y) ? (d = this._value().entities[y], u = ct({}, this._value().entities[y], g), c = t.baseClass ? new t.baseClass(u) : u, f = (h = this.akitaPreUpdateEntity(d, c))[this.idKey], a[f] = h, s.push(f)) : (p = t.baseClass ? new t.baseClass(g) : g, f = (h = this.akitaPreAddEntity(p))[this.idKey], n.push(f), a[f] = h)
}
} catch (e) {
i = {
error: e
}
} finally {
try {
l && !l.done && (r = o.return) && r.call(o)
} finally {
if (i) throw i.error
}
}
_o && Do("Upsert Many"), this._setState(function(e) {
return ct({}, e, {
ids: n.length ? gt(e.ids, n) : e.ids,
entities: ct({}, e.entities, a),
loading: !!t.loading
})
}), s.length && this.entityActions.next({
type: Eo.Update,
ids: s
}), n.length && this.entityActions.next({
type: Eo.Add,
ids: n
}), n.length && this.hasUIStore() && this.handleUICreation(!0)
}, yl.prototype.replace = function(e, t) {
var i, r, n = Ro(e);
if (!Uo(n)) {
var s = {};
try {
for (var a = ft(n), o = a.next(); !o.done; o = a.next()) {
var l = o.value;
t[this.idKey] = l, s[l] = t
}
} catch (e) {
i = {
error: e
}
} finally {
try {
o && !o.done && (r = a.return) && r.call(a)
} finally {
if (i) throw i.error
}
}
_o && Mo("Replace Entity", e), this._setState(function(e) {
return ct({}, e, {
entities: ct({}, e.entities, s)
})
})
}
}, yl.prototype.move = function(e, t) {
var i = this.ids.slice();
i.splice(t < 0 ? i.length + t : t, 0, i.splice(e, 1)[0]), _o && Mo("Move Entity"), this._setState(function(e) {
return ct({}, e, {
entities: ct({}, e.entities),
ids: i
})
})
}, yl.prototype.remove = function(t) {
var e, i, r = this;
Uo(this.ids) || (e = Bo(t), i = [], Uo(i = $o(t) ? this.ids.filter(function(e) {
return t(r.entities[e])
}) : e ? Ro(t) : this.ids) || (_o && Mo("Remove Entity", i), this._setState(function(e) {
return function(e) {
var t, i = e.state,
r = e.ids;
if (Po(r)) return ct({}, i, {
entities: {},
ids: [],
active: qo(i.active) ? [] : null
});
var n = i.entities,
s = {};
try {
for (var a = ft(i.ids), o = a.next(); !o.done; o = a.next()) {
var l = o.value;
!1 === r.includes(l) && (s[l] = n[l])
}
} catch (e) {
d = {
error: e
}
} finally {
try {
o && !o.done && (t = a.return) && t.call(a)
} finally {
if (d) throw d.error
}
}
var d = ct({}, i, {
entities: s,
ids: i.ids.filter(function(e) {
return !1 === r.includes(e)
})
});
return Ko(i) && (d.active = Ho(d)), d
}({
state: e,
ids: i
})
}), e || this.setHasCache(!1), this.handleUIRemove(i), this.entityActions.next({
type: Eo.Remove,
ids: i
})))
}, yl.prototype.updateActive = function(e) {
var t = Ro(this.active);
_o && Mo("Update Active", t), this.update(t, e)
}, yl.prototype.setActive = function(e) {
e = function(e, t, i) {
var r;
if (Fo(e)) r = e;
else if (No(e)) {
if (Po(i)) return;
e = Object.assign({
wrap: !0
}, e);
var n = t.indexOf(i);
if (e.prev) {
var s = 0 === n;
if (s && !e.wrap) return;
r = s ? t[t.length - 1] : t[n - 1]
} else if (e.next) {
s = t.length === n + 1;
if (s && !e.wrap) return;
r = s ? t[0] : t[n + 1]
}
} else {
if (e === i) return;
r = e
}
return r
}(e, this.ids, this.active);
void 0 !== e && (_o && Mo("Set Active", e), this._setActive(e))
}, yl.prototype.addActive = function(e) {
var t = this,
i = Ro(e);
Uo(i) || i.every(function(e) {
return -1 < t.active.indexOf(e)
}) || (_o && Mo("Add Active", e), this._setState(function(e) {
var t = Array.from(new Set(gt(e.active, i)));
return ct({}, e, {
active: t
})
}))
}, yl.prototype.removeActive = function(e) {
var t = this,
i = Ro(e);
Uo(i) || i.some(function(e) {
return -1 < t.active.indexOf(e)
}) && (_o && Mo("Remove Active", e), this._setState(function(e) {
return ct({}, e, {
active: Array.isArray(e.active) ? e.active.filter(function(e) {
return -1 === i.indexOf(e)
}) : null
})
}))
}, yl.prototype.toggleActive = function(e) {
var i = this,
t = Ro(e),
r = function(t) {
return function(e) {
return i.active.includes(e) === t
}
},
e = t.filter(r(!0)),
r = t.filter(r(!1));
this.removeActive(e), this.addActive(r), _o && Do("Toggle Active")
}, yl.prototype.createUIStore = function(e, t) {
var i = {
name: "UI/" + this.storeName,
idKey: this.idKey
};
return this.ui = new ml(e = void 0 === e ? {} : e, ct({}, i, t = void 0 === t ? {} : t)), this.ui
}, yl.prototype.destroy = function() {
pl.prototype.destroy.call(this), this.ui instanceof yl && this.ui.destroy(), this.entityActions.complete()
}, yl.prototype.akitaPreUpdateEntity = function(e, t) {
return t
}, yl.prototype.akitaPreAddEntity = function(e) {
return e
}, yl.prototype.akitaPreCheckEntity = function(e) {
return e
}, Object.defineProperty(yl.prototype, "ids", {
get: function() {
return this._value().ids
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(yl.prototype, "entities", {
get: function() {
return this._value().entities
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(yl.prototype, "active", {
get: function() {
return this._value().active
},
enumerable: !0,
configurable: !0
}), yl.prototype._setActive = function(t) {
this._setState(function(e) {
return ct({}, e, {
active: t
})
})
}, yl.prototype.handleUICreation = function(e) {
var r = this,
t = this.ids,
n = $o(this.ui._akitaCreateEntityFn),
i = function(e) {
var t = r.entities[e],
i = n ? r.ui._akitaCreateEntityFn(t) : r.ui._akitaCreateEntityFn;
return ct(((e = {})[r.idKey] = t[r.idKey], e), i)
},
i = ((e = void 0 === e ? !1 : e) ? this.ids.filter(function(e) {
return Vo(r.ui.entities[e])
}) : t).map(i);
e ? this.ui.add(i) : this.ui.set(i)
}, yl.prototype.hasInitialUIState = function() {
return this.hasUIStore() && !1 === Vo(this.ui._akitaCreateEntityFn)
}, yl.prototype.handleUIRemove = function(e) {
this.hasUIStore() && this.ui.remove(e)
}, yl.prototype.hasUIStore = function() {
return this.ui instanceof ml
}, ht([ol(), pt("design:type", Function), pt("design:paramtypes", [Object, Object, Object, Object]), pt("design:returntype", void 0)], yl.prototype, "upsert", null), ht([ol(), pt("design:type", Function), pt("design:paramtypes", ["function" == typeof(w = "undefined" != typeof T && T) ? w : Object]), pt("design:returntype", void 0)], yl.prototype, "toggleActive", null), yl),
ml = (ut(gl, hl = fl), gl.prototype.setInitialEntityState = function(e) {
this._akitaCreateEntityFn = e
}, gl);
function gl(e, t) {
return hl.call(this, e = void 0 === e ? {} : e, t = void 0 === t ? {} : t) || this
}
function yl(e, t) {
void 0 === t && (t = {});
e = pl.call(this, ct({}, {
entities: {},
ids: [],
loading: !0,
error: null
}, e = void 0 === e ? {} : e), t) || this;
return e.options = t, e.entityActions = new Xt, e.entityIdChanges = new Xt, e
}
function vl() {
return Is(function(e, t) {
return e === t || !1 !== Fo(e) && !1 !== Fo(t) && (!(!Uo(e) || !Uo(t)) || !Sl(t, e) && !1 === Sl(e, t))
})
}
function Sl(e, t) {
return t.some(function(t) {
return void 0 === e.find(function(e) {
return e === t
})
})
}
function bl(i, e) {
for (var r, n, s, a = [], o = i.ids, l = i.entities, d = e.filterBy, t = e.limitTo, u = e.sortBy, e = e.sortByOrder, c = 0; c < o.length; c++) ! function(t) {
var i = l[o[t]];
if (!d) return a.push(i);
Ro(d).every(function(e) {
return e(i, t)
}) && a.push(i)
}(c);
u && (s = $o(u) ? u : (r = u, void 0 === (n = e) && (n = cl.ASC), function(e, t) {
if (!e.hasOwnProperty(r) || !t.hasOwnProperty(r)) return 0;
var i = "string" == typeof e[r] ? e[r].toUpperCase() : e[r],
e = "string" == typeof t[r] ? t[r].toUpperCase() : t[r],
t = 0;
return e < i ? t = 1 : i < e && (t = -1), n == cl.DESC ? -1 * t : t
}), a = a.sort(function(e, t) {
return s(e, t, i)
}));
t = Math.min(t || a.length, a.length);
return t === a.length ? a : a.slice(0, t)
}
function Tl(e) {
return "string" == typeof e
}
function El(t, i) {
return function(e) {
e = e[t];
if (!Vo(e)) return i ? Tl(i) ? e[i] : i(e) : e
}
}(vi = cl = cl || {}).ASC = "asc", vi.DESC = "desc";
Il.prototype.select = function(t) {
var e, n;
if ($o(t)) e = t;
else if (Tl(t)) e = function(e) {
return e[t]
};
else {
if (Array.isArray(t)) return this.store._select(function(e) {
return e
}).pipe(Is((n = t, function(t, i) {
var r = $o(n[0]);
return !1 === n.some(function(e) {
return r ? e(t) !== e(i) : t[e] !== i[e]
})
})), hr(function(i) {
return $o(t[0]) ? t.map(function(e) {
return e(i)
}) : t.reduce(function(e, t) {
return e[t] = i[t], e
}, {})
}));
e = function(e) {
return e
}
}
return this.store._select(e)
}, Il.prototype.selectLoading = function() {
return this.select(function(e) {
return e.loading
})
}, Il.prototype.selectError = function() {
return this.select(function(e) {
return e.error
})
}, Il.prototype.getValue = function() {
return this.store._value()
}, Il.prototype.selectHasCache = function() {
return this.store._cache().asObservable()
}, Il.prototype.getHasCache = function() {
return this.store._cache().value
}, Object.defineProperty(Il.prototype, "config", {
get: function() {
return this.constructor.akitaQueryConfig
},
enumerable: !0,
configurable: !0
}), bi = Il;
function Il(e) {
this.store = e, this.__store__ = e, _o && (tl[e.storeName] = this)
}
function wl(e) {
return e.pipe(ln(function(e) {
return null != e
}))
}
var Al, Ol, kl = (ut(Ml, Ol = bi), Ml.prototype.selectAll = function(e) {
var t = this;
return void 0 === e && (e = {
asObject: !1
}), this.select(function(e) {
return e.entities
}).pipe(hr(function() {
return t.getAll(e)
}))
}, Ml.prototype.getAll = function(e) {
return (e = void 0 === e ? {
asObject: !1,
filterBy: void 0,
limitTo: void 0
} : e).asObject ? function(e, t) {
var r = {},
n = t.filterBy,
s = t.limitTo,
a = e.ids,
o = e.entities;
if (!n && !s) return o;
e = !1 === Po(s);
if (n && e)
for (var l = 0, i = 0, d = a.length; i < d && "break" !== function(t) {
if (l === s) return "break";
var e = a[t],
i = o[e];
Ro(n).every(function(e) {
return e(i, t)
}) && (r[e] = i, l++)
}(i); i++);
else
for (var u = Math.min(s || a.length, a.length), i = 0; i < u; i++) ! function(t) {
var e = a[t],
i = o[e];
if (!n) return r[e] = i;
Ro(n).every(function(e) {
return e(i, t)
}) && (r[e] = i)
}(i);
return r
}(this.getValue(), e) : (t = e, i = this.config || this.options, t.sortBy = t.sortBy || i && i.sortBy, t.sortByOrder = t.sortByOrder || i && i.sortByOrder, bl(this.getValue(), e));
var t, i
}, Ml.prototype.selectMany = function(e, i) {
return e && e.length ? this.select(function(e) {
return e.entities
}).pipe(hr(function(t) {
return n = function(e) {
return El(e, i)(t)
}, e.reduce(function(e, t, i, r) {
t = n(t);
return void 0 !== t && e.push(t), e
}, []);
var n
}), vl()) : $i([])
}, Ml.prototype.selectEntity = function(e, t) {
var i = e;
return $o(e) && (i = function(e, t) {
var i, r;
try {
for (var n = ft(Object.keys(t)), s = n.next(); !s.done; s = n.next()) {
var a = s.value;
if (!0 === e(t[a])) return a
}
} catch (e) {
i = {
error: e
}
} finally {
try {
s && !s.done && (r = n.return) && r.call(n)
} finally {
if (i) throw i.error
}
}
}(e, this.getValue().entities)), this.select(function(e) {
return e.entities
}).pipe(hr(El(i, t)), Is())
}, Ml.prototype.getEntity = function(e) {
return this.getValue().entities[e]
}, Ml.prototype.selectActiveId = function() {
return this.select(function(e) {
return e.active
})
}, Ml.prototype.getActiveId = function() {
return this.getValue().active
}, Ml.prototype.selectActive = function(t) {
var i = this;
return Fo(this.getActive()) ? this.selectActiveId().pipe(La(function(e) {
return i.selectMany(e, t)
})) : this.selectActiveId().pipe(La(function(e) {
return i.selectEntity(e, t)
}))
}, Ml.prototype.getActive = function() {
var t = this,
e = this.getActiveId();
return Fo(e) ? e.map(function(e) {
return t.getValue().entities[e]
}) : Jo(e) ? this.getEntity(e) : void 0
}, Ml.prototype.selectCount = function(e) {
var t = this;
return this.select(function(e) {
return e.entities
}).pipe(hr(function() {
return t.getCount(e)
}))
}, Ml.prototype.getCount = function(e) {
return ($o(e) ? this.getAll().filter(e) : this.getValue().ids).length
}, Ml.prototype.selectLast = function(e) {
return this.selectAt(function(e) {
return e[e.length - 1]
}, e)
}, Ml.prototype.selectFirst = function(e) {
return this.selectAt(function(e) {
return e[0]
}, e)
}, Ml.prototype.selectEntityAction = function(e) {
if (Po(e)) return this.store.selectEntityAction$;
var t = Fo(e) ? function(e) {
return e
} : function(e) {
return e.ids
},
i = Ro(e);
return this.store.selectEntityAction$.pipe(ln(function(e) {
e = e.type;
return i.includes(e)
}), hr(function(e) {
return t(e)
}))
}, Ml.prototype.hasEntity = function(e) {
var t = this;
return Po(e) ? 0 < this.getValue().ids.length : $o(e) ? this.getAll().some(e) : Fo(e) ? e.every(function(e) {
return e in t.getValue().entities
}) : e in this.getValue().entities
}, Ml.prototype.hasActive = function(e) {
var t = this.getValue().active,
i = Bo(e);
return Array.isArray(t) ? i ? t.includes(e) : 0 < t.length : i ? t === e : Bo(t)
}, Ml.prototype.createUIQuery = function() {
this.ui = new Cl(this.__store__.ui)
}, Ml.prototype.selectAt = function(e, t) {
var i = this;
return this.select(function(e) {
return e.ids
}).pipe(hr(e), Is(), La(function(e) {
return i.selectEntity(e, t)
}))
}, Ml),
Cl = (ut(Dl, Al = kl), Dl);
function Dl(e) {
return Al.call(this, e) || this
}
function Ml(e, t) {
void 0 === t && (t = {});
var i = Ol.call(this, e) || this;
return i.options = t, i.__store__ = e, i
}
function xl(e, t) {
return 1 === t.split(".").length ? e : t.split(".").slice(1).join(".").split(".").reduce(function(e, t) {
return e && e[t]
}, e)
}
function Pl(e, t, r) {
var i = t.split(".");
if (1 === i.length) return ct({}, e, r);
e = ct({}, e);
var n = i.length - 2;
return t.split(".").slice(1).reduce(function(e, t, i) {
return e[t] = i !== n ? ct({}, e[t]) : Array.isArray(e[t]) || !No(e[t]) ? r : ct({}, e[t], r), e && e[t]
}, e), e
}
new Ji(1);
var Rl, Ll, _l, Nl, A = (Bl.prototype.getQuery = function() {
return this.query
}, Bl.prototype.getStore = function() {
return this.getQuery().__store__
}, Bl.prototype.isEntityBased = Jo, Bl.prototype.selectSource = function(e, t) {
var i = this;
return this.isEntityBased(e) ? this.getQuery().selectEntity(e).pipe(wl) : t ? this.getQuery().select(function(e) {
return xl(e, i.withStoreName(t))
}) : this.getQuery().select()
}, Bl.prototype.getSource = function(e, t) {
if (this.isEntityBased(e)) return this.getQuery().getEntity(e);
e = this.getQuery().getValue();
return t ? xl(e, this.withStoreName(t)) : e
}, Bl.prototype.withStoreName = function(e) {
return this.storeName + "." + e
}, Object.defineProperty(Bl.prototype, "storeName", {
get: function() {
return this.getStore().storeName
},
enumerable: !0,
configurable: !0
}), Bl.prototype.updateStore = function(t, e, i) {
var r = this;
this.isEntityBased(e) ? this.getStore().update(e, t) : i ? this.getStore()._setState(function(e) {
return Pl(e, r.withStoreName(i), t)
}) : this.getStore()._setState(function(e) {
return ct({}, e, t)
})
}, Bl.prototype.onReset = function(i) {
var r = this,
n = this.getStore().reset;
this.getStore().reset = function() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
setTimeout(function() {
n.apply(r.getStore(), e), i()
})
}
}, Bl),
Fl = {
pagesControls: !1,
range: !1,
startWith: 1,
cacheTimeout: void 0,
clearStoreWithCache: !0
};
function Bl(e, t) {
this.query = e
}
function Ul(e, t, i) {
void 0 === i && (i = {});
var r = Rl.call(this, e) || this;
return r.query = e, r.factoryFnOrPath = t, r.params = i, r.params = ct({
debounceTime: 300,
formKey: "akitaForm",
emitEvent: !1,
arrControlFactory: function(e) {
return r.builder.control(e)
}
}, i), r.isRootKeys = !1 === Jo(t), r.isKeyBased = Tl(t) || r.isRootKeys, r
}
function $l(e, t) {
void 0 === t && (t = {});
var i = Ll.call(this, e, {
resetFn: function() {
i.initial = !1, i.destroy({
clearCache: !0,
currentPage: 1
})
}
}) || this;
i.query = e, i.config = t, i.metadata = new Map, i.pages = new Map, i.pagination = {
currentPage: 1,
perPage: 0,
total: 0,
lastPage: 0,
data: []
}, i.initial = !0, i.isLoading$ = i.query.selectLoading().pipe(function(t) {
void 0 === t && (t = ir);
var i = as(0) ? 0 - t.now() : Math.abs(0);
return function(e) {
return e.lift(new ls(i, t))
}
}()), i.config = Object.assign(Fl, t);
e = i.config, t = e.startWith, e = e.cacheTimeout;
return i.page = new yi(t), e && (e instanceof $t || "function" == typeof e.lift && "function" == typeof e.subscribe) && (i.clearCacheSubscription = e.subscribe(function() {
return i.clearCache()
})), i
}
ut($l, Ll = A), Object.defineProperty($l.prototype, "pageChanges", {
get: function() {
return this.page.asObservable()
},
enumerable: !0,
configurable: !0
}), Object.defineProperty($l.prototype, "currentPage", {
get: function() {
return this.pagination.currentPage
},
enumerable: !0,
configurable: !0
}), Object.defineProperty($l.prototype, "isFirst", {
get: function() {
return 1 === this.currentPage
},
enumerable: !0,
configurable: !0
}), Object.defineProperty($l.prototype, "isLast", {
get: function() {
return this.currentPage === this.pagination.lastPage
},
enumerable: !0,
configurable: !0
}), $l.prototype.withControls = function() {
return this.config.pagesControls = !0, this
}, $l.prototype.withRange = function() {
return this.config.range = !0, this
}, $l.prototype.setLoading = function(e) {
void 0 === e && (e = !0), this.getStore().setLoading(e)
}, $l.prototype.update = function(e) {
this.pagination = e, this.addPage(e.data)
}, $l.prototype.addPage = function(e) {
var t = this;
this.pages.set(this.currentPage, {
ids: e.map(function(e) {
return e[t.getStore().idKey]
})
}), this.getStore().upsertMany(e)
}, $l.prototype.clearCache = function(e) {
void 0 === e && (e = {}), this.initial || (Do("@Pagination - Clear Cache"), !1 !== e.clearStore && (this.config.clearStoreWithCache || e.clearStore) && this.getStore().remove(), this.pages = new Map, this.metadata = new Map), this.initial = !1
}, $l.prototype.clearPage = function(e) {
this.pages.delete(e)
}, $l.prototype.destroy = function(e) {
var t = void 0 === e ? {} : e,
e = t.clearCache,
t = t.currentPage;
this.clearCacheSubscription && this.clearCacheSubscription.unsubscribe(), e && this.clearCache(), Vo(t) || this.setPage(t), this.initial = !0
}, $l.prototype.isPageActive = function(e) {
return this.currentPage === e
}, $l.prototype.setPage = function(e) {
e === this.currentPage && this.hasPage(e) || this.page.next(this.pagination.currentPage = e)
}, $l.prototype.nextPage = function() {
this.currentPage !== this.pagination.lastPage && this.setPage(this.pagination.currentPage + 1)
}, $l.prototype.prevPage = function() {
1 < this.pagination.currentPage && this.setPage(this.pagination.currentPage - 1)
}, $l.prototype.setLastPage = function() {
this.setPage(this.pagination.lastPage)
}, $l.prototype.setFirstPage = function() {
this.setPage(1)
}, $l.prototype.hasPage = function(e) {
return this.pages.has(e)
}, $l.prototype.getPage = function(e) {
var t = this,
i = this.pagination.currentPage;
return this.hasPage(i) ? this.selectPage(i) : (this.setLoading(!0), Fr(e()).pipe(La(function(e) {
return i = e.currentPage, al(function() {
t.setLoading(!1), t.update(e)
}), t.selectPage(i)
})))
}, $l.prototype.getQuery = function() {
return this.query
}, $l.prototype.refreshCurrentPage = function() {
!1 === Po(this.currentPage) && (this.clearPage(this.currentPage), this.setPage(this.currentPage))
}, $l.prototype.getFrom = function() {
return this.isFirst ? 1 : (this.currentPage - 1) * this.pagination.perPage + 1
}, $l.prototype.getTo = function() {
return this.isLast ? this.pagination.total : this.currentPage * this.pagination.perPage
}, $l.prototype.selectPage = function(n) {
var s = this;
return this.query.selectAll({
asObject: !0
}).pipe(Ds(1), hr(function(t) {
var e = ct({}, s.pagination, {
data: s.pages.get(n).ids.map(function(e) {
return t[e]
})
}),
i = s.config,
r = i.range,
i = i.pagesControls;
return isNaN(s.pagination.total) && (1 === e.lastPage ? e.total = e.data ? e.data.length : 0 : e.total = e.perPage * e.lastPage, s.pagination.total = e.total), r && (e.from = s.getFrom(), e.to = s.getTo()), i && (e.pageControls = function(e, t) {
for (var i = Math.ceil(e / t), r = [], n = 0; n < i; n++) r.push(n + 1);
return r
}(s.pagination.total, s.pagination.perPage)), e
}))
}, ht([(_l = "@Pagination - New Page", function(e, t, i) {
var r = i.value;
return i.value = function() {
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
return Do(_l, Nl), r.apply(this, e)
}, i
}), pt("design:type", Function), pt("design:paramtypes", [Object]), pt("design:returntype", void 0)], $l.prototype, "update", null), ut(Ul, Rl = A), Ul.prototype.setForm = function(e, t) {
return this.form = e, this.builder = t, this.activate(), this
}, Ul.prototype.reset = function(e) {
var r = this,
e = e || (this.isKeyBased ? this.initialValue : this.factoryFnOrPath());
this.isKeyBased && Object.keys(this.initialValue).forEach(function(i) {
var e, t = r.initialValue[i];
Array.isArray(t) && r.builder && (e = r.form.controls[i], r.cleanArray(e), t.forEach(function(e, t) {
r.form.get(i).insert(t, r.params.arrControlFactory(e))
}))
}), this.form.patchValue(e, {
emitEvent: this.params.emitEvent
});
var t = this.isKeyBased ? Pl(this.getQuery().getValue(), this.getStore().storeName + "." + this.factoryFnOrPath, e) : ((t = {})[this.params.formKey] = e, t);
this.updateStore(t)
}, Ul.prototype.cleanArray = function(e) {
for (; 0 !== e.length;) e.removeAt(0)
}, Ul.prototype.resolveInitialValue = function(e, n) {
var s = this;
if (e) return Object.keys(e).reduce(function(e, i) {
var r, t = n[i];
return Array.isArray(t) && s.builder && (r = s.params.arrControlFactory, s.cleanArray(s.form.get(i)), t.forEach(function(e, t) {
s.form.get(i).insert(t, r(e))
})), e[i] = n[i], e
}, {})
}, Ul.prototype.activate = function() {
var i, e, t, r = this;
this.isKeyBased ? (this.isRootKeys ? this.initialValue = this.resolveInitialValue(this.form.value, this.getQuery().getValue()) : (i = this.getStore().storeName + "." + this.factoryFnOrPath, e = xl(this.getQuery().getValue(), i), this.initialValue = this.resolveInitialValue(e, e)), this.form.patchValue(this.initialValue, {
emitEvent: this.params.emitEvent
})) : (this.getQuery().getValue()[this.params.formKey] || (Do("@PersistNgFormPlugin activate"), this.updateStore(((t = {})[this.params.formKey] = this.factoryFnOrPath(), t))), t = this.getQuery().getValue()[this.params.formKey], this.form.patchValue(t)), this.formChanges = this.form.valueChanges.pipe(Gn(this.params.debounceTime)).subscribe(function(t) {
var e;
Do("@PersistForm - Update"), e = r.isKeyBased ? r.isRootKeys ? function(e) {
return ct({}, e, t)
} : function(e) {
return Pl(e, i, t)
} : function() {
var e;
return (e = {})[r.params.formKey] = t, e
}, r.updateStore(e(r.getQuery().getValue()))
})
}, Ul.prototype.destroy = function() {
this.formChanges && this.formChanges.unsubscribe(), this.form = null, this.builder = null
};
var Vl, Kl, Vr = (jl.prototype.getEntity = function(e) {
return this.entities.get(e)
}, jl.prototype.hasEntity = function(e) {
return this.entities.has(e)
}, jl.prototype.removeEntity = function(e) {
return this.destroy(e), this.entities.delete(e)
}, jl.prototype.createEntity = function(e, t) {
return this.entities.set(e, t)
}, jl.prototype.getIds = function() {
return Vo(this.entityIds) ? this.query.getValue().ids : Ro(this.entityIds)
}, jl.prototype.resolvedIds = function(e) {
return Vo(e) ? this.getIds() : Ro(e)
}, jl.prototype.rebase = function(i, r) {
var n = this;
if (void 0 === r && (r = {}), Jo(i))
if (Vo(this.entityIds)) {
for (var e = 0, t = i.length; e < t; e++) {
var s, a = i[e];
!1 === this.hasEntity(a) && ($o(r.beforeAdd) && r.beforeAdd(a), s = this.instantiatePlugin(a), this.entities.set(a, s), $o(r.afterAdd) && r.afterAdd(s))
}
this.entities.forEach(function(e, t) {
-1 === i.indexOf(t) && ($o(r.beforeRemove) && r.beforeRemove(e), n.removeEntity(t))
})
} else
for (var o = Ro(this.entityIds), e = 0, t = o.length; e < t; e++) a = o[e], -1 < i.indexOf(a) && !1 === this.hasEntity(a) ? ($o(r.beforeAdd) && r.beforeAdd(a), s = this.instantiatePlugin(a), this.entities.set(a, s), $o(r.afterAdd) && r.afterAdd(s)) : this.entities.forEach(function(e, t) {
-1 === i.indexOf(t) && !0 === n.hasEntity(t) && ($o(r.beforeRemove) && r.beforeRemove(e), n.removeEntity(t))
});
else this.getIds().forEach(function(e) {
n.hasEntity(e) || n.createEntity(e, n.instantiatePlugin(e))
})
}, jl.prototype.selectIds = function() {
return this.query.select(function(e) {
return e.ids
})
}, jl.prototype.activate = function(e) {
this.rebase(e)
}, jl.prototype.forEachId = function(e, t) {
for (var i = this.resolvedIds(e), r = 0, n = i.length; r < n; r++) {
var s = i[r];
this.hasEntity(s) && t(this.getEntity(s))
}
}, jl),
ql = (ut(Hl, Vl = A), Object.defineProperty(Hl.prototype, "hasPast$", {
get: function() {
return this._hasPast$
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(Hl.prototype, "hasFuture$", {
get: function() {
return this._hasFuture$
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(Hl.prototype, "hasPast", {
get: function() {
return 0 < this.history.past.length
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(Hl.prototype, "hasFuture", {
get: function() {
return 0 < this.history.future.length
},
enumerable: !0,
configurable: !0
}), Object.defineProperty(Hl.prototype, "property", {
get: function() {
return this.params.watchProperty
},
enumerable: !0,
configurable: !0
}), Hl.prototype.updateHasHistory = function() {
this.hasFutureSubject.next(this.hasFuture), this.hasPastSubject.next(this.hasPast)
}, Hl.prototype.activate = function() {
var r = this;
this.hasPastSubject = new yi(!1), this._hasPast$ = this.hasPastSubject.asObservable().pipe(Is()), this.hasFutureSubject = new yi(!1), this._hasFuture$ = this.hasFutureSubject.asObservable().pipe(Is()), this.history.present = this.getSource(this._entityId, this.property), this.subscription = this.selectSource(this._entityId, this.property).pipe(ha()).subscribe(function(e) {
var t = mt(e, 2),
i = t[0],
e = t[1];
r.skip ? r.skip = !1 : (t = r.params.comparator(i, e), !r.skipUpdate && t && (r.history.past.length === r.params.maxAge && (r.history.past = r.history.past.slice(1)), r.history.past = gt(r.history.past, [i]), r.history.present = e, r.updateHasHistory()))
})
}, Hl.prototype.undo = function() {
var e, t, i;
0 < this.history.past.length && (e = (i = this.history).past, t = i.present, i = e[e.length - 1], this.history.past = e.slice(0, e.length - 1), this.history.present = i, this.history.future = gt([t], this.history.future), this.update())
}, Hl.prototype.redo = function() {
var e, t, i, r;
0 < this.history.future.length && (e = (r = this.history).past, t = r.present, i = this.history.future[0], r = this.history.future.slice(1), this.history.past = gt(e, [t]), this.history.present = i, this.history.future = r, this.update("Redo"))
}, Hl.prototype.jumpToPast = function(e) {
var t, i, r, n;
e < 0 || e >= this.history.past.length || (t = (r = this.history).past, n = r.future, i = r.present, r = t.slice(0, e), n = gt(t.slice(e + 1), [i], n), e = t[e], this.history.past = r, this.history.present = e, this.history.future = n, this.update())
}, Hl.prototype.jumpToFuture = function(e) {
var t, i, r;
e < 0 || e >= this.history.future.length || (i = (r = this.history).past, t = r.future, i = gt(i, [r.present], t.slice(0, e)), r = t[e], e = t.slice(e + 1), this.history.past = i, this.history.present = r, this.history.future = e, this.update("Redo"))
}, Hl.prototype.jump = function(e) {
return 0 < e ? this.jumpToFuture(e - 1) : e < 0 ? this.jumpToPast(this.history.past.length + e) : void 0
}, Hl.prototype.clear = function(e) {
this.history = $o(e) ? e(this.history) : {
past: [],
present: null,
future: []
}, this.updateHasHistory()
}, Hl.prototype.destroy = function(e) {
(e = void 0 === e ? !1 : e) && this.clear(), this.subscription.unsubscribe()
}, Hl.prototype.ignoreNext = function() {
this.skip = !0
}, Hl.prototype.update = function(e) {
void 0 === e && (e = "Undo"), this.skipUpdate = !0, Do("@StateHistory - " + e), this.updateStore(this.history.present, this._entityId, this.property), this.updateHasHistory(), this.skipUpdate = !1
}, Hl);
function Hl(e, t, i) {
void 0 === t && (t = {});
var r = Vl.call(this, e, {
resetFn: function() {
return r.clear()
}
}) || this;
return r.query = e, r.params = t, r._entityId = i, r.skip = !1, r.history = {
past: [],
present: null,
future: []
}, r.skipUpdate = !1, t.maxAge = t.maxAge || 10, t.comparator = t.comparator || function() {
return !0
}, r.activate(), r
}
function jl(e, t) {
this.query = e, this.entityIds = t, this.entities = new Map
}
function Ql(e, t) {
var i = Kl.call(this, e, (t = void 0 === t ? {} : t).entityIds) || this;
return i.query = e, (i.params = t).maxAge = Jo(t.maxAge) ? t.maxAge : 10, i.activate(), i.selectIds().pipe(ka(1)).subscribe(function(e) {
return i.activate(e)
}), i
}
ut(Ql, Kl = Vr), Ql.prototype.redo = function(e) {
this.forEachId(e, function(e) {
return e.redo()
})
}, Ql.prototype.undo = function(e) {
this.forEachId(e, function(e) {
return e.undo()
})
}, Ql.prototype.hasPast = function(e) {
if (this.hasEntity(e)) return this.getEntity(e).hasPast
}, Ql.prototype.hasFuture = function(e) {
if (this.hasEntity(e)) return this.getEntity(e).hasFuture
}, Ql.prototype.jumpToFuture = function(e, t) {
this.forEachId(e, function(e) {
return e.jumpToFuture(t)
})
}, Ql.prototype.jumpToPast = function(e, t) {
this.forEachId(e, function(e) {
return e.jumpToPast(t)
})
}, Ql.prototype.clear = function(e) {
this.forEachId(e, function(e) {
return e.clear()
})
}, Ql.prototype.destroy = function(e, t) {
void 0 === t && (t = !1), this.forEachId(e, function(e) {
return e.destroy(t)
})
}, Ql.prototype.ignoreNext = function(e) {
this.forEachId(e, function(e) {
return e.ignoreNext()
})
}, Ql.prototype.instantiatePlugin = function(e) {
return new ql(this.query, this.params, e)
};
var Wl = {
comparator: function(e, t) {
return JSON.stringify(e) !== JSON.stringify(t)
}
};
function Gl(e, t) {
return t.split(".").reduce(function(e, t) {
return e && "undefined" !== e[t] ? e[t] : void 0
}, e)
}
var zl, Xl, Yl = (ut(Jl, zl = A), Jl.prototype.reset = function(e) {
var t = this.head;
$o((e = void 0 === e ? {} : e).updateFn) && (t = this.isEntityBased(this._entityId) ? e.updateFn(this.head, this.getQuery().getEntity(this._entityId)) : e.updateFn(this.head, this.getQuery().getValue())), Do("@DirtyCheck - Revert"), this.updateStore(t, this._entityId), this._reset.next()
}, Jl.prototype.setHead = function() {
return this.active ? this.head = this._getHead() : (this.activate(), this.active = !0), this.updateDirtiness(!1), this
}, Jl.prototype.isDirty = function() {
return !!this.dirty.value
}, Jl.prototype.hasHead = function() {
return !!this.getHead()
}, Jl.prototype.destroy = function() {
this.head = null, this.subscription && this.subscription.unsubscribe(), this._reset && this._reset.complete()
}, Jl.prototype.isPathDirty = function(e) {
var t = this.getHead(),
i = Gl(this.getQuery().getValue(), e),
e = Gl(t, e);
return this.params.comparator(i, e)
}, Jl.prototype.getHead = function() {
return this.head
}, Jl.prototype.activate = function() {
var i = this;
this.head = this._getHead();
var e = this.params.watchProperty ? this.params.watchProperty.map(function(t) {
return i.query.select(function(e) {
return e[t]
}).pipe(hr(function(e) {
return {
val: e,
__akitaKey: t
}
}))
}) : [this.selectSource(this._entityId)];
this.subscription = Mr.apply(void 0, gt(e)).pipe(ka(1)).subscribe(function(e) {
Vo(i.head) || (e = e.some(function(e) {
var t = e.__akitaKey ? i.head[e.__akitaKey] : i.head,
e = e.__akitaKey ? e.val : e;
return i.params.comparator(t, e)
}), i.updateDirtiness(e))
})
}, Jl.prototype.updateDirtiness = function(e) {
this.dirty.next(e)
}, Jl.prototype._getHead = function() {
var e = this.getSource(this._entityId);
return e = this.params.watchProperty ? this.getWatchedValues(e) : e
}, Jl.prototype.getWatchedValues = function(i) {
return this.params.watchProperty.reduce(function(e, t) {
return e[t] = i[t], e
}, {})
}, Jl);
function Jl(e, t, i) {
var r = zl.call(this, e) || this;
return r.query = e, r.params = t, r._entityId = i, r.dirty = new yi(!1), r.active = !1, r._reset = new Xt, r.isDirty$ = r.dirty.asObservable().pipe(Is()), r.reset$ = r._reset.asObservable(), r.params = ct({}, Wl, t), r.params.watchProperty && (t = Ro(r.params.watchProperty), e instanceof kl && t.includes("entities") && !t.includes("ids") && t.push("ids"), r.params.watchProperty = t), r
}
function Zl() {
return Math.random().toString(36).slice(2)
}
function ed(e) {
return Mr(e).pipe($n(0))
}
function td(e, t) {
var i = Xl.call(this, e, (t = void 0 === t ? {} : t).entityIds) || this;
return i.query = e, i.params = t, i._someDirty = new Xt, i.someDirty$ = an(i.query.select(function(e) {
return e.entities
}), i._someDirty.asObservable()).pipe($n(0), hr(function() {
return i.checkSomeDirty()
})), i.params = ct({}, Wl, t), i.activate(), i.selectIds().pipe(ka(1)).subscribe(function(e) {
Xl.prototype.rebase.call(i, e, {
afterAdd: function(e) {
return e.setHead()
}
})
}), i
}
ut(td, Xl = Vr), td.prototype.setHead = function(e) {
if (this.params.entityIds && e) {
var t = Ro(e);
if (!1 === Ro(this.params.entityIds).some(function(e) {
return -1 < t.indexOf(e)
})) return this
}
return this.forEachId(e, function(e) {
return e.setHead()
}), this._someDirty.next(), this
}, td.prototype.hasHead = function(e) {
return !!this.entities.has(e) && this.getEntity(e).hasHead()
}, td.prototype.reset = function(e, t) {
void 0 === t && (t = {}), this.forEachId(e, function(e) {
return e.reset(t)
})
}, td.prototype.isDirty = function(e, t) {
if (void 0 === t && (t = !0), this.entities.has(e)) {
e = this.getEntity(e);
return t ? e.isDirty$ : e.isDirty()
}
return !1
}, td.prototype.someDirty = function() {
return this.checkSomeDirty()
}, td.prototype.isPathDirty = function(e, t) {
if (this.entities.has(e)) {
var i = this.getEntity(e).getHead(),
e = Gl(this.query.getEntity(e), t),
t = Gl(i, t);
return this.params.comparator(e, t)
}
return null
}, td.prototype.destroy = function(e) {
this.forEachId(e, function(e) {
return e.destroy()
}), e || this._someDirty.complete()
}, td.prototype.instantiatePlugin = function(e) {
return new Yl(this.query, this.params, e)
}, td.prototype.checkSomeDirty = function() {
var e, t, i = this.resolvedIds();
try {
for (var r = ft(i), n = r.next(); !n.done; n = r.next()) {
var s = n.value;
if (this.getEntity(s).isDirty()) return !0
}
} catch (t) {
e = {
error: t
}
} finally {
try {
n && !n.done && (t = r.return) && t.call(r)
} finally {
if (e) throw e.error
}
}
return !1
}, (tu = tu || {}).Update = "UPDATE", {} [tu.Update] = "update", (vr = ru = ru || {}).Update = "UPDATE", vr.AddEntities = "ADD_ENTITIES", vr.SetEntities = "SET_ENTITIES", vr.UpdateEntities = "UPDATE_ENTITIES", vr.RemoveEntities = "REMOVE_ENTITIES", vr.UpsertEntities = "UPSERT_ENTITIES", vr.UpsertManyEntities = "UPSERT_MANY_ENTITIES", (iu = {})[ru.Update] = "update", iu[ru.AddEntities] = "add", iu[ru.SetEntities] = "set", iu[ru.UpdateEntities] = "update", iu[ru.RemoveEntities] = "remove", iu[ru.UpsertEntities] = "upsert", iu[ru.UpsertManyEntities] = "upsertMany";
w = {};
Object.defineProperty(w, "__esModule", {
value: !0
});
var vi = "undefined" != typeof Symbol && "symbol" == typeof Symbol("x"),
id = "undefined" != typeof Map,
rd = "undefined" != typeof Set,
nd = "undefined" != typeof Proxy && void 0 !== Proxy.revocable && "undefined" != typeof Reflect,
sd = vi ? Symbol.for("immer-nothing") : ((nu = {})["immer-nothing"] = !0, nu),
ad = vi ? Symbol.for("immer-draftable") : "__$immer_draftable",
od = vi ? Symbol.for("immer-state") : "__$immer_state",
ld = "undefined" != typeof Symbol && Symbol.iterator || "@@iterator",
dd = {
0: "Illegal state",
1: "Immer drafts cannot have computed properties",
2: "This object has been frozen and should not be mutated",
3: function(e) {
return "Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " + e
},
4: "An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.",
5: "Immer forbids circular references",
6: "The first or second argument to `produce` must be a function",
7: "The third argument to `produce` must be a function or undefined",
8: "First argument to `createDraft` must be a plain object, an array, or an immerable object",
9: "First argument to `finishDraft` must be a draft returned by `createDraft`",
10: "The given draft is already finalized",
11: "Object.defineProperty() cannot be used on an Immer draft",
12: "Object.setPrototypeOf() cannot be used on an Immer draft",
13: "Immer only supports deleting array indices",
14: "Immer only supports setting array indices and the 'length' property",
15: function(e) {
return "Cannot apply patch, path doesn't resolve: " + e
},
16: 'Sets cannot have "replace" patches.',
17: function(e) {
return "Unsupported patch operation: " + e
},
18: function(e) {
return "The plugin for '" + e + "' has not been loaded into Immer. To enable the plugin, import and call `enable" + e + "()` when initializing your application."
},
20: "Cannot use proxies if Proxy, Proxy.revocable or Reflect are not available",
21: function(e) {
return "produce can only be called on things that are draftable: plain objects, arrays, Map, Set or classes that are marked with '[immerable]: true'. Got '" + e + "'"
},
22: function(e) {
return "'current' expects a draft, got: " + e
},
23: function(e) {
return "'original' expects a draft, got: " + e
}
};
function ud(e) {
for (var t = arguments.length, i = new Array(1 < t ? t - 1 : 0), r = 1; r < t; r++) i[r - 1] = arguments[r];
var n = dd[e],
e = n ? "function" == typeof n ? n.apply(null, i) : n : "unknown error nr: " + e;
throw new Error("[Immer] " + e)
}
function cd(e) {
return !!e && !!e[od]
}
function hd(t) {
return !!t && (function() {
if (!t || "object" != typeof t) return !1;
var e = Object.getPrototypeOf(t);
return !e || e === Object.prototype
}() || Array.isArray(t) || !!t[ad] || !!t.constructor[ad] || Td(t) || Ed(t))
}
var pd = "undefined" != typeof Reflect && Reflect.ownKeys ? Reflect.ownKeys : void 0 !== Object.getOwnPropertySymbols ? function(e) {
return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))
} : Object.getOwnPropertyNames,
fd = Object.getOwnPropertyDescriptors || function(t) {
var i = {};
return pd(t).forEach(function(e) {
i[e] = Object.getOwnPropertyDescriptor(t, e)
}), i
};
function md(i, r, t) {
void 0 === t && (t = !1), 0 === gd(i) ? (t ? Object.keys : pd)(i).forEach(function(e) {
t && "symbol" == typeof e || r(e, i[e], i)
}) : i.forEach(function(e, t) {
return r(t, e, i)
})
}
function gd(e) {
var t = e[od];
return t ? 3 < t.type_ ? t.type_ - 4 : t.type_ : Array.isArray(e) ? 1 : Td(e) ? 2 : Ed(e) ? 3 : 0
}
function yd(e, t) {
return 2 === gd(e) ? e.has(t) : Object.prototype.hasOwnProperty.call(e, t)
}
function vd(e, t) {
return 2 === gd(e) ? e.get(t) : e[t]
}
function Sd(e, t, i) {
var r = gd(e);
2 === r ? e.set(t, i) : 3 === r ? (e.delete(t), e.add(i)) : e[t] = i
}
function bd(e, t) {
return e === t ? 0 !== e || 1 / e == 1 / t : e != e && t != t
}
function Td(e) {
return id && e instanceof Map
}
function Ed(e) {
return rd && e instanceof Set
}
function Id(e) {
return e.copy_ || e.base_
}
function wd(e) {
if (Array.isArray(e)) return Array.prototype.slice.call(e);
var t = fd(e);
delete t[od];
for (var i = pd(t), r = 0; r < i.length; r++) {
var n = i[r],
s = t[n];
!1 === s.writable && (s.writable = !0, s.configurable = !0), (s.get || s.set) && (t[n] = {
configurable: !0,
writable: !0,
enumerable: s.enumerable,
value: e[n]
})
}
return Object.create(Object.getPrototypeOf(e), t)
}
function Ad(e, t) {
kd(e) || cd(e) || !hd(e) || (1 < gd(e) && (e.set = e.add = e.clear = e.delete = Od), Object.freeze(e), t && md(e, function(e, t) {
return Ad(t, !0)
}, !0))
}
function Od() {
ud(2)
}
function kd(e) {
return null == e || "object" != typeof e || Object.isFrozen(e)
}
var Cd, Dd = {};
function Md(e) {
var t = Dd[e];
return t || ud(18, e), t
}
function xd(e, t) {
Dd[e] || (Dd[e] = t)
}
function Pd() {
return Cd || ud(0), Cd
}
function Rd(e, t) {
t && (Md("Patches"), e.patches_ = [], e.inversePatches_ = [], e.patchListener_ = t)
}
function Ld(e) {
_d(e), e.drafts_.forEach(Fd), e.drafts_ = null
}
function _d(e) {
e === Cd && (Cd = e.parent_)
}
function Nd(e) {
return Cd = {
drafts_: [],
parent_: Cd,
immer_: e,
canAutoFreeze_: !0,
unfinalizedDrafts_: 0
}
}
function Fd(e) {
e = e[od];
0 === e.type_ || 1 === e.type_ ? e.revoke_() : e.revoked_ = !0
}
function Bd(e, t) {
t.unfinalizedDrafts_ = t.drafts_.length;
var i = t.drafts_[0],
r = void 0 !== e && e !== i;
return t.immer_.useProxies_ || Md("ES5").willFinalizeES5_(t, e, r), r ? (i[od].modified_ && (Ld(t), ud(4)), hd(e) && (e = Ud(t, e), t.parent_ || Vd(t, e)), t.patches_ && Md("Patches").generateReplacementPatches_(i[od], e, t.patches_, t.inversePatches_)) : e = Ud(t, i, []), Ld(t), t.patches_ && t.patchListener_(t.patches_, t.inversePatches_), e !== sd ? e : void 0
}
function Ud(i, r, n) {
if (kd(r)) return r;
var s, a = r[od];
return a ? a.scope_ !== i ? r : a.modified_ ? (a.finalized_ || (a.finalized_ = !0, a.scope_.unfinalizedDrafts_--, s = 4 === a.type_ || 5 === a.type_ ? a.copy_ = wd(a.draft_) : a.copy_, md(3 === a.type_ ? new Set(s) : s, function(e, t) {
return $d(i, a, s, e, t, n)
}), Vd(i, s, !1), n && i.patches_ && Md("Patches").generatePatches_(a, n, i.patches_, i.inversePatches_)), a.copy_) : (Vd(i, a.base_, !0), a.base_) : (md(r, function(e, t) {
return $d(i, a, r, e, t, n)
}, !0), r)
}
function $d(e, t, i, r, n, s) {
if (n === i && ud(5), cd(n)) {
s = Ud(e, n, s && t && 3 !== t.type_ && !yd(t.assigned_, r) ? s.concat(r) : void 0);
if (Sd(i, r, s), !cd(s)) return;
e.canAutoFreeze_ = !1
}
hd(n) && !kd(n) && (!e.immer_.autoFreeze_ && e.unfinalizedDrafts_ < 1 || (Ud(e, n), t && t.scope_.parent_ || Vd(e, n)))
}
function Vd(e, t, i) {
void 0 === i && (i = !1), e.immer_.autoFreeze_ && e.canAutoFreeze_ && Ad(t, i)
}
var Kd = {
get: function(e, t) {
if (t === od) return e;
var i, r, n = Id(e);
if (!yd(n, t)) return i = e, (r = jd(n, t)) ? "value" in r ? r.value : null === (r = r.get) || void 0 === r ? void 0 : r.call(i.draft_) : void 0;
n = n[t];
return !e.finalized_ && hd(n) && n === Hd(e.base_, t) ? (Wd(e), e.copy_[t] = zd(e.scope_.immer_, n, e)) : n
},
has: function(e, t) {
return t in Id(e)
},
ownKeys: function(e) {
return Reflect.ownKeys(Id(e))
},
set: function(e, t, i) {
var r = jd(Id(e), t);
if (null != r && r.set) return r.set.call(e.draft_, i), !0;
if (!e.modified_) {
var n = Hd(Id(e), t),
r = null == n ? void 0 : n[od];
if (r && r.base_ === i) return e.copy_[t] = i, !(e.assigned_[t] = !1);
if (bd(i, n) && (void 0 !== i || yd(e.base_, t))) return !0;
Wd(e), Qd(e)
}
return e.copy_[t] = i, e.assigned_[t] = !0
},
deleteProperty: function(e, t) {
return void 0 !== Hd(e.base_, t) || t in e.base_ ? (e.assigned_[t] = !1, Wd(e), Qd(e)) : delete e.assigned_[t], e.copy_ && delete e.copy_[t], !0
},
getOwnPropertyDescriptor: function(e, t) {
var i = Id(e),
r = Reflect.getOwnPropertyDescriptor(i, t);
return r && {
writable: !0,
configurable: 1 !== e.type_ || "length" !== t,
enumerable: r.enumerable,
value: i[t]
}
},
defineProperty: function() {
ud(11)
},
getPrototypeOf: function(e) {
return Object.getPrototypeOf(e.base_)
},
setPrototypeOf: function() {
ud(12)
}
},
qd = {};
function Hd(e, t) {
var i = e[od];
return (i ? Id(i) : e)[t]
}
function jd(e, t) {
if (t in e)
for (var i = Object.getPrototypeOf(e); i;) {
var r = Object.getOwnPropertyDescriptor(i, t);
if (r) return r;
i = Object.getPrototypeOf(i)
}
}
function Qd(e) {
e.modified_ || (e.modified_ = !0, e.parent_ && Qd(e.parent_))
}
function Wd(e) {
e.copy_ || (e.copy_ = wd(e.base_))
}
md(Kd, function(e, t) {
qd[e] = function() {
return arguments[0] = arguments[0][0], t.apply(this, arguments)
}
}), qd.deleteProperty = function(e, t) {
return isNaN(parseInt(t)) && ud(13), Kd.deleteProperty.call(this, e[0], t)
}, qd.set = function(e, t, i) {
return "length" !== t && isNaN(parseInt(t)) && ud(14), Kd.set.call(this, e[0], t, i, e[0])
};
(A = Gd.prototype).produce = function(e, s, t) {
if ("function" == typeof e && "function" != typeof s) {
var a = s;
s = e;
var o = this;
return function(e) {
var t = this;
void 0 === e && (e = a);
for (var i = arguments.length, r = new Array(1 < i ? i - 1 : 0), n = 1; n < i; n++) r[n - 1] = arguments[n];
return o.produce(e, function(e) {
return s.call.apply(s, [t, e].concat(r))
})
}
}
var i;
if ("function" != typeof s && ud(6), void 0 !== t && "function" != typeof t && ud(7), hd(e)) {
var r = Nd(this),
n = zd(this, e, void 0),
l = !0;
try {
i = s(n), l = !1
} finally {
(l ? Ld : _d)(r)
}
return "undefined" != typeof Promise && i instanceof Promise ? i.then(function(e) {
return Rd(r, t), Bd(e, r)
}, function(e) {
throw Ld(r), e
}) : (Rd(r, t), Bd(i, r))
}
if (!e || "object" != typeof e) return (i = s(e)) === sd ? void 0 : (void 0 === i && (i = e), this.autoFreeze_ && Ad(i, !0), i);
ud(21, e)
}, A.produceWithPatches = function(n, e, t) {
var i, r, s = this;
return "function" == typeof n ? function(e) {
for (var t = arguments.length, i = new Array(1 < t ? t - 1 : 0), r = 1; r < t; r++) i[r - 1] = arguments[r];
return s.produceWithPatches(e, function(e) {
return n.apply(void 0, [e].concat(i))
})
} : [this.produce(n, e, function(e, t) {
i = e, r = t
}), i, r]
}, A.createDraft = function(e) {
hd(e) || ud(8), cd(e) && (e = Xd(e));
var t = Nd(this),
e = zd(this, e, void 0);
return e[od].isManual_ = !0, _d(t), e
}, A.finishDraft = function(e, t) {
e = e && e[od];
e && e.isManual_ || ud(9), e.finalized_ && ud(10);
e = e.scope_;
return Rd(e, t), Bd(void 0, e)
}, A.setAutoFreeze = function(e) {
this.autoFreeze_ = e
}, A.setUseProxies = function(e) {
e && !nd && ud(20), this.useProxies_ = e
}, A.applyPatches = function(e, t) {
for (var i = t.length - 1; 0 <= i; i--) {
var r = t[i];
if (0 === r.path.length && "replace" === r.op) {
e = r.value;
break
}
}
var n = Md("Patches").applyPatches_;
return cd(e) ? n(e, t) : this.produce(e, function(e) {
return n(e, t.slice(i + 1))
})
}, Vr = Gd;
function Gd(e) {
this.useProxies_ = nd, this.autoFreeze_ = !0, "boolean" == typeof(null == e ? void 0 : e.useProxies) && this.setUseProxies(e.useProxies), "boolean" == typeof(null == e ? void 0 : e.autoFreeze) && this.setAutoFreeze(e.autoFreeze), this.produce = this.produce.bind(this), this.produceWithPatches = this.produceWithPatches.bind(this)
}
function zd(e, t, i) {
t = Td(t) ? Md("MapSet").proxyMap_(t, i) : Ed(t) ? Md("MapSet").proxySet_(t, i) : e.useProxies_ ? function(e, t) {
var i = Array.isArray(e),
r = {
type_: i ? 1 : 0,
scope_: t ? t.scope_ : Pd(),
modified_: !1,
finalized_: !1,
assigned_: {},
parent_: t,
base_: e,
draft_: null,
copy_: null,
revoke_: null,
isManual_: !1
},
t = r,
e = Kd;
i && (t = [r], e = qd);
t = Proxy.revocable(t, e), e = t.revoke, t = t.proxy;
return r.draft_ = t, r.revoke_ = e, t
}(t, i) : Md("ES5").createES5Proxy_(t, i);
return (i ? i.scope_ : Pd()).drafts_.push(t), t
}
function Xd(e) {
return cd(e) || ud(22, e),
function i(e) {
if (!hd(e)) return e;
var r, n = e[od],
t = gd(e);
if (n) {
if (!n.modified_ && (n.type_ < 4 || !Md("ES5").hasChanges_(n))) return n.base_;
n.finalized_ = !0, r = Yd(e, t), n.finalized_ = !1
} else r = Yd(e, t);
return md(r, function(e, t) {
n && vd(n.base_, e) === t || Sd(r, e, i(t))
}), 3 === t ? new Set(r) : r
}(e)
}
function Yd(e, t) {
switch (t) {
case 2:
return new Map(e);
case 3:
return Array.from(e)
}
return wd(e)
}
function Jd() {
var r = {};
function l(i, e) {
var t = r[i];
return t ? t.enumerable = e : r[i] = t = {
configurable: !0,
enumerable: e,
get: function() {
var e = this[od];
return a(e), Kd.get(e, i)
},
set: function(e) {
var t = this[od];
a(t), Kd.set(t, i, e)
}
}, t
}
function n(e) {
for (var t = e.length - 1; 0 <= t; t--) {
var i = e[t][od];
if (!i.modified_) switch (i.type_) {
case 5:
u(i) && Qd(i);
break;
case 4:
s(i) && Qd(i)
}
}
}
function s(e) {
for (var t = e.base_, i = e.draft_, r = pd(i), n = r.length - 1; 0 <= n; n--) {
var s = r[n];
if (s !== od) {
var a = t[s];
if (void 0 === a && !yd(t, s)) return !0;
var o = i[s],
s = o && o[od];
if (s ? s.base_ !== a : !bd(o, a)) return !0
}
}
e = !!t[od];
return r.length !== pd(t).length + (e ? 0 : 1)
}
function u(e) {
var t = e.draft_;
if (t.length !== e.base_.length) return !0;
t = Object.getOwnPropertyDescriptor(t, t.length - 1);
return !(!t || t.get)
}
function a(e) {
e.revoked_ && ud(3, JSON.stringify(Id(e)))
}
xd("ES5", {
createES5Proxy_: function(e, t) {
var i = Array.isArray(e),
r = function(e, t) {
if (e) {
for (var i = new Array(t.length), r = 0; r < t.length; r++) Object.defineProperty(i, "" + r, l(r, !0));
return i
}
var n = fd(t);
delete n[od];
for (var s = pd(n), a = 0; a < s.length; a++) {
var o = s[a];
n[o] = l(o, e || !!n[o].enumerable)
}
return Object.create(Object.getPrototypeOf(t), n)
}(i, e),
e = {
type_: i ? 5 : 4,
scope_: t ? t.scope_ : Pd(),
modified_: !1,
finalized_: !1,
assigned_: {},
parent_: t,
base_: e,
draft_: r,
copy_: null,
revoked_: !1,
isManual_: !1
};
return Object.defineProperty(r, od, {
value: e,
writable: !0
}), r
},
willFinalizeES5_: function(e, t, i) {
i ? cd(t) && t[od].scope_ === e && n(e.drafts_) : (e.patches_ && function t(e) {
if (e && "object" == typeof e) {
var i = e[od];
if (i) {
var r = i.base_,
n = i.draft_,
s = i.assigned_;
if (4 === (e = i.type_)) md(n, function(e) {
e !== od && (void 0 !== r[e] || yd(r, e) ? s[e] || t(n[e]) : (s[e] = !0, Qd(i)))
}), md(r, function(e) {
void 0 !== n[e] || yd(n, e) || (s[e] = !1, Qd(i))
});
else if (5 === e) {
if (u(i) && (Qd(i), s.length = !0), n.length < r.length)
for (var a = n.length; a < r.length; a++) s[a] = !1;
else
for (var o = r.length; o < n.length; o++) s[o] = !0;
for (var l = Math.min(n.length, r.length), d = 0; d < l; d++) void 0 === s[d] && t(n[d])
}
}
}
}(e.drafts_[0]), n(e.drafts_))
},
hasChanges_: function(e) {
return (4 === e.type_ ? s : u)(e)
}
})
}
function Zd() {
var m = "replace",
g = "add",
y = "remove";
function d(e) {
if (!hd(e)) return e;
if (Array.isArray(e)) return e.map(d);
if (Td(e)) return new Map(Array.from(e.entries()).map(function(e) {
return [e[0], d(e[1])]
}));
if (Ed(e)) return new Set(Array.from(e).map(d));
var t, i = Object.create(Object.getPrototypeOf(e));
for (t in e) i[t] = d(e[t]);
return i
}
function v(e) {
return cd(e) ? d(e) : e
}
xd("Patches", {
applyPatches_: function(l, e) {
return e.forEach(function(e) {
for (var t = e.path, i = e.op, r = l, n = 0; n < t.length - 1; n++) "object" != typeof(r = vd(r, t[n])) && ud(15, t.join("/"));
var s = gd(r),
a = d(e.value),
o = t[t.length - 1];
switch (i) {
case m:
switch (s) {
case 2:
return r.set(o, a);
case 3:
ud(16);
default:
return r[o] = a
}
case g:
switch (s) {
case 1:
return r.splice(o, 0, a);
case 2:
return r.set(o, a);
case 3:
return r.add(a);
default:
return r[o] = a
}
case y:
switch (s) {
case 1:
return r.splice(o, 1);
case 2:
return r.delete(o);
case 3:
return r.delete(e.value);
default:
return delete r[o]
}
default:
ud(17, i)
}
}), l
},
generatePatches_: function(c, e, t, i) {
switch (c.type_) {
case 0:
case 4:
case 2:
return d = e, u = t, h = i, p = c.base_, f = c.copy_, void md(c.assigned_, function(e, t) {
var i = vd(p, e),
r = vd(f, e),
t = t ? yd(p, e) ? m : g : y;
i === r && t == m || (e = d.concat(e), u.push(t == y ? {
op: t,
path: e
} : {
op: t,
path: e,
value: r
}), h.push(t == g ? {
op: y,
path: e
} : t == y ? {
op: g,
path: e,
value: v(i)
} : {
op: m,
path: e,
value: v(i)
}))
});
case 5:
case 1:
return function(e, t, i) {
var r, n = c.base_,
s = c.assigned_,
a = c.copy_;
a.length < n.length && (n = (r = [a, n])[0], a = r[1], t = (r = [i, t])[0], i = r[1]);
for (var o, l = 0; l < n.length; l++) s[l] && a[l] !== n[l] && (o = e.concat([l]), t.push({
op: m,
path: o,
value: v(a[l])
}), i.push({
op: m,
path: o,
value: v(n[l])
}));
for (var d = n.length; d < a.length; d++) {
var u = e.concat([d]);
t.push({
op: g,
path: u,
value: v(a[d])
})
}
n.length < a.length && i.push({
op: m,
path: e.concat(["length"]),
value: n.length
})
}(e, t, i);
case 3:
return r = e, n = t, s = i, a = c.base_, o = c.copy_, l = 0, a.forEach(function(e) {
var t;
o.has(e) || (t = r.concat([l]), n.push({
op: y,
path: t,
value: e
}), s.unshift({
op: g,
path: t,
value: e
})), l++
}), l = 0, void o.forEach(function(e) {
var t;
a.has(e) || (t = r.concat([l]), n.push({
op: g,
path: t,
value: e
}), s.unshift({
op: y,
path: t,
value: e
})), l++
})
}
var r, n, s, a, o, l, d, u, h, p, f
},
generateReplacementPatches_: function(e, t, i, r) {
i.push({
op: m,
path: [],
value: t
}), r.push({
op: m,
path: [],
value: e.base_
})
}
})
}
function eu() {
var r = function(e, t) {
return (r = Object.setPrototypeOf || {
__proto__: []
}
instanceof Array && function(e, t) {
e.__proto__ = t
} || function(e, t) {
for (var i in t) t.hasOwnProperty(i) && (e[i] = t[i])
})(e, t)
};
function i(e, t) {
function i() {
this.constructor = e
}
r(e, t), e.prototype = (i.prototype = t.prototype, new i)
}
var n = function() {
function e(e, t) {
return this[od] = {
type_: 2,
parent_: t,
scope_: t ? t.scope_ : Pd(),
modified_: !1,
finalized_: !1,
copy_: void 0,
assigned_: void 0,
base_: e,
draft_: this,
isManual_: !1,
revoked_: !1
}, this
}
i(e, Map);
var t = e.prototype;
return Object.defineProperty(t, "size", {
get: function() {
return Id(this[od]).size
}
}), t.has = function(e) {
return Id(this[od]).has(e)
}, t.set = function(e, t) {
var i = this[od];
return l(i), Id(i).has(e) && Id(i).get(e) === t || (s(i), Qd(i), i.assigned_.set(e, !0), i.copy_.set(e, t), i.assigned_.set(e, !0)), this
}, t.delete = function(e) {
if (!this.has(e)) return !1;
var t = this[od];
return l(t), s(t), Qd(t), t.assigned_.set(e, !1), t.copy_.delete(e), !0
}, t.clear = function() {
var t = this[od];
l(t), Id(t).size && (s(t), Qd(t), t.assigned_ = new Map, md(t.base_, function(e) {
t.assigned_.set(e, !1)
}), t.copy_.clear())
}, t.forEach = function(r, n) {
var s = this;
Id(this[od]).forEach(function(e, t, i) {
r.call(n, s.get(t), t, s)
})
}, t.get = function(e) {
var t = this[od];
l(t);
var i = Id(t).get(e);
if (t.finalized_ || !hd(i)) return i;
if (i !== t.base_.get(e)) return i;
i = zd(t.scope_.immer_, i, t);
return s(t), t.copy_.set(e, i), i
}, t.keys = function() {
return Id(this[od]).keys()
}, t.values = function() {
var e, t = this,
i = this.keys();
return (e = {})[ld] = function() {
return t.values()
}, e.next = function() {
var e = i.next();
return e.done ? e : {
done: !1,
value: t.get(e.value)
}
}, e
}, t.entries = function() {
var e, i = this,
r = this.keys();
return (e = {})[ld] = function() {
return i.entries()
}, e.next = function() {
var e = r.next();
if (e.done) return e;
var t = i.get(e.value);
return {
done: !1,
value: [e.value, t]
}
}, e
}, t[ld] = function() {
return this.entries()
}, e
}();
function s(e) {
e.copy_ || (e.assigned_ = new Map, e.copy_ = new Map(e.base_))
}
var a = function() {
function e(e, t) {
return this[od] = {
type_: 3,
parent_: t,
scope_: t ? t.scope_ : Pd(),
modified_: !1,
finalized_: !1,
copy_: void 0,
base_: e,
draft_: this,
drafts_: new Map,
revoked_: !1,
isManual_: !1
}, this
}
i(e, Set);
var t = e.prototype;
return Object.defineProperty(t, "size", {
get: function() {
return Id(this[od]).size
}
}), t.has = function(e) {
var t = this[od];
return l(t), t.copy_ ? !!t.copy_.has(e) || !(!t.drafts_.has(e) || !t.copy_.has(t.drafts_.get(e))) : t.base_.has(e)
}, t.add = function(e) {
var t = this[od];
return l(t), this.has(e) || (o(t), Qd(t), t.copy_.add(e)), this
}, t.delete = function(e) {
if (!this.has(e)) return !1;
var t = this[od];
return l(t), o(t), Qd(t), t.copy_.delete(e) || !!t.drafts_.has(e) && t.copy_.delete(t.drafts_.get(e))
}, t.clear = function() {
var e = this[od];
l(e), Id(e).size && (o(e), Qd(e), e.copy_.clear())
}, t.values = function() {
var e = this[od];
return l(e), o(e), e.copy_.values()
}, t.entries = function() {
var e = this[od];
return l(e), o(e), e.copy_.entries()
}, t.keys = function() {
return this.values()
}, t[ld] = function() {
return this.values()
}, t.forEach = function(e, t) {
for (var i = this.values(), r = i.next(); !r.done;) e.call(t, r.value, r.value, this), r = i.next()
}, e
}();
function o(i) {
i.copy_ || (i.copy_ = new Set, i.base_.forEach(function(e) {
var t;
hd(e) ? (t = zd(i.scope_.immer_, e, i), i.drafts_.set(e, t), i.copy_.add(t)) : i.copy_.add(e)
}))
}
function l(e) {
e.revoked_ && ud(3, JSON.stringify(Id(e)))
}
xd("MapSet", {
proxyMap_: function(e, t) {
return new n(e, t)
},
proxySet_: function(e, t) {
return new a(e, t)
}
})
}
var tu = new Vr,
vr = tu.produce,
iu = tu.produceWithPatches.bind(tu),
ru = tu.setAutoFreeze.bind(tu),
nu = tu.setUseProxies.bind(tu),
vi = tu.applyPatches.bind(tu),
A = tu.createDraft.bind(tu),
tu = tu.finishDraft.bind(tu);
w.Immer = Vr, w.applyPatches = vi, w.castDraft = function(e) {
return e
}, w.castImmutable = function(e) {
return e
}, w.createDraft = A, w.current = Xd, w.default = vr, w.enableAllPlugins = function() {
Jd(), eu(), Zd()
}, w.enableES5 = Jd;
A = w.enableMapSet = eu;
w.enablePatches = Zd, w.finishDraft = tu, w.immerable = ad, w.isDraft = cd, w.isDraftable = hd, w.nothing = sd, w.original = function(e) {
return cd(e) || ud(23, e), e[od].base_
};
var su = w.produce = vr;
w.produceWithPatches = iu;
var au = w.setAutoFreeze = ru;
w.setUseProxies = nu;
const ou = /^((?:[^\/;?#]+:)?)(\/\/[^\/\;?#]*)?(.*?)??(;.*?)?(\?.*?)?(#.*?)?$/,
lu = /^([^\/;?#]*)(.*)$/,
du = /(?:\/|^)\.(?=\/)/g,
uu = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g,
cu = {
buildAbsoluteURL: function(e, t, i) {
if (i = i || {}, e = e.trim(), !(t = t.trim())) {
if (!i.alwaysNormalize) return e;
const t = cu.parseURL(e);
if (!t) throw new Error("Error trying to parse base URL.");
return t.path = cu.normalizePath(t.path), cu.buildURLFromParts(t)
}
const r = cu.parseURL(t);
if (!r) throw new Error("Error trying to parse relative URL.");
if (r.scheme) return i.alwaysNormalize ? (r.path = cu.normalizePath(r.path), cu.buildURLFromParts(r)) : t;
const n = cu.parseURL(e);
if (!n) throw new Error("Error trying to parse base URL.");
if (!n.netLoc && n.path && "/" !== n.path[0]) {
const e = lu.exec(n.path);
n.netLoc = e[1], n.path = e[2]
}
n.netLoc && !n.path && (n.path = "/");
const s = {
scheme: n.scheme,
netLoc: r.netLoc,
path: null,
params: r.params,
query: r.query,
fragment: r.fragment
};
if (!r.netLoc && (s.netLoc = n.netLoc, "/" !== r.path[0]))
if (r.path) {
i.inheritQuery && (r.query || (s.query = n.query));
const e = n.path,
t = e.substring(0, e.lastIndexOf("/") + 1) + r.path;
s.path = cu.normalizePath(t)
} else s.path = n.path, r.params || (s.params = n.params, r.query || (s.query = n.query));
return null === s.path && (s.path = i.alwaysNormalize ? cu.normalizePath(r.path) : r.path), cu.buildURLFromParts(s)
},
parseURL: function(e) {
e = ou.exec(e);
return e ? {
scheme: e[1] || "",
netLoc: e[2] || "",
path: e[3] || "",
params: e[4] || "",
query: e[5] || "",
fragment: e[6] || ""
} : null
},
normalizePath: function(e) {
for (e = e.split("").reverse().join("").replace(du, ""); e.length !== (e = e.replace(uu, "")).length;);
return e.split("").reverse().join("")
},
buildURLFromParts: function(e) {
return e.scheme + e.netLoc + e.path + e.params + e.query + e.fragment
},
getHostName: function(e) {
let t;
return e && (t = -1 < e.indexOf("://") ? e.split("/")[2] : e.split("/")[0], t = t.split(":")[0], t = t.split("?")[0]), t
}
};
var hu, pu, fu, mu, gu, yu, vu, Su, bu = cu;
function Tu(e) {
return null != e && !e.startsWith("http://") && !e.startsWith("https://")
}
function Eu(e) {
return null == e || Tu(e) ? null : cu.getHostName(e)
}
const Iu = [".*.itunes.apple.com"],
wu = {
deviceName: "&xapdn=",
deviceModel: "&xapdm=",
language: "&xapdl=",
dsid: "&xapdsid=",
subs: "&xapsub="
};
function Au(e, t) {
return !e || e === Eu(t)
}(iu = hu = hu || {})[iu.DOVI = 4] = "DOVI", iu[iu.HEVC = 3] = "HEVC", iu[iu.VP09 = 2] = "VP09", iu[iu.AVC = 1] = "AVC", iu[iu.UNKNOWN = 0] = "UNKNOWN", (ru = pu = pu || {})[ru.PQ = 3] = "PQ", ru[ru.HLG = 2] = "HLG", ru[ru.SDR = 1] = "SDR", ru[ru.UNKNOWN = 0] = "UNKNOWN", (w = fu = fu || {})[w.ALAC = 7] = "ALAC", w[w.FLAC = 6] = "FLAC", w[w.EC3 = 5] = "EC3", w[w.AC3 = 4] = "AC3", w[w.XHEAAC = 3] = "XHEAAC", w[w.AAC = 2] = "AAC", w[w.MP3 = 1] = "MP3", w[w.UNKNOWN = 0] = "UNKNOWN", (nu = mu = mu || {})[nu.VALID = 1] = "VALID", nu[nu.INVALID = 0] = "INVALID";
const Ou = ["via", "x-apple-request-uuid"],
ku = {
maxNumRetry: 4,
retryDelayMs: 0,
maxRetryDelayMs: 0
},
Cu = {
maxNumRetry: 6,
retryDelayMs: 1e3,
maxRetryDelayMs: 8e3
},
Du = {
maxNumRetry: 0,
retryDelayMs: 0,
maxRetryDelayMs: 0
},
Mu = {
default: {
maxTimeToFirstByteMs: 5e3,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: Du,
errorRetry: Du
},
customURL: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: Du,
errorRetry: Du
}
},
xu = {
maxNumRetry: 8,
retryDelayMs: 1e3,
maxRetryDelayMs: 2e4,
backoff: "linear"
},
Pu = Object.assign(Object.assign({}, xu), {
maxNumRetry: 1
}),
Ru = {
autoStartLoad: !0,
startPosition: NaN,
defaultAudioCodec: void 0,
defaultVideoCodec: void 0,
debug: !1,
debugLevel: "info",
buildType: void 0,
minFramesBeforeSwitchingLevel: 11,
minTargetDurations: 3,
maxBufferLength: 60,
maxBufferHole: .5,
maxSeekHole: 2,
nudgeFromEventSeek: !0,
jaggedSeekTolerance: 0,
discontinuitySeekTolerance: 2,
bufferedSegmentEjectionToleranceMs: .5,
almostDryBufferSec: .5,
maxTotalDurationTolerance: .1,
lowBufferThreshold: .5,
lowBufferWatchdogPeriod: .5,
highBufferWatchdogPeriod: 3,
seekWatchdogPeriod: 5,
nudgeOffset: .1,
nudgeMaxRetry: 3,
maxFragLookUpTolerance: .2,
initialLiveManifestSize: 1,
liveSyncDurationCount: 3,
liveMaxLatencyDurationCount: 1 / 0,
liveSyncDuration: void 0,
liveMaxLatencyDuration: void 0,
liveFlushExpiredFrags: !0,
liveMaxUnchangedPlaylistRefresh: 3,
liveEdgeForZeroStartPositon: !1,
livePlaylistUpdateStaleness: 2,
livePlaylistDurationNudge: .001,
allowFastSwitchUp: !1,
minMatchGroupDuration: 5,
desiredIframeFPS: 8,
initialIframeFPS: 6,
minRemainingTimeInMediaPipeline: 3,
leftMediaTimeToAutoPause: 10,
startTargetDurationFactor: .9,
minRequiredStartDuration: 4,
maxRequiredStartDuration: 15,
enableWorker: !0,
enableWebCrypto: !0,
keySystemPreference: void 0,
useMultipleKeySessions: !1,
enablePlayReadyKeySystem: !1,
useMediaKeySystemAccessFilter: !1,
playReadyMessageFormat: "utf16",
startLevel: void 0,
livePlaylistRefreshDelay: 2500,
liveMinPlayingBufferLen: 5,
enableIFramePreloading: !0,
useMediaCapabilities: !1,
enableID3Cues: !0,
certLoadPolicy: Mu,
keyLoadPolicy: {
default: {
maxTimeToFirstByteMs: 5e3,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: Pu,
errorRetry: xu
},
customURL: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: Pu,
errorRetry: xu
}
},
manifestLoadPolicy: {
default: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0
},
errorRetry: {
maxNumRetry: 1,
retryDelayMs: 1e3,
maxRetryDelayMs: 8e3
}
},
customURL: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 1e4,
autoRetry: !1,
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0
},
errorRetry: {
maxNumRetry: 1,
retryDelayMs: 1e3,
maxRetryDelayMs: 8e3
}
}
},
trickPlaybackConfig: {
enabled: !0,
minIframeDuration: 8
},
playlistLoadPolicy: {
default: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0
},
errorRetry: {
maxNumRetry: 2,
retryDelayMs: 1e3,
maxRetryDelayMs: 8e3
}
},
customURL: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 1e4,
autoRetry: !1,
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0
},
errorRetry: {
maxNumRetry: 2,
retryDelayMs: 1e3,
maxRetryDelayMs: 8e3
}
}
},
fragLoadPolicy: {
default: {
maxTimeToFirstByteMs: 5e3,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: ku,
errorRetry: Cu,
forceContentLenCheckIfNoHeader: !1,
reportCDNServer: !0
},
customURL: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: ku,
errorRetry: Cu,
reportCDNServer: !0
}
},
steeringManifestLoadPolicy: {
default: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 2e4,
autoRetry: !1,
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0
},
errorRetry: {
maxNumRetry: 1,
retryDelayMs: 1e3,
maxRetryDelayMs: 8e3
}
},
customURL: {
maxTimeToFirstByteMs: 1e4,
maxLoadTimeMs: 1e4,
autoRetry: !1,
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0
},
errorRetry: {
maxNumRetry: 1,
retryDelayMs: 1e3,
maxRetryDelayMs: 8e3
}
}
},
maxNumAddLevelToPenaltyBox: 4,
firstAudioMustOverlapVideoStart: !1,
keyMinHoldTimeBeforeCleanup: 15e3,
startFragPrefetch: !1,
appendErrorMaxRetry: 3,
alwaysResetOnNewCC: !1,
fLoader: void 0,
pLoader: void 0,
xhrSetup: void 0,
iframeMaxExitSeekDuration: 2e3,
iframeStallMaxRetry: 5,
audioPrimingDelay: 0,
enableCEA708Captions: !0,
customTextTrackCueRenderer: !1,
enableWebVTT: !0,
captionsTextTrack1Label: "English",
captionsTextTrack1LanguageCode: "en",
captionsTextTrack2Label: "Spanish",
captionsTextTrack2LanguageCode: "es",
enableDualTrackSelection: !1,
condenseSubtitleTrack: !1,
nativeTextTrackChangeHandling: !0,
earlyFragTolerance: 7,
vttConcurrentLoadCount: 1,
trottleCheckInterval: 2e3,
subtitleLeadTime: 30,
lateTolerance: 2,
stretchShortVideoTrack: !1,
forceKeyFrameOnDiscontinuity: !0,
useFirstLevelAtIncompatDiscontinuity: !0,
abrBandwidthEstimator: "bandwidth-history-controller",
abrEwmaDefaultEstimate: 5e5,
abrDefaultEstimate: 5e5,
abrBandWidthFactor: .95,
abrBandWidthUpFactor: .9,
abrMaxWithRealBitrate: !1,
maxStarvationDelay: 4,
maxLoadingDelay: 4,
minAutoBitrate: 0,
enableRtcReporting: !1,
rtcIntervalTimeout: 3e5,
rtcSender: "HLSJS",
rtcSessionTag: "none",
useHTTPPlaybackSessionId: !1,
warmupCdms: !1,
enablePerformanceLogging: !1,
overridePlaybackRate: !1,
nativeControlsEnabled: !1,
useCustomMediaFunctions: !0,
seekEventThrottleMs: 150,
enableAdaptiveStartup: !0,
bandwidthHistoryWindowSize: 12e4,
bandwidthHistoryTTL: 6e5,
bandwidthHistoryAggregationMethod: "quadratic-time-weighted",
bandwidthHistoryGetEstimateThrottleMs: 1e3,
defaultTargetDuration: 10,
targetStartupMs: 4e3,
adaptiveStartupMetricsOverride: {
maxValidHeight: 1080,
maxValidBitrate: 1 / 0,
maxPreferredBitrate: 1 / 0
},
bandwidthHistoryStorageKey: "AppleHLS-bandwidth-estimation",
storageKeyPrefix: "AppleHLS-",
storage: {
get: "undefined" == typeof localStorage ? void 0 : localStorage.getItem.bind(localStorage),
set: "undefined" == typeof localStorage ? void 0 : localStorage.setItem.bind(localStorage)
},
minFragmentCount: 10,
minPlaylistCount: 5,
enableCDNFallback: !0,
enableQueryParamsForITunes: !1,
gapless: !1,
useViewportSizeForLevelCap: !1,
statDefaults: {
playlistLoadTimeMs: 500,
playlistParseTimeMs: 50,
fragParseTimeMs: 50,
fragBufferCreationDelayMs: 200,
dataFragAppendMs: 50,
initFragAppendMs: 50
},
disableVideoCodecList: new Set([]),
disableAudioCodecList: new Set([fu.ALAC, fu.FLAC, fu.XHEAAC]),
useHighestVideoCodecPrivate: !0,
sessionDataAutoLoad: {
"com.apple.hls.chapters": !0
}
},
Lu = Object.assign(Object.assign({}, {
itemId: "Nah",
mediaOptionId: "Nah"
}), {
mediaOptionType: void 0
}),
_u = e => {
var {
itemId: t,
mediaOptionId: e
} = e;
return "Nah" !== t && "Nah" !== e
};
(iu = gu = gu || {})[iu.Variant = 0] = "Variant", iu[iu.AltAudio = 1] = "AltAudio", iu[iu.Subtitle = 2] = "Subtitle";
const Nu = ["variant", "altAudio", "subtitle"],
Fu = [gu.Variant, gu.AltAudio, gu.Subtitle],
Bu = [gu.Variant, gu.AltAudio];
(ru = yu = yu || {})[ru.Variant = 0] = "Variant", ru[ru.AltAudio = 1] = "AltAudio";
const Uu = ["variant", "altAudio"];
function $u(e) {
switch (e) {
case gu.Variant:
return yu.Variant;
case gu.AltAudio:
return yu.AltAudio;
default:
return null
}
}
function Vu(e) {
return e === yu.Variant ? gu.Variant : gu.AltAudio
}(w = vu = vu || {})[w.NO = 0] = "NO", w[w.YES = 1] = "YES", (nu = Su = Su || {}).UNKNOWN = "unkn", nu.VIDEO = "vide", nu.AUDIO = "soun", nu.SUBTITLE = "sbtl", nu.CLOSEDCAPTION = "clcp";
const Ku = {
search: function(e, t) {
let i, r, n = 0,
s = (null == e ? void 0 : e.length) - 1;
for (; n <= s;) {
var a = t(r = e[i = (n + s) / 2 | 0]);
if (0 < a) n = 1 + i;
else {
if (!(a < 0)) return r;
s = i - 1
}
}
return null
}
};
var qu = Ku,
Hu = {
findFragmentBySNAndBuffer: function(e, t, i = 0, r = 0, n = 0) {
let s;
e = e ? t[e.mediaSeqNum - t[0].mediaSeqNum + 1] : null;
return s = i < r ? (r - n < i && (n = 0), e && !this.fragmentWithinToleranceTest(i, n, e) ? e : Ku.search(t, this.fragmentWithinToleranceTest.bind(null, i, n))) : t[t.length - 1], s
},
fragmentWithinToleranceTest: function(e, t, i) {
t = Math.min(t, i.duration);
return i.start + i.duration - t <= e ? 1 : i.start - t > e && i.start ? -1 : 0
}
};
const ju = {
startFragmentInCC: function(e, t, i) {
let r = t - i.discoSeqNum;
if (0 === r) {
const t = e[i.mediaSeqNum - e[0].mediaSeqNum - 1];
r = t && t.discoSeqNum === i.discoSeqNum ? -1 : 0
}
return r
},
endFragmentInCC: function(e, t, i) {
let r = t - i.discoSeqNum;
if (0 === r) {
const t = e[i.mediaSeqNum - e[0].mediaSeqNum + 1];
r = t && t.discoSeqNum === i.discoSeqNum ? 1 : 0
}
return r
},
findStartEndFragmentsInCC: function(e, t, i) {
let r, n;
return 0 < (null == e ? void 0 : e.length) && ne(t) && (r = Ku.search(e, ju.startFragmentInCC.bind(null, e, t)), n = Ku.search(e, ju.endFragmentInCC.bind(null, e, t))), r && !ne(r.discoSeqNum) && (r = void 0), n && !ne(n.discoSeqNum) && (n = void 0), {
startFrag: r,
endFrag: n
}
},
getTimeRangeDictForCC: function(e, t, i) {
var {
startFrag: t,
endFrag: i
} = ju.findStartEndFragmentsInCC(e, t, i);
return {
start: t.start,
end: i.start + i.duration
}
},
getTimeRangeForCC: function(e, t, i) {
var {
startFrag: t,
endFrag: i
} = ju.findStartEndFragmentsInCC(e, t, i);
let r = [];
return t && i && (r = [t.start, i.start + i.duration]), r
},
snapToCCTimeRange: function(e, t, i, r) {
r = ju.getTimeRangeForCC(t, i, r);
return null != r && r.length ? Math.min(r[1], Math.max(r[0], e)) : e
},
getMinTimeForCC(e, t, i, r) {
if (null == e || !e.length) return 0;
let n = 0;
if (ne(i) && e) {
e = ju.getTimeRangeForCC(e, i, r);
if (e) {
const s = ju.getTimeRangeForCC(t, i, r);
n = null != s && s.length ? Math.max(s[0], e[0]) : e[0]
}
}
return n
},
discoSeqNumForTime(e, t, i = 0) {
i = Ku.search(e, Hu.fragmentWithinToleranceTest.bind(null, t, i));
return null == i ? void 0 : i.discoSeqNum
}
};
var Qu = ju;
const Wu = $i(void 0);
function Gu(e, t, i = 1) {
return e.pipe(ln(t), Ds(i))
}
function zu(e, t) {
var i = e.timeline;
return {
seconds: (e.seconds - i.rootTimeSeconds) / i.rate * t.rate + t.rootTimeSeconds,
timeline: t
}
}
class Xu {
constructor() {
this._timeline = null
}
get forward() {
var e;
return 0 < (null === (e = this.timeline) || void 0 === e ? void 0 : e.rate)
}
get isStarted() {
return Boolean(this.hostClock)
}
start(e) {
this.stopTime = null, this._timeline = Object.assign({}, e);
const t = {
rootTimeSeconds: performance.now() / 1e3,
rate: 1
};
this.hostClock = {
timeline: t,
getCurrentTime: () => ({
seconds: performance.now() / 1e3,
timeline: t
})
}
}
pause() {
this.isStarted && (this.stopTime = this.getCurrentTime())
}
stop() {
this.pause(), this.hostClock = null, this._timeline = null
}
get timeline() {
return this._timeline
}
getCurrentTime() {
return this.stopTime || zu(this.hostClock.getCurrentTime(), this.timeline)
}
}
class Yu {
constructor(e) {
this._timeline = e, this.mediaRootTime = this.lastTimeSeconds = e.rootTimeSeconds
}
get timeline() {
return Object.assign({}, this._timeline)
}
getCurrentTime() {
return {
seconds: this.lastTimeSeconds,
timeline: Object.assign({}, this._timeline)
}
}
}
const Ju = {
name: "ifm"
};
class Zu {
constructor(e, t) {
this.config = e, this.logger = t, this.scaledFragments = [], this.iframeClock = new Xu, this.hasMore$ = new yi(!0), this.logger = t.child(Ju)
}
destroy() {
this.stop()
}
resetScaledSegments() {
this.scaledFragments = []
}
get anchorFrag() {
return this.scaledFragments.length ? this.scaledFragments[0] : null
}
get lastFrag() {
return this.scaledFragments.length ? this.scaledFragments.slice(-1)[0] : null
}
get isStarted() {
return Boolean(this.iframeClock.isStarted)
}
get iframeRate() {
var e;
return null !== (e = null === (e = this.iframeClock.timeline) || void 0 === e ? void 0 : e.rate) && void 0 !== e ? e : 0
}
get iframeClockTimeSeconds() {
return Math.max(0, this.iframeClock.getCurrentTime().seconds)
}
get mediaAppendClockTimeSeconds() {
var e;
return null !== (e = null === (e = this.mediaAppendClock) || void 0 === e ? void 0 : e.getCurrentTime().seconds) && void 0 !== e ? e : 0
}
get mediaRootTime() {
var e;
return null === (e = this.mediaAppendClock) || void 0 === e ? void 0 : e.mediaRootTime
}
pause() {
this.iframeClock.pause()
}
stop() {
this.hasMore$.next(!0), this.iframeClock.stop(), this.mediaAppendClock = null, this.resetScaledSegments()
}
checkHasMore() {
this.hasMore$.next(!0)
}
startClocksAndGetFirstFragment(e, t, i, r, n) {
let s = Ku.search(e, Hu.fragmentWithinToleranceTest.bind(null, r, 1e-4));
if (!s && r >= e[e.length - 1].start && (s = e[e.length - 1]), !s) return this.logger.error(`startClocksAndGetFirstFragment => no anchorFrag for time ${r}`), this.hasMore$.next(!1), null;
var a = ne(n) ? n : s.discoSeqNum,
a = Qu.getMinTimeForCC(e, t, a, this.logger),
r = ne(n) && 1 < i ? a : r,
a = 1 < i ? Math.ceil(r) : Math.ceil(a);
return this.iframeClock.start({
rootTimeSeconds: r,
rate: i
}), this.mediaAppendClock = new Yu({
rootTimeSeconds: a,
rate: 1
}), {
frag: s,
newMediaRootTime: a
}
}
getNextFragment(e, t, i) {
const r = this.lastFrag,
{
iframeClock: n,
mediaAppendClock: s
} = this,
a = n.timeline;
s.lastTimeSeconds = t;
var o = n.forward ? 1 : -1;
let l, d = Math.max(0, Math.min(r.mediaSeqNum - e[0].mediaSeqNum + o, e.length - 1));
if (r.mediaSeqNum !== e[d].mediaSeqNum)
do {
l = e[d];
const i = n.forward ? l.start : l.start + l.duration;
if (zu({
seconds: i,
timeline: a
}, s.timeline).seconds >= t && (n.forward && i >= this.iframeClockTimeSeconds || !n.forward && i <= this.iframeClockTimeSeconds)) break
} while (d += o, 0 < d && d < e.length);
return l || (this.logger.error(`getNextFragment(bufferEnd: ${t}) => no more frags, but we should have found an end fragment, setting hasMore to false`), this.hasMore$.next(!1)), {
frag: l
}
}
nextFragment(e, t, i, r) {
let n, s;
if (this.isStarted && i !== this.iframeRate && (s = this.iframeClockTimeSeconds, this.stop()), this.isStarted) {
if (n = this.getNextFragment(e, r, i), !n.frag) return;
if (n.frag.discoSeqNum !== this.anchorFrag.discoSeqNum) {
const a = this.iframeClockTimeSeconds;
this.stop();
const s = this.startClocksAndGetFirstFragment(e, t, i, a, n.frag.discoSeqNum)["newMediaRootTime"];
n.newMediaRootTime = s
}
} else if (n = this.startClocksAndGetFirstFragment(e, t, i, null != s ? s : r), !n) return;
var r = n["frag"],
r = this.handleNextFrag(e, r);
return Object.assign(Object.assign({}, n), {
frag: r
})
}
handleNextFrag(e, t) {
const i = Object.assign(Object.assign({}, t), {
iframeMediaStart: NaN,
iframeMediaDuration: NaN
}),
{
mediaAppendClock: r,
iframeClock: n
} = this;
this.iframeClockBounds = Qu.getTimeRangeDictForCC(e, i.discoSeqNum, this.logger);
var s = r.getCurrentTime().seconds,
t = n.timeline.rate;
return ne(i.iframeOriginalStart) || (i.iframeOriginalStart = i.start), i.start = i.iframeMediaStart = s, i.iframeMediaDuration = Math.max(i.duration / Math.abs(t), 1 / this.config.minIframeDuration), this.scaledFragments.push(i), this.isEndFrag(e, i) && this.hasMore$.next(!1), i
}
get hasMore() {
return this.hasMore$.value
}
handleWaitForMore() {
return this.isStarted ? (this.iframeClock.getCurrentTime(), Gu(this.hasMore$, e => !0 === e).pipe(Za(() => {}))) : Wu
}
isEndFrag(e, t) {
var i = e[0],
r = e[e.length - 1],
e = this.iframeClock.forward;
return !e && (null == i ? void 0 : i.mediaSeqNum) === t.mediaSeqNum || e && (null == r ? void 0 : r.mediaSeqNum) === t.mediaSeqNum
}
}
function ec(e, t) {
for (var i = 0; i < t.length; i++) {
var r = t[i];
r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(e, r.key, r)
}
}
function tc(t) {
return function(e) {
return e.lift(new nc(t))
}
}
var ic, rc, nc = (ec(sc.prototype, [{
key: "call",
value: function(e, t) {
return t.subscribe(e)
}
}]), sc);
function sc(e) {
! function(e) {
if (!(e instanceof sc)) throw new TypeError("Cannot call a class as a function")
}(this), "tag" in this ? Object.defineProperty(this, "tag", {
value: void 0,
enumerable: !0,
configurable: !0,
writable: !0
}) : this.tag = void 0, this.tag = e
}
function ac(e) {
const {
method: t,
isEncrypted: i,
uri: r,
format: n,
formatversions: s
} = e, a = {
method: t,
isEncrypted: i,
uri: r,
format: n,
formatversions: s,
iv: e.ivBuf ? new Uint8Array(e.ivBuf) : null
};
return e.keyIdBuf && (a.keyId = new Uint8Array(e.keyIdBuf)), e.keyBuf && (a.key = new Uint8Array(e.keyBuf)), e.psshBuf && (a.pssh = new Uint8Array(e.psshBuf)), a
}(iu = ic = ic || {}).MustRequestResponse = "MustRequestResponse", iu.WaitingForKeyResponse = "WaitingForKeyResponse", iu.GotKeyResponse = "GotKeyResponse";
class oc extends Error {
constructor(e, t) {
super(e), this.code = t
}
}
class lc extends p {
constructor(e, t, i, r, n, s) {
super(o, e, t, i, n), this.code = r, this.isTimeout = s, this.response = n
}
}
class dc extends lc {
constructor(e, t, i, r, n) {
super(n ? "manifestLoadTimeOut" : "manifestLoadError", e, t, i, r, n)
}
}
class uc extends lc {
constructor(e, t, i, r, n, s, a, o) {
switch (super("", e, t, i, r, n), this.mediaOptionType = s, this.mediaOptionId = a, this.url = o, s) {
case gu.Variant:
this.details = n ? "levelLoadTimeOut" : N;
break;
case gu.AltAudio:
this.details = n ? "audioTrackLoadTimeOut" : "audioTrackLoadError";
break;
case gu.Subtitle:
this.details = n ? "subtitleTrackLoadTimeout" : "subtitleTrackLoadError"
}
}
}
class cc extends lc {
constructor(e, t, i, r) {
super("sessionDataLoadError", e, t, i, r, !1)
}
}
class hc extends lc {
constructor(e, t, i, r, n, s, a) {
super(n ? "fragLoadTimeOut" : "fragLoadError", e, t, i, r, n), this.mediaOptionId = s.mediaOptionId, this.mediaOptionType = s.mediaOptionType, this.stats = a
}
}
class pc extends dr {
constructor(e, t, i) {
super(), this.message = e, this.code = t, this.stats = i
}
}
class fc extends lc {
constructor(e, t, i) {
super("fragAbortError", !1, "Fragment abort", 0, i, !1), this.candidateMediaOptionId = t, this.mediaOptionId = e.mediaOptionId, this.mediaOptionType = e.mediaOptionType
}
}
class mc extends lc {
constructor(e, t, i, r = []) {
super("keyLoadTimeOut", !1, e, i.code, i, !0), this.keyuri = t, this.response = i, this.mediaOptionIds = r
}
}(ru = rc = rc || {})[ru.InvalidState = 0] = "InvalidState", ru[ru.Abort = 1] = "Abort", ru[ru.OutputRestricted = 2] = "OutputRestricted", ru[ru.AlreadyFailedKey = 3] = "AlreadyFailedKey", ru[ru.HttpError = 4] = "HttpError", ru[ru.InternalError = 5] = "InternalError", ru[ru.LicenseServerError = 6] = "LicenseServerError", ru[ru.InsufficientCPC = 7] = "InsufficientCPC";
class gc extends lc {
constructor(e, t, i, r, n, s, a = !1, o = []) {
super("keyLoadError", a, e, i, r, !1), this.keyuri = t, this.isOkToRetry = n, this.keyErrorReason = s, this.mediaOptionIds = o
}
}
class yc extends p {
constructor(e, t, i, r, n) {
super(s, "keySystemGenericError", !0, e, r), this.keyuri = t, this.code = i, this.response = r, this.keysystemstring = n
}
}
function vc(e, t) {
return e instanceof gc ? new gc(e.message, e.keyuri, e.code, e.response, e.isOkToRetry, e.keyErrorReason, e.fatal, t) : e instanceof mc ? new mc(e.message, e.keyuri, $.CryptResponseReceivedSlowly, t) : e ? new V(e.fatal, e.reason, $.InternalError) : null
}
const Sc = {
id: "fairplaystreaming",
systemStringPrefix: "com.apple.fps",
keyFormatString: "com.apple.streamingkeydelivery",
securityLevels: {
AppleBaseline: 0,
AppleMain: 1,
Main: 1,
Baseline: 0
}
};
class bc extends kl {
constructor(e) {
super(e), this.store = e
}
get unresolvedUriLoading$() {
return this.selectEntityAction(Eo.Add).pipe(hr(e => e.map(e => this.getEntity(e))))
}
}
class Tc {
constructor(e) {
this.store = e
}
createUnresolvedUriLoading(e, t, i) {
Do("loader.create.unresolvedUriLoading"), this.store.add({
uri: e,
responseType: t,
userAgent: i
})
}
removeUnresolvedUriLoading(e) {
Do("loader.remove.unresolvedUriLoading"), this.store.remove(e)
}
}
const Ec = new class extends fl {
constructor() {
super({}, {
name: "loader",
producerFn: su,
idKey: "uri"
})
}
};
let Ic = null;
class wc extends t {
trigger(e, t) {
try {
this.emit(e, e, t), "hlsFragLoadProgress" !== e.toString() && ("hlsInternalError" !== e && "hlsError" !== e || !t.length || JSON.stringify(t[0], ["fatal", "details", "reason"]), e.toString())
} catch (t) {
Qe().warn(`error in event listener for ${e}: ${t.message}`)
}
}
}
class Ac {
constructor(e, t) {
this.target = e, this._this = t
}
eventWithOptions(e, t, i, r = this._this) {
let n = rn(this.target, e, t);
return this.target instanceof wc && (n = n.pipe(hr(([, e]) => e))), i && (r && (i = i.bind(r)), n = n.pipe(Za(i))), n
}
event(e, t, i = this._this) {
return this.eventWithOptions(e, void 0, t, i)
}
listen(e, t, i, r = this._this) {
return this.event(e, i, r).pipe(Va(t)).subscribe()
}
}
function Oc(e, t) {
return new Ac(e, t)
}
function kc(e, t, i) {
var r;
return {
currentTarget: null !== (r = null == i ? void 0 : i.currentTarget) && void 0 !== r ? r : e,
target: null !== (i = null == i ? void 0 : i.target) && void 0 !== i ? i : e,
type: t
}
}
function Cc(y, v) {
return new $t(e => {
const {
maxTimeToFirstByteMs: t,
maxLoadTimeMs: i
} = v, r = new XMLHttpRequest, n = {
trequest: performance.now(),
tfirst: NaN,
tload: NaN,
loaded: 0,
total: NaN,
complete: !1
}, s = Oc(r), a = s.event("progress").pipe(Aa(), ao(300, Ti, {
leading: !0,
trailing: !0
}), hr(e => (isNaN(n.tfirst) && (n.tfirst = performance.now()), n.loaded = e.loaded, e.lengthComputable && (n.total = e.total), e.target)), ln(e => 3 <= e.readyState)), o = s.event("readystatechange").pipe(Aa(), hr(e => e.target), ln(e => 2 <= e.readyState), Za(e => {
isNaN(n.tfirst) && 3 <= e.readyState && (n.tfirst = performance.now())
}));
let l = Ii;
isFinite(t) && 0 < t && (l = an(a, o).pipe(Ds(1), So(0 < y.extendMaxTTFB ? y.extendMaxTTFB : t), La(() => Ii)));
let d = Ii;
isFinite(i) && 0 < i && (d = o.pipe(ln(e => 4 <= e.readyState), Ds(1), So(i), La(() => Ii)));
let u = Ii;
y.onProgress && (u = an($i(r), a).pipe(hr(e => {
const {
getData: t,
cb: i
} = y.onProgress;
return i(y.url, e.status, n, t ? e.response : void 0)
}), Wa(e => !e, !0)).pipe($a(Ii)));
const c = an(a.pipe(La(() => Ii)), o, l, d, u).pipe(ln(e => 4 <= e.readyState), Ds(1), La(e => {
if (n.complete = !0, 200 <= e.status && e.status < 300) {
if (n.tload = performance.now(), n.contentType = e.getResponseHeader("Content-Type"), v.reportCDNServer && (n.cdnServer = e.getResponseHeader("CDN-Server")), n.contentLength = v.forceContentLenCheckIfNoHeader ? function(e) {
let t;
const i = e.getResponseHeader("Content-Encoding"),
r = e.getResponseHeader("Transfer-Encoding"),
n = !i || i && "identity" === i.toLowerCase(),
s = !r || r && "identity" === r.toLowerCase();
return n && s && (t = function(e) {
e = /([0-9]+)\-([0-9]+)\/([0-9]+)/.exec(e);
return e ? parseInt(e[2]) - parseInt(e[1]) + 1 : void 0
}(e.getResponseHeader("Content-Range")), ne(t) || (t = parseInt(e.getResponseHeader("Content-Length")))), t
}(e) : null, i = e, (r = y).collectServerInstanceInfo && (r.serverInstanceInfo = {}, r.collectServerInstanceInfo.forEach(e => {
var t = i.getResponseHeader(e);
t && (r.serverInstanceInfo[e] = t)
})), "arraybuffer" === y.responseType ? n.loaded = e.response.byteLength : n.loaded = e.responseText.length, n.total = n.loaded, y.checkContentLength && (0 === n.total || ne(n.contentLength) && n.total != n.contentLength)) throw new oc("Network error", e.status);
return Nr($i([e, n]), Ti)
}
var i, r;
throw new oc("Network error", e.status)
}), Vn(e => {
if (e instanceof dr) throw new pc(e.message, 0, n);
if (!(e instanceof oc)) throw new oc(e.message, 0);
throw e
})).subscribe(e),
{
url: h,
method: p,
byteRangeOffset: f,
responseType: m,
body: g
} = y;
y.mimeType && r.overrideMimeType(y.mimeType);
try {
const v = y.xhrSetup;
if (v) try {
v(r, h)
} catch (e) {
r.open(p, y.url, !0), v(r, y.url)
}
r.readyState || r.open(p, y.url, !0)
} catch (e) {
throw new oc(e.message, r.status)
}
if (r.responseType = m, f && ne(f.start) && ne(f.end) && 0 <= f.start && f.end > f.start) {
const {
start: y,
end: v
} = f;
r.setRequestHeader("Range", `bytes=${y}-${v-1}`)
}
if (y.headers)
for (const [v, e] of Object.entries(y.headers)) r.setRequestHeader(v, e);
return "POST" === p && g ? r.send(g) : r.send(), () => {
r.abort(), c.unsubscribe()
}
})
}
const Dc = {
name: "CustomUrlLoader"
};
class Mc {
constructor(e) {
this.loaderService = e, this.requestMap = {}, this.logger = Qe()
}
load(a, o) {
return new $t(e => {
const t = a.url,
i = o["maxTimeToFirstByteMs"],
r = {
trequest: performance.now(),
tfirst: NaN,
tload: NaN,
loaded: 0,
total: NaN,
complete: !1
},
n = (this.requestMap[t] = new er).pipe(So(0 < a.extendMaxTTFB ? a.extendMaxTTFB : i), La(e => (r.tfirst = performance.now(), this.handleExternalResponse(e, a, o, r))), Vn(e => {
if (e instanceof dr) throw new pc(e.message, 0, r);
throw e
}), Vs(() => {
this.requestMap[t] = void 0, this.loaderService.removeUnresolvedUriLoading(t)
}));
a.onProgress && a.onProgress.cb(t, 0, r, void 0);
const s = n.subscribe(e);
return this.loaderService.createUnresolvedUriLoading(t, a.responseType, navigator.userAgent), () => {
s.unsubscribe(), this.requestMap[t] = void 0
}
})
}
setCustomUrlResponse(e, t) {
const i = this.requestMap[e];
i && (i.next(t), i.complete(), this.requestMap[e] = void 0)
}
handleExternalResponse(e, t, i, r) {
r.tload = performance.now();
var n = e.response.status || 200;
return 200 <= n && n < 300 ? ("arraybuffer" === t.responseType && e.response.data instanceof ArrayBuffer ? r.loaded = e.response.data.byteLength : r.loaded = e.response.data.toString().length, r.total = r.loaded, r.complete = !0, Nr($i({
status: n,
data: e,
stats: r
}), Ti)) : 300 === n || 302 === n || 303 === n || 305 === n ? this.redirectRequest(e.response.uri, t, i, r) : (this.logger.warn(Dc, `unable to load custom url > uri=${le(e.response.uri)}, status=${n}`), Vi(new oc("Unable to load custom url", n)))
}
redirectRequest(e, t, i, n) {
var {
maxLoadTimeMs: r,
maxTimeToFirstByteMs: s
} = i, r = r - (performance.now() - n.trequest), s = 0 < t.extendMaxTTFB ? t.extendMaxTTFB : s - (performance.now() - n.trequest), i = Object.assign(Object.assign({}, i), {
maxLoadTimeMs: r,
maxTimeToFirstByteMs: s
}), e = Object.assign(Object.assign({}, t), {
url: e
});
return r <= 0 || s <= 0 ? Vi(new dr) : Cc(e, i).pipe(hr(([e, t]) => {
var {
responseURL: i,
status: r
} = e, i = i || "", i = {
uri: i,
response: {
status: r,
uri: i,
data: e.response
}
};
return n.loaded = n.total = t.loaded, n.tload = performance.now(), n.complete = !0, {
status: e.status,
data: i,
stats: n
}
}))
}
}
let xc;
function Pc(e) {
return xc || (e = e || (Ic = Ic || new Tc(Ec), Ic), xc = new Mc(e)), xc
}
function Rc(e, t) {
const i = Object.assign(Object.assign({}, e), {
method: "GET",
responseType: "arraybuffer"
}),
r = Pc();
return Tu(i.url) ? r.load(i, t).pipe(hr(e => [e.data.response.data, e.stats, i.serverInstanceInfo])) : Cc(i, t).pipe(hr(([e, t]) => [e.response, t, i.serverInstanceInfo]))
}
function Lc(e, t) {
return !e.url || Tu(e.url) ? t.customURL : t.default
}
function _c(e, t) {
return e instanceof lc ? e.isTimeout ? t.timeoutRetry : t.errorRetry : null
}
function Nc(e) {
var t = e.type,
i = e.liveOrEvent;
let r = "VOD";
"EVENT" === t && i ? r = "EVENT" : t && 0 !== t.length && "LIVE" !== t || !i || (r = "LIVE"), e.type !== r && (e.type = r)
}
const Fc = {
id: "playready",
systemStringPrefix: "com.microsoft.playready",
keyFormatString: "com.microsoft.playready",
securityLevels: {
SL2000: 0,
SL3000: 1
}
},
Bc = {
id: "widevine",
systemStringPrefix: "com.widevine.alpha",
keyFormatString: "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed",
securityLevels: {
WIDEVINE_SOFTWARE: 0,
WIDEVINE_HARDWARE: 1
}
};
function Uc(e) {
return e.replace(/\+/g, "-").replace(/\//g, "_").replace(/\=+$/, "")
}
class $c {
static strToBase64Encode(e) {
return btoa(e)
}
static base64DecodeToStr(e) {
return atob(e)
}
static base64Encode(e) {
return btoa(String.fromCharCode(...e))
}
static base64UrlEncode(e) {
return Uc($c.base64Encode(e))
}
static base64Decode(e) {
return Uint8Array.from(atob(e), e => e.charCodeAt(0))
}
}
class Vc {
static strToBase64Encode(e) {
return l.Buffer.from(e).toString("base64")
}
static base64DecodeToStr(e) {
return l.Buffer.from(e, "base64").toString()
}
static base64Encode(e) {
return l.Buffer.from(e).toString("base64")
}
static base64UrlEncode(e) {
return Uc(Vc.base64Encode(e))
}
static base64Decode(e) {
e = l.Buffer.from(e, "base64");
return new Uint8Array(e.buffer, e.byteOffset, e.byteLength)
}
}
var Kc, qc = void 0 !== l.Buffer ? Vc : $c;
const Hc = {
avc1: "video/mp4",
avc3: "video/mp4",
dvav: "video/mp4",
dva1: "video/mp4",
hev1: "video/mp4",
hvc1: "video/mp4",
dvh1: "video/mp4",
dvhe: "video/mp4"
},
jc = {
mp4a: "audio/mp4",
"ac-3": "audio/mp4",
"ec-3": "audio/mp4"
};
function Qc(e) {
const t = O.strToUtf8array(e).subarray(0, 16),
i = new Uint8Array(16);
return i.set(t, 16 - t.length), i
}
const Wc = {
getCapabilities: function(e, t) {
const i = {
videoCapabilities: [],
audioCapabilities: []
};
return e && e.forEach(e => {
var t = e.split(".")[0].trim();
t in Hc && i.videoCapabilities.push({
contentType: Hc[t] + ";codecs=" + e,
robustness: ""
})
}), t && t.forEach(e => {
var t = e.split(".")[0].trim();
t in jc && i.audioCapabilities.push({
contentType: jc[t] + ";codecs=" + e,
robustness: ""
})
}), i
},
changeEndianness: function(e) {
function t(e, t, i) {
var r = e[t];
e[t] = e[i], e[i] = r
}
t(e, 0, 3), t(e, 1, 2), t(e, 4, 5), t(e, 6, 7)
},
getKeyIdBytes: Qc,
convertDataUriToArrayBytes: function(e) {
const t = e.split(":");
let i = null;
if ("data" === t[0] && 2 === t.length) {
const e = t[1].split(";"),
r = e[e.length - 1].split(",");
if (2 === r.length) {
const t = "base64" === r[0],
n = r[1];
i = t ? (e.splice(-1, 1), qc.base64Decode(n)) : Qc(n)
}
}
return i
},
makeKeyIdsInitData: function(e) {
e = {
kids: e.map(qc.base64UrlEncode)
};
return O.strToUtf8array(JSON.stringify(e))
},
parsePSSHList: function(e) {
const i = new DataView(e);
let r = 0;
const n = {};
for (; r < i.buffer.byteLength;) {
const e = r,
t = i.getUint32(r);
r += 4;
var s = e + t;
if (1886614376 === i.getUint32(r)) {
switch (r += 4, i.getUint8(r)) {
case 0:
case 1:
r += 1;
break;
default:
r = s
}
r += 3;
let t = "";
for (let e = 0; e < 16; ++e, ++r) switch (t += i.getUint8(r).toString(16), e) {
case 4:
case 6:
case 8:
case 10:
t += "-"
}
r += 4, n[t] = i.buffer.slice(e, s)
} else r = s
}
return n
}
};
let Gc = {};
class zc {
constructor(e, t, i, r, n) {
if (this.method = e, this.uri = t, this.iv = i, this.format = r, this.formatversions = n, this.isEncrypted = this.method && "NONE" !== this.method, this.formatversions && 0 !== this.formatversions.length || (this.formatversions = [1]), this.key = void 0, this.keyId = void 0, this.isEncrypted) {
const a = Wc.convertDataUriToArrayBytes(this.uri);
if (a) switch (r) {
case Fc.keyFormatString: {
this.pssh = a;
const e = new Uint16Array(a.buffer, a.byteOffset, a.byteLength / 2),
t = String.fromCharCode.apply(null, Array.from(e)),
i = t.substring(t.indexOf("<"), t.length),
r = (new DOMParser).parseFromString(i, "text/xml").getElementsByTagName("KID")[0];
if (r) {
var s = null;
if (s = r.childNodes[0] ? r.childNodes[0].nodeValue : r.getAttribute("VALUE")) {
const t = qc.base64Decode(s).subarray(0, 16);
Wc.changeEndianness(t), this.keyId = t
}
}
break
}
case Bc.keyFormatString:
this.pssh = a, 22 <= a.length && (this.keyId = a.subarray(a.length - 22, a.length - 6));
break;
default: {
let e = a.subarray(0, 16);
if (16 !== e.length) {
const t = new Uint8Array(16);
t.set(e, 16 - e.length), e = t
}
this.keyId = e;
break
}
}
if (!this.keyId || 16 !== this.keyId.byteLength) {
let e = Gc[this.uri];
if (!e) {
const t = Object.keys(Gc).length % Number.MAX_SAFE_INTEGER;
e = new Uint8Array(16), new DataView(e.buffer, 12, 4).setUint32(0, t), Gc[this.uri] = e
}
this.keyId = e
}
}
}
get keyTagInfo() {
var {
method: e,
isEncrypted: t,
uri: i,
iv: r,
keyId: n,
key: s,
format: a,
formatversions: o
} = this;
return {
method: e,
isEncrypted: t,
uri: i,
iv: r,
keyId: n,
key: s,
format: a,
formatversions: o
}
}
static clearKeyUriToKeyIdMap() {
Gc = {}
}
}(w = Kc = Kc || {}).NONE = "NONE", w.GET_REQUEST_INFO = "GET_REQUEST_INFO", w.GET_CHALLENGE = "GET_CHALLENGE", w.GET_KEY_RESPONSE = "GET_KEY_RESPONSE", w.PROCESS_LICENSE = "PROCESS_LICENSE";
class Xc {
constructor(e, t, i, r) {
this.session = e, this.onkeystatuseschange = t, this.onkeymessage = i, this.logger = r, this.isClosing$ = new yi(!1), this.closed$ = new yi(!1);
const n = Oc(this.session);
n.listen("keystatuseschange", this.isClosing$.pipe(ln(e => !0 === e)), this.onkeystatuseschange), n.listen("message", this.closed$.pipe(ln(e => !0 === e)), this.onkeymessage)
}
get isClosing() {
return this.isClosing$.value
}
get isClosed() {
return this.closed$.value
}
destroy() {
this.isClosing$.next(!0);
const e = this.session;
return Fr(e.remove().catch(e => {}).then(() => e.close()).catch(e => {})).pipe(Za(() => {
this.isClosing$.next(!1), this.closed$.next(!0)
}), Vs(() => {
this.isClosing$.next(!1), this.closed$.next(!0)
}))
}
}
class Yc {
constructor(e, t = null) {
this.decryptdata = e, this._requestState$ = new yi(Kc.NONE), this.destroy$ = new Xt, this.currentObservable = null, this.session = null, this.oldSessions = [], this.session = t
}
get requestState() {
return this._requestState$.value
}
get onKeyRequestState$() {
return this._requestState$
}
destroy() {
this.destroy$.next()
}
abort() {
var e;
this.requestState !== Kc.NONE && (e = new gc("Aborted", this.decryptdata.uri, 0, $.KeySystemAbort, !0, rc.Abort), this.error(e))
}
setKeyRequestState(e) {
if (this.currentObservable) {
const t = new gc(`Unexpected state transition ${this.requestState}->${e}`, this.decryptdata.uri, 0, $.KeySystemUnexpectedStateTransition, !0, rc.InvalidState);
this.error(t)
}
this._requestState$.next(e);
const t = new er;
return e === Kc.NONE ? (t.complete(), this.currentObservable = null) : this.currentObservable = t, t
}
resolveState(e, t) {
if (this.currentObservable)
if (e === this.requestState)
if (t instanceof Error) this.error(t);
else {
const e = this.currentObservable;
this.currentObservable = null, e.next(t), e.complete()
}
else {
const t = new gc(`Unexpected state ${this.requestState} != ${e}`, this.decryptdata.uri, 0, $.KeySystemUnexpectedState, !0, rc.InvalidState);
this.error(t)
}
}
error(e) {
if (this.currentObservable) {
const t = this.currentObservable;
this.currentObservable = null, t.error(e)
}
this.setKeyRequestState(Kc.NONE)
}
}
function Jc(e) {
return `uri=${le(e.uri)} keyId=${je(e.keyId)}`
}
class Zc {
constructor(e, t, i, r, n, s, a) {
this.mediaKeys = e, this.systemString = t, this.config = i, this.eventEmitter = r, this.useSingleKeySession = n, this.sessionHandler = s, this.logger = a, this.destroy$ = new Xt, this.setCert = !1, this.certificate$ = new yi(null), this._keyStatusChange$ = new Xt, this.shouldDestroyMediaKeys = !1, this.itemId = "", this.sessions = [], this.keyIdToKeyInfo = {}, this.keyUriToKeyInfo = {}, this.sessionIdToKeyUri = {}, this.onkeystatuseschange = this.handleKeyStatusesChange.bind(this), this.onkeymessage = this.handleKeyMessage.bind(this)
}
get keyStatusChange$() {
return this._keyStatusChange$
}
destroy() {
this.isDestroying = !0, this.destroy$.next();
for (const e of Object.values(this.keyIdToKeyInfo)) this._abortKeyRequest(e);
const e = this.sessions.map(e => e.destroy()),
t = nn(() => 0 === e.length, Wu, en(e)).pipe(Zs(void 0), Vs(() => {
this.mediaKeys = void 0, this.keyIdToKeyInfo = {}, this.keyUriToKeyInfo = {}, this.sessionIdToKeyUri = {}
}));
return zc.clearKeyUriToKeyIdMap(), t
}
setServerCertificate(e = null) {
return this.needsCert ? (e && this.certificate$.next(e), Gu(this.certificate$, e => null != e).pipe(So(1e4)).pipe(La(e => this.setCert ? $i(!0) : !this.setCertSubject || this.setCertSubject.isStopped ? (this.setCertSubject = new er, Fr(this.mediaKeys.setServerCertificate(e)).pipe(Za(e => {
e = void 0 === e || e;
this.setCert = e, this.setCertSubject.next(e), this.setCertSubject.complete()
}), Vn(e => (this.setCert = !1, this.setCertSubject.error(e), Wu)), La(() => this.setCertSubject))) : this.setCertSubject), Vn(e => {
throw e
}))) : $i(!0)
}
ensureKeyContext(e) {
var t = e.uri;
this.keyUriToKeyInfo[t] || (this.keyUriToKeyInfo[t] = new Yc(e));
const i = this.keyUriToKeyInfo[t];
if (i.session) return i;
if (this.useSingleKeySession && 0 < this.sessions.length) return i.session = this.sessions[0].session, i;
t = this.mediaKeys.createSession();
return t && this.sessions.push(new Xc(t, this.onkeystatuseschange, this.onkeymessage, this.logger)), i.session = t, i
}
startKeyRequest(t) {
const i = t.uri,
r = this.ensureKeyContext(t);
if (null == r || !r.session) return Vi(new yc("Could not create key session", t.uri, 0, $.KeySystemFailedToCreateSession, this.systemString));
var e = O.utf8arrayToStr(t.keyId);
return this.keyIdToKeyInfo[e] = r, en([this.getKeyRequestInfo(r), this.setServerCertificate()]).pipe(hr(e => e[0]), La(e => {
var t;
return null === (t = this.sessionHandler) || void 0 === t || t.licenseChallengeSubmitted({
keyuri: i,
keyFormat: this.systemString
}), this.generateLicenseChallenge(r, e).pipe(Vn(e => {
var t;
throw null === (t = this.sessionHandler) || void 0 === t || t.licenseChallengeError({
keyuri: i
}), e
}))
}), La(e => {
var t;
return null === (t = this.sessionHandler) || void 0 === t || t.licenseChallengeCreated({
keyuri: i,
cdmVersion: this.cdmVersion
}), this.getKeyRequestResponse(r, e)
}), La(e => {
var t;
return null === (t = this.sessionHandler) || void 0 === t || t.licenseResponseSubmitted({
keyuri: i
}), this.handleParsedKeyResponse(r, e).pipe(Vn(e => {
var t;
throw null === (t = this.sessionHandler) || void 0 === t || t.licenseResponseError({
keyuri: i
}), e
}))
}), hr(() => {
var e;
return null === (e = this.sessionHandler) || void 0 === e || e.licenseResponseProcessed({
keyuri: i
}), r.setKeyRequestState(Kc.NONE), this.removeSessions(r.decryptdata, !1).subscribe(), t
}), Vn(e => {
throw this.handleKeyExchangeError(r, e), e
}), Vs(() => {
this._abortKeyRequest(r)
}))
}
_abortKeyRequest(e) {
var t, i;
e && (i = e.decryptdata.uri, O.utf8arrayToStr(e.decryptdata.keyId), e.requestState !== Kc.NONE && (null === (t = this.sessionHandler) || void 0 === t || t.keyAborted({
keyuri: i
})), e.abort())
}
handleKeyExchangeError(e, t) {
e.error(t), O.utf8arrayToStr(e.decryptdata.keyId)
}
updateItemId(e) {
this.itemId = e
}
removeKey(e) {
return this.removeKeyInternal(e)
}
removeKeyInternal(e) {
const t = this.keyUriToKeyInfo[e.uri];
if (t && t.session) {
var i = t.session;
t.abort(), t.destroy();
var r = O.utf8arrayToStr(e.keyId);
return this.keyIdToKeyInfo[r] = void 0, this.keyUriToKeyInfo[e.uri] = void 0, this.removeSession(i)
}
}
removeSessions(e, t) {
const i = this.keyUriToKeyInfo[e.uri];
if (i) {
const r = i.oldSessions.map(e => this.removeSession(e));
return i.oldSessions = [], nn(() => 0 === r.length, Wu, en(r)).pipe(La(() => t ? this.removeKeyInternal(e) : Wu))
}
return Wu
}
removeSession(t) {
const e = this.sessions.findIndex(e => e.session === t),
i = this.sessions[e];
return -1 < e && this.sessions.splice(e, 1), this.sessionIdToKeyUri[t.sessionId] = void 0, i ? i.destroy() : Wu
}
getKeyRequestInfo(e) {
var t = e.decryptdata,
i = t.uri,
e = e.setKeyRequestState(Kc.GET_REQUEST_INFO);
return this.eventEmitter.trigger(x.KEY_REQUEST_STARTED, {
keyuri: i,
decryptdata: t,
timestamp: Date.now()
}), e
}
setKeyRequestInfo(e, t) {
const i = this.keyUriToKeyInfo[e];
i && i.resolveState(Kc.GET_REQUEST_INFO, t)
}
sanitizeRequest(e) {
return e
}
generateLicenseChallengeInternal(t, e, i) {
const r = t.decryptdata,
n = t.session,
s = r.uri,
a = r.keyId;
let o;
var l = t.setKeyRequestState(Kc.GET_CHALLENGE);
if (n.generateRequestPromise) o = Nr(n.generateRequestPromise, Ti).pipe(La(() => this.generateRequestInitialized(t, "usable" === i)));
else {
const i = this.generateInitData(a, r, e);
n.generateRequestPromise = n.generateRequest(i.initDataType, i.initData), o = Nr(n.generateRequestPromise, Ti).pipe(Za(() => {
this.sessionIdToKeyUri[n.sessionId] = s
}), Vn(e => {
throw new yc(e.message, t.decryptdata.uri, 0, $.KeySystemFailedToGenerateLicenseRequest, this.systemString)
}))
}
return en([l, o]).pipe(hr(e => new Uint8Array(e[0])))
}
generateLicenseChallenge(e, t) {
const i = e.decryptdata,
r = e.session,
n = i.uri,
s = i.keyId;
let a, o;
if (O.utf8arrayToStr(i.keyId), e.licenseChallenge && e.resolveState(Kc.GET_CHALLENGE, e.licenseChallenge), t = this.sanitizeRequest(t), e.requestInfo = t, this.sessionId = this.sessionId || t && t.sessionId || this.itemId, this.systemString === Fc.systemStringPrefix) {
const e = new Uint8Array(s);
Wc.changeEndianness(e), a = r.keyStatuses.get(e)
} else a = r.keyStatuses.get(s);
switch (a) {
case "status-pending":
case "usable":
case "expired":
case void 0:
o = this.generateLicenseChallengeInternal(e, t, a);
break;
default:
o = Vi(new yc(`Bad internal state state=${a}`, n, 0, $.KeySystemUnexpectedState, this.systemString))
}
return o
}
setParsedResponse(e, t) {
const i = this.keyUriToKeyInfo[e];
i && i.resolveState(Kc.GET_KEY_RESPONSE, t)
}
handleKeyStatusesChange(e) {
e.target.keyStatuses.forEach((e, t, i) => {
t = new Uint8Array(t);
this.systemString === Fc.systemStringPrefix && Wc.changeEndianness(t);
t = O.utf8arrayToStr(t), t = this.keyIdToKeyInfo[t];
t && this.handleKeyStatusForKey(e, t)
})
}
handleKeyStatusForKey(e, t) {
if (t) {
var i = t.decryptdata,
r = i.uri;
switch (e) {
case "internal-error":
this.logger.error(`${this.systemString} internal-error for key ${Jc(i)}`), this._signalError(t, new gc("Got internal error from key system", r, 0, $.KeySystemInternalError, !1, rc.InternalError));
break;
case "usable":
t.requestState === Kc.PROCESS_LICENSE && t.resolveState(Kc.PROCESS_LICENSE, void 0);
break;
case "output-restricted":
this.logger.warn(`${this.systemString} output-restricted for key ${Jc(i)}`), t.session && this.removeSession(t.session).pipe(Va(this.destroy$)).subscribe(), this._signalError(t, new gc("output-restricted", r, 0, $.KeySystemOutputRestricted, !1, rc.OutputRestricted));
break;
case "expired":
this.logger.warn(`${this.systemString} expired for key ${Jc(i)}. Attempting renewal`), this._signalRenewal(t)
}
}
}
_scheduleRenewal(e, t) {
bn(t).pipe(Za(() => this._signalRenewal(e)), Va(fn(e.destroy$, this.destroy$, Gu(e.onKeyRequestState$, e => e === Kc.GET_REQUEST_INFO)))).subscribe()
}
_signalRenewal(e) {
this._keyStatusChange$.next({
decryptdata: e.decryptdata,
status: "needs-renewal"
})
}
_signalError(e, t) {
this._keyStatusChange$.next({
decryptdata: e.decryptdata,
status: "error",
error: t
}), e.error(t)
}
}
const eh = "org.w3.clearkey",
th = {
id: "clearkey",
systemStringPrefix: eh,
keyFormatString: eh,
securityLevels: {
NONE: 0
}
},
ih = ["clearkey", "fairplaystreaming", "playready", "widevine"],
rh = {
initDataTypes: ["keyids", "cenc"]
};
var nh, nu = class extends Zc {
constructor(e, t, i, r, n, s) {
super(e, t, i, r, !1, n, s)
}
static get requestAccessConfig() {
return rh
}
get needsCert() {
return !1
}
getKeyRequestResponse(e, t) {
return Rc({
url: e.decryptdata.uri,
xhrSetup: this.config.xhrSetup
}, {
maxLoadTimeMs: 0,
maxTimeToFirstByteMs: 0,
autoRetry: !1,
timeoutRetry: null,
errorRetry: null
}).pipe(hr(([e]) => {
e = new Uint8Array(e);
return {
response: this.parseResponse(t, e)
}
}))
}
parseResponse(e, t) {
t = {
kty: "oct",
kid: qc.base64UrlEncode(e),
k: qc.base64UrlEncode(t)
};
return O.strToUtf8array(JSON.stringify({
keys: [t]
}))
}
handleParsedKeyResponse(i, e) {
e = e.response;
return en([i.setKeyRequestState(Kc.PROCESS_LICENSE), Fr(i.session.update(e)).pipe(Za(() => {
var e = i.decryptdata.keyId,
e = i.session.keyStatuses.get(e);
this.handleKeyStatusForKey(e, i)
}), Vn(e => {
var t = {
code: e.code,
text: "Failed to update with key response"
};
throw new yc(e.message, i.decryptdata.uri, e.code, t, this.systemString)
}))]).pipe(Zs(void 0))
}
generateInitData(e) {
return {
initData: Wc.makeKeyIdsInitData([e]),
initDataType: "keyids"
}
}
generateRequestInitialized() {
return Wu
}
sanitizeRequest(e) {
return e
}
handleKeyMessage(e) {
if (!this.isDestroying && "license-request" === e.messageType) {
e = new Uint8Array(e.message), e = JSON.parse(O.utf8arrayToStr(e).trim());
if (1 === e.kids.length) {
const t = qc.base64Decode(e.kids[0]),
i = O.utf8arrayToStr(t),
r = this.keyIdToKeyInfo[i];
r && r.resolveState(Kc.GET_CHALLENGE, t)
}
}
}
};
const sh = {
initDataTypes: ["cenc"]
},
ah = new Uint8Array([148, 206, 134, 251, 7, 255, 79, 67, 173, 184, 147, 210, 250, 150, 140, 162]);
(iu = nh = nh || {})[iu.CENC = 1667591779] = "CENC", iu[iu.CBCS = 1667392371] = "CBCS";
class oh extends Zc {
constructor(e, t, i, r, n, s, a) {
super(e, t, i, r, n, s, a), this._hasSetRenewal = !1
}
static get systemId() {
return ah
}
static get requestAccessConfig() {
return sh
}
get needsCert() {
return !0
}
sanitizeRequest(e) {
return {
assetId: e && e.assetId ? new Uint8Array(e.assetId) : void 0,
ssc: e && e.ssc ? new Uint8Array(e.ssc) : void 0,
sessionId: e && e.sessionId ? e.sessionId : void 0
}
}
_scheduleRenewal(e, t) {
this.useSingleKeySession ? this._hasSetRenewal || (this._hasSetRenewal = !0, bn(t).pipe(Za(() => {
var e = Object.values(this.keyUriToKeyInfo)[0];
e && this._signalRenewal(e)
}), Vs(() => {
this._hasSetRenewal = !1
}), Va(this.destroy$)).subscribe()) : super._scheduleRenewal(e, t)
}
handleParsedKeyResponse(t, e) {
var i = t.decryptdata.uri,
r = e.statusCode,
n = e.ckc && 0 !== e.ckc.byteLength ? e.ckc : e.license && 0 !== e.license.byteLength ? e.license : void 0;
if (0 === r && !n) return Vi(new gc("License request resulted in HTTP Error", i, r, {
code: r,
text: "HTTP Error"
}, !0, rc.HttpError));
if (0 !== r) return Vi(new gc("License server responded with error", i, r, {
code: r,
text: "Server Error"
}, !1, rc.LicenseServerError));
if (!n) return Vi(new gc("License server responded with invalid license", i, r, {
code: r,
text: "Invalid license"
}, !1, rc.LicenseServerError));
const s = e.renewalDate,
a = new Date,
o = s > a ? s.getTime() - a.getTime() : 0;
0 < o && this._scheduleRenewal(t, o);
const l = this.makeProcessLicenseRequestMessage(t, n, o),
d = t.session,
u = Fr(d.update(l)).pipe(Za(() => {
var e = t.decryptdata.keyId,
e = d.keyStatuses.get(e);
this.handleKeyStatusForKey(e, t)
}), Vn(e => {
throw new yc(e.message, t.decryptdata.uri, 0, $.KeySystemFailedToUpdateSession, this.systemString)
}));
return en([t.setKeyRequestState(Kc.PROCESS_LICENSE), u]).pipe(Zs(void 0))
}
makeKeyRequests(e) {
const t = [];
for (const i of e) {
const e = i.decryptdata,
r = i.requestInfo,
n = e.keyId;
t.push({
keyId: n,
assetId: r ? r.assetId : void 0,
ssc: r ? r.ssc : void 0,
versionList: e.formatversions
})
}
return t
}
getSchemeAndFlags(e) {
return {
scheme: "ISO-23001-7" === e.method ? nh.CENC : nh.CBCS,
flags: 0
}
}
generateInitData(e, t, i) {
var {
scheme: r,
flags: n
} = this.getSchemeAndFlags(t), i = this.makeKeyRequests([{
decryptdata: t,
requestInfo: i
}]);
return {
initData: this.makeFpsKeySystemInitData(r, n, i),
initDataType: "cenc"
}
}
generateRequestInitialized(t, e) {
tc(`[Keys] challenge create start uri=${le(t.decryptdata.uri)} versions=${JSON.stringify(t.decryptdata.formatversions)}`);
e = this.makeKeyRequestMessage(t, e);
return e ? Fr(t.session.update(e)).pipe(Za(() => {
t.requestInfo = void 0
}), Vn(e => {
throw tc(`[Keys] ${this.systemString} FAIL: generateRequestInitialized keyuri=${le(t.decryptdata.uri)} message=${e.message}`), new yc(e.message, t.decryptdata.uri, 0, $.KeySystemFailedToGenerateLicenseRenewal, this.systemString)
})) : Vi(new gc("Unable to generate request using existing keySession", t.decryptdata.uri, 0, $.KeySystemFailedToGenerateLicenseRequest, !0, rc.InvalidState))
}
getKeyRequestResponse(e, t) {
var i = e.decryptdata.uri,
e = e.setKeyRequestState(Kc.GET_KEY_RESPONSE);
return this.eventEmitter.trigger(x.LICENSE_CHALLENGE_CREATED, {
keyuri: i,
licenseChallenge: t,
keysystem: this.systemString
}), e
}
resolveSPCPromise(e, t) {
e.resolveState(Kc.GET_CHALLENGE, t)
}
}
const lh = {},
dh = 1919710053;
function uh(e, t, i) {
if (!(i + 4 > e.byteLength)) {
t = t.getUint32(i);
if (!((i += 4) + t > e.byteLength)) {
e = e.slice(i, i + t);
return {
pos: i += t,
data: e
}
}
}
}
function ch(t) {
const i = {},
r = new DataView(t.buffer);
let n = 4;
const s = r.getUint32(n);
n += 4;
for (let e = 0; e < s && n < t.byteLength && !(n + 16 > t.byteLength); ++e) {
const s = t.slice(n, n + 16);
if (n += 16, n + 4 > t.byteLength) break;
var a = uh(t, r, n);
if (!a) break;
n = a.pos, i[O.utf8arrayToStr(s)] = a.data
}
return i
}
function hh(e, t, i, r) {
var n = r ? r.byteLength : 0;
return t.setUint32(i, n), n && e.set(r, i + 4), i + (4 + n)
}
function ph(e) {
let t = 4;
for (const i of e) t += 28 + (i.assetId ? i.assetId.byteLength : 0) + (i.ssc ? i.ssc.byteLength : 0) + (i.versionList ? 4 * i.versionList.length : 0);
return t
}
function fh(e, t, i, r) {
t.setUint32(i, r.length), i += 4;
for (const n of r)
if (e.set(n.keyId, i), i = hh(e, t, i += 16, n.assetId), i = hh(e, t, i, n.ssc), t.setUint32(i, n.versionList ? n.versionList.length : 0), i += 4, n.versionList)
for (const e of n.versionList) t.setUint32(i, e), i += 4;
return i
}
class mh extends oh {
constructor(e, t, i, r, n, s) {
super(e, t, i, r, void 0 === i.useMultipleKeySessions || !i.useMultipleKeySessions, n, s)
}
makeProcessLicenseRequestMessage(e, t, i) {
t = new Uint8Array(t);
return function(e) {
let t = 0;
for (const i of e) t += 24 + i.ckc.byteLength;
let i = 0;
const r = new Uint8Array(8 + t),
n = new DataView(r.buffer);
n.setUint32(0, 1667982195), n.setUint32(4, e.length), i += 8;
for (const t of e) r.set(t.keyId, i), i += 16, n.setUint32(i, t.expirySec), i += 4, i = hh(r, n, i, t.ckc);
return r
}([{
keyId: e.decryptdata.keyId,
expirySec: i / 1e3,
ckc: t
}])
}
makeFpsKeySystemInitData(e, t, i) {
i = function(e, t, i) {
var r = ph(i);
const n = new Uint8Array(8 + r),
s = new DataView(n.buffer);
return s.setUint32(0, e), s.setUint32(4, 1 << 24 | 16777215 & t), fh(n, s, 8, i), n
}(e, t, i);
return ge.pssh(mh.systemId, [], i)
}
makeKeyRequestMessage(e) {
return function(e) {
var t = ph(e);
const i = new Uint8Array(4 + t),
r = new DataView(i.buffer);
return r.setUint32(0, 1668442994), fh(i, r, 4, e), i
}([{
keyId: e.decryptdata.keyId,
assetId: e.requestInfo ? e.requestInfo.assetId : void 0,
ssc: e.requestInfo ? e.requestInfo.ssc : void 0,
versionList: e.decryptdata.formatversions
}])
}
handleKeyMessage(e) {
if (e.message.byteLength < 4) this.logger.warn("Unexpected message");
else {
const t = new Uint8Array(e.message),
i = new DataView(e.message),
r = i.getUint32(0);
if (this.isDestroying && r !== dh) this.logger.warn(`In the middle of destroying, ignore command: ${r.toString(16)}`);
else switch (r) {
case 1667592820:
this.logger.warn("Certificate not set!");
break;
case 1919837559: {
const e = ch(t);
for (const t in e)
if (Object.prototype.hasOwnProperty.call(e, t)) {
const e = this.keyIdToKeyInfo[t];
e && this._signalRenewal(e)
} break
}
case 1936745331: {
const e = ch(t);
for (const t in e)
if (Object.prototype.hasOwnProperty.call(e, t)) {
const i = this.keyIdToKeyInfo[t],
r = e[t];
i && r && this.resolveSPCPromise(i, r)
} break
}
case dh:
this._handleLicenseRelease(t);
break;
case 1667525993: {
const e = uh(t, i, 4);
e && (this.cdmVersion = O.utf8arrayToStr(e.data));
break
}
default:
this.logger.warn(`Unrecognized command:'0x${r.toString(16)}'`)
}
}
}
_handleLicenseRelease(e) {
const t = {},
i = new DataView(e.buffer);
switch (i.getUint32(4)) {
case 1936946288:
lh, 0, t[lh.SessionId] = this.sessionId;
var r;
if (e.byteLength < 12) break;
t[lh.APIProvider] = i.getUint32(8) === nh.CENC ? "EC396D13-FB13-4993-9D0D-71518ACF3D6F" : "F19BF03B-7470-41A4-9655-86D078307D59", 0;
var n = uh(e, i, 12);
if (!n) break;
if (r = n.pos, t[lh.MovieID] = O.utf8arrayToStr(n.data), !(n = uh(e, i, r))) break;
if (r = n.pos, t[lh.SecureStopSPC] = n.data, !(n = uh(e, i, r))) break;
n.pos, t[lh.SessionLifespanSPC] = n.data
}
this.eventEmitter.trigger(x.LICENSE_RELEASED, {
keysystem: this.systemString,
itemId: this.itemId,
releaseRecord: t
})
}
}
ru = mh;
const gh = {
fpsd: O.strToUtf8array("fpsd"),
fpsi: O.strToUtf8array("fpsi"),
fpsk: O.strToUtf8array("fpsk"),
fkri: O.strToUtf8array("fkri"),
fkai: O.strToUtf8array("fkai"),
fkcx: O.strToUtf8array("fkcx"),
fkvl: O.strToUtf8array("fkvl")
};
t = class extends oh {
constructor(e, t, i, r, n, s) {
super(e, t, i, r, !1, n, s), this.sessions = [], this.keyIdToKeyInfo = {}, this.keyUriToKeyInfo = {}, this.sessionIdToKeyUri = {}
}
static get needsCert() {
return !0
}
handleKeyExchangeError(e, t) {
this.removeKey(e.decryptdata).subscribe(), super.handleKeyExchangeError(e, t)
}
_abortKeyRequest(e) {
return !this.isDestroying && e && e.requestState !== Kc.NONE && this.removeKey(e.decryptdata).subscribe(), super._abortKeyRequest(e)
}
makeFpsKeySystemInitData(e, t, i) {
const r = [gh.fpsd, (n = e, e = t, t = new Uint8Array(4), ge.set32(n, t, 0), ge.box(gh.fpsi, new Uint8Array([0, e >> 16 & 255, e >> 8 & 255, 255 & e]), t))];
var n;
for (const s of i) r.push(function(t, e, i, r) {
const n = [gh.fpsk],
s = ge.box(gh.fkri, new Uint8Array([0, 0, 0, 0]), t);
if (n.push(s), e && e.byteLength && n.push(ge.box(gh.fkai, e)), i && i.byteLength && n.push(ge.box(gh.fkcx, i)), r && r.length) {
const t = new Uint8Array(4 * r.length);
let e = 0;
for (const i of r) ge.set32(i, t, e), e += 4;
n.push(ge.box(gh.fkvl, t))
}
return ge.box.apply(null, n)
}(s.keyId, s.assetId, s.ssc, s.versionList));
i = ge.box.apply(null, r);
return ge.pssh(oh.systemId, null, i)
}
makeKeyRequestMessage(e, t) {
if (t) return O.strToUtf8array("renew")
}
makeProcessLicenseRequestMessage(e, t, i) {
t = JSON.stringify([{
keyID: qc.base64Encode(e.decryptdata.keyId),
payload: qc.base64Encode(new Uint8Array(t))
}]);
return O.strToUtf8array(t)
}
handleKeyMessage(e) {
const t = e.target,
i = t.sessionId,
r = e.messageType,
n = this.sessionIdToKeyUri[i];
let s;
if (n) s = this.keyUriToKeyInfo[n];
else
for (const e of Object.values(this.keyUriToKeyInfo)) e && e.session === t && (s = e);
if (s) switch (r) {
case "license-request": {
const t = new Uint8Array(e.message),
i = O.utf8arrayToStr(t);
try {
JSON.parse(i).forEach(e => {
var t = qc.base64DecodeToStr(e.keyID),
e = qc.base64Decode(e.payload),
t = this.keyIdToKeyInfo[t];
t && this.resolveSPCPromise(t, e)
})
} catch (e) {
this.logger.warn("[Keys] got unexpected license-request format"), this.resolveSPCPromise(s, t)
}
break
}
case "license-renewal": {
const t = new Uint8Array(e.message);
this.resolveSPCPromise(s, t);
break
}
case "license-release":
this._handleLicenseRelease(t);
break;
default:
this.logger.warn(`[Keys] Unexpected messageType ${r}`)
} else this.logger.warn("[Keys] No key associated with session")
}
_handleLicenseRelease(e) {
e.update(O.strToUtf8array("acknowledged")).catch(e => {
this.logger.error(`Promise error: ${e.message}`)
})
}
};
const yh = {
initDataTypes: ["cenc"]
},
vh = new Uint8Array([154, 4, 240, 121, 152, 64, 66, 134, 171, 146, 230, 91, 224, 136, 95, 149]);
class Sh extends Zc {
constructor(e, t, i, r, n, s) {
super(e, t, i, r, !1, n, s), this.shouldDestroyMediaKeys = !0
}
static get systemId() {
return vh
}
static get requestAccessConfig() {
return yh
}
get needsCert() {
return !1
}
generateInitData(e, t) {
t = t.pssh;
return {
initData: ge.pssh(Sh.systemId, [], t),
initDataType: "cenc"
}
}
removeKey(e) {
return super.removeSessions(e, !0)
}
ensureKeyContext(e) {
const t = e.uri,
i = this.keyUriToKeyInfo[t];
return null != i && i.session && (i.oldSessions.push(i.session), i.session = null), super.ensureKeyContext(e)
}
getKeyRequestResponse(e, t) {
var i = e.decryptdata.uri,
r = e.setKeyRequestState(Kc.GET_KEY_RESPONSE);
return this.eventEmitter.trigger(x.LICENSE_CHALLENGE_CREATED, {
keyuri: i,
licenseChallenge: t,
keysystem: this.systemString,
keyId: e.decryptdata.keyId
}), r
}
generateRequestInitialized(e) {
var t = e.licenseChallenge;
return e.requestInfo = void 0, e.resolveState(Kc.GET_CHALLENGE, t), Wu
}
handleParsedKeyResponse(t, e) {
const i = t.decryptdata.uri,
r = e.statusCode;
if (0 !== r) return Vi(new gc("License server responded with error", i, r, {
code: r,
text: "Server error"
}, !1, rc.LicenseServerError));
if (!e.license || !e.license.byteLength) return Vi(new gc("License server responded with invalid license", i, r, {
code: r,
text: "Invalid license"
}, !1, rc.LicenseServerError));
if (e.renewalDate) {
const i = e.renewalDate,
r = new Date,
n = i > r ? i.getTime() - r.getTime() : 0;
0 < n && this._scheduleRenewal(t, n)
}
return en([t.setKeyRequestState(Kc.PROCESS_LICENSE), Fr(t.session.update(e.license)).pipe(Za(() => {
t.resolveState(Kc.PROCESS_LICENSE, void 0)
}), Vn(e => {
throw this.logger.error(`${this.systemString} FAIL: Failed to update with key response message=${e.message}`), new yc(e.message, t.decryptdata.uri, 0, $.KeySystemFailedToUpdateSession, this.systemString)
}))]).pipe(Zs(void 0))
}
handleKeyMessage(e) {
if (this.isDestroying) this.logger.warn("In the middle of destroying, ignore key message");
else {
const t = new DOMParser,
i = new("utf16" === this.config.playReadyMessageFormat ? Uint16Array : Uint8Array)(e.message.buffer || e.message),
r = String.fromCharCode.apply(null, Array.from(i)),
n = t.parseFromString(r, "application/xml").getElementsByTagName("PlayReadyKeyMessage")[0];
if (n && "LicenseAcquisition" === n.getAttribute("type")) {
const s = t.parseFromString(r, "application/xml").getElementsByTagName("Challenge")[0];
if (s && "base64encoded" === s.getAttribute("encoding") && 0 !== s.childNodes.length) {
const a = qc.base64Decode(s.childNodes[0].nodeValue),
o = O.utf8arrayToStr(a),
l = t.parseFromString(o, "application/xml").getElementsByTagName("KID")[0];
e = null, e = l.childNodes[0] ? l.childNodes[0].nodeValue : l.getAttribute("VALUE"), e = qc.base64Decode(e).subarray(0, 16);
Wc.changeEndianness(e);
const d = this.keyIdToKeyInfo[O.utf8arrayToStr(e)];
d && (d.licenseChallenge = a, d.resolveState(Kc.GET_CHALLENGE, a))
} else this.logger.warn(`${this.systemString} wrong challenge format or empty challenge`)
} else this.logger.warn(`${this.systemString} unrecognized message ignore it`)
}
}
}
w = Sh;
const bh = {
initDataTypes: ["cenc", "keyids"]
},
Th = new Uint8Array([237, 239, 139, 169, 121, 214, 74, 206, 163, 200, 39, 220, 213, 29, 33, 237]),
Eh = {
clearkey: th,
fairplaystreaming: Sc,
playready: Fc,
widevine: Bc
},
Ih = {
clearkey: [
["org.w3.clearkey", nu]
],
fairplaystreaming: [
["com.apple.fps.3_0", t],
["com.apple.fps", ru]
],
playready: [
["com.microsoft.playready.recommendation", w]
],
widevine: [
["com.widevine.alpha", class extends Zc {
constructor(e, t, i, r, n, s) {
super(e, t, i, r, !1, n, s), this.shouldDestroyMediaKeys = !0
}
static get systemId() {
return Th
}
static get requestAccessConfig() {
return bh
}
get needsCert() {
return !0
}
removeKey(e) {
return super.removeSessions(e, !0)
}
ensureKeyContext(e) {
const t = e.uri,
i = this.keyUriToKeyInfo[t];
return null != i && i.session && (i.oldSessions.push(i.session), i.session = null), super.ensureKeyContext(e)
}
getKeyRequestResponse(e, t) {
var i = e.decryptdata.uri,
r = e.setKeyRequestState(Kc.GET_KEY_RESPONSE);
return this.eventEmitter.trigger(x.LICENSE_CHALLENGE_CREATED, {
keyuri: i,
licenseChallenge: t,
keysystem: this.systemString,
keyId: e.decryptdata.keyId
}), r
}
handleParsedKeyResponse(t, e) {
t.licenseChallenge = void 0;
const i = t.decryptdata.uri,
r = e.statusCode;
if (0 !== r) return Vi(new gc("License server responded with error", i, r, {
code: r,
text: "Server error"
}, !1, rc.LicenseServerError));
if (!e.license || !e.license.byteLength) return Vi(new gc("License server responded with invalid license", i, r, {
code: r,
text: "Invalid license"
}, !1, rc.LicenseServerError));
if (e.renewalDate) {
const i = e.renewalDate,
r = new Date,
n = i > r ? i.getTime() - r.getTime() : 0;
0 < n && this._scheduleRenewal(t, n)
}
return en([t.setKeyRequestState(Kc.PROCESS_LICENSE), Fr(t.session.update(e.license)).pipe(Za(() => {
var e = t.decryptdata.keyId,
e = t.session.keyStatuses.get(e);
this.handleKeyStatusForKey(e, t)
}), Vn(e => {
throw this.logger.error(`${this.systemString} FAIL: Failed to update with key response code=${e.code} message=${e.message}`), new yc(e.message, t.decryptdata.uri, e.code, {
code: e.code,
text: "Failed to update with key response"
}, this.systemString)
}))]).pipe(Zs(void 0))
}
generateInitData(e, t) {
return {
initData: t.pssh,
initDataType: "cenc"
}
}
generateRequestInitialized(e) {
var t = e.licenseChallenge;
return e.requestInfo = void 0, e.resolveState(Kc.GET_CHALLENGE, t), Wu
}
handleKeyMessage(i) {
if (this.isDestroying) this.logger.warn("In the middle of destroying, ignore key message");
else {
const r = i.target;
let e = null,
t = null;
if (r.sessionId in this.sessionIdToKeyUri) e = this.sessionIdToKeyUri[r.sessionId], t = this.keyUriToKeyInfo[e];
else
for (const [i, n] of Object.entries(this.keyUriToKeyInfo))
if (n.session === r) {
e = i, t = n;
break
} if (t) switch (i.messageType) {
case "license-request": {
const r = new Uint8Array(i.message);
t.resolveState(Kc.GET_CHALLENGE, r);
break
}
} else this.logger.warn(`${this.systemString} empty keyuri and keyInfo`)
}
}
}]
]
},
wh = th.id;
class Ah {
createMediaKeys(t, e, i, r, n) {
let s = Ah.idToMediaKeysInfoMap[t];
if (!s) {
const a = Wc.getCapabilities(e, i),
o = new er;
Ah.requestKeySystemAccess(t, a, n, r).pipe(La(function(e) {
return Fr((Ah.idToMediaKeysInfoMap[t].keySystemAccess = e).createMediaKeys())
}), Za(e => {
o.next(e), o.complete()
}), Vn(e => (o.error(new yc(`could not initialize key system: ${e.message}`, void 0, 0, $.KeySystemFailedToInitialize, t)), Ii)), Va(Ah.destroy$)).subscribe(), s = Ah.idToMediaKeysInfoMap[t] = {
mediaKeys$: o,
keySystemAccess: null
}
}
return s.mediaKeys$
}
destroyMediaKeys() {
Ah.destroy$.next(), Ah.idToMediaKeysInfoMap = {}
}
static getKeySystemIdForDecryptData(e) {
let t;
if (e) {
t = wh;
var i = e.format;
for (const e of ih) {
var r = Eh[e];
if ((null == r ? void 0 : r.keyFormatString) === i) {
t = e;
break
}
}
}
if (!t) throw Error("No matching key system");
return t
}
static requestKeySystemAccess(e, t, i, r) {
if ("undefined" == typeof navigator || void 0 === navigator.requestMediaKeySystemAccess) return Vi(new yc("navigator undefined", void 0, 0, $.KeySystemUndefinedNavigator, e));
const n = Ih[e];
let s = Vi(new yc("no key systems to try", void 0, 0, $.KeySystemNoKeySystemsToTry, e));
for (const e of n) {
const n = e[0],
o = e[1],
l = (a = i) && "object" == typeof a ? i : o.requestAccessConfig,
d = [Object.assign({}, l, t)];
s = s.pipe(Vn(() => Ah.requestKeySystemInternal(n, d, r)))
}
var a;
return s
}
static requestKeySystemInternal(e, t, i) {
return Zr(() => Fr(navigator.requestMediaKeySystemAccess(e, t)))
}
make(e, t, i, r, n, s) {
var a = null === (l = Ah.idToMediaKeysInfoMap[e]) || void 0 === l ? void 0 : l.keySystemAccess;
if (!a) throw new yc(`No keySystemAccess for ${e}`, void 0, 0, $.KeySystemNoKeySystemAccess, e);
let o;
var l = Eh[e].systemStringPrefix;
for (const t of Ih[e])
if (t[0] === a.keySystem) {
o = t[1];
break
} if (!o) throw new yc(`No constructor associated with ${e}`, void 0, 0, $.KeySystemNoConstructor, l);
return new o(t, l, i, r, n, s)
}
static get availableKeySystems() {
return Object.keys(Eh)
}
static getKeySystemFormat(e) {
e = Eh[e];
return e ? e.keyFormatString : ""
}
static getKeySystemSecurityLevel(e) {
e = Eh[e];
return e ? e.securityLevels : void 0
}
}
Ah.idToMediaKeysInfoMap = {}, Ah.destroy$ = new Xt;
const Oh = ["avc1.42E01E"],
kh = ["mp4a.40.2"];
function Ch(e, t, i) {
if (t) {
if (t instanceof dr) t = new mc("Key request timed out", e, $.KeySystemRequestTimedOut);
else if (t instanceof yc) {
const i = (null == t ? void 0 : t.response) || $.InternalError;
t = new gc(t.message, e, 0, i, !1, rc.InternalError, !0)
}
} else t = new gc("Unknown error from CDM", e, 0, $.KeySystemCDMUnknownError, !1, rc.InternalError);
return (t instanceof gc || t instanceof mc) && (t.mediaOptionIds = [...i]), t
}
class Dh {
constructor(e, t, i, r, n, s, a, o = new Ah) {
this.ksService = e, this.mediaSink = t, this.config = i, this.platformQuery = r, this.eventEmitter = n, this.sessionHandler = s, this.keySystemFactory = o, this.reset$ = new Xt, this.keyRequest$ = new Xt, this.abort$ = new Xt, this.keySystem$ = new yi(null), this._keyStatusChange$ = new Xt, this.protectionData = {}, this.keySystemId = null, this.keyUriToRequest = {}, this.ksQuery = e.getQuery(), this.logger = a.child({
name: "eme"
}), this.config.warmupCdms && this.keySystemFactory.createMediaKeys(Sc.id, Oh, kh, this.logger, void 0).subscribe(), an(r.platformInfo$.pipe(Is((e, t) => e && t && e.requiresCDMAttachOnStart === t.requiresCDMAttachOnStart), La(e => null != e && e.requiresCDMAttachOnStart ? this.attachMediaKeys().pipe(Vn(e => (this.handleKeySystemError(e), Ii))) : Wu), $a(Ii)), this.keyRequest$.pipe(jr(e => e.pipe(Vn(() => Ii)))), this.keySystem$.pipe(La(e => e ? e.keyStatusChange$.pipe(Za(e => {
var t = e.decryptdata.uri,
i = this.ksQuery.getKeyInfo(t);
"needs-renewal" === e.status ? this.ksService.updateKeyRequestState(t, ic.MustRequestResponse, e => e === ic.GotKeyResponse) : (i = Ch(t, e.error, null !== (i = null == i ? void 0 : i.mediaOptionIds) && void 0 !== i ? i : []), this.ksService.setError(t, i)), this._keyStatusChange$.next(e)
})) : Ii)), this.isKeyCleanupSupported() ? this.mediaSink.mediaQuery.bufferedSegmentsTuple$.pipe(jr(e => {
const [t, i] = e, r = new Set;
return t.forEach(e => {
e = null === (e = null === (e = e.frag) || void 0 === e ? void 0 : e.keyTagInfo) || void 0 === e ? void 0 : e.uri;
e && r.add(e)
}), i.forEach(e => {
e = null === (e = null === (e = e.frag) || void 0 === e ? void 0 : e.keyTagInfo) || void 0 === e ? void 0 : e.uri;
e && r.add(e)
}), this.handleKeyCleanup(r)
})) : Wu).pipe(Va(this.reset$)).subscribe()
}
get keyStatusChange$() {
return this._keyStatusChange$
}
get keySystem() {
return this.keySystem$.value
}
destroy() {
this.reset$.next(), this.ksService.removeAll(), this.keySystemId = null;
const e = this.keySystem;
let t = Wu;
return e && (this.keySystem$.next(null), e.shouldDestroyMediaKeys && this.keySystemFactory.destroyMediaKeys(), t = e.destroy()), Mr([t, this.mediaSink.clearMediaKeys()]).pipe(Zs(void 0))
}
attachMediaKeys() {
if (this.keySystem) return Wu;
var e = this.config.keySystemPreference ? Ah.getKeySystemFormat(this.config.keySystemPreference) : Sc.keyFormatString;
return this.makeKeySystem(new zc("NONE", null, null, e, [1])).pipe(Zs(void 0))
}
isKeyCleanupSupported() {
return !0 === this.config.useMultipleKeySessions || "widevine" === this.config.keySystemPreference || "playready" === this.config.keySystemPreference
}
handleKeyCleanup(i) {
if (this.ksQuery.getCount() < 6) return Wu;
const r = performance.now(),
e = this.ksQuery.getAll().map(e => {
var t = e.keyUri;
if (!i.has(t)) {
const i = ac(e.decryptdata);
if ("AES-128" !== i.method && r > e.minHoldTime) return this._removeKey(t, i)
}
return Wu
});
return e.length ? en(e).pipe($a(Wu)) : Wu
}
_removeKey(e, t) {
return this.abort$.next(e), this.ksService.removeKey(e), this.keySystem.removeKey(t)
}
removeKeysForItems(i) {
const r = [];
return al(() => {
for (const e of i) {
this.ksService.removeAllKeysForItem(e);
const i = this.ksQuery.getAll({
filterBy: e => 0 === e.itemIds.length
});
for (const t of i) r.push(this._removeKey(t.keyUri, ac(t.decryptdata)))
}
}), r.length ? en(r).pipe(La(() => Wu)) : Wu
}
get availableKeySystems() {
return Ah.availableKeySystems
}
initialize(e) {
var t = this.protectionData;
this.protectionData = {};
var i = this.config.keySystemPreference;
for (const a of Ah.availableKeySystems) {
var r = e[a];
if (r)
if (i === a) {
var n, s = r.certificate,
r = r.serverCertUrl ? bu.buildAbsoluteURL(window.location.href, r.serverCertUrl) : void 0;
let e;
this.protectionData[a] = {
serverCertUrl: r,
certificate: s
}, s ? e = $i({
keysystem: a,
certificate: s
}) : r && (null === (n = null == t ? void 0 : t[a]) || void 0 === n ? void 0 : n.serverCertUrl) !== r && (n = Tu(r) ? this.config.certLoadPolicy.customURL : this.config.certLoadPolicy.default, e = Rc({
url: r,
xhrSetup: this.config.xhrSetup
}, n).pipe(hr(([e]) => ({
keysystem: a,
certificate: new Uint8Array(e)
})))), e && e.pipe(La(e => this.onServerCertificateLoaded(e)), Vn(e => {
throw this.logger.error(`Error loading cert: ${e.message}`), this.eventEmitter.trigger(x.INTERNAL_ERROR, {
type: o,
details: "certificateLoadError",
fatal: !1,
handled: !0,
reason: "Error handling cert",
response: $.KeySystemCertificateLoadError,
message: e.message,
name: "certificateLoadError"
}), e
}), Va(this.reset$)).subscribe()
} else this.logger.warn(`Key system ${a} does not match preference ${i}, ignoring`)
}
}
generateRequest(e, t) {
this.keySystem && this.keySystem.setKeyRequestInfo(e, t)
}
setLicenseResponse(e, t) {
this.keySystem && this.keySystem.setParsedResponse(e, t)
}
getKeyFromDecryptData(e, t) {
if (!e || !e.isEncrypted) return $i(e);
let i;
return al(() => {
i = this._getKeyFromDecryptData(e, t)
}), i
}
_getKeyFromDecryptData(t, i) {
let r = null,
n = null;
i && (r = i.itemId, n = i.mediaOptionId);
const s = t.uri,
e = this.ksQuery.getKeyInfo(s);
if (e && null != i && this.ksService.addMediaOption(s, i), (null == e ? void 0 : e.error) instanceof gc && !1 === e.error.isOkToRetry) return Vi(e.error);
if (e && e.requestState !== ic.MustRequestResponse) return e.requestState === ic.GotKeyResponse ? $i(ac(e.decryptdata)) : this.keyUriToRequest[s]; {
const o = performance.now() + this.config.keyMinHoldTimeBeforeCleanup;
let e;
this.abort$.next(s), this.ksService.upsertKey({
keyUri: s,
decryptdata: function(e) {
var {
method: t,
isEncrypted: i,
uri: r,
format: n,
formatversions: s
} = e;
return {
method: t,
isEncrypted: i,
uri: r,
format: n,
formatversions: s,
ivBuf: null !== (s = null === (s = e.iv) || void 0 === s ? void 0 : s.buffer) && void 0 !== s ? s : null,
keyIdBuf: null === (s = e.keyId) || void 0 === s ? void 0 : s.buffer,
keyBuf: null === (s = e.key) || void 0 === s ? void 0 : s.buffer,
psshBuf: null === (e = e.key) || void 0 === e ? void 0 : e.buffer
}
}(t),
minHoldTime: o,
mediaOptionIds: [n],
requestState: ic.WaitingForKeyResponse,
itemIds: [r]
});
var a = t.method;
switch (a) {
case "SAMPLE-AES":
case "ISO-23001-7":
case "SAMPLE-AES-CTR": {
const o = this.config.keyLoadPolicy.customURL;
e = this.fetchKeyEME(t).pipe(So(o.maxLoadTimeMs));
break
}
case "AES-128":
e = this.fetchKeyHTTP(t.uri, t, this.config.keyLoadPolicy);
break;
default:
return Vi(new V(!1, `Unexpected METHOD attribute ${a}`, $.KeySystemUnexpectedMETHOD))
}
i = this.keyUriToRequest[s] = e.pipe(hr(e => {
var t = e.decryptdata;
return this.ksService.updateKeyValue(s, t.key), this.eventEmitter.trigger(x.KEY_LOADED, e), e.decryptdata
}), Vn(e => {
var t = this.ksQuery.getKeyInfo(s);
return e = Ch(s, e, null !== (t = null == t ? void 0 : t.mediaOptionIds) && void 0 !== t ? t : []), this.ksService.setError(s, e), Vi(e)
}), Vs(() => {
this.ksService.updateKeyRequestState(s, ic.MustRequestResponse, e => e === ic.WaitingForKeyResponse), this.keyUriToRequest[s] = null
}), Aa(), Va(fn(this.abort$.pipe(ln(e => e === s)), this.reset$).pipe(Za(e => this.logger.warn(e ? `aborted ${le(e)}` : "got reset")))));
return this.keyRequest$.next(i), i
}
}
fetchKeyEME(e) {
return this.requestKey(e).pipe(hr(e => ({
timestamp: performance.now(),
keyuri: e.uri,
decryptdata: e
})))
}
fetchKeyHTTP(e, t, i) {
return Dh.fetchKeyHTTP(e, this.config, t, i)
}
static fetchKeyHTTP(t, e, i, r) {
e = {
url: t,
xhrSetup: e.xhrSetup
};
return Rc(e, Lc(e, r)).pipe(hr(([e]) => (i.key = new Uint8Array(e), {
decryptdata: i,
keyuri: t,
timestamp: performance.now()
})))
}
requestKey(t) {
return this.makeKeySystem(t).pipe(La(e => e.startKeyRequest(t)))
}
ensureKeySystem(t) {
return Zr(() => {
if (!this.keySystem && this.keySystemId) {
this.keySystem$.next(this.keySystemFactory.make(this.keySystemId, t, this.config, this.eventEmitter, this.sessionHandler, this.logger));
var e = this.protectionData && this.protectionData[this.keySystemId];
if (e) return this.keySystem.setServerCertificate(e.certificate).pipe(Zs(this.keySystem))
}
return $i(this.keySystem)
})
}
makeKeySystem(e) {
return this.ensureMediaKeys(e).pipe(La(e => this.mediaSink.setMediaKeys(e).pipe(La(() => this.ensureKeySystem(e)))))
}
ensureMediaKeys(e) {
var t = Ah.getKeySystemIdForDecryptData(e);
if (null == this.keySystemId) this.keySystemId = t;
else if (this.keySystemId !== t) return Vi(new gc(`New key system string does not match existing ${t} !== ${this.keySystemId}`, e.uri, 0, $.KeySystemUnmatchedString, !1, rc.InternalError));
return this.keySystemFactory.createMediaKeys(this.keySystemId, Oh, kh, this.logger, null === (e = this.platformQuery.platformInfo) || void 0 === e ? void 0 : e.keySystemConfig)
}
onServerCertificateLoaded(e) {
var t = e.keysystem,
e = e.certificate;
return this.protectionData[t].certificate = e, this.keySystem && this.keySystemId === t ? this.keySystem.setServerCertificate(e).pipe(Zs(void 0)) : Wu
}
handleKeySystemError(e) {
e = new yc(e.message, void 0, void 0, $.KeySystemSetupError, void 0);
this.eventEmitter.trigger(x.INTERNAL_ERROR, e)
}
}
class Mh extends kl {
constructor(e) {
super(e)
}
getKeyInfo(e) {
e = this.getEntity(e);
return e ? Object.assign(Object.assign({}, e), {
error: vc(e.error, e.mediaOptionIds)
}) : null
}
getKeyInfo$(e) {
return this.selectEntity(e).pipe(hr(e => e ? Object.assign(Object.assign({}, e), {
error: vc(e.error, e.mediaOptionIds)
}) : null))
}
getKeyRequestState$(e) {
return this.selectEntity(e, e => null == e ? void 0 : e.requestState)
}
getKeyStatus$(e) {
return this.selectEntity(e, e => null == e ? void 0 : e.status)
}
getKeyError$(e) {
return this.selectEntity(e, e => vc(null == e ? void 0 : e.error, null == e ? void 0 : e.mediaOptionIds)).pipe(wl)
}
}
class xh {
constructor(e) {
this.store = e
}
getQuery() {
return new Mh(this.store)
}
upsertKey(i) {
Do("keys.upsert", i.keyUri);
const r = new Set(i.itemIds.filter(e => null != e)),
n = new Set(i.mediaOptionIds.filter(e => null != e));
this.store.upsert(i.keyUri, e => {
const t = Object.assign(Object.assign({}, e), i);
if ("itemIds" in e)
for (const i of e.itemIds) r.add(i);
if (t.itemIds = Array.from(r), "mediaOptionIds" in e)
for (const i of e.mediaOptionIds) n.add(i);
return t.mediaOptionIds = Array.from(n), t
}, () => Object.assign(Object.assign({}, i), {
itemIds: Array.from(r),
mediaOptionIds: Array.from(n)
}))
}
removeKey(e) {
Do("keys.removeKey", e), this.store.remove(e)
}
removeAllKeysForItem(i) {
Do(`keys.removeAllKeysForItem ${i}`), this.store.update(null, e => {
var t = e.itemIds.findIndex(e => e === i);
0 <= t && e.itemIds.splice(t, 1)
})
}
removeAll() {
Do("keys.remove"), this.store.remove()
}
updateKeyValue(e, t) {
Do("keys.updateKeyValue", e), this.store.update(e, e => {
null == e.decryptdata.keyBuf && null != t && (e.decryptdata.keyBuf = t.buffer), e.requestState = ic.GotKeyResponse
})
}
updateKeyStatus(e, t) {
Do(`keys.updateKeyStatus ${t}`, e), this.store.update(e, e => {
e.status = t
})
}
updateKeyRequestState(e, t, i) {
Do(`keys.updateKeyRequestState ${t}`, e), this.store.update(e, e => {
i && !i(e.requestState) || (e.requestState = t)
})
}
addMediaOption(e, t) {
const {
itemId: i,
mediaOptionId: r
} = t;
Do(`keys.addMediaOption itemId: ${i}, mediaOptionId: ${r}`, e), this.store.update(e, e => {
null != r && e.mediaOptionIds.every(e => e !== r) && e.mediaOptionIds.push(r), null != i && e.itemIds.every(e => e !== i) && e.itemIds.push(i)
})
}
setError(e, t) {
var i;
Do(`keys.setError ${null===(i=null==t?void 0:t.constructor)||void 0===i?void 0:i.name}`, e), this.store.update(e, e => {
e.error = vc(t), e.requestState = ic.MustRequestResponse
})
}
}
const Ph = new class extends fl {
constructor() {
super({}, {
name: "key-system-store",
idKey: "keyUri",
producerFn: su
})
}
};
let Rh = null;
function Lh(e) {
let t = e;
return Nh.hasOwnProperty(e) && (t = Nh[e]), String.fromCharCode(t)
}
function _h(t) {
const i = [];
for (let e = 0; e < t.length; e++) i.push(t[e].toString(16));
return i
}
const Nh = {
42: 225,
92: 233,
94: 237,
95: 243,
96: 250,
123: 231,
124: 247,
125: 209,
126: 241,
127: 9608,
128: 174,
129: 176,
130: 189,
131: 191,
132: 8482,
133: 162,
134: 163,
135: 9834,
136: 224,
137: 32,
138: 232,
139: 226,
140: 234,
141: 238,
142: 244,
143: 251,
144: 193,
145: 201,
146: 211,
147: 218,
148: 220,
149: 252,
150: 8216,
151: 161,
152: 42,
153: 8217,
154: 9473,
155: 169,
156: 8480,
157: 8226,
158: 8220,
159: 8221,
160: 192,
161: 194,
162: 199,
163: 200,
164: 202,
165: 203,
166: 235,
167: 206,
168: 207,
169: 239,
170: 212,
171: 217,
172: 249,
173: 219,
174: 171,
175: 187,
176: 195,
177: 227,
178: 205,
179: 204,
180: 236,
181: 210,
182: 242,
183: 213,
184: 245,
185: 123,
186: 125,
187: 92,
188: 94,
189: 95,
190: 124,
191: 8764,
192: 196,
193: 228,
194: 214,
195: 246,
196: 223,
197: 165,
198: 164,
199: 9475,
200: 197,
201: 229,
202: 216,
203: 248,
204: 9487,
205: 9491,
206: 9495,
207: 9499
},
Fh = 100,
Bh = {
17: 1,
18: 3,
21: 5,
22: 7,
23: 9,
16: 11,
19: 12,
20: 14
},
Uh = {
17: 2,
18: 4,
21: 6,
22: 8,
23: 10,
19: 13,
20: 15
},
$h = {
25: 1,
26: 3,
29: 5,
30: 7,
31: 9,
24: 11,
27: 12,
28: 14
},
Vh = {
25: 2,
26: 4,
29: 6,
30: 8,
31: 10,
27: 13,
28: 15
},
Kh = ["white", "green", "blue", "cyan", "red", "yellow", "magenta", "black", "transparent"],
qh = {
verboseFilter: {
DATA: 3,
DEBUG: 3,
INFO: 2,
WARNING: 2,
TEXT: 1,
ERROR: 0
},
time: null,
verboseLevel: 0,
setTime: function(e) {
this.time = e
},
log: function(e, t) {
var i = this.verboseFilter[e];
this.verboseLevel >= i && console.log(this.time + " [" + e + "] " + t)
}
};
class Hh {
constructor(e, t, i, r, n) {
this.foreground = e || "white", this.underline = t || !1, this.italics = i || !1, this.background = r || "black", this.flash = n || !1
}
reset() {
this.foreground = "white", this.underline = !1, this.italics = !1, this.background = "black", this.flash = !1
}
setStyles(e) {
Object.assign(this, e)
}
isDefault() {
return "white" === this.foreground && !this.underline && !this.italics && "black" === this.background && !this.flash
}
equals(e) {
return this.foreground === e.foreground && this.underline === e.underline && this.italics === e.italics && this.background === e.background && this.flash === e.flash
}
copy(e) {
this.foreground = e.foreground, this.underline = e.underline, this.italics = e.italics, this.background = e.background, this.flash = e.flash
}
toString() {
return "color=" + this.foreground + ", underline=" + this.underline + ", italics=" + this.italics + ", background=" + this.background + ", flash=" + this.flash
}
}
class jh {
constructor(e, t, i, r, n, s) {
this.uchar = e || " ", this.penState = new Hh(t, i, r, n, s)
}
reset() {
this.uchar = " ", this.penState.reset()
}
setChar(e, t) {
this.uchar = e, this.penState.copy(t)
}
setPenState(e) {
this.penState.copy(e)
}
equals(e) {
return this.uchar === e.uchar && this.penState.equals(e.penState)
}
copy(e) {
this.uchar = e.uchar, this.penState.copy(e.penState)
}
isEmpty() {
return " " === this.uchar && this.penState.isDefault()
}
}
class Qh {
constructor() {
this.chars = [];
for (let e = 0; e < Fh; e++) this.chars.push(new jh);
this.pos = 0, this.currPenState = new Hh
}
equals(t) {
let i = !0;
for (let e = 0; e < Fh; e++)
if (!this.chars[e].equals(t.chars[e])) {
i = !1;
break
} return i
}
copy(t) {
for (let e = 0; e < Fh; e++) this.chars[e].copy(t.chars[e])
}
isEmpty() {
let t = !0;
for (let e = 0; e < Fh; e++)
if (!this.chars[e].isEmpty()) {
t = !1;
break
} return t
}
setCursor(e) {
this.pos !== e && (this.pos = e), this.pos < 0 ? (qh.log("ERROR", "Negative cursor position " + this.pos), this.pos = 0) : this.pos > Fh && (qh.log("ERROR", "Too large cursor position " + this.pos), this.pos = Fh)
}
moveCursor(e) {
var t = this.pos + e;
if (1 < e)
for (let e = this.pos + 1; e < t + 1; e++) this.chars[e].setPenState(this.currPenState);
this.setCursor(t)
}
backSpace() {
this.moveCursor(-1), this.chars[this.pos].setChar(" ", this.currPenState)
}
insertChar(e) {
144 <= e && this.backSpace();
var t = Lh(e);
this.pos >= Fh ? qh.log("ERROR", "Cannot insert " + e.toString(16) + " (" + t + ") at position " + this.pos + ". Skipping it!") : (this.chars[this.pos].setChar(t, this.currPenState), this.moveCursor(1))
}
clearFromPos(e) {
let t;
for (t = e; t < Fh; t++) this.chars[t].reset()
}
clear() {
this.clearFromPos(0), this.pos = 0, this.currPenState.reset()
}
clearToEndOfRow() {
this.clearFromPos(this.pos)
}
getTextString() {
const t = [];
let i = !0;
for (let e = 0; e < Fh; e++) {
var r = this.chars[e].uchar;
" " !== r && (i = !1), t.push(r)
}
return i ? "" : t.join("")
}
setPenStyles(e) {
this.currPenState.setStyles(e), this.chars[this.pos].setPenState(this.currPenState)
}
}
class Wh {
constructor() {
this.rows = [];
for (let e = 0; e < 15; e++) this.rows.push(new Qh);
this.currRow = 14, this.nrRollUpRows = null, this.reset()
}
reset() {
for (let e = 0; e < 15; e++) this.rows[e].clear();
this.currRow = 14
}
equals(t) {
let i = !0;
for (let e = 0; e < 15; e++)
if (!this.rows[e].equals(t.rows[e])) {
i = !1;
break
} return i
}
copy(t) {
for (let e = 0; e < 15; e++) this.rows[e].copy(t.rows[e])
}
isEmpty() {
let t = !0;
for (let e = 0; e < 15; e++)
if (!this.rows[e].isEmpty()) {
t = !1;
break
} return t
}
backSpace() {
this.rows[this.currRow].backSpace()
}
clearToEndOfRow() {
this.rows[this.currRow].clearToEndOfRow()
}
insertChar(e) {
this.rows[this.currRow].insertChar(e)
}
setPen(e) {
this.rows[this.currRow].setPenStyles(e)
}
moveCursor(e) {
this.rows[this.currRow].moveCursor(e)
}
setCursor(e) {
qh.log("INFO", "setCursor: " + e), this.rows[this.currRow].setCursor(e)
}
setPAC(t) {
qh.log("INFO", "pacData = " + JSON.stringify(t));
let i = t.row - 1;
if (this.nrRollUpRows && i < this.nrRollUpRows - 1 && (i = this.nrRollUpRows - 1), this.nrRollUpRows && this.currRow !== i) {
for (let e = 0; e < 15; e++) this.rows[e].clear();
const t = this.currRow + 1 - this.nrRollUpRows,
r = this.lastOutputScreen;
if (r) {
const e = r.rows[t].cueStartTime;
if (e && e < qh.time)
for (let e = 0; e < this.nrRollUpRows; e++) this.rows[i - this.nrRollUpRows + e + 1].copy(r.rows[t + e])
}
}
this.currRow = i;
const r = this.rows[this.currRow];
if (null !== t.indent) {
const i = t.indent,
e = Math.max(i - 1, 0);
r.setCursor(t.indent), t.color = r.chars[e].penState.foreground
}
const e = {
foreground: t.color,
underline: t.underline,
italics: t.italics,
background: "black",
flash: !1
};
this.setPen(e)
}
setBkgData(e) {
qh.log("INFO", "bkgData = " + JSON.stringify(e)), this.backSpace(), this.setPen(e), this.insertChar(32)
}
setRollUpRows(e) {
this.nrRollUpRows = e
}
rollUp() {
if (null !== this.nrRollUpRows) {
qh.log("INFO", "TEXT " + this.getDisplayText());
const e = this.currRow + 1 - this.nrRollUpRows,
t = this.rows.splice(e, 1)[0];
t.clear(), this.rows.splice(this.currRow, 0, t), qh.log("INFO", "Rolling up")
} else qh.log("DEBUG", "roll_up but nrRollUpRows not set yet")
}
getDisplayText(t) {
t = t || !1;
const i = [];
let e = "",
r;
for (let e = 0; e < 15; e++) {
const n = this.rows[e].getTextString();
n && (r = e + 1, t ? i.push("Row " + r + ": '" + n + "'") : i.push(n.trim()))
}
return 0 < i.length && (e = t ? "[" + i.join(" | ") + "]" : i.join("\n")), e
}
getTextAndFormat() {
return this.rows
}
}
class Gh {
constructor(e, t) {
this.chNr = e, this.outputFilter = t, this.mode = null, this.verbose = 0, this.displayedMemory = new Wh, this.nonDisplayedMemory = new Wh, this.lastOutputScreen = new Wh, this.currRollUpRow = this.displayedMemory.rows[14], this.writeScreen = this.displayedMemory, this.mode = null, this.cueStartTime = null
}
reset() {
this.mode = null, this.displayedMemory.reset(), this.nonDisplayedMemory.reset(), this.lastOutputScreen.reset(), this.currRollUpRow = this.displayedMemory.rows[14], this.writeScreen = this.displayedMemory, this.mode = null, this.cueStartTime = null, this.lastCueEndTime = null
}
getHandler() {
return this.outputFilter
}
setHandler(e) {
this.outputFilter = e
}
setPAC(e) {
this.writeScreen.setPAC(e)
}
setBkgData(e) {
this.writeScreen.setBkgData(e)
}
setMode(e) {
e !== this.mode && (this.mode = e, qh.log("INFO", "MODE=" + e), "MODE_POP-ON" === this.mode ? this.writeScreen = this.nonDisplayedMemory : (this.writeScreen = this.displayedMemory, this.writeScreen.reset()), "MODE_ROLL-UP" !== this.mode && (this.displayedMemory.nrRollUpRows = null, this.nonDisplayedMemory.nrRollUpRows = null), this.mode = e)
}
insertChars(t) {
for (let e = 0; e < t.length; e++) this.writeScreen.insertChar(t[e]);
var e = this.writeScreen === this.displayedMemory ? "DISP" : "NON_DISP";
qh.log("INFO", e + ": " + this.writeScreen.getDisplayText(!0)), "MODE_PAINT-ON" !== this.mode && "MODE_ROLL-UP" !== this.mode || (qh.log("TEXT", "DISPLAYED: " + this.displayedMemory.getDisplayText(!0)), this.outputDataUpdate())
}
ccRCL() {
qh.log("INFO", "RCL - Resume Caption Loading"), this.setMode("MODE_POP-ON")
}
ccBS() {
qh.log("INFO", "BS - BackSpace"), "MODE_TEXT" !== this.mode && (this.writeScreen.backSpace(), this.writeScreen === this.displayedMemory && this.outputDataUpdate())
}
ccAOF() {}
ccAON() {}
ccDER() {
qh.log("INFO", "DER- Delete to End of Row"), this.writeScreen.clearToEndOfRow(), this.outputDataUpdate()
}
ccRU(e) {
qh.log("INFO", "RU(" + e + ") - Roll Up"), this.writeScreen = this.displayedMemory, this.setMode("MODE_ROLL-UP"), this.writeScreen.setRollUpRows(e)
}
ccFON() {
qh.log("INFO", "FON - Flash On"), this.writeScreen.setPen({
flash: !0
})
}
ccRDC() {
qh.log("INFO", "RDC - Resume Direct Captioning"), this.setMode("MODE_PAINT-ON")
}
ccTR() {
qh.log("INFO", "TR"), this.setMode("MODE_TEXT")
}
ccRTD() {
qh.log("INFO", "RTD"), this.setMode("MODE_TEXT")
}
ccEDM() {
qh.log("INFO", "EDM - Erase Displayed Memory"), this.displayedMemory.reset(), this.outputDataUpdate(!0)
}
ccCR() {
qh.log("INFO", "CR - Carriage Return"), this.writeScreen.rollUp(), this.outputDataUpdate(!0)
}
ccENM() {
qh.log("INFO", "ENM - Erase Non-displayed Memory"), this.nonDisplayedMemory.reset()
}
ccEOC() {
var e;
qh.log("INFO", "EOC - End Of Caption"), "MODE_POP-ON" === this.mode && (e = this.displayedMemory, this.displayedMemory = this.nonDisplayedMemory, this.nonDisplayedMemory = e, this.writeScreen = this.nonDisplayedMemory, qh.log("TEXT", "DISP: " + this.displayedMemory.getDisplayText())), this.outputDataUpdate(!0)
}
ccTO(e) {
qh.log("INFO", "TO(" + e + ") - Tab Offset"), this.writeScreen.moveCursor(e)
}
ccMIDROW(e) {
const t = {
flash: !1,
underline: !1,
italics: !1
};
t.underline = e % 2 == 1, t.italics = 46 <= e, t.italics ? t.foreground = "white" : (e = Math.floor(e / 2) - 16, t.foreground = ["white", "green", "blue", "cyan", "red", "yellow", "magenta"][e]), qh.log("INFO", "MIDROW: " + JSON.stringify(t)), this.writeScreen.setPen(t)
}
outputDataUpdate(e = !1) {
var t = qh.time;
null !== t && this.outputFilter && (this.outputFilter.updateData && this.outputFilter.updateData(t, this.displayedMemory), null !== this.cueStartTime || this.displayedMemory.isEmpty() ? this.displayedMemory.equals(this.lastOutputScreen) || (this.outputFilter.newCue && (this.outputFilter.newCue(this.cueStartTime, t, this.lastOutputScreen), !0 === e && this.outputFilter.dispatchCue && this.outputFilter.dispatchCue()), this.cueStartTime = this.displayedMemory.isEmpty() ? null : t) : this.cueStartTime = t, this.lastOutputScreen.copy(this.displayedMemory))
}
cueSplitAtTime(e) {
this.outputFilter && (this.displayedMemory.isEmpty() || (this.outputFilter.newCue && this.outputFilter.newCue(this.cueStartTime, e, this.displayedMemory), this.cueStartTime = e))
}
}
var zh = class {
constructor(e = 1, t, i) {
this.field = e, this.currChNr = -1, this.lastCmdA = null, this.lastCmdB = null, this.channels = [new Gh(1, t), new Gh(2, i)], this.dataCounters = {
padding: 0,
char: 0,
cmd: 0,
other: 0
}
}
getHandler(e) {
return this.channels[e].getHandler()
}
setHandler(e, t) {
this.channels[e].setHandler(t)
}
addData(e, t) {
let i, r, n, s = null;
qh.setTime(e);
for (let e = 0; e < t.length; e += 2) r = 127 & t[e], n = 127 & t[e + 1], 16 <= r && r <= 31 && r === this.lastCmdA && n === this.lastCmdB ? (this.lastCmdA = null, this.lastCmdB = null, qh.log("DEBUG", "Repeated command (" + _h([r, n]) + ") is dropped")) : 0 != r || 0 != n ? (qh.log("DATA", "[" + _h([t[e], t[e + 1]]) + "] -> (" + _h([r, n]) + ")"), i = this.parseCmd(r, n), i = i || this.parseMidrow(r, n), i = i || this.parsePAC(r, n), i = i || this.parseBackgroundAttributes(r, n), !i && (s = this.parseChars(r, n), s) && (this.currChNr && 0 <= this.currChNr ? this.channels[this.currChNr - 1].insertChars(s) : qh.log("WARNING", "No channel found yet. TEXT-MODE?")), i ? this.dataCounters.cmd += 2 : s ? this.dataCounters.char += 2 : (this.dataCounters.other += 2, qh.log("WARNING", "Couldn't parse cleaned data " + _h([r, n]) + " orig: " + _h([t[e], t[e + 1]])))) : this.dataCounters.padding += 2
}
parseCmd(e, t) {
var i;
if (!((20 === e || 21 === e || 28 === e || 29 === e) && 32 <= t && t <= 47 || (23 === e || 31 === e) && 33 <= t && t <= 35)) return !1;
const r = this.channels[(i = 20 === e || 23 === e ? 1 : 2) - 1];
return 20 === e || 21 === e || 28 === e || 29 === e ? 32 === t ? r.ccRCL() : 33 === t ? r.ccBS() : 34 === t ? r.ccAOF() : 35 === t ? r.ccAON() : 36 === t ? r.ccDER() : 37 === t ? r.ccRU(2) : 38 === t ? r.ccRU(3) : 39 === t ? r.ccRU(4) : 40 === t ? r.ccFON() : 41 === t ? r.ccRDC() : 42 === t ? r.ccTR() : 43 === t ? r.ccRTD() : 44 === t ? r.ccEDM() : 45 === t ? r.ccCR() : 46 === t ? r.ccENM() : 47 === t && r.ccEOC() : r.ccTO(t - 32), this.lastCmdA = e, this.lastCmdB = t, this.currChNr = i, !0
}
parseMidrow(e, t) {
var i;
if ((17 === e || 25 === e) && 32 <= t && t <= 47) {
if ((i = 17 === e ? 1 : 2) !== this.currChNr) return qh.log("ERROR", "Mismatch channel in midrow parsing"), !1;
const r = this.channels[i - 1];
return r.insertChars([32]), r.ccMIDROW(t), qh.log("DEBUG", "MIDROW (" + _h([e, t]) + ")"), this.lastCmdA = e, this.lastCmdB = t, !0
}
return !1
}
parsePAC(e, t) {
if (!((17 <= e && e <= 23 || 25 <= e && e <= 31) && 64 <= t && t <= 127 || (16 === e || 24 === e) && 64 <= t && t <= 95)) return !1;
var i = e <= 23 ? 1 : 2,
r = (64 <= t && t <= 95 ? 1 == i ? Bh : $h : 1 == i ? Uh : Vh)[e],
r = this.interpretPAC(r, t);
return this.channels[i - 1].setPAC(r), this.lastCmdA = e, this.lastCmdB = t, this.currChNr = i, !0
}
interpretPAC(e, t) {
var i;
const r = {
color: null,
italics: !1,
indent: null,
underline: !1,
row: e
};
return i = 95 < t ? t - 96 : t - 64, r.underline = 1 == (1 & i), i <= 13 ? r.color = ["white", "green", "blue", "cyan", "red", "yellow", "magenta", "white"][Math.floor(i / 2)] : i <= 15 ? (r.italics = !0, r.color = "white") : r.indent = 4 * Math.floor((i - 16) / 2), r
}
parseChars(e, t) {
let i = null,
r = null,
n = null;
var s;
if (n = 25 <= e ? (i = 2, e - 8) : (i = 1, e), 17 <= n && n <= 19 ? (s = t, s = 17 === n ? t + 80 : 18 === n ? t + 112 : t + 144, qh.log("INFO", "Special char '" + Lh(s) + "' in channel " + i), r = [s], this.lastCmdA = e, this.lastCmdB = t) : 32 <= e && e <= 127 && (r = 0 === t ? [e] : [e, t], this.lastCmdA = null, this.lastCmdB = null), r) {
const e = _h(r);
qh.log("DEBUG", `Char codes = ${e.join(",")}`)
}
return r
}
parseBackgroundAttributes(e, t) {
let i, r, n;
return ((16 === e || 24 === e) && 32 <= t && t <= 47 || (23 === e || 31 === e) && 45 <= t && t <= 47) && (i = {
underline: !1
}, 16 === e || 24 === e ? (r = Math.floor((t - 32) / 2), i.background = Kh[r], t % 2 == 1 && (i.background = i.background + "_semi")) : 45 === t ? i.background = "transparent" : (i.foreground = "black", 47 === t && (i.underline = !0)), n = this.channels[(e < 24 ? 1 : 2) - 1], n.setBkgData(i), this.lastCmdA = null, !(this.lastCmdB = null))
}
reset() {
for (let e = 0; e < this.channels.length; e++) this.channels[e] && this.channels[e].reset();
this.lastCmdA = null, this.lastCmdB = null
}
cueSplitAtTime(t) {
for (let e = 0; e < this.channels.length; e++) this.channels[e] && this.channels[e].cueSplitAtTime(t)
}
};
class Xh {
constructor(e, t) {
this.handler = e, this.track = t, this.startTime = null, this.endTime = null, this.screen = null
}
dispatchCue() {
null !== this.startTime && (this.handler.addCues("cc" + this.track, this.startTime, this.endTime, this.screen), this.startTime = null)
}
newCue(e, t, i) {
(null === this.startTime || this.startTime > e) && (this.startTime = e), this.endTime = t, this.screen = i, this.handler.createHTMLCaptionsTrack(this.track)
}
}
var Yh = {},
iu = {},
nu = {},
t = {};
Object.defineProperty(t, "__esModule", {
value: !0
}), t.isValidPercentValue = function(e) {
return "number" == typeof e && 0 <= e && e <= 100
}, t.isValidAlignSetting = function(e) {
return "string" == typeof e && ["start", "center", "end", "left", "right", "middle"].includes(e)
}, t.isValidDirectionSetting = function(e) {
return "string" == typeof e && ["", "rl", "lr"].includes(e)
}, t.isValidLineAndPositionSetting = function(e) {
return "number" == typeof e || "auto" === e
}, t.isValidLineAlignSetting = function(e) {
return "string" == typeof e && ["start", "center", "end"].includes(e)
}, t.isValidPositionAlignSetting = function(e) {
return "string" == typeof e && ["line-left", "center", "line-right", "auto", "left", "start", "middle", "end", "right"].includes(e)
}, t.isValidScrollSetting = function(e) {
return ["", "up"].includes(e)
};
ru = {};
Object.defineProperty(ru, "__esModule", {
value: !0
});
const Jh = {
"&": "&",
"<": "<",
">": ">",
"": "‎",
"": "â€",
" ": "Â "
},
Zh = {
c: "span",
i: "i",
b: "b",
u: "u",
ruby: "ruby",
rt: "rt",
v: "span",
lang: "span"
},
ep = {
v: "title",
lang: "lang"
},
tp = {
rt: "ruby"
},
ip = {
"text-combine-upright": "-webkit-text-combine:horizontal; text-orientation: mixed;"
};
class rp {
static parseTimeStamp(e) {
function t(e) {
var [t, i, r, e] = e.map(e => e ? parseInt("" + e) : 0);
return 3600 * t + 60 * i + r + e / 1e3
}
const i = /^(\d+):(\d{2})(:\d{2})?\.(\d{3})/.exec(e);
return i ? i[3] ? t([i[1], i[2], i[3].substring(1), i[4]]) : 59 < parseInt(i[1]) ? t([i[1], i[2], null, i[4]]) : t([null, i[1], i[2], i[4]]) : null
}
static parseContent(s, t, a) {
let i = t.text;
function e(e) {
return Jh[e]
}
const r = s.document.createElement("div"),
n = [];
let o, l, d = r;
for (; null !== (o = function() {
if (!i) return null;
var e = (e = /^([^<]*)(<[^>]+>?)?/.exec(i))[1] || e[2];
return i = i.substr(e.length), e
}());)
if ("<" !== o[0]) d.appendChild(s.document.createTextNode(o.replace(/&(amp|lt|gt|lrm|rlm|nbsp);/g, e)));
else {
if ("/" === o[1]) {
n.length && n[n.length - 1] === o.substr(2).replace(">", "") && (n.pop(), d = d.parentNode);
continue
}
const t = rp.parseTimeStamp(o.substr(1, o.length - 2));
let e;
if (t) {
e = s.document.createProcessingInstruction("timestamp", t.toString()), d.appendChild(e);
continue
}
if (!(l = /^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/.exec(o))) continue;
if (e = function(e, t, i) {
var r = Zh[e];
if (!r) return null;
const n = s.document.createElement(r);
if (n.dataset.localName = r, (e = ep[e]) && i && (n[e] = i.trim()), t)
if (a[t]) {
const s = function(e) {
let t = "";
for (const i in e) t += ip[i] || i + ":" + e[i] + ";";
return t
}(a[t]);
n.setAttribute("style", s)
} else console.info(`WebVTT: parseContent: Style referenced, but no style defined for '${t}'!`);
return n
}(l[1], l[2], l[3]), !e) continue;
if (u = d, c = e, tp[c.dataset.localName] && tp[c.dataset.localName] !== u.dataset.localName) continue;
n.push(l[1]), d.appendChild(e), d = e
} var u, c;
return r
}
}
ru.default = rp;
w = e && e.__decorate || function(e, t, i, r) {
var n, s = arguments.length,
a = s < 3 ? t : null === r ? r = Object.getOwnPropertyDescriptor(t, i) : r;
if ("object" == typeof Reflect && "function" == typeof Reflect.decorate) a = Reflect.decorate(e, t, i, r);
else
for (var o = e.length - 1; 0 <= o; o--)(n = e[o]) && (a = (s < 3 ? n(a) : 3 < s ? n(t, i, a) : n(t, i)) || a);
return 3 < s && a && Object.defineProperty(t, i, a), a
};
Object.defineProperty(nu, "__esModule", {
value: !0
});
const np = t,
sp = ru;
w = w([function(e) {
let t = e;
return "undefined" != typeof window && null != window.VTTCue && (t = window.VTTCue, t.create = e.create, t.fromJSON = e.fromJSON, t.prototype.toJSON = e.prototype.toJSON), t
}], w = class {
constructor(e, t, i) {
this._id = "", this._pauseOnExit = !1, this._region = null, this._vertical = "", this._snapToLines = !0, this._line = "auto", this._lineAlign = "start", this._position = "auto", this._positionAlign = "auto", this._size = 100, this._align = "center", this.hasBeenReset = !1, this._startTime = e, this._endTime = t, this._text = i
}
get id() {
return this._id
}
set id(e) {
this._id = "" + e
}
get pauseOnExit() {
return this._pauseOnExit
}
set pauseOnExit(e) {
this._pauseOnExit = !!e
}
get startTime() {
return this._startTime
}
set startTime(e) {
if ("number" != typeof e) throw new TypeError(`Start time must be set to a number: ${e}`);
this._startTime = e, this.hasBeenReset = !0
}
get endTime() {
return this._endTime
}
set endTime(e) {
if ("number" != typeof e) throw new TypeError(`End time must be set to a number: ${e}`);
this._endTime = e, this.hasBeenReset = !0
}
get text() {
return this._text
}
set text(e) {
this._text = "" + e, this.hasBeenReset = !0
}
get region() {
return this._region
}
set region(e) {
this._region = e, this.hasBeenReset = !0
}
get vertical() {
return this._vertical
}
set vertical(e) {
if (!np.isValidDirectionSetting(e)) throw new SyntaxError(`An invalid or illegal string was specified for vertical: ${e}`);
this._vertical = e, this.hasBeenReset = !0
}
get snapToLines() {
return this._snapToLines
}
set snapToLines(e) {
this._snapToLines = !!e, this.hasBeenReset = !0
}
get line() {
return this._line
}
set line(e) {
if (!np.isValidLineAndPositionSetting(e)) throw new SyntaxError(`An invalid number or illegal string was specified for line: ${e}`);
this._line = e, this.hasBeenReset = !0
}
get lineAlign() {
return this._lineAlign
}
set lineAlign(e) {
if (!np.isValidLineAlignSetting(e)) throw new SyntaxError(`An invalid or illegal string was specified for lineAlign: ${e}`);
this._lineAlign = e, this.hasBeenReset = !0
}
get position() {
return this._position
}
set position(e) {
if (!np.isValidLineAndPositionSetting(e)) throw new Error(`Position must be between 0 and 100 or auto: ${e}`);
this._position = e, this.hasBeenReset = !0
}
get positionAlign() {
return this._positionAlign
}
set positionAlign(e) {
if (!np.isValidPositionAlignSetting(e)) throw new SyntaxError(`An invalid or illegal string was specified for positionAlign: ${e}`);
this._positionAlign = e, this.hasBeenReset = !0
}
get size() {
return this._size
}
set size(e) {
if (e < 0 || 100 < e) throw new Error(`Size must be between 0 and 100: ${e}`);
this._size = e, this.hasBeenReset = !0
}
get align() {
return this._align
}
set align(e) {
if (!np.isValidAlignSetting(e)) throw new SyntaxError(`An invalid or illegal string was specified for align: ${e}`);
this._align = e, this.hasBeenReset = !0
}
getCueAsHTML() {
return sp.default.parseContent(window, this, {})
}
static create(t) {
if (!t.hasOwnProperty("startTime") || !t.hasOwnProperty("endTime") || !t.hasOwnProperty("text")) throw new Error("You must at least have start time, end time, and text.");
const i = new this(t.startTime, t.endTime, t.text);
return Object.keys(t).forEach(e => {
i.hasOwnProperty(e) && (i[e] = t[e])
}), i
}
static fromJSON(e) {
return this.create(JSON.parse(e))
}
toJSON() {
const t = {};
return Object.keys(this).forEach(e => {
this.hasOwnProperty(e) && "getCueAsHTML" !== e && "hasBeenReset" !== e && "displayState" !== e && (t[e] = this[e])
}), t
}
});
nu.VTTCue = w;
w = {}, e = e && e.__decorate || function(e, t, i, r) {
var n, s = arguments.length,
a = s < 3 ? t : null === r ? r = Object.getOwnPropertyDescriptor(t, i) : r;
if ("object" == typeof Reflect && "function" == typeof Reflect.decorate) a = Reflect.decorate(e, t, i, r);
else
for (var o = e.length - 1; 0 <= o; o--)(n = e[o]) && (a = (s < 3 ? n(a) : 3 < s ? n(t, i, a) : n(t, i)) || a);
return 3 < s && a && Object.defineProperty(t, i, a), a
};
Object.defineProperty(w, "__esModule", {
value: !0
});
const ap = t;
e = e([function(e) {
let t = e;
return "undefined" != typeof window && null != window.VTTRegion && (t = window.VTTRegion, t.create = e.create, t.fromJSON = e.fromJSON, t.prototype.toJSON = e.prototype.toJSON), t
}], e = class {
constructor() {
this._id = "", this._lines = 3, this._regionAnchorX = 0, this._regionAnchorY = 100, this._scroll = "", this._viewportAnchorX = 0, this._viewportAnchorY = 100, this._width = 100
}
get id() {
return this._id
}
set id(e) {
if ("string" != typeof e) throw new Error("ID must be a string.");
this._id = e
}
get lines() {
return this._lines
}
set lines(e) {
if ("number" != typeof e) throw new TypeError("Lines must be set to a number.");
this._lines = e
}
get regionAnchorX() {
return this._regionAnchorX
}
set regionAnchorX(e) {
if (!ap.isValidPercentValue(e)) throw new TypeError("RegionAnchorX must be between 0 and 100.");
this._regionAnchorX = e
}
get regionAnchorY() {
return this._regionAnchorY
}
set regionAnchorY(e) {
if (!ap.isValidPercentValue(e)) throw new TypeError("RegionAnchorY must be between 0 and 100.");
this._regionAnchorY = e
}
get scroll() {
return this._scroll
}
set scroll(e) {
if ("string" == typeof e) {
e = e.toLowerCase();
if (ap.isValidScrollSetting(e)) return void(this._scroll = e)
}
throw new SyntaxError("An invalid or illegal string was specified.")
}
get viewportAnchorX() {
return this._viewportAnchorX
}
set viewportAnchorX(e) {
if (!ap.isValidPercentValue(e)) throw new TypeError("ViewportAnchorX must be between 0 and 100.");
this._viewportAnchorX = e
}
get viewportAnchorY() {
return this._viewportAnchorY
}
set viewportAnchorY(e) {
if (!ap.isValidPercentValue(e)) throw new TypeError("ViewportAnchorY must be between 0 and 100.");
this._viewportAnchorY = e
}
get width() {
return this._width
}
set width(e) {
if (!ap.isValidPercentValue(e)) throw new TypeError("Width must be between 0 and 100.");
this._lines = e
}
toJSON() {
const t = {};
return Object.keys(this).forEach(e => {
this.hasOwnProperty(e) && (t[e] = this[e])
}), t
}
static create(t) {
const i = new this;
return Object.keys(t).forEach(e => {
i.hasOwnProperty(e) && (i[e] = t[e])
}), i
}
static fromJSON(e) {
return this.create(JSON.parse(e))
}
});
w.VTTRegion = e, Object.defineProperty(iu, "__esModule", {
value: !0
});
const op = nu;
iu.VTTCue = op.VTTCue;
const lp = w;
iu.VTTRegion = lp.VTTRegion;
const dp = ru;
class up extends Error {
constructor(e, t) {
super(), this.name = "ParsingError", this.code = "number" == typeof e ? e : e.code, t ? this.message = t : e instanceof up && (this.message = e.message)
}
}(iu.ParsingError = up).Errors = {
BadSignature: new up(0, "Malformed WebVTT signature."),
BadTimeStamp: new up(1, "Malformed time stamp.")
};
class cp {
constructor() {
this.values = {}
}
set(e, t) {
this.get(e) || "" === t || (this.values[e] = t)
}
get(e, t, i) {
return "object" == typeof t && "string" == typeof i ? this.has(e) ? this.values[e] : t[i] : this.has(e) ? this.values[e] : t
}
has(e) {
return e in this.values
}
alt(t, i, r) {
for (let e = 0; e < r.length; ++e)
if (i === r[e]) {
this.set(t, i);
break
}
}
integer(e, t) {
/^-?\d+$/.test(t) && this.set(e, parseInt(t, 10))
}
percent(e, t) {
if (t.match(/^([\d]{1,3})(\.[\d]*)?%$/)) try {
var i = parseFloat(t);
if (0 <= i && i <= 100) return this.set(e, i), !0
} catch (e) {
return !1
}
return !1
}
}
class hp {
constructor(e, t, i) {
this.window = e, this.state = "INITIAL", this.styleCollector = "", this.buffer = "", this.decoder = t || new TextDecoder("utf8"), this.regionList = [], this.onStylesParsedCallback = i, this._styles = {}
}
static StringDecoder() {
return {
decode: e => {
if (!e) return "";
if ("string" != typeof e) throw new Error("Error - expected string data.");
return decodeURIComponent(encodeURIComponent(e))
}
}
}
reportOrThrowError(e) {
if (!(e instanceof up && "function" == typeof this.onparsingerror)) throw e;
this.onparsingerror(e)
}
parseOptions(e, t, i, r) {
e = r ? e.split(r) : [e];
for (const n of e)
if ("string" == typeof n) {
const r = n.split(i);
2 === r.length && t(r[0], r[1])
}
}
parseCue(t, e, a) {
const i = t,
r = () => {
var e = dp.default.parseTimeStamp(t);
if (null === e) throw new up(up.Errors.BadTimeStamp, "Malformed timestamp: " + i);
return t = t.replace(/^[^\sa-zA-Z-]+/, ""), e
},
n = () => {
t = t.replace(/^\s+/, "")
};
if (n(), e.startTime = r(), n(), "--\x3e" !== t.substr(0, 3)) throw new up(up.Errors.BadTimeStamp, `Malformed time stamp (time stamps must be separated by '--\x3e'): ${i}`);
t = t.substr(3), n(), e.endTime = r(), n(), ((e, t) => {
const s = new cp;
this.parseOptions(e, (t, i) => {
let e, r;
switch (t) {
case "region":
for (let e = a.length - 1; 0 <= e; e--)
if (a[e].id === i) {
s.set(t, a[e].region);
break
} break;
case "vertical":
s.alt(t, i, ["rl", "lr"]);
break;
case "line":
e = i.split(","), r = e[0], s.integer(t, r), s.percent(t, r) && s.set("snapToLines", !1), s.alt(t, r, ["auto"]), 2 === e.length && s.alt("lineAlign", e[1], ["start", "center", "end"]);
break;
case "position":
e = i.split(","), s.percent(t, e[0]), 2 === e.length && (n = ["line-left", "line-right", "center", "auto", "left", "start", "middle", "end", "right"], s.alt("positionAlign", e[1], n));
break;
case "size":
s.percent(t, i);
break;
case "align":
var n = ["start", "center", "end", "left", "right", "middle"];
s.alt(t, i, n)
}
}, /:/, /\s/), t.region = s.get("region", null), t.vertical = s.get("vertical", ""), t.line = s.get("line", void 0 === t.line ? "auto" : t.line), t.lineAlign = s.get("lineAlign", "start"), t.snapToLines = s.get("snapToLines", !0), t.size = s.get("size", 100);
e = s.get("align", "center");
t.align = "middle" === e ? "center" : e, t.position = s.get("position", "auto");
e = s.get("positionAlign", {
start: "start",
left: "start",
center: "center",
right: "end",
end: "end"
}, t.align);
t.positionAlign = {
start: "start",
"line-left": "start",
left: "start",
center: "center",
middle: "center",
"line-right": "end",
right: "end",
end: "end"
} [e]
})(t, e)
}
parseRegion(e) {
const n = new cp;
if (this.parseOptions(e, (e, t) => {
switch (e) {
case "id":
n.set(e, t);
break;
case "width":
n.percent(e, t);
break;
case "lines":
n.integer(e, t);
break;
case "regionanchor":
case "viewportanchor": {
var i = t.split(",");
if (2 !== i.length) break;
const r = new cp;
if (r.percent("x", i[0]), r.percent("y", i[1]), !r.has("x") || !r.has("y")) break;
n.set(e + "X", r.get("x")), n.set(e + "Y", r.get("y"));
break
}
case "scroll":
n.alt(e, t, ["up"])
}
}, /=/, /\s/), n.has("id")) {
const e = new lp.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", ""), this.onregion && this.onregion(e), this.regionList.push({
id: n.get("id"),
region: e
})
}
}
parseStyle(i) {
const e = i.split("}");
e.pop();
for (const i of e) {
let e = null,
t = null;
const r = i.split("{");
r[0] && (e = r[0].trim()), r[1] && (t = (e => {
const t = {},
i = e.split(";");
for (let e = 0; e < i.length; e++)
if (i[e].includes(":")) {
const r = i[e].split(":", 2),
n = r[0].trim(),
s = r[1].trim();
"" !== n && "" !== s && (t[n] = s)
} return t
})(r[1])), e && t && (this._styles[e] = t)
}
this.onStylesParsedCallback && this.onStylesParsedCallback(this._styles)
}
parseHeader(e) {
this.parseOptions(e, function(e, t) {
"Region" === e && this.parseRegion(t)
}, /:/)
}
parse(i) {
i && (this.buffer += this.decoder.decode(i, {
stream: !0
}));
const r = () => {
const e = this.buffer;
let t = 0;
let i = {
start: e.length,
length: 0
};
for (; t < e.length;) {
const r = ((t, i) => {
const r = {
start: -1,
length: -1
};
if ("\r" === t[i]) r.start = i, r.length = 1;
else if ("\n" === t[i]) r.start = i, r.length = 1;
else if ("<" === t[i] && i + 1 < t.length && "b" === t[i + 1] && i + 2 < t.length && "r" === t[i + 2]) {
let e = i + 2;
for (; e < t.length && ">" !== t[e++];);
r.start = i, r.length = e - i
}
return r
})(e, t);
if (0 < r.length) {
i = r;
break
}++t
}
const r = e.substr(0, i.start);
return this.buffer = e.substr(i.start + i.length), r
};
try {
let e;
if ("INITIAL" === this.state) {
if (!/\r\n|\n/.test(this.buffer)) return this;
e = r();
var n = /^()?WEBVTT([ \t].*)?$/.exec(e);
if (!n || !n[0]) throw new up(up.Errors.BadSignature);
this.state = "HEADER"
}
let t = !1;
for (; this.buffer;) {
if (!/\r\n|\n/.test(this.buffer)) return this;
switch (t ? t = !1 : e = r(), this.state) {
case "HEADER":
e.includes(":") ? this.parseHeader(e) : e || (this.state = "ID");
continue;
case "NOTE":
e || (this.state = "ID");
continue;
case "STYLE":
e ? this.styleCollector += e : (this.parseStyle(this.styleCollector), this.state = "ID", this.styleCollector = "");
continue;
case "ID":
if (/^NOTE($|[ \t])/.test(e)) {
this.state = "NOTE";
break
}
if (/^STYLE($|[ \t])/.test(e)) {
this.state = "STYLE";
break
}
if (!e) continue;
if (this.cue = new op.VTTCue(0, 0, ""), this.state = "CUE", !e.includes("--\x3e")) {
this.cue.id = e;
continue
}
case "CUE":
try {
this.parseCue(e, this.cue, this.regionList)
} catch (i) {
this.reportOrThrowError(i), this.cue = null, this.state = "BADCUE";
continue
}
this.state = "CUETEXT";
continue;
case "CUETEXT": {
const r = e.includes("--\x3e");
if (!e || r) {
t = !0, this.oncue && this.oncue(this.cue), this.cue = null, this.state = "ID";
continue
}
this.cue.text && (this.cue.text += "\n"), this.cue.text += e;
continue
}
case "BADCUE":
e || (this.state = "ID");
continue
}
}
} catch (i) {
this.reportOrThrowError(i), "CUETEXT" === this.state && this.cue && this.oncue && this.oncue(this.cue), this.cue = null, this.state = "INITIAL" === this.state ? "BADWEBVTT" : "BADCUE"
}
return this
}
flush() {
try {
if (this.buffer += this.decoder.decode(), !this.cue && "HEADER" !== this.state || (this.buffer += "\n\n", this.parse()), "INITIAL" === this.state) throw new up(up.Errors.BadSignature)
} catch (e) {
this.reportOrThrowError(e)
}
return this.onflush && this.onflush(), this
}
styles() {
return this._styles
}
}
iu.default = hp, iu.WebVTTParser = hp;
var pp, w = {};
Object.defineProperty(w, "__esModule", {
value: !0
});
const fp = nu;
w.VTTCue = fp.VTTCue;
const mp = ru,
gp = [/^(::cue\()(\..*)(\))/, /^(::cue\()(#.*)(\))/, /^(::cue\()(c|i|b|u|ruby|rt|v|lang)(\))/],
yp = [
[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]
];
class vp {
applyStyles(e, t) {
t = t || this.div;
for (const i in e) e.hasOwnProperty(i) && (t.style[i] = e[i])
}
formatStyle(e, t) {
return 0 === e ? "0" : e + t
}
}
w.StyleBox = vp;
class Sp extends vp {
constructor(e, t, i, r, n) {
super();
let s = {
textAlign: {
start: "left",
"line-left": "left",
left: "left",
center: "center",
middle: "center",
"line-right": "right",
right: "right",
end: "right"
} [(this.cue = t).positionAlign] || t.align,
whiteSpace: "pre-line",
position: "absolute"
};
s.direction = this.determineBidi(this.cueDiv), s.writingMode = this.directionSettingToWritingMode(t.vertical), s.unicodeBidi = "plaintext", this.div = e.document.createElement("div"), this.applyStyles(s), s = {
backgroundColor: r.backgroundColor,
display: "inline-block"
}, this.parseOpacity(s.backgroundColor) && (s.padding = "5px", s.borderRadius = "5px"), this.backgroundDiv = e.document.createElement("div"), this.applyStyles(s, this.backgroundDiv), s = {
color: i.color,
backgroundColor: i.backgroundColor,
textShadow: i.textShadow,
fontSize: i.fontSize,
fontFamily: i.fontFamily,
position: "relative",
left: "0",
right: "0",
top: "0",
bottom: "0",
display: "inline-block",
textOrientation: "upright"
}, s.writingMode = this.directionSettingToWritingMode(t.vertical), s.unicodeBidi = "plaintext", this.cueDiv = mp.default.parseContent(e, t, n), this.applyStyles(s, this.cueDiv), this.backgroundDiv.appendChild(this.cueDiv), this.div.appendChild(this.backgroundDiv);
let a = 0;
if ("number" == typeof t.position) {
n = t.positionAlign || t.align;
if (n) switch (n) {
case "start":
case "left":
a = t.position;
break;
case "center":
case "middle":
a = t.position - t.size / 2;
break;
case "end":
case "right":
a = t.position - t.size
}
}
"" === t.vertical ? this.applyStyles({
left: this.formatStyle(a, "%"),
width: this.formatStyle(t.size, "%")
}) : this.applyStyles({
top: this.formatStyle(a, "%"),
height: this.formatStyle(t.size, "%")
})
}
determineBidi(e) {
let t = [],
i = "";
if (!e || !e.childNodes) return "ltr";
function n(t, i) {
for (let e = i.childNodes.length - 1; 0 <= e; e--) t.push(i.childNodes[e])
}
for (n(t, e); i = function e(t) {
if (!t || !t.length) return null;
let i = t.pop(),
r = i.textContent || i.innerText;
if (r) {
const i = /^.*(\n|\r)/.exec(r);
return i ? i[t.length = 0] : r
}
return "ruby" === i.tagName ? e(t) : i.childNodes ? (n(t, i), e(t)) : void 0
}(t);)
for (let e = 0; e < i.length; e++)
if (function(e, t) {
for (const i of t)
if (e >= i[0] && e <= i[1]) return 1
}(i.charCodeAt(e), yp)) return "rtl";
return "ltr"
}
parseOpacity(e) {
if (!e || "string" != typeof e) return null;
e = (e = e.replace(/ /g, "").replace("rgba(", "").replace(")", "")).split(",");
return e && 4 <= e.length ? e[3] : null
}
directionSettingToWritingMode(e) {
return "" === e ? "horizontal-tb" : "lr" === e ? "vertical-lr" : "vertical-rl"
}
move(e) {
this.applyStyles({
top: this.formatStyle(e.top, "px"),
bottom: this.formatStyle(e.bottom, "px"),
left: this.formatStyle(e.left, "px"),
right: this.formatStyle(e.right, "px"),
height: this.formatStyle(e.height, "px"),
width: this.formatStyle(e.width, "px")
})
}
}
w.CueStyleBox = Sp;
class bp {
constructor(e) {
var t;
let i, r, n, s, a, o;
if (e instanceof Sp && e.cue ? (t = e.cue) && "" !== t.vertical ? this.property = "width" : this.property = "height" : e instanceof bp && (this.property = e.property || "height"), e instanceof Sp && e.div) {
n = e.div.offsetHeight, s = e.div.offsetWidth, a = e.div.offsetTop;
const t = e.div.firstChild;
if (o = (t || e.div).getBoundingClientRect(), i = o && o[this.property] || null, t && t.firstChild) {
const e = t.firstChild;
e && "string" == typeof e.textContent && (r = i / this.calculateNewLines(e.textContent))
}
} else e instanceof bp && (o = e);
this.left = o.left, this.right = o.right, this.top = o.top || a, this.height = o.height || n, this.bottom = o.bottom || a + (o.height || n), this.width = o.width || s, this.lineHeight = null !== i ? i : o.lineHeight, this.singleLineHeight = null !== r ? r : o.singleLineHeight, this.singleLineHeight || (this.singleLineHeight = 41)
}
calculateNewLines(t) {
let i = 1;
for (let e = 0; e < t.length; e++) "\n" === t[e] && i++;
return i
}
move(e, t) {
switch (t = void 0 !== t ? t : this.singleLineHeight, e) {
case "+x":
this.left += t, this.right += t;
break;
case "-x":
this.left -= t, this.right -= t;
break;
case "+y":
this.top += t, this.bottom += t;
break;
case "-y":
this.top -= t, this.bottom -= t
}
}
overlaps(e) {
return this.left < e.right && this.right > e.left && this.top < e.bottom && this.bottom > e.top
}
overlapsAny(e) {
for (const t of e)
if (this.overlaps(t)) return !0;
return !1
}
within(e) {
return this.top >= e.top && this.bottom <= e.bottom && this.left >= e.left && this.right <= e.right
}
moveIfOutOfBounds(e, t) {
switch (t) {
case "+x":
this.left < e.left && (this.left = e.left, this.right = this.left + this.width);
break;
case "-x":
this.right > e.right && (this.right = e.right, this.left = this.right - this.width);
break;
case "+y":
this.top < e.top && (this.top = e.top, this.bottom = this.top + this.height);
break;
case "-y":
this.bottom > e.bottom && (this.bottom = e.bottom, this.top = this.bottom - this.height)
}
}
toCSSCompatValues(e) {
return {
top: this.top - e.top,
bottom: e.bottom - this.bottom,
left: this.left - e.left,
right: e.right - this.right,
height: this.height,
width: this.width
}
}
static getSimpleBoxPosition(e) {
let t = null;
e instanceof vp && e.div ? t = e.div : e instanceof HTMLElement && (t = e);
let i = t.offsetHeight || 0,
r = t.offsetWidth || 0,
n = t.offsetTop || 0,
s = n + i,
a = t.getBoundingClientRect();
var {
left: o,
right: e
} = a;
return a.top && (n = a.top), a.height && (i = a.height), a.width && (r = a.width), a.bottom && (s = a.bottom), {
left: o,
right: e,
top: n,
height: i,
bottom: s,
width: r
}
}
static getBoxPosition(r, n) {
if (r && 0 < r.length) {
let t = 0,
i = r[0][n];
for (let e = 0; e < r.length; e++) n in ["top", "right"] ? r[e][n] > i && (t = e, i = r[e][n]) : n in ["bottom", "left"] && r[e][n] < i && (t = e, i = r[e][n]);
return r[t]
}
return null
}
static moveToMinimumDistancePlacement(e, t, i) {
"height" === e.property ? "+y" === t ? (e.top = i.topMostBoxPosition.bottom + 0, e.bottom = e.top + e.height) : "-y" === t && (e.bottom = +i.bottomMostBoxPosition.top, e.top = e.bottom - e.height) : "width" === e.property && ("+x" === t ? (e.left = i.rightMostBoxPosition.right + 0, e.right = e.left + e.width) : "-x" === t && (e.right = +i.leftMostBoxPosition.left, e.left = e.right - e.width))
}
static moveBoxToLinePosition(e, a, o) {
var n = e.cue;
let i, r = new bp(e),
s = function() {
if ("number" == typeof n.line && (n.snapToLines || 0 <= n.line && n.line <= 100)) return n.line;
if (!n.track || !n.track.textTrackList || !n.track.textTrackList.mediaElement) return -1;
let t = 0;
var i = n.track,
r = i.textTrackList;
for (let e = 0; e < r.length && r[e] !== i; e++) "showing" === r[e].mode && t++;
return -1 * ++t
}(),
l = [];
if (n.snapToLines) {
let t = 0;
switch (n.vertical) {
case "":
l = ["+y", "-y"], i = "height";
break;
case "rl":
l = ["+x", "-x"], i = "width";
break;
case "lr":
l = ["-x", "+x"], i = "width"
}
const o = r.lineHeight,
d = a[i] + o,
u = l[0];
if (s < 0) {
let e = 0;
switch (n.vertical) {
case "":
e = a.height - o - .05 * a.height;
break;
case "rl":
case "lr":
e = -a.width + o + .05 * a.width
}
t = e, l = l.reverse()
} else {
switch (n.vertical) {
case "":
t = o * Math.round(s);
break;
case "rl":
t = a.width - o * Math.round(s);
break;
case "lr":
t = o * Math.round(s)
}
Math.abs(t) > d && (t = t < 0 ? -1 : 1, t *= Math.ceil(d / o) * o)
}
r.move(u, t)
} else {
const o = "" === n.vertical ? a.height : a.width,
i = r.lineHeight / o * 100;
switch (n.lineAlign) {
case "center":
s -= i / 2;
break;
case "end":
s -= i
}
switch (n.vertical) {
case "":
e.applyStyles({
top: e.formatStyle(s, "%")
});
break;
case "rl":
e.applyStyles({
right: e.formatStyle(s, "%")
});
break;
case "lr":
e.applyStyles({
left: e.formatStyle(s, "%")
})
}
l = ["+y", "-y", "+x", "-x"], "+y" === n.axis ? l = ["+y", "-y", "+x", "-x"] : "-y" === n.axis && (l = ["-y", "+y", "+x", "-x"]), r = new bp(e)
}
const d = function(r, n) {
let s;
for (let i = 0; i < n.length; i++) {
r.moveIfOutOfBounds(a, n[i]);
let e = 0,
t = !1;
for (; r.overlapsAny(o) && !(9 < e);) t ? r.move(n[i]) : (o && 0 < o.length && (s = s || {
topMostBoxPosition: bp.getBoxPosition(o, "top"),
bottomMostBoxPosition: bp.getBoxPosition(o, "bottom"),
leftMostBoxPosition: bp.getBoxPosition(o, "left"),
rightMostBoxPosition: bp.getBoxPosition(o, "right")
}, bp.moveToMinimumDistancePlacement(r, n[i], s)), t = !0), e++
}
return r
}(r, l);
e.move(d.toCSSCompatValues(a))
}
}
w.BoxPosition = bp;
class Tp {
constructor(e, t, i = !0) {
if (!e) return null;
this.window = e, this.overlay = t, this.loggingEnabled = i, this.foregroundStyleOptions = {
fontFamily: "Helvetica",
fontSize: "36px",
color: "rgba(255, 255, 255, 1)",
textShadow: "",
backgroundColor: "rgba(0, 0, 0, 0)"
}, this.backgroundStyleOptions = {
backgroundColor: "rgba(0, 0, 0, 0.5)"
}, this.globalStyleCollection = {};
const r = e.document.createElement("div");
r.style.position = "absolute", r.style.left = "0", r.style.right = "0", r.style.top = "0", r.style.bottom = "0", r.style.margin = "1.5%", this.paddedOverlay = r, t.appendChild(this.paddedOverlay), this.initSubtitleCSS()
}
initSubtitleCSS() {
var e = [new fp.VTTCue(0, 0, "String to init CSS - Won't be visible to user")];
this.paddedOverlay.style.opacity = "0", this.processCues(e), this.processCues([]), this.paddedOverlay.style.opacity = "1"
}
convertCueToDOMTree(e) {
return e ? mp.default.parseContent(this.window, e, this.globalStyleCollection) : null
}
setStyles(i) {
function r(e, t, i) {
for (const r in t) t.hasOwnProperty(r) && (!0 === i && void 0 !== e[r] || !1 === i) && (e[r] = t[r])
}
for (const a in i) {
let t = !1,
e = null;
"::cue" === a ? (e = this.foregroundStyleOptions, t = !0) : "::-webkit-media-text-track-display" === a && (e = this.backgroundStyleOptions, t = !0);
var n = i[a];
if (!0 === t) r(e, n, t);
else
for (let e = 0; e < gp.length; e++) {
var s = gp[e].exec(a);
if (s && 4 === s.length) {
const i = s[2],
o = {};
r(o, n, t), this.globalStyleCollection[i] = o
}
}
}
this.initSubtitleCSS(), this.loggingEnabled && (console.log("WebVTTRenderer setStyles foregroundStyleOptions: " + JSON.stringify(this.foregroundStyleOptions)), console.log("WebVTTRenderer setStyles backgroundStyleOptions: " + JSON.stringify(this.backgroundStyleOptions)), console.log("WebVTTRenderer setStyles globalStyleCollection: " + JSON.stringify(this.globalStyleCollection)))
}
processCues(r) {
if (r) {
for (; this.paddedOverlay.firstChild;) this.paddedOverlay.removeChild(this.paddedOverlay.firstChild);
if (function(t) {
for (let e = 0; e < t.length; e++)
if (t[e].hasBeenReset || !t[e].displayState) return 1
}(r)) {
const n = [],
s = bp.getSimpleBoxPosition(this.paddedOverlay);
1 < r.length && (r = function(t) {
const i = [];
let r = 0;
for (let e = 0; e < t.length; e++) {
var n = t[e];
if ("number" != typeof n.line) return t;
r += n.line, i.push(n)
}
return r /= t.length, 50 < r ? (i.forEach(function(e) {
e.axis = "-y"
}), i.sort((e, t) => t.line - e.line)) : (i.forEach(function(e) {
e.axis = "+y"
}), i.sort((e, t) => e.line - t.line)), i
}(r));
for (let i = 0; i < r.length; i++) {
let e = r[i],
t = new Sp(this.window, e, this.foregroundStyleOptions, this.backgroundStyleOptions, this.globalStyleCollection);
this.paddedOverlay.appendChild(t.div), bp.moveBoxToLinePosition(t, s, n), e.displayState = t.div, n.push(bp.getSimpleBoxPosition(t))
}
} else
for (let e = 0; e < r.length; e++) this.paddedOverlay.appendChild(r[e].displayState)
}
}
setSize(e, t) {
e && (this.overlay.style.width = e + "px"), t && (this.overlay.style.height = t + "px")
}
getOverlay() {
return this.overlay
}
}
function Ep(e) {
for (var t in e) pp.hasOwnProperty(t) || (pp[t] = e[t])
}
w.default = Tp, w.WebVTTRenderer = Tp, pp = Yh, Object.defineProperty(pp, "__esModule", {
value: !0
}), Ep(iu), Ep(w);
function Ip(e, t, i) {
return e.substr(i || 0, t.length) === t
}
function wp(e) {
let t = 5381,
i = e.length;
for (; i;) t = 33 * t ^ e.charCodeAt(--i);
return (t >>> 0).toString()
}
function Ap(e) {
var t = Math.floor(e),
i = t + .5,
r = t + 1;
return i <= e ? r - e <= e - i ? r : i : i - e <= e - t ? i : t
}
function Op(e, t = 0, i = 8589934592) {
if (!Number.isFinite(t)) return e;
var r = i / 2,
n = Math.abs(e - t) % i;
return t + (t < e ? -1 : 1) * (r < n ? i - n : -n)
}
var kp, Cp, Dp, Mp = function(e, t, i, r, n, s, a, o) {
const l = O.utf8arrayToStr(new Uint8Array(e)).trim().replace(/\r\n|\n\r|\n|\r/g, "\n").split("\n"),
d = {
baseTime: Math.floor(9e4 * t.baseTime / t.timescale),
timescale: 9e4
};
let u = 0,
c = 0;
const h = [];
let p = null,
f = !0;
const m = new Yh.WebVTTParser(window, Yh.WebVTTParser.StringDecoder(), a);
m.oncue = function(e) {
var t = S({
baseTime: Op(Op(u) - d.baseTime, 9e4 * i),
timescale: 9e4
});
e.startTime = Op(e.startTime + t - c, 0, 95443.7176888889), e.endTime = Op(e.endTime + t - c, 0, 95443.7176888889), e.id = wp(Ap(e.startTime).toString()) + wp(Ap(e.endTime - e.startTime).toString()) + wp(e.text), e.text = decodeURIComponent(encodeURIComponent(e.text)), 0 < e.endTime && h.push(e)
}, m.onparsingerror = function(e) {
p = e
}, m.onflush = function() {
p && s ? s(p) : n(h)
}, l.forEach(a => f && Ip(a, "X-TIMESTAMP-MAP=") ? (f = !1, void a.substr(16).split(",").forEach(e => {
if (Ip(e, "LOCAL:")) {
let t;
try {
t = (i = e.substr(6), r = parseInt(i.substr(-3)), n = parseInt(i.substr(-6, 2)), s = parseInt(i.substr(-9, 2)), i = 9 < i.length ? parseInt(i.substr(0, i.indexOf(":"))) : 0, ne(r) && ne(n) && ne(s) && ne(i) ? (r += 1e3 * n, r += 6e4 * s, r += 36e5 * i) : -1)
} catch (e) {
t = -1
} - 1 !== t ? c = t / 1e3 : p = new Error(`Malformed X-TIMESTAMP-MAP: ${a}`)
} else Ip(e, "MPEGTS:") && (u = parseInt(e.substr(7)));
var i, r, n, s
})) : void m.parse(a + "\n")), m.flush()
},
xp = {
newCue: function(e, t, i, r, n) {
let s, a, o, l, d;
var u, c, h = {
foreground: !1,
background: !1,
italics: !1,
underline: !1,
flash: !1,
styleStack: []
};
for ([u, c] of r.rows.entries())
if (a = !0, o = 0, l = "", !c.isEmpty()) {
for (let e = 0; e < c.chars.length; e++) c.chars[e].uchar.match(/\s/) && a ? o++ : (l += this.getFormattedChar(c.chars[e], h), a = !1);
(c.cueStartTime = t) === i && (i += 1e-4), l = l.trim().replace(/ /gi, "\n"), l += this.closeStyles(h), s = new Yh.VTTCue(t, i, l), 16 <= o ? o-- : o++, d = !navigator.userAgent.match(/Firefox\//) && 7 < u ? u : u + 1, s.snapToLines = !1, s.line = 10 + 5.33 * d, s.align = "left", s.position = this.getPosition(o, n), e.addCue(s)
}
},
getPosition: function(e, t) {
let i = 1.3333333333333333;
t && t.offsetWidth && t.offsetHeight && 1.6 <= t.offsetWidth / t.offsetHeight && (i = 1.7777777777777777);
let r = 10 + e / 32 * 80,
n = 10,
s = 90;
return 1.7777777777777777 === i && (r = 12.5 + .75 * r, n = 20, s = 80), Math.max(n, Math.min(s, r + (navigator.userAgent.match(/Firefox\//) ? 50 : 0)))
},
getRootStyleTag: function(e) {
var t = e[0];
return "c" === t ? t : e
},
closeStyles: function(t) {
let i = "";
for (let e = t.styleStack.length - 1; 0 <= e; --e) i += "" + this.getRootStyleTag(t.styleStack[e]) + ">", t.styleStack.pop();
return i
},
beginStyleAndBalance: function(e, t) {
let i = "";
return "c" === t[0] && (i += this.closeStyleAndBalance(e, "c")), i += "<" + t + ">", e.styleStack.push(t), i
},
closeStyleAndBalance: function(t, i) {
var r = t.styleStack.length;
let n = 0,
s = "";
for (let e = r - 1; 0 <= e; --e) {
var a = t.styleStack[e],
o = this.getRootStyleTag(a);
if (i[0] === a[0]) {
s += "" + o + ">", t.styleStack.splice(r - 1 - n);
break
}
"c" === o[0] ? (t.background = "", t.foreground = "", t.flash = !1, s += "") : "u" === o[0] ? (t.underline = !1, s += "") : "i" === o[0] && (t.italics = !1, s += ""), n++
}
return s
},
getFormattedChar: function(e, t) {
let i = "",
r = e.uchar,
n = "";
var s = e.penState.foreground !== t.foreground,
a = e.penState.background !== t.background,
o = e.penState.flash !== t.flash;
return (s || a || o) && (n = "." + e.penState.foreground, n += ".bg_" + e.penState.background, e.penState.flash && o && (n += ".blink"), e.penState.foreground || e.penState.background || e.penState.blink ? i += this.beginStyleAndBalance(t, "c" + n) : i += this.closeStyleAndBalance(t, "c"), s && (t.foreground = e.penState.foreground), a && (t.background = e.penState.background), o && (t.flash = e.penState.flash)), e.penState.underline !== t.underline && (i += e.penState.underline ? this.beginStyleAndBalance(t, "u") : this.closeStyleAndBalance(t, "u"), t.underline = e.penState.underline), e.penState.italics !== t.italics && (i += e.penState.italics ? this.beginStyleAndBalance(t, "i") : this.closeStyleAndBalance(t, "i"), t.italics = e.penState.italics), i + r
}
};
(w = kp = kp || {}).CloseEnough = "CloseEnough", w.TooFar = "TooFar", w.Unknown = "Unknown";
const Pp = e => "cc1" === e || "cc2" === e;
function Rp(t) {
const i = [];
for (let e = 0; e < t.length; e++) {
var r = t[e];
("captions" === r.kind || "subtitles" === r.kind || "metadata" === r.kind && r.customTextTrackCueRenderer) && i.push(r)
}
return i
}
function Lp(e) {
if (e && e.cues)
for (; 0 < e.cues.length;) e.removeCue(e.cues[0])
}
class _p extends $t {
constructor(e, t, i, r) {
super(e => {
const t = Oc(this.hls, this);
if (e.add(t.event(x.INLINE_STYLES_PARSED, this.onInlineStylesParsed).pipe(Vs(() => this.destroy())).subscribe()), e.add(bn(0, this.config.trottleCheckInterval).pipe(La(() => (this.checkReadyToLoadNextSubtitleFragment(), Wu))).subscribe()), this.config.nativeTextTrackChangeHandling)
if (this.mediaSink.textTracks && "onchange" in this.mediaSink.textTracks) {
const t = Oc(this.mediaSink.textTracks, this);
e.add(t.event("change", this._onTextTracksChanged).subscribe())
} else e.add(bn(0, 500).pipe(La(() => (this._onTextTracksChanged(), Wu))).subscribe())
}), this.config = t, this.hls = i, this.logger = r.child({
name: "legible"
}), this.mediaSink = e, this.id3Track = e.id3TextTrack, this.enableCaption = !0, this.Cues = xp, this.tracks = [], this.cueRanges = [], this.channelToTrackMap = {}, this.htmlTextTrackMap = new Map, this.lastCueEndTime = 0, this.gotTracks = !1, this.tryAgain$ = new yi(!0), this.needNextSubtitle$ = new yi(!0)
}
destroy() {
Lp(this.textTrack1), Lp(this.textTrack2), this.mediaSink = void 0, this.nativeSubtitleTrackChange$ = void 0
}
convertCuesIntoSubtitleFragInfo(t) {
const i = {};
if (null != t && 0 < t.length)
for (let e = 0; e < t.length; e++) {
var r = t[e];
if (ne(r.fragSN)) {
const n = i[r.fragSN];
n ? (n.count++, n.startTime = Math.min(r.startTime, n.startTime), n.endTime = Math.max(r.endTime, n.endTime)) : i[r.fragSN] = {
count: 1,
startTime: r.startTime,
endTime: r.endTime
}
}
}
return i
}
checkReadyToLoadNextSubtitleFragment() {
let e = !1;
this.mediaSink.mediaQuery.currentTime >= this.lastCueEndTime - this.config.subtitleLeadTime && (e = !0), this.needNextSubtitle$.next(e)
}
checkReadyToLoadNextSubtitleFragment$(e, t) {
return e.mediaSeqNum === (null === (t = t[0]) || void 0 === t ? void 0 : t.mediaSeqNum) ? $i(!0) : (this.checkReadyToLoadNextSubtitleFragment(), this.needNextSubtitle$)
}
getNextFragment(e, t) {
t = t.mediaSeqNum + 1;
return t < e.fragments.length ? e.fragments[t - e.startSN] : null
}
calculateFragInfoMap(e, t, i, r) {
var n = this.convertCuesIntoSubtitleFragInfo(t);
let s = {
len: 0,
start: e,
end: e
},
a = e,
o = e,
l = null,
d = null;
for (const t in n)
if (Object.prototype.hasOwnProperty.call(n, t)) {
var u = Number(t);
if (ne(u)) {
var c = n[u];
if (this.isFragmentCompleteOrEmpty(u, c.count, i))
if (u === r.startSN && e < c.startTime && (a = o = s.start = s.end = e = c.startTime), e >= c.startTime && (a === e || ne(l) && 1 < u - l) && (a = o = c.startTime), e >= c.startTime) o = c.endTime, l = u;
else {
if (!ne(l) || u - l != 1) {
d = u;
break
}
o = c.endTime, l = u
}
} else this.logger.warn(`$fragInfoMap has invalid key ${u}`)
} return s = {
len: o - a,
start: a,
end: o
}, {
fragInfoMap: n,
bufferInfo: s,
prevFragSN: l,
nextFragSN: d
}
}
findFrags$(t, i) {
return this.tryAgain$.pipe(ji(tr), La(() => {
var e = this.findFragmentsForPosition(this.mediaSink.mediaQuery.currentTime, i, t);
return e.foundFrags ? (this.lastCueEndTime = 0, this.needNextSubtitle$.next(!0), $i(e)) : Ii
}))
}
reviewParsedFrag(e, i, r) {
var n = e.frag,
s = e.cueRange,
t = i.subtitleBufferInfo,
a = i.subtitleParsedInfo,
o = this.mediaSink.mediaQuery.currentTime,
e = i.foundFrags;
let l = !0;
if (n.mediaSeqNum === e[0].mediaSeqNum) {
if (!i.timelineEstablished) return kp.TooFar;
if (!s) return this.logger.warn(`[subtitle] 1st frag sn ${n.mediaSeqNum} has no cue; details ${r.fragments.length} frags`), kp.Unknown;
if (s.startTime < o) {
const d = r.fragments,
i = n.mediaSeqNum - r.startSN;
let e = i,
t = s.startTime;
for (; e < d.length && (t += d[e].duration, !(t >= o)); ++e);
l = e - i + 1 <= this.config.earlyFragTolerance
} else if (s.startTime > o && n.mediaSeqNum !== r.startSN) {
const d = s.startTime - o,
i = t.prevFragSN;
l = n.mediaSeqNum === i + 1 && (null === (t = t.fragInfoMap[i]) || void 0 === t ? void 0 : t.count) === (null === (a = a[i]) || void 0 === a ? void 0 : a.count) || d <= this.config.lateTolerance
}
}
return l ? kp.CloseEnough : kp.TooFar
}
isFragmentEmpty(e) {
return e && !ne(e.startTime) && 0 === e.count
}
isFragmentCompleteOrEmpty(e, t, i) {
e = i ? i[e] : null;
return (null == e ? void 0 : e.count) === t || this.isFragmentEmpty(e)
}
getEarlierFragmentInSameDisco(e, t, i) {
var r = t.mediaSeqNum - e.startSN - 1;
if (r < 0 || r > e.fragments.length - 1) return this.logger.error(`[subtitle] getEarlierFragmentInSameDisco index ${r} out of range`), t;
r = e.fragments[r];
return r && r.discoSeqNum === t.discoSeqNum && !i[t.mediaSeqNum] ? r : t
}
inferSubtitleFragmentForPosition(i, r, t, n, s) {
let a, o, e, l, d;
if (ne(n.prevFragSN) && (o = n.prevFragSN - s.startSN, e = t[n.prevFragSN]), ne(n.nextFragSN) && (l = n.nextFragSN - s.startSN, d = t[n.nextFragSN]), ne(o) && 0 <= o && o < s.fragments.length && e) {
let t = e.startTime;
const n = ne(l) ? l : s.fragments.length;
for (let e = o; e < n; ++e) {
const l = s.fragments[e];
if (!ne(r) || l.discoSeqNum === r) {
if (e === n - 1) {
a = {
foundFrag: l,
timelineEstablished: !0
};
break
}
if (t + l.duration > i && e > o) {
a = {
foundFrag: l,
timelineEstablished: !0
};
break
}
t += l.duration
}
}
} else if (ne(l) && 0 <= l && l < s.fragments.length && d) {
let t = d.startTime;
for (let e = l - 1; 0 <= e; --e) {
const o = s.fragments[e];
if (!ne(r) || o.discoSeqNum === r) {
if (t <= i) {
a = {
foundFrag: o,
timelineEstablished: !0
};
break
}
t -= o.duration
}
}
} else
for (let e = 0; e < s.fragments.length; ++e) {
const t = s.fragments[e];
if (ne(r) && t.discoSeqNum === r) {
a = {
foundFrag: t,
timelineEstablished: !1
};
break
}
}
return a
}
generateFragmentBatch(t, i, e, r, n, s) {
var a;
const o = [],
l = null == e ? void 0 : e.foundFrag;
if (!l) return {
foundFrags: void 0,
subtitleParsedInfo: void 0,
subtitleBufferInfo: void 0,
timelineEstablished: null == e ? void 0 : e.timelineEstablished
};
for (let e = l ? l.mediaSeqNum - s.startSN : s.fragments.length; e < s.fragments.length && o.length < t; ++e) {
const t = s.fragments[e];
if (t.discoSeqNum === i) {
const l = null === (a = n.fragInfoMap[t.mediaSeqNum]) || void 0 === a ? void 0 : a.count;
this.isFragmentCompleteOrEmpty(t.mediaSeqNum, null != l ? l : 0, r) || o.push(t)
}
}
return {
foundFrags: o,
subtitleParsedInfo: r,
subtitleBufferInfo: n,
timelineEstablished: null == e ? void 0 : e.timelineEstablished
}
}
findFragmentsForPosition(e, t, i) {
var r = this.mediaSink.mediaQuery.getParsedSubtitleRecordsForMediaOption(this.selectedTrack.persistentID),
n = this.getCuesOfEnabledTrack(this.selectedMediaOption.mediaOptionId, !1),
s = this.calculateFragInfoMap(e, n, r, i),
n = s.bufferInfo,
n = Math.max(e, n.end),
n = this.inferSubtitleFragmentForPosition(n, t, r, s, i);
return this.generateFragmentBatch(1 / 0, t, n, r, s, i)
}
get selectedMediaOption() {
return this.selectedTrack || this._disabledMediaOption
}
set selectedMediaOption(e) {
this.selectedTrack = "groupId" in e ? e : void 0
}
get selectedTrack() {
return this._selectedMediaOption
}
set selectedTrack(e) {
e !== this._selectedMediaOption && (this._selectedMediaOption = e, this.updateTextTrackState())
}
getTrack(t) {
return this._availableMediaOptions.find(e => e.mediaOptionId === t)
}
updateTextTrackState() {
if (this.mediaSink.textTracks) {
const i = this.selectedTrack ? this.getExistingHTMLTextTrack(this.selectedTrack) : void 0,
r = Rp(this.mediaSink.textTracks);
for (let e = 0; e < r.length; e++) {
var t = r[e];
t === i && "showing" !== r[e].mode ? r[e].mode = "showing" : t !== i && "hidden" !== r[e].mode && (r[e].mode = "hidden")
}
}
}
mapHTMLTextTrackIndexToMediaOptionId(e) {
const i = this.mediaSink.textTracks[e];
let r;
return this.htmlTextTrackMap.forEach((e, t) => {
i === e && (r = t)
}), r
}
get mediaSelectionOptions() {
return this._availableMediaOptions
}
_makeDisableOption(e) {
return {
itemId: e.itemId,
mediaOptionType: e.mediaOptionType,
mediaOptionId: "Nah"
}
}
_onTextTracksChanged() {
if (this.mediaSink) {
let t, i = !1;
const r = Rp(this.mediaSink.textTracks);
for (let e = 0; e < r.length; e++) r[e].seen ? "showing" === r[e].mode && (t = r[e].persistentId) : (r[e].seen = !0, i = !0);
if (!i) {
const e = this.selectedTrack;
if ((null == e ? void 0 : e.persistentID) !== t) {
const e = this.mediaSelectionOptions.find(function(e) {
return e.persistentID === t
});
this.nativeSubtitleTrackChange$.next(e || this._disabledMediaOption)
}
}
}
}
addCues(e, t, i, r) {
const n = this.cueRanges;
let s = !1;
for (let e = n.length; e--;) {
const r = n[e],
d = (a = r[0], o = r[1], l = t, Math.min(o, i) - Math.max(a, l));
if (0 <= d && (r[0] = Math.min(r[0], t), r[1] = Math.max(r[1], i), s = !0, .5 < d / (i - t))) return
}
var a, o, l;
s || n.push([t, i]), this.Cues.newCue(this.channelToTrackMap[e], t, i, r, this.mediaSink)
}
getExistingHTMLTextTrackWithChannelNumber(t) {
var i = this.mediaSink;
if (i)
for (let e = 0; e < i.textTracks.length; e++) {
var r = i.textTracks[e],
n = "cc" + t;
if (Pp(n) && !0 === r[n]) return r
}
return null
}
sendAddTrackEvent(e, t) {
let i = null;
try {
i = new window.Event("addtrack")
} catch (e) {
i = document.createEvent("Event"), i.initEvent("addtrack", !1, !1)
}
i.track = e, t.dispatchEvent(i)
}
createHTMLCaptionsTrackGuts(e, t, i, r) {
var n = "cc" + e;
if (!this.channelToTrackMap[n]) {
e = this.getExistingHTMLTextTrackWithChannelNumber(e);
if (e) this.channelToTrackMap[n] = e, Lp(this.channelToTrackMap[n]), this.sendAddTrackEvent(this.channelToTrackMap[n], this.mediaSink);
else {
const s = this.createHTMLTextTrackGuts("captions", t, i, r);
s && Pp(n) && (s[n] = !0, this.channelToTrackMap[n] = s)
}
}
return this.channelToTrackMap[n]
}
createHTMLCaptionsTrack(e) {
return this.createHTMLCaptionsTrackGuts(e, this.config[1 === e ? "captionsTextTrack1Label" : "captionsTextTrack2Label"], this.config.captionsTextTrack1LanguageCode, !1)
}
getExistingHTMLTextTrack(e) {
return this.config.condenseSubtitleTrack ? this.htmlTextTrackMap.get(e.persistentID) : this.htmlTextTrackMap.get(e.id)
}
getExistingHTMLTextTrackWithSubtitleTrackId(t) {
var e = this._availableMediaOptions.find(e => e.id === t);
return e ? this.getExistingHTMLTextTrack(e) : void 0
}
getExistingHTMLTextTrackIndex(e) {
var t = this.getExistingHTMLTextTrack(e),
i = this.mediaSink.textTracks;
let r = -1;
for (let e = 0; e < i.length; ++e)
if (i[e] === t) {
r = e;
break
} return r
}
setExistingHTMLTextTrack(e, t) {
return t.persistentId = e.persistentID, this.config.condenseSubtitleTrack ? this.htmlTextTrackMap.set(e.persistentID, t) : this.htmlTextTrackMap.set(e.id, t)
}
createHTMLTextTrack(t) {
let i = this.getExistingHTMLTextTrack(t);
if (i) this.tracksReused += 1;
else {
if ("sbtl" === t.mediaType) this.subtitleTracksCreated += 1, i = this.createHTMLTextTrackGuts("subtitles", t.name, t.lang, t.forced);
else {
let e = 1;
t.inStreamID && (e = Number(t.inStreamID.substring(2))), this.captionTracksCreated += 1, i = this.createHTMLCaptionsTrackGuts(e, t.name, t.lang, !1)
}
i ? this.setExistingHTMLTextTrack(t, i) : (this.logger.error(`failed to create HTML text track for track ${t.id}: persistent id ${t.persistentID} name ${t.name} lang ${t.lang} inStreamID ${t.inStreamID}`), this.tracksFailed += 1)
}
return i
}
createHTMLTextTrackGuts(t, i, r, e) {
const n = this.mediaSink;
if (n) {
let e = !1;
"metadata" !== t && this.config.customTextTrackCueRenderer && (e = !0, t = "metadata");
const s = n.addTextTrack(t, i, r);
return e && (s.customTextTrackCueRenderer = !0), s
}
}
resetLoadSource() {
this.resetTracks()
}
resetTracks() {
this._cleanTracks(), this.cueRanges = []
}
_cleanTracks() {
var e = this.mediaSink;
if (e) {
var t = e.textTracks;
if (t)
for (let e = 0; e < t.length; e++) Lp(t[e])
}
}
getCuesOfEnabledTrack(e, t = !1) {
let i = [];
if (t) {
const t = this._getCuesOfEnabledTrack(e);
for (let e = 0; e < t.length; e++) {
var r = t[e];
Boolean(r.webVTTCue) && i.push(r)
}
} else i = this._getCuesOfEnabledTrack(e);
return i
}
_getCuesOfEnabledTrack(e) {
e = this.getTrack(e), e = this.config.condenseSubtitleTrack ? null == e ? void 0 : e.persistentID : null == e ? void 0 : e.id, e = this.htmlTextTrackMap.get(e);
return e && e.cues ? Array.from(e.cues) : []
}
attachSubtitleTracks() {
this.gotTracks && (this.subtitleTracksCreated = 0, this.captionTracksCreated = 0, this.tracksReused = 0, this.tracksFailed = 0, this.tracks.forEach(e => {
this.createHTMLTextTrack(e)
}))
}
setTracks(e, t, i) {
this._cleanTracks(), this.htmlTextTrackMap = new Map, this.cueRanges = [], this.config.enableWebVTT && (this.tracks = e || []), this.gotTracks = !0, this._availableMediaOptions = e, this._disabledMediaOption = i, this.attachSubtitleTracks(), this.selectedTrack = t, this.nativeSubtitleTrackChange$ = new Xt, this.mediaSink.textTracksCreated = !0
}
onInlineStylesParsed(e) {}
processSubtitleFrag(e, t, i, r) {
var n = new Uint8Array(r),
e = this.getExistingHTMLTextTrackIndex(e);
if (t && r.byteLength) {
const s = this._parseVTTs(e, t, i, n);
return s && ne(s.startTime) && (this.lastCueEndTime = Math.max(this.lastCueEndTime, s.endTime)), s
}
}
_parseVTTs(r, n, e, t) {
let s;
return Mp(t, e, n.start, n.discoSeqNum, e => {
const t = this.mediaSink.textTracks[r],
i = {
count: 0,
startTime: Number.POSITIVE_INFINITY,
endTime: 0
};
e.map(e => {
!t || t.cues && t.cues.getCueById(e.id) || (e.fragSN = n.mediaSeqNum, e.webVTTCue = !0, t.addCue(e), i.count++), i.startTime = Math.min(e.startTime, i.startTime), i.endTime = Math.max(e.endTime, i.endTime)
}), s = i, this.mediaSink.archiveParsedSubtitleFragmentRecord(this.selectedTrack.persistentID, n.mediaSeqNum, i)
}, e => {}, e => {
this.hls.trigger(x.INLINE_STYLES_PARSED, {
styles: e
})
}, this.logger), s
}
_ensureParser() {
var e, t;
this.cea608Parser || (e = new Xh(this, 1), t = new Xh(this, 2), this.cea608Parser = new zh(0, e, t))
}
setupForFrag(e) {
e && e.mediaOptionType === gu.Variant && !e.iframe && ((e = e.mediaSeqNum) !== this.lastVariantSeqNum + 1 && this.resetClosedCaptionParser(), this.lastVariantSeqNum = e)
}
resetClosedCaptionParser() {
var e;
null === (e = this.cea608Parser) || void 0 === e || e.reset()
}
addLegibleSamples(e, t, i, r) {
t && this.addClosedCaptionSamples(e, t), i && 0 < i.length && this.addId3Samples(e, i, S(r))
}
addClosedCaptionSamples(e, t) {
t.mp4 ? this.addMP4CaptionSamples(e, t.mp4) : t.ts && this.addTSCaptionSamples(e, t.ts)
}
addMP4CaptionSamples(e, i) {
if (this.enableCaption && this.config.enableCEA708Captions) {
var r = S(e);
this._ensureParser();
for (let e = 0; e < i.length; e++) {
let t = i[e].pts - r;
var n = i[e].bytes;
for (let e = 0; e < n.length; e += 2) {
const i = [];
i.push(n[e]), e + 1 < n.length ? i.push(n[e + 1]) : i.push(80), this.cea608Parser.addData(t, i), t += .03336666666666667
}
}
}
}
addTSCaptionSamples(e, t) {
if (this.enableCaption && this.config.enableCEA708Captions) {
var i = S(e);
this._ensureParser();
for (let e = 0; e < t.length; e++) {
var r = t[e].pts - i,
n = _p.extractCea608Data(t[e].bytes);
this.cea608Parser.addData(r, n)
}
}
}
addId3Samples(e, t, r) {
if (this.config.enableID3Cues) {
const n = window.WebKitDataCue || window.VTTCue || window.TextTrackCue,
s = S(e);
for (let e = 0; e < t.length; e++) {
const a = t[e].pts - s;
let i = (e < t.length - 1 ? t[e + 1].pts : r) - s;
a === i && (i += 1e-4), t[e].frames && t[e].frames.forEach(e => {
if (e && !this.id3shouldIgnore(e)) {
const t = new n(a, i, "");
t.value = e, this.id3Track.addCue(t)
}
})
}
}
}
id3shouldIgnore(e) {
return "PRIV" === e.key && ("com.apple.streaming.transportStreamTimestamp" === e.info || "com.apple.streaming.audioDescription" === e.info)
}
static extractCea608Data(t) {
var i = 31 & t[0];
let r, n, s, a = 2;
const o = [];
for (let e = 0; e < i; e++) r = t[a++], n = 127 & t[a++], s = 127 & t[a++], 0 == n && 0 == s || 0 != (4 & r) && 0 == (3 & r) && (o.push(n), o.push(s));
return o
}
}
const Np = {
name: "plist"
};
class Fp {
constructor(e, t, i, r) {
this.config = e, this.xhrLoader = t, this.customUrlLoader = i, this.sessionDataCheckForCompleteness = e => {
const t = this.config["sessionDataAutoLoad"],
i = Object.assign({}, e);
return e.complete || (e.itemList ? i.complete = e.itemList.every(e => t[e["DATA-ID"]] && !e.VALUE && !e._STATUS && e.URI ? (this.logger.warn(`Incomplete because ${e["DATA-ID"]} was autoloaded but no response yet`), !1) : (t[e["DATA-ID"]] && !e.URI && this.logger.warn(`id=${e["DATA-ID"]} missing uri`), !0)) : this.logger.warn("Uninitialized SessionData")), i
}, this.logger = r.child({
name: "SessionDataLoader"
})
}
loadSessionData(r) {
const n = this.config["sessionDataAutoLoad"],
t = r.itemList || [];
let s = $i(r);
return t.forEach(e => {
const i = e["DATA-ID"],
t = e.URI;
if (t && n[i]) {
const n = bu.buildAbsoluteURL(r.baseUrl, t, {
alwaysNormalize: !0
}),
e = "";
s = s.pipe(La(t => this.loadSessionDataItemWithUrl(n, i, "", this.config, t, this.xhrLoader, this.customUrlLoader).pipe(Vn(e => (this.logger.error(`Error loading SessionData > url=${n}, id=${i}, err=${e}`), $i(t))))))
}
}), s.pipe(hr(e => {
if (t.length < 1) return e;
e = this.sessionDataCheckForCompleteness(e);
if (e.complete) return e;
throw new V(!1, "Session data not complete after loading all items", $.IncompleteSessionData)
}), Vs(() => {}))
}
loadSessionDataItemWithUrl(e, t, i, r, n, s, a) {
const o = Qe(),
l = {
url: e,
method: "GET",
responseType: i,
xhrSetup: r.xhrSetup,
mimeType: "application/xml"
},
d = Lc({
url: e
}, r.fragLoadPolicy);
let u;
return u = Tu(e) ? a(l, d).pipe(hr(e => this.onLoadSuccess(n, t, e.data.response.data.toString(), e.data.response.data))) : s(l, d).pipe(hr(([e]) => this.onLoadSuccess(n, t, e.response, e.responseXML))), u.pipe(Vn(e => (e instanceof dr ? e = new cc(!1, e.message, 0, $.SessionDataLoadTimeout) : e instanceof oc && (e = new cc(!1, e.message, e.code, {
code: e.code,
text: "Failed to load SessionData"
})), o.error(`Unable to load SessionData > err=${e}`), $i(this.onLoadError(n, t, e)))))
}
onLoadSuccess(e, t, i, r) {
let n = null,
s = e;
if (function(e) {
const t = /[\s]*<\?xml/i;
t.lastIndex = 0;
var i = t.exec(e);
return i || /[\s]*"), null)
} else if ("string" === i) {
const e = a[0];
s = e ? e.nodeValue : null
} else if ("integer" === i) {
const e = a[0];
s = e ? parseInt(e.nodeValue) : 0
} else if ("float" === i) {
const e = a[0];
s = e ? parseFloat(e.nodeValue) : 0
} else if ("date" === i) {
const e = a[0];
s = e ? new Date(e.nodeValue) : null
} else if ("data" === i) {
const e = a[0];
s = e ? atob(e.nodeValue) : null
} else "true" === i ? s = !0 : "false" === i && (s = !1)
} else if (a.length < 1) t.warn(Np, `unknown node with unknown value > nodeType=${e.nodeType} tagName=${e.tagName} nodeName=${e.nodeName} value=${e.nodeValue}`);
else {
s = [];
for (let e = 0; e < a.length; ++e) {
const r = a[e];
r.tagName && s.push(n(r))
}
1 === s.length && (s = s[0])
}
return s
}(n);
s = this.setSessionData(e, t, "VALUE", i)
} else if (function(e) {
const t = /[\s]*[\{\[]/;
return t.lastIndex = 0, t.exec(e)
}(i)) try {
const r = JSON.parse(i);
s = this.setSessionData(e, t, "VALUE", r)
} catch (r) {
this.logger.error(`JSON parser error: ${r}`), s = this.setSessionData(e, t, "VALUE", i), s = this.setSessionData(s, t, "_STATUS", -1)
} else s = this.setSessionData(e, t, "VALUE", i);
return s
}
setSessionData(t, i, r, n) {
let s = t;
if (t.itemList) {
let e;
const a = [...t.itemList];
for (e = 0; e < t.itemList.length; ++e) {
const t = Object.assign({}, a[e]);
if (t["DATA-ID"] === i) {
t[r] = n, a[e] = t;
break
}
}
e === t.itemList.length && this.logger.error(`Can't set ${r} of session data ${i}`), s = Object.assign(Object.assign({}, t), {
itemList: a
})
} else this.logger.error(`Can't set ${r} on uninitialized session data`);
return s
}
onLoadError(e, t, i) {
return this.setSessionData(e, t, "_STATUS", null === (i = i.response) || void 0 === i ? void 0 : i.code)
}
}
function Bp(e, t) {
let i, r = 0;
for (const a of e)
if (a.start <= t.endPTS && a.end > t.startPTS) {
const e = (n = t, s = a, Math.min(n.endPTS, s.end) - Math.max(n.startPTS, s.start));
e > r && (i = a, r = e)
} else if (0 < r) break;
var n, s;
return i
}
function Up(e) {
return null != e && "iframeMediaDuration" in e && "iframeMediaStart" in e
}
function $p(e, t) {
return e === t || e && t && e.itemId === t.itemId && e.mediaOptionId === t.mediaOptionId && e.mediaSeqNum === t.mediaSeqNum && e.discoSeqNum === t.discoSeqNum
}
function Vp(e) {
return JSON.stringify(e, ["mediaOptionId", "mediaSeqNum", "discoSeqNum", "start", "duration"])
}
function Kp() {
return e => e.pipe(ln(e => null != e), hr(e => e))
}
function qp(e) {
return be.isDolby(e) ? hu.DOVI : be.isHEVC(e) ? hu.HEVC : be.isVP09(e) ? hu.VP09 : be.isAVC(e) ? hu.AVC : hu.UNKNOWN
}
function Hp(e) {
return null == e ? void 0 : e.split(".")[0]
}
function jp(e) {
return be.isALAC(e) ? fu.ALAC : be.isFLAC(e) ? fu.FLAC : be.isEC3(e) ? fu.EC3 : be.isAC3(e) ? fu.AC3 : be.isXHEAAC(e) ? fu.XHEAAC : be.isAAC(e) ? fu.AAC : be.isMP3(e) ? fu.MP3 : fu.UNKNOWN
}
class Qp {
constructor(...e) {
this.identifier = e
}
ensureSameIdentifierLength(e) {
if (this.identifier.length !== e.identifier.length) throw new Error(`Identifiers have non-matching lengths! (${this.identifier.length} vs ${e.identifier.length})`)
}
isGreaterThan(t) {
this.ensureSameIdentifierLength(t);
for (let e = 0; e < this.identifier.length; ++e) {
if (this.identifier[e] < t.identifier[e]) return !1;
if (this.identifier[e] > t.identifier[e]) return !0
}
return !1
}
isEqualTo(i) {
return this.ensureSameIdentifierLength(i), this.identifier.every((e, t) => e === i.identifier[t])
}
}
function Wp(e) {
return ne(e) && 0 !== e && 1 !== e
}
class Gp extends Error {}
class zp {
constructor(e) {
this.value = e, this.waiters = [], this.wcounter = 0, this.rcounter = 0
}
lock(e, t = !1) {
return this._lock(!0, e, t)
}
unlock() {
this._unlock(!0)
}
readLock(e, t = !1) {
return this._lock(!1, e, t)
}
readUnlock() {
this._unlock(!1)
}
_schedule() {
const t = [];
this.waiters = this.waiters.filter(e => !this._canLock(e.rw) || (e.rw ? ++this.wcounter : ++this.rcounter, t.push(e), !1));
for (const e of t) e.observer.next(this.value), e.observer.complete()
}
_canLock(e) {
return e && 0 === this.wcounter && 0 === this.rcounter || !e && 0 === this.wcounter
}
_lock(i, e, r = !1) {
"boolean" == typeof e && ([r, e] = [e, void 0]);
const t = new $t(e => {
var t = this._canLock(i);
if (r && !t) throw new Gp;
t ? (i ? ++this.wcounter : ++this.rcounter, e.next(), e.complete()) : this.waiters.push({
rw: i,
observer: e
})
});
return e ? t.pipe(jr(() => ((e, t, i, r) => {
if (!r) return $i(e);
let n, s;
try {
n = r(e, t)
} catch (e) {
s = Vi(() => e)
}
return s = s || (void 0 === n ? $i(e) : Fr(n)), s.pipe(Vs(i))
})(this.value, e => {
this.value = e
}, () => this._unlock(i), e))) : t
}
_unlock(e) {
e ? this.wcounter = Math.max(this.wcounter - 1, 0) : this.rcounter = Math.max(this.rcounter - 1, 0), this._schedule()
}
}
class Xp extends $t {
constructor() {
super(e => this._count$.pipe(ln(e => 0 === e), Ds(1), Zs(void 0)).subscribe(e)), this._count$ = new yi(0)
}
wrap(e) {
return Zr(() => (this.add(), Fr(e))).pipe(Za({
error: e => this._count$.error(e)
}), Vs(() => this.done()))
}
add(e = 1) {
this._count$.next(this._count$.value + e)
}
done(e = 1) {
this._count$.next(this._count$.value - e)
}
}
const Yp = {
isBuffered(t, i) {
for (let e = 0; t && e < t.length; e++)
if (i >= t.start(e) && i <= t.end(e)) return !0;
return !1
},
timeRangesToBufferedRange(t) {
const i = [];
for (let e = 0; t && e < t.length; e++) i.push({
start: t.start(e),
end: t.end(e)
});
return i
},
subtitleBufferInfo(e, t, i) {
if (e) {
e = this.bufferedCues(e);
return this.getBufferedInfo(e, t, i)
}
return {
len: 0,
start: t,
end: t,
nextStart: void 0
}
},
fragmentsBufferedInfo(e, t, i) {
const r = [];
for (const t of e) r.push({
start: t.start,
end: t.start + t.duration
});
return this.getBufferedInfo(r, t, i)
},
bufferedCues(t) {
const i = [];
if (t)
for (let e = 0; e < t.length; e++) i.push({
start: t[e].startTime,
end: t[e].endTime
});
return i
},
bufferedInfoFromMedia: (e, t, i) => Yp.getBufferedInfo(Yp.timeRangesToBufferedRange(e.buffered), t, i),
getBufferedInfo(e, t, i) {
const r = [];
let n, s, a, o, l;
const d = e.map(({
start: e,
end: t
}) => ({
start: e,
end: t
}));
for (d.sort((e, t) => {
return e.start - t.start || t.end - e.end
}), l = 0; l < d.length; l++) {
const e = r.length;
if (e) {
const t = r[e - 1].end;
d[l].start - t < i ? d[l].end > t && (r[e - 1].end = d[l].end) : r.push(d[l])
} else r.push(d[l])
}
for (l = 0, n = 0, s = a = t; l < r.length; l++) {
const e = r[l]["start"],
d = r[l]["end"];
if (t + i >= e && t < d) s = e, a = d, n = a - t;
else if (t + i < e) {
o = e;
break
}
}
return {
len: n,
start: s,
end: a,
nextStart: o
}
},
toRangeString: e => `[${e.start.toFixed(3)},${e.end.toFixed(3)}]`
};
(w = Cp = Cp || {}).Seek = "Seek", w.HighBuffer = "HighBuffer", w.LowBuffer = "LowBuffer", (w = Dp = Dp || {}).AlmostDry = "AlmostDry", w.LowWater = "LowWater", w.HighWater = "HighWater", w.AboveHighWater = "AboveHighWater";
const Jp = {
[Dp.AlmostDry]: 0,
[Dp.LowWater]: 1,
[Dp.HighWater]: 2,
[Dp.AboveHighWater]: 3
};
function Zp(t, e) {
return [{
threshold: e.highWaterLevelSeconds,
level: Dp.HighWater
}, {
threshold: e.lowWaterLevelSeconds,
level: Dp.LowWater
}, {
threshold: e.almostDryWaterLevelSeconds,
level: Dp.AlmostDry
}].find(({
threshold: e
}) => e < t)
}
function ef(t, e) {
return [{
threshold: e.almostDryWaterLevelSeconds,
level: Dp.AlmostDry
}, {
threshold: e.lowWaterLevelSeconds,
level: Dp.LowWater
}, {
threshold: e.highWaterLevelSeconds,
level: Dp.HighWater
}, {
threshold: 1 / 0,
level: Dp.AboveHighWater
}].find(({
threshold: e
}) => t <= e)
}
function tf(t, i) {
const e = ef(t.getCurrentWaterLevel(i), t.bufferMonitorInfo).level,
r = [null, null];
return [yu.Variant, yu.AltAudio].forEach(e => {
null != t.sourceBufferEntityByType(e) && (r[e] = ef(t.getCurrentWaterLevelByType(e, i), t.bufferMonitorInfo).level)
}), {
combined: e,
sbTuple: r
}
}
function rf(s, a) {
return ed([s.combinedBuffer$, s.gotPlaying$, s.seeking$, s.waterLevelChangedForType$(null), s.stallInfo$]).pipe(La(([e, t, i, r, n]) => 0 === e.length || !t || i || null == r || null != n ? Ii : function t(i, r, e) {
const n = i.getCurrentWaterLevel(r),
s = Zp(n, i.bufferMonitorInfo);
if (s) {
const e = s["threshold"];
return bn(Math.ceil(1e3 * (n - e))).pipe(La(() => {
const e = Zp(i.getCurrentWaterLevel(r), i.bufferMonitorInfo);
return (null == e ? void 0 : e.level) === s.level ? t(i, r) : Wu
}), hr(() => tf(i, r)))
}
return Ii
}(s, a)))
}
class nf extends kl {
constructor(e, t) {
super(t), this.mediaElement = e
}
get mediaElementDuration$() {
return this.selectActive(({
mediaElementDuration: e
}) => e)
}
get mediaElementDuration() {
var e;
return null !== (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.mediaElementDuration) && void 0 !== e ? e : 1 / 0
}
get msDuration() {
var e;
return null !== (e = null === (e = this.mediaSourceEntity) || void 0 === e ? void 0 : e.duration) && void 0 !== e ? e : 1 / 0
}
get minSBDuration() {
var e;
let i = Number.POSITIVE_INFINITY;
return null === (e = null === (e = this.mediaSourceEntity) || void 0 === e ? void 0 : e.sourceBufferEntities) || void 0 === e || e.forEach((e, t) => {
e && (i = ne(e.totalDuration) ? Math.min(i, e.totalDuration) : Number.NEGATIVE_INFINITY)
}), ne(i) ? i : 1 / 0
}
get currentTime() {
return this.mediaElement.currentTime
}
get clientWidth() {
return this.mediaElement.clientWidth
}
get clientHeight() {
return this.mediaElement.clientHeight
}
getBufferedDuration(e = .5) {
var t = Yp.timeRangesToBufferedRange(this.mediaElement.buffered),
e = Yp.getBufferedInfo(t, this.currentTime, e);
return e.end - e.start
}
get mediaSourceEntity() {
var e;
return null === (e = this.getActive()) || void 0 === e ? void 0 : e.mediaSourceEntity
}
get msReadyState() {
var e;
return null === (e = this.mediaSourceEntity) || void 0 === e ? void 0 : e.readyState
}
get sourceBufferEntities() {
var e;
return null === (e = this.mediaSourceEntity) || void 0 === e ? void 0 : e.sourceBufferEntities
}
sourceBufferEntityByType(e) {
var t;
return null === (t = this.sourceBufferEntities) || void 0 === t ? void 0 : t[e]
}
initSegmentEntityByType(e) {
return null === (e = this.sourceBufferEntityByType(e)) || void 0 === e ? void 0 : e.initSegmentInfo
}
get maxBufferSize() {
var e = null === (e = this.sourceBufferEntities) || void 0 === e ? void 0 : e[yu.Variant];
let t = 1 / 0;
return null != e && e.gotQuotaExceeded && (t = null !== (e = e.maxTotalBytes) && void 0 !== e ? e : 1 / 0), t
}
get postFlushSeek() {
var e;
return null === (e = this.getActive()) || void 0 === e ? void 0 : e.postFlushSeek
}
get seekable() {
return this.mediaElement.seekable
}
get desiredRate() {
var e;
return (null === (e = this.getActive()) || void 0 === e ? void 0 : e.desiredRate) || 0
}
get desiredRate$() {
return this.selectActive(({
desiredRate: e
}) => null != e ? e : 0)
}
get effectiveRate() {
return this.isIframeRate ? this.desiredRate : this.paused ? 0 : 1
}
get playbackRate() {
return this.mediaElement.playbackRate
}
get isIframeRate() {
return Wp(this.desiredRate)
}
get isIframeRate$() {
return this.desiredRate$.pipe(hr(Wp))
}
get msObjectUrl$() {
return this.selectActive(({
mediaSourceEntity: e
}) => null == e ? void 0 : e.objectUrl).pipe(Is())
}
get msReadyState$() {
return this.selectActive(({
mediaSourceEntity: e
}) => {
return null !== (e = null == e ? void 0 : e.readyState) && void 0 !== e ? e : null
})
}
get readyState() {
var e;
return null !== (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.readyState) && void 0 !== e ? e : 0
}
get readyState$() {
return this.selectActive(({
readyState: e
}) => null != e ? e : 0)
}
get mediaSourceEntity$() {
return this.selectActive(({
mediaSourceEntity: e
}) => e)
}
get expectedSbCount$() {
return this.selectActive(({
expectedSbCount: e
}) => e)
}
get expectedSbCount() {
var e;
return null === (e = this.getActive()) || void 0 === e ? void 0 : e.expectedSbCount
}
get paused$() {
return this.selectActive(({
paused: e
}) => e)
}
get paused() {
var e;
return null === (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.paused) || void 0 === e || e
}
get playbackStarted() {
var e;
return ne(null === (e = this.getActive()) || void 0 === e ? void 0 : e.firstPlayTime)
}
get flushing$() {
return this.selectActive(({
flushing: e
}) => e)
}
get flushing() {
var e;
return null !== (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.flushing) && void 0 !== e && e
}
get waitingForDisco$() {
return this.selectActive(({
waitingForDisco: e
}) => e)
}
get waitingForDisco() {
var e;
return null !== (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.waitingForDisco) && void 0 !== e && e
}
get gotPlaying() {
var e;
return null !== (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.gotPlaying) && void 0 !== e && e
}
get gotPlaying$() {
return this.selectActive(({
gotPlaying: e
}) => e)
}
get gotLoadStart$() {
return this.selectActive(({
gotLoadStart: e
}) => e)
}
get seekTo() {
var e;
return null === (e = this.getActive()) || void 0 === e ? void 0 : e.seekTo
}
get seekTo$() {
return this.selectActive(({
seekTo: e
}) => e)
}
get seeking() {
var e;
return null !== (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.seeking) && void 0 !== e && e
}
get seeking$() {
return this.selectActive(({
seeking: e
}) => e)
}
get nudgeTarget$() {
return this.selectActive(({
nudgeInfo: e
}) => null == e ? void 0 : e.nudgeTarget)
}
get nudgeCount() {
var e;
return null !== (e = null === (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.nudgeInfo) || void 0 === e ? void 0 : e.nudgeCount) && void 0 !== e ? e : 0
}
get sourceBufferEntities$() {
return this.selectActive(({
mediaSourceEntity: e
}) => null == e ? void 0 : e.sourceBufferEntities)
}
sourceBufferEntityByType$(t) {
return this.selectActive(({
mediaSourceEntity: e
}) => {
return null === (e = null == e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[t]
})
}
bufferedSegmentsByType$(t) {
return this.selectActive(({
mediaSourceEntity: e
}) => {
return null !== (e = null === (e = null === (e = null == e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[t]) || void 0 === e ? void 0 : e.bufferedSegments) && void 0 !== e ? e : []
})
}
getBufferedSegmentsByType(e) {
return null !== (e = null === (e = this.sourceBufferEntityByType(e)) || void 0 === e ? void 0 : e.bufferedSegments) && void 0 !== e ? e : []
}
get bufferedSegmentsTuple$() {
return ed([this.bufferedSegmentsByType$(yu.Variant), this.bufferedSegmentsByType$(yu.AltAudio)]).pipe(Gn(10))
}
get timeupdate$() {
return Oc(this.mediaElement).event("timeupdate").pipe(ji(tr), Aa(), ao(125, void 0, {
leading: !0,
trailing: !0
}), hr(e => this.currentTime), ln(e => ne(e)))
}
get playingEvent$() {
return Oc(this.mediaElement).event("playing").pipe(hr(() => {}))
}
get mediaElementEntity$() {
return this.selectActive(e => Boolean(e))
}
get ended$() {
return this.selectActive(e => {
return null !== (e = null == e ? void 0 : e.ended) && void 0 !== e && e
})
}
sbUpdating$(t) {
return this.selectActive(e => {
return null !== (e = null === (e = null === (e = null === (e = null == e ? void 0 : e.mediaSourceEntity) || void 0 === e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[t]) || void 0 === e ? void 0 : e.updating) && void 0 !== e && e
})
}
sbUpdating(e) {
var t;
return null !== (e = null === (e = null === (t = null === (t = null === (t = this.getActive()) || void 0 === t ? void 0 : t.mediaSourceEntity) || void 0 === t ? void 0 : t.sourceBufferEntities) || void 0 === t ? void 0 : t[e]) || void 0 === e ? void 0 : e.updating) && void 0 !== e && e
}
sbError$(t) {
return this.selectActive(e => {
return null === (e = null === (e = null === (e = null == e ? void 0 : e.mediaSourceEntity) || void 0 === e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[t]) || void 0 === e ? void 0 : e.error
})
}
get updating$() {
return ed([this.sbUpdating$(yu.Variant), this.sbUpdating$(yu.AltAudio)]).pipe(hr(e => e.some(e => e)))
}
get bufferedRangeTuple$() {
return ed([this.selectActive(e => {
return null !== (e = null === (e = null === (e = null === (e = null == e ? void 0 : e.mediaSourceEntity) || void 0 === e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[gu.Variant]) || void 0 === e ? void 0 : e.bufferedRanges) && void 0 !== e ? e : null
}), this.selectActive(e => {
return null !== (e = null === (e = null === (e = null === (e = null == e ? void 0 : e.mediaSourceEntity) || void 0 === e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[gu.AltAudio]) || void 0 === e ? void 0 : e.bufferedRanges) && void 0 !== e ? e : null
})])
}
getBufferedRangeByType(e) {
return null !== (e = null === (e = this.sourceBufferEntities[e]) || void 0 === e ? void 0 : e.bufferedRanges) && void 0 !== e ? e : []
}
get combinedBuffer$() {
return this.selectActive(e => {
return null !== (e = null == e ? void 0 : e.bufferedRanges) && void 0 !== e ? e : []
})
}
getBufferInfo(n, s) {
var e;
const t = null === (e = this.sourceBufferEntities) || void 0 === e ? void 0 : e.map(e => null == e ? void 0 : e.bufferedRanges),
i = {
buffered: {
start: n,
end: n,
len: 0
},
bufferedSegments: []
},
a = [i, i];
return t && t.forEach((e, t) => {
if (e) {
const i = Yp.getBufferedInfo(e, n, s),
r = (null !== (e = this.sourceBufferEntities[t].bufferedSegments) && void 0 !== e ? e : []).filter(e => !(e.endPTS < i.start || e.startPTS > i.end));
a[t] = {
buffered: i,
bufferedSegments: r
}
}
}), a
}
getCombinedBufferInfo(e, t) {
var i = this.getActive();
return i ? Yp.getBufferedInfo(i.bufferedRanges, e, t) : null
}
get bufferMonitorInfo() {
var e;
return null !== (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.bufferMonitorInfo) && void 0 !== e ? e : null
}
get bufferMonitorThresholds$() {
return this.selectActive(e => {
var t = null == e ? void 0 : e.bufferMonitorInfo;
if (!t) return null;
var {
almostDryWaterLevelSeconds: i,
lowWaterLevelSeconds: r,
highWaterLevelSeconds: e,
maxBufferSeconds: t
} = t;
return {
almostDryWaterLevelSeconds: i,
lowWaterLevelSeconds: r,
highWaterLevelSeconds: e,
maxBufferSeconds: t
}
}).pipe(Is((e, t) => (null == e ? void 0 : e.lowWaterLevelSeconds) === (null == t ? void 0 : t.lowWaterLevelSeconds)))
}
get waterLevelType$() {
return this.selectActive(e => {
return null !== (e = null == e ? void 0 : e.bufferMonitorInfo.waterLevelType) && void 0 !== e ? e : null
})
}
waterLevelForType(e) {
var t;
return null !== (e = null === (t = null === (t = this.getActive()) || void 0 === t ? void 0 : t.bufferMonitorInfo.waterLevelType) || void 0 === t ? void 0 : t.sbTuple[e]) && void 0 !== e ? e : null
}
waterLevelChangedForType$(t) {
return this.waterLevelType$.pipe(hr(e => null == e ? null : null == t ? e.combined : e.sbTuple[t]))
}
get fellBelowLowWater$() {
return this.waterLevelChangedForType$(yu.Variant).pipe(ha(), hr(([e, t]) => function(e, t) {
return Jp[e] > Jp[t]
}(e, t) && (t === Dp.LowWater || t === Dp.AlmostDry)), bo(this.seekTo$, this.waitingForDisco$), hr(([e, t, i]) => e && !ne(null == t ? void 0 : t.pos) && !i), Ra(!1))
}
isBufferedToEnd$(s, a = !0) {
return ed([this.combinedBuffer$, this.selectActive(e => e.bufferMonitorInfo).pipe(Kp(), hr(e => a ? e.almostDryWaterLevelSeconds : Math.max(e.almostDryWaterLevelSeconds, e.lowWaterLevelSeconds / 2))), this.seeking$]).pipe(hr(([e, t]) => {
var i = this.minSBDuration;
if (!e || !ne(i) && a) return !1;
e = Yp.getBufferedInfo(e, this.currentTime, s).end;
let r, n;
return n = a ? (r = i, Math.abs(r - e) <= t) : (r = this.mediaElementDuration, r - e <= t), n
}), Is())
}
needData$(e, n = !1) {
var t = !n;
return ed([this.msReadyState$, this.waterLevelChangedForType$(null), this.isBufferedToEnd$(e, t), this.bufferedRangeTuple$, this.seekTo$, this.mediaElementDuration$]).pipe(Gn(10), hr(([e, t, i, , r]) => {
if ("closed" === e) return !1;
if (n) return !0;
i = null == t || !i && t !== Dp.AboveHighWater, r = this.isIframeRate || !!r;
return i || t !== Dp.AboveHighWater && r
}), tc("needData"))
}
getSourceBufferInfoAction(e, t, i, r) {
var {
currentTime: n,
sourceBufferEntities: s,
msReadyState: a
} = this;
let o = [null, null];
return !e && i.every(e => !(null != e && e.userInitiated)) ? null : "open" === a && s && null != s[0] ? (o = this.getBufferInfo(n, r), {
position: n,
discoSeqNum: null == t ? void 0 : t.discoSeqNum,
bufferInfoTuple: o,
switchContexts: i
}) : {
position: null == t ? void 0 : t.pos,
discoSeqNum: null == t ? void 0 : t.discoSeqNum,
bufferInfoTuple: o,
switchContexts: i
}
}
get haveEnough() {
var e;
return null !== (e = null === (e = this.getActive()) || void 0 === e ? void 0 : e.haveEnough) && void 0 !== e && e
}
get haveEnough$() {
return this.selectActive(({
haveEnough: e
}) => e)
}
static likelyToKeepUp(e, t, i) {
return t && i >= e.HAVE_FUTURE_DATA
}
get playbackLikelyToKeepUp() {
return nf.likelyToKeepUp(this.mediaElement, this.haveEnough, this.readyState)
}
get playbackLikelyToKeepUp$() {
return ed([this.haveEnough$, this.readyState$]).pipe(hr(([e, t]) => nf.likelyToKeepUp(this.mediaElement, e, t)))
}
getCurrentWaterLevel(e) {
var t = this.currentTime,
i = null !== (i = null === (i = this.getActive()) || void 0 === i ? void 0 : i.bufferedRanges) && void 0 !== i ? i : [];
return Yp.getBufferedInfo(i, t, e).len
}
getCombinedMediaSourceBufferInfo(e) {
var t = this.currentTime,
[i, r] = null === (r = null === (i = this.getActive()) || void 0 === i ? void 0 : i.mediaSourceEntity) || void 0 === r ? void 0 : r.sourceBufferEntities;
return [Yp.getBufferedInfo(null !== (i = null == i ? void 0 : i.bufferedRanges) && void 0 !== i ? i : [], t, e), Yp.getBufferedInfo(null !== (r = null == r ? void 0 : r.bufferedRanges) && void 0 !== r ? r : [], t, e)]
}
getCurrentWaterLevelByType(e, t) {
var i = this.currentTime,
e = this.sourceBufferEntityByType(e),
e = null !== (e = null == e ? void 0 : e.bufferedRanges) && void 0 !== e ? e : [];
return Yp.getBufferedInfo(e, i, t).len
}
canContinuePlaybackWithoutGap(e, t, i, r) {
if ("LIVE" !== e.type) return !0;
if (!e.ptsKnown) return !1;
var n = this.currentTime,
i = performance.now() + i.avgPlaylistLoadTimeMs + 1e3 * e.targetduration,
t = e.fragments[0].start + (i - t) / 1e3;
let s = this.getCombinedBufferInfo(n, r).end;
return s >= e.fragments[0].start - r && s <= e.fragments[0].start + e.totalduration && (s = e.fragments[0].start + e.totalduration), t <= s
}
get stallInfo$() {
return this.selectActive(e => {
return null !== (e = null == e ? void 0 : e.stallInfo) && void 0 !== e ? e : null
})
}
get textTracks() {
return this.mediaElement.textTracks
}
get textTracksCreated$() {
return this.selectActive(e => null == e ? void 0 : e.textTracksCreated)
}
get mediaOptionParsedSubtitleRecord() {
var e;
return null === (e = this.getActive()) || void 0 === e ? void 0 : e.mediaOptionParsedSubtitleRecord
}
getParsedSubtitleRecordsForMediaOption(e) {
return this.mediaOptionParsedSubtitleRecord ? this.mediaOptionParsedSubtitleRecord[e] || {} : null
}
}
class sf {
constructor(e, t, i, r) {
this.mediaSink = e, this.media = t, this.logger = r, this.useCustomMediaFunctions = i.useCustomMediaFunctions, this.overridePlaybackRate = i.overridePlaybackRate
}
install() {
const e = this.media;
e && (this.useCustomMediaFunctions && e && e.play && e.pause && (e.originalPlay || (e.originalPlay = e.play.bind(e)), e.originalPause || (e.originalPause = e.pause.bind(e)), e.play = () => (this.mediaSink.checkForReplay(), this.mediaSink.desiredRate = 1, 0 < e.currentTime && !e.paused && !e.ended && 2 < e.readyState ? Promise.resolve() : new Promise((e, t) => {
this.pendingPlayPromises || (this.pendingPlayPromises = []), this.pendingPlayPromises.push({
resolve: e,
reject: t
})
})), e.pause = () => {
this.mediaSink.desiredRate = 0
}), "function" == typeof HTMLMediaElement && this.overridePlaybackRate && Object.defineProperty(e, "playbackRate", {
enumerable: !0,
configurable: !0,
get: function() {
return 1
},
set: function(e) {
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, "playbackRate").set.call(this, e)
}
}), this.playPromise = null, this.expectPauseEvent = this.expectPlayEvent = !1)
}
uninstall() {
const e = this.media;
e && (e.originalPlay && (e.play = e.originalPlay, delete e.originalPlay), e.originalPause && (e.pause = e.originalPause, delete e.originalPause), this.overridePlaybackRate && (e.playbackRate = 1, delete e.playbackRate)), this.playPromise = null, this.expectPauseEvent = this.expectPlayEvent = !1
}
play() {
var e;
this.media && (e = this.mediaSink.flushing, this.playPromise || e ? this.logger.warn(`Ignoring play command playPromise/flushing ${Boolean(this.playPromise)}/${e}`) : (this.expectPlayEvent = this.expectPlayEvent || this.media.paused, this.playPromise = this._mediaPlayInternal(), this.playPromise && this.playPromise.then(function() {
this.playPromise = null, this._handlePendingPlayPromises(null)
}.bind(this)).catch(function(e) {
this.playPromise = null, this.expectPlayEvent = !1, this._handlePendingPlayPromises(e || new Error("Play rejected for unknown reason")), "NotAllowedError" === (null == e ? void 0 : e.name) ? (this.logger.warn("play() not allowed, going back to rate 0"), this.mediaSink.desiredRate = 0) : this.logger.error(`play() error: ${null==e?void 0:e.message}`)
}.bind(this))))
}
pause() {
this.media && (this.playPromise ? this.playPromise.then(() => {
var e = this.mediaSink.mediaQuery;
(0 === this.mediaSink.desiredRate || e.seeking && !e.playbackLikelyToKeepUp) && this._mediaPauseInternal()
}).catch(e => {
this.logger.error(`Promise error in pause(): ${e.message}`)
}) : this._mediaPauseInternal())
}
_handlePendingPlayPromises(t) {
var e, i = null === (e = this.pendingPlayPromises) || void 0 === e ? void 0 : e.length;
if (t)
for (let e = 0; e < i; e++) this.pendingPlayPromises[e].reject(t);
else
for (let e = 0; e < i; e++) this.pendingPlayPromises[e].resolve();
this.pendingPlayPromises = []
}
_mediaPlayInternal() {
return (this.media.originalPlay || this.media.play.bind(this.media))()
}
_mediaPauseInternal() {
return this.expectPauseEvent = this.expectPauseEvent || !this.media.paused, (this.media.originalPause || this.media.pause.bind(this.media))()
}
}
class af extends Error {}
class of extends p {
constructor(e, t, i, r, n) {
super(L, e, t, i, r), this.sbType = n, this.response = r
}
}
class lf extends of {
constructor(e, t, i, r) {
super("bufferAddCodecError", !1, e, t, i), this.mediaOptionId = r, this.mediaOptionType = Vu(this.sbType)
}
}
class df extends of {
constructor(e, t, i, r, n, s) {
super(e, t, i, r, n), this.isTimeout = s, this.mediaOptionType = Vu(this.sbType)
}
}
class uf extends df {
constructor(e, t, i, r) {
super("bufferFullError", !1, e, t, i, !1), this.maxTotalBytes = r
}
}
class cf extends df {
constructor(e, t, i) {
super(n, !1, e, t, i, !0)
}
}
class hf extends df {
constructor(e, t, i, r) {
super(n, !1, e, t, i, !1), this.mediaOptionId = r, this.mediaOptionType = Vu(this.sbType)
}
}
class pf extends p {
constructor(e, t, i, r, n, s, a = NaN) {
super(L, e, t, i, r), this.stallType = n, this.bufferLen = s, this.nudgePosition = a, this.response = r
}
}
class ff extends $t {
constructor(n, e, s, a, o, l, d, u, c) {
super(e => {
const t = Oc(l),
i = u.child({
sb: o
});
n.setSourceBufferEntity(o, d), d.mimeType.includes("audio/mpeg") && (this.updateMp3Timestamps = !0);
const r = an(t.event("updatestart").pipe(Za(() => {
n.setSourceBufferUpdating(o)
})), t.event("updateend").pipe(ji(tr), Za(() => {
var e = Yp.timeRangesToBufferedRange(l.buffered),
t = Yp.timeRangesToBufferedRange(s.buffered);
n.setBufferedRangesUpdated(o, e, t, !1, c)
})), t.event("error").pipe(Za(() => {
n.setSourceBufferError(o, "Got source buffer error")
}))).pipe(La(() => Ii)).subscribe(e);
return () => {
r.unsubscribe();
try {
"open" === a.readyState && l.abort(), a.removeSourceBuffer(l)
} catch (e) {
i.error(`Error aborting SourceBuffer on unsubscribe: ${e.message}`)
}
}
}), this.mediaElementStore = n, this.mediaElementQuery = e, this.mediaElement = s, this.type = o, this.sourceBuffer = l, this.config = c, this.updateMp3Timestamps = !1
}
get buffered() {
return this.sourceBuffer.buffered
}
appendBuffer(e, t) {
return Zr(() => this.sourceBuffer.updating ? this._waitForUpdateEndOrError().pipe(La(() => this.appendBuffer(e, t))) : this._appendBufferAsync(e, t))
}
_appendBufferAsync(e, t) {
let i = NaN,
r = null;
const n = ("startPTS" in t ? t.frag : t).mediaOptionId;
try {
"startPTS" in t && (r = {
startPTS: t.startPTS,
endPTS: t.endPTS,
bytes: t.bytes,
frag: Object.assign({}, t.frag)
}), this.mediaElementStore.setInflightSegment(this.type, r), i = performance.now(), this.sourceBuffer.appendBuffer(e)
} catch (e) {
return 22 !== e.code ? (this.mediaElementStore.setInflightSegment(this.type, null), this.mediaElement.error ? Vi(new hf(e.message, $.VideoDecoderBadDataErr, this.type, n)) : Vi(e)) : (this.mediaElementStore.setBufferedRangesUpdated(this.type, Yp.timeRangesToBufferedRange(this.sourceBuffer.buffered), Yp.timeRangesToBufferedRange(this.mediaElement.buffered), !0, this.config), Vi(new uf(e.message, $.AllocationFailed, this.type, this.maxTotalBytes)))
}
return this._waitForUpdateEndOrError().pipe(hr(() => ({
startAppend: i,
endAppend: performance.now(),
bytesAppend: e.byteLength
})), So(1e4), Vn(e => {
throw e instanceof dr ? (this.sourceBuffer.abort(), e = new cf("Append took longer than 10000ms", $.InternalError, this.type)) : e instanceof of && (e = new hf("Decode error", $.VideoDecoderBadDataErr, this.type, n)), e
}))
}
remove(e, t) {
return this._waitForUpdateEndOrError().pipe(La(this._removeAsync.bind(this, e, t)))
}
_removeAsync(e, t) {
try {
this.sourceBuffer.remove(e, t)
} catch (e) {
return Vi(new of (r, !1, e.message, $.InternalError, this.type))
}
return this._waitForUpdateEndOrError()
}
abort() {
try {
this.sourceBuffer.abort()
} catch (e) {
return Vi(new of (r, !1, e.message, $.InternalError, this.type))
}
return this._waitForUpdateEndOrError()
}
get updating() {
return this.sourceBuffer.updating
}
get timestampOffset() {
return this.sourceBuffer.timestampOffset
}
set timestampOffset(e) {
this.sourceBuffer.timestampOffset = e
}
get gotQuotaExceeded() {
var e;
return null !== (e = null === (e = this.mediaElementQuery.sourceBufferEntityByType(this.type)) || void 0 === e ? void 0 : e.gotQuotaExceeded) && void 0 !== e && e
}
get bufferedSegments() {
var e;
return null !== (e = null === (e = this.mediaElementQuery.sourceBufferEntityByType(this.type)) || void 0 === e ? void 0 : e.bufferedSegments) && void 0 !== e ? e : []
}
get totalBytes() {
var e;
return null !== (e = null === (e = this.mediaElementQuery.sourceBufferEntityByType(this.type)) || void 0 === e ? void 0 : e.totalBytes) && void 0 !== e ? e : 0
}
get maxTotalBytes() {
var e = null !== (e = null === (e = this.mediaElementQuery.sourceBufferEntityByType(this.type)) || void 0 === e ? void 0 : e.maxTotalBytes) && void 0 !== e ? e : 1 / 0;
return this.gotQuotaExceeded ? e : 1 / 0
}
_waitForUpdateEndOrError() {
return this.sourceBuffer.updating && this.mediaElementStore.setSourceBufferUpdating(this.type), this.mediaElementQuery.sbUpdating$(this.type).pipe(ln(e => !1 === e), bo(this.mediaElementQuery.sbError$(this.type)), hr(([, e]) => {
if (e) throw new of (r, !1, "Got error during sourceBuffer operation", $.InternalError, this.type)
}), Ds(1))
}
}
class mf extends $t {
constructor(a, o, e, l, t) {
super(e => {
const t = Oc(l),
i = an(t.event("sourceopen"), t.event("sourceclose"), t.event("sourceended")).pipe(Za(e => {
e = (null !== (e = null == e ? void 0 : e.target) && void 0 !== e ? e : l).readyState;
o.msReadyState = e
})),
r = this.sourceBuffers$.pipe(La(e => e ? an(...e.filter(e => null != e)) : Ii)),
n = an(i, r).pipe(La(() => Ii)).subscribe(e),
s = URL.createObjectURL(l);
return a.src = s, o.setMediaSourceEntity(s, l.readyState), () => {
n.unsubscribe(), URL.revokeObjectURL(s), a.src === s && (a.removeAttribute("src"), a.load(), o.setMediaSourceEntity(null)), this.sourceBuffers$.next(null)
}
}), this.mediaElement = a, this.mediaElementStore = o, this.mediaElementQuery = e, this.mediaSource = l, this.logger = t, this.sourceBuffers$ = new yi(null)
}
get readyState() {
return this.mediaSource.readyState
}
set duration(e) {
this.mediaSource.duration = e
}
get duration() {
return this.mediaSource.duration
}
endOfStream(e) {
this.mediaSource.endOfStream(e)
}
createSourceBuffers(e, a) {
const o = this.mediaSource;
al(() => {
try {
const s = [null, null];
e.forEach((t, i) => {
if (t) {
var {
mimeType: r,
mediaOptionId: n
} = t;
let e;
try {
e = o.addSourceBuffer(r)
} catch (t) {
throw new lf(t.message, $.IncompatibleAsset, i, n)
}
s[i] = new ff(this.mediaElementStore, this.mediaElementQuery, this.mediaElement, this.mediaSource, i, e, t, this.logger, a)
}
}), this.sourceBuffers$.next(s)
} catch (e) {
if (!(e instanceof p)) throw new af(`error initializing sourcebuffers ${e.message} readyState=${o.readyState}`);
throw e
}
})
}
get needSourceBuffers() {
return null == this.sourceBuffers$.value || null == this.sourceBuffers$.value[0]
}
get sourceBuffers() {
return this.sourceBuffers$.value
}
getSourceBufferByType(e) {
var t = this.sourceBuffers$.value;
return t ? t[e] : null
}
updateLiveSeekableRange(e, t) {
const i = this.mediaSource;
null != i && i.setLiveSeekableRange && "open" === (null == i ? void 0 : i.readyState) && i.setLiveSeekableRange(e, t)
}
clearLiveSeekableRange() {
const e = this.mediaSource;
null != e && e.clearLiveSeekableRange && "open" === (null == e ? void 0 : e.readyState) && e.clearLiveSeekableRange()
}
}
function gf(e, c, t) {
const {
lowBufferThreshold: h,
lowBufferWatchdogPeriod: p,
highBufferWatchdogPeriod: f,
seekWatchdogPeriod: m
} = t, i = ed([c.desiredRate$, c.ended$, c.combinedBuffer$, c.seekTo$]).pipe(hr(e => {
var t, [i, r, n, s] = e;
return t = c.currentTime, e = i, i = r, r = n, n = isFinite(null == s ? void 0 : s.pos), s = r.some(e => e.start <= t && e.end > t), !(1 !== e || i || 0 === r.length || n && !s)
}), Is()), r = c.combinedBuffer$.pipe(hr(() => c.getCurrentWaterLevel(0) <= t.lowBufferThreshold || !c.haveEnough ? Cp.LowBuffer : Cp.HighBuffer), Is()), n = ed([i, c.seekTo$, c.gotPlaying$, r]).pipe(La(e => {
var [t, i, r] = e;
if (!t) return $i(null);
var n, s, a, o, l, d, u, e = c.nudgeCount,
t = m + +e;
return isFinite(null == i ? void 0 : i.pos) || !r ? (n = c, s = performance.now(), t = t, a = h, bn(1e3 * t).pipe(hr(() => {
var e = n.currentTime,
t = n.getCombinedBufferInfo(e, 0);
return yf(Cp.Seek, e, s, t, a, n.haveEnough)
}))) : (o = c, l = p, d = f + +e, u = h, an($i(o.currentTime), o.timeupdate$).pipe(La(e => {
const t = performance.now(),
i = o.getCombinedBufferInfo(e, 0);
let r, n;
return r = i.len <= u || !o.haveEnough ? (n = l, Cp.LowBuffer) : (n = d, Cp.HighBuffer), bn(Math.max(100, 1e3 * n)).pipe(hr(() => e < o.currentTime ? null : yf(r, e, t, i, u, o.haveEnough)))
})))
})), s = n.pipe(Kp(), bo(c.combinedBuffer$), La(([]) => ed([c.seeking$, c.paused$])), La(([e, t]) => e || t ? Ii : c.timeupdate$.pipe(ha(), ln(([e, t]) => ne(e) && ne(t) && e < t), Ds(1))), hr(() => null));
return an(n, s)
}
function yf(e, t, i, r, n, s) {
var a = performance.now() - i;
return {
type: e,
isLowBufferStall: r.len <= n || !s,
tstalled: i,
stallDurationMs: a,
currentTime: t
}
}
class vf extends $t {
constructor(w, A, e, t, i, r, n) {
super(e => {
const t = this.config,
i = A.startMediaSession(w, t.maxBufferLength, t.almostDryBufferSec, t.defaultTargetDuration),
r = Sf(w, A, this._mediaQuery, this, this.hlsGapless, t, this.logger, this.rtcService),
n = this.mediaSource$.pipe(La(e => e || Ii)),
s = this._mediaQuery.seekTo$.pipe((u = w, c = this._mediaQuery, p = (h = this).config, f = (f = this.logger).child({
name: "seek"
}), e => e.pipe(Za(e => {}), ln(e => e && ne(e.pos)), La(e => c.readyState$.pipe(ln(e => e >= u.HAVE_METADATA), Ds(1), Zs(e), La(({
pos: e,
fromEvent: t
}) => (h.checkForInconsistentStoreBufferRangesAndUpdate(), u.paused || h.pause(), t || (u.currentTime = e), Gu(c.haveEnough$, e => e).pipe(Zs({
pos: e,
fromEvent: t
})))), La(({
pos: e,
fromEvent: t
}) => {
var i = c.getCombinedBufferInfo(e, 0),
r = i.nextStart;
return (!t || p.nudgeFromEventSeek) && 0 === i.len && ne(r) && e < r && r - e <= p.maxSeekHole ? (h.seekTo = r, Ii) : $i(e)
}), bo(c.desiredRate$), hr(([, e]) => {
u.paused && 0 !== e && h.play()
}), $a(Ii), Vn(e => (f.error(`error during seek ${e.message}`), Ii))))))),
a = this._mediaQuery.desiredRate$.pipe((o = w, l = this._mediaQuery, d = this, e => e.pipe(bo(l.seekTo$), La(([e, t]) => ne(null == t ? void 0 : t.pos) ? Ii : 0 === e ? (o.paused || d.pause(), Ii) : Gu(l.haveEnough$, e => e).pipe(Za(() => {
o.paused && d.play()
}))), $a(Ii))));
var o, l, d, u, c, h, p, f;
this.liveSeekableWindow = {
start: NaN,
end: NaN
}, this.mediaFunctions = this.mediaFunctions || new sf(this, w, t, this.logger), this.mediaFunctions.install();
var m, g, y, v, S, b, T, E, I = an(gf(this.logger, this._mediaQuery, this.config).pipe(Za(e => {
A.setStallInfo(e)
})), this.mediaQuery.stallInfo$.pipe((g = A, y = (m = this).config, v = this.logger, e => e.pipe(_s(e => e ? function(i, e, r, n) {
const s = i.mediaQuery;
return an(ed([s.seekTo$, s.nudgeTarget$]).pipe(ln(([e, t]) => e && ne(e.pos) && ne(t) && (e.pos < t || e.pos - t > r.maxSeekHole)), Zs(null)), s.stallInfo$).pipe(bo(s.desiredRate$), ji(tr), hr(([c, e], t) => {
if (!c) return NaN;
var h = s.getCombinedBufferInfo(c.currentTime, 0),
e = Wp(e);
return function(e, t, i, r, n) {
var {
type: s,
isLowBufferStall: a,
currentTime: o
} = c, l = h.len, d = t.maxSeekHole;
let u = NaN;
if (a) {
const t = h.nextStart - o <= d ? h.nextStart : 1 / 0;
ne(t) ? u = t : e.mediaQuery.msDuration - o < .1 && (u = o + .1)
} else if (n < t.nudgeMaxRetry) u = o + t.nudgeOffset;
else {
if (!r) throw i.error(`still stuck in high buffer @${o} after ${t.nudgeMaxRetry}, raise fatal error`), new pf("bufferStalledError", !0, "got fatal buffer error", $.VideoDecoderBadDataErr, s, l);
i.error(`still stuck in high buffer @${o} after ${t.nudgeMaxRetry}, non fatal in iframeMode`)
}
return ne(u) && e.nudgeSeek(u, n + 1), u
}(i, r, n, e, t)
}), Wa(e => ne(e)), Vs(() => {
e.setNudgeInfo(null)
}))
}(m, g, y, v) : $i(NaN))))));
an(r, n, s, a, I, (S = this.mediaQuery, b = A, I = t.maxBufferHole, an((E = I, ed([(T = S).bufferMonitorThresholds$, T.combinedBuffer$, T.seeking$]).pipe(hr(([e]) => null == e ? null : tf(T, E)))), rf(S, I)).pipe(ji(tr), Za(({
combined: e,
sbTuple: t
}) => {
b.updateWaterLevels(e, t)
})))).pipe($a(Ii), Vs(() => {
A.remove(i), this.mediaFunctions.uninstall(), this.mediaFunctions = void 0
})).subscribe(e)
}), this.mediaElement = w, this.mediaElementStore = A, this.config = e, this.hlsGapless = t, this.logger = i, this.teardownWG$ = r, this.rtcService = n, this.mediaSource$ = new yi(null), this.mediaKeysMutex = new zp, this._mediaQuery = new nf(w, A), this.logger = i.child({
name: "mse"
}), this.createId3Track(w), this.mediaFunctions = new sf(this, w, e, this.logger)
}
get mediaSourceAdapter() {
return this.mediaSource$.value
}
get sourceBuffers() {
var e;
return null !== (e = null === (e = this.mediaSourceAdapter) || void 0 === e ? void 0 : e.sourceBuffers) && void 0 !== e ? e : []
}
get needSourceBuffers() {
return !this.sourceBuffers[0]
}
get mediaQuery() {
return this._mediaQuery
}
sourceBuffersBufferedRangeByType(e) {
var t, e = null === (t = null === (t = this.mediaSourceAdapter) || void 0 === t ? void 0 : t.sourceBuffers) || void 0 === t ? void 0 : t[e];
return e ? Yp.timeRangesToBufferedRange(e.sourceBuffer.buffered) : null
}
createId3Track(e) {
this.id3Track = e.addTextTrack("metadata", "id3"), this.id3Track.mode = "hidden"
}
checkForInconsistentStoreBufferRangesAndUpdate() {
var e = Yp.timeRangesToBufferedRange(this.mediaElement.buffered),
t = this.sourceBuffersBufferedRangeByType(yu.Variant),
i = this.sourceBuffersBufferedRangeByType(yu.AltAudio),
r = null !== (n = null === (r = this.mediaQuery.sourceBufferEntityByType(yu.Variant)) || void 0 === r ? void 0 : r.bufferedRanges) && void 0 !== n ? n : null,
n = null !== (n = null === (n = this.mediaQuery.sourceBufferEntityByType(yu.AltAudio)) || void 0 === n ? void 0 : n.bufferedRanges) && void 0 !== n ? n : null;
this.shouldUpdateStoreValues(t, r) && (this.logger.warn(`[${Uu[yu.Variant]}] SourceBuffer's loaded bufferedRanges ${JSON.stringify(t)} & mediaElementStore's bufferedRanges ${JSON.stringify(r)} are out of sync!`), this.updateMediaElementStoreBufferedRanges(e, yu.Variant)), this.shouldUpdateStoreValues(i, n) && (this.logger.warn(`[${Uu[yu.AltAudio]}] SourceBuffer's loaded bufferedRanges ${JSON.stringify(i)} & mediaElementStore's bufferedRanges ${JSON.stringify(n)} are out of sync!`), this.updateMediaElementStoreBufferedRanges(e, yu.AltAudio))
}
shouldUpdateStoreValues(e, i) {
return !(null == e && null == i || (null == e ? void 0 : e.length) == (null == i ? void 0 : i.length) && !e.find(t => {
var e = Ku.search(i, e => t.start >= e.start && t.end <= e.end ? 0 : t.end < e.start ? -1 : 1);
return null == e || e.start != t.start || e.end != t.end || void 0
}))
}
updateMediaElementStoreBufferedRanges(e, t) {
var i = this.sourceBuffersBufferedRangeByType(t);
i && !this.mediaQuery.sbUpdating(t) && this.mediaElementStore.setBufferedRangesUpdated(t, i, e, !1, this.config)
}
destroyMediaSource() {
this.mediaSource$.next(null)
}
makeMediaSource() {
return new MediaSource
}
openMediaSource(t) {
al(() => {
var e;
t ? (e = new mf(this.mediaElement, this.mediaElementStore, this.mediaQuery, t, this.logger), this.mediaSource$.next(e)) : this.mediaSource$.next(null)
})
}
createSourceBuffers(e) {
const t = this.mediaSource$.value;
if (!t) throw new Error("createSourceBuffers empty mediaSource");
t.createSourceBuffers(e, this.config)
}
_waitForMediaSourceOpen(i) {
const r = this.mediaQuery.mediaSourceEntity.objectUrl;
return ed([this.mediaQuery.msReadyState$, this.mediaQuery.msObjectUrl$]).pipe(La(([e, t]) => t !== r ? $i(null) : "open" === e || "ended" === e ? $i(i) : Ii))
}
get appendOrder() {
return this.mediaQuery.isIframeRate ? [yu.Variant, yu.AltAudio] : [yu.AltAudio, yu.Variant]
}
clearFlush(e) {
e.forEach(e => {
e && (e.dataSeg.flushBeforeAppend = {
start: 0,
end: 0
})
})
}
getSwitchPosition(e) {
return e.reduce((e, t) => {
t = t ? t.dataSeg.switchPosition : void 0;
return ne(t) ? ne(e) ? Math.min(e, t) : t : e
}, void 0)
}
checkForReplay() {
var e = this.mediaElement;
e.paused && !e.seeking && e.duration && e.currentTime && e.currentTime >= e.duration - this.config.maxTotalDurationTolerance && (this.seekTo = 0)
}
resetMediaSourceIfNeeded(r) {
const n = this["mediaQuery"],
e = n["sourceBufferEntities"],
t = n.getActive()["expectedSbCount"];
if (!e || this.needSourceBuffers) return this._waitForMediaSourceOpen(r);
const s = function(e, s, t, i) {
const r = s.filter(e => Boolean(e)).length,
n = e.filter(e => Boolean(e)).length,
l = [null, null];
e.forEach((e, t) => {
var i, r, n, s, a, o;
e && (s = e["offsetTimestamp"], a = S(s), i = e.initSeg.mimeType, {
audioCodec: r,
videoCodec: n
} = e.initSeg.initParsedData, o = e["dataSeg"], s = S(o.startPts) - a, a = S(o.endPts) - a, o = o.discoSeqNum, l[t] = {
audioCodec: r,
videoCodec: n,
mimeType: i,
startPTSSec: s,
endPTSSec: a,
discoSeqNum: o,
mediaOptionId: e.initSeg.mediaOptionId
})
});
let a = r === t,
o = n === t;
if (1 === n && n < t && 0 !== r) {
const t = e[gu.Variant] ? gu.Variant : gu.AltAudio,
h = 1 - t,
r = l[t],
n = l[h] = function(e, i, r, n, t, s) {
const a = null == e ? void 0 : e.bufferedSegments;
if (!a) return s.warn("getMatchingInfo trying to query null sbEntity"), null;
s = a.find(e => {
var t = e.frag.discoSeqNum === n,
e = Math.max(i, e.startPTS) < Math.min(r, e.endPTS);
return t && e
});
if (null == s) return null; {
const {
audioCodec: i,
videoCodec: r,
mimeType: o
} = e;
return {
mimeType: o,
audioCodec: i,
videoCodec: r,
startPTSSec: s.startPTS,
endPTSSec: s.endPTS,
discoSeqNum: n,
mediaOptionId: t
}
}
}(s[h], r.startPTSSec, r.endPTSSec, r.discoSeqNum, r.mediaOptionId, i);
if (!n)
if (null !== (e = null === (e = e[gu.Variant]) || void 0 === e ? void 0 : e.dataSeg) && void 0 !== e && e.iframe && t === gu.Variant && l[t]) {
const p = s[t].videoCodec,
h = l[t].videoCodec;
if (a = a && (p === h || be.isCompatibleVideoCodec(p, h)), a) return {
compatible: a,
boundary: NaN,
allowance: NaN,
discoSeqNum: l[t].discoSeqNum
}
} else i.warn(`${Nu[t]} No matching frag found ${ae(r)} buffered=${ae(s[h].bufferedSegments.map(e=>{var{mediaSeqNum:t,discoSeqNum:i}=e.frag;return{mediaSeqNum:t,discoSeqNum:i,startPTS:e.startPTS,endPTS:e.endPTS}}))}`);
o = null != n
}
let d = NaN,
u = NaN,
c = NaN;
return o && l.forEach((e, t) => {
if (!e) return null;
ne(c) ? c !== e.discoSeqNum && (c = NaN) : c = e.discoSeqNum;
t = s[t];
if (t) {
const s = t.audioCodec,
i = t.videoCodec,
{
audioCodec: r,
videoCodec: n
} = e;
a = a && (i === n || be.isCompatibleVideoCodec(i, n)), a = a && (s === r || be.isCompatibleAudioCodec(s, r))
} else a = !1;
d = ne(d) ? (u = Math.abs(e.startPTSSec - d), Math.max(e.startPTSSec, d)) : (u = 0, e.startPTSSec)
}), {
compatible: a && o,
boundary: d,
allowance: u,
discoSeqNum: c
}
}(r, e, t, (this.config.maxBufferHole, this.logger));
if (s.compatible) return this._waitForMediaSourceOpen(r);
let i = s.boundary;
const a = s.allowance,
o = this.getSwitchPosition(r);
if (ne(o) && (i = o), !ne(i)) return this.logger.warn("not enough info #disco"), $i(null);
const l = fn(Gu(an($i(n.currentTime), n.timeupdate$), e => e >= i), Gu(n.stallInfo$.pipe(hr(e => {
return null !== (e = null == e ? void 0 : e.currentTime) && void 0 !== e ? e : NaN
})), e => e >= i - a - this.config.discontinuitySeekTolerance));
return this.mediaElementStore.waitingForDisco = !0, l.pipe(Zs(i), La(e => {
performance.now();
const t = n.currentTime,
i = this.msDuration;
return this.resetMediaSource(Math.max(t, e), s.discoSeqNum), this._waitForMediaSourceOpen(r).pipe(Za(() => {
performance.now(), this.msDuration = i
}))
}), Vs(() => {
this.mediaElementStore.waitingForDisco = !1
}))
}
resetMediaSource(e = NaN, t) {
var i;
ne(e) || (e = null !== (i = null === (i = this.mediaQuery.seekTo) || void 0 === i ? void 0 : i.pos) && void 0 !== i ? i : this.mediaQuery.currentTime), ne(t) || (t = null === (i = this.mediaQuery.seekTo) || void 0 === i ? void 0 : i.discoSeqNum), 0 < this.sourceBuffers.length && (this.openMediaSource(this.makeMediaSource()), this.setSeekToWithDiscontinuity(e, t))
}
setExpectedSbCount(e) {
this.mediaElementStore.expectedSbCount = e
}
appendInitSegments(l, d) {
const {
mediaQuery: e,
mediaElementStore: u,
sourceBuffers: c
} = this, h = e["sourceBufferEntities"];
if (!c) throw new Error("appendInitSegments: null sourceBuffers");
if (!h) throw new Error("appendInitSegments: null sourceBufferEntities");
var t = this.appendOrder.map(t => {
if (l[t]) {
const i = c[t],
r = l[t],
n = h[t],
s = r["initSeg"];
if (!n) throw new Error(`appendInitSegments: sb[${Uu[t]}] null currentSbEntity`);
if (!i) throw new Error(`appendInitSegments: sb[${Uu[t]}] null source buffer`);
const a = n.initSegmentInfo,
o = function() {
var {
itemId: e,
mediaOptionId: t,
discoSeqNum: i,
keyTagInfo: r
} = s;
return {
itemId: e,
mediaOptionId: t,
discoSeqNum: i,
keyId: je(null == r ? void 0 : r.keyId)
}
}();
if ((e = o) && a && e.itemId === a.itemId && e.mediaOptionId === a.mediaOptionId && e.discoSeqNum === a.discoSeqNum && e.keyId === a.keyId) return $i(null);
var e = Vu(t);
return i.appendBuffer(s.data, s).pipe(Za(e => {
u.setInitSegmentEntity(t, o)
}), d(i, e, s.mediaOptionId, this.config, this.mediaQuery))
}
}).filter(e => Boolean(e));
return 0 === t.length ? $i(null) : en(t)
}
appendDataSegments(m, g) {
var e = this.appendOrder.map(e => {
const t = m[e],
{
mediaQuery: i,
sourceBuffers: r
} = this,
n = i["sourceBufferEntities"];
if (!r) throw new Error("appendDataSegments: null sourceBuffers");
if (!n) throw new Error("appendDataSegments: null sourceBufferEntities");
if (!t) return null;
const s = r[e],
a = m[e],
o = n[e];
if (!o) throw new Error("appendDataSegments: null currentSbEntity");
const l = o.initSegmentInfo,
d = a["dataSeg"];
if (!l) throw new Error(`appendDataSegments: sb[${Uu[e]}] null currentInitSegmentInfo`);
if (!o) throw new Error(`appendDataSegments: sb[${Uu[e]}] null currentSbEntity`);
if (!s) throw new Error(`appendDataSegments: sb[${Uu[e]}] null source buffer`);
const u = s.timestampOffset,
c = {
startPTS: S(d.startPts) + u,
endPTS: S(d.endPts) + u,
firstKeyframePts: d.firstKeyframePts ? S(d.firstKeyframePts) + u : void 0,
bytes: d.data2 ? d.data1.byteLength + d.data2.byteLength : d.data1.byteLength,
frag: {
itemId: d.itemId,
mediaOptionId: d.mediaOptionId,
mediaSeqNum: d.mediaSeqNum,
discoSeqNum: d.discoSeqNum,
keyTagInfo: d.keyTagInfo,
isLastFragment: d.isLastFragment,
iframe: d.iframe,
framesWithoutIDR: d.framesWithoutIDR,
dropped: d.dropped
}
},
h = Vu(e);
let p = Wu;
var f = t.dataSeg.flushBeforeAppend;
return f && f.start !== f.end && (p = this.flushData(e, f.start, f.end)), p.pipe(La(() => $i(d.data1, d.data2).pipe(Kp()).pipe(Wn(e => s.appendBuffer(e, c).pipe(g(s, h, d.mediaOptionId, this.config, this.mediaQuery))))), Za(() => {
i.getBufferedRangeByType(e)
}))
}).filter(e => Boolean(e));
return 0 === e.length ? $i(null) : en(e)
}
setStoreSbTimeoffsets(s) {
const {
mediaElementStore: a,
sourceBuffers: e
} = this;
e.forEach((t, i) => {
if (t && s[i]) {
var {
offsetTimestamp: r,
dataSeg: n
} = s[i], n = S(n.startPts);
let e = -1 * S(r);
t.updateMp3Timestamps && .1 < Math.abs(t.timestampOffset - n) && (e = n + e), t.timestampOffset !== e && (t.timestampOffset = e, a.setTimestampOffset(i, t.timestampOffset))
}
})
}
adjustJaggedStart(e) {
const {
mediaQuery: t,
logger: n
} = this, {
sourceBufferEntities: i,
currentTime: r,
seekTo: s
} = t, a = e.reduce((e, t) => null != t && t.dataSeg.endPts ? Math.min(b(t.dataSeg.endPts, t.offsetTimestamp), e) : e, Number.POSITIVE_INFINITY);
if (!i) throw new Error("appendSourceBufferData null currentSbEntity");
const o = (null == s ? void 0 : s.pos) || r;
let l = NaN;
i.forEach((e, t) => {
if (e) {
e = Yp.getBufferedInfo(e.bufferedRanges, o, 0);
if (0 === e.len) {
const i = e["nextStart"],
r = ne(this.config.jaggedSeekTolerance) ? this.config.jaggedSeekTolerance : 0;
n.warn(`sb[${Uu[t]}] jagged start: ${i} appendEndTime=${a} current=${l} tolerance=${r}`), ne(i) && (!ne(l) || i - l > r) && (l = i)
}
}
}), ne(l) && a > l && (n.warn(`[seek] jagged start, adjusting currentTime:${r.toFixed(3)} seekTo=${null===(e=null==s?void 0:s.pos)||void 0===e?void 0:e.toFixed(3)}->${l} appendEndTime=${a}`), this.seekTo = l)
}
addCues(e, t) {
const i = this.mediaElement.textTracks[e];
i && t.forEach(e => {
i.addCue(e)
})
}
_flushInternal(e, t, i) {
return Zr(() => e.remove(t, i)).pipe(Za(() => {}))
}
flushAll(i, r, n = !1) {
return 0 === this.sourceBuffers.length ? Wu : en(this.sourceBuffers.map((e, t) => e ? this.flushData(t, i, r, n) : Wu)).pipe(Zs(void 0))
}
flushData(o, l, d, u = !1) {
const {
mediaQuery: t,
logger: c
} = this;
return Gu(t.updating$, e => !1 === e).pipe(La(() => {
var e = t["sourceBufferEntities"],
e = e[o];
null != e && e.updating && this.logger.warn(`trying to flush while updating ${o}`);
const r = this.sourceBuffers[o];
if (!r) return Wu;
let n, s, a = Wu;
e = -1 === navigator.userAgent.toLowerCase().indexOf("firefox");
if (this.flushing = !0, e) return this._flushInternal(r, l, d);
for (let i = 0; i < r.buffered.length; i++) {
let e, t;
n = r.buffered.start(i), s = r.buffered.end(i), t = d === 1 / 0 ? (e = l, d) : (e = Math.max(n, l), Math.min(s, d)), Math.min(t, s) > e && (u || .5 < Math.min(t, s) - e) ? a = a.pipe($a(this._flushInternal(r, e, t))) : c.warn(`ignoring sb[${Uu[o]}] flush ${e},${t}`)
}
return a
}), Vs(() => {
this.flushing = !1
}))
}
static convertInitSegToCompatInfo(e) {
return {
mimeType: e.mimeType,
audioCodec: e.initParsedData.audioCodec,
videoCodec: e.initParsedData.videoCodec,
startPTSSec: void 0,
endPTSSec: void 0,
discoSeqNum: e.discoSeqNum,
mediaOptionId: e.mediaOptionId
}
}
static combineAppendDataInfoWithCompatInfo(e, t, i, r = 0) {
const n = [...t];
e.forEach((e, t) => null != e && e.initSeg ? n[t] = vf.convertInitSegToCompatInfo(e.initSeg) : null);
t = n[yu.Variant].videoCodec, e = Hp(t);
if (i && i.has(e)) {
const s = i.get(e);
n[yu.Variant].mimeType = n[yu.Variant].mimeType.replace(t, s), n[yu.Variant].videoCodec = s
}
return n
}
convertSourceBufferEntitiesToCompatInfo(e) {
const t = e.sourceBufferEntities,
i = [null, null];
return t.forEach((e, t) => {
e && (i[t] = {
mimeType: e.mimeType,
audioCodec: e.audioCodec,
videoCodec: e.videoCodec,
startPTSSec: void 0,
endPTSSec: void 0,
discoSeqNum: void 0,
mediaOptionId: null === (e = e.initSegmentInfo) || void 0 === e ? void 0 : e.mediaOptionId
})
}), i
}
appendData(e, i, r) {
const {
mediaQuery: t,
logger: n
} = this, o = this.convertSourceBufferEntitiesToCompatInfo(t);
return e.every(e => null == e) ? $i([]) : this.resetMediaSourceIfNeeded(e).pipe(La(e => e ? t.updating$.pipe(ln(e => !1 === e), Ds(1), Zs(e)) : $i(null)), La(t => {
if (!t) return $i([]);
let s = NaN,
a = NaN;
if (this.needSourceBuffers) {
s = performance.now();
const i = vf.combineAppendDataInfoWithCompatInfo(t, o, r, n);
this.createSourceBuffers(i), a = performance.now(), this.clearFlush(t)
}
return t.forEach(e => {
e = null == e ? void 0 : e.dataSeg;
null != e && e.cues && ne(null == e ? void 0 : e.texttrackIdx) && this.addCues(e.texttrackIdx, e.cues)
}), this.setStoreSbTimeoffsets(t), Jr(Zr(() => this.appendInitSegments(t, i)), Zr(() => this.appendDataSegments(t, i))).pipe(function(r, i) {
return 2 <= arguments.length ? function(e) {
return Bt(sa(r, i), Ws(1), (void 0 === (t = i) && (t = null), function(e) {
return e.lift(new is(t))
}))(e);
var t
} : function(e) {
return Bt(sa(function(e, t, i) {
return r(e, t)
}), Ws(1))(e)
}
}((e, t) => (e.push(t), e), new Array), hr(([i, r]) => {
const n = [null, null];
return [yu.Variant, yu.AltAudio].forEach(e => {
var t;
null != (null == i ? void 0 : i[e]) && (t = {
fragmentType: Vu(e),
bufferCreationStart: s,
bufferCreationEnd: a,
startInitAppend: i[e].startAppend,
endInitAppend: i[e].endAppend,
initBytesAppend: i[e].bytesAppend,
startDataAppend: r[e].startAppend,
endDataAppend: r[e].endAppend,
dataBytesAppend: r[e].bytesAppend
}, n[e] = t)
}), n
}), Za(e => {
this.adjustJaggedStart(t)
}))
}), Ds(1))
}
endStream() {
try {
this.mediaSourceAdapter.endOfStream()
} catch (e) {
this.logger.warn(`endOfStream failed: ${e.message}`)
}
}
setMediaKeys(e) {
return this.teardownWG$.wrap(this.mediaKeysMutex.lock(() => Fr(this.mediaElement.setMediaKeys(e))).pipe(Za(() => {}), va(e => e.pipe(jr((e, t) => {
if (t < 3) return bn(100 * t);
throw e
})))))
}
clearMediaKeys() {
return Zr(() => {
if (!this.mediaElement) return Wu;
const e = -1 < navigator.userAgent.toLowerCase().indexOf("chrome"),
t = this.mediaElement.src;
return e && (this.mediaElement.src = ""), this.setMediaKeys(null).pipe(Za(() => this.mediaElement.src = t))
})
}
set postFlushSeek(e) {
this.mediaElementStore.postFlushSeek = e
}
schedulePostFlushSeek(e) {
al(() => {
this.mediaQuery.seekTo && (this.seekTo = null), this.postFlushSeek = e
})
}
set seekTo(e) {
this.mediaElementStore.setSeekToPos(e, !1)
}
setSeekToWithDiscontinuity(e, t) {
this.mediaElementStore.setSeekToPos(e, !1, t)
}
nudgeSeek(e, t) {
al(() => {
this.mediaElementStore.setSeekToPos(e, !1), this.mediaElementStore.setNudgeInfo({
nudgeTarget: e,
nudgeCount: t
})
})
}
set desiredRate(e) {
this.mediaElementStore.desiredRate = e
}
toggleTrickPlaybackMode(e) {
if (this.config.overridePlaybackRate) {
const t = e ? 2 : 1;
try {
this.mediaElement.playbackRate = t
} catch (e) {
this.logger.error({
name: "iframes"
}, `Exception when setting playbackRate=${t}: ${e.message}`)
}
}
const t = this.muteValueOnTrickPlaybackToggle;
e && void 0 === t ? (this.muteValueOnTrickPlaybackToggle = this.mediaElement.muted, this.mediaElement.muted = e) : e || void 0 === t || (this.mediaElement.muted = t, this.muteValueOnTrickPlaybackToggle = void 0)
}
play() {
this.mediaFunctions.play()
}
pause() {
this.mediaFunctions.pause()
}
get expectPlayEvent() {
return this.mediaFunctions.expectPlayEvent
}
set expectPlayEvent(e) {
this.mediaFunctions.expectPlayEvent = e
}
get expectPauseEvent() {
return this.mediaFunctions.expectPauseEvent
}
set expectPauseEvent(e) {
this.mediaFunctions.expectPauseEvent = e
}
set textTracksCreated(e) {
const t = this["mediaElementStore"];
t.textTracksCreated = e
}
get msDuration() {
return this._mediaQuery.msDuration
}
set msDuration(e) {
try {
const t = this["mediaElementStore"],
i = this.mediaSource$.value;
i.duration !== e && (i.duration = e, t.msDuration = e)
} catch (e) {
this.logger.warn(`Error setting duration ${e.message}`)
}
}
set haveEnough(e) {
this.mediaElementStore.haveEnough = e
}
set flushing(e) {
this.mediaElementStore.flushing = e
}
set bufferMonitorTargetDuration(e) {
this.mediaElementStore.bufferMonitorTargetDuration = e
}
get textTracks() {
return this.mediaElement.textTracks
}
get id3TextTrack() {
return this.id3Track
}
addTextTrack(e, t, i) {
return this.mediaElement.addTextTrack(e, t, i)
}
dispatchEvent(e) {
return this.mediaElement.dispatchEvent(e)
}
get offsetWidth() {
return this.mediaElement.offsetWidth
}
get offsetHeight() {
return this.mediaElement.offsetHeight
}
getliveSeekableWindow() {
return this.liveSeekableWindow
}
archiveParsedSubtitleFragmentRecord(e, t, i) {
return this.mediaElementStore.archiveParsedSubtitleFragmentRecord(e, t, i)
}
updateLiveSeekableRange(e) {
var t = e.fragments,
e = t.length;
if (1 < e) {
const i = Math.max(t[0].start, 0),
r = t[e - 1].start + t[e - 1].duration;
this.mediaSource$.value.updateLiveSeekableRange(i, r), this.liveSeekableWindow.start = i, this.liveSeekableWindow.end = r
}
}
clearLiveSeekableRange() {
this.mediaSource$.value.clearLiveSeekableRange(), this.liveSeekableWindow.start = NaN, this.liveSeekableWindow.end = NaN
}
}
const Sf = (t, r, n, s, a, o, l, i) => {
if (!t) return Ii;
const e = Oc(t);
return an(e.event("durationchange").pipe(hr(e => kc(t, "durationchange", e)), Za(e => {
e = e.currentTarget;
r.mediaElementDuration = e.duration
})), e.event("seeking").pipe(ao(o.seekEventThrottleMs), hr(e => kc(t, "seeking", e)), Za(e => {
var t = e.currentTarget,
e = t.currentTime;
if (t.readyState >= t.HAVE_METADATA) {
const i = n.seekTo;
!i || !i.fromEvent && 1e-5 < Math.abs(i.pos - e) ? a.inGaplessMode ? function(e, t, i, r, n) {
let s = !1;
e < t.playingItem.itemStartOffset && (n.warn(`[Gapless] Seeking past track boundary oldSeek=${e}, adjustedSeek=${t.playingItem.itemStartOffset}`), e = t.playingItem.itemStartOffset, s = !0), t.isPreloading && (e > t.loadingItem.itemStartOffset && (n.warn(`[Gapless] Seeking past track boundary oldSeek=${e}, adjustedSeek=${t.loadingItem.itemStartOffset}`), e = t.loadingItem.itemStartOffset, s = !0), t.dequeueSource("SeekToUnbufferedTimeRanges")), s ? i.resetMediaSource(e) : r.setSeekToPos(e, !0)
}(e, a, s, r, l) : s && s.hasOwnProperty("liveSeekableWindow") && ne(s.getliveSeekableWindow().start) && ne(s.getliveSeekableWindow().end) && (e < s.getliveSeekableWindow().start || e > s.getliveSeekableWindow().end) ? function(e, t, i, r, n, s) {
let a = e;
if (e < t) a = t;
else if (i < e) {
let e = r.defaultTargetDuration;
ne(r.liveSyncDuration) ? e = r.liveSyncDuration : ne(r.liveSyncDurationCount) && (e = r.liveSyncDurationCount * r.defaultTargetDuration), a = Math.max(0, i - e)
}
s.warn(`[live] liveAdjustedSeek seekTo:${se(e,3)}, adjustedSeek:${se(a,3)}, liveWindowStart:${se(t,3)}, liveWindowEnd:${se(i,3)}`), n.setSeekToPos(a, !0)
}(e, s.getliveSeekableWindow().start, s.getliveSeekableWindow().end, o, r, l) : r.setSeekToPos(e, !0) : r.seeking = !0
}
})), e.event("seeked").pipe(hr(e => kc(t, "seeked", e)), Za(() => {
r.setSeekToPos(null, !0)
})), e.event("play").pipe(hr(e => kc(t, "play", e)), bo(n.desiredRate$), hr(([e]) => {
var t = e.currentTarget;
r.paused = t.paused;
var i = s.expectPlayEvent,
t = t.controls || o.nativeControlsEnabled;
return !i && t && (s.checkForReplay(), r.desiredRate = 1), s.expectPlayEvent = !1, e
})), e.event("playing").pipe(hr(e => kc(t, "playing", e)), Za(e => {
e = e.currentTarget;
r.paused = e.paused, r.gotPlayingEvent()
})), e.event("loadstart").pipe(hr(e => kc(t, "loadstart", e)), Za(() => {
r.gotLoadStartEvent()
})), e.event("pause").pipe(hr(e => kc(t, "pause", e)), Za(e => {
var t = e.currentTarget;
r.paused = t.paused;
e = s.expectPauseEvent, t = t.controls || o.nativeControlsEnabled;
!e && t && (r.desiredRate = 0), s.expectPauseEvent = !1
})), e.event("loadedmetadata").pipe(hr(e => kc(t, "loadedmetadata", e))), e.event("loadeddata").pipe(hr(e => kc(t, "loadeddata", e))), e.event("canplay").pipe(hr(e => kc(t, "canplay", e))), e.event("canplaythrough").pipe(hr(e => kc(t, "canplaythrough", e))), e.event("waiting").pipe(hr(e => kc(t, "waiting", e))), e.event("emptied").pipe(hr(e => kc(t, "emptied", e))), e.event("error").pipe(hr(e => kc(t, "error", e)), Wn(e => Vi(t.error))), e.event("ended").pipe(hr(e => kc(t, "ended", e)))).pipe(bo(n.bufferedRangeTuple$), ll(([e]) => {
var t = e.currentTarget,
e = t.readyState;
r.readyState = e, r.ended = t.ended
}), Vn(e => (e instanceof MediaError ? (l.warn(`mediaElementError, code: ${e.code}, message: ${e.message}`), null == i || i.handleMediaElementError(e)) : l.error(`media event error: ${e.message}`), Ii)), $a(on), Vn(e => e instanceof MediaError ? (l.warn(`mediaElementError, code: ${e.code}, message: ${e.message}`), Vi(e)) : (l.error(`media event error: ${e.message}`), Ii)))
},
bf = new class extends fl {
constructor() {
super({}, {
name: "media-element-store",
producerFn: su
}), this._activeId = ""
}
get activeId() {
return this._activeId
}
startMediaSession(i, r, n, s) {
return Do("playback.session.start"), this._activeId = `media session: ${(new Date).toISOString()}`, al(() => {
var e = s,
t = Math.max(e, r - e),
t = {
id: this.activeId,
desiredRate: !i.autoplay && i.paused ? 0 : 1,
paused: i.paused,
gotPlaying: !1,
gotLoadStart: !1,
firstPlayTime: void 0,
seeking: i.seeking,
flushing: !1,
readyState: i.readyState,
ended: i.ended,
bufferedRanges: [],
haveEnough: !1,
mediaSourceEntity: null,
expectedSbCount: NaN,
bufferMonitorInfo: {
waterLevelType: null,
almostDryWaterLevelSeconds: n,
lowWaterLevelSeconds: e,
highWaterLevelSeconds: t,
maxBufferSeconds: r
},
mediaOptionParsedSubtitleRecord: [],
textTracksCreated: !1,
waitingForDisco: !1
};
this.add(t), this.setActive(this.activeId)
}), this.logger = Qe().child({
name: "UpdateBufferedSegments"
}), this.activeId
}
setMediaSourceEntity(t, i) {
Do("playback.set.msObjectUrl"), this.updateActive(e => {
e.mediaSourceEntity = null != t && null != i ? {
objectUrl: t,
readyState: i,
duration: NaN,
sourceBufferEntities: [null, null]
} : null, e.bufferedRanges = [], e.haveEnough = !1, e.readyState = 0, e.bufferMonitorInfo.waterLevelType = null
})
}
set mediaElementDuration(t) {
Do("playback.set.mediaElementDuration"), this.updateActive(e => {
e && (e.mediaElementDuration = t)
})
}
set msReadyState(t) {
Do("playback.set.msReadyState"), this.updateActive(({
mediaSourceEntity: e
}) => {
e && (e.readyState = t)
})
}
set readyState(t) {
Do(`playback.set.readyState ${t}`), this.updateActive(e => {
e.readyState = t
})
}
set ended(t) {
Do(`playback.set.ended ${t}`), this.updateActive(e => {
e.ended = t
})
}
set msDuration(t) {
Do("playback.set.msDuration"), this.updateActive(e => {
e.mediaSourceEntity.duration = t
})
}
set textTracksCreated(t) {
Do("playback.set.textTracksCreated ${created}"), this.updateActive(e => {
e.textTracksCreated = t
})
}
set expectedSbCount(t) {
Do("playback.set.expectedSbCount"), this.updateActive(e => {
e.expectedSbCount = t
})
}
set postFlushSeek(e) {
this.updateActive({
postFlushSeek: e
})
}
setSeekToPos(t, i, r) {
Do(`playback.set.seekToPos: ${null==t?void 0:t.toFixed(3)} cc: ${r}`), this.updateActive(e => {
ne(t) ? (e.seekTo = {
pos: t,
fromEvent: i,
discoSeqNum: r
}, e.gotPlaying = !1, e.haveEnough = !1) : (e.seekTo = null, e.postFlushSeek = void 0), i && (e.seeking = ne(t))
})
}
set seeking(t) {
Do(`playback.set.seeking: ${t}`), this.updateActive(e => {
e.seeking = t
})
}
set paused(t) {
Do(`playback.set.paused: ${t}`), this.updateActive(e => {
(e.paused = t) && (e.gotPlaying = !1)
})
}
gotPlayingEvent() {
Do("playback.set.playing"), this.updateActive(e => {
e.paused || (e.gotPlaying = !0, e.firstPlayTime = e.firstPlayTime || performance.now())
})
}
gotLoadStartEvent() {
Do("playback.set.loadstart"), this.updateActive(e => {
e.gotLoadStart = !0
})
}
set desiredRate(t) {
Do(`playback.set.desiredRate: ${t}`), this.updateActive(e => {
e.desiredRate = t
})
}
set haveEnough(t) {
Do(`playback.set.haveEnough: ${t}`), this.updateActive(e => {
e.haveEnough = t
})
}
set flushing(e) {
Do(`playback.set.flushing: ${e}`), this.updateActive({
flushing: e
})
}
set waitingForDisco(t) {
Do(`playback.set.waitingForDisco: ${t}`), this.updateActive(e => {
e && (e.waitingForDisco = t)
})
}
setSourceBufferUpdating(i) {
Do(`playback.set.sourcebuffers[${Uu[i]}].updating`), this.updateActive(({
mediaSourceEntity: e
}) => {
const t = null === (e = null == e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[i];
t && (t.updating = !0, t.error = void 0)
})
}
setTimestampOffset(i, r) {
Do(`playback.set.sourcebuffers[${Uu[i]}].timestampOffset`), this.updateActive(({
mediaSourceEntity: e
}) => {
const t = null === (e = null == e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[i];
t && (t.timestampOffset = r)
})
}
setBufferedRangesUpdated(a, o, l, d, u) {
Do(`playback.set.sourcebuffers[${Uu[a]}].bufferupdated`), this.updateActive(e => {
var t, i, r;
const n = null == e ? void 0 : e.mediaSourceEntity,
s = null === (r = null == n ? void 0 : n.sourceBufferEntities) || void 0 === r ? void 0 : r[a];
if (s) {
const a = null == n ? void 0 : n.duration;
s.updating = !1, s.bufferedRanges = [...o], t = s, i = t.inFlight, r = t.bufferedSegments, i && ne(i.startPTS) && ne(i.endPTS) && function(t, i) {
let r = !1;
for (let e = t.length - 1; - 1 < e; e--) {
const s = t[e],
a = Math.max(i.startPTS, s.startPTS),
o = Math.min(i.endPTS, s.endPTS);
var n;
o <= a || ((n = (1 - (o - a) / (s.endPTS - s.startPTS)) * s.bytes) <= 0 ? t.splice(e, 1) : (s.bytes = n, s.startPTS < i.startPTS ? s.endPTS = a : (s.startPTS = o, r || (t.splice(e, 0, i), r = !0))))
}
r || t.push(i)
}(r, i), t.inFlight = null,
function(e, t, i, r, n) {
const {
maxBufferHole: s,
bufferedSegmentEjectionToleranceMs: a
} = r, o = e.bufferedSegments, l = e.bufferedRanges;
let d, u = 0,
c = !1;
if (l.length)
for (let e = o.length - 1; - 1 < e; e--) {
const t = o[e],
r = !t.frag.iframe;
r && t.frag.isLastFragment && (d = t.frag);
var h = t.endPTS - t.startPTS;
if (h <= 0) o.splice(e, 1), null == n || n.warn(`Ejecting segment from bufferedSegments due to segmentDuration <= 0 > segment=${ae(t)}`), c = t.frag === d;
else {
var p = Bp(l, t);
if (p) {
var f = Math.max(p.start, t.startPTS),
p = Math.min(p.end, t.endPTS),
f = p - f;
if (u += t.bytes * f / h, r)
if (f < Math.min(h, s)) o.splice(e, 1), null == n || n.warn(`Ejecting segment from bufferedSegments due to tiny overlaps > segment=${ae(t)}, bufferedRanges=${ae(l)}`), c = t.frag === d;
else {
const r = t.appendedDuration,
u = (r || 0) - f,
m = Math.min(.001 * a, h);
r ? !(u > m && f != h) || t.frag.isLastFragment && p === i || (o.splice(e, 1), null == n || n.warn(`Ejecting segment from bufferedSegments due to change in current overlap > segment=${ae(t)}, delta=${u}, bufferedRanges=${ae(l)}`), c = t.frag === d) : t.appendedDuration = f
}
} else null == n || n.warn(`Ejecting segment from bufferedSegments due to no overlap > segment=${ae(t)}, bufferedRanges=${ae(l)}`), o.splice(e, 1), c = t.frag === d
}
} else o.length && o.splice(0, o.length);
e.totalDuration = d && !c && 0 < l.length ? l[l.length - 1].end : 1 / 0, e.gotQuotaExceeded = e.gotQuotaExceeded || t, e.totalBytes = u, e.maxTotalBytes = Math.max(e.totalBytes, e.maxTotalBytes)
}(s, d, a, u, this.logger)
}
e.bufferedRanges = [...l]
})
}
setSourceBufferEntity(n, s) {
Do(`playback.set.sourcebuffers[${Uu[n]}].setSourceBufferEntity`), this.updateActive(({
mediaSourceEntity: e
}) => {
var t, i, r;
e && ({
mimeType: t,
audioCodec: i,
videoCodec: r
} = s, e.sourceBufferEntities[n] = {
mimeType: t,
audioCodec: i,
videoCodec: r,
updating: !1,
bufferedRanges: [],
timestampOffset: 0,
inFlight: null,
bufferedSegments: [],
totalBytes: 0,
maxTotalBytes: 0,
gotQuotaExceeded: !1,
totalDuration: 1 / 0
})
})
}
setInflightSegment(i, r) {
Do(`playback.set.sourcebuffers[${Uu[i]}].setInflightSegment`), this.updateActive(({
mediaSourceEntity: e
}) => {
const t = null === (e = null == e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[i];
t && (t.inFlight = r)
})
}
setInitSegmentEntity(i, r) {
Do(`playback.set.sourcebuffers[${Uu[i]}].setInitSegmentEntity`), this.updateActive(({
mediaSourceEntity: e
}) => {
const t = null === (e = null == e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[i];
t && (t.initSegmentInfo = r)
})
}
setSourceBufferError(i, r) {
Do(`playback.set.sourcebuffers[${i}].error: ${r}`), this.updateActive(({
mediaSourceEntity: e
}) => {
const t = null === (e = null == e ? void 0 : e.sourceBufferEntities) || void 0 === e ? void 0 : e[i];
t && (t.inFlight = null, t.updating = !1, t.error = r)
})
}
setStallInfo(t) {
Do(`playback.set.stallInfo stalled=${null!=t}`), this.updateActive(e => {
e.stallInfo = t
})
}
setNudgeInfo(t) {
Do(`playback.set.nudgeInfo ${ae(t)}`), this.updateActive(e => {
e.nudgeInfo = t
})
}
updateWaterLevels(t, i) {
Do("playback.set.updateWaterLevels"), this.updateActive(e => {
e.bufferMonitorInfo.waterLevelType = {
combined: t,
sbTuple: [...i]
}
})
}
set bufferMonitorTargetDuration(i) {
Do(`playback.set.targetDuration: ${i}`), this.updateActive(e => {
if (ne(i) && 0 < i) {
const t = e.bufferMonitorInfo;
t.lowWaterLevelSeconds = Math.min(i, t.maxBufferSeconds), t.highWaterLevelSeconds = Math.max(t.lowWaterLevelSeconds, t.maxBufferSeconds - i)
}
})
}
archiveParsedSubtitleFragmentRecord(i, r, n) {
Do(`playback.cues.set persistentId ${i} mediaSeqNum ${r}: parsed ${n.count} time-range ${n.startTime}:${n.endTime}`), this.updateActive(e => {
let t = e.mediaOptionParsedSubtitleRecord[i];
t || (t = {}, e.mediaOptionParsedSubtitleRecord[i] = t), t[r] = n
})
}
};
class Tf extends bi {
constructor(e) {
super(e), this.store = e, this.displaySupportsHdr$ = this.select("supportsHdr"), this.platformInfo$ = this.select("platformInfo"), this.viewportInfo$ = this.select("viewportInfo")
}
get platformInfo() {
return this.getValue().platformInfo
}
get displaySupportsHdr() {
return this.getValue().supportsHdr
}
get viewportInfo() {
return this.getValue().viewportInfo
}
}
class Ef {
constructor(e) {
this.store = e
}
getQuery() {
return new Tf(this.store)
}
updateSupportsHdr(t) {
this.store.update(e => {
e.supportsHdr = t
})
}
updatePlatformInfo(e) {
this.store.update({
platformInfo: e
})
}
updateViewportInfo(t) {
this.store.update(e => {
e.viewportInfo = t
})
}
}
const If = new class extends dl {
constructor() {
super({
supportsHdr: !0
}, {
name: "platform",
producerFn: su
})
}
};
let wf = null;
function Af() {
return wf = wf || new Ef(If), wf
}
class Of extends $t {
constructor(e, t) {
super(e => {
null == t || t.add(), e.add(this._handler$.pipe(jr(([e, t, i]) => e(...t).pipe(Za({
next(e) {
i(e, null)
},
error(e) {
i(null, e)
}
})))).subscribe())
}), this._vanillaRPC = e, this.teardownWG$ = t, this._handler$ = new Xt
}
register(e, i) {
return this._vanillaRPC.register(e, (...t) => e => {
this._handler$.next([i, t, e])
})
}
invoke(e, t, r) {
return new $t(i => {
this._vanillaRPC.invoke(e, t, r)((e, t) => {
null != t ? i.error(t) : (i.next(e), i.complete())
})
})
}
}
class kf extends Of {
constructor(e) {
super(e)
}
decrypt(e, t, i, r, n) {
return this.invoke("decrypt", [e, t, i, r, n], [e, t, r])
}
}
class Cf extends Of {
constructor(e) {
super(e), this.rpcService = e, this.sessions = {}, this._onEvent = (e, t, i) => () => {
null != this.sessions[e] && this.sessions[e].observer.trigger(t, i)
}, this.rpcService.register("demuxer.event", this._onEvent)
}
init(e, t, i) {
return [{
maxSeekHole: r,
maxBufferHole: n,
audioPrimingDelay: s,
stretchShortVideoTrack: a,
forceKeyFrameOnDiscontinuity: o
}] = [t], this.invoke("demuxer.init", [e, t = {
maxSeekHole: r,
maxBufferHole: n,
audioPrimingDelay: s,
stretchShortVideoTrack: a,
forceKeyFrameOnDiscontinuity: o
}, i], []).pipe(hr(e => {
var t = new Df(this, e);
return this.sessions[e] = t
}));
var r, n, s, a, o
}
}
class Df {
constructor(e, t) {
this.rpc = e, this.demuxSessionID = t, this.observer = new a
}
push(e, t, i, r, n, s, a, o, l, d, u, c, h) {
return this.rpc.invoke("demuxer.push", [this.demuxSessionID, e, t, i, r, n, s, a, o, l, d, u, c], null != h ? h : [e])
}
pushWithoutTransfer(e, t, i, r, n, s, a, o, l, d, u, c) {
return this.push(e, t, i, r, n, s, a, o, l, d, u, c, [])
}
destroy() {
this.observer.removeAllListeners(), this.rpc.invoke("demuxer.destroy", [this.demuxSessionID], []).subscribe()
}
}
class Mf {
constructor() {
this.handlers = {}
}
register(e, t) {
if (null != this.handlers[e]) return !1;
this.handlers[e] = t
}
unregister(e) {
if (null != this.handlers[e]) return !1;
delete this.handlers[e]
}
invoke(e, i) {
return (t = Mf._fallbackCallback) => {
try {
if (null == this.handlers[e]) throw new Error(`command ${e} not found`);
this.handlers[e](...i)(t)
} catch (e) {
t(void 0, e)
}
}
}
teardown(e) {
this.handlers = null, e()
}
}
Mf._fallbackCallback = (e, t) => {
if (null != t) throw t
};
const xf = e => {
e = e.child({
name: "InlineRPCService"
});
var t = new Mf;
return new i(t, e), new ot(t, e), t
};
let Pf;
const Rf = e => {
try {
if (null == Pf) {
const e = new Blob(["var exports = {};var module = { exports: exports };function define(f){f()};define.amd = true;(" + Xy.toString() + ")(true);"], {
type: "text/javascript"
}),
r = URL.createObjectURL(e);
Pf = new Worker(r)
}
var t = new lt(Pf);
return i = t, n = e.child({
name: "WorkerRPCService"
}), i.register("logger.log", (e, i, ...r) => t => {
try {
for (const i of e) n = n.child(i);
"function" == typeof n[i] && n[i](...r), t()
} catch (e) {
t(void 0, e)
}
}), t
} catch (e) {
throw new Error("Failed to create WebWorker")
}
var i, n
},
Lf = (...r) => i => {
for (let t = 0; t < r.length; t++) {
const e = r[t];
try {
return e(i)
} catch (e) {
if (t === r.length - 1) throw e;
i.warn(e)
}
}
},
_f = e => Lf(Rf, xf)(e);
class Nf {}
Nf.PlayEnded = 6101, Nf.Periodic = 6110, Nf.PlayStalled = 6103, Nf.KeySessionComplete = 6104, Nf.PlayLikelyToKeepUp = 6105, Nf.PlayRateChanged = 6106, Nf.PlayError = 6107, Nf.MediaEngineStalled = 6108, Nf.SwitchComplete = 6109, Nf.VariantEnded = 6111, Nf.NwError = 6202;
const Ff = {
avc1: 1,
avc3: 1,
hvc1: {
SDR: 2,
HLG: 10,
PQ: 11
},
hev1: {
SDR: 2,
HLG: 10,
PQ: 11
},
vp09: {
SDR: 3,
HLG: 14,
PQ: 13
},
dvh1: {
PQ: 12
}
};
class Bf {
constructor(e, t) {
this.query = e, this.logger = t
}
setReportingAgent(e) {
this.reportingAgent = e
}
sendPlayEnded(e) {
var t = Nf.PlayEnded;
this.fillAndFire(t, this.query.playEnded(e))
}
sendPlayStalled(e) {
var t = Nf.PlayStalled;
this.fillAndFire(t, this.query.playStalled(e))
}
sendMediaEngineStalled(e) {
var t = Nf.MediaEngineStalled;
this.fillAndFire(t, this.query.mediaEngineStalled(e))
}
sendKeySessionComplete(e) {
var t = Nf.KeySessionComplete;
this.fillAndFire(t, this.query.keySessionComplete(e))
}
sendPlayLikelyToKeepUp(e) {
var t = Nf.PlayLikelyToKeepUp;
this.fillAndFire(t, this.query.playLikelyToKeepUp(e))
}
sendPlayRateChange(e) {
var t = Nf.PlayRateChanged;
this.fillAndFire(t, this.query.playRateChanged(e))
}
sendSwitchComplete(e) {
var t = Nf.SwitchComplete;
this.fillAndFire(t, this.query.switchComplete(e))
}
sendVariantEnded(e) {
var t = Nf.VariantEnded;
this.fillAndFire(t, this.query.variantEnded(e))
}
sendPlayError(e) {
var t = Nf.PlayError;
this.fillAndFire(t, this.query.playError(e))
}
sendNwError(e) {
var t = Nf.NwError;
this.fillAndFire(t, this.query.nwError(e))
}
sendPeriodic(e) {
var t = Nf.Periodic;
this.fillAndFire(t, this.query.periodic(e))
}
fillAndFire(e, t) {
if (e !== Nf.Periodic || t.PlayTimeWC || t.ADT) {
var r = e === Nf.PlayEnded || e === Nf.Periodic ? 1 : 0;
if (this.reportingAgent) {
let i = {};
Object.entries(t).forEach(([e, t]) => {
"object" == typeof(t = ne(t) ? Number(Number(t).toFixed(2)) : t) ? "ServerInfo" === e && Object.entries(t).forEach(([e, t]) => {
i[e] = t
}): i[e] = t
}), i = JSON.parse(JSON.stringify(i));
try {
this.reportingAgent.issueReportingEvent(e, i, r)
} catch (e) {}
}
}
}
}
class Uf extends kl {
constructor(e, t) {
super(e), this.logger = t
}
get activeEntity() {
return this.getActive()
}
entity(e) {
return this.getEntity(e)
}
playEnded(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.playEndedRecord
}
periodic(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.periodicRecord
}
playStalled(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.playStalledRecord
}
mediaEngineStalled(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.mediaEngineStalledRecord
}
keySessionComplete(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.keySessionCompleteRecord
}
playLikelyToKeepUp(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.playLikelyToKeepUpRecord
}
playRateChanged(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.playRateChangedRecord
}
switchComplete(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.switchCompleteRecord
}
variantEnded(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.variantEndedRecord
}
playError(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.playErrorRecord
}
nwError(e) {
return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.nwErrorRecord
}
}
class $f extends fl {
constructor(e) {
super({}, {
name: "rtc-store",
idKey: "itemId",
producerFn: su,
resettable: !0
}), this.logger = e
}
createEntity(e) {
e = {
itemId: e,
sessionControlRecord: {
state: "RTC_STATE_INIT",
rate: 0,
oldRate: 0,
eventStartTime: Date.now(),
sessionStartTime: Date.now(),
lastLikelyToKeepUpTime: Date.now(),
lastPeriodicTime: Date.now(),
playLikelyToKeepUpEventCounter: 1,
periodicEventCounter: 1,
activeKeySessions: {},
intervalVariantList: {},
sessionVariantList: {}
},
playEndedRecord: {},
periodicRecord: {},
playStalledRecord: {},
keySessionCompleteRecord: {},
playLikelyToKeepUpRecord: {},
playRateChangedRecord: {},
playErrorRecord: {},
mediaEngineStalledRecord: {},
switchCompleteRecord: {},
variantEndedRecord: {},
nwErrorRecord: {}
};
this.add(e)
}
updateEnded(e) {
this._prepareEventPlayEnded(e)
}
updatePeriodic(e, t) {
this._prepareEventPeriodic(e, {
isFinal: t
})
}
updateBufferStalled(e, t) {
this.update(e, ({
sessionControlRecord: e,
variantEndedRecord: t,
periodicRecord: i,
playEndedRecord: r
}) => {
e.rate = 0, t.StallCount = (t.StallCount || 0) + 1, i.StallCount = (i.StallCount || 0) + 1, r.StallCount = (r.StallCount || 0) + 1
}), this._prepareEventPlayStalled(e, t)
}
updateSegmentKeyLoaded(e, r) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = {},
i = r.timestamp;
t.keyFormat = "identity", t.keyDeliveryTime = r.adt, t.currentMediaTime = r.currentTime, "RTC_STATE_INIT" === e.state && (t.keyInitTime = i - e.sessionStartTime), e.activeKeySessions[r.keyuri] = t
}), this._prepareEventKeySessionComplete(e, r)
}
updateLicenseResponseProcessed(e, i) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = e.activeKeySessions[i.keyuri];
t.licenseResponseProcessTime = i.timestamp - t.licenseResponseSubmitTime, e.lastKeyDeliveryTime = t.keyDeliveryTime = i.timestamp - t.licenseChallengeStartTime, t.currentMediaTime = i.currentTime, e.finishedKeyUri = i.keyuri
}), this._prepareEventKeySessionComplete(e, i)
}
updateLicenseChallengeError(e, i) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = e.activeKeySessions[i.keyuri];
e.lastKeyErrorType = t.keyErrorType = "licenseChallengeError", e.finishedKeyUri = i.keyuri
}), this._prepareEventKeySessionComplete(e, i)
}
updateLicenseResponseError(e, i) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = e.activeKeySessions[i.keyuri];
e.lastKeyErrorType = t.keyErrorType = "licenseResponseError", e.finishedKeyUri = i.keyuri
}), this._prepareEventKeySessionComplete(e, i)
}
updateKeyAborted(e, t) {
this.update(e, ({
sessionControlRecord: e
}) => {
e.activeKeySessions[t.keyuri].keyErrorType = "keyAborted", e.finishedKeyUri = t.keyuri
}), this._prepareEventKeySessionComplete(e, t)
}
updateCanPlay(e, t) {
this.update(e, ({}) => {}), this._prepareEventPlayLikelyToKeepUp(e, t)
}
updateRateChanged(e, t) {
this.update(e, ({
sessionControlRecord: e
}) => {
e.rate = 100 * t.rate, 0 < t.rate && 0 === e.oldRate && (e.playInfo || (e.playInfo = []), e.playInfo.push({
latency: t.latency
}), e.curLevelUrl || (e.curLevelUrl = t.url))
}), this._prepareEventPlayRateChanged(e, t)
}
updateMediaError(e, r) {
this.update(e, ({
sessionControlRecord: e,
periodicRecord: t,
playEndedRecord: i
}) => {
t.PlayerErrCount = (t.PlayerErrCount || 0) + 1, i.PlayerErrCount = (i.PlayerErrCount || 0) + 1, r.fatal && (e.rate = 0, t.FatalPlayerErrCount = (t.FatalPlayerErrCount || 0) + 1, i.FatalPlayerErrCount = (i.FatalPlayerErrCount || 0) + 1, i.ErrCode = r.details, i.ErrReason = r.code, i.ErrIsFatal = !0, i.ErrDomain = "mediaError")
}), r.fatal ? this._prepareEventPlayError(e, r) : this.update(e, ({
sessionControlRecord: e
}) => {
var t = r.details + "/" + r.code;
e.nonFatalPlayErrList[t] = (e.nonFatalPlayErrList[t] || 0) + 1
})
}
updateMediaElementError(e, t) {
let i;
try {
i = JSON.parse(t.message)
} catch (e) {
this.logger.warn(`message is not JSON, ignoring; ${t.message}`)
}
var r = i ? parseInt(i.ErrReason) : null,
n = i ? parseInt(i.ErrDetail) : null;
this._prepareEventPlayError(e, {
domain: "mediaElementError",
mediaElemCode: t.code,
mediaElemReason: r,
mediaElemDetail: n,
code: null,
details: null,
fatal: null
})
}
updateMediaEngineStalled(e, t) {
this.update(e, ({
sessionControlRecord: e,
variantEndedRecord: t,
periodicRecord: i,
playEndedRecord: r
}) => {
e.rate = 0, t.MediaEngineStallCount = (t.MediaEngineStallCount || 0) + 1, i.MediaEngineStallCount = (i.MediaEngineStallCount || 0) + 1, r.MediaEngineStallCount = (r.MediaEngineStallCount || 0) + 1
}), this._prepareEventMediaEngineStalled(e, t)
}
updateLevelSwitched(e, d) {
this.update(e, ({
sessionControlRecord: e,
switchCompleteRecord: t,
periodicRecord: i,
playEndedRecord: r
}) => {
i.SwCnt = (i.SwCnt || 0) + 1, r.SwCnt = (r.SwCnt || 0) + 1;
var n = Date.now(),
s = e.curLevelUrl,
a = d.url,
i = this._getVariantInfo(s, e),
r = this._getVariantInfo(a, e);
let o, l = !1;
s && (o = r.bandwidth < i.bandwidth ? "Down" : "Up", l = r.iframes), t.BadSw = this._isBadSw(o, e.lastSwitchDir || o, l, e.lastLevelIsIframe || l, n, e.lastSwitchTime || n, d.isSeeking), e.lastSwitchDir = o, e.lastSwitchTime = n, e.lastLevelIsIframe = l, e.curLevelUrl = a, e.variantStartTimeMedia = d.currentTime
}), this._prepareEventSwitchComplete(e, d)
}
updateLevelLoadError(e, o) {
this.update(e, ({
sessionControlRecord: e,
switchCompleteRecord: t,
periodicRecord: i,
playEndedRecord: r
}) => {
var n = Date.now();
let s, a = !1;
if (e.curLevelUrl) {
const t = this._getVariantInfo(e.curLevelUrl, e),
i = this._getVariantInfo(o.url, e);
s = i.bandwidth < t.bandwidth ? "Down" : "Up", a = i.iframes
}
i.SwCnt = (i.SwCnt || 0) + 1, r.SwCnt = (r.SwCnt || 0) + 1, t.BadSw = this._isBadSw(s, e.lastSwitchDir || s, a, e.lastLevelIsIframe || a, n, e.lastSwitchTime || n, o.isSeeking), t.SwFail = !0
}), this._prepareEventSwitchComplete(e, o)
}
updateVariantEnd(e, t) {
this._prepareEventVariantEnded(e, t)
}
updateNwError(e, r) {
this.update(e, ({
sessionControlRecord: e,
periodicRecord: t,
playEndedRecord: i
}) => {
t.NwErrCount = (t.NwErrCount || 0) + 1, i.NwErrCount = (i.NwErrCount || 0) + 1, r.fatal && (e.rate = 0, t.FatalNwErrCount = (t.FatalNwErrCount || 0) + 1, i.FatalNwErrCount = (i.FatalNwErrCount || 0) + 1, i.ErrCode = r.details, i.ErrReason = r.code, i.ErrIsFatal = !0, i.ErrDomain = "networkError")
}), r.fatal ? this._prepareEventNwError(e, r) : this.update(e, ({
sessionControlRecord: e
}) => {
var t = r.details + "/" + r.code;
e.nonFatalNwErrList[t] = (e.nonFatalNwErrList[t] || 0) + 1
})
}
finalize(e, t) {
switch (t) {
case Nf.PlayEnded:
this.update(e, ({
sessionControlRecord: e
}) => {
e.state = "RTC_STATE_STOP", e.oldRate = 0
}), this.update(e, e => {
e.playEndedRecord = {}
});
break;
case Nf.Periodic:
this.update(e, ({
sessionControlRecord: t
}) => {
t.lastPeriodicTime = Date.now(), t.periodicEventCounter += 1, Object.keys(t.intervalVariantList).forEach(e => {
t.intervalVariantList[e].playTime = 0
})
}), this.update(e, e => {
e.periodicRecord = {}
});
break;
case Nf.PlayStalled:
this.update(e, ({
sessionControlRecord: e
}) => {
e.state = "RTC_STATE_STALL", e.oldRate = 0
}), this.update(e, e => {
e.playStalledRecord = {}
});
break;
case Nf.KeySessionComplete:
this.update(e, ({
sessionControlRecord: e
}) => {
delete e.activeKeySessions[e.finishedKeyUri]
}), this.update(e, e => {
e.keySessionCompleteRecord = {}
});
break;
case Nf.PlayLikelyToKeepUp:
this.update(e, ({
sessionControlRecord: e
}) => {
"RTC_STATE_PLAY" !== e.state && (e.state = "RTC_STATE_CANPLAY", e.lastLikelyToKeepUpTime = Date.now(), e.playLikelyToKeepUpEventCounter += 1)
}), this.update(e, e => {
e.playLikelyToKeepUpRecord = {}
});
break;
case Nf.PlayRateChanged:
this.update(e, ({
sessionControlRecord: e,
playEndedRecord: t,
playStalledRecord: i,
mediaEngineStalledRecord: r,
playErrorRecord: n,
nwErrorRecord: s
}) => {
0 !== e.rate ? (e.state = "RTC_STATE_PLAY", delete t.LastStall, delete t.LastMediaEngineStall, delete t.LastPause, delete n.LastPause, delete s.LastPause) : (e.state = "RTC_STATE_PAUSE", delete i.LastResume, delete r.LastResume, delete n.LastResume, delete s.LastResume), e.oldRate = e.rate
}), this.update(e, e => {
e.playRateChangedRecord = {}
});
break;
case Nf.PlayError:
this.update(e, ({
sessionControlRecord: e
}) => {
e.state = "RTC_STATE_PLAYERROR"
}), this.update(e, e => {
e.playErrorRecord = {}
});
break;
case Nf.MediaEngineStalled:
this.update(e, ({
sessionControlRecord: e
}) => {
e.state = "RTC_STATE_MEDIAENGINESTALL", e.oldRate = 0
}), this.update(e, e => {
e.mediaEngineStalledRecord = {}
});
break;
case Nf.SwitchComplete:
this.update(e, e => {
e.switchCompleteRecord = {}, e.sessionControlRecord.prevLevelUrl = e.sessionControlRecord.curLevelUrl
});
break;
case Nf.VariantEnded:
this.update(e, ({
sessionControlRecord: e
}) => {
e.decodedFramesForVariant = 0, e.decodedFramesForVariantSampleCount = 0
}), this.update(e, e => {
e.variantEndedRecord = {}
});
break;
case Nf.NwError:
this.update(e, ({
sessionControlRecord: e
}) => {
e.state = "RTC_STATE_NWERROR"
}), this.update(e, e => {
e.nwErrorRecord = {}
})
}
this.update(e, ({
sessionControlRecord: e
}) => {
e.eventStartTime = Date.now()
})
}
updatePlaybackInfo(e, s) {
this.update(e, ({
sessionControlRecord: e,
periodicRecord: t,
playEndedRecord: i
}) => {
s.droppedVideoFrames < e.droppedVideoFrames && (e.droppedVideoFrames = 0), s.decodedFrameCount < e.decodedFrameCount && (e.decodedFrameCount = 0);
var r = s.droppedVideoFrames - (e.droppedVideoFrames || 0),
n = s.decodedFrameCount - (e.decodedFrameCount || 0);
e.droppedVideoFrames = s.droppedVideoFrames, e.decodedFrameCount = s.decodedFrameCount, e.decodedFramesForVariant += n, e.decodedFramesForVariantSampleCount += 1, r && (3 <= r ? (t.GroupViFrDr = (t.GroupViFrDr || 0) + r, t.GroupViFrDrEvtCount = (t.GroupViFrDrEvtCount || 0) + 1, i.GroupViFrDr = (i.GroupViFrDr || 0) + r, i.GroupViFrDrEvtCount = (i.GroupViFrDrEvtCount || 0) + 1) : (t.SparseViFrDr = (t.SparseViFrDr || 0) + r, t.SparseViFrDrEvtCount = (t.SparseViFrDrEvtCount || 0) + 1, i.SparseViFrDr = (i.SparseViFrDr || 0) + r, i.SparseViFrDrEvtCount = (i.SparseViFrDrEvtCount || 0) + 1))
})
}
updateBufferAppended(e, t) {
this.update(e, ({
sessionControlRecord: e
}) => {
e.bufferAppendInfo || (e.bufferAppendInfo = []), e.bufferAppendInfo.push(t)
})
}
updateSeeked(e, t) {
this.update(e, ({
sessionControlRecord: e
}) => {
e.seekInfo || (e.seekInfo = []), e.seekInfo.push(t)
})
}
updateManifestParsed(e, r) {
this.update(e, ({
sessionControlRecord: e,
periodicRecord: t,
playEndedRecord: i
}) => {
t.MasterPlaylistADT = (t.MasterPlaylistADT || 0) + r.adt, i.MasterPlaylistADT = (i.MasterPlaylistADT || 0) + r.adt;
t = this._computeVariantInfo(r.levels);
i.IsAudioOnly = r.isAudioOnly, i.IsGapless = r.isGapless, i.IsFirstItem = r.isFirstItem, i.ItemID = r.itemID, i.MaxVideoQltyIndex = t.maxVideoQltyIndex, i.MaxReWd = t.maxWidth, i.MaxReHt = t.maxHeight, e.manifestData = {
variantList: t.variantList,
varListString: t.varListString
}
})
}
updateFragLoaded(e, r) {
this.update(e, ({
sessionControlRecord: e,
periodicRecord: t,
playEndedRecord: i
}) => {
if (t.MediaRequestsSent = (t.MediaRequestsSent || 0) + 1, i.MediaRequestsSent = (i.MediaRequestsSent || 0) + 1, r.cdnServer) {
const e = r.cdnServer.toLowerCase();
"aapl" !== e && "akam" !== e && "llnw" !== e || (i.LastMediaCDNServer = e)
}
r.serverInfo && (i.ServerInfo = r.serverInfo), e.segmentMimeTypes || (e.segmentMimeTypes = []), void 0 === e.segmentMimeTypes.find(e => e == r.contentType) && e.segmentMimeTypes.push(r.contentType), r.fragType === gu.Variant ? (e.variantVideoBytes = (e.variantVideoBytes || 0) + r.bytes, e.variantVideoDuration = (e.variantVideoDuration || 0) + r.duration, e.intervalVideoBytes = (e.intervalVideoBytes || 0) + r.bytes, e.intervalVideoDuration = (e.intervalVideoDuration || 0) + r.duration, e.sessionVideoBytes = (e.sessionVideoBytes || 0) + r.bytes, e.sessionVideoDuration = (e.sessionVideoDuration || 0) + r.duration, e.obrLast = 8 * r.bytes / (r.duration / 1e3), t.NetBytes = (t.NetBytes || 0) + r.bytes, t.ADT = (t.ADT || 0) + r.adt, t.SegmentProcessTime = (t.SegmentProcessTime || 0) + r.processTime, i.ADT = (i.ADT || 0) + r.adt, i.NetBytes = (i.NetBytes || 0) + r.bytes, i.SegmentProcessTime = (i.SegmentProcessTime || 0) + r.processTime) : r.fragType === gu.AltAudio && (e.variantAudioBytes = (e.variantAudioBytes || 0) + r.bytes, e.variantAudioDuration = (e.variantAudioDuration || 0) + r.duration, e.intervalAudioBytes = (e.intervalAudioBytes || 0) + r.bytes, e.intervalAudioDuration = (e.intervalAudioDuration || 0) + r.duration, e.sessionAudioBytes = (e.sessionAudioBytes || 0) + r.bytes, e.sessionAudioDuration = (e.sessionAudioDuration || 0) + r.duration)
})
}
updateFragBuffered(e, i) {
this.update(e, ({
periodicRecord: e,
playEndedRecord: t
}) => {
i.fragType === gu.Variant && (e.SegmentParseTime = (e.SegmentParseTime || 0) + i.parseTime, t.SegmentParseTime = (t.SegmentParseTime || 0) + i.parseTime)
})
}
updateLevelLoaded(e, n) {
this.update(e, ({
sessionControlRecord: e,
playLikelyToKeepUpRecord: t,
periodicRecord: i,
playEndedRecord: r
}) => {
t.PlaylistADT = (t.PlaylistADT || 0) + n.adt, i.PlaylistADT = (i.PlaylistADT || 0) + n.adt, r.PlaylistADT = (r.PlaylistADT || 0) + n.adt, i.MaxPlaylistDT = n.adt > i.MaxPlaylistDT ? n.adt : i.MaxPlaylistDT, r.MaxPlaylistDT = n.adt > r.MaxPlaylistDT ? n.adt : r.MaxPlaylistDT, r.PlayType = n.playType, this._setTargetDuration(n.url, n.targetduration, e), e.playlistMimeTypes || (e.playlistMimeTypes = []), void 0 === e.playlistMimeTypes.find(e => e == n.contentType) && e.playlistMimeTypes.push(n.contentType);
i = n.url, r = this._getVariantInfo(i, e);
e.intervalVariantList[i] || (e.intervalVariantList[i] = Object.assign({}, r)), e.sessionVariantList[i] || (e.sessionVariantList[i] = Object.assign({}, r))
})
}
updateLevelsChanged(e, r) {
this.update(e, ({
sessionControlRecord: t,
playEndedRecord: e
}) => {
const i = this._computeVariantInfo(r.levels);
e.MaxVideoQltyIndex = i.maxVideoQltyIndex, e.MaxReWd = i.maxWidth, e.MaxReHt = i.maxHeight, t.manifestData = {
variantList: i.variantList,
varListString: i.varListString
}, Object.keys(i.variantList).forEach(e => {
t.intervalVariantList[e] && (t.intervalVariantList[e].brRnk = i.variantList[e].brRnk), t.sessionVariantList[e] && (t.sessionVariantList[e].brRnk = i.variantList[e].brRnk)
})
})
}
updateLicenseChallengeRequested(e, r) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = {},
i = r.timestamp;
t.licenseChallengeStartTime = i, "RTC_STATE_INIT" === e.state && (t.keyInitTime = i - e.sessionStartTime), e.activeKeySessions[r.keyuri] = t
})
}
updateLicenseChallengeReceived(e, i) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = e.activeKeySessions[i.keyuri];
t.licenseChallengeRequestTime = i.timestamp - t.licenseChallengeStartTime
})
}
updateLicenseChallengeSubmitted(e, i) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = e.activeKeySessions[i.keyuri];
t.keyFormat = i.keyFormat, t.licenseChallengeSubmitTime = i.timestamp
})
}
updateLicenseChallengeCreated(e, i) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = e.activeKeySessions[i.keyuri];
t.cdmVersion = i.cdmVersion, t.licenseChallengeCreationTime = i.timestamp - t.licenseChallengeSubmitTime
})
}
updateLicenseResponseRequested(e, t) {
this.update(e, ({
sessionControlRecord: e
}) => {
e.activeKeySessions[t.keyuri].licenseResponseRequestTime = t.timestamp
})
}
updateLicenseResponseReceived(e, i) {
this.update(e, ({
sessionControlRecord: e
}) => {
const t = e.activeKeySessions[i.keyuri];
t.licenseResponseReceiveTime = i.timestamp - t.licenseResponseRequestTime
})
}
updateLicenseResponseSubmitted(e, t) {
this.update(e, ({
sessionControlRecord: e
}) => {
e.activeKeySessions[t.keyuri].licenseResponseSubmitTime = t.timestamp
})
}
_prepareEventPlayEnded(e) {
this.update(e, ({
sessionControlRecord: e,
playEndedRecord: t
}) => {
t.AvgVideoBitrate = 8 * (e.sessionVideoBytes || 0) / (e.sessionVideoDuration || 1), t.AvgAudioBitrate = 8 * (e.sessionAudioBytes || 0) / (e.sessionAudioDuration || 1);
var i = 1e3 * Math.round((t.NetBytes || 0) / 1e3);
t.NetBytes = i;
var r = t.ADT || 1,
n = t.ADT + t.SegmentProcessTime || 1,
s = t.ADT + t.SegmentProcessTime + t.SegmentParseTime || 1;
t.TWOBR = 8 * i / (r / 1e3), t.PerceivedTWOBR = 8 * i / (n / 1e3), t.NetTWOBR = 8 * i / (s / 1e3);
var s = this._findTimeWeightedValues("RTC_STATE_PLAY" === e.state ? Date.now() - e.eventStartTime : 0, e.sessionVariantList, e.curLevelUrl);
t.PlayerTWIBR = s.twIBR, t.PlayerTWIABR = s.twIABR, t.TWBitRk = s.twBRnk;
s = this._getVariantInfo(e.curLevelUrl, e);
t.TargetDur = s.targetduration, t.ReWd = s.width, t.ReHt = s.height, t.VariantList = null === (s = e.manifestData) || void 0 === s ? void 0 : s.varListString;
let a = "";
e.playlistMimeTypes && (e.playlistMimeTypes.forEach(e => {
a += e + ","
}), a = a.slice(0, -1));
let o = "";
e.segmentMimeTypes && (e.segmentMimeTypes.forEach(e => {
o += e + ","
}), o = o.slice(0, -1)), t.PlaylistMimeType = a, t.SegmentMimeType = o, t.Rate = e.rate
}), this._aggregateTimes(e)
}
_prepareEventPeriodic(e, o) {
this.update(e, ({
sessionControlRecord: e,
periodicRecord: t,
playEndedRecord: i
}) => {
t.EventCounter = e.periodicEventCounter, t.PInterval = Date.now() - e.lastPeriodicTime, t.AvgVideoBitrate = 8 * (e.intervalVideoBytes || 0) / (e.intervalVideoDuration || 1), t.AvgAudioBitrate = 8 * (e.intervalAudioBytes || 0) / (e.intervalAudioDuration || 1);
let r = t.NetBytes || 0;
o.isFinal && (t.NetBytes = r = 1e3 * Math.round(r / 1e3));
var n = t.ADT || 1,
s = t.ADT + t.SegmentProcessTime || 1,
a = t.ADT + t.SegmentProcessTime + t.SegmentParseTime || 1;
t.TWOBR = 8 * r / (n / 1e3), t.PerceivedTWOBR = 8 * r / (s / 1e3), t.NetTWOBR = 8 * r / (a / 1e3);
var a = this._findTimeWeightedValues("RTC_STATE_PLAY" === e.state ? Date.now() - e.eventStartTime : 0, e.intervalVariantList, e.curLevelUrl);
t.PlayerTWIBR = a.twIBR, t.PlayerTWIABR = a.twIABR, t.TWBitRk = a.twBRnk;
a = this._getVariantInfo(e.curLevelUrl, e);
t.TargetDur = a.targetduration, t.ReWd = a.width, t.ReHt = a.height, t.VariantList = null === (a = e.manifestData) || void 0 === a ? void 0 : a.varListString, t.Rate = e.rate;
e = this._computeMediaStats(e);
e && (t.MedianBufferAppendLatency = e.bufLatencyInfo.median, t.MaxBufferAppendLatency = e.bufLatencyInfo.max, t.MedianBufferAppendSize = e.bufSizeInfo.median, t.MaxBufferAppendSize = e.bufSizeInfo.max, t.MedianSeekLatency = e.seekLatencyInfo.median, t.MaxSeekLatency = e.seekLatencyInfo.max, t.MedianPlayLatency = e.playLatencyInfo.median, t.MaxPlayLatency = e.playLatencyInfo.max), this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_prepareEventPlayStalled(e, s) {
this.update(e, ({
sessionControlRecord: e,
playStalledRecord: t,
playEndedRecord: i
}) => {
var r = this._getVariantInfo(e.curLevelUrl, e),
n = Date.now();
t.MediaDur = s.mediaDur, t.BitRnk = r.brRnk, t.Codecs = r.codecs, t.LastLikelyToKeepUp = n - e.lastLikelyToKeepUpTime, t.LastSwitch = n - e.lastSwitchTime, t.StallDetectionTime = s.stallDurationMs, t.StallType = s.type, t.BufferLength = s.bufferLen, "networkError" === i.ErrDomain && (t.NwErrTime = i.NwErrTime, t.NwErrCode = i.ErrCode), t.LaSwDir = e.lastSwitchDir, t.TargetDur = r.targetduration, t.PlayerIABR = r.avgBandwidth, t.PlayerIBR = r.bandwidth, t.Rate = e.rate, t.OBRLast = e.obrLast, t.OBRMean = 8 * i.NetBytes / (i.ADT / 1e3), this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_prepareEventKeySessionComplete(e, r) {
this.update(e, ({
sessionControlRecord: e,
keySessionCompleteRecord: t,
playEndedRecord: i
}) => {
e = e.activeKeySessions[r.keyuri];
e ? (t.KeyFormat = e.keyFormat, t.CDMVersion = e.cdmVersion, t.LicenseChallengeRequestTime = e.licenseChallengeRequestTime, t.LicenseChallengeCreationTime = e.licenseChallengeCreationTime, t.LicenseResponseReceiveTime = e.licenseResponseReceiveTime, t.LicenseResponseProcessTime = e.licenseResponseProcessTime, t.KeyDeliveryTime = e.keyDeliveryTime, t.CurrentMediaTime = 1e3 * e.currentMediaTime, t.KeyInitTime = e.keyInitTime, t.KeyErrorType = e.keyErrorType, this._copyCommonKeys(t, i)) : this.logger.warn(`_prepareEventKeySessionComplete no keySessionInfo for ${le(r.keyuri)}`)
}), this._aggregateTimes(e)
}
_prepareEventPlayLikelyToKeepUp(e, n) {
this.update(e, ({
sessionControlRecord: e,
playLikelyToKeepUpRecord: t,
playEndedRecord: i
}) => {
var r = this._getVariantInfo(e.curLevelUrl, e);
t.EventCounter = e.playLikelyToKeepUpEventCounter, t.PlayerIABR = r.avgBandwidth, t.PlayerIBR = r.bandwidth, t.MediaDur = n.mediaDur, t.BitRnk = r.brRnk, t.Codecs = r.codecs, t.TargetDur = r.targetduration, this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_prepareEventPlayRateChanged(e, n) {
this.update(e, ({
sessionControlRecord: e,
playRateChangedRecord: t,
playEndedRecord: i
}) => {
var r = this._getVariantInfo(e.curLevelUrl, e);
t.Rate = e.rate, t.StNPT = n.currentTime, t.PlayerIABR = r.avgBandwidth, t.PlayerIBR = r.bandwidth, t.BitRnk = r.brRnk, t.MediaDur = n.mediaDur, t.Codecs = r.codecs, this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_prepareEventPlayError(e, s) {
this.update(e, ({
sessionControlRecord: e,
playErrorRecord: t,
playEndedRecord: i
}) => {
var r = this._getVariantInfo(e.curLevelUrl, e),
n = Date.now();
"mediaElementError" == s.domain ? (t.ErrDomain = t.ErrCode = "mediaElementError", t.ErrIsFatal = !0, t.ErrCodeMediaElement = s.mediaElemCode, t.ErrReason = s.mediaElemReason, t.ErrDetail = s.mediaElemDetail) : (t.ErrCode = s.details, t.ErrReason = s.code, t.ErrIsFatal = s.fatal, t.ErrDomain = "mediaError"), t.PlayerErrCount = s.count || 1, t.BitRnk = r.brRnk, t.MediaDur = s.mediaDur, t.PlayTime = i.PlayTime, t.PlayTimeWC = i.PlayTimeWC, t.PlayerIABR = r.avgBandwidth, t.PlayerIBR = r.bandwidth, t.LastLikelyToKeepUp = n - e.lastLikelyToKeepUpTime, t.LastSwitch = n - e.lastSwitchTime, t.VideoQltyIndex = r.qltyIndex, t.Rate = e.rate, t.KeyErrorType = e.lastKeyErrorType, t.KeyDeliveryTime = e.lastKeyDeliveryTime, this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_prepareEventMediaEngineStalled(e, s) {
this.update(e, ({
sessionControlRecord: e,
mediaEngineStalledRecord: t,
playEndedRecord: i
}) => {
var r = Date.now(),
n = this._getVariantInfo(e.curLevelUrl, e);
t.MediaDur = s.mediaDur, t.BitRnk = n.brRnk, t.Codecs = n.codecs, t.LastLikelyToKeepUp = r - e.lastLikelyToKeepUpTime, t.LastSwitch = r - e.lastSwitchTime, t.StallDetectionTime = s.stallDurationMs, t.StallType = s.type, t.BufferLength = s.bufferLen, t.LaSwDir = e.lastSwitchDir, t.TargetDur = n.targetduration, t.PlayerIABR = n.avgBandwidth, t.PlayerIBR = n.bandwidth, t.Rate = e.rate, t.OBRLast = e.obrLast, t.OBRMean = 8 * i.NetBytes / (i.ADT / 1e3), this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_prepareEventSwitchComplete(e, s) {
this.update(e, ({
sessionControlRecord: e,
switchCompleteRecord: t,
playEndedRecord: i
}) => {
var r = this._getVariantInfo(e.prevLevelUrl, e),
n = this._getVariantInfo(e.curLevelUrl, e);
t.FrBitRnk = r.brRnk, t.ToBitRnk = n.brRnk, t.TimeToBitrate = Date.now() - e.sessionStartTime, t.MediaDur = s.mediaDur, t.Rate = e.rate, t.PlayerIBR = n.bandwidth, t.PlayerIABR = n.avgBandwidth, t.LastPlayerIBR = r.bandwidth, t.LastPlayerIABR = r.avgBandwidth, t.ReWd = n.width, t.ReHt = n.height, this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_prepareEventVariantEnded(e, n) {
this.update(e, ({
sessionControlRecord: e,
variantEndedRecord: t,
playEndedRecord: i
}) => {
var r = this._getVariantInfo(e.curLevelUrl, e);
t.Rate = e.rate, t.VarAvgBitrate = r.avgBandwidth, t.VarPeakBitrate = r.bandwidth, t.VarBitRk = r.brRnk, t.VarSTTime = e.variantStartTimeMedia, t.VarEndTime = 1e3 * n.currentTime, t.IFR = r.framerate, t.ODR = e.decodedFramesForVariant / e.decodedFramesForVariantSampleCount, t.ReWd = r.width, t.ReHt = r.height, t.Codecs = r.codecs, t.AvgVideoBitrate = 8 * (e.variantVideoBytes || 0) / (e.variantVideoDuration || 1), t.AvgAudioBitrate = 8 * (e.variantAudioBytes || 0) / (e.variantAudioDuration || 1), this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_prepareEventNwError(e, n) {
this.update(e, ({
sessionControlRecord: e,
nwErrorRecord: t,
playEndedRecord: i
}) => {
var r = this._getVariantInfo(e.curLevelUrl, e);
t.ErrCode = n.details, t.ErrReason = n.code, t.ErrIsFatal = n.fatal, t.NwErrCount = n.count || 1, t.ErrDomain = "networkError", t.PlayTime = i.PlayTime, t.PlayTimeWC = i.PlayTimeWC, t.BitRnk = r.brRnk, t.Rate = e.rate, t.KeyErrorType = e.lastKeyErrorType, t.KeyDeliveryTime = e.lastKeyDeliveryTime, this._copyCommonKeys(t, i)
}), this._aggregateTimes(e)
}
_copyCommonKeys(e, t) {
e.PlayType = t.PlayType, e.LastMediaCDNServer = t.LastMediaCDNServer, e.MaxVideoQltyIndex = t.MaxVideoQltyIndex, e.MaxReWd = t.MaxReWd, e.MaxReHt = t.MaxReHt, e.IsGapless = t.IsGapless, e.IsAudioOnly = t.IsAudioOnly, e.IsFirstItem = t.IsFirstItem, e.ItemID = t.ItemID, e.ServerInfo = t.ServerInfo
}
_computeVariantInfo(e) {
const i = {};
let r = 0,
n = 0,
s = 0,
a = 0;
const o = this._getMaxNormalizedPeak(e);
e.forEach(e => {
if (e.attrs) {
const r = this._getVideoFourCC(e.attrs.CODECS),
n = this._getVideoQualityIndex(r, e.attrs["VIDEO-RANGE"]) || 0,
s = {
codecs: e.attrs.CODECS,
width: e.width,
height: e.height,
bandwidth: e.attrs.BANDWIDTH,
avgBandwidth: e.attrs["AVERAGE-BANDWIDTH"],
framerate: e.attrs["FRAME-RATE"],
iframes: e.iframes,
brRnk: this._getBitrateRank(e.attrs.BANDWIDTH, r, o),
qltyIndex: n,
targetduration: 0,
playTime: 0
};
a = n > a ? n : a, i[e.url] = s
}
var t = e.width * e.height;
t > s && (s = t, r = e.width, n = e.height)
});
e = 0 < Object.keys(i).length ? Object.values(i).map(e => e.bandwidth + ":" + e.avgBandwidth).join(",") : void 0;
return {
variantList: i,
varListString: e,
maxVideoQltyIndex: a,
maxWidth: r,
maxHeight: n
}
}
_getMaxNormalizedPeak(e) {
let n = 0;
return e.forEach(e => {
e = e.attrs;
if (e) {
const t = e.BANDWIDTH || 0,
i = this._getNormalizedPeak(t, this._getVideoFourCC(e.CODECS)),
r = Math.max(t, i);
n = r > n ? r : n
}
}), n
}
_getNormalizedPeak(e, t) {
return "object" == typeof Ff[t] ? 1.5 * e : +e
}
_getVideoFourCC(e) {
return e && e.split(",").map(e => e.split(".")[0].trim()).find(e => !!Ff[e])
}
_getVideoQualityIndex(e, t) {
return "object" == typeof Ff[e] ? Ff[e][t] : Ff[e]
}
_getBitrateRank(e, t, i) {
t = Math.max(1, this._getNormalizedPeak(e, t));
return Math.ceil(100 * t / i)
}
_findTimeWeightedValues(o, l, d) {
const e = {
twBRnk: 0,
twIBR: 0,
twIABR: 0
};
if (l) {
let i = 0,
r = 0,
n = 0,
s = 0,
a = 0;
Object.values(l).forEach(e => {
let t = e.playTime;
e === l[d] && (t += o || 0), t && (r += e.bandwidth * t, i += e.brRnk * t, n += t, e.avgBandwidth && (s += e.avgBandwidth * t, a += t))
}), n && (e.twBRnk = i / n, e.twIBR = r / n), s && a && (e.twIABR = s / a)
}
return e
}
_computeMediaStats(e) {
const t = e.bufferAppendInfo;
let i = [];
const r = [];
t && t.forEach && t.forEach(e => {
i.push(e.latency), r.push(e.size)
});
var n = this._computeStats(i),
s = this._computeStats(r),
a = e.seekInfo;
i = [], a && a.forEach && e.seekInfo.forEach(e => i.push(e.latency));
var o = this._computeStats(i),
a = e.playInfo;
return i = [], a && a.forEach && e.playInfo.forEach(e => i.push(e.latency)), {
bufLatencyInfo: n,
bufSizeInfo: s,
seekLatencyInfo: o,
playLatencyInfo: this._computeStats(i)
}
}
_computeStats(e) {
let t, i;
if (e) {
const r = e.filter(e => 0 < e);
if (0 < r.length) {
t = r.reduce((e, t) => Math.max(e, t));
const e = r.length,
n = r.sort((e, t) => e - t),
s = Math.ceil(e / 2);
i = e % 2 == 0 ? (n[s] + n[s - 1]) / 2 : n[s - 1]
}
}
return {
max: t,
median: i
}
}
_getVariantInfo(e, t) {
return e && t.manifestData && t.manifestData.variantList && t.manifestData.variantList[e] ? t.manifestData.variantList[e] : {}
}
_setTargetDuration(e, t, i) {
e && i.manifestData && i.manifestData.variantList && i.manifestData.variantList[e] && (i.manifestData.variantList[e].targetduration = t)
}
_isBadSw(e, t, i, r, n, s, a) {
let o = n - s < 1e4 && t !== e && r === i && !a ? !0 : !1;
return o
}
_aggregateTimes(e) {
this.update(e, ({
sessionControlRecord: t,
playLikelyToKeepUpRecord: i,
playStalledRecord: r,
mediaEngineStalledRecord: n,
switchCompleteRecord: s,
playRateChangedRecord: a,
variantEndedRecord: o,
playErrorRecord: l,
nwErrorRecord: d,
periodicRecord: u,
playEndedRecord: c
}) => {
var h = Date.now() - t.eventStartTime;
switch (t.state) {
case "RTC_STATE_INIT":
i.StartupTime = (i.StartupTime || 0) + h, u.InitTime = (u.InitTime || 0) + h, c.InitTime = (c.InitTime || 0) + h;
break;
case "RTC_STATE_CANPLAY":
a.StartupTime = (a.StartupTime || 0) + h, u.InitTime = (u.InitTime || 0) + h, c.InitTime = (c.InitTime || 0) + h;
break;
case "RTC_STATE_PAUSE":
u.PauseTime = (u.PauseTime || 0) + h, c.PauseTime = (c.PauseTime || 0) + h, a.LastPause = (a.LastPause || 0) + h, c.LastPause = (c.LastPause || 0) + h, l.LastPause = (l.LastPause || 0) + h, d.LastPause = (d.LastPause || 0) + h;
break;
case "RTC_STATE_STALL":
o.StallTime = (o.StallTime || 0) + h, u.StallTime = (u.StallTime || 0) + h, c.StallTime = (c.StallTime || 0) + h, a.LastStall = (a.LastStall || 0) + h, l.LastStall = (l.LastStall || 0) + h, c.LastStall = (c.LastStall || 0) + h;
break;
case "RTC_STATE_MEDIAENGINESTALL":
o.MediaEngineStallTime = (o.MediaEngineStallTime || 0) + h, u.MediaEngineStallTime = (u.MediaEngineStallTime || 0) + h, c.MediaEngineStallTime = (c.MediaEngineStallTime || 0) + h, a.LastMediaEngineStall = (a.LastMediaEngineStall || 0) + h, l.LastMediaEngineStall = (l.LastMediaEngineStall || 0) + h, c.LastMediaEngineStall = (c.LastMediaEngineStall || 0) + h;
break;
case "RTC_STATE_NWERROR":
c.NwErrTime = (c.NwErrTime || 0) + h, u.NwErrTime = (u.NwErrTime || 0) + h;
break;
case "RTC_STATE_PLAYERROR":
u.PlayErrTime = (u.PlayErrTime || 0) + h, c.PlayErrTime = (c.PlayErrTime || 0) + h;
break;
case "RTC_STATE_PLAY": {
a.RateChangePlayTime = (a.RateChangePlayTime || 0) + h, s.PlayTime = (s.PlayTime || 0) + h, s.PlayTimeLastSW = (s.PlayTimeLastSW || 0) + h * (t.oldRate / 100), r.LastResume = (r.LastResume || 0) + h, n.LastResume = (n.LastResume || 0) + h, l.LastResume = (l.LastResume || 0) + h, d.LastResume = (d.LastResume || 0) + h, o.VarPlayTimeWC = (o.VarPlayTimeWC || 0) + h, o.VarPlayTime = (o.VarPlayTime || 0) + h * (t.oldRate / 100), u.PlayTimeWC = (u.PlayTimeWC || 0) + h, u.PlayTime = (u.PlayTime || 0) + h * (t.oldRate / 100), c.PlayTimeWC = (c.PlayTimeWC || 0) + h, c.PlayTime = (c.PlayTime || 0) + h * (t.oldRate / 100), n.PlayTime = c.PlayTime, r.PlayTime = c.PlayTime;
const i = t.curLevelUrl;
let e = t.intervalVariantList[i];
e.playTime = (e.playTime || 0) + h, e = t.sessionVariantList[i], e.playTime = (e.playTime || 0) + h;
break
}
}
})
}
}
const Vf = {
name: "rtc-service"
};
class Kf {
constructor(e, t, i, r) {
this.hls = e, this.config = t, this.accessLog = i, this.logger = r, this.destroy$ = new Xt, this.isSeeking = !1, this.seekStart = null, this.periodicInterval = t.rtcIntervalTimeout || 3e5, this.intervalFunc = null, this.rtcStore = new $f(this.logger), this.rtcQuery = new Uf(this.rtcStore, this.logger), this.rtcComponent = new Bf(this.rtcQuery, this.logger), i.setRTCQuery(this.rtcQuery), this.subscribeAndUpdateStore(), this.registerForEvents()
}
destroy() {
this.destroy$.next(), this.clearPeriodic(), this.rtcStore.reset()
}
detachMedia() {
this.clearPeriodic();
var e;
try {
e = this.hls.realCurrentTime, this.rtcStore.updateVariantEnd(this.rtcEventItemId(!0), {
currentTime: e
}), this.sendAndFinalize(this.rtcEventItemId(!0), Nf.VariantEnded), this.rtcStore.updatePeriodic(this.rtcEventItemId(!0), !0), this.sendAndFinalize(this.rtcEventItemId(!0), Nf.Periodic), this.rtcStore.updateEnded(this.rtcEventItemId(!0)), this.sendAndFinalize(this.rtcEventItemId(!0), Nf.PlayEnded)
} catch (e) {
this.logger.warn(Vf, e)
}
}
handleError(e) {
var t = e instanceof p ? e : new V(!0, e.message, $.InternalError);
t instanceof uc && !t.fatal ? (this.rtcStore.updateLevelLoadError(this.rtcEventItemId(), {
url: t.url,
mediaDur: this.hls.bufferedDuration,
isSeeking: this.isSeeking
}), this.sendAndFinalize(this.rtcEventItemId(), Nf.SwitchComplete)) : t.type === o ? (this.rtcStore.updateNwError(this.rtcEventItemId(), {
fatal: t.fatal,
details: t.details,
code: null === (e = t.response) || void 0 === e ? void 0 : e.code
}), this.sendAndFinalize(this.rtcEventItemId(), Nf.NwError)) : (this.rtcStore.updateMediaError(this.rtcEventItemId(), {
fatal: t.fatal,
details: t.details,
code: null === (t = t.response) || void 0 === t ? void 0 : t.code
}), this.sendAndFinalize(this.rtcEventItemId(), Nf.PlayError))
}
handleMediaElementError(e) {
this.rtcStore.updateMediaElementError(this.rtcEventItemId(), e), this.sendAndFinalize(this.rtcEventItemId(), Nf.PlayError)
}
handleFragLoaded(e, t) {
var i, r, n;
this.checkMediaOptionType(e.mediaOptionType) && (e.itemId !== this.rtcEventItemId() && this.logger.warn(Vf, `Frag id does not match current item id. Frag Id=${e.itemId}, playing id=${this.rtcEventItemId(!0)}, loading id=${null===(n=this.hls.loadingItem)||void 0===n?void 0:n.itemId}`), i = t.tload - t.trequest, r = t.tload - t.tfirst, n = this.serverInfoInstance || {}, this.rtcStore.updateFragLoaded(e.itemId, {
fragType: e.mediaOptionType,
bytes: t.loaded,
duration: e.duration,
adt: i,
processTime: r,
contentType: t.contentType,
cdnServer: t.cdnServer,
serverInfo: n
}), this.accessLog.updateFragLoaded(e.itemId, this.isSeeking, {
fragType: e.mediaOptionType,
bytes: t.loaded,
duration: e.duration,
adt: i,
processTime: r,
startPTS: e.start,
endPTS: e.start + e.duration
}))
}
handleFragBuffered(e) {
var t;
this.checkMediaOptionType(e.fragmentType) && (t = e.endDataAppend - e.startDataAppend, this.rtcStore.updateFragBuffered(this.rtcEventItemId(), {
fragType: e.fragmentType,
bytes: e.dataBytesAppend,
parseTime: t
}))
}
handleLevelLoaded(e, t) {
var i;
e ? (e.itemId !== this.rtcEventItemId() && this.logger.warn(Vf, `media option id does not match current item id. media Id=${e.itemId}, current id=${this.rtcEventItemId}`), e.mediaOptionType === gu.Variant && (i = t.tload - t.trequest, this.rtcStore.updateLevelLoaded(this.rtcEventItemId(), {
url: e.url,
targetduration: e.targetduration,
adt: i,
contentType: t.contentType,
playType: e.type
}))) : this.logger.warn(`handleLevelLoaded called with mediaOptionDetails as ${e}`)
}
handleLevelSwitched(e) {
var t = {
url: e.url,
isSeeking: this.isSeeking,
mediaDur: this.hls.bufferedDuration,
currentTime: this.hls.realCurrentTime
};
e.oldVariant && (this.rtcStore.updateVariantEnd(this.rtcEventItemId(), {
currentTime: this.hls.realCurrentTime
}), this.sendAndFinalize(this.rtcEventItemId(), Nf.VariantEnded)), this.rtcStore.updateLevelSwitched(this.rtcEventItemId(), t), this.sendAndFinalize(this.rtcEventItemId(), Nf.SwitchComplete)
}
handleLevelSwitching(e) {
this.levelSwitchingUrl = e
}
handleLevelsChanged(e) {
this.rtcStore.updateLevelsChanged(this.rtcEventItemId(), {
levels: e
})
}
handleManifestParsed(e) {
var t = e.stats.tload - e.stats.trequest;
this.rtcStore.updateManifestParsed(this.rtcEventItemId(), {
levels: e.levels,
adt: t,
contentType: e.stats.contentType,
isAudioOnly: this.hls.inGaplessMode,
isGapless: this.hls.inGaplessMode,
isFirstItem: this.hls.isFirstItem,
itemID: ((null === (e = this.hls.reportingAgent) || void 0 === e ? void 0 : e.SessionID) || Zl()) + "-" + this.rtcEventItemId()
})
}
handleSeek(e) {
if ("SEEKING" === e) this.isSeeking = !0, this.seekStart = Date.now();
else if ("SEEKED" === e) {
this.isSeeking = !1;
let e = 0;
this.seekStart && (e = Date.now() - this.seekStart), this.seekStart = null, this.rtcStore.updateSeeked(this.rtcEventItemId(!0), {
latency: e
})
}
}
handleDesiredRateChanged(e, t) {
0 === t || 1 < Math.abs(e) && 1 < Math.abs(t) ? (this.rtcStore.updateRateChanged(this.rtcEventItemId(!0), {
rate: t,
latency: 0,
mediaDur: this.hls.bufferedDuration,
currentTime: this.hls.realCurrentTime,
url: this.levelSwitchingUrl
}), this.sendAndFinalize(this.rtcEventItemId(!0), Nf.PlayRateChanged)) : 1 !== e && 1 === t && (this.playStart = Date.now()), this.oldRate = e, this.newRate = t
}
handleVariantBufferAppended(e, t) {
let i = 0;
e && (i = Date.now() - e), this.rtcStore.updateBufferAppended(this.rtcEventItemId(), {
latency: i,
size: t
})
}
handleStalled(e, t) {
var i = {
type: e.type,
stallDurationMs: e.stallDurationMs,
bufferLen: t,
mediaDur: this.hls.bufferedDuration
},
t = this.rtcQuery.getEntity(this.rtcEventItemId(!0)).sessionControlRecord.state;
e.type === Cp.LowBuffer || e.type === Cp.Seek && e.isLowBufferStall ? "RTC_STATE_PLAY" === t && (this.rtcStore.updateBufferStalled(this.rtcEventItemId(!0), i), this.sendAndFinalize(this.rtcEventItemId(!0), Nf.PlayStalled)) : "RTC_STATE_PLAY" === t && (this.rtcStore.updateMediaEngineStalled(this.rtcEventItemId(!0), i), this.sendAndFinalize(this.rtcEventItemId(!0), Nf.MediaEngineStalled))
}
handlePlaybackInfo(e, t) {
this.rtcStore.updatePlaybackInfo(this.rtcEventItemId(!0), {
droppedVideoFrames: e,
decodedFrameCount: t
}), this.accessLog.updatePlaybackInfo(this.rtcEventItemId(!0), {
droppedVideoFrames: e,
decodedFrameCount: t
})
}
checkMediaOptionType(e) {
return e === gu.Variant || e === gu.AltAudio || (this.logger.error(Vf, 'Should not have media option type = "%s" in RTC', Nu[e]), !1)
}
rtcEventItemId(e = !1) {
return (this.hls.isPreloading ? e ? this.hls.playingItem : this.hls.loadingItem : this.hls.currentItem).itemId
}
subscribeAndUpdateStore() {
this.hls.publicQueries$.pipe(La(([, e]) => this.mediaElementQueryListener(e)), Va(this.destroy$)).subscribe(), this.hls.itemQueue.activeItemById$.pipe(Za(t => {
if (t) {
let e = !1;
if (this.hls.userInfo ? this.hls.userInfo.internalBuild ? e = !0 : this.hls.userInfo.diagnosticsAndUsage && (e = this.config.enableRtcReporting) : e = this.config.enableRtcReporting, e) {
const i = this.hls.reportingAgent;
i ? this.rtcComponent.setReportingAgent(i) : this.logger.warn(Vf, "[RTCA] - Reporting is enabled but reportingAgent is null")
} else this.rtcComponent.setReportingAgent(null);
this.serverInfoInstance = null;
t = t.itemId;
this.rtcStore.createEntity(t), !this.hls.isFirstItem && this.hls.inGaplessMode || this.setPeriodic(t)
}
}), Va(this.destroy$)).subscribe()
}
itemTransitioned(e, t) {
this.rtcStore.updateVariantEnd(e, {
currentTime: this.hls.realCurrentTime
}), this.sendAndFinalize(e, Nf.VariantEnded), this.rtcStore.updatePeriodic(e, !0), this.sendAndFinalize(e, Nf.Periodic), this.rtcStore.updateEnded(e), this.sendAndFinalize(e, Nf.PlayEnded), this.setPeriodic(t)
}
mediaElementQueryListener(e) {
return e.gotPlaying$.pipe(Za(e => {
if (e) {
const e = this.oldRate,
t = this.newRate || 1;
1 < Math.abs(e) && 1 < Math.abs(t) || (this.rtcStore.updateCanPlay(this.rtcEventItemId(!0), {
mediaDur: this.hls.bufferedDuration
}), this.sendAndFinalize(this.rtcEventItemId(!0), Nf.PlayLikelyToKeepUp), this.rtcStore.updateRateChanged(this.rtcEventItemId(!0), {
rate: t,
latency: ne(this.playStart) ? Date.now() - this.playStart : 0,
mediaDur: this.hls.bufferedDuration,
currentTime: this.hls.realCurrentTime,
url: this.levelSwitchingUrl
}), this.sendAndFinalize(this.rtcEventItemId(!0), Nf.PlayRateChanged))
}
}))
}
registerForEvents() {
const e = Oc(this.hls, this);
an(e.event(P.KEY_REQUEST_STARTED, this.keyRequestStarted, this), e.event(P.KEY_LOADED, this.keyLoaded, this)).pipe(Va(this.destroy$)).subscribe()
}
keyRequestStarted(e) {
e.timestamp = Date.now(), this.rtcStore.updateLicenseChallengeRequested(this.rtcEventItemId(), e)
}
keyLoaded(e) {
e.timestamp = Date.now(), e.currentTime = this.hls.realCurrentTime, this.rtcStore.updateSegmentKeyLoaded(this.rtcEventItemId(), e)
}
licenseChallengeReceived(e) {
this.rtcStore.updateLicenseChallengeReceived(this.rtcEventItemId(), {
timestamp: Date.now(),
keyuri: e.keyuri
})
}
licenseChallengeSubmitted(e) {
this.rtcStore.updateLicenseChallengeSubmitted(this.rtcEventItemId(), {
timestamp: Date.now(),
keyFormat: e.keyFormat,
keyuri: e.keyuri
})
}
licenseChallengeCreated(e) {
this.rtcStore.updateLicenseChallengeCreated(this.rtcEventItemId(), {
timestamp: Date.now(),
cdmVersion: e.cdmVersion,
keyuri: e.keyuri
}), this.rtcStore.updateLicenseResponseRequested(this.rtcEventItemId(), {
timestamp: Date.now(),
keyuri: e.keyuri
})
}
licenseResponseSubmitted(e) {
this.rtcStore.updateLicenseResponseReceived(this.rtcEventItemId(), {
timestamp: Date.now(),
keyuri: e.keyuri
}), this.rtcStore.updateLicenseResponseSubmitted(this.rtcEventItemId(), {
timestamp: Date.now(),
keyuri: e.keyuri
})
}
licenseResponseProcessed(e) {
this.rtcStore.updateLicenseResponseProcessed(this.rtcEventItemId(), {
timestamp: Date.now(),
keyuri: e.keyuri,
currentTime: this.hls.realCurrentTime
}), this.sendAndFinalize(this.rtcEventItemId(), Nf.KeySessionComplete)
}
licenseChallengeError(e) {
this.rtcStore.updateLicenseChallengeError(this.rtcEventItemId(), {
timestamp: Date.now(),
keyuri: e.keyuri
}), this.sendAndFinalize(this.rtcEventItemId(), Nf.KeySessionComplete)
}
licenseResponseError(e) {
this.rtcStore.updateLicenseResponseError(this.rtcEventItemId(), {
timestamp: Date.now(),
keyuri: e.keyuri
}), this.sendAndFinalize(this.rtcEventItemId(), Nf.KeySessionComplete)
}
keyAborted(e) {
var t;
null != (null === (t = this.rtcQuery.getEntity(this.rtcEventItemId())) || void 0 === t ? void 0 : t.sessionControlRecord.activeKeySessions[e.keyuri]) ? (this.rtcStore.updateKeyAborted(this.rtcEventItemId(), {
timestamp: Date.now(),
keyuri: e.keyuri
}), this.sendAndFinalize(this.rtcEventItemId(), Nf.KeySessionComplete)) : this.logger.warn(`keyAbort called without active key session ${le(e.keyuri)}`)
}
setPeriodic(e) {
this.clearPeriodic(), this.intervalFunc = setInterval(this.handlePeriodic.bind(this, e), this.periodicInterval)
}
handlePeriodic(e) {
this.rtcStore.updatePeriodic(e, !1), this.sendAndFinalize(e, Nf.Periodic)
}
clearPeriodic() {
this.intervalFunc && clearInterval(this.intervalFunc), this.intervalFunc = null
}
sendAndFinalize(e, t) {
switch (this.accessLog.addPlayTime(e), t) {
case Nf.PlayEnded:
this.rtcComponent.sendPlayEnded(e);
break;
case Nf.Periodic:
this.rtcComponent.sendPeriodic(e);
break;
case Nf.PlayStalled:
this.accessLog.updateStallCount(e), this.rtcComponent.sendPlayStalled(e);
break;
case Nf.KeySessionComplete:
this.rtcComponent.sendKeySessionComplete(e);
break;
case Nf.PlayLikelyToKeepUp:
this.accessLog.updateCanPlay(e), this.rtcComponent.sendPlayLikelyToKeepUp(e);
break;
case Nf.PlayRateChanged:
this.rtcComponent.sendPlayRateChange(e);
break;
case Nf.PlayError:
this.accessLog.addToErrorLog(e, "mediaError"), this.rtcComponent.sendPlayError(e);
break;
case Nf.MediaEngineStalled:
this.accessLog.updateMediaEngineStallCount(e), this.rtcComponent.sendMediaEngineStalled(e);
break;
case Nf.SwitchComplete:
this.accessLog.addToAccessLog(e), this.rtcComponent.sendSwitchComplete(e);
break;
case Nf.VariantEnded:
this.rtcComponent.sendVariantEnded(e);
break;
case Nf.NwError:
this.accessLog.addToErrorLog(e, "networkError"), this.rtcComponent.sendNwError(e);
break;
default:
return void this.logger.error(Vf, `Unknown rtc event eventGroupId:${e}`)
}
this.rtcStore.finalize(e, t)
}
}
const qf = a => (e, t) => {
let i = 0,
r = 0;
for (var {
timestamp: n,
value: s
} of e) {
const e = Math.pow(Math.max(0, n - t) / 1e3, a);
i += e * s, r += e
}
return i / r
},
Hf = {
"uniform-time-weighted": qf(0),
"linear-time-weighted": qf(1),
"quadratic-time-weighted": qf(2)
};
class jf {
constructor(e, t = "quadratic-time-weighted", i = {
avgLatencyMs: NaN,
avgBandwidth: NaN
}) {
this.windowSize = e, this.aggregationMethod = t, this.latencyEntries = [], this.bandwidthEntries = [], this.minEntries = 1, this.cleanUpExpiredEntries = this.cleanUpExpiredEntries.bind(this), this.bwSubject = new yi(i)
}
get estimate$() {
return this.bwSubject.asObservable()
}
record(e) {
var {
trequest: t,
tfirst: i,
tload: r,
bitsDownloaded: e
} = e;
t !== r && (this.recordLatency(t, i), this.recordBandwidth(t, r, 1e3 * e / (r - t)), this.bwSubject.closed || (t = this.getEstimate(), this.bwSubject.next(t)))
}
getEstimate() {
if (this.latencyEntries.length < this.minEntries) return {
avgLatencyMs: NaN,
avgBandwidth: NaN
};
const e = performance.now() - this.windowSize,
t = Hf[this.aggregationMethod],
i = this.latencyEntries.map(({
start: e,
end: t
}) => ({
timestamp: t,
value: t - e,
duration: 1
}));
this.bandwidthEntries = function(r) {
function n(t, i) {
if (t.length) {
for (let e = 0; e < t.length; e++)
if (t[e].start > i.start || t[e].start === i.start && t[e].end > i.end) {
t.splice(e, 0, i);
break
}
} else t.push(i)
}
const s = [...r].sort((e, t) => e.start !== t.start ? e.start - t.start : e.end - t.end),
t = [];
for (; s.length;) {
const r = s[0];
let e;
if (s.shift(), t.length && (e = t[t.length - 1]), 0 === t.length || e.end <= r.start) t.push(r);
else if (r.start === e.start) r.end === e.end ? e.bitsPerSec += r.bitsPerSec : r.end < e.end || (e.bitsPerSec += r.bitsPerSec, r.start = e.end, n(s, r));
else {
var a = e.end,
o = e.bitsPerSec;
e.end = r.start;
var i = {
start: r.start,
end: Math.min(a, r.end),
bitsPerSec: r.bitsPerSec + o
};
if (t.push(i), a !== r.end) {
let e = 0,
t = 0,
i = 0;
i = a < r.end ? (e = a, t = r.end, r.bitsPerSec) : (e = r.end, t = a, o), n(s, {
start: e,
end: t,
bitsPerSec: i
})
}
}
}
return t
}(this.bandwidthEntries);
var r = this.bandwidthEntries.map(({
end: e,
bitsPerSec: t
}) => ({
timestamp: e,
duration: 1,
value: t
}));
return {
avgLatencyMs: t(i, e),
avgBandwidth: t(r, e)
}
}
getLatest() {
if (0 === this.latencyEntries.length) return {
avgLatencyMs: NaN,
avgBandwidth: NaN
};
var e = this.latencyEntries[this.latencyEntries.length - 1],
t = this.bandwidthEntries[this.bandwidthEntries.length - 1];
return {
avgLatencyMs: e.end - e.start,
avgBandwidth: t.bitsPerSec
}
}
recordLatency(e, t) {
this.latencyEntries.push({
start: e,
end: t
}), this.updateCleanupTimeout(t)
}
recordBandwidth(e, t, i) {
this.bandwidthEntries.push({
start: e,
end: t,
bitsPerSec: i
}), this.updateCleanupTimeout(t)
}
setCleanupTimeout(e) {
this.cleanupTimeout = setTimeout(this.cleanUpExpiredEntries, Math.max(e - performance.now(), 0)), this.cleanupTimestamp = e
}
clearCleanupTimeout() {
void 0 !== this.cleanupTimeout && (clearTimeout(this.cleanupTimeout), this.cleanupTimeout = void 0), this.cleanupTimestamp = void 0
}
updateCleanupTimeout(e) {
e += this.windowSize;
(!this.cleanupTimestamp || e < this.cleanupTimestamp) && (this.clearCleanupTimeout(), this.setCleanupTimeout(e))
}
cleanUpExpiredEntries() {
this.clearCleanupTimeout();
const t = performance.now() - this.windowSize;
if (this.latencyEntries = this.latencyEntries.filter(e => e.end >= t), this.bandwidthEntries = this.bandwidthEntries.filter(e => e.end >= t), this.bwSubject.closed || this.bwSubject.next(this.getEstimate()), 0 < this.latencyEntries.length || 0 < this.bandwidthEntries.length) {
const t = Math.min(...this.latencyEntries.map(e => e.end), ...this.bandwidthEntries.map(e => e.end));
this.updateCleanupTimeout(t)
}
}
destroy() {
this.clearCleanupTimeout()
}
}
const Qf = {
setCombinedEstimate: function(t, i, r) {
const n = Qe();
if (void 0 !== t.storage.set) {
var s = t.bandwidthHistoryStorageKey,
a = {
avgLatencyMs: i.avgLatencyMs,
avgBandwidth: i.avgBandwidth
},
a = Object.assign({}, a, {
expires: Date.now() + t.bandwidthHistoryTTL
});
try {
t.storage.set(s, JSON.stringify(a))
} catch (t) {
n.warn(`Error stringifying! Not persisting bandwidth estimates: ${t.message}`)
}
i = {
maxDuration: i.maxDurationSec,
avgFragParseTimeMs: i.avgParseTimeMs,
avgFragBufferCreationDelayMs: i.avgBufferCreateMs,
avgPlaylistLoadTimeMs: i.avgPlaylistLoadTimeMs,
avgPlaylistParseTimeMs: i.avgPlaylistParseTimeMs,
avgInitFragAppendMs: i.avgInitFragAppendMs,
avgDataFragAppendMs: i.avgDataFragAppendMs
};
let e = t.storageKeyPrefix;
r && (e += r);
try {
t.storage.set(e, JSON.stringify(i))
} catch (t) {
n.warn(`Error stringifying! Not persisting bandwidth estimates: ${t.message}`)
}
} else n.warn("storage.set is not supported! Not persisting bandwidth estimates")
},
getCombinedEstimate: function(t, e) {
const i = Qe();
let r = {};
if (void 0 === t.storage.get) return i.warn("storage.get is not supported! unable to retreive bandwidth estimates"), this.convertStorageJsonToCombinedEstimate(r);
try {
let e = JSON.parse(t.storage.get(t.bandwidthHistoryStorageKey));
e = null != e && e.expires && e.expires < Date.now() ? null : {
avgLatencyMs: null == e ? void 0 : e.avgLatencyMs,
avgBandwidth: null == e ? void 0 : e.avgBandwidth
}, r = Object.assign(Object.assign({}, r), e)
} catch (t) {
i.warn(`Unable to get persisted bandwidth history: ${t.message}`)
}
let n = t.storageKeyPrefix;
e && (n += e);
try {
const e = JSON.parse(t.storage.get(n));
r = Object.assign(Object.assign({}, r), e)
} catch (t) {
i.warn(`Unable to get persisted bandwidth history: ${t.message}`)
}
return this.convertStorageJsonToCombinedEstimate(r)
},
convertStorageJsonToCombinedEstimate: function(e) {
return {
avgLatencyMs: (null == e ? void 0 : e.avgLatencyMs) || NaN,
avgBandwidth: (null == e ? void 0 : e.avgBandwidth) || NaN,
maxDurationSec: (null == e ? void 0 : e.maxDuration) || NaN,
avgParseTimeMs: (null == e ? void 0 : e.avgFragParseTimeMs) || NaN,
avgBufferCreateMs: (null == e ? void 0 : e.avgFragBufferCreationDelayMs) || NaN,
avgPlaylistLoadTimeMs: (null == e ? void 0 : e.avgPlaylistLoadTimeMs) || NaN,
avgPlaylistParseTimeMs: (null == e ? void 0 : e.avgPlaylistParseTimeMs) || NaN,
avgInitFragAppendMs: (null == e ? void 0 : e.avgInitFragAppendMs) || NaN,
avgDataFragAppendMs: (null == e ? void 0 : e.avgDataFragAppendMs) || NaN
}
},
getBandwidthEstimate: function(e, t) {
const i = this.getCombinedEstimate(e, t),
r = {
avgLatencyMs: null == i ? void 0 : i.avgLatencyMs,
avgBandwidth: null == i ? void 0 : i.avgBandwidth
};
return ne(r.avgLatencyMs) || (r.avgLatencyMs = NaN), ne(r.avgBandwidth) || (r.avgBandwidth = NaN), r
},
getPlaylistEstimate: function(e, t) {
const i = this.getCombinedEstimate(e, t),
r = {
avgPlaylistLoadTimeMs: null == i ? void 0 : i.avgPlaylistLoadTimeMs,
avgPlaylistParseTimeMs: null == i ? void 0 : i.avgPlaylistParseTimeMs
};
return ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = NaN), ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = NaN), r
},
getFragEstimate: function(e, t) {
const i = this.getCombinedEstimate(e, t),
r = {
maxDurationSec: null == i ? void 0 : i.maxDurationSec,
avgParseTimeMs: null == i ? void 0 : i.avgParseTimeMs
};
return ne(r.maxDurationSec) || (r.maxDurationSec = NaN), ne(r.avgParseTimeMs) || (r.avgParseTimeMs = NaN), r
},
getBufferEstimate: function(e, t) {
const i = this.getCombinedEstimate(e, t),
r = {
avgBufferCreateMs: null == i ? void 0 : i.avgBufferCreateMs,
avgInitFragAppendMs: null == i ? void 0 : i.avgInitFragAppendMs,
avgDataFragAppendMs: null == i ? void 0 : i.avgDataFragAppendMs
};
return ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = NaN), ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = NaN), ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = NaN), r
}
};
var Wf = Qf;
class Gf {
constructor(e = 0) {
this._minSamples = e, this._sum = 0, this._max = Number.NEGATIVE_INFINITY, this._numSamples = 0
}
get avg() {
return this._numSamples < this._minSamples ? NaN : this._sum / this._numSamples
}
get max() {
return 0 < this.count ? this._max : NaN
}
get count() {
return this._numSamples
}
reset() {
this._sum = 0, this._numSamples = 0, this._max = Number.NEGATIVE_INFINITY
}
add(e) {
this._sum += e, this._max = Math.max(this._max, e), ++this._numSamples
}
}
class zf extends kl {
constructor(e, t) {
super(e), this.id = t
}
getBandwidthEstimate(e, t) {
var i;
const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.bandwidthEstimate);
if (ne(r.avgBandwidth) && ne(r.avgLatencyMs)) return r;
if (e) {
const i = Qf.getBandwidthEstimate(e, t);
ne(r.avgBandwidth) || (r.avgBandwidth = i.avgBandwidth), ne(r.avgLatencyMs) || (r.avgLatencyMs = i.avgLatencyMs)
}
return r
}
getPlaylistEstimate(e, t) {
var i;
const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.playlistEstimate),
n = e => ne(e.avgPlaylistLoadTimeMs) && ne(e.avgPlaylistParseTimeMs);
if (n(r)) return r;
if (e) {
const i = Qf.getPlaylistEstimate(e, t);
if (ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = i.avgPlaylistLoadTimeMs), ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = i.avgPlaylistParseTimeMs), n(r)) return r;
ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = e.statDefaults.playlistLoadTimeMs), ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = e.statDefaults.playlistParseTimeMs)
}
return r
}
getBufferEstimate(e, t) {
var i;
const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.bufferEstimate),
n = e => ne(e.avgBufferCreateMs) && ne(e.avgDataFragAppendMs) && ne(e.avgInitFragAppendMs);
if (n(r)) return r;
if (e) {
const i = Qf.getBufferEstimate(e, t);
if (ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = i.avgBufferCreateMs), ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = i.avgDataFragAppendMs), ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = i.avgInitFragAppendMs), n(r)) return r;
ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = e.statDefaults.fragBufferCreationDelayMs), ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = e.statDefaults.dataFragAppendMs), ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = e.statDefaults.initFragAppendMs)
}
return r
}
getFragEstimate(e, t) {
var i;
const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.fragEstimate),
n = e => ne(e.maxDurationSec) && ne(e.avgParseTimeMs);
if (n(r)) return r;
if (e) {
const i = Qf.getFragEstimate(e, t);
if (ne(r.maxDurationSec) || (r.maxDurationSec = i.maxDurationSec), ne(r.avgParseTimeMs) || (r.avgParseTimeMs = i.avgParseTimeMs), n(r)) return r;
ne(r.maxDurationSec) || (r.maxDurationSec = e.defaultTargetDuration), ne(r.avgParseTimeMs) || (r.avgParseTimeMs = e.statDefaults.fragParseTimeMs)
}
return r
}
getCombinedEstimate() {
return Object.assign(Object.assign(Object.assign(Object.assign({}, this.getFragEstimate()), this.getPlaylistEstimate()), this.getBufferEstimate()), this.getBandwidthEstimate())
}
get statsEntity() {
return this.getEntity(this.id)
}
get bandwidthSample() {
var e;
return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.bandwidthSample
}
get bandwidthStatus() {
var e;
return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.bandwidthStatus
}
get fragSample() {
var e;
return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.fragSample
}
get bandwidthEstimate$() {
return this.selectEntity(this.id, "bandwidthEstimate")
}
get fragEstimate$() {
return this.selectEntity(this.id, "fragEstimate")
}
get playlistEstimate$() {
return this.selectEntity(this.id, "playlistEstimate")
}
get bufferEstimate$() {
return this.selectEntity(this.id, "bufferEstimate")
}
get bandwidthSample$() {
return this.selectEntity(this.id, ({
bandwidthSample: e
}) => e).pipe(Kp())
}
get fragSample$() {
return this.selectEntity(this.id, ({
fragSample: e
}) => e).pipe(Kp())
}
get playlistSample$() {
return this.selectEntity(this.id, ({
playlistSample: e
}) => e).pipe(Kp())
}
get bufferMetric$() {
return this.selectEntity(this.id, ({
bufferMetric: e
}) => e).pipe(Kp())
}
}
class Xf {
constructor(e) {
this.statsStore = e
}
getQuery() {
return new kl(this.statsStore)
}
getQueryForItem(e) {
return new zf(this.statsStore, e)
}
remove(e) {
this.statsStore.remove(e)
}
removeAll() {
this.statsStore.remove()
}
setBandwidthSample(e) {
this.statsStore.bandwidthSample = e
}
setFragSample(e) {
this.statsStore.fragSample = e
}
setPlaylistSample(e) {
this.statsStore.playlistSample = e
}
setBufferMetric(e) {
this.statsStore.bufferMetric = e
}
setBandwidthEstimate(e) {
this.statsStore.bandwidthEstimate = e
}
setFragEstimate(e) {
this.statsStore.fragEstimate = e
}
setPlaylistEstimate(e) {
this.statsStore.playlistEstimate = e
}
setBufferEstimate(e) {
this.statsStore.bufferEstimate = e
}
}
const Yf = new class extends fl {
constructor() {
super({}, {
name: "stats-store",
producerFn: su
})
}
set statsEntity(e) {
Do("statsStore.set.stats"), al(() => {
this.add(e), this.setActive(e.id)
})
}
set playlistSample(t) {
Do(`stats.set.playlistSample: ${t}`), this.updateActive(e => {
e.playlistSample = t
})
}
set bandwidthSample(t) {
Do(`stats.set.bandwidthSample: ${t}`), this.updateActive(e => {
e.bandwidthSample = t, e.bandwidthStatus.bandwidthSampleCount += 1, e.bandwidthStatus.instantBw = 8e3 * t.loaded / (t.tload - t.trequest)
})
}
set fragSample(t) {
Do(`stats.set.fragSample: ${t}`), this.updateActive(e => {
e.fragSample = t
})
}
set bufferMetric(t) {
Do(`stats.set.bufferMetric: ${t}`), this.updateActive(e => {
e.bufferMetric = t
})
}
set bandwidthEstimate(t) {
Do(`stats.set.bandwidthEstimate: ${t}`), this.updateActive(e => {
e.bandwidthEstimate = t
})
}
set fragEstimate(t) {
Do(`stats.set.fragEstimate: ${t}`), this.updateActive(e => {
e.fragEstimate = t
})
}
set playlistEstimate(t) {
Do(`stats.set.playlistEstimate: ${t}`), this.updateActive(e => {
e.playlistEstimate = t
})
}
set bufferEstimate(t) {
Do(`stats.set.bufferEstimate: ${t}`), this.updateActive(e => {
e.bufferEstimate = t
})
}
};
let Jf = null;
const Zf = e => new zf(Yf, e);
function em(e, t) {
if (e === t) return !0;
if (!e || !t) return !1;
let i = Object.keys(e).length === Object.keys(t).length;
for (const r of Object.keys(e)) i = i && (isNaN(e[r]) && isNaN(t[r]) || e[r] === t[r]);
return i
}
function tm(f, m, g) {
return new $t(e => {
(e => {
const t = Zf(e);
t.hasEntity(e) ? $i(t) : (i = Yf, e = e, Do("stats.loading"), i.setLoading(!0), i.statsEntity = {
id: e,
bandwidthEstimate: {
avgLatencyMs: NaN,
avgBandwidth: NaN
},
bandwidthStatus: {
bandwidthSampleCount: 0,
instantBw: NaN
},
fragEstimate: {
maxDurationSec: NaN,
avgParseTimeMs: NaN
},
playlistEstimate: {
avgPlaylistLoadTimeMs: NaN,
avgPlaylistParseTimeMs: NaN
},
bufferEstimate: {
avgBufferCreateMs: NaN,
avgInitFragAppendMs: NaN,
avgDataFragAppendMs: NaN
}
}, i.setLoading(!1), Do("stats.loaded"));
var i
})(g.itemId);
const t = Zf(g.itemId),
{
fragSample$: i,
playlistSample$: r,
bandwidthSample$: n,
bufferMetric$: s
} = t;
return an(r.pipe(ji(tr), (h = f, p = m, e => e.pipe(tc("statsPlaylistProcessingEpic.in"), sa((e, t) => (e.playlistLoadTimeMs.add(t.playlistLoadTimeMs), e.playlistParseTimeMs.add(t.playlistParseTimeMs), e), {
playlistLoadTimeMs: new Gf(h.minPlaylistCount),
playlistParseTimeMs: new Gf(h.minPlaylistCount)
}), hr(e => ({
avgPlaylistLoadTimeMs: e.playlistLoadTimeMs.avg,
avgPlaylistParseTimeMs: e.playlistParseTimeMs.avg
})), Is(em), Za(e => {
p.setPlaylistEstimate(e)
})))), n.pipe(ji(tr), (u = f, c = m, n => new $t(e => {
let t = new jf(u.bandwidthHistoryWindowSize, u.bandwidthHistoryAggregationMethod, {
avgLatencyMs: NaN,
avgBandwidth: NaN
});
const i = t.estimate$,
r = an(n.pipe(ln(e => e.complete), Za(e => {}), hr(e => ({
trequest: e.trequest,
tfirst: e.tfirst,
tload: e.tload,
bitsDownloaded: 8 * e.loaded
})), tc("statsBandwidthProcessingEpic.in"), La(e => (t.record(e), Ii))), i.pipe(Is(), tc("statsBandwidthProcessingEpic.change"), Za(e => {
c && c.setBandwidthEstimate(e)
}))).subscribe(e);
return () => {
r.unsubscribe(), t.destroy(), t = void 0
}
}))), i.pipe(ji(tr), (l = f, d = m, e => e.pipe(tc("statsFragProcessingEpic.in"), sa((e, t) => (e.durationSec.add(t.durationSec), e.fragParseMs.add(t.parseTimeMs), e), {
durationSec: new Gf,
fragParseMs: new Gf(l.minFragmentCount)
}), hr(e => ({
maxDurationSec: e.durationSec.max,
avgParseTimeMs: e.fragParseMs.avg
})), Is(em), Za(e => d.setFragEstimate(e))))), s.pipe(ji(tr), (a = f, o = m, e => e.pipe(tc("statsBufferMetricProcessingEpic.in"), sa((e, t) => (ne(t.bufferCreationStart) && ne(t.bufferCreationEnd) && e.bufferCreateMs.add(t.bufferCreationEnd - t.bufferCreationStart), ne(t.startInitAppend) && ne(t.endInitAppend) && e.initFragAppendMs.add(t.endInitAppend - t.startInitAppend), ne(t.startDataAppend) && ne(t.endDataAppend) && e.dataFragAppendMs.add(t.endDataAppend - t.startDataAppend), e), {
bufferCreateMs: new Gf,
initFragAppendMs: new Gf,
dataFragAppendMs: new Gf(a.minFragmentCount)
}), hr(e => ({
avgBufferCreateMs: e.bufferCreateMs.avg,
avgInitFragAppendMs: e.initFragAppendMs.avg,
avgDataFragAppendMs: e.dataFragAppendMs.avg
})), Is(em), Za(e => {
o.setBufferEstimate(e)
}))))).pipe($a(Ii)).subscribe(e), () => {
Wf.setCombinedEstimate(f, Object.assign(Object.assign(Object.assign(Object.assign({}, t.getFragEstimate()), t.getPlaylistEstimate()), t.getBufferEstimate()), t.getBandwidthEstimate()), g.serviceName), m.remove(g.itemId)
};
var a, o, l, d, u, c, h, p
})
}
const im = {
isWebkitMediaElement: e => "webkitDroppedFrameCount" in e,
isHtmlVideoElement: e => "getVideoPlaybackQuality" in e,
timeRangeToArray(t) {
const i = [];
for (let e = 0; e < t.length; e++) i.push([t.start(e), t.end(e)]);
return i
}
};
class rm {
constructor(e, t) {
this.hls = e, this.sessionID = t, this.rtcQuery = null, this.accessLogData = this.createAccessLogEntry(), this.accesslog = [], this.errorlog = []
}
destroy() {
this.rtcQuery = null, this.accesslog = [], this.errorlog = [], this.accessLogData = void 0, this.accessLogReporter = void 0
}
setRTCQuery(e) {
this.rtcQuery = e
}
setupReporter(e) {
this.accessLogReporter = {
SessionID: this.sessionID,
ClientName: null == e ? void 0 : e.clientName,
ServiceName: null == e ? void 0 : e.serviceName
}
}
addPlayTime(e) {
var t, e = null === (t = this.rtcQuery) || void 0 === t ? void 0 : t.getEntity(e);
!e || "RTC_STATE_PLAY" === (e = e.sessionControlRecord).state && (this.accessLogData.PlayTimeWC = (this.accessLogData.PlayTimeWC || 0) + e.eventStartTime)
}
updatePlaybackInfo(e, t) {
this.accessLogData.ViFrDr = this.rtcQuery.getEntity(e).sessionControlRecord.droppedVideoFrames || 0
}
updateStallCount(e) {
"RTC_STATE_PLAY" === this.rtcQuery.getEntity(e).sessionControlRecord.state && this.accessLogData.StallCount++
}
updateMediaEngineStallCount(e) {
"RTC_STATE_PLAY" === this.rtcQuery.getEntity(e).sessionControlRecord.state && this.accessLogData.MediaEngineStallCount++
}
updateCanPlay(e) {
this.accessLogData.StartupTime = this.rtcQuery.getEntity(e).sessionControlRecord.eventStartTime
}
updateFragLoaded(e, t, i) {
var r;
i.fragType === gu.Variant ? (this.accessLogData.NetBytes += i.bytes, this.accessLogData.ADT += i.adt, r = this.aggregateFragObserverdBitrate(i, ++this.accessLogData.fragmentCnt, this.accessLogData.NetBytes, this.accessLogData.ADT), this.accessLogData.OBRLast = r.obrLast, this.accessLogData.OBRMean = r.obrMean, this.aggregateFragMinMaxBitrate(this.accessLogData, r.obr), this.hls.realCurrentTime > i.startPTS && !t && this.accessLogData.overdue++, this.hasGap(i.startPTS, i.endPTS, this.accessLogData.lastStartPTS, this.accessLogData.lastEndPTS) && this.addToAccessLog(e), this.accessLogData.startPTS || (this.accessLogData.startPTS = i.startPTS), this.accessLogData.lastStartPTS = i.startPTS, this.accessLogData.lastEndPTS = i.endPTS, this.accessLogData.videoBytes += i.bytes, this.accessLogData.videoDuration += i.duration) : i.fragType === gu.AltAudio && (this.accessLogData.audioBytes += i.bytes, this.accessLogData.audioDuration += i.duration)
}
addToAccessLog(e) {
var t = this.getVariantInfo(e),
i = this.rtcQuery.getEntity(e).sessionControlRecord.curLevelUrl,
r = this.rtcQuery.getEntity(e).playEndedRecord.PlayType;
if (i && "" !== i) {
r = this.translateToAccessLogItem(e, i, t, r);
if (r) {
const n = this.accesslog.length - 20;
0 < n && this.accesslog.splice(0, n), this.accesslog.push(r)
}
this.accessLogData = this.createAccessLogEntry();
e = this.rtcQuery.getEntity(e).switchCompleteRecord.MediaDur;
this.accessLogData.lastMediaDur = e || this.hls.bufferedDuration
}
}
addToErrorLog(e, t) {
var i = null === (r = this.rtcQuery) || void 0 === r ? void 0 : r.getEntity(e);
if (i) {
var r = Number(("mediaError" === t ? i.playErrorRecord : i.nwErrorRecord).ErrCode),
i = i.sessionControlRecord.curLevelUrl,
r = this.translateToErrorLogItem(e, i, {
domain: t,
code: r
});
if (r) {
const e = this.errorlog.length - 20;
0 < e && this.errorlog.splice(0, e), this.errorlog.push(r)
}
}
}
getAccessLog(e) {
var t;
const i = this.accesslog.slice(0),
r = null === (t = this.rtcQuery) || void 0 === t ? void 0 : t.getEntity(e);
if (i && r) {
const t = r.sessionControlRecord.curLevelUrl;
if (t && "" !== t) {
const r = this.getVariantInfo(e),
n = this.translateToAccessLogItem(e, t, r, this.rtcQuery.getEntity(e).playEndedRecord.PlayType);
n && (n["c-provisional-entry"] = !0, i.push(n))
}
}
return i
}
get errorLog() {
return this.errorlog
}
createAccessLogEntry() {
return {
fragmentCnt: 0,
overdue: 0,
startPTS: 0,
obrMax: 0,
obrMin: 0,
audioBytes: 0,
audioDuration: 0,
videoBytes: 0,
videoDuration: 0,
svrAddrChanged: 0,
svrAddr: "",
PlayTimeWC: 0,
ViFrDr: 0,
StallCount: 0,
MediaEngineStallCount: 0,
ADT: 0,
NetBytes: 0,
StartupTime: 0,
OBRMean: 0,
OBRLast: 0
}
}
convertStringObjectToPrimitive(e) {
return e ? "object" == typeof e ? e.toString() : e : ""
}
updateSvrAddrStats(t) {
const i = bu.parseURL(t);
if (i && i.netLoc) {
const t = i.netLoc.indexOf(":");
let e = 0 <= t ? i.netLoc.slice(0, t) : i.netLoc;
e.startsWith("//") && (e = e.slice(2)), this.accessLogData.svrAddr ? e !== this.accessLogData.svrAddr && this.accessLogData.svrAddrChanged++ : this.accessLogData.svrAddrChanged = 0, this.accessLogData.svrAddr = e
}
}
translateToAccessLogItem(e, t, i, r) {
t = this.convertStringObjectToPrimitive(t);
this.updateSvrAddrStats(t);
let n = this.rtcQuery.getEntity(e).switchCompleteRecord.MediaDur;
n = n || this.hls.bufferedDuration, n = n || 0;
const s = {
uri: t,
"s-ip": this.accessLogData.svrAddr,
"s-ip-changes": this.accessLogData.svrAddrChanged,
"sc-wwan-count": -1,
"c-transfer-duration": this.accessLogData.ADT,
bytes: this.accessLogData.NetBytes,
"c-total-media-requests": this.accessLogData.fragmentCnt,
"cs-guid": this.accessLogReporter.SessionID,
"c-start-time": this.accessLogData.startPTS,
"c-startup-time": this.accessLogData.StartupTime,
"c-duration-watched": this.accessLogData.PlayTimeWC / 1e3,
"c-frames-dropped": this.accessLogData.ViFrDr,
"c-stalls": this.accessLogData.StallCount + this.accessLogData.MediaEngineStallCount,
"c-duration-downloaded": this.accessLogData.lastMediaDur ? n - this.accessLogData.lastMediaDur : n,
"c-overdue": this.accessLogData.overdue,
"c-avg-video-bitrate": 8 * this.accessLogData.videoBytes / (this.accessLogData.videoDuration || 1),
"c-observed-max-bitrate": this.accessLogData.obrMax,
"c-observed-min-bitrate": this.accessLogData.obrMin,
"sc-indicated-bitrate": i.bandwidth || 0,
"sc-indicated-avg-bitrate": i.avgBandwidth || 0,
"c-observed-bitrate": this.accessLogData.OBRMean,
"c-switch-bitrate": this.accessLogData.OBRLast,
"c-provisional-entry": !1
};
return s["s-playback-type"] = r, this.accessLogData.audioBytes && (s["c-avg-audio-bitrate"] = 8 * this.accessLogData.audioBytes / (this.accessLogData.audioDuration || 1)), s
}
translateToErrorLogItem(e, t, i) {
t = this.convertStringObjectToPrimitive(t);
return this.updateSvrAddrStats(t), {
date: new Date,
"cs-guid": this.accessLogReporter.SessionID + "-" + e,
uri: t,
"s-ip": this.accessLogData.svrAddr,
status: "" + i.code,
domain: i.domain
}
}
hasGap(e, t, i, r) {
return void 0 !== e && void 0 !== i && (1 < e - r || 1 < i - t)
}
aggregateFragObserverdBitrate(e, t, i, r) {
r = 8 * i / (r / 1e3);
return {
obr: r,
obrLast: 8 * e.bytes / (e.adt / 1e3),
obrMean: r / t
}
}
aggregateFragMinMaxBitrate(e, t) {
(!e.obrMax || t > e.obrMax) && (e.obrMax = t), (!e.obrMin || t < e.obrMin) && (e.obrMin = t)
}
getVariantInfo(e) {
var t = this.rtcQuery.getEntity(e).sessionControlRecord.curLevelUrl,
e = null === (e = this.rtcQuery.getEntity(e).sessionControlRecord.manifestData) || void 0 === e ? void 0 : e.variantList;
return t && e && e[t] ? e[t] : {}
}
}
const nm = (r, e, t, i, n, s) => {
var a, {
absoluteUrl: o,
byteRangeOffset: l,
keyTagInfo: d,
iframe: u,
isInitSegment: c
} = r,
h = o,
p = d["method"],
{
start: o,
end: d
} = l,
t = Lc({
url: h
}, t);
let f, m = o,
g = d,
y = !1,
v = ne(o) || ne(d) ? l : void 0;
if ("AES-128" === p && d && (u || c)) {
const r = d - o;
r % 16 && (g = d + (16 - r % 16)), 0 !== o && (y = !0, m = o - 16), v = {
start: m,
end: g
}
}
return n && ne(r.mediaSeqNum) && r.mediaOptionType === gu.Variant && (f = [], null === (n = t.reportHTTPResponseHeaders) || void 0 === n || n.forEach(function(e) {
Ou.includes(e) ? f.push(e) : Qe().warn({
name: "load-media-fragment"
}, `${e} is not in approved privacy list. Actions required.`)
}), 0 === f.length && (f = void 0)), Rc({
url: h,
byteRangeOffset: v,
checkContentLength: !0,
extendMaxTTFB: s,
collectServerInstanceInfo: f,
onProgress: i,
xhrSetup: e.xhrSetup
}, t).pipe(hr(([e, t, i]) => {
if (y) {
const t = e;
r.keyTagInfo.iv = new Uint8Array(t.slice(0, 16)), e = t.slice(16)
}
return [r, e, t, i]
}), (a = r, e => e.pipe(Vn(e => {
if (e instanceof pc) throw new hc(!1, "Timeout", 0, $.FragmentTimeoutError, !0, a, e.stats);
if (e instanceof oc) throw new hc(!1, e.message, e.code, {
code: e.code,
text: "Fragment Network Error"
}, !1, a);
throw e
}))))
},
sm = {
clearkey: th,
fairplaystreaming: Sc,
playready: Fc,
widevine: Bc
},
am = {
getKeySystemFormat(e) {
e = sm[e];
return e ? e.keyFormatString : ""
},
getKeySystemSecurityLevel(e) {
e = sm[e];
return e ? e.securityLevels : null
}
},
om = {
NONE: "",
"AES-128": "",
"ISO-23001-7": "",
"SAMPLE-AES": "",
"SAMPLE-AES-CTR": ""
},
lm = {
NONE: 0,
"TYPE-0": 1,
"TYPE-1": 2,
"TYPE-2": 3
};
function dm(e) {
return e in lm
}
function um(e) {
return null == e ? 4 : lm[e]
}
const cm = ["SDR", "PQ", "HLG"],
hm = {
afr: "af",
aka: "ak",
amh: "am",
ara: "ar",
arg: "an",
asm: "as",
ava: "av",
ave: "ae",
aym: "ay",
aze: "az",
bam: "bm",
bel: "be",
ben: "bn",
bih: "bh",
bod: "bo",
bos: "bs",
bre: "br",
bul: "bg",
cat: "ca",
ces: "cs",
cha: "ch",
che: "ce",
chu: "cu",
chv: "cv",
cor: "kw",
cos: "co",
cre: "cr",
cym: "cy",
dan: "da",
deu: "de",
div: "dv",
dzo: "dz",
ell: "el",
eng: "en",
epo: "eo",
est: "et",
eus: "eu",
ewe: "ee",
fao: "fo",
fas: "fa",
fin: "fi",
fra: "fr",
fry: "fy",
ful: "ff",
gla: "gd",
gle: "ga",
glg: "gl",
glv: "gv",
grn: "gn",
guj: "gu",
hat: "ht",
heb: "he",
her: "hz",
hin: "hi",
hmo: "ho",
hrv: "hr",
hun: "hu",
hye: "hy",
ibo: "ig",
ido: "io",
iii: "ii",
iku: "iu",
ile: "ie",
ina: "ia",
ind: "id",
isl: "is",
ita: "it",
jav: "jv",
jpn: "ja",
kal: "kl",
kan: "kn",
kas: "ks",
kat: "ka",
kau: "kr",
kaz: "kk",
khm: "km",
kik: "ki",
kin: "rw",
kir: "ky",
kom: "kv",
kon: "kg",
kor: "ko",
kua: "kj",
kur: "ku",
lao: "lo",
lat: "la",
lav: "lv",
lim: "li",
lit: "lt",
ltz: "lb",
lub: "lu",
lug: "lg",
mah: "mh",
mal: "ml",
mar: "mr",
mkd: "mk",
mlg: "mg",
mlt: "mt",
mol: "mo",
mon: "mn",
mri: "mi",
msa: "ms",
mya: "my",
nav: "nv",
nbl: "nr",
nde: "nd",
ndo: "ng",
nep: "ne",
nld: "nl",
nno: "nn",
nob: "nb",
nya: "ny",
oci: "oc",
oji: "oj",
ori: "or",
orm: "om",
oss: "os",
pan: "pa",
pli: "pi",
pol: "pl",
por: "pt",
pus: "ps",
que: "qu",
roh: "rm",
ron: "ro",
run: "rn",
rus: "ru",
san: "sa",
sin: "si",
slk: "sk",
slv: "sl",
sme: "se",
snd: "sd",
som: "so",
spa: "es",
sqi: "sq",
srd: "sc",
srp: "sr",
sun: "su",
swa: "sw",
swe: "sv",
tah: "ty",
tam: "ta",
tat: "tt",
tel: "te",
tgk: "tg",
tgl: "tl",
tha: "th",
tir: "ti",
ton: "to",
tuk: "tk",
tur: "tr",
uig: "ug",
ukr: "uk",
urd: "ur",
uzb: "uz",
ven: "ve",
vie: "vi",
wln: "wa",
yid: "yi",
zha: "za",
zho: "zh"
},
pm = {
isLanguageCode: e => e in hm,
shortenLanguageCode(e) {
let t;
var i, r;
return e && (r = 0 <= (i = e.indexOf("-")) ? e.slice(0, i) : e, pm.isLanguageCode(r) && (t = hm[r]), t = t || r, 0 < i && (t += "-" + e.slice(i + 1))), t
}
},
fm = {
getRichestVideoCodec(e) {
if (e && e.length) {
e = e.sort((e, t) => qp(t) - qp(e));
return e && e.length ? e[0] : void 0
}
},
getRichestAudioCodec(e) {
if (e && e.length) {
e = e.sort((e, t) => jp(t) - jp(e));
return e && e.length ? e[0] : void 0
}
},
getRichestChannelLayoutForGroupId(t, i) {
if (t && i && i.length) {
let e;
const r = i.filter(e => e.groupId === t);
if (r && r.length) {
const t = r.sort((e, t) => be.getChannelCount(t.channels) - be.getChannelCount(e.channels));
t && t.length && (e = t[0].channels)
}
return e
}
}
};
function mm(e) {
return new R(L, "steeringManifestParsingError", !1, e, $.FormatError)
}
class gm {
constructor(e) {
this._url = null, this._programDateTime = null, this._byteRange = null, this.relurl = null, this.baseurl = null, this.isInitSegment = !1, this.mediaSeqNum = NaN, this.cc = NaN, this.iframe = !1, this.bitrate = NaN, this.start = NaN, this.duration = NaN, this.lastByteRangeEndOffset = NaN, this.inheritQuery = e, this.tagList = new Array, this.iframe = !1
}
getMediaFragment(e, t, i) {
const r = {
mediaOptionType: i,
absoluteUrl: this.url,
start: this.start,
duration: this.duration,
mediaSeqNum: this.mediaSeqNum,
discoSeqNum: this.cc,
mediaOptionId: t,
itemId: e,
isLastFragment: !1,
isInitSegment: this.isInitSegment
};
return null !== (e = this.byteRange) && void 0 !== e && e.length && (r.byteRangeOffset = {
start: this.byteRangeStartOffset,
end: this.byteRangeEndOffset
}), this.iframe && (r.iframe = this.iframe), this.levelkey && (r.keyTagInfo = this.levelkey), this.programDateTime && (r.programDateTime = this.programDateTime), r
}
get url() {
return !this._url && this.relurl && this.baseurl && (this._url = bu.buildAbsoluteURL(this.baseurl, this.relurl, {
alwaysNormalize: !0,
inheritQuery: this.inheritQuery
})), this._url
}
set url(e) {
this._url = e
}
get programDateTime() {
return !this._programDateTime && this.rawProgramDateTime && (this._programDateTime = new Date(Date.parse(this.rawProgramDateTime))), this._programDateTime
}
get byteRange() {
if (!this._byteRange) {
const i = new Array(2);
var e, t;
this.rawByteRange && (1 === (e = this.rawByteRange.split("@", 2)).length ? (t = this["lastByteRangeEndOffset"], i[0] = t || 0) : i[0] = parseInt(e[1]), i[1] = parseInt(e[0]) + i[0]), this._byteRange = i
}
return this._byteRange
}
get byteRangeStartOffset() {
return this.byteRange[0]
}
get byteRangeEndOffset() {
return this.byteRange[1]
}
get rangeString() {
return 0 <= this.start && 0 <= this.duration ? `${this.start.toFixed(2)}-${(this.start+this.duration).toFixed(2)}` : "N/A"
}
get fragTag() {
return `sn/cc/levelId: ${this.mediaSeqNum}/${this.cc}`
}
}
const ym = {
parseMediaCharacteristics: e => e ? e.split(/\s*,\s*/) : new Array,
addMediaToSelectionArray(e, t, i) {
if (void 0 === e) return -1;
const r = e.MediaSelectionGroupOptions;
let n = r.find(e => e.MediaSelectionOptionsMediaType === t.mediaType && e.MediaSelectionOptionsName === t.name && e.MediaSelectionOptionsExtendedLanguageTag === t.lang);
return n || (n = {
MediaSelectionOptionsMediaType: t.mediaType,
MediaSelectionOptionsExtendedLanguageTag: t.lang,
MediaSelectionOptionsIsDefault: t.default,
MediaSelectionOptionsName: t.name,
MediaSelectionOptionsPersistentID: i,
MediaSelectionOptionsTaggedMediaCharacteristics: t.characteristics
}, t.mediaType === Su.SUBTITLE && (n.MediaSelectionOptionsDisplaysNonForcedSubtitles = t.forced ? vu.NO : vu.YES), i++, r.push(n)), t.persistentID = n.MediaSelectionOptionsPersistentID, i
},
addDefaultClosedCaptionOption(e, t, i, r) {
e = {
itemId: e,
mediaOptionType: gu.Subtitle,
id: 0,
mediaOptionId: "cc1_" + Zl(),
mediaType: Su.CLOSEDCAPTION,
inStreamID: "CC1",
groupId: "cc",
name: "English-CC",
type: "CLOSED-CAPTIONS",
default: !1,
autoselect: !1,
forced: !1,
lang: "en",
characteristics: ["public.accessibility.transcribes-spoken-dialog", "public.accessibility.describes-music-and-sound"],
persistentID: r
};
t.push(e), ym.addMediaToSelectionArray(i, e, r)
}
},
vm = {
BANDWIDTH: NaN,
"AVERAGE-BANDWIDTH": NaN
},
Sm = {
"TIME-OFFSET": NaN,
"FRAME-RATE": NaN,
SCORE: NaN,
"PLANNED-DURATION": NaN,
DURATION: NaN
},
bm = /^(\d+)x(\d+)$/,
Tm = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g;
class Em {
constructor(e) {
this.validTags = e
}
isKey(e) {
return e in this.validTags
}
trySetValue(e, t, i) {
return !!this.isKey(e) && (i[e] = this.parseFunc(t), !0)
}
}
class Im {
static parseTags(t) {
let i;
var r = {};
if (!t) return r;
for (Tm.lastIndex = 0; null !== (i = Tm.exec(t));) {
const t = i[1].toUpperCase();
let e = i[2];
0 === e.indexOf('"') && e.lastIndexOf('"') === e.length - 1 && (e = e.slice(1, -1));
for (const i of Im.tagParsers)
if (i.trySetValue(t, e, r)) break
}
return r
}
}
Im.tagParsers = [new class extends Em {
parseFunc(e) {
return e
}
}({
NAME: "",
TYPE: "",
DEFAULT: "",
AUTOSELECT: "",
FORCED: "",
LANGUAGE: "",
URI: "",
AUDIO: "",
"VIDEO-RANGE": "",
"CLOSED-CAPTIONS": "",
CODECS: "",
BYTERANGE: "",
"INSTREAM-ID": "",
"GROUP-ID": "",
CHANNELS: "",
CHARACTERISTICS: "",
KEYFORMAT: "",
KEYFORMATVERSIONS: "",
"DATA-ID": "",
VALUE: "",
METHOD: "",
"HDCP-LEVEL": "",
"ALLOWED-CPC": "",
SUBTITLES: "",
ID: "",
CLASS: "",
"START-DATE": "",
"END-DATE": "",
"END-ON-NEXT": "",
"SERVER-URI": "",
"PATHWAY-ID": ""
}), new class extends Em {
parseFunc(e) {
e = parseInt(e);
return e > Number.MAX_SAFE_INTEGER ? 1 / 0 : e
}
}(vm), new class extends Em {
constructor() {
super(...arguments), this.parseFunc = parseFloat
}
}(Sm), new class extends Em {
parseFunc(e) {
let t = (e || "0x").slice(2);
t = (1 & t.length ? "0" : "") + t;
const i = new Uint8Array(t.length / 2);
for (let e = 0; e < t.length / 2; e++) {
var r = parseInt(t.slice(2 * e, 2 * e + 2), 16);
if (!ne(r)) return;
i[e] = r
}
return i
}
}({
IV: null
}), new class extends Em {
parseFunc(e) {
e = bm.exec(e);
let t;
return null !== e && (t = {
width: parseInt(e[1], 10),
height: parseInt(e[2], 10)
}), t
}
}({
RESOLUTION: null
})];
const wm = {
ExtractVariableParameter: /{\$(.*?)}/g,
LevelPlaylistFast: /#EXTINF:(\d*(?:\.\d+)?)(?:,(.*))?|(?!#)(\S.+)|#EXT-X-BYTERANGE: *(.+)|#EXT-X-PROGRAM-DATE-TIME:(.+)|#EXT-X-BITRATE:(.+)|#EXT-X-DATERANGE:(.+)|#.*/g,
LevelPlaylistSlow: /(?:(?:#(EXTM3U))|(?:#EXT-X-(PLAYLIST-TYPE):(.+))|(?:#EXT-X-(MEDIA-SEQUENCE): *(\d+))|(?:#EXT-X-(TARGETDURATION): *(\d+))|(?:#EXT-X-(KEY):(.+))|(?:#EXT-X-(START):(.+))|(?:#EXT-X-(ENDLIST))|(?:#EXT-X-(DISCONTINUITY-SEQ)UENCE:(\d+))|(?:#EXT-X-(DIS)CONTINUITY))|(?:#EXT-X-(VERSION):(\d+))|(?:#EXT-X-(MAP):(.+))|(?:#EXT-X-(I-FRAMES)-ONLY)|(?:#EXT-X-(DEFINE):(.+))|(?:(#)(.*):(.*))|(?:(#)(.*))(?:.*)\r?\n?/,
MasterPlaylist: /#EXT-X-STREAM-INF:([^\n\r]*)[\r\n]+([^\r\n]+)|#EXT-X-I-FRAME-STREAM-INF:([^\r\n]+)|#EXT-X-DEFINE:([^\n\r]*)|#EXT-X-CONTENT-STEERING:([^\n\r]*)/g,
MasterPlaylistAlternateMedia: /#EXT-X-MEDIA:(.*)/g,
SessionData: /#EXT-X-SESSION-DATA[^:]*:(.*)/g,
SessionKeys: /#EXT-X-SESSION-KEY:([^\n\r]*)/g,
VARIABLE_PLAYLIST_REGEX: /(NAME|VALUE)=\"(.*)\",(NAME|VALUE)=\"(.*)\"|(IMPORT)=\"(.*)\"/
};
function Am(e, t, i) {
return cu.buildAbsoluteURL(t, e, {
alwaysNormalize: !0,
inheritQuery: i
})
}
class Om {
static isValidPlaylist(e) {
return 0 === e.indexOf("#EXTM3U")
}
static isMediaPlaylist(e) {
return 0 < e.indexOf("#EXTINF:") || 0 < e.indexOf("#EXT-X-PLAYLIST-TYPE:")
}
static replaceVariables(e, t) {
let i, r = !1;
return e && t && (i = e.replace(wm.ExtractVariableParameter, e => {
wm.ExtractVariableParameter.lastIndex = 0;
e = wm.ExtractVariableParameter.exec(e)[1];
if (e && t.hasOwnProperty(e)) return t[e];
r = !0
})), {
updatedString: i,
error: r
}
}
static parseDecryptData(e, t, i) {
const r = Im.parseTags(e),
n = (e = r.METHOD) && e in om ? r.METHOD : null;
e = null !== (e = r.KEYFORMAT) && void 0 !== e ? e : null;
if (n && Om.shouldSelectKeyTag(e, n, i)) {
const s = r.URI,
i = r.IV || null;
if (s && r.IV && !i) {
const s = new R(L, _, !0, `Invalid IV: ${r.IV}`, $.PlaylistErrorInvalidEntry);
throw s.url = t, s
}
const a = s ? cu.buildAbsoluteURL(t, s, {
alwaysNormalize: !0
}) : t,
o = (r.KEYFORMATVERSIONS || "1").split("/").map(Number).filter(isFinite);
return new zc(n, a, i, e, o)
}
}
static shouldSelectKeyTag(e, t, i) {
return "AES-128" === t || "NONE" === t || null == i || e === am.getKeySystemFormat(i)
}
static optOutClosedCaption(t) {
let i = !1,
r = !1;
if (t)
for (let e = 0; e < t.length; ++e) {
const n = t[e];
if (n.videoCodec && ((r = !0) !== n.iframes && n.closedcaption && "none" === n.closedcaption.toLowerCase())) {
i = !0;
break
}
}
return !r || i
}
static parseRootPlaylistAlternateMediaOptions(a, o, l, d, u, c) {
let h, p;
var f = {
MediaSelectionGroupAllowEmptySelection: 1,
MediaSelectionGroupMediaCharacteristics: ["public.audible"],
MediaSelectionGroupMediaType: Su.AUDIO,
MediaSelectionGroupOptions: []
},
m = {
MediaSelectionGroupAllowEmptySelection: 1,
MediaSelectionGroupMediaCharacteristics: ["public.legible"],
MediaSelectionGroupMediaType: Su.SUBTITLE,
MediaSelectionGroupOptions: []
},
g = {
videoAlternateOptions: [],
audioAlternateOptions: [],
subtitleAlternateOptions: [],
audioMediaSelectionGroup: f,
subtitleMediaSelectionGroup: m
};
let y = 0;
for (wm.MasterPlaylistAlternateMedia.lastIndex = 0; null != (h = wm.MasterPlaylistAlternateMedia.exec(o));) {
const o = Om.replaceVariables(h[1], c);
if (o.error) {
p = new R(L, N, !0, $.PlaylistErrorInvalidEXTXDEFINE.text, $.PlaylistErrorInvalidEXTXDEFINE);
break
}
var v = Im.parseTags(o.updatedString);
let e, t, i, r = Su.UNKNOWN;
const S = ym.parseMediaCharacteristics(v.CHARACTERISTICS),
b = v["GROUP-ID"],
T = v.CHANNELS;
let n, s = null;
switch (v.TYPE) {
case "VIDEO":
r = Su.VIDEO, t = g.videoAlternateOptions;
break;
case "AUDIO":
r = Su.AUDIO, s = gu.AltAudio, t = g.audioAlternateOptions, i = f;
const a = d.find(e => e.audioGroupId === b);
n = a ? a.audioCodecList : [];
break;
case "SUBTITLES":
r = Su.SUBTITLE, s = gu.Subtitle, t = g.subtitleAlternateOptions, i = m;
break;
case "CLOSED-CAPTIONS":
r = Su.CLOSEDCAPTION, s = gu.Subtitle, e = v["INSTREAM-ID"], t = g.subtitleAlternateOptions, i = m
}
const E = {
itemId: a,
mediaOptionType: s,
mediaType: r,
groupId: b,
channels: T,
groupCodecList: n,
name: v.NAME,
type: v.TYPE,
default: "YES" === v.DEFAULT,
autoselect: "YES" === v.AUTOSELECT,
forced: "YES" === v.FORCED,
characteristics: S,
persistentID: y,
id: t ? t.length : 0,
mediaOptionId: `${v.NAME}_${b}_${y}`,
lang: pm.shortenLanguageCode(v.LANGUAGE)
};
v.URI && (E.url = Am(v.URI, l, u)), E.name || (E.name = E.lang, E.mediaType === Su.CLOSEDCAPTION && (E.name += " CC")), E.mediaType === Su.CLOSEDCAPTION && e && (E.inStreamID = e), t && (E.id = t.length, t.push(E)), y = ym.addMediaToSelectionArray(i, E, y)
}
return 0 !== g.subtitleAlternateOptions.length || Om.optOutClosedCaption(d) || ym.addDefaultClosedCaptionOption(a, g.subtitleAlternateOptions, m, y), {
alternateMediaInfo: g,
playlistParsingError: p
}
}
static parseMediaOptionPlaylist(e, t, i = !0, r, n, s, a, o, l, d = 0, u = !1) {
var c;
let h = 0,
p = 0;
const f = {
itemId: s,
mediaOptionId: a,
mediaOptionType: o,
type: "",
version: 0,
url: t,
initSegments: {},
fragments: [],
liveOrEvent: !0,
startSN: 0,
endSN: 0,
iframesOnly: u,
targetduration: 0,
totalduration: 0,
averagetargetduration: 0,
ptsKnown: !1
};
let m, g, y, v = new zc("NONE", t, null, null, null),
S = !1,
b = !1,
T = 0,
E = null,
I = new gm(i),
w = 0;
const A = {};
let O, k, C, D = !0,
M = !0;
wm.LevelPlaylistFast.lastIndex = 0;
for (var x = () => new R(L, _, !0, "Invalid key system preference for the playlist", $.IncompatibleAsset); null !== (m = wm.LevelPlaylistFast.exec(e));) {
const e = m[1];
if (e) {
I.duration = parseFloat(e);
const t = (" " + m[2]).slice(1);
I.title = t || null, I.tagList.push(t ? ["INF", e, t] : ["INF", e])
} else if (m[3]) {
if (ne(I.duration)) {
const e = h++;
if (I.start = p + d, I.levelkey = v, b && !S) {
k = x();
break
}
if (S = !1, b = !1, I.mediaSeqNum = e, I.cc = T, I.iframe = f.iframesOnly, I.baseurl = t, (O = Om.replaceVariables((" " + m[3]).slice(1), A)).error) {
k = new R(L, N, !0, $.PlaylistErrorInvalidEXTXDEFINE.text, $.PlaylistErrorInvalidEXTXDEFINE);
break
}
if (I.relurl = O.updatedString, I.bitrate = ne(I.byteRangeEndOffset) ? 8 * (I.byteRangeEndOffset - I.byteRangeStartOffset) / I.duration : w, null != y) {
I.rawProgramDateTime = y, I.tagList.push(["PROGRAM-DATE-TIME", I.rawProgramDateTime]);
const e = I.programDateTime.getTime();
f.programDateTimeMap = null !== (c = f.programDateTimeMap) && void 0 !== c ? c : {}, f.programDateTimeMap[e] = I.mediaSeqNum, f.dateMediaTimePairs = null !== (c = f.dateMediaTimePairs) && void 0 !== c ? c : [], f.dateMediaTimePairs.push([e, I.start]), y = void 0
}
if (f.fragments.push(I.getMediaFragment(s, a, o)), E = I, p += I.duration, D || !f.initSegments[T] || M)
if (f.iframesOnly && 0 < I.byteRangeStartOffset && !f.initSegments[T] && !M) {
const e = new gm(i);
if (e.url = I.url, e.rawByteRange = Math.min(I.byteRangeStartOffset, 1316) + "@0", e.baseurl = t, e.isInitSegment = !0, e.cc = T, e.levelkey = v, e.iframe = !0, b && !S) {
k = x();
break
}
S = !1, b = !1, f.initSegments[T] = e.getMediaFragment(s, a, o)
} else C && (C.discoSeqNum = T, f.initSegments[T] = C);
D = !1, M = !1, I = new gm(i)
}
} else if (m[4]) {
if (I.rawByteRange = (" " + m[4]).slice(1), E) {
const e = E.byteRangeEndOffset;
e && (I.lastByteRangeEndOffset = e)
}
} else if (m[5]) y = (" " + m[5]).slice(1);
else if (m[6]) {
const e = parseInt(m[6]);
ne(e) && (w = 1e3 * e)
} else if (m[7]) {
const e = m[7],
t = Im.parseTags(e);
t.ID && (f.daterangeTags || (f.daterangeTags = {}), f.daterangeTags[t.ID] = t)
} else {
for (m = m[0].match(wm.LevelPlaylistSlow), g = 1; g < m.length && void 0 === m[g]; g++);
const e = Om.replaceVariables((" " + m[g + 1]).slice(1), A),
l = Om.replaceVariables((" " + m[g + 2]).slice(1), A);
if (e.error || l.error) {
k = new R(L, N, !0, $.PlaylistErrorInvalidEXTXDEFINE.text, $.PlaylistErrorInvalidEXTXDEFINE);
break
}
const d = e.updatedString,
u = l.updatedString;
switch (m[g]) {
case "#":
I.tagList.push(u ? [d, u] : [d]);
break;
case "PLAYLIST-TYPE":
f.type = d.toUpperCase(), "VOD" === f.type && (f.liveOrEvent = !1);
break;
case "MEDIA-SEQUENCE":
0 === f.fragments.length && (h = f.startSN = parseInt(d));
break;
case "TARGETDURATION":
f.targetduration = parseFloat(d);
break;
case "VERSION":
f.version = parseInt(d);
break;
case "EXTM3U":
break;
case "ENDLIST":
f.liveOrEvent = !1;
break;
case "DIS":
T++, I.tagList.push(["DIS"]), D = !0;
break;
case "DISCONTINUITY-SEQ":
T = parseInt(d);
break;
case "KEY":
const e = d;
if (b = !0, !S) {
try {
v = Om.parseDecryptData(e, t, r)
} catch (e) {
k = e
}
v && (S = !0)
}
break;
case "START":
const l = d,
P = Im.parseTags(l)["TIME-OFFSET"];
ne(P) && (f.startTimeOffset = P);
break;
case "I-FRAMES":
f.iframesOnly = !0;
break;
case "MAP":
const c = Im.parseTags(d);
if (I.relurl = c.URI, I.rawByteRange = c.BYTERANGE, I.baseurl = t, I.isInitSegment = !0, I.levelkey = v, b && !S) {
k = x();
break
}
S = !1, b = !1, C = I.getMediaFragment(s, a, o), M = !0, I = new gm(i);
break;
case "DEFINE":
const p = wm.VARIABLE_PLAYLIST_REGEX.exec(d),
m = "NAME" === p[1] ? p[2] : p[4],
g = "VALUE" === p[1] ? p[2] : p[4],
y = p[5],
N = p[6];
if (m || g || "IMPORT" !== y || !n.hasOwnProperty(N)) {
if (!m || y || p[1] === p[3] || A.hasOwnProperty(m)) {
k = new R(L, _, !0, $.PlaylistErrorMissingImportReference.text, $.PlaylistErrorMissingImportReference);
break
}
A[m] = g
} else A[N] = n[N]
}
}
}
return I = E, I && !I.relurl && (f.fragments.pop(), p -= I.duration), !f.liveOrEvent && 0 < f.fragments.length && (f.fragments[f.fragments.length - 1].isLastFragment = !0), f.totalduration = p, f.averagetargetduration = p / f.fragments.length, f.endSN = h - 1, {
mediaOptionDetails: f,
playlistParsingError: k
}
}
static parseRootPlaylist(t, e, i, r) {
const n = [],
s = {};
let a, o, l, d, u = null,
c = !0;
for (wm.MasterPlaylist.lastIndex = 0; null != (a = wm.MasterPlaylist.exec(e));)
if (a[4]) {
a = wm.VARIABLE_PLAYLIST_REGEX.exec(a[4]);
const t = "NAME" === a[1] ? a[2] : a[4],
e = "VALUE" === a[1] ? a[2] : a[4],
i = a[5];
if (!t || s.hasOwnProperty(t) || i || a[1] === a[3]) {
d = new R(L, _, !0, $.PlaylistErrorInvalidEXTXDEFINE.text, $.PlaylistErrorInvalidEXTXDEFINE);
break
}
s[t] = e
} else if (a[5]) {
const t = Om.replaceVariables(a[5], s);
if (t.error) {
d = new R(L, _, !0, $.PlaylistErrorInvalidEXTXDEFINE.text, $.PlaylistErrorInvalidEXTXDEFINE);
break
}
const e = Im.parseTags(t.updatedString);
if ("string" != typeof e["SERVER-URI"]) {
d = new R(L, _, !0, $.PlaylistErrorInvalidSERVERURI.text, $.PlaylistErrorInvalidSERVERURI);
break
}
if (null != e["PATHWAY-ID"] && "string" != typeof e["PATHWAY-ID"]) {
d = new R(L, _, !0, $.PlaylistErrorInvalidPATHWAYID.text, $.PlaylistErrorInvalidPATHWAYID);
break
}
u = {
serverURI: Am(e["SERVER-URI"], i, !1),
initPathwayID: e["PATHWAY-ID"] || "."
}
} else {
l = Om.replaceVariables(a[1] || a[3], s);
const e = Im.parseTags(l.updatedString);
if (o = Om.replaceVariables(a[2] || e.URI, s), l.error || o.error) {
d = new R(L, _, !0, $.PlaylistErrorInvalidEXTXDEFINE.text, $.PlaylistErrorInvalidEXTXDEFINE);
break
}
if (void 0 !== e.SCORE && !ne(e.SCORE) || e.SCORE < 0) {
d = new R(L, _, !0, $.PlaylistErrorInvalidSCORE.text, $.PlaylistErrorInvalidSCORE), c = !1;
break
}
c && void 0 === e.SCORE && (c = !1);
const u = e.BANDWIDTH,
p = e["AVERAGE-BANDWIDTH"],
f = p || u,
m = null !== (h = e["VIDEO-RANGE"]) && void 0 !== h ? h : "SDR";
if (null == (h = m) || !cm.includes(h)) continue;
const g = {
itemId: t,
mediaOptionId: `level_${(f||0)+n.length%1e3/1e3}`,
mediaOptionType: gu.Variant,
attrs: e,
url: Am(o.updatedString, i, r),
name: e.NAME,
audioGroupId: e.AUDIO,
subtitleGroupId: e.SUBTITLES,
iframes: !!a[3],
bandwidth: u,
avgBandwidth: p,
bitrate: f,
videoRange: m,
frameRate: e["FRAME-RATE"],
allowedCPCMap: Om.parseAllowedCPC(e["ALLOWED-CPC"]),
closedcaption: e["CLOSED-CAPTIONS"],
levelCodec: e.CODECS,
score: e.SCORE,
pathwayID: e["PATHWAY-ID"] || "."
},
y = e["HDCP-LEVEL"];
dm(y) && (g.hdcpLevel = y);
var h = e.RESOLUTION;
if (h && (g.width = h.width, g.height = h.height), e.CODECS) {
g.videoCodecList = new Array, g.audioCodecList = new Array;
const t = e.CODECS.split(/[ ,]+/),
i = t["length"];
for (let e = 0; e < i; e++) {
const i = t[e];
switch (i.slice(0, 4)) {
case "avc1":
g.videoCodec = be.avc1toavcoti(i), g.videoCodecList.push(g.videoCodec);
break;
case "avc3":
case "dvav":
case "dva1":
case "hev1":
case "hvc1":
case "dvh1":
case "dvhe":
case "vp09":
g.videoCodec = i, g.videoCodecList.push(g.videoCodec);
break;
default:
g.audioCodec = i, g.audioCodecList.push(g.audioCodec)
}
}
1 < g.audioCodecList.length && (g.audioCodec = fm.getRichestAudioCodec(g.audioCodecList)), 1 < g.videoCodecList.length && (g.videoCodec = fm.getRichestVideoCodec(g.videoCodecList))
}
if (null != (d = "string" != typeof(h = g.pathwayID) ? mm("invalid steering manifest PATHWAY-PRIORITY list item data type") : /^[\w\-\.]+$/.test(h) ? void 0 : mm("steering manifest contains invalid pathway ID: " + h))) break;
let cpc = g.allowedCPCMap ? JSON.stringify(g.allowedCPCMap) : "null";
if (!cpc.includes("WIDEVINE_HARDWARE") && !g.url.includes('trickPlay') && !g.videoCodec.includes("hvc1"))
n.push(g)
}
try{
// console.log(n, window.screen.width)
let ok = (n.map( function(item){return{height : item.height, content: item}}));
let screenHeight = (app.cfg.visual.videoRes ?? window.screen.height) ;
ok.sort(function (a, b) {
return a.height - b.height;
});
for (var i = 0; i < ok.length; i++){
if (ok[i].height > screenHeight){
if (i == 0){n.splice(0,n.length);n.push(ok[i].content)}
else{n.splice(0,n.length);n.push(ok[i-1].content)}
console.log('selected' , n[0].height)
break;
}
}
if (n.length > 1){
n.splice(0,n.length - 1);
}
// console.log(n)
// console.log(ok)
} catch (e){ console.log(e)}
return {
variantMediaOptions: n,
contentSteeringOption: u,
masterVariableList: s,
playlistParsingError: d,
scoreAvailable: c
}
}
static parseAllowedCPC(e) {
if ("string" != typeof e) return null;
const n = {};
return e.split(",").forEach(e => {
const t = e.split(":");
let i, r;
if (2 === t.length) i = t[0].trim(), r = t[1].trim();
else {
if (!(2 < t.length)) return;
r = t[t.length - 1].trim(), t.pop(), i = t.join(":")
}
if (!(i in n)) {
let e = new Array;
"" !== r && (e = r.split("/").map(e => e.trim())), n[i] = e
}
}), n
}
static parseSessionKeys(e, t, i) {
var r;
const n = [];
for (wm.SessionData.lastIndex = 0; r = wm.SessionKeys.exec(e);) try {
const e = Om.parseDecryptData(r[1], t, i);
e && e.isEncrypted && n.push(e)
} catch (e) {}
return n
}
static parseSessionData(e, t) {
var i;
const r = [],
n = new Set;
for (wm.SessionData.lastIndex = 0; null != (i = wm.SessionData.exec(e));) {
const e = Im.parseTags(i[1]);
e.LANGUAGE = pm.shortenLanguageCode(e.LANGUAGE);
const t = e.LANGUAGE ? e["DATA-ID"] + "|" + e.LANGUAGE : void 0;
"DATA-ID" in e ? t && n.has(t) || ("com.apple.hls.other-tags" === e["DATA-ID"] && (e.VALUE = function(t) {
let i;
try {
i = JSON.parse(qc.base64DecodeToStr(t))
} catch (e) {
i = t
}
return i
}(e.VALUE)), r.push(e), t && n.add(t)) : Qe().error(`Error processing DATA-ID ${e["DATA-ID"]} and LANGUAGE ${e.LANGUAGE}`)
}
return {
itemList: r,
baseUrl: t
}
}
}
var km, Cm, Dm, Mm, xm, Pm, Rm = Om;
const Lm = (e, t, i) => {
i = Object.assign(Object.assign({}, e), {
method: "GET",
responseType: "text",
extendMaxTTFB: i
});
return Tu(i.url) ? Pc().load(i, t).pipe(hr(e => ({
responseText: e.data.response.data.toString(),
responseURL: e.data.response.uri,
stats: e.stats
}))) : Cc(i, t).pipe(hr(([e, t]) => ({
responseText: e.responseText,
responseURL: e.responseURL,
stats: t
})))
},
_m = (e, n, t, i, s, a, o, l, r) => {
const {
url: d,
itemId: u,
mediaOptionId: c,
mediaOptionType: h,
iframes: p = !1
} = e, f = Lc(e, i);
return Lm({
url: d,
xhrSetup: t.xhrSetup
}, f, r).pipe(hr(({
responseText: e,
responseURL: t,
stats: i
}) => {
t || (s.warn("Missing response url. Reusing request url as base url"), t = d);
var r = performance.now(),
e = Om.parseMediaOptionPlaylist(e, t, !0, a, l, u, c, h, s, n, p);
Nc(e.mediaOptionDetails);
var t = performance.now(),
e = e["mediaOptionDetails"],
r = {
playlistLoadTimeMs: i.tload - i.trequest,
playlistParseTimeMs: t - r
};
return o.setPlaylistSample(r), {
mediaOptionDetails: e,
stats: i
}
}), (m = h, g = c, y = d, e => e.pipe(Vn(e => {
if (e instanceof pc) throw new uc(!1, "Timeout", 0, $.PlaylistTimeoutError, !0, m, g, y);
if (e instanceof oc) throw new uc(!1, e.message, e.code, {
code: e.code,
text: "Playlist Network Error"
}, !1, m, g, y);
throw e
}))));
var m, g, y
},
Nm = (f, e, m, t, g) => $i(e).pipe(La(e => {
const {
keyTagInfo: t,
isInitSegment: i,
iframe: r,
byteRangeOffset: n
} = f, s = t["method"], {
start: a,
end: o
} = n;
if ("AES-128" !== s) return $i(e); {
!t.uri || t.iv || t.format && "identity" !== t.format || (t.iv = function(t) {
const i = new Uint8Array(16);
for (let e = 12; e < 16; e++) i[e] = t >> 8 * (15 - e) & 255;
return i
}(f.mediaSeqNum));
const n = e,
s = t.key.buffer,
l = t.iv.buffer,
d = o && (r || i) ? o - a : void 0,
u = !m.enableWebCrypto || !!d,
c = s.slice(0),
h = l.slice(0),
p = {
useJSCrypto: u,
plainTextLength: d
};
return g.decrypt(c, h, "AES-CBC", n, p)
}
}));
function Fm(e, t) {
var i = e.fragments,
r = t.mediaSeqNum - e.startSN;
return 0 <= r && r < e.fragments.length && $p(t, i[r])
}
function Bm(t, r, n, s, a = !1, o = !1) {
if (Fm(t, r)) {
var l = r.mediaSeqNum - t.startSN;
let i = t.fragments,
e = i[l];
var {
startDtsTs: d,
startPts: u,
endPts: r
} = r;
a && (i = t.fragments = t.fragments.slice(), e = i[l] = Object.assign({}, e)), e.startDtsTs = d, e.startPts = u, e.endPts = r, !s && void 0 === e.isIframeStart || (e.isIframeStart = s), e.start = n, e.duration = b(r, u);
for (let e = l, t = !0; 0 < e && (o || t); e--) t = Um(i, e, e - 1, s, u.timescale, a);
for (let e = l, t = !0; e < i.length - 1 && (o || t); e++) t = Um(i, e, e + 1, s, u.timescale, a);
l = i[i.length - 1];
t.totalduration = l.start + l.duration - i[0].start, t.ptsKnown = !0
}
}
function Um(e, t, i, r, n, s = !1) {
var a = e[t];
let o = e[i];
var l = null != r && null != o.isIframeStart && o.isIframeStart !== r && o.discoSeqNum === a.discoSeqNum;
let d = o.start;
!l && null != o.startPts || (d = t < i ? a.start + a.duration : Math.max(a.start - o.duration, 0));
n = ne(n) ? 1 / n : Number.EPSILON, n = Math.abs(o.start - d) > n;
return !(!l && !n || (s && (o = e[i] = Object.assign({}, o)), n && (o.start = d), l && (o.isIframeStart = r), 0))
}
function $m(e) {
if (e.programDateTimeMap) {
e.dateMediaTimePairs = [];
for (var [t, i] of Object.entries(e.programDateTimeMap)) {
t = Number(t), i = e.fragments[i - e.startSN];
i && (i = i.start, e.dateMediaTimePairs.push([t, i]))
}
e.dateMediaTimePairs.sort((e, t) => e[0] - t[0])
}
}
class Vm {
constructor(e) {
this.option = e
}
get name() {
return this.option.name
}
get priority() {
return this.option.priority
}
get expiry() {
return this.option.expiry
}
filter(i, e) {
const r = this.option.initFn && this.option.initFn(i, e) || (e ? Object.assign({}, e) : {});
let t = i;
return this.option.firstPassFn && i.forEach((e, t) => this.option.firstPassFn(e, t, r, i)), this.option.filterFn && (t = i.filter((e, t) => this.option.filterFn(e, t, r, i))), null != this.option.filterFn && 0 !== t.length || !this.option.minSortingFn || (t = i.sort((e, t) => this.option.minSortingFn(e, t, r, i))), this.option.finalFn && this.option.finalFn(t, r, i), t
}
}
function Km(e, t, i) {
return (t || []).reduce((e, t) => t.filter(e, i), Array.from(e))
}
function qm(t, e) {
return e.filter(e => {
return Au(t, null !== (e = e.url) && void 0 !== e ? e : null)
})
}
function Hm() {
return [new Vm({
name: "Remove Filter",
priority: 0,
filterFn: (t, e, i) => !i || i.removed.every(e => t.mediaOptionId !== e)
}), new Vm({
name: "Penalty Box Filter",
priority: 1,
filterFn: (t, e, i) => {
const r = performance.now();
return !i || i.penaltyBoxQueue.every(e => e.expiry <= r || t.mediaOptionId !== e.mediaOptionId)
}
}), new Vm({
name: "Compatible IDs Filter",
priority: 1,
filterFn: (t, e, i) => !i || null == i.compatibleIds || i.compatibleIds.some(e => e === t.mediaOptionId)
})]
}
class jm extends kl {
constructor(e, t, i) {
super(e), this.itemId = t, this.mediaOptionType = i, this.allowFilters = this._initFilters()
}
get mediaOptionList() {
var e;
return (null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.mediaOptions) || null
}
get mediaOptionList$() {
return this.mediaOptionListInfo$.pipe(hr(({
mediaOptions: e
}) => e))
}
mediaOptionFromId(t) {
var e;
return null !== (e = (null !== (e = this.mediaOptionList) && void 0 !== e ? e : []).find(e => e.mediaOptionId === t)) && void 0 !== e ? e : null
}
_getFilteredList(e) {
return Km(e.mediaOptions, this.allowFilters, e)
}
get filteredMediaOptionList() {
return this.mediaOptionListInfo ? this._getFilteredList(this.mediaOptionListInfo) : null
}
get filteredMediaOptionList$() {
return this.mediaOptionListInfo$.pipe(La(e => {
const t = [Wu],
i = performance.now();
for (const r of e.penaltyBoxQueue) ne(r.expiry) && r.expiry > i && t.push(bn(r.expiry - i));
return an(...t).pipe(hr(() => this._getFilteredList(e)))
}), vl())
}
get preferredMediaOptionList() {
return this.filteredMediaOptionList ? qm(this.preferredHost, this.filteredMediaOptionList) : []
}
get preferredMediaOptionList$() {
return ed([this.preferredHost$, this.filteredMediaOptionList$]).pipe(hr(([e, t]) => qm(e, t)))
}
getNewHost(e) {
e = this.getFallbackVariant(e, !1, !0);
return null != e && e.url ? Eu(e.url) : this.preferredHost
}
}
function Qm(e) {
return "PQ" === e.videoRange || "HLG" === e.videoRange
}
function Wm(e, t) {
return t.iframes === e
}
function Gm(e, t, i, r) {
return !r || i.bitrate > r.bitrate && i.bitrate <= e.bitrate ? km.Better : i.bitrate === r.bitrate ? km.Same : km.Worse
}
function zm(e, t) {
return e && !t ? -1 : !e && t ? 1 : 0
}(dl = km = km || {})[dl.Better = 1] = "Better", dl[dl.Same = 0] = "Same", dl[dl.Worse = -1] = "Worse";
class Xm extends jm {
constructor(e, t) {
super(e, t, gu.Variant)
}
static makeFilters() {
return [...Hm().concat([new Vm({
name: "HDR Filter",
priority: 1,
filterFn: (e, t, i) => !i || (i.hasHdrLevels && i.preferHDR) === Qm(e)
}), new Vm({
name: "Viewport Filter",
priority: 1,
firstPassFn: (e, t, i) => {
if (i && e && !e.iframes && e.videoCodec) {
const t = !i.lowestBitrate || e.bitrate < i.lowestBitrate ? e.bitrate : i.lowestBitrate;
i.lowestBitrate = t
}
},
filterFn: (e, t, i) => !(e && i && i.viewportInfo && e.videoCodec && i.lowestBitrate) || function(e, t) {
return e.width < 1.35 * t.width && e.height < 1.35 * t.height && e.width * e.height < t.width * t.height * 1.35
}({
width: e.width,
height: e.height
}, i.viewportInfo) || e.bitrate === i.lowestBitrate
}), new Vm({
name: "HDCP Filter",
priority: 2,
filterFn: (e, t, i) => !i || !dm(i.maxHdcpLevel) || um(e.hdcpLevel) < um(i.maxHdcpLevel)
})])].sort((e, t) => {
return (null !== (e = e.priority) && void 0 !== e ? e : Number.MAX_SAFE_INTEGER) - (null !== (t = t.priority) && void 0 !== t ? t : Number.MAX_SAFE_INTEGER)
})
}
_initFilters() {
return Xm.kAllowFilters
}
get preferredHost() {
var e;
return null !== (e = null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.preferredHost) && void 0 !== e ? e : null
}
get preferredHost$() {
return this.selectEntity(this.itemId, e => {
return null !== (e = null == e ? void 0 : e.mediaOptionListTuple[gu.Variant].preferredHost) && void 0 !== e ? e : null
})
}
get mediaOptionListInfo() {
var e;
return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionListTuple[gu.Variant]) && void 0 !== e ? e : null
}
get mediaOptionListInfo$() {
return this.selectEntity(this.itemId, e => {
return null === (e = null == e ? void 0 : e.mediaOptionListTuple) || void 0 === e ? void 0 : e[gu.Variant]
}).pipe(Kp())
}
get hdrMode$() {
return this.mediaOptionListInfo$.pipe(hr(e => !0 === e.preferHDR && e.hasHdrLevels), Is())
}
get maxHdcpLevel$() {
return this.selectEntity(this.itemId, e => {
e = null === (e = null == e ? void 0 : e.mediaOptionListTuple) || void 0 === e ? void 0 : e[gu.Variant];
return null == e ? void 0 : e.maxHdcpLevel
}).pipe(Is())
}
listFallbackVariants(t, e, i, r, n) {
var s = this.mediaOptionListInfo,
a = null === (o = this.mediaOptionList) || void 0 === o ? void 0 : o.find(e => e.mediaOptionId === t);
if (!a || !s) return null;
var o = this.makeFilteredListFromVariant(a, e, n);
if (!o) return null;
e = Eu(a.url), s = s.hasScore;
return Xm._listFallbackVariants(o, a, e, s, i, r, n)
}
getFallbackVariant(t, e, i, r) {
var n = this.mediaOptionListInfo,
s = null === (s = this.mediaOptionList) || void 0 === s ? void 0 : s.find(e => e.mediaOptionId === t);
if (!s || !n) return null;
e = this.makeFilteredListFromVariant(s, e, r);
if (!e) return null;
r = Eu(s.url), n = n.hasScore;
return Xm._getFallbackVariant(e, s, r, n, i)
}
makeFilteredListFromVariant(e, t, i) {
let r = this.mediaOptionListInfo;
if (!e || !this.mediaOptionList || !r) return null;
r = Object.assign(Object.assign({}, r), {
includeAllEligiblePathways: !0
});
e = Array.from(this.mediaOptionList);
let n = t ? Km(e, this.allowFilters, Object.assign(Object.assign({}, r), {
preferHDR: !1,
compatibleIds: null
})) : this._getFilteredList(r);
return n ? (i && 0 < i.length && (n = n.filter(e => !i.includes(e.mediaOptionId))), n) : null
}
get hasIframes() {
var e;
return null !== (e = null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.hasIframeLevels) && void 0 !== e && e
}
canSwitchToSDR(e, t, i = !1) {
var r = this.mediaOptionListInfo;
if (!this.mediaOptionList || !r) return !1;
var n = this.mediaOptionFromId(e);
if (!n) return !1;
if (!Qm(n)) return !1;
var s = Eu(n.url),
e = Km(Array.from(this.mediaOptionList), this.allowFilters, Object.assign(Object.assign({}, r), {
preferHDR: !1,
compatibleIds: null
})),
r = r.hasScore;
return null != Xm._getFallbackVariant(e, n, s, r, t, i)
}
static _listFallbackVariants(e, r, n, t, s, a = !1, i = null) {
let o = !1;
const l = function(e, s, a) {
const t = [...e],
o = Eu(s.url),
l = s.audioGroupId;
return t.sort((e, t) => {
let i = 0;
var r = a && ne(e.score) && ne(t.score),
n = r ? e.score > t.score && e.score <= s.score : e.bitrate > t.bitrate && e.bitrate <= s.bitrate,
r = r ? e.score === t.score : e.bitrate === t.bitrate;
return n ? i = -1 : r ? (i = zm(Au(o, e.url), Au(o, t.url)), 0 === i && (i = zm(!l || e.audioGroupId === l, !l || t.audioGroupId === l))) : i = 1, i
}), t
}(e.filter(e => {
var t = !(e.iframes !== r.iframes || s && Au(n, e.url)),
i = a ? e.bitrate < r.bitrate : e.bitrate <= r.bitrate,
i = t && i;
return r.mediaOptionId === e.mediaOptionId ? (o = i, !1) : i
}), r, t);
return !o || i && i.includes(r.mediaOptionId) || l.unshift(r), l
}
static _getFallbackVariant(e, t, i, r, n, s = !1) {
let a = null;
e = (e = s ? e.filter(e => e.bitrate < t.bitrate) : e).filter(e => e.mediaOptionId !== t.mediaOptionId && e.iframes === t.iframes);
if (n && null != i)
for (const o of e) Gm(t, 0, o, a) !== km.Better || Au(i, o.url) || (a = o);
else
for (const o of e) {
const r = Gm(t, 0, o, a);
r !== km.Better && (r !== km.Same || !Au(i, o.url) || Au(i, a.url) && o.audioGroupId !== t.audioGroupId) || (a = o)
}
return a
}
getMatchingVariant(e, t) {
var i = this.mediaOptionFromId(e),
r = Eu(null == i ? void 0 : i.url),
n = t.mediaOptionType === gu.AltAudio ? "audioGroupId" : "subtitleGroupId";
let s = null;
this.mediaOptionListInfo.hasScore;
for (const e of this.filteredMediaOptionList)
if (e[n] === t.groupId) {
if (!i) {
s = e;
break
}
var a = Gm(i, 0, e, s);
a !== km.Better && (a !== km.Same || s.mediaOptionId === i.mediaOptionId || e.mediaOptionId !== i.mediaOptionId && !Au(r, e.url)) || (s = e)
} return s
}
get currentPathwayID() {
var e;
return null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.currentPathwayID
}
}
function Ym(e, t) {
switch (e) {
case Cm.SendAlternateToPenaltyBox:
e = Cm.RetryRequest, 401 !== t && 403 !== t && 407 !== t && t !== $.CorruptStream.code && t !== $.LivePlaylistUpdateError.code || (e = Cm.SendEndCallback);
break;
case Cm.RemoveAlternatePermanently:
e = Cm.SendEndCallback
}
return e
}
function Jm(e, t, i, r, n, s, a, o = !1) {
const l = s.mediaOptionListQueries[n],
d = 0 != (e.errorActionFlags & Dm.MoveAllAlternatesMatchingHost),
u = s.mediaOptionListQueries[n].mediaOptionFromId(r),
c = a.getFallbackMediaOptionTupleFromMediaOptionId(s, n, r, u.backingMediaOptionId, !1, d, o);
let {
errorAction: h,
errorActionFlags: p
} = e;
return s.isValidMediaOptionTuple(c) ? Au(l.preferredHost, c[n].url) && (p &= ~Dm.MoveAllAlternatesMatchingHost) : (t || (h = Ym(h, i), p = 0), l instanceof Xm && (!0 === l.mediaOptionFromId(r).iframes ? (h = Cm.DoNothing, p = 0) : !t && a.canSwitchToSDR(s, r, d, o) && (h = e.errorAction, p = Dm.SwitchToSDR))), {
errorAction: h,
errorActionFlags: p
}
}
function Zm(e) {
let t, i = 0;
switch (e) {
case 0:
t = Cm.SendAlternateToPenaltyBox, i = Dm.MoveAllAlternatesMatchingHost;
break;
case 410:
t = Cm.RemoveAlternatePermanently;
break;
case 500:
case 502:
case 503:
case 504:
case 404:
case 409:
case 401:
case 403:
case 407:
case $.LivePlaylistUpdateError.code:
case $.PlaylistNotReceived.code:
default:
t = Cm.SendAlternateToPenaltyBox, i = 0
}
return {
errorAction: t,
errorActionFlags: i
}
}
function eg(i, r, n, s, a, o, l) {
var {
errorAction: d,
errorActionFlags: u
} = i;
let e = !0;
switch (d) {
case Cm.RemoveAlternatePermanently:
case Cm.SendAlternateToPenaltyBox: {
if (null == a || null == o) return r.handled = !1;
const i = n.itemId;
let e = o,
t = n.mediaOptionListQueries[a].mediaOptionFromId(o);
t.backingMediaOptionId && (e = t.backingMediaOptionId, t = n.mediaOptionListQueries[a].mediaOptionFromId(e));
var c = 0 != (u & Dm.MoveAllAlternatesMatchingHost),
h = 0 != (u & Dm.MoveAllAlternatesMatchingHDCP),
p = 0 != (u & Dm.SwitchToSDR),
f = d === Cm.RemoveAlternatePermanently;
if (h && "hdcpLevel" in t) {
const r = t.hdcpLevel;
s.setMaxHdcpLevel(i, r)
}
if (p && s.switchToSDROnly(i), c) {
const r = Eu(t.url);
s.moveAllWithMatchingHosts(i, a, r, f)
} else f ? s.removePermanently(i, a, e) : s.addToPenaltyBox(i, a, e);
if (n.enabledMediaOptionIdByType(a) === o) {
let e = [Lu, Lu, Lu];
e = s.getFallbackMediaOptionTupleFromMediaOptionId(n, a, o, null, !1, c, l), n.isValidMediaOptionTuple(e) ? s.setPreferredHost(i, Eu(e[gu.Variant].url)) : r.fatal = !0, r.fatal && (e = [Lu, Lu, Lu]), s.setNextMediaOptions(n.itemId, e)
}
break
}
case Cm.SendEndCallback:
r.fatal = !0;
break;
case Cm.RetryRequest:
case Cm.DoNothing:
default:
e = !1
}
return r.handled = e, e
}
function tg(e, t) {
t instanceof dc || t instanceof uc || t instanceof hc || (t instanceof gc || t instanceof mc) && le(t.keyuri)
}
function ig(t, i, r) {
if (t.handled = !0, r && i < r.maxNumRetry && ne(r.retryDelayMs)) {
let e;
return e = "linear" === r.backoff ? (i + 1) * r.retryDelayMs : Math.pow(2, i) * r.retryDelayMs, e = Math.min(r.maxRetryDelayMs, e), tg(0, t), bn(e)
}
return t.fatal = !0, tg(0, t), Vi(t)
}
function rg(e, t, i, r, n, s, a, o, l = !1) {
return (null == r ? void 0 : r.errorAction) === Cm.RetryRequest ? ig(e, t, i, s.logger) : ng(e, 0, r, n, s, a, o, l)
}
function ng(e, t, i, r, n, s, a, o = !1) {
const l = new er;
return al(() => {
i && (tg(n.logger, e), eg(i, e, r, n, s, a, o)), l.error(e)
}), l
}
function sg(t, i, r, n) {
return e => e.pipe(Vn(e => {
if (t.logger.error(`Got demux error ${e.message}`), e instanceof D || e instanceof F) {
Cm.SendAlternateToPenaltyBox;
return ng(e, 0, {
errorAction: e.fatal ? Cm.SendEndCallback : e instanceof F ? Cm.SendAlternateToPenaltyBox : Cm.RemoveAlternatePermanently,
errorActionFlags: 0
}, i, t, r, n)
}
throw e
}))
}
function ag(e, t, i, r, n) {
e = null !== (e = null === (e = n.getKeyInfo(e)) || void 0 === e ? void 0 : e.mediaOptionIds) && void 0 !== e ? e : [];
for (const s of e)
for (const n of i.mediaOptionListQueries) null != n.mediaOptionFromId(s) && r.updateConsecutiveTimeouts(i.itemId, n.mediaOptionType, t, "key")
}
function og(r, t, e, n, s, a) {
const o = n.logger,
i = s.enabledMediaOptionKeys,
l = [];
for (const t of r.mediaOptionIds) {
const r = i.some(e => e.mediaOptionId === t),
e = s.mediaOptionListQueries.find(e => null != e.mediaOptionFromId(t));
if (e) {
const n = e.mediaOptionType,
a = {
mediaOptionId: t,
mediaOptionType: n
};
r ? l.push(a) : l.unshift(a)
} else o.warn(`Couldn't find query for ${t}`)
}
const d = new er;
return al(() => {
const e = r instanceof mc;
ag(r.keyuri, e, s, n, a);
let t, i = !1;
for (const {
mediaOptionId: e,
mediaOptionType: a
} of l) t = function(e, t, i, r, n) {
let s = {
errorAction: Cm.SendAlternateToPenaltyBox,
errorActionFlags: 0
};
if (e instanceof mc) s.errorAction = Cm.SendAlternateToPenaltyBox;
else {
const t = e.isOkToRetry;
e.keyErrorReason === rc.OutputRestricted ? (s.errorAction = Cm.RemoveAlternatePermanently, s.errorActionFlags |= Dm.MoveAllAlternatesMatchingHDCP) : t ? s = Zm(e.code) : s.errorAction = Cm.RemoveAlternatePermanently
}
s.errorActionFlags &= ~Dm.MoveAllAlternatesMatchingHost;
var a = r.enabledMediaOptionIdByType(i);
return t === a ? Jm(s, !1, e.code, a, i, r, n, e.isTimeout) : s
}(r, e, a, s, n), o.error(`[Keys] handleNetworkError uri=${le(r.keyuri)} mediaOptionId=${e} mediaOptionType=${a} action=${JSON.stringify(t)}`), t.errorAction === Cm.RetryRequest && (i = !0), eg(t, r, s, n, a, e);
i ? (d.next(), d.complete()) : (tg(0, r), d.error(r))
}), d.pipe(La(() => ig(r, t, e, n.logger)))
}
function lg(t, i, r, n, s, a, o, l) {
return n = Math.max(0, n), e => e.pipe(Za(() => {
null != i && o.updateConsecutiveTimeouts(t, i, !1, "load")
}), va(e => e.pipe(jr((e, t) => function(e, t, i, r, n, s, a, o) {
var l;
if (!(e instanceof p)) return Vi(e);
let d, u, c, h = !1;
if (e instanceof dc) c = {
errorAction: Ym(Zm((l = e).response.code).errorAction, l.response.code),
errorActionFlags: 0
};
else if (e instanceof uc || e instanceof hc) {
({
mediaOptionType: u,
mediaOptionId: d,
isTimeout: h
} = e);
const t = null === (l = s.mediaOptionListQueries[u]) || void 0 === l ? void 0 : l.mediaOptionFromId(d);
if (!r && e.isTimeout && null != t && (!("iframes" in t) || !0 !== t.iframes) && (a.updateConsecutiveTimeouts(s.itemId, e.mediaOptionType, !0, "load"), e instanceof hc && e.stats)) {
const t = performance.now();
o.setBandwidthSample(Object.assign(Object.assign({}, e.stats), {
tfirst: e.stats.tfirst || t,
tload: e.stats.tload || t,
complete: !0,
mediaOptionType: u
}))
}
c = function(e, t, i, r, n) {
var s = e.response.code;
let a = Zm(s);
var {
mediaOptionId: o,
mediaOptionType: l
} = e;
return t ? a.errorActionFlags &= ~Dm.MoveAllAlternatesMatchingHost : a = function(e, t, i, r, n) {
let {
errorAction: s,
errorActionFlags: a
} = t;
if (e.isTimeout) {
const t = e["mediaOptionType"],
o = null !== (n = null === (n = n.getErrorInfoByType(t)) || void 0 === n ? void 0 : n.timeouts.load) && void 0 !== n ? n : 0;
!i && r <= o && (s = Cm.DoNothing, a = 0)
}
return {
errorAction: s,
errorActionFlags: a
}
}(e, a, t, i, r), a = Jm(a, t, s, o, l, r, n, e.isTimeout), a
}(e, r, n, s, a)
}
return rg(e, t, i, c, s, a, u, d, h)
}(e, t, _c(e, r), s, n, a, o, l)))))
}
Xm.kAllowFilters = Xm.makeFilters(), (dl = Cm = Cm || {})[dl.DoNothing = 0] = "DoNothing", dl[dl.SendEndCallback = 1] = "SendEndCallback", dl[dl.SendAlternateToPenaltyBox = 2] = "SendAlternateToPenaltyBox", dl[dl.RemoveAlternatePermanently = 3] = "RemoveAlternatePermanently", dl[dl.InsertDiscontinuity = 4] = "InsertDiscontinuity", dl[dl.RetryRequest = 5] = "RetryRequest", (dl = Dm = Dm || {})[dl.MoveAllAlternatesMatchingHost = 1] = "MoveAllAlternatesMatchingHost", dl[dl.MoveAllAlternatesMatchingHDCP = 2] = "MoveAllAlternatesMatchingHDCP", dl[dl.SwitchToSDR = 4] = "SwitchToSDR";
class dg extends kl {
constructor(e) {
super(e)
}
get currentConfig() {
var e;
return null === (e = this.getActive()) || void 0 === e ? void 0 : e.config
}
get extendMaxTTFB() {
var e;
return null === (e = this.getActive()) || void 0 === e ? void 0 : e.extendMaxTTFB
}
get config$() {
return this.selectActive(e => null == e ? void 0 : e.config)
}
get userSeek$() {
return this.selectActive(e => null == e ? void 0 : e.userSeek)
}
}
A();
class ug extends fl {
constructor() {
super({}, {
name: "hls-store",
producerFn: su
})
}
}
class cg {
constructor(e) {
this.store = e
}
getQuery() {
return new dg(this.store)
}
setHlsEntity(e) {
const t = e.id;
Do(`hls.set.entity ${t}`), al(() => {
this.store.add(de(e)), this.store.setActive(t)
})
}
removeEntity(e) {
Do(`hls.remove ${e}`), this.store.remove(e)
}
setStartTime(t) {
this.store.updateActive(e => {
e.config.startPosition = t
})
}
setUserSeek(t) {
this.store.updateActive(e => {
e.userSeek = t
})
}
setExtendMaxTTFB(t) {
this.store.updateActive(e => {
e.extendMaxTTFB = t
})
}
}
let hg, pg;
function fg() {
return hg = hg || new cg(new ug), hg
}
function mg() {
return fg().getQuery().currentConfig
}
function gg(r, n) {
if ("VOD" !== r.type && "VOD" !== n.type && r.iframesOnly === n.iframesOnly) {
const s = r.mediaOptionId === n.mediaOptionId,
a = Math.max(r.startSN, n.startSN) - n.startSN,
o = Math.min(r.endSN, n.endSN) - n.startSN,
l = n.startSN - r.startSN,
d = r.fragments,
u = n.fragments;
let t = 0;
for (let e = a; e <= o; ++e)
if (d[l + e] && u[e]) {
t = d[l + e].discoSeqNum - u[e].discoSeqNum;
break
} const c = {};
let i = null;
for (let e = 0; e < u.length; e++) {
const h = d[l + e],
a = u[e];
if (t) {
const r = a.discoSeqNum + t;
n.initSegments[a.discoSeqNum] && (n.initSegments[a.discoSeqNum].discoSeqNum = r, c[r] = n.initSegments[a.discoSeqNum], delete n.initSegments[a.discoSeqNum]), a.discoSeqNum = r
}
s && a.mediaSeqNum === (null == h ? void 0 : h.mediaSeqNum) && null != h.startPts && (a.start = h.start, a.duration = h.duration, a.startDtsTs = h.startDtsTs, a.endDtsTs = h.endDtsTs, a.startPts = h.startPts, a.endPts = h.endPts, i = a)
}
if (Object.keys(c).length && (n.initSegments = c), i) Bm(n, i, i.start, void 0, !1, !0);
else if (0 <= l && l < d.length) {
const r = d[l].start,
h = n.fragments;
for (let e = 0; e < u.length; e++) h[e].start += r
}
n.ptsKnown = n.ptsKnown || s && !0 === r.ptsKnown && r.endSN >= n.startSN, $m(n)
}
}
function yg(e, t, i) {
let r = t.targetduration;
return ne(i.liveSyncDuration) ? r = i.liveSyncDuration : ne(i.liveSyncDurationCount) && (r = i.liveSyncDurationCount * t.targetduration), e + Math.max(0, t.totalduration - r)
}
function vg(e, t, i, r, n) {
if (!t.ptsKnown) return 0;
var s = t.targetduration,
a = t.fragments[0].start,
r = n.canContinuePlaybackWithoutGap(t, i, {
avgPlaylistLoadTimeMs: 0,
avgPlaylistParseTimeMs: 0
}, r);
let o = Math.max(0, e - s);
return e < a && !r && (o = a), o
}
function Sg(e) {
return 1e3 * (e.averagetargetduration || e.targetduration)
}
function bg(e, t) {
var i = Sg(e),
t = performance.now() - t;
return e.liveOrEvent && i <= t
}
function Tg(t, i, r = NaN) {
var n = t.fragments;
for (let e = r > t.startSN ? r - t.startSN : 0; e < n.length; ++e) {
const t = n[e],
r = t["start"];
if (i(t)) return {
timelineOffset: r,
mediaFragment: t
}
}
return null
}
function Eg(e, t, i) {
var r = 0 < i.duration,
n = i.start + i.duration,
n = null == t || t < n || t - n < 1 && i.isLastFragment,
e = e.every(e => !$p(e.frag, i));
return r && e && n
}
function Ig(e, t, i, r, n) {
i = null !== (i = Tg(r, Eg.bind(null, n, void 0), i)) && void 0 !== i ? i : null;
let s = null;
i && (s = null !== (e = Tg(r, Eg.bind(null, n, e), i.mediaFragment.mediaSeqNum)) && void 0 !== e ? e : null, s || !r.liveOrEvent || r.ptsKnown || (s = i));
let a = NaN;
null != s && ne(t) && s.mediaFragment.discoSeqNum !== t && (a = s.mediaFragment.discoSeqNum, s = null);
t = n.some(e => 0 < e.frag.framesWithoutIDR);
return s && t && n[n.length - 1].frag.mediaOptionId !== r.mediaOptionId && (s = null !== (r = Tg(r, e => e.mediaSeqNum === s.mediaFragment.mediaSeqNum - 1)) && void 0 !== r ? r : s), {
foundFrag: s,
nextDisco: a
}
}
function wg(e) {
e = e.fragments[e.fragments.length - 1];
return e ? e.start + e.duration : 0
}
class Ag extends kl {
constructor(e, t) {
super(e), this.mediaOption = t
}
get itemId() {
return this.mediaOption.itemId
}
get mediaOptionId() {
return this.mediaOption.mediaOptionId
}
get initSegmentEntities() {
var e;
return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.initSegmentCacheEntities
}
get mediaLibraryEntity() {
return this.getEntity(this.itemId)
}
get mediaOptionDetailsEntityRecord() {
var e;
return null === (e = this.mediaLibraryEntity) || void 0 === e ? void 0 : e.mediaOptionDetailsEntityRecord
}
get mediaOptionDetailsEntity() {
return this.mediaOptionDetailsEntityRecord ? this.mediaOptionDetailsEntityRecord[this.mediaOptionId] : null
}
get mediaOptionDetails() {
var e;
return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.mediaOptionDetails
}
get playlistDuration() {
var e;
return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.playlistDuration
}
get mediaOptionDetailsEntity$() {
const {
itemId: e,
mediaOptionId: t
} = this;
return this.selectEntity(e, e => {
if (null != e && e.mediaOptionDetailsEntityRecord) return null == e ? void 0 : e.mediaOptionDetailsEntityRecord[t]
})
}
get mediaOptionDetails$() {
return this.selectEntity(this.itemId, e => {
return null === (e = null == e ? void 0 : e.mediaOptionDetailsEntityRecord[this.mediaOptionId]) || void 0 === e ? void 0 : e.mediaOptionDetails
}).pipe(Kp())
}
get playlistDuration$() {
return this.mediaOptionDetailsEntity$.pipe(hr(e => null == e ? void 0 : e.playlistDuration), Kp(), Is())
}
get live$() {
return this.mediaOptionDetails$.pipe(hr(e => null == e ? void 0 : e.liveOrEvent), Is())
}
}
class Og extends fl {
constructor() {
super({}, {
name: "media-library-store",
idKey: "itemId",
producerFn: su
})
}
}
class kg {
constructor(e) {
this.store = e
}
getQuery() {
return new kl(this.store)
}
getQueryForOption(e) {
return new Ag(this.store, e)
}
createMediaLibraryEntity(e) {
var t = {
itemId: e,
mediaOptionDetailsEntityRecord: {}
};
Do(`library.entity.create: ${e}`), this.store.add(t)
}
setDetailsLoading(e) {
const {
itemId: t,
mediaOptionId: i
} = e;
Do(`library.details.loading: ${i}`), this.store.update(t, ({
mediaOptionDetailsEntityRecord: e
}) => {
e[i] || (e[i] = {
initSegmentCacheEntities: {},
unchangedCount: 0
}), e[i].detailsLoading = !0
})
}
archiveMediaOptionDetails(i, r, n) {
const {
itemId: e,
mediaOptionId: s
} = i, a = performance.now(), o = wg(i);
Do(`library.details.loaded: ${s}`), this.store.update(e, e => {
const t = e.mediaOptionDetailsEntityRecord[s];
t.detailsLoading = !1, t.mediaOptionDetails = i, t.lastUpdateMillis = a, n ? t.unchangedCount = 0 : ++t.unchangedCount, t.playlistDuration = o, t.stats = r, e.liveOrEvent = i.liveOrEvent
})
}
setInitSegmentLoading(e) {
const {
itemId: t,
mediaOptionId: i,
discoSeqNum: r
} = e;
Do(`library.initsegs.loading: ${i}/${r}`), this.store.update(t, e => {
e.mediaOptionDetailsEntityRecord[i].initSegLoading = r
})
}
archiveInitSegmentEntity(i, r) {
const {
itemId: e,
mediaOptionId: n,
discoSeqNum: s
} = i;
Do(`library.initseg.loaded: ${n}/${s}`), this.store.update(e, ({
mediaOptionDetailsEntityRecord: e
}) => {
const t = e[n];
t.initSegmentCacheEntities[s] = [i, r], t.initSegLoading = null
})
}
updatePTSDTS(e, i, t, r) {
var n = null === (n = this.getQueryForOption({
itemId: e,
mediaOptionId: i
})) || void 0 === n ? void 0 : n.mediaOptionDetails;
if (n && Fm(n, r)) {
const s = r["startDtsTs"],
{
variantDTS: a,
timelineOffset: o,
iframeMode: l
} = t,
d = b(s, a) + o,
u = Object.assign({}, n);
Bm(u, r, d, l, !0), $m(u);
const c = wg(u);
this.store.update(e, ({
mediaOptionDetailsEntityRecord: e
}) => {
const t = e[i];
null != t && t.mediaOptionDetails && (t.mediaOptionDetails = u, t.playlistDuration = c)
})
}
}
remove(e) {
this.store.remove(e)
}
clear() {
this.store.remove()
}
}
function Cg() {
return pg = pg || new kg(new Og), pg
}
const Dg = e => Cg().getQueryForOption(e),
Mg = (d, e, t = !1, i = !1) => {
if (null == e || !_u(e)) return $i(null);
const r = e["itemId"],
n = d["mediaLibraryService"],
s = n.getQueryForOption(e);
s.hasEntity(r) || n.createMediaLibraryEntity(r);
var a = s.mediaOptionDetailsEntity,
o = s.mediaOptionDetails;
return null == o || i || "VOD" !== o.type && (!o.liveOrEvent || bg(o, a.lastUpdateMillis)) ? (n.setDetailsLoading(e), function(u, e) {
var t;
const {
logger: i,
config: c,
rootPlaylistQuery: h,
rootPlaylistService: p,
statsService: r,
mediaLibraryService: f,
mediaSink: n
} = d, m = n.mediaQuery, s = c.playlistLoadPolicy, a = c.keySystemPreference, o = h.masterVariableList, l = null === (t = null === (t = fg()) || void 0 === t ? void 0 : t.getQuery()) || void 0 === t ? void 0 : t.extendMaxTTFB;
return _m(u, h.itemStartOffset, c, s, i, a, r, o, l).pipe(hr(e => {
const t = f.getQueryForOption(u),
i = t.mediaOptionDetails,
r = e["mediaOptionDetails"],
n = e["stats"];
let s = !0;
if (r.liveOrEvent) {
const d = r["mediaOptionType"];
e = r, s = null == i || e.endSN !== i.endSN || e.liveOrEvent !== i.liveOrEvent, i && gg(i, r);
const u = h.lastLoadedMediaOptionByType(d),
t = u ? null === (l = f.getQueryForOption(u)) || void 0 === l ? void 0 : l.mediaOptionDetails : null;
!r.ptsKnown && t && t.mediaOptionId !== (null == i ? void 0 : i.mediaOptionId) && gg(t, r)
}
r && al(() => {
f.archiveMediaOptionDetails(r, n, s), p.setLastLoadedMediaOptionByType(h.itemId, u.mediaOptionType, u)
});
const a = !s && t.mediaOptionDetailsEntity.unchangedCount >= c.liveMaxUnchangedPlaylistRefresh,
o = function(e, t, i, r) {
t = vg(r.currentTime, e, t, i, r), i = e.fragments[e.fragments.length - 1], r = (null == i ? void 0 : i.start) + (null == i ? void 0 : i.duration);
return {
expired: null != i && e.liveOrEvent && e.ptsKnown && r < t,
windowEnd: r,
minPosition: t
}
}(r, n.tload, c.maxBufferHole, m);
if (a || o.expired) {
var l = a ? $.LivePlaylistUpdateError : {
text: `Live window too far in the past end:${o.windowEnd.toFixed(3)} minPosition:${o.minPosition}`,
code: 0
};
throw new uc(!1, l.text, l.code, l, !1, u.mediaOptionType, u.mediaOptionId, u.url)
}
return r
}), tc("getMediaOptionDetailsCommon.emit.loaded"), lg(u.itemId, u.mediaOptionType, Lc(u, s), c.maxNumAddLevelToPenaltyBox, e, h, p, r)).pipe(Ds(1))
}(e, t)) : $i(o).pipe(tc("retrieveMediaOptionDetails.emit.cached")).pipe(Ds(1))
};
const xg = (t, i) => {
if (!i) return $i(null);
const r = t["logger"],
{
mediaLibraryService: e,
mediaParser: n
} = t,
s = e.getQueryForOption(i),
{
mediaOption: a,
mediaOptionDetailsEntityRecord: o,
mediaOptionDetails: l
} = s,
d = a["mediaOptionId"];
if (null == o || !o[d]) throw new Error("retrieveInitSegmentCacheEntity no details entity");
if (!l) throw new Error("retrieveInitSegmentCacheEntity no details");
var u = o[d]["initSegmentCacheEntities"],
c = l["initSegments"],
h = i["discoSeqNum"];
if (u[h]) {
const [t, r] = u[h];
let e = t;
return r && (e = n.willBeTrackSwitch(i) ? t : r), $i(e)
}
const p = c[h];
return p ? (e.setInitSegmentLoading(p), r.child({
name: "timing"
}), Rg(t, p, !1, !1).pipe(Za(() => {}), ji(tr), La(e => Pg(e, p, t)), Za(() => {}))) : $i(null)
};
function Pg(e, n, t) {
const {
logger: s,
mediaSink: i,
rootPlaylistService: r,
rootPlaylistQuery: a,
mediaParser: o,
mediaLibraryService: l,
gaplessInstance: d
} = t, u = i["mediaQuery"], c = l.getQueryForOption(n), {
mediaOption: h,
mediaOptionDetails: p
} = c, {
itemId: f,
mediaOptionId: m
} = h, {
keyTagInfo: g,
discoSeqNum: y,
mediaOptionType: v
} = n, S = u.seeking, b = p.liveOrEvent, T = v === gu.Variant && p.ptsKnown;
let E, I;
n.isInitSegment ? I = new Uint8Array(e) : E = new Uint8Array(e);
var e = {
segment: E,
initSegment: I,
frag: n,
ptsKnown: T,
seeking: S,
live: b,
totalDuration: p.totalduration
};
return o.parseInitSegment(e, null !== (e = null === navigator || void 0 === navigator ? void 0 : navigator.vendor) && void 0 !== e ? e : "").pipe(hr(e => {
var {
track: t,
moovData: i,
mimeType: r
} = e, e = t["initSegment"];
d.inGaplessMode && be.isVideoCodec(t.codec) && (s.warn(`Video codec discovered in gapless mode codec:${t.codec}`), d.dequeueSource("InvalidFormat"));
r = {
itemId: f,
mediaOptionId: m,
discoSeqNum: y,
initParsedData: i,
data: e,
mimeType: r,
keyTagInfo: g,
fragment: n
};
return l.archiveInitSegmentEntity(r), r
}), sg(r, a, v, m))
}
function Rg(n, s, i, r) {
var e;
const {
rootPlaylistQuery: t,
rootPlaylistService: a,
config: o,
rtcService: l,
statsService: d
} = n, {
itemId: u,
mediaOptionType: c
} = s, h = o.fragLoadPolicy, p = ne(s.mediaSeqNum);
let f;
p && (f = {
getData: !1,
cb: (e, t, i, r) => (a.updateInflightFrag(u, s.mediaOptionType, s, "loading", i), !1)
});
let m = !1;
r && null === l.serverInfoInstance && (m = !0);
const g = nm(s, o, h, f, m, null === (e = null === (e = fg()) || void 0 === e ? void 0 : e.getQuery()) || void 0 === e ? void 0 : e.extendMaxTTFB).pipe(Za(([, , e, t]) => {
i && d.setBandwidthSample(Object.assign(Object.assign({}, e), {
mediaOptionType: s.mediaOptionType
})), r && m && (l.serverInfoInstance = t), p && a.updateInflightFrag(u, s.mediaOptionType, s, "loaded", e)
}), Za(([e, , t]) => {
r && l.handleFragLoaded(e, t)
}), lg(u, c, Lc(s, h), o.maxNumAddLevelToPenaltyBox, !1, t, a, d));
return "AES-128" === (null === (e = s.keyTagInfo) || void 0 === e ? void 0 : e.method) ? en([_g(n, s.keyTagInfo, {
itemId: s.itemId,
mediaOptionId: s.mediaOptionId
}), g]).pipe(La(([e, t]) => {
const [i, r] = t;
return i.keyTagInfo.key = e.key, Nm(i, r, o, n.logger, n.rpcClients.crypto)
})) : g.pipe(hr(e => e[1]))
}
const Lg = (i, r, e) => {
const {
rootPlaylistService: n,
rootPlaylistQuery: s
} = i, {
timelineOffset: a,
mediaFragment: o
} = e.foundFrag, {
itemId: l,
discoSeqNum: d
} = o;
return xg(i, o).pipe(La(t => (n.updateInflightFrag(l, o.mediaOptionType, o, "loading", null), Rg(i, o, !0, !0).pipe(La(e => {
return n.updateInflightFrag(l, r, o, "parsing", null),
function(e, t, i, y, v, S) {
const r = new Uint8Array(e),
{
legibleSystemAdapter: n,
rootPlaylistService: s,
mediaSink: a,
mediaParser: o,
rootPlaylistQuery: l,
mediaLibraryService: b
} = S,
d = a["mediaQuery"],
u = b.getQueryForOption(y),
{
mediaOption: c,
mediaOptionDetails: h
} = u,
p = h["initSegments"],
{
itemId: T,
mediaOptionId: E
} = c,
{
discoSeqNum: I,
mediaSeqNum: w,
mediaOptionType: f,
isLastFragment: A
} = y,
m = d.seeking,
g = h.liveOrEvent,
O = p[I],
k = f === gu.Variant && h.ptsKnown,
C = {
segment: r,
frag: y,
seeking: m,
live: g,
ptsKnown: k,
totalDuration: h.totalduration,
defaultInitPTS: t,
iframeMediaStart: Up(y) ? y.iframeMediaStart : void 0,
iframeDuration: Up(y) ? y.iframeMediaDuration : void 0,
iframeOriginalStart: Up(y) ? y.iframeOriginalStart : void 0
};
let D;
if (null != i && (null === (t = y.keyTagInfo) || void 0 === t ? void 0 : t.uri) === (null === (t = i.keyTagInfo) || void 0 === t ? void 0 : t.uri)) D = $i(i);
else if (null != i) {
const M = Object.assign(Object.assign({}, i.fragment), {
keyTagInfo: y.keyTagInfo
});
D = Pg(O ? i.data : e, M, S)
} else D = Pg(e, y, S);
return D.pipe(La(m => {
const g = performance.now();
if (null != m) {
const g = m["data"],
e = new Uint8Array(g);
C.initSegment = e
}
return y.mediaOptionType === gu.Variant && (null == n || n.setupForFrag(y)), o.parseSegment(C, "").pipe(hr(e => {
var t = performance.now(),
{
startPTS: i,
startDTS: r,
endPTS: n,
endDTS: s,
firstKeyframePts: a,
framesWithoutIDR: o,
dropped: l,
data1: d,
data2: u,
captionData: c,
id3Samples: h,
parsedInitSegment: e
} = e,
t = {
durationSec: n.baseTime / n.timescale - i.baseTime / i.timescale,
parseTimeMs: t - g
};
S.statsService.setFragSample(t);
let p = Object.assign({}, m);
if (e) {
const {
track: g,
moovData: f,
mimeType: v
} = e, S = g["initSegment"];
p = {
itemId: T,
mediaOptionId: E,
discoSeqNum: I,
initParsedData: f,
data: S,
mimeType: v,
keyTagInfo: y.keyTagInfo,
fragment: y
}, b.archiveInitSegmentEntity(m, p)
}
e = y.keyTagInfo;
return [p, {
itemId: T,
mediaOptionId: E,
mediaSeqNum: w,
discoSeqNum: I,
startDtsTs: r,
endDtsTs: s,
timelineOffset: v,
firstKeyframePts: a,
framesWithoutIDR: o,
dropped: l,
data1: d,
data2: u,
startPts: i,
endPts: n,
keyTagInfo: e,
isLastFragment: A,
iframe: null !== (e = y.iframe) && void 0 !== e && e,
duration: y.duration,
iframeMediaDuration: Up(y) ? y.iframeMediaDuration : void 0,
iframeOriginalStart: Up(y) ? y.iframeOriginalStart : void 0,
captionData: c,
id3Samples: h
}]
}))
}), sg(s, l, f, E))
}(e, null === (e = s.getInitPTS(d)) || void 0 === e ? void 0 : e.offsetTimestamp, t, o, a, i)
}), Za(e => {
n.updateInflightFrag(l, r, o, "parsed", null)
}), tc(`retrieveMediaFragmentCacheEntity.${r}.emit`)))), Ds(1))
};
function _g(e, t, i) {
const {
keySystemAdapter: r,
rootPlaylistQuery: n,
rootPlaylistService: s,
config: a
} = e;
return r.getKeyFromDecryptData(t, i).pipe((o = t.uri, l = Lc({
url: t.uri
}, a.keyLoadPolicy), d = n, u = s, c = r.ksQuery, e => e.pipe(ll(() => {
ag(o, !1, d, u, c)
}), va(e => e.pipe(jr((e, t) => {
if (e instanceof mc || e instanceof gc) return og(e, t, _c(e, l), u, d, c);
throw e
}))))));
var o, l, d, u, c
}
class Ng {
constructor(e, t, i) {
this.hls = e, this.destroy$ = new Xt, this.iframeSwitchStart = 0, this.logger = t.child({
name: "hls-player-events"
}), this.rtc = i, this.subscribeAndEmit()
}
destroy() {
this.destroy$.next()
}
subscribeAndEmit() {
var e = this.loaderQueryListener(new bc(Ec)),
t = this.hls.publicQueries$.pipe(La(([e, t]) => an(this.rootPlaylistQueryListener(e, t), this.mediaElementQueryListener(t, e))));
an(e, t, this.activeItemListener(this.hls.itemQueue)).pipe(Vn(e => {
var t = e.message;
return this.logger.error(`Got error in HlsPlayerEvents ${t}`, e), Ii
}), Va(this.destroy$), Vs(() => {})).subscribe()
}
activeItemListener(e) {
return e.activeItemById$.pipe(Kp(), La(e => {
e = e.url;
return this.hls.trigger(P.MANIFEST_LOADING, {
url: e
}), Ii
}))
}
rootPlaylistQueryListener(t, e) {
var i = t.enabledMediaOptionByType$(gu.Variant).pipe(ln(e => !!e), La(e => {
var t;
return this.hls.trigger(P.LEVEL_SWITCHING, e), null === (t = this.rtc) || void 0 === t || t.handleLevelSwitching(e.url), Ii
})),
r = t.enabledMediaOptionByType$(gu.Variant).pipe(La(i => Dg(i).mediaOptionDetailsEntity$.pipe(ln(e => !0 === (null == e ? void 0 : e.detailsLoading)), Za(e => {
var t = {
url: le(null == i ? void 0 : i.url),
level: i.mediaOptionId,
type: Nu[i.mediaOptionType]
};
return this.hls.trigger(P.LEVEL_LOADING, t), Ii
})))),
n = t.enabledMediaOptionByType$(gu.Variant).pipe(La(e => {
const t = Dg(e);
let i = 0;
return t.mediaOptionDetailsEntity$.pipe(Kp(), ln(e => {
var t = null !== e.stats && !1 === e.detailsLoading && e.lastUpdateMillis > i;
return i = null !== (e = e.lastUpdateMillis) && void 0 !== e ? e : 0, t
}))
}), La(e => {
var t = e.mediaOptionDetails,
i = e.stats,
r = {
mediaOptionId: t.mediaOptionId,
details: t,
playlistType: t.type,
stats: i
};
if (null === (i = this.rtc) || void 0 === i || i.handleLevelLoaded(t, r.stats), this.hls.trigger(P.LEVEL_LOADED, r), 0 === e.unchangedCount) {
const e = {
level: 0,
details: t
};
this.hls.trigger(P.LEVEL_UPDATED, e)
}
if (null != t && t.daterangeTags) {
const e = {
daterangeTags: t.daterangeTags
};
this.hls.trigger(P.DATERANGE_UPDATED, e)
}
return Ii
})),
s = t.enableMediaOptionSwitchedForType$(gu.AltAudio).pipe(La(e => {
e = t.alternateMediaOptionById(gu.AltAudio, e.mediaOptionId);
return e && this.triggerAudioSwitch(e), Ii
})),
a = t.rootPlaylistEntity$.pipe(ln(e => null !== e.enabledMediaOptionKeys[gu.AltAudio].mediaOptionId), Ds(1), La(e => {
const t = e.enabledMediaOptionKeys[gu.AltAudio].mediaOptionId;
return t && (e = e.mediaOptionListTuple[gu.AltAudio].mediaOptions.find(e => e.mediaOptionId === t), this.triggerAudioSwitch(Object.assign(Object.assign({}, e), {
url: le(null == e ? void 0 : e.url)
}))), Ii
}));
return an(i, s, Gu(e.textTracksCreated$, e => e).pipe(La(() => t.enabledMediaOptionByType$(gu.Subtitle).pipe(La(e => {
e = t.alternateMediaOptionById(gu.Subtitle, e.mediaOptionId);
return e ? this.hls.trigger(P.SUBTITLE_TRACK_SWITCH, {
track: Object.assign({}, e),
hidden: !1
}) : this.hls.trigger(P.SUBTITLE_TRACK_SWITCH, {
track: void 0,
hidden: !1
}), Ii
})))), t.sessionData$.pipe(ln(e => null != e.complete), Ds(1), Za(e => {}), hr(e => {
this.hls.trigger(P.SESSION_DATA_COMPLETE, e)
})), t.getPreferredMediaOptionsByType$(gu.Variant).pipe(ka(1), hr(e => {
const t = e;
null === (e = this.rtc) || void 0 === e || e.handleLevelsChanged(t), t.forEach(e => {}), this.hls.trigger(P.LEVELS_CHANGED, {
requiresReset: !1,
levels: t
})
})), t.getPreferredMediaOptionsByType$(gu.AltAudio).pipe(hr(e => {
this.hls.trigger(P.AUDIO_TRACKS_UPDATED, {
audioTracks: e
})
})), Gu(e.textTracksCreated$, e => e).pipe(La(() => t.getPreferredMediaOptionsByType$(gu.Subtitle).pipe(Ds(1), hr(e => {
this.hls.trigger(P.SUBTITLE_TRACKS_UPDATED, {
subtitleTracks: e
}), this.hls.trigger(P.SUBTITLE_TRACKS_CREATED)
})))), n, r, a)
}
mediaElementQueryListener(s, e) {
return an(s.seekTo$.pipe(hr(e => {
var t;
e && ne(e.pos) ? (null === (t = this.rtc) || void 0 === t || t.handleSeek("SEEKING"), this.hls.trigger(P.SEEKING, {
seekToPos: e.pos
})) : null === e && (null === (e = this.rtc) || void 0 === e || e.handleSeek("SEEKED"), this.hls.trigger(P.SEEKED))
})), s.desiredRate$.pipe(Ra(0), ha(), hr(e => {
var t = e[0],
i = e[1];
Wp(i) ? 0 == this.iframeSwitchStart && (this.iframeSwitchStart = performance.now()) : this.iframeSwitchStart = 0, this.hls.trigger(P.DESIRED_RATE_CHANGED, {
oldRate: t,
newRate: i
}), null === (e = this.rtc) || void 0 === e || e.handleDesiredRateChanged(t, i)
})), s.sourceBufferEntityByType$(yu.AltAudio).pipe(ln(e => !!e), Is((e, t) => e.totalBytes === t.totalBytes), hr(e => {
this.hls.trigger(P.BUFFER_APPENDED)
})), s.sourceBufferEntityByType$(yu.Variant).pipe(ln(e => !!e), Is((e, t) => e.totalBytes === t.totalBytes), hr(e => {
var t;
null === (t = this.rtc) || void 0 === t || t.handleVariantBufferAppended(e.timestampOffset, e.totalBytes), this.hls.trigger(P.BUFFER_APPENDED)
})), s.stallInfo$.pipe(Kp(), bo(s.combinedBuffer$), hr(([e]) => {
var t;
null === (t = this.rtc) || void 0 === t || t.handleStalled(e, s.getCombinedBufferInfo(e.currentTime, 0).len), this.hls.trigger(P.STALLED, e)
})), Mr([$i(e), ed([s.timeupdate$, s.bufferedSegmentsByType$(yu.Variant)]).pipe(ao(1e3), hr(([t, e]) => null == e ? void 0 : e.find(e => e.startPTS <= t && e.endPTS > t)), ln(e => !!e), Ra(null), ha())]).pipe(La(([e, [t, i]]) => {
var r = null == i ? void 0 : i.frag,
t = null == t ? void 0 : t.frag;
if (r && !$p(t, r) && (this.hls.trigger(P.FRAG_CHANGED, i), this.hls.inGaplessMode && this.checkAndTriggerReadyForNext(s, i), !t || r.mediaOptionId !== t.mediaOptionId)) {
const s = e.mediaOptionListQueries[gu.Variant].mediaOptionFromId(r.mediaOptionId);
if (!s) return this.logger.warn("variantInfo is undefined in fragChangeMonitor"), Ii;
const n = t ? t.mediaOptionId : "",
i = r.mediaOptionId;
s.iframes && (performance.now(), this.iframeSwitchStart), null === (r = this.rtc) || void 0 === r || r.handleLevelSwitched({
url: s.url,
mediaOptionId: s.mediaOptionId,
oldVariant: "" !== n ? n : void 0,
newVariant: i
}), this.hls.trigger(P.LEVEL_SWITCHED, s)
}
return Ii
})), s.isBufferedToEnd$(this.hls.config.maxBufferHole, !1).pipe(ln(e => !0 === e), ji(tr), hr(e => {
if (e && !this.hls.itemQueue.isPreloading() && this.hls.inGaplessMode) {
const i = s.getCombinedBufferInfo(s.currentTime, 0);
var t = 0;
i && (t = i.end, e = s.mediaElementDuration, 0 < t && e - s.currentTime < 10 && this.hls.trigger(P.READY_FOR_NEXT_ITEM, {
duration: t
}))
}
})))
}
checkAndTriggerReadyForNext(e, t) {
var i, r;
t && t.frag && (i = e.currentTime, (r = e.getCombinedBufferInfo(i, 0)) && (i = r.end, r = e.mediaElementDuration, e = e.bufferMonitorInfo, e = Math.max(e.almostDryWaterLevelSeconds, e.lowWaterLevelSeconds / 2), (r - t.endPTS <= e || t.frag.isLastFragment) && this.hls.inGaplessMode && !this.hls.isPreloading && this.hls.trigger(P.READY_FOR_NEXT_ITEM, {
duration: i
})))
}
loaderQueryListener(e) {
return an(e.unresolvedUriLoading$.pipe(hr(e => e.map(e => {
e = {
uri: e.uri,
responseType: e.responseType,
userAgent: e.userAgent
};
this.hls.trigger(P.UNRESOLVED_URI_LOADING, e)
}))))
}
triggerAudioSwitch(e) {
e && this.hls.trigger(P.AUDIO_TRACK_SWITCHED, {
id: e.id
})
}
triggerManifestLoaded(e) {
e = {
levels: e.rootMediaOptionsTuple[gu.Variant],
audioTracks: e.rootMediaOptionsTuple[gu.AltAudio],
subtitleTracks: e.rootMediaOptionsTuple[gu.Subtitle],
url: e.baseUrl,
audioMediaSelectionGroup: e.audioMediaSelectionGroup,
subtitleMediaSelectionGroup: e.subtitleMediaSelectionGroup,
stats: e.stats,
isMediaPlaylist: e.isMediaPlaylist
};
this.hls.trigger(P.MANIFEST_LOADED, e)
}
triggerManifestParsed(e) {
var t = {
levels: e.mediaOptionListQueries[gu.Variant].filteredMediaOptionList,
firstLevel: 0,
audio: !1,
video: !0,
altAudio: !1,
audioTracks: e.mediaOptionListQueries[gu.AltAudio].filteredMediaOptionList,
audioMediaSelectionGroup: e.audioMediaSelectionGroup,
subtitleMediaSelectionGroup: e.subtitleMediaSelectionGroup,
stats: e.loadStats
};
null === (e = this.rtc) || void 0 === e || e.handleManifestParsed(t), this.hls.trigger(P.MANIFEST_PARSED, t)
}
urlRedactedManifestLoaded(e) {
const t = Object.assign({}, e);
return t.url = le(t.url), t.levels = ue(t.levels), t.audioTracks = ce(t.audioTracks), t.subtitleTracks = ce(t.subtitleTracks), t
}
urlRedactedManifestParsed(e) {
const t = Object.assign({}, e);
return t.levels = ue(t.levels), t.audioTracks = ce(t.audioTracks), t
}
}(A = Mm = Mm || {}).LowBandwidth = "LowBandwidth", A.HighBandwidth = "HighBandwidth", A.PreferredListChanged = "PreferredListChanged", A.IframeModeChange = "IframeModeChange", A.None = "";
const Fg = {
minValidBitrate: 2e6,
maxValidBitrate: 5e6,
maxPreferredBitrate: 3e6,
minValidHeight: 480,
maxValidHeight: 720
};
function Bg(e, a, o, l, d, u) {
return e.reduce((e, t) => {
if (t.iframes) return e;
let i = e;
const r = (n = t.score, s = a && o && l && d && !Ug(t, a, o, l, d, u) ? mu.INVALID : mu.VALID, new Qp(s, n));
var n, s;
return (!e || r.isGreaterThan(e.bestRank) || r.isEqualTo(e.bestRank) && t.bandwidth < e.selected.bandwidth) && (i = {
selected: t,
bestRank: r
}), i
}, null).selected
}
function Ug(e, t, i, r, n, s) {
var {
targetDuration: a,
targetStartupMs: o
} = i, l = r["avgPlaylistLoadTimeMs"], d = n["avgParseTimeMs"], {
avgBufferCreateMs: i,
avgInitFragAppendMs: r,
avgDataFragAppendMs: n
} = s, {
avgBandwidth: s,
avgLatencyMs: t
} = t;
return e.bandwidth <= s && (e.avgBandwidth || e.bandwidth) * a / s * 1e3 + l + i + +(t + d + (r + n)) <= o
}
const $g = {
name: "abr"
};
function Vg(e, t) {
return ne(e) ? Math.min(e, t) : t
}
function Kg(e) {
return ne(null == e ? void 0 : e.avgBandwidth)
}
function qg(e, t) {
return e.getCurrentWaterLevelByType(yu.Variant, t) / (0 !== e.playbackRate ? Math.abs(e.playbackRate) : 1)
}
function Hg(t, i, e, r) {
if (e) return t;
let n = -1;
if (t < 0) return n;
for (let e = t; e < i.length; ++e) {
const t = Qg(i[e], r);
if (t.altAudio && t.subtitle) {
n = e;
break
}
}
return n
}
function jg(t, e, i, r, n, s, a) {
const o = i.preferredMediaOptions[gu.Variant].filter(e => e.iframes === t);
if (!o.length) return {
variantMediaOption: Lu.mediaOptionId,
holdOffDuration: 0,
lowestCandidate: null
};
let l = 0;
const d = i.nextMinAutoOptionId;
if (d !== Lu.mediaOptionId) {
const t = o.findIndex(e => e.mediaOptionId === d);
0 <= t && (l = t)
}
if (l = Hg(l, o, t, i), l < 0) return {
variantMediaOption: Lu.mediaOptionId,
holdOffDuration: 0,
lowestCandidate: null
};
let u = o.length - 1;
const c = i.nextMaxAutoOptionId;
if (c !== Lu.mediaOptionId) {
const t = o.findIndex(e => e.mediaOptionId === c);
0 <= t && (u = t)
}
var h = i.variantMediaOptionById(r.mediaOptionId),
p = r.mediaOptionDetails,
f = (null == h ? void 0 : h.iframes) !== t ? 0 : qg(n, e.maxBufferHole);
let m, g;
if (t) {
const t = e.desiredIframeFPS;
g = p ? p.targetduration / t : 0, g = Math.max(1 / t, g)
} else g = p ? p.targetduration : 0;
h = e.abrBandWidthUpFactor, p = e.abrBandWidthFactor;
return m = Wg(o, g, l, u, f, t, s.getCombinedEstimate(), s.bandwidthStatus, p, h, e, i, r, n, a), m.variantMediaOption === Lu.mediaOptionId && (m = Wg(o, g, l, u, f + Vg(g, e.maxStarvationDelay), t, s.getCombinedEstimate(), s.bandwidthStatus, p, h, e, i, r, n, a), m.variantMediaOption === Lu.mediaOptionId && 0 <= l && (m.variantMediaOption = o[l].mediaOptionId, m.alternates = t ? null : Qg(o[l], i))), m
}
function Qg(e, t) {
var i = t.enabledMediaOptionKeys,
r = i[gu.AltAudio],
r = _u(r) ? t.mediaOptionListQueries[gu.AltAudio].getMatchingAlternate(r.mediaOptionId, e) : Lu,
i = i[gu.Subtitle];
return {
altAudio: r,
subtitle: _u(i) ? t.mediaOptionListQueries[gu.Subtitle].getMatchingAlternate(i.mediaOptionId, e) : Lu
}
}
function Wg(i, r, n, e, s, a, o, l, t, d, u, c, h, p, f) {
"bandwidth-history-controller" !== u.abrBandwidthEstimator && f.warn(`Unsupported configuration: ${u.abrBandwidthEstimator} for ABR bandwidth estimator`);
const m = l.bandwidthSampleCount,
g = c.abrStatus,
y = p.maxBufferSize,
v = u.minTargetDurations || 1,
S = c.mediaOptionListQueries[gu.Variant].mediaOptionListInfo.hasScore;
if (!i.length) return {
variantMediaOption: Lu.mediaOptionId,
holdOffDuration: -1,
lowestCandidate: null
};
const b = c.enabledMediaOptionIdByType(gu.Variant),
T = c.variantMediaOptionById(b),
E = null != i.find(e => e.mediaOptionId === b),
I = T && T.iframes === a,
w = T && I ? T.score : void 0,
A = T && I ? T.frameRate : void 0,
O = T && I ? T.height : void 0,
k = I ? qg(p, u.maxBufferHole) : 0;
e = Math.max(0, Math.min(i.length - 1, e)), n = Math.max(0, Math.min(i.length - 1, n));
var C = h.mediaOptionDetailsEntityRecord,
D = Gg(o.avgBandwidth, d, t, m);
let M;
for (let t = e; t >= n; t--) {
const n = i[t];
let e = n.mediaOptionId;
const u = n.score,
h = C && C[e] ? C[e].mediaOptionDetails : void 0,
p = C && C[e] ? C[e].lastUpdateMillis : null,
f = h ? h.totalduration / h.fragments.length : r,
B = null != T && n.bitrate > T.bitrate,
m = null != T && n.bitrate < T.bitrate,
U = !(null != A && (B && n.frameRate < A || m && n.frameRate > A)),
$ = !(B && null != O && O > n.height),
V = !(m && (n.bitrate === T.bitrate - 1 || n.bitrate === T.bitrate + 1)),
K = !(S && B && null != w && (u < w || u === w && T && n.bitrate >= T.bitrate)),
q = n.iframes === a;
if (ne(f) && q && U && $ && V && K) {
var {
adjustedbw: x,
bitrate: P,
fetchDuration: R,
rejectLevelDueToPeakBW: L,
canFitMultipleSegments: _,
requireAlternates: N,
alternates: F
} = function(e, t, i, r, n, s, a, o, l, d, u, c) {
var h = n ? a.bwUp : a.bwDown,
n = e.bitrate,
a = t ? t.totalduration / t.fragments.length : o,
s = zg(e, t, o, h, ne(s.avgPlaylistLoadTimeMs) ? s.avgPlaylistLoadTimeMs : s.avgLatencyMs, d),
d = e.bandwidth,
i = n < h && h < d && i <= 2 * a,
l = r * ((d || n || 0) * ((null == t ? void 0 : t.targetduration) || a)) / 8 <= l;
let p = null;
u = !u;
return u && (p = Qg(e, c), p.altAudio && p.subtitle || (p = null)), {
adjustedbw: h,
bitrate: n,
fetchDuration: s,
rejectLevelDueToPeakBW: i,
canFitMultipleSegments: l,
requireAlternates: u,
alternates: p
}
}(n, h, k, v, B, o, D, r, y, p, a, c);
if (N && Boolean(F) && (M = e), P < x && _ && !L && (!N || Boolean(F)) && (a || !R || R < s)) {
if (L = x, N = g, x = (x = l).instantBw, (N.fragDownloadSlow || N.fragDownloadTooSlow || ne(x) && x < L) && E && I)
if (k <= 2 * f && B) e = b;
else if (B && d * l.instantBw < P) continue;
return {
variantMediaOption: e,
holdOffDuration: R,
alternates: F,
lowestCandidate: M
}
}
}
}
return {
variantMediaOption: Lu.mediaOptionId,
holdOffDuration: -1,
lowestCandidate: M
}
}
function Gg(e, t, i, r) {
let n, s;
return 4 <= r ? (n = e * t, s = e * i) : n = s = e / 1.8, {
bwUp: n,
bwDown: s
}
}
function zg(e, t, i, r, n, s) {
let a = e.bitrate * (t ? t.totalduration / t.fragments.length : i) / r;
return null == t || !t.liveOrEvent || t.ptsKnown && !Yg(t.totalduration, n, s) || (a *= 2), ne(n) && (!ne(s) || null != t && t.liveOrEvent) && (a += n / 1e3), a
}
function Xg(t, e) {
let i = 1 / 0;
if (t === Lu.mediaOptionId) return i;
var r = e.find(e => e.mediaOptionId === t);
if (!r) return 1 / 0;
const n = r.iframes,
s = r.bitrate,
a = r.frameRate,
o = e.find(e => e.iframes === n && (void 0 === a || e.frameRate >= a) && e.bitrate > s);
return o && (i = o.bitrate), i
}
function Yg(e, t, i) {
return t = ne(t) ? t : 0, !ne(i) || performance.now() - i + t > 1e3 * e
}
function Jg(e, t) {
return (null == e ? void 0 : e.fragDownloadSlow) === (null == t ? void 0 : t.fragDownloadSlow) && e.fragDownloadTooSlow === (null == t ? void 0 : t.fragDownloadTooSlow)
}
function Zg(e) {
return "loading" === (null == e ? void 0 : e.state) && ne(null === (e = e.bwSample) || void 0 === e ? void 0 : e.trequest)
}
const ey = 2e3;
function ty(e, t, i, r) {
let {
fragDownloadSlow: n,
fragDownloadTooSlow: s
} = t;
var a = i.variantMediaOptionById(e.mediaOptionId).bitrate,
t = e.bwSample;
r = r.child($g);
i = t.total || Math.max(t.loaded, Math.round(e.duration * a / 8)), a = performance.now() - t.tfirst, i = t.loaded * e.duration * 1e3 / i;
return a >= ey && 1e3 <= a - i && (n || r.warn(`flow indicates low bandwidth, after time/duration behind real time: ${a}/${a-i}`), n = !0), a >= 1e3 * e.duration && (s || r.warn(`too much time spent downloading fragment, likely to switch down ${a} > ${1e3*e.duration}`), s = !0), {
fragDownloadSlow: n,
fragDownloadTooSlow: s
}
}
function iy(e, t, i, r, n) {
var s;
const a = n.logger.child($g),
o = r.isIframeRate,
l = i.mediaOptionListQueries[gu.Variant].preferredMediaOptionList,
d = i.enabledMediaOptionKeys[gu.Variant];
let u = e;
if (u !== Mm.None || l.some(e => e.mediaOptionId === d.mediaOptionId) || (u = Mm.PreferredListChanged), u !== Mm.None && !(o && u !== Mm.IframeModeChange && r.getBufferedSegmentsByType(yu.Variant).filter(e => e.frag.iframe).length < t.minFramesBeforeSwitchingLevel)) {
o && u === Mm.IframeModeChange && n.setEnabledVariantMediaOptionIdBeforeTrickplaySwitch(i.itemId, d.mediaOptionId);
const h = Zf(i.itemId),
p = Dg(d),
f = [Lu, Lu, Lu];
if (!o && e === Mm.IframeModeChange) {
const e = function(e, t, i, r) {
const n = i.mediaOptionListQueries[gu.Variant].preferredMediaOptionList,
s = t.targetStartupMs,
a = {
avgPlaylistParseTimeMs: 0,
avgPlaylistLoadTimeMs: 0
},
o = r.getFragEstimate(),
l = {
avgBufferCreateMs: 0,
avgInitFragAppendMs: 0,
avgDataFragAppendMs: 0
},
d = o.maxDurationSec,
u = {
avgLatencyMs: 0,
avgBandwidth: r.getBandwidthEstimate().avgBandwidth
},
c = {
targetDuration: d,
targetStartupMs: s,
metricsOverride: {
maxValidHeight: 0,
maxValidBitrate: 0,
maxPreferredBitrate: 0
}
},
h = n.filter(e => !e.iframes && (!e.width || !e.height || e.width * e.height <= 2488320));
let p = e;
0 < h.length && (p = h[0].mediaOptionId);
e = h.filter(e => Ug(e, u, c, a, o, l));
return 0 < e.length && (p = e[e.length - 1].mediaOptionId), p
}(i.enabledVariantMediaOptionIdBeforeTrickplaySwitch, t, i, h);
n.setNextMaxAutoOptionId(i.itemId, e), n.setEnabledVariantMediaOptionIdBeforeTrickplaySwitch(i.itemId, void 0)
}
var c = function(e, t, i, r, n, s, a) {
let o = t.nextMaxAutoOptionId;
if (o === Lu.mediaOptionId || Kg(s.getBandwidthEstimate())) return l = e, d = t, u = r, e = n, r = s, s = a.child({
name: "abr"
}), a = e.isIframeRate, d.enabledMediaOptionIdByType(gu.Variant), jg(a, l, d, u, e, r, s);
if (n.isIframeRate) return {
variantMediaOption: o,
holdOffDuration: 0,
lowestCandidate: null
}; {
const c = t.variantMediaOptionById(o),
h = t.enabledAlternateMediaOptionByType(gu.Subtitle),
n = t.enabledAlternateMediaOptionByType(gu.AltAudio),
p = null == n ? void 0 : n.persistentID,
f = null == h ? void 0 : h.persistentID,
m = !t.preferHDR,
g = i.getBestMediaOptionTupleFromVariantAndPersistentId(t, c, p, f, void 0, [], m, !1, !1);
return t.isValidMediaOptionTuple(g) ? (o = g[gu.Variant].mediaOptionId, {
variantMediaOption: o,
holdOffDuration: 0,
alternates: {
altAudio: g[gu.AltAudio],
subtitle: g[gu.Subtitle]
},
lowestCandidate: null
}) : {
variantMediaOption: t.enabledMediaOptionKeys[gu.Variant].mediaOptionId,
holdOffDuration: 0,
lowestCandidate: null
}
}
var l, d, u
}(t, i, n, p, r, h, a);
if (o || e !== Mm.IframeModeChange || n.setNextMaxAutoOptionId(i.itemId, Lu.mediaOptionId), c.variantMediaOption !== d.mediaOptionId) {
f[gu.Variant] = {
itemId: i.itemId,
mediaOptionId: c.variantMediaOption
};
for (const e of [gu.AltAudio, gu.Subtitle]) {
const t = i.enabledMediaOptionIdByType(e);
if (t !== Lu.mediaOptionId) {
const r = e === gu.AltAudio ? null === (s = c.alternates) || void 0 === s ? void 0 : s.altAudio : null === (s = c.alternates) || void 0 === s ? void 0 : s.subtitle;
f[e] = r || {
itemId: i.itemId,
mediaOptionId: t
}
}
}
return n.setEnabledMediaOptions(i.itemId, f), 1
}
}
}
const ry = {
name: "iframes"
};
(A = xm = xm || {})[A.DISABLED = 0] = "DISABLED", A[A.ERRORED = 1] = "ERRORED", A[A.SUCCESS = 2] = "SUCCESS";
const ny = new fl({}, {
name: "item-queue",
producerFn: su,
idKey: "itemId",
resettable: !0
}),
sy = new class extends kl {}(ny);
class ay {
constructor() {
this.firstItem = !0, this.playingEntity = null, this.loadingEntity = null
}
static createItem(e, t, i = NaN, r, n) {
const s = new Date,
a = `${s.getHours()}:${s.getMinutes()}:${s.getSeconds()}`;
Qe();
var o = function(e) {
e = cu.parseURL(e).fragment.substr(1);
if (0 === e.length) return null;
const t = new URLSearchParams(e);
if (!t.has("t")) return null;
e = Number(t.get("t"));
return ne(e) ? e : null
}(t);
if (ne(o)) i = o;
else {
const e = mg();
ne(null == e ? void 0 : e.startPosition) && (i = e.startPosition)
}
return {
itemId: `${e}_${a}`,
name: e,
url: t,
serviceName: n,
createTime: a,
initialSeekTime: i,
itemStartOffset: 0,
platformInfo: r,
config: {}
}
}
get activeItemById$() {
return sy.selectActiveId().pipe(hr(e => sy.getActive()))
}
get removedItems$() {
return sy.selectEntityAction(Eo.Remove).pipe(hr(e => e))
}
get activeItem() {
return sy.getActive()
}
get queueItems$() {
return sy.selectAll().pipe(hr(e => null != e ? e : []))
}
get isFirstItem() {
return this.firstItem
}
get playingItem() {
return this.playingEntity
}
get loadingItem() {
return this.loadingEntity
}
addQueueItem(e, t, i, r, n, s) {
sy.getCount();
const a = ay.createItem(e, t, i, r, s);
null != this.playingEntity && (a.initialSeekTime = void 0), n && (a.itemStartOffset = n, this.firstItem = !1, this.playingEntity = this.activeItem, this.loadingEntity = a), Do(`queue.add.item: ${e}`), al(() => {
ny.add(a), ny.setActive(a.itemId)
})
}
updatePlayingItemId() {
this.playingEntity = this.loadingEntity, this.loadingEntity = null, this.clearAllButActive()
}
resetLoadingItem() {
this.removeQueueItem(this.loadingEntity.itemId), this.loadingEntity = null, al(() => {
ny.setActive(this.playingEntity.itemId)
})
}
isPreloading() {
return null !== this.playingEntity && null !== this.loadingEntity
}
setQueueItem(t, i, r, n, s) {
Do("queue.set.item"), this.loadingEntity = null, al(() => {
ny.reset();
var e = ay.createItem(t, i, r, n, s);
ny.add(e), ny.setActive(e.itemId)
}), this.playingEntity = this.activeItem
}
removeQueueItem(e) {
ny.remove(e)
}
clearQueue() {
ny.reset()
}
clearAllButActive() {
var e;
const t = null === (e = this.activeItem) || void 0 === e ? void 0 : e.itemId;
al(() => {
sy.getAll().forEach(e => {
e.itemId !== t && ny.remove(e.itemId)
})
})
}
set earlyAudioSelection(t) {
ny.updateActive(e => {
e.earlySelection || (e.earlySelection = {}), e.earlySelection.audioPersistentId = t
})
}
get earlyAudioSelection() {
var e;
return null === (e = this.activeItem.earlySelection) || void 0 === e ? void 0 : e.audioPersistentId
}
set earlySubtitleSelection(t) {
ny.updateActive(e => {
e.earlySelection || (e.earlySelection = {}), e.earlySelection.subtitlePersistentId = t
})
}
get earlySubtitleSelection() {
var e;
return null === (e = this.activeItem.earlySelection) || void 0 === e ? void 0 : e.subtitlePersistentId
}
}
function oy(e, t, i, r, n, s) {
return ng(e, 0, Jm({
errorAction: Cm.RemoveAlternatePermanently,
errorActionFlags: 0
}, !1, e.response.code, i, t, s, n), s, n, t, i).pipe(Vn(e => {
throw !1 === e.fatal && r.resetMediaSource(), e
}))
}
class ly {
constructor(e, t, i, r, n, s) {
this.logger = e, this._rootPlaylistService = t, this._rootQuery = i, this._mediaQuery = r, this._iframeMachine = n, this._anchorMSNs = [NaN, NaN], this._avDetails = [null, null], this.logger = e.child({
name: "fpicker"
}), this._discoSeqNum = NaN, this.lookUpTolerance = Math.max(s.maxBufferHole, s.maxFragLookUpTolerance), this.firstAudioMustOverlapVideoStart = s.firstAudioMustOverlapVideoStart, this.lookUpToleranceAlt = s.firstAudioMustOverlapVideoStart ? 0 : s.maxFragLookUpTolerance
}
destroy() {
this._anchorMSNs = [NaN, NaN], this._avDetails = [null, null], this._rootQuery = null, this._mediaQuery = null, this._rootPlaylistService = null, this._iframeMachine = null
}
get discoSeqNum() {
return this._discoSeqNum
}
get _discoSeqNum() {
return this._rootQuery.discoSeqNum
}
set _discoSeqNum(e) {
this._rootPlaylistService.setDiscoSeqNum(this._rootQuery.itemId, e)
}
get anchorMSNs() {
return this._anchorMSNs
}
_resolvePosition(e, t, i) {
let r = e;
var t = this._avDetails[t];
if ((null == t ? void 0 : t.mediaOptionId) !== (null == i ? void 0 : i.mediaOptionId) && i.liveOrEvent && !1 === i.ptsKnown && (!t || Math.max(t.startSN, i.startSN) > Math.min(t.endSN, i.endSN))) {
const e = 3 * i.targetduration,
n = (null === (t = i.fragments[0]) || void 0 === t ? void 0 : t.start) + i.totalduration;
r = Math.max(0, n - e)
}
return r
}
getDiscoSeqNumForTime(e, t) {
return this._mediaQuery.isIframeRate && e.iframesOnly ? Qu.discoSeqNumForTime(e.fragments, t) : (r = t, null == (e = null !== (e = Tg(e, e => {
var t = 0 < e.duration,
i = e.start + e.duration,
e = r < i || r - i < 1 && e.isLastFragment;
return t && e
})) && void 0 !== e ? e : null) ? void 0 : e.mediaFragment.discoSeqNum);
var r
}
_updateAnchorByPosition(e, t) {
let i = NaN;
const r = t[yu.Variant];
let n = e;
if (r) {
const t = r.fragments;
if (n = this._resolvePosition(e, yu.Variant, r), i = this.getDiscoSeqNumForTime(r, n), !ne(i)) {
const r = t[0],
s = t[t.length - 1],
a = null == r ? void 0 : r.start,
o = (null == s ? void 0 : s.start) + (null == s ? void 0 : s.duration);
this.logger.warn(`${e.toFixed(3)} out of range [${null==a?void 0:a.toFixed(3)},${null==o?void 0:o.toFixed(3)}]`), n <= a ? i = r.discoSeqNum : n >= o ? i = s.discoSeqNum : this.logger.warn(`Unable to determine newCC. fragFirst: ${JSON.stringify(r)} fragLast: ${JSON.stringify(s)}`), ne(i) || this.logger.warn(`Unable to determine newCC. fragFirst: ${JSON.stringify(r)} fragLast: ${JSON.stringify(s)}`)
}
} else this.logger.warn("No variant details for anchoring");
return this._updateAnchor(i, t), n
}
_updateAnchor(e, s) {
const a = e !== this._discoSeqNum;
a && (this._discoSeqNum = e), Bu.forEach(e => {
const t = this._avDetails[e],
i = s[e],
r = (null == t ? void 0 : t.mediaOptionId) !== (null == i ? void 0 : i.mediaOptionId);
if (a || r) this._updateAnchorForType($u(e), i);
else if (i) {
const {
mediaOptionId: s,
ptsKnown: a,
dateMediaTimePairs: t,
startSN: r,
endSN: n
} = i;
this._avDetails[e] = {
mediaOptionId: s,
ptsKnown: a,
dateMediaTimePairs: t,
startSN: r,
endSN: n
}
}
})
}
getNextFragments(i, r, n) {
const {
position: s,
bufferInfoTuple: e,
switchContexts: a
} = i;
let t = e.map((e, t) => dy(s, r[t], a[t], null == e ? void 0 : e.buffered, t === gu.AltAudio ? this.lookUpToleranceAlt : this.lookUpTolerance)).reduce((e, t) => Math.min(t, e), Number.POSITIVE_INFINITY);
if (ne(i.discoSeqNum)) {
const s = r.reduce((e, t) => {
if (!t) return e;
t = Qu.getTimeRangeForCC(t.fragments, i.discoSeqNum, n);
return [Math.max(e[0], t[0]), Math.min(e[1], t[1])]
}, [Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY]);
t = Math.min(Math.max(t, s[0]), s[1])
}
return i.position = this._updateAnchorByPosition(t, r), this._getNextFragmentsInternal(i, r)
}
_getNextFragmentsInternal(r, n) {
const s = [null, null];
let a;
n.forEach((e, t) => {
var i;
this.firstAudioMustOverlapVideoStart && t === gu.AltAudio && this._mediaQuery.seeking && null !== (i = s[gu.Variant]) && void 0 !== i && i.foundFrag && (a = r.position, r.position = s[gu.Variant].foundFrag.mediaFragment.start), s[t] = this._getNextFragmentForType(r, n, t)
});
var e = s[yu.Variant],
t = s[yu.AltAudio],
i = null === (o = null == e ? void 0 : e.foundFrag) || void 0 === o ? void 0 : o.mediaFragment,
o = null === (o = null == t ? void 0 : t.foundFrag) || void 0 === o ? void 0 : o.mediaFragment;
if (i && o && (o.start > i.start + i.duration ? (this.logger.warn("Audio too far ahead"), s[yu.AltAudio] = ly.noopResult) : i.start > o.start + o.duration && !this._mediaQuery.isIframeRate && (this.logger.warn("Video too far ahead"), s[yu.Variant] = ly.noopResult)), !isFinite(null == e ? void 0 : e.nextDisco) || null != t && !ne(t.nextDisco)) return s; {
const l = s[yu.Variant].nextDisco;
return this._updateAnchor(l, n), ne(a) && (r.position = a, a = NaN), this._getNextFragmentsInternal(r, n)
}
}
_getNextFragmentForType(e, t, i) {
var {
position: r,
bufferInfoTuple: n,
switchContexts: s
} = e, a = t[i], o = null !== (d = null === (c = n[i]) || void 0 === c ? void 0 : c.buffered) && void 0 !== d ? d : {
start: r,
end: r,
len: 0
}, l = this._mediaQuery.getBufferedSegmentsByType(i), d = null !== (c = null === (e = s[i]) || void 0 === e ? void 0 : e.userInitiated) && void 0 !== c && c, u = dy(r, a, s[i], o, this.lookUpTolerance);
if (!a) return null;
var {
highWaterLevelSeconds: e,
lowWaterLevelSeconds: c
} = this._mediaQuery.bufferMonitorInfo, r = o.len;
if (!d && e <= r) return ly.noopResult;
var e = i === yu.Variant ? yu.AltAudio : yu.Variant,
n = null === (n = n[e]) || void 0 === n ? void 0 : n.buffered,
e = null !== (e = null === (e = s[e]) || void 0 === e ? void 0 : e.userInitiated) && void 0 !== e && e;
let h = !1;
i === yu.Variant && c <= r && 1 < this._mediaQuery.expectedSbCount && null != n && n.end < o.end && (e || n.end - n.start < c) && (h = !0);
let p, f = null,
m = NaN;
if (this._mediaQuery.isIframeRate && i === yu.Variant && a.iframesOnly) {
const g = function(e, t, i) {
e = i.nextFragment(a.fragments, (null == e ? void 0 : e.fragments) || [], t, u);
if (!e) return null;
var {
frag: t,
newMediaRootTime: e
} = e;
return {
foundFrag: {
timelineOffset: t.iframeMediaStart,
mediaFragment: t
},
nextDisco: NaN,
newMediaRootTime: e
}
}(t[yu.AltAudio], this._mediaQuery.desiredRate, this._iframeMachine);
if (g) {
({
foundFrag: f,
nextDisco: m,
newMediaRootTime: p
} = g);
const i = f.mediaFragment;
i.discoSeqNum !== this._discoSeqNum && this._updateAnchor(i.discoSeqNum, t)
}
} else {
const g = this._anchorMSNs[i];
({
foundFrag: f,
nextDisco: m,
newMediaRootTime: p
} = Ig(u, this._discoSeqNum, g, a, l))
}
return h && this._rootQuery.getInitPTS(null == f ? void 0 : f.mediaFragment.discoSeqNum) ? ly.noopResult : {
foundFrag: f,
nextDisco: m,
newMediaRootTime: p
}
}
_updateAnchorForType(e, t) {
var i, r, n, s, a;
if (!t) return this._anchorMSNs[e] = NaN, void(this._avDetails[e] = null);
ne(this._discoSeqNum) ? (a = this._discoSeqNum, a = null !== (s = null == (n = (r = t.fragments, i = a, r.find(e => e.discoSeqNum === i))) ? void 0 : n.mediaSeqNum) && void 0 !== s ? s : t.startSN, this._anchorMSNs[e] = a, {
mediaOptionId: r,
ptsKnown: n,
dateMediaTimePairs: s,
startSN: a,
endSN: t
} = t, this._avDetails[e] = {
mediaOptionId: r,
ptsKnown: n,
dateMediaTimePairs: s,
startSN: a,
endSN: t
}) : this.logger.warn("Trying to anchor with non-finite discoSeqNum")
}
}
function dy(e, t, i, r, n) {
r = null != r ? r : {
start: e,
end: e,
len: 0
};
i = null !== (i = null == i ? void 0 : i.userInitiated) && void 0 !== i && i, n = null != t && t.iframesOnly ? 0 : n;
return i || 0 === r.len ? e : r.end + n
}
ly.noopResult = {
foundFrag: null,
nextDisco: NaN
};
const uy = {
name: "avpipe"
};
function cy(r) {
const {
config: o,
rootPlaylistService: l,
rootPlaylistQuery: d,
mediaSink: e,
gaplessInstance: t
} = r, u = e.mediaQuery, i = ed(Bu.map(e => d.enabledMediaOptionSwitchForType$(e).pipe(Za(e => {})))).pipe(La(e => {
if (!_u({
itemId: d.itemId,
mediaOptionId: e[gu.Variant].toId
})) throw new V(!0, `No valid variant enabled id:${e[gu.Variant].toId}`, $.NoValidAlternates);
e = e.map(({
fromId: e,
toId: t
}, i) => function(t, i, r, n, s) {
var a, o;
const {
rootPlaylistQuery: l,
rootPlaylistService: d,
mediaSink: u,
mediaParser: c,
config: h,
iframeMachine: p
} = t, f = u.mediaQuery;
if (!n || !s || n === s && (r === gu.AltAudio || !p.isStarted)) return Wu;
switch (r) {
case gu.Variant: {
n !== s && c.reset(gu.Variant);
const t = $u(r),
g = l.variantMediaOptionById(n),
y = l.variantMediaOptionById(s),
v = l.itemId;
if (null == y || null == g) return Wu;
var e = !y.iframes && p.isStarted;
if (g.iframes !== y.iframes || e) return u.toggleTrickPlaybackMode(y.iframes), e && (ne(u.mediaQuery.postFlushSeek) || (u.postFlushSeek = p.iframeClockTimeSeconds), p.stop()), u.pause(), (e ? u.flushAll(0, 1 / 0, !0) : u.flushData(t, 0, 1 / 0, !0)).pipe(Za(() => {
var e = u.mediaQuery.postFlushSeek;
ne(e) && d.setPendingSeek(v, e)
}));
if (!h.allowFastSwitchUp || y.iframes) return Wu;
var m = Dg(g).mediaOptionDetails;
if (null != m && null != y && g.bitrate < y.bitrate) {
const r = m.targetduration,
n = Dg(y),
s = n.mediaOptionDetails,
d = n.mediaOptionDetailsEntity.lastUpdateMillis,
c = f.getCurrentWaterLevelByType(t, h.maxBufferHole),
p = function(e, t, i, r, n, s, a, o) {
if (n.nextMaxAutoOptionId !== Lu.mediaOptionId && !Kg(s.getBandwidthEstimate())) return Number.POSITIVE_INFINITY;
a = Gg(s.getBandwidthEstimate().avgBandwidth, a.abrBandWidthUpFactor, a.abrBandWidthFactor, s.bandwidthStatus.bandwidthSampleCount), s = ne(s.getPlaylistEstimate().avgPlaylistLoadTimeMs) ? s.getPlaylistEstimate().avgPlaylistLoadTimeMs : s.getBandwidthEstimate().avgLatencyMs, a = t.bitrate > e.bitrate ? a.bwUp : a.bwDown;
return null == i || !i.liveOrEvent || i.ptsKnown && !Yg(i.totalduration, s, o) ? zg(t, i, r, a, s, o) : Number.POSITIVE_INFINITY
}(g, y, s, r, l.abrStatus, i, h, d) + h.maxStarvationDelay,
S = f.currentTime + p,
b = null === (o = null === (a = f.sourceBufferEntityByType(t)) || void 0 === a ? void 0 : a.bufferedSegments) || void 0 === o ? void 0 : o.find(e => e.startPTS >= S);
let e;
if (b) {
const t = b.endPTS - b.startPTS;
e = b.startPTS + Math.min(Math.max(t - h.maxFragLookUpTolerance, .5 * t), .75 * t)
}
if (ne(e) && c >= p) return u.flushData(t, e, 1 / 0)
}
}
break;
case gu.AltAudio:
e = l, m = s, o = "Nah" === (a = n) ? null : e.alternateMediaOptionById(gu.AltAudio, a), o = Boolean(o && o.url), m = "Nah" === a ? null : e.alternateMediaOptionById(gu.AltAudio, m), m = Boolean(m && m.url), o && !m && (d.setEnabledMediaOptionSwitchContextByType(l.itemId, gu.AltAudio, s, void 0), u.resetMediaSource(f.currentTime)), c.reset(gu.AltAudio)
}
return Wu
}(r, n, i, e, t));
return Jr($i(!0), en(e).pipe(Zs(!1)))
}), tc("mediaOptionSwitch.audiovideo.out")), n = Zf(d.itemId), s = r.logger.child(uy), a = new ly(s, l, d, u, r.iframeMachine, o);
return ed([d.anchorTime$.pipe(tc("anchorTime.audiovideo.in")), i]).pipe(La(([i, e]) => e ? Ii : u.needData$(o.maxBufferHole, t.inGaplessMode).pipe(hr(e => {
var t = [d.enabledMediaOptionSwitchContexts[gu.Variant], d.enabledMediaOptionSwitchContexts[gu.AltAudio]];
return u.getSourceBufferInfoAction(e, i, t, o.maxBufferHole)
}), _s(e => e ? fn($i(e).pipe(hy(r, a), my(r)), Gu(function(e) {
const {
mediaSink: t,
rootPlaylistQuery: i,
rootPlaylistService: r
} = e, n = t.mediaQuery, s = e.logger.child($g);
return an((a = i, o = s, ed([n.fellBelowLowWater$, a.getInFlightFragByType$(gu.Variant)]).pipe(La(e => {
var [, t] = e;
if (!Zg(t)) return Ii;
const i = performance.now() - t.bwSample.trequest,
r = ey - i,
n = 1e3 * t.duration - i,
s = [Wu];
return 0 < r && s.push(bn(r)), 0 < n && s.push(bn(n)), an(...s).pipe(Zs(e))
}), sa((e, [t, i]) => {
const r = Object.assign({}, e);
return t && (r.fragDownloadSlow = !0), ty(i, r, a, o)
}, {
fragDownloadSlow: !1,
fragDownloadTooSlow: !1
}), Ra({
fragDownloadSlow: !1,
fragDownloadTooSlow: !1
}), Is(Jg))), function(r) {
const s = r.mediaSink.mediaQuery,
{
rootPlaylistQuery: e,
config: a
} = r;
return s.desiredRate$.pipe(La(t => 0 === t ? Ii : ed([e.getInFlightFragByType$(gu.Variant), e.mediaOptionListQueries[gu.Variant].preferredMediaOptionList$.pipe(hr(e => e.filter(Wm.bind(null, Wp(t)))))])), ao(100), La(e => {
const [t, i] = e;
if (!Zg(t) || i.findIndex(e => e.mediaOptionId === t.mediaOptionId) <= 0) return Ii;
var r = performance.now() - t.bwSample.trequest,
n = Vg(t.duration, a.maxStarvationDelay),
n = Math.min(1e3 * n, 500 * t.duration / s.playbackRate);
return bn(Math.max(0, n - r), 100).pipe(Zs(e))
})).pipe(sa((e, [t, i]) => function(t, i, r, e) {
let {
fragDownloadSlow: n,
fragDownloadTooSlow: s
} = t;
const {
config: a,
rootPlaylistService: o,
rootPlaylistQuery: l,
mediaSink: d,
statsService: u,
mediaLibraryService: c
} = e, h = e.logger.child($g), p = d.mediaQuery;
if (p.paused) return t;
e = i.bwSample;
if (!ne(e.tfirst)) return t;
const f = performance.now(),
m = f - e.trequest,
g = Vg(i.duration, a.maxStarvationDelay),
y = gu.Variant,
v = i.mediaOptionId,
S = l.variantMediaOptionById(v),
b = c.getQueryForOption(S),
T = S.bitrate,
E = Math.max(1, 8e3 * e.loaded / m),
I = 8 * ((ne(e.total) ? e.total : Math.max(e.loaded, Math.round(i.duration * T / 8))) - e.loaded) / E,
w = qg(p, a.maxBufferHole);
let A;
if (ne(w) && 0 < w && !ne(null === (O = p.seekTo) || void 0 === O ? void 0 : O.pos)) A = w;
else {
const N = m / 1e3;
A = N < g ? g - N : g
}
var O = n;
({
fragDownloadSlow: n,
fragDownloadTooSlow: s
} = ty(i, t, l, h));
t = 2 * ((null === (t = b.mediaOptionDetails) || void 0 === t ? void 0 : t.targetduration) || i.duration);
if (!(w <= t && (I >= A || n))) return fg().getQuery().extendMaxTTFB && fg().setExtendMaxTTFB(0), {
fragDownloadSlow: n,
fragDownloadTooSlow: s
};
O || h.warn(`likely to stall ${ae({maxTimeToLoadSec:A,minSwitchDuration:t,stats:e,elapsedMs:m,remainingTimeSec:I,instantBw:E,bufferAheadSec:w,fragDownloadSlow:n})}`), n = !0, fg().getQuery().extendMaxTTFB || fg().setExtendMaxTTFB(6e5);
let k;
const C = i.itemId,
D = u.getQueryForItem(C),
M = D.getCombinedEstimate(),
x = Object.assign(Object.assign({}, M), {
avgBandwidth: E
}),
P = D.bandwidthStatus,
R = S.iframes,
L = I >= A && !R,
_ = Hg(0, r, R, l);
if (_ < 0) return {
fragDownloadSlow: n,
fragDownloadTooSlow: s
};
t = Math.max(_, r.findIndex(e => e && e.mediaOptionId === S.mediaOptionId));
if (L) {
let e = Wg(r, i.duration, _, t, A, R, x, P, 1, 1, a, l, b, p, h);
const F = Lu.mediaOptionId;
k = e.variantMediaOption !== F || (e = Wg(r, i.duration, _, t, I, R, x, P, 1, 1, a, l, b, p, h)).variantMediaOption !== F ? e.variantMediaOption : e.lowestCandidate
} else {
const N = Hg(0, r.slice(_, t).reverse(), R, l),
i = t - 1 - N;
(0 <= N || t === _) && (k = r[i].mediaOptionId)
}
if (null != k && k !== l.abrStatus.nextMaxAutoOptionId && o.setNextMaxAutoOptionId(C, k), L) throw h.warn(`loading too slow, abort fragment loading and switch to level ${k}`), u.setBandwidthSample(Object.assign(Object.assign({}, e), {
tfirst: e.tfirst || f,
tload: e.tload || f,
complete: !0,
mediaOptionType: y
})), s = !0, new fc({
mediaOptionType: y,
mediaOptionId: v
}, k, $.FragmentAbortError);
return {
fragDownloadSlow: n,
fragDownloadTooSlow: s
}
}(e, t, i, r), {
fragDownloadSlow: !1,
fragDownloadTooSlow: !1
}), Ra({
fragDownloadSlow: !1,
fragDownloadTooSlow: !1
}), Is(Jg))
}(e)).pipe(Ra({
fragDownloadSlow: !1,
fragDownloadTooSlow: !1
}), sa((e, t) => ({
fragDownloadSlow: e.fragDownloadSlow || t.fragDownloadSlow,
fragDownloadTooSlow: e.fragDownloadTooSlow || t.fragDownloadTooSlow
})), Is(Jg), hr(e => (r.setFragLoadSlow(i.itemId, e), !1)), Vn(e => {
if (e instanceof fc) {
const e = {
fragDownloadSlow: !0,
fragDownloadTooSlow: !0
};
return r.setFragLoadSlow(i.itemId, e), $i(!0)
}
return Vi(e)
}));
var a, o
}(r), e => e)).pipe(Ds(1), Vs(() => {
Bu.forEach(e => {
l.updateInflightFrag(d.itemId, e, null, null, null)
})
})) : Ii))), hr(() => {
if (!d.getEntity(d.itemId).manualMode) {
let e = Mm.None;
var i, r, n, s;
i = Af(), r = u, n = o, s = null == r ? void 0 : r.clientWidth, a = null == r ? void 0 : r.clientHeight, r = "object" == typeof window && window.devicePixelRatio ? window.devicePixelRatio : 1, a = s && a ? {
width: s * r,
height: a * r
} : void 0, r = (r = (null === (r = i.getQuery()) || void 0 === r ? void 0 : r.viewportInfo) || {}) && a && (r.width !== a.width || r.height !== a.height), n.useViewportSizeForLevelCap && r && (i.updateViewportInfo(a), 1) && (e = Mm.PreferredListChanged);
let t = !1;
var a = d.enabledVariantMediaOption;
! function(e, t) {
const i = l.logger.child($g),
r = e.abrStatus,
n = r.fragDownloadSlow || r.fragDownloadTooSlow,
s = ne(null === (t = t.seekTo) || void 0 === t ? void 0 : t.pos);
return n && !r.fragDownloadTooSlow && s ? (i.warn("could be ignoring low bandwidth due to seek"), 0) : n
}(d, u) ? u.playbackStarted && function(e, t) {
const i = Zf(t.itemId),
r = i.getBandwidthEstimate(),
n = t.abrStatus;
if (Kg(r)) {
var t = (null === (t = i.bandwidthStatus) || void 0 === t ? void 0 : t.bandwidthSampleCount) || 0,
t = Gg(r.avgBandwidth, e.abrBandWidthUpFactor, e.abrBandWidthFactor, t)["bwUp"];
return t > n.highBWTrigger
}
}(o, d) && (e = Mm.HighBandwidth, l.setNextMinAutoOptionId(a.itemId, a.mediaOptionId)): (e = Mm.LowBandwidth, d.nextMaxAutoOptionId === Lu.mediaOptionId && (l.setNextMaxAutoOptionId(a.itemId, a.mediaOptionId), t = !0)), iy(e, o, d, u, l), t ? l.setNextMaxAutoOptionId(a.itemId, Lu.mediaOptionId) : e === Mm.HighBandwidth && l.setNextMinAutoOptionId(a.itemId, Lu.mediaOptionId)
}
}), Vs(() => {}))
}
const hy = (r, n) => e => {
const {
rootPlaylistQuery: t,
mediaSink: a
} = r, i = r.logger.child(uy);
return e.pipe(ji(tr), bo(t.enabledMediaOptionKeys$), La(([s, e]) => En(py(s, gu.Variant, r, e).pipe(Za(e => {
var e = e.detailsEntity;
if (!e.mediaOptionDetails.liveOrEvent || e.mediaOptionDetails.ptsKnown) {
const t = e.playlistDuration,
i = (null === (e = s.bufferInfoTuple[0]) || void 0 === e ? void 0 : e.buffered.end) || 0,
r = (null === (e = s.bufferInfoTuple[1]) || void 0 === e ? void 0 : e.buffered.end) || 0,
n = Math.max(i, r);
a.msDuration = ne(a.msDuration) ? Math.max(a.msDuration, t, n) : t
}
})), py(s, gu.AltAudio, r, e)).pipe(hr(e => ({
action: s,
detailsAndContext: e
})))), La(({
action: e,
detailsAndContext: t
}) => function t(n, s, a, i, d) {
var e;
const {
mediaSink: u,
iframeMachine: c,
rootPlaylistQuery: o
} = a, r = [d[gu.Variant].detailsEntity.mediaOptionDetails, null === (e = null === (e = d[gu.AltAudio]) || void 0 === e ? void 0 : e.detailsEntity) || void 0 === e ? void 0 : e.mediaOptionDetails];
let l = s.getNextFragments(i, r, n);
const h = l.reduce((e, t) => Math.max(e, ne(null == t ? void 0 : t.newMediaRootTime) ? t.newMediaRootTime : -1 / 0), -1 / 0);
return ne(h) && (u.seekTo = h, l = [null, null]), l.every(e => null == (null == e ? void 0 : e.foundFrag)) ? $i(null) : En(...l.map((t, l) => {
if (t && null != t.foundFrag) {
const i = t.foundFrag["mediaFragment"],
r = _g(a, i.keyTagInfo, {
itemId: i.itemId,
mediaOptionId: i.mediaOptionId
});
let e = Lg(a, l, t).pipe(Za(e => {
const t = e[1],
i = d[l].switchContext;
t.switchPosition = null == i ? void 0 : i.switchPosition;
const r = null !== (e = null == i ? void 0 : i.userInitiated) && void 0 !== e && e,
n = u["mediaQuery"],
{
desiredRate: s,
isIframeRate: a
} = n,
o = a && c.isStarted && s && s < 0 && s !== c.iframeRate;
(r || o) && (t.flushBeforeAppend = {
start: 0,
end: Number.POSITIVE_INFINITY
})
}));
return e = l === gu.Variant ? e.pipe(Za(e => {
const t = function(t, i, r, n) {
if (!r) return null;
const {
rootPlaylistService: s,
rootPlaylistQuery: a
} = i, o = a.itemId, l = r[1], d = l.iframe;
let u = a.getInitPTS(n);
if (null == u || !d && u.iframeMode) {
const i = null !== (r = l.startDtsTs) && void 0 !== r ? r : null;
if (null == i) return t.warn("updateInitPTS: Variant data missing."), null;
let e = null !== (t = l.timelineOffset) && void 0 !== t ? t : 0;
d && (e = null !== (t = l.iframeOriginalStart) && void 0 !== t ? t : 0), i.timescale < 1e3 && (i.timescale = 1e3 * i.timescale, i.baseTime = 1e3 * i.baseTime);
const a = B(e, i.timescale),
c = {
baseTime: i.baseTime - a.baseTime,
timescale: i.timescale
};
s.setInitPTS(o, n, i, e, c, d), u = {
variantDTS: i,
timelineOffset: e,
offsetTimestamp: c,
iframeMode: d
}
}
return u
}(n, a, e, s.discoSeqNum);
fy(n, a, e, t)
})) : en([e, Gu(o.initPTS$(s.discoSeqNum), e => {
const t = u.mediaQuery.isIframeRate;
return null != e && (t || !e.iframeMode)
})]).pipe(hr(([e, t]) => (fy(n, a, e, t), e))), en([r, e]).pipe(hr(e => e[1]))
}
return $i(null)
})).pipe(hr(e => function(g, t, e, i) {
const {
rootPlaylistQuery: r,
mediaSink: n,
config: y
} = t, v = n.mediaQuery, s = v.isIframeRate, a = r.getInitPTS(e);
if (null == a) return g.warn("No initPTS info found"), null;
const o = i[gu.Variant],
l = null == o ? void 0 : o[1];
if (l && l.iframe !== s) return g.warn(`frag mediaSeqNum ${l.mediaSeqNum} discoSeqNum ${l.discoSeqNum} mediaOptionId ${l.mediaOptionId} doesn't match mediaSink's iframeMode ${s}; discard`), null;
const S = [null, null];
if (o) {
const [g, t] = o;
let e = a.offsetTimestamp;
if (s) {
const g = t.startDtsTs,
i = B(t.timelineOffset, g.timescale);
e = {
baseTime: g.baseTime - i.baseTime,
timescale: g.timescale
}
}
S[yu.Variant] = {
initSeg: g,
dataSeg: t,
offsetTimestamp: e
}
}
const d = i[gu.AltAudio];
if (null != d) {
const [g, t] = d;
S[yu.AltAudio] = {
initSeg: g,
dataSeg: t,
offsetTimestamp: a.offsetTimestamp
}
}
const u = S.map((e, t) => {
const i = null == e ? void 0 : e.dataSeg;
if (i) {
const {
itemId: r,
mediaOptionId: n,
mediaSeqNum: s,
discoSeqNum: a,
startPts: o,
endPts: l,
duration: d,
iframe: u
} = i, c = e["offsetTimestamp"], h = b(o, c), p = b(l, c), f = Dg(i), m = S[0];
return m && m.dataSeg.dropped || i.flushBeforeAppend || !((null === (e = null === (e = v.getBufferInfo(h, y.maxBufferHole)[t]) || void 0 === e ? void 0 : e.buffered) || void 0 === e ? void 0 : e.len) >= p - h) ? {
start: h,
duration: u ? d : p - h,
itemId: r,
mediaOptionId: n,
mediaSeqNum: s,
discoSeqNum: a,
targetDuration: f.mediaOptionDetails.targetduration
} : (g.warn(`${Nu[t]} Discarding append due to complete overlap with existing buffer`), S[t] = null)
}
return null
});
return u.every(e => !e) ? null : {
appendDataTuple: S,
inFlightFrags: u,
initPTSInfo: a
}
}(n, a, s.discoSeqNum, e)), La(e => {
if (e) return $i(e); {
const e = function(e, r) {
const n = e.enabledMediaOptionKeys,
s = [null, null],
a = [null, null];
return Bu.map(e => {
var t;
if (_u(n[e])) {
const i = Dg(n[e]).mediaOptionDetailsEntity;
a[e] = null === (t = i.mediaOptionDetails) || void 0 === t ? void 0 : t.ptsKnown, s[e] = {
detailsEntity: i,
switchContext: null === (e = r[e]) || void 0 === e ? void 0 : e.switchContext
}
}
}), s
}(o, d);
return t(n, s, a, i, e)
}
}))
}(i, n, r, e, t)), tc("mediaProducerEpic.emit"))
};
function py(e, i, t, r) {
const {
rootPlaylistQuery: n,
mediaLibraryService: s,
config: a
} = t, o = r[i];
if (t.logger.child({
name: Nu[i]
}), !o || "Nah" === o.mediaOptionId) return $i({
detailsEntity: null,
switchContext: null
});
const l = s.getQueryForOption(o);
return Mr([$i(e), l.mediaOptionDetailsEntity$.pipe(Is((e, t) => (null == e ? void 0 : e.lastUpdateMillis) === (null == t ? void 0 : t.lastUpdateMillis)), ln(e => {
var t = null == e ? void 0 : e.mediaOptionDetails;
if (!t) return !0;
var i = performance.now(),
r = e.lastUpdateMillis || i,
e = t.liveOrEvent,
t = t.targetduration;
return !e || i - r < a.livePlaylistUpdateStaleness * t * 1e3
}))]).pipe(ln(([, e]) => {
if (i === gu.AltAudio && !n.altMediaOptionHasValidUrl(i, o.mediaOptionId)) return !0;
var t = null == e ? void 0 : e.mediaOptionDetails;
return null != t && (e = null !== (e = e.lastUpdateMillis) && void 0 !== e ? e : 0, !t.liveOrEvent || !t.ptsKnown || !Yg(null == t ? void 0 : t.totalduration, 0, e))
}), Ds(1), bo(n.enabledMediaOptionSwitchContextsByType$(i)), hr(([
[, e], t
]) => ({
detailsEntity: e,
switchContext: t
})))
}
function fy(e, t, i, r) {
const {
mediaLibraryService: n,
rootPlaylistQuery: s,
mediaSink: a
} = t, o = s.itemId;
null != r && (a.mediaQuery.isIframeRate || !r.iframeMode ? i && !ne(i[1].iframeMediaDuration) && (performance.now(), n.updatePTSDTS(o, i[1].mediaOptionId, r, i[1])) : e.warn("updatePTSDTS iframeMode mismatch"))
}
const my = t => e => {
const {
rootPlaylistQuery: g,
rootPlaylistService: y,
mediaSink: v,
legibleSystemAdapter: o,
statsService: l,
rtcService: d
} = t;
return e.pipe(tc("mediaConsumerEpic.in"), La(e => {
if (!e) return $i(!1);
const {
appendDataTuple: r,
inFlightFrags: m,
initPTSInfo: t
} = e, i = t["offsetTimestamp"];
return m.forEach((e, t) => {
e && y.updateInflightFrag(e.itemId, t, e, "appending", null)
}), r.forEach(e => {
e && (e = e.dataSeg, o.addLegibleSamples(i, e.captionData, e.id3Samples, e.endPts))
}), v.appendData(r, (e, t, i, r, n) => {
var s, a, o, l, d, u, c, h, p, f = null !== (f = m[t].targetDuration) && void 0 !== f ? f : 10;
return s = v, a = e, o = t, l = i, d = f, u = r, c = g, h = y, p = n, e => e.pipe(Za(() => {
h.updateConsecutiveTimeouts(c.itemId, o, !1, "append")
}), va(e => e.pipe(jr((e, t) => {
var i = e instanceof df && e.isTimeout;
if (h.updateConsecutiveTimeouts(c.itemId, o, i, "append"), i) return function(e, t, i, r, n, s, a, o) {
let l = {
errorAction: Cm.SendAlternateToPenaltyBox,
errorActionFlags: 0
};
var d = s.getCurrentWaterLevel(i.maxBufferHole),
u = d < i.almostDryBufferSec;
let c = NaN;
s = i.appendErrorMaxRetry, i = a.rootPlaylistEntity.errorsByType[r].timeouts.append;
u && s <= i || s <= t ? l.errorAction = Cm.SendEndCallback : c = 1e3 * d;
s = {
retryDelayMs: c,
maxNumRetry: s,
maxRetryDelayMs: c
};
return l = Jm(l, !1, e.response.code, n, r, a, o), rg(e, t, s, l, a, o, r, n).pipe()
}(e, t, u, o, l, p, c, h);
if (e instanceof uf) return function(e, t, i, r, n, s, a, o, l, d) {
var u = t.type,
u = o.getCurrentWaterLevelByType(u, n.maxBufferHole);
if (u >= n.almostDryBufferSec && !o.isIframeRate) {
const t = 1e3 * r,
n = {
errorAction: Cm.RetryRequest,
errorActionFlags: 0
};
return 1e3 * u < t && (d.hasFallbackMediaOptionTuple(l, s, a, !1) ? n.errorAction = Cm.SendAlternateToPenaltyBox : n.errorAction = Cm.SendEndCallback), rg(e, i, {
retryDelayMs: t,
maxNumRetry: 1 / 0,
maxRetryDelayMs: t
}, n, l, d, s, a)
}
return i < n.appendErrorMaxRetry ? t.remove(0, Number.POSITIVE_INFINITY) : (e.fatal = !0, Vi(e))
}(e, a, t, d, u, o, l, p, c, h);
if (e instanceof hf) {
const {
mediaOptionType: a,
mediaOptionId: o
} = e;
return oy(e, a, o, s, h, c)
}
throw e
}))))
}, g.highestVideoCodec).pipe(hr(e => {
m.forEach((e, t) => {
e && y.updateInflightFrag(e.itemId, t, e, "appended", null)
});
var t = e.filter(e => (null == e ? void 0 : e.fragmentType) === gu.Variant);
t.length && (l.setBufferMetric(t[0]), null == d || d.handleFragBuffered(t[0]));
e = r[yu.AltAudio];
if (null !== (t = null == e ? void 0 : e.dataSeg) && void 0 !== t && t.flushBeforeAppend || ne(null === (t = null == e ? void 0 : e.dataSeg) || void 0 === t ? void 0 : t.switchPosition)) {
const {
itemId: i,
mediaOptionId: r
} = e.dataSeg;
y.setEnabledMediaOptionSwitchContextByType(i, gu.AltAudio, r, void 0)
}
return !0
}), (n = v, s = y, a = g, e => e.pipe(Vn(e => {
if (e instanceof lf) {
var {
mediaOptionType: t,
mediaOptionId: i
} = e;
return oy(e, t, i, n, s, a)
}
throw e
}))));
var n, s, a
}))
};
function gy(d, u, c, h, p, f) {
return u = u.child({
name: "seek"
}), e => e.pipe(La((e, t) => {
if (null == e) return Ii;
var i, r, n, s, a, o, l = c.mediaQuery.seekTo$.pipe(ka(1), Kp());
return i = 0 === t, r = d, n = u, s = p, t = f, (null == (e = e) ? Ii : e instanceof Date ? (a = e, o = t, s.enabledMediaOptionByType$(gu.Variant).pipe(La(e => o.getQueryForOption(e).mediaOptionDetails$), hr(e => function(e, t) {
if (!e || 0 === e.length) return 0;
const i = [...e].sort((e, t) => t[0] - e[0]),
r = t.getTime(),
n = null !== (t = i.find(([e]) => r >= e)) && void 0 !== t ? t : i[i.length - 1],
[s, a] = n,
o = a + (r - s) / 1e3;
return Math.max(0, o)
}(e.dateMediaTimePairs, a)), Ds(1))) : function(r, e, a, n, t, o) {
let i = n.enabledMediaOptionByType$(gu.Variant).pipe(La(e => t.getQueryForOption(e).mediaOptionDetails$), ln(e => ne(null == e ? void 0 : e.totalduration)), Ds(1), hr(s => {
var e = !s.liveOrEvent,
t = s.totalduration,
i = n.itemStartOffset;
return e ? ne(r) ? 0 <= r ? r : i + (t + r) : i + (ne(s.startTimeOffset) ? s.startTimeOffset : 0) : !ne(r) || r < 0 || 0 === r && a.liveEdgeForZeroStartPositon ? yg(0, s, a) : function(e, t) {
let i = e;
var r = s.fragments[0].start,
n = s.fragments[s.fragments.length - 1].start + s.fragments[s.fragments.length - 1].duration;
return e < r ? i = r : n < e && (i = yg(0, s, a)), (e < r || n < e) && t.warn(`[live] sanitizeLiveSeek seekTo:${se(e,3)}, sanitizedSeek:${se(i,3)}, liveWindowStart:${se(r,3)}, liveWindowEnd:${se(n,3)}`), i
}(r, o)
}));
return e && (i = i.pipe(Za(e => {}))), i
}(e, i, r, s, t, n)).pipe(Vs(() => {
h.setPendingSeek(p.itemId, void 0)
}), Va(l))
}), Za(e => {
ne(e) && (c.seekTo = e)
}))
}
function yy(e) {
const {
logger: r,
rootPlaylistService: n,
rootPlaylistQuery: t
} = e, s = t.itemId;
return e => e.pipe(va(e => e.pipe(jr(e => {
if (r.error(`Got error in pipeline ${e.message} fatal:${null==e?void 0:e.fatal} handled:${null==e?void 0:e.handled}`), !(e instanceof p) || e.fatal) throw e;
return e.handled ? (t = n, i = s, bn(0).pipe(hr(() => {
t.updateEnabledMediaOptions(i)
}))) : Ii;
var t, i
}))))
}
const vy = () => e => e.pipe(tc("mediaFragmentPipelineEpic.in"), La(i => {
if (!i) return Ii;
const {
logger: e,
config: t,
platformService: r,
rootPlaylistService: n,
rootPlaylistQuery: s,
keySystemAdapter: a,
mediaSink: o,
mediaParser: l,
gaplessInstance: d,
mediaLibraryService: u
} = i, c = s["itemId"], h = o["mediaQuery"], p = a.keyStatusChange$.pipe((f = i, e => e.pipe(La(e => {
const {
decryptdata: t,
status: i,
error: r
} = e, n = f["rootPlaylistQuery"];
if ("needs-renewal" === i) return _g(f, t, null);
if ("error" !== i || !(r instanceof gc || r instanceof mc) || r.handled) return Ii; {
const {
rootPlaylistService: e,
keySystemAdapter: t
} = f;
return og(r, 0, null, e, n, t.ksQuery)
}
}), La(() => Ii))));
var f;
const m = r.getQuery(),
g = m.displaySupportsHdr$.pipe(Is(), La(e => (n.setHDRPreference(c, e, !0), Ii))),
y = m.viewportInfo$.pipe(Is((e, t) => e && t && e.width === t.width && e.height === t.height), Za(e => {
t.useViewportSizeForLevelCap && n.setViewportInfo(c, e)
}), $a(Ii)),
v = ed([s.hdrMode$.pipe(Is()), s.maxHdcpLevel$.pipe(Is())]).pipe(La(([]) => (d.inGaplessMode || 0 !== s.itemStartOffset || (o.resetMediaSource(), l.reset()), Ii))),
S = an(function(i) {
const {
rootPlaylistQuery: t,
mediaSink: r
} = i, e = t.enabledMediaOptions$.pipe(Kp(), Za(e => {
e = e[gu.AltAudio], e = _u(e) && null != (null == e ? void 0 : e.url) ? 2 : 1;
r.setExpectedSbCount(e)
})), n = en([t.enabledMediaOptionByType$(gu.Variant).pipe(ln(e => _u(e)), La(e => Dg(e).mediaOptionDetails$), Ds(1)), Gu(r.mediaQuery.updating$, e => e)]).pipe(ji(tr), Za(([e]) => {
r.bufferMonitorTargetDuration = e.targetduration
})), s = Fu.map(e => t.enabledMediaOptionByType$(e).pipe(tc("mediaOptionRetrieve.switch"), La(t => {
if (!t || !t.url || !_u(t)) return Ii;
var e = r.mediaQuery.desiredRate$.pipe(hr(e => 0 !== e), Is());
return Mg(i, t).pipe(tc("mediaOptionRetrieve.first"), $a(e), La(e => e ? function e(t, i) {
const r = t.mediaLibraryService;
return function(e) {
if (!e) return Ii;
var {
mediaOptionDetails: t,
lastUpdateMillis: i,
unchangedCount: e
} = e;
if (null == t || !t.liveOrEvent) return Ii;
if (bg(t, i)) return bn(0).pipe(Za(() => {}));
let r = Sg(t);
return 0 < e && (r /= 2, r = Math.max(r, 5e3)), r -= performance.now() - i, r += 0, r = Math.max(1e3, Math.round(r)), bn(r).pipe(Za(() => {}))
}(r.getQueryForOption(i).mediaOptionDetailsEntity).pipe(La(() => Mg(t, i, !1, !0)), La(() => e(t, i)))
}(i, t) : Ii))
})));
return an(e, n, an(...s)).pipe($a(Ii))
}(i), cy(i), function(t) {
const {
rootPlaylistQuery: i,
mediaSink: e
} = t;
return Gu(e.mediaQuery.mediaElementEntity$, e => e).pipe(La(e => i.anchorTime$.pipe(tc("anchorTime.subtitle.in"), ln(e => ne(null == e ? void 0 : e.pos)), (s => e => {
const {
rootPlaylistQuery: i,
rootPlaylistService: t,
legibleSystemAdapter: r
} = s, n = i.enabledAlternateMediaOptionByType(gu.Subtitle);
if (r.gotTracks) r.selectedTrack = n;
else {
const s = i.preferredMediaOptions[gu.Subtitle];
r.setTracks(s, n, i.getDisabledMediaOption(gu.Subtitle))
}
return e.pipe(tc("subtitleEpic.select.in"), La(() => an(r.nativeSubtitleTrackChange$.pipe(La(e => (e.mediaOptionId !== r.selectedMediaOption.mediaOptionId && t.setEnabledMediaOptionByType(e.itemId, gu.Subtitle, e), Ii))), i.enabledMediaOptionByType$(gu.Subtitle).pipe(hr(e => {
const t = _u(e) ? i.alternateMediaOptionById(gu.Subtitle, e.mediaOptionId) : e;
return r.selectedMediaOption = t, t
})).pipe(Is((e, t) => (null == e ? void 0 : e.mediaOptionId) === (null == t ? void 0 : t.mediaOptionId))))), tc("subtitleEpic.select.emit"))
})(t), (s => e => {
const {
mediaSink: t,
rootPlaylistQuery: i,
legibleSystemAdapter: r,
logger: n
} = s;
return e.pipe(tc("subtitleEpic.process.in"), La(e => {
if (!e || !e.url || !_u(e)) return $i([null, null, null]);
return ed([Dg(e).mediaOptionDetails$, i.discoSeqNum$.pipe(ln(e => ne(e)))]).pipe(La(([e, t]) => ((i, r, e) => {
const {
legibleSystemAdapter: n,
rootPlaylistQuery: t
} = i;
return t.initPTS$(e).pipe(La(t => !t || t.iframeMode ? on : n.findFrags$(r, e).pipe(La(e => r && (null == e ? void 0 : e.foundFrags) ? Sy(i, t.offsetTimestamp, e, r) : Wu))))
})(s, e, t)))
}), tc("subtitleEpic.process.emit"))
})(t))))
}(i), p).pipe(Zs(void 0), yy(i)),
b = h.seekTo$.pipe(ln(e => ne(null == e ? void 0 : e.pos)), Is((e, t) => Math.abs(e.pos - t.pos) < Number.EPSILON), La(e => (n.setAnchorTime(c, e), Ii))),
T = h.gotPlaying$.pipe(ln(e => e), Za(e => {
s.mediaOptionListQueries[gu.Variant].filteredMediaOptionList.forEach(e => {})
}), Ds(1), $a(Ii));
return an(s.pendingSeek$.pipe(gy(t, e, o, n, s, u)), function() {
const {
config: n,
mediaSink: s,
rootPlaylistQuery: e,
mediaLibraryService: t
} = i, a = (i.logger.child({
name: "live"
}), s.mediaQuery);
return e.enabledMediaOptionByType$(gu.Variant).pipe(ln(_u), La(e => t.getQueryForOption(e).mediaOptionDetailsEntity$.pipe(ln(e => {
var t;
return (null === (t = null == e ? void 0 : e.mediaOptionDetails) || void 0 === t ? void 0 : t.ptsKnown) && e.mediaOptionDetails.liveOrEvent
}), Is((e, t) => (null == e ? void 0 : e.lastUpdateMillis) === (null == t ? void 0 : t.lastUpdateMillis)))), hr(e => {
var t = e.mediaOptionDetails,
i = a.currentTime;
a.msDuration < e.playlistDuration ? s.msDuration = e.playlistDuration : ne(s.msDuration) && (s.msDuration = s.msDuration + n.livePlaylistDurationNudge);
let r = NaN;
return i < vg(i, t, e.lastUpdateMillis, n.maxBufferHole, a) && (r = yg(t.fragments[0].start, t, n), s.seekTo = r), r
}))
}(), b, S, g, y, v, function() {
const e = i.mediaSink.mediaQuery;
return Mr([$i(i), e.desiredRate$.pipe(ha())]).pipe(La(([e, [t, i]]) => {
const {
rootPlaylistQuery: s,
rootPlaylistService: r,
config: a,
mediaSink: n,
mediaLibraryService: o,
statsService: l
} = e, d = n.mediaQuery;
if (Wp(t) !== Wp(i)) iy(Mm.IframeModeChange, a, s, d, r);
else if (0 === t && 1 === i && !Bu.every(e => {
const t = s.enabledMediaOptionKeys[e],
i = o.getQueryForOption(t),
r = l.getQueryForItem(s.itemId),
n = i.mediaOptionDetailsEntity;
return !(null !== (e = null == n ? void 0 : n.mediaOptionDetails) && void 0 !== e && e.ptsKnown) || d.canContinuePlaybackWithoutGap(n.mediaOptionDetails, n.lastUpdateMillis, r.getPlaylistEstimate(), a.maxBufferHole)
})) return n.pause(), n.flushAll(0, 1 / 0, !0);
return Ii
}), $a(Ii))
}(), function(e) {
const t = e.rootPlaylistQuery,
i = e.mediaSink.mediaQuery,
r = t.enabledMediaOptionByType$(gu.Variant);
return Mr([$i(e), i.desiredRate$.pipe(ha())]).pipe(Is((e, t) => e[1] === t[1]), bo(r), La(([
[e, [t, i]], r
]) => {
t = Wp(t), i = Wp(i);
if (t === i) return Ii;
const n = e["rootPlaylistService"];
return i && e.rootPlaylistQuery.nextMaxAutoOptionId === Lu.mediaOptionId && n.setNextMaxAutoOptionId(e.rootPlaylistQuery.itemId, r.mediaOptionId), Ii
}))
}(i), T).pipe(tc("mediaFragmentPiplineEpic.emit"), Zs(void 0))
})),
Sy = (r, e, t, i) => {
const n = r.legibleSystemAdapter,
s = t.foundFrags;
return Fr(s).pipe(hr(t => {
return ((e, t, i) => {
const {
rootPlaylistQuery: r,
legibleSystemAdapter: n
} = e;
return Zr(() => ((t, i) => Rg(e, i, !1, !1).pipe(hr(e => ({
initPTS: t,
data: e,
mediaFragment: i
})), tc("retrieveSubtitleFragmentCacheEntity.emit")))(t, i).pipe(hr(({
initPTS: e,
data: t,
mediaFragment: i
}) => ({
frag: i,
cueRange: function(e, t, i, r, n) {
if (e) return n.processSubtitleFrag(e, t, i, r)
}(r.enabledAlternateMediaOptionByType(gu.Subtitle), i, e, t, n)
}))))
})(r, e, t).pipe((i = e => n.checkReadyToLoadNextSubtitleFragment$(t, s).pipe(ln(e => e)), function(e) {
return e.lift(new gs(i))
}));
var i
}), Yr(r.config.vttConcurrentLoadCount), Za(e => {
n.reviewParsedFrag(e, t, i) !== kp.CloseEnough && r.legibleSystemAdapter.tryAgain$.next(!0)
}))
},
by = (e, t) => {
let i, r = "";
return i = e.videoCodec && e.audioCodec ? (r = `${e.videoCodec}, ${e.audioCodec}`, t = null != t ? t : "video/mp4", "audiovideo") : e.videoCodec ? (r = `${e.videoCodec}`, t = null != t ? t : "video/mp4", "video") : (r = `${null!==(e=e.audioCodec)&&void 0!==e?e:""}`, t = null != t ? t : "audio/mp4", "audio"), {
mimeType: `${t};codecs=${r}`,
codec: r,
container: t,
type: i
}
};
class Ty {
constructor(e, t, i) {
this.config = e, this.logger = t, this.demuxClient = i, this.typeSupported = {
mp4: MediaSource.isTypeSupported("video/mp4"),
mpeg: MediaSource.isTypeSupported("audio/mpeg"),
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"'),
ec3: MediaSource.isTypeSupported('audio/mp4; codecs="ec-3"')
}, this.demuxers = [], this.lastInitFrags = [], this.lastFrags = []
}
parseInitSegment(h, e) {
return this.getDemuxerInfo(h, this.lastInitFrags, e, this.demuxClient).pipe(La(({
demuxer: e,
contiguous: t,
trackSwitch: i,
discontinuity: r,
accurateTimeOffset: n
}) => {
const s = h["frag"],
{
keyTagInfo: a,
start: o,
mediaOptionType: l
} = s;
if (this.lastInitFrags[l] = s, h.initSegment) {
const e = ze.remuxInitSegment(new Uint8Array(h.initSegment), this.logger, a),
t = Ze.parseInitSegment(e),
{
mimeType: i,
type: r,
codec: n,
container: s
} = by(t);
return $i({
moovData: t,
mimeType: i,
track: {
type: r,
codec: n,
initSegment: e,
container: s
}
})
}
const d = h.segment || h.initSegment,
u = d ? h.initSegment : void 0,
c = Oc(e.observer);
return $i(c.event(v.FRAG_PARSING_INIT_SEGMENT).pipe(hr(this.handleInitSegmentData)), c.event(x.INTERNAL_ERROR).pipe(La(this.handleError)), e.pushWithoutTransfer(d, a, u, o, r, i, t, h.totalDuration, n, void 0, h.iframeMediaStart, h.iframeDuration).pipe($a(Ii))).pipe(Yr(), Ds(1))
}))
}
parseSegment(y, e) {
return this.getDemuxerInfo(y, this.lastFrags, e, this.demuxClient).pipe(La(({
demuxer: e,
contiguous: t,
trackSwitch: i,
discontinuity: r,
accurateTimeOffset: n
}) => {
const {
frag: h,
defaultInitPTS: p
} = y, {
keyTagInfo: s,
start: a,
duration: f,
mediaOptionType: m
} = h;
let g;
this.lastFrags[m] = h;
const o = Oc(e.observer);
return $i(o.event(v.FRAG_PARSING_INIT_SEGMENT).pipe(La(e => {
var t;
return e.track.initSegment.byteLength !== (null === (t = y.initSegment) || void 0 === t ? void 0 : t.byteLength) && (g = this.handleInitSegmentData(e)), Ii
})), o.event(v.FRAG_PARSING_DATA).pipe(hr(e => {
var {
startPTS: t,
startDTS: i,
firstKeyframePts: r,
framesWithoutIDR: n,
dropped: s,
data1: a,
data2: o,
captionData: l,
id3Samples: d
} = e;
let {
endPTS: u,
endDTS: c
} = e;
return null == u && (this.logger.warn(`${Nu[m]} ${Vp(h)}: null endPTS parsed, using duration ${f}`), u = Object.assign(Object.assign({}, t), {
baseTime: t.baseTime + B(f, t.timescale).baseTime
})), null == c && (this.logger.warn(`${Nu[m]} ${Vp(h)}: null endDTS parsed, using duration ${f}`), c = Object.assign(Object.assign({}, i), {
baseTime: i.baseTime + B(f, i.timescale).baseTime
})), ne(y.iframeMediaStart) || function(e, t, i, r) {
let n = NaN,
s = NaN;
if (ne(i)) s = i, n = .01, isFinite(s) && isFinite(r) && (s += r);
else {
{
const o = void 0
}
}
var {
startPTS: a,
startDTS: i,
endPTS: r,
endDTS: t
} = t;
if (!(0 <= a.baseTime && 0 <= i.baseTime && 0 < e.duration && (null == r || 0 < b(r, a)) && (null == t || 0 < b(t, i)) && (!ne(n) || !ne(s) || Math.abs(S(i) - s) <= n))) throw new D(!1, `Failed demuxer sanity check frag=${Vp(e)} parsed=${JSON.stringify({startPTS:a,endPTS:r,startDTS:i,endDTS:t})} ${ae({expectedStartDTS:s,fudge:n})}`, $.FailedDemuxerSanityCheck)
}(h, e, (p, y.iframeMediaStart), this.config.audioPrimingDelay), {
startPTS: t,
endPTS: u,
startDTS: i,
endDTS: c,
firstKeyframePts: r,
framesWithoutIDR: n,
dropped: s,
data1: a,
data2: o,
captionData: l,
id3Samples: d,
parsedInitSegment: g
}
})), o.event(x.INTERNAL_ERROR).pipe(La(this.handleError)), e.push(y.segment, s, y.initSegment, a, r, i, t, y.totalDuration, n, p, y.iframeMediaStart, y.iframeDuration).pipe($a(Ii))).pipe(Yr(), Ds(1))
}))
}
reset(e) {
if (null == e) return this.demuxers.forEach(e => {
e && e.destroy()
}), void(this.demuxers = []);
const t = this.demuxers[e];
null == t || t.destroy(), this.demuxers[e] = null
}
destroy(e) {
null != e ? this.reset(e) : this.reset()
}
willBeTrackSwitch(e, t) {
var {
mediaOptionType: i,
mediaOptionId: e
} = e, i = (t || this.lastFrags)[i];
return !(i && i.mediaOptionId === e)
}
getDemuxerInfo(e, r, t, i) {
const {
frag: n,
ptsKnown: s,
seeking: a,
live: o
} = e, {
discoSeqNum: l,
mediaSeqNum: d,
mediaOptionType: u
} = n;
return Zr(() => {
var e = this.demuxers[u];
return e ? $i(e) : i.init(this.typeSupported, this.config, t).pipe(Za(e => this.demuxers[u] = e))
}).pipe(hr(e => {
var t = r[u],
i = this.willBeTrackSwitch(n, r);
return {
demuxer: e,
trackSwitch: i,
discontinuity: !(t && l === t.discoSeqNum),
contiguous: !!t && !i && t.mediaSeqNum + 1 === d,
accurateTimeOffset: !a && (s || !o)
}
}))
}
handleInitSegmentData(e) {
var t = e["track"],
i = t["initSegment"],
r = Ze.parseInitSegment(i),
{
mimeType: n,
type: s,
codec: a,
container: e
} = by(r, t.container);
return {
moovData: r,
mimeType: n,
track: Object.assign(Object.assign({}, t), {
type: s,
codec: a,
initSegment: i,
container: e
})
}
}
handleError(e) {
return Vi(e)
}
}
function Ey(a, e, t, h, p, i, r, n) {
var s = h["combined"],
o = function(e) {
let t = 1 / 0;
h.playingFrag && (t = null !== (s = null === (n = e.fragments[h.playingFrag.mediaSeqNum - e.startSN]) || void 0 === n ? void 0 : n.duration) && void 0 !== s ? s : 1 / 0);
var {
minRequiredStartDuration: i,
maxRequiredStartDuration: r,
startTargetDurationFactor: n
} = a, {
targetduration: s,
averagetargetduration: e
} = e, r = n * Math.min(t, e, s, r);
return Math.max(i, r)
}(t.details);
let l = function(e, t, i) {
const {
pos: r,
combined: n,
playingFrag: s
} = h;
if (0 === n.len) return !1;
var a = t.details,
o = a.fragments;
let l = 0 != p && 1 != p || n.len >= i;
var d = o[a.fragments.length - 1],
t = o[0].start + a.totalduration;
let u = !1;
if (s) {
const c = qu.search(o, e => s.discoSeqNum - e.discoSeqNum);
u = e && s.discoSeqNum !== e.discoSeqNum || null == c || $p(c, s)
}
return l && a.liveOrEvent ? l = r <= t - d.duration : a.liveOrEvent || (l = l || t - i <= r), l = l || u, l
}(e, t, o);
return !l && 0 < s.len && null != e && e.state && (l = function(n, e, t, i, r, s, a) {
var o = null === (l = h.sbTuple[gu.Variant]) || void 0 === l ? void 0 : l.buffered,
l = null === (l = h.sbTuple[gu.AltAudio]) || void 0 === l ? void 0 : l.buffered;
if ((null == o ? void 0 : o.len) >= t && (!l || l.len >= t)) return 0;
if (!(o && n && (d = h.pos, (l = n.start + n.duration) > o.end && (n.start - o.end <= a || n.start <= o.end) && t <= l - d))) return 1 / 0;
var d = n.state;
let u = n.tstart,
c = 0;
switch (d) {
case "loading":
c += function(e, t) {
var {
bwSample: i,
duration: r
} = n;
if (!i) return 1 / 0;
r = ne(i.total) ? 8 * i.total : Math.ceil(r * e), e = 8 * i.loaded, r -= e, i = e / (performance.now() - i.tfirst) * 1e3;
if (!ne(i)) return 1 / 0;
t = t.avgBandwidth;
return r / Math.min(t, i)
}(e, i), u = n.tstart + 1e3 * c;
case "loaded":
case "parsing":
c += function(e, t) {
t = ne(t.avgParseTimeMs) ? t.avgParseTimeMs : 0;
return performance.now() < e ? t / 1e3 : Math.max(0, t - (performance.now() - e)) / 1e3
}(u, r), u = n.tstart + 1e3 * c;
case "parsed":
case "appending":
c += function(e, t) {
t = ne(t.avgDataFragAppendMs) ? t.avgDataFragAppendMs : 0;
return performance.now() < e ? t / 1e3 : Math.max(0, t - (performance.now() - e)) / 1e3
}(u, s);
break;
default:
c = 1 / 0
}
return c
}(e, t.variant.bitrate, o, i, r, n, a.maxBufferHole) <= s.len), l
}
function Iy(e, t, i, r) {
if (200 === t && r && 10 < r.length) {
if (Rm.isValidPlaylist(r)) return !0; {
const t = new R(o, _, !0, "response doesnt have #EXTM3U tag", $.PlaylistErrorMissingEXTM3U);
throw t.url = e, t
}
}
return !1
}
const wy = {
name: "pltfrm"
};
function Ay(e, t) {
t = Ah.getKeySystemSecurityLevel(t);
return null != e && void 0 !== t[e]
}
function Oy(e) {
return e.every(e => e.iframes)
}
function ky(e, t) {
return !ne(e) || !ne(t) || e <= t
}
function Cy() {
const n = new Set,
s = new Set;
return e => {
const i = (e, t) => {
t = t ? "audio" : "video";
n.has(e) || s.has(e) || (((e, t) => {
let i = MediaSource.isTypeSupported(`${e}/mp4;codecs=${t}`);
return "mp4a.40.34" !== t || i || (i = MediaSource.isTypeSupported(`${e}/mpeg`)), i
})(t, e) ? n : s).add(e)
},
t = (e, t) => (i(e, t), s.has(e));
let r = !1;
return e.audioCodecList && (r = e.audioCodecList.some(e => t(e, !0))), !r && e.videoCodecList && (r = e.videoCodecList.some(e => t(e, !1))), !r
}
}
function Dy(e, t) {
for (const i in e)
if (e[i].type === t) return e[i];
return {}
}
function My(e, t, i) {
t.filter(e => !i.includes(e)).map(e => e.mediaOptionId)
}
function xy(e, i, s) {
const a = new Map,
r = new Array;
return e.forEach(t => {
var e = Array();
! function(e, t, i) {
var r = Wc.getCapabilities(t.videoCodecList, t.audioCodecList),
t = JSON.stringify(r);
let n;
a.has(t) ? n = a.get(t) : (n = Ah.requestKeySystemAccess(e, r, void 0, s).pipe(hr(() => !0), Vn(e => (s.warn(`Request key system error: ${e.message}`), $i(!1))), Oa({
bufferSize: 1,
refCount: !0
})), a.set(t, n)), i.push(n)
}(i, t, e);
e = en(e).pipe(hr(e => {
if (void 0 === e.find(e => !1 === e)) return t
}));
r.push(e)
}), en(r).pipe(hr(e => e.filter(e => Boolean(e))))
}
function Py(e, r) {
const o = new Set,
l = new Set,
d = !MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.2"; channels="-1"'),
u = d && !MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.2"; channels="2"; features="INVALID"'),
t = e.filter(e => {
let t = !1;
var i;
return e.audioCodecList && e.audioGroupId && (i = fm.getRichestChannelLayoutForGroupId(e.audioGroupId, r), 0 < e.audioCodecList.length && i && (t = ((e, t) => {
var i, r, n, s = be.isDolbyAtmos(e, t);
if (u || d && !s) {
n = `${i=e}/${r=t}`, o.has(n) || l.has(n) || (((e, t) => {
const i = t.split("/"),
r = parseInt(i[0]);
let n, s;
if (1 < i.length) {
const t = i[1].split(",")[0];
n = `audio/mp4;codecs="${e}";channels="${r}";features="${t}"`, s = `audio/mp4;codecs="${e}";channels="8";features="${t}"`
} else n = `audio/mp4;codecs="${e}";channels="${r}"`;
let a = MediaSource.isTypeSupported(n);
return !a && s && (a = MediaSource.isTypeSupported(s)), a
})(i, r) ? o : l).add(n);
const a = `${e}/${t}`;
return l.has(a)
}
return !!s
})(fm.getRichestAudioCodec(e.audioCodecList), i))), !t
});
return My(0, e, t), t
}
function Ry(e, t, l) {
const n = 0 < (null == t ? void 0 : t.length),
i = e.filter(o => {
var e = function() {
if (!l) return {
highestPlayableAverageBitRate: void 0,
highestPlayablePeakBitRate: void 0,
highestPlayableWidth: void 0,
highestPlayableHeight: void 0,
highestPlayableFrameRate: void 0
};
const e = o.videoCodec,
t = o.videoRange,
i = l.videoDynamicRangeFormats,
r = l.videoCodecs,
n = be.getDynamicRangeType(t, e),
s = be.getCompressionType(e),
a = function(e, t, i, r) {
if (!r && !i) return {};
var n, s, t = i ? Dy(i, t) : {},
r = r ? Dy(r, e) : {};
let a, o;
return o = e === fe.SDR ? (a = t, r) : (a = r, t), n = Object.assign({}, a), s = o, Object.keys(s).forEach(e => {
n[e] || (n[e] = s[e])
}), n
}(n, s, r, i);
return s !== me.VP09 && (a.highestPlayablePeakBitRateForClearContent = void 0), a
}(),
t = e["highestPlayablePeakBitRateForClearContent"],
i = o.allowedCPCMap || n,
r = ky(o.bandwidth, e.highestPlayablePeakBitRate);
return (i || !t ? r : r || ky(o.bandwidth, t)) && ky(o.avgBandwidth, e.highestPlayableAverageBitRate) && ky(o.width, e.highestPlayableWidth) && ky(o.height, e.highestPlayableHeight) && ky(o.frameRate, e.highestPlayableFrameRate)
});
return My(0, e, i), i
}
function Ly(e, a, o, l, d, u) {
var r = (null == l ? void 0 : l.maxHdcpLevel) || void 0;
let c = [...e];
(0 < d.disableVideoCodecList.size || 0 < d.disableAudioCodecList.size) && (c = function(e, t, i) {
let r = e.filter(e => !e.videoCodec || e.videoCodecList.every(e => {
e = qp(e);
return !t.has(e)
}));
return r = r.filter(e => !(!e.iframes && e.audioCodec) || e.audioCodecList.every(e => {
e = jp(e);
return !i.has(e)
})), My(0, e, r), r
}(c, d.disableVideoCodecList, d.disableAudioCodecList)), r && dm(r) && (c = function(e) {
const t = um(r),
i = e.filter(e => {
e = e.hdcpLevel;
return !e || um(e) <= t
});
return My(0, e, i), i
}(c));
var t = null == l ? void 0 : l.maxSecurityLevel,
e = null == d ? void 0 : d.keySystemPreference;
t && e && Ay(t, e) && (c = function(e, t, i) {
function r(e) {
return Ay(e, i) ? n[e] : -1
}
const n = Ah.getKeySystemSecurityLevel(i),
s = Ah.getKeySystemFormat(i),
a = r(t),
o = e.filter(e => {
e = null !== (e = null === (e = e.allowedCPCMap) || void 0 === e ? void 0 : e[s]) && void 0 !== e ? e : [];
let t = !0;
for (const i of e)
if (t = r(i) <= a, !t) break;
return t
});
return My(0, e, o), [...o]
}(c, t, e)), c = c.map(t => {
var e;
return t.audioCodecList && t.audioGroupId && ((e = null == (e = a.find(e => e.groupId === t.audioGroupId)) ? void 0 : e.channels) && (t.audioChannelCount = parseInt(e))), t
});
const h = !(null == d || !d.useMediaKeySystemAccessFilter) && e && navigator && "function" == typeof navigator.requestMediaKeySystemAccess;
return (h ? xy(c, e, u) : $i(c)).pipe(La(e => {
if (0 === e.length || Oy(e)) throw new R(L, f, void 0, "no media option with compatible codecs found in playlist", void 0);
h && My(0, c, e);
const t = navigator && navigator.mediaCapabilities,
n = !(null == d || !d.useMediaCapabilities) && t && "function" == typeof t.decodingInfo;
let i;
return i = n ? function(e, n, s) {
const a = [],
o = Cy(),
l = function(o) {
const l = new Map,
d = navigator && navigator.mediaCapabilities;
return (i, e, t, n, r) => {
const s = {
type: "media-source"
};
n ? s.video = function(e) {
const t = {
contentType: `video/mp4;codecs=${e}`,
width: i.width,
height: i.height,
bitrate: i.bandwidth || i.avgBandwidth,
framerate: i.iframes ? 8 : i.frameRate
};
if (i.videoRange) switch (i.videoRange) {
case "PQ":
be.isDolby(e) ? (t.hdrMetadataType = Pm.DoVi, t.colorGamut = "rec2020") : (be.isHEVC(e) || be.isVP09(e)) && (t.hdrMetadataType = Pm.HDR10, t.colorGamut = "rec2020"), t.transferFunction = "pq";
break;
case "HLG":
t.colorGamut = "rec2020", t.transferFunction = "hlg"
}
return t
}(t) : s.audio = function(e, t, i) {
const r = {
contentType: `audio/mp4;codecs=${e}`
},
n = fm.getRichestChannelLayoutForGroupId(t.audioGroupId, i);
return n && (r.channels = be.getChannelCount(n).toString(), r.spatialRendering = be.isDolbyAtmos(e, n)), r
}(t, i, e);
e = JSON.stringify(s);
let a;
return l.has(e) ? a = l.get(e) : (a = Fr(d.decodingInfo(s)).pipe(hr(e => {
const t = e.configuration || e.supportedConfiguration,
i = t instanceof Object && (!s.video || null == Object.keys(s.video).find(e => !(e in t.video))) && (!s.audio || null == Object.keys(s.audio).find(e => !(e in t.audio))),
r = e.supported && (!n || e.powerEfficient) && i;
return r || o.warn(wy, `Unsupported config ${e.supported}/${e.powerEfficient}/${i} ${JSON.stringify(s)} supportedConfig=${JSON.stringify(t)}`), r
})), l.set(e, a)), [...r, a]
}
}(s);
return e.forEach(t => {
var e;
let i = [];
if (null === (e = t.videoCodecList) || void 0 === e || e.forEach(e => {
i = l(t, n, e, !0, i)
}), 0 < (null === (e = t.audioCodecList) || void 0 === e ? void 0 : e.length)) {
const s = fm.getRichestAudioCodec(t.audioCodecList);
i = l(t, n, s, !1, i)
}
let r = $i(t);
0 < i.length && (r = en(i).pipe(hr(e => null == e.find(e => !1 === e) ? t : null), Vn(e => (s.warn(wy, `decodingInfo errror: ${e.message}`), $i(o(t) ? t : null))))), a.push(r)
}), en(a).pipe(hr(e => e.filter(e => Boolean(e))))
}(e, a, u) : $i(e = Py((r = e, s = Cy(), s = r.filter(s), My(0, r, s), e = s), a)), i.pipe(hr(e => {
if (0 === e.length || Oy(e)) throw new R(L, f, void 0, "no media option with compatible codecs found in manifest", void 0);
if (0 === (t = e = Ry(e, o, l), r = t.filter(e => !e.iframes || !e.width || !e.height || e.width * e.height <= 2488320), My(0, t, r), (e = r).length) || Oy(e)) throw new R(L, f, void 0, "no media option with compatible codecs found in manifest", void 0);
var t;
let i = (null == l ? void 0 : l.videoDynamicRangeFormats) || [];
n && 0 === i.length && (i = [{
type: fe.SDR
}, {
type: fe.HDR
}, {
type: fe.HDR10
}, {
type: fe.DolbyVision
}, {
type: fe.HLG
}]);
var {
hdrMediaOptions: r,
sdrMediaOptions: e
} = function(e, t) {
const i = t.reduce((e, t) => {
switch (t.type) {
case fe.DolbyVision:
e.doViSupported = !0;
break;
case fe.HDR10:
e.hdr10Supported = !0;
break;
case fe.HLG:
e.hlgSupported = !0
}
return e
}, {
doViSupported: !1,
hdr10Supported: !1,
hlgSupported: !1
}),
{
doViSupported: r,
hdr10Supported: n,
hlgSupported: s
} = i;
return e.reduce((e, t) => {
var i;
switch (be.getDynamicRangeType(t.videoRange, null !== (i = t.videoCodec) && void 0 !== i ? i : "")) {
case fe.HDR:
case fe.HDR10:
n && e.hdrMediaOptions.push(t);
break;
case fe.DolbyVision:
r && e.hdrMediaOptions.push(t);
break;
case fe.HLG:
s && e.hdrMediaOptions.push(t);
break;
default:
"SDR" !== t.videoRange && null != t.videoRange || e.sdrMediaOptions.push(t)
}
return e
}, {
hdrMediaOptions: new Array,
sdrMediaOptions: new Array
})
}(e, i);
if (0 === r.length && 0 === e.length || Oy(r) && Oy(e)) throw new R(L, "manifestIncompatibleVideoRangeError", void 0, "mediaOption with compatible VIDEO-RANGE not found in manifest", void 0);
return {
hdrMediaOptions: r,
sdrMediaOptions: e
}
}), Vn(e => {
throw e instanceof R && (e.fatal = !0, e.response = $.IncompatibleAsset), e
}));
var r, s
}))
}
function _y(e, t) {
return t.mediaOptionId !== e.mediaOptionId && t.persistentID === e.persistentID && t.groupId !== e.groupId
}(A = Pm = Pm || {}).HDR10 = "smpteSt2086", A.DoVi = "smpteSt2094-10", A.HDR10Plus = "smpteSt2094-40";
class Ny extends jm {
constructor(e, t, i) {
super(e, t, i)
}
static makeFilters() {
return Hm()
}
_initFilters() {
return Ny.kAllowFilters
}
get _mediaOptionType() {
return this.mediaOptionType
}
get preferredHost() {
return null
}
get preferredHost$() {
return $i(null)
}
get mediaOptionListInfo() {
var e;
return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionListTuple[this._mediaOptionType]) && void 0 !== e ? e : null
}
get mediaOptionListInfo$() {
return this.selectEntity(this.itemId, e => e && e.mediaOptionListTuple ? e.mediaOptionListTuple[this._mediaOptionType] : null).pipe(Kp())
}
getFallbackVariant(t, e, i, r) {
var n;
const s = null === (n = this.mediaOptionList) || void 0 === n ? void 0 : n.find(e => e.mediaOptionId === t);
if (!s) return null;
const a = this.filteredMediaOptionList;
if (!a) return null;
const o = Eu(s.url);
if (i) return null !== (i = a.find(e => _y(s, e) && !Au(o, e.url))) && void 0 !== i ? i : null;
let l = null;
for (const t of a) !_y(s, t) || l && !Au(o, t.url) || (l = t);
return l
}
getMatchingAlternateWithPersistentId(t, i, r) {
var e;
return null !== (e = this.preferredMediaOptionList.find(e => !(0 < (null == r ? void 0 : r.length) && r.includes(e.mediaOptionId)) && (!ne(t) || e.persistentID === t) && (!i || this.matchGroup(e, i.audioGroupId, i.subtitleGroupId, i.closedcaption)))) && void 0 !== e ? e : null
}
matchGroup(e, t, i, r) {
let n = !1;
switch (e.type) {
case "CLOSED-CAPTIONS":
n = !r || e.groupId === r;
break;
case "SUBTITLES":
n = !i || e.groupId === i;
break;
case "AUDIO":
n = !t || e.groupId === t
}
return n
}
getMatchingAlternate(e, t) {
e = this.mediaOptionFromId(e);
return this.getMatchingAlternateWithPersistentId(null == e ? void 0 : e.persistentID, t, [])
}
packageAlternateMediaOption(e, t, i) {
return t.mediaType === Su.CLOSEDCAPTION ? this.augmentClosedCaptionsWithForcedSubtitles(null == e ? void 0 : e.subtitleGroupId, t, i) : t
}
augmentClosedCaptionsWithForcedSubtitles(e, t, i) {
i = this.pairForcedSubtitleMediaOptionWithClosedCaption(e, t, i);
return i ? Object.assign(Object.assign({}, t), {
url: i.url,
backingMediaOptionId: i.mediaOptionId
}) : t
}
pairForcedSubtitleMediaOptionWithClosedCaption(t, i, r) {
let n;
if (i && i.mediaType === Su.CLOSEDCAPTION) {
let e = this.mediaOptionList;
r && (e = this.preferredMediaOptionList), n = Ny.pairForcedSubtitleMediaOptionWithClosedCaptionInList(t, i, e)
}
return n
}
static pairForcedSubtitleMediaOptionWithClosedCaptionInList(t, i, e) {
return e.find(function(e) {
return e.mediaType === Su.SUBTITLE && e.lang === i.lang && e.forced && e.autoselect && (!t || e.groupId === t)
})
}
}
Ny.kAllowFilters = Ny.makeFilters();
class Fy extends kl {
constructor(e, t) {
super(e), this.itemId = t, this.mediaOptionListQueries = [new Xm(e, this.itemId), new Ny(e, this.itemId, gu.AltAudio), new Ny(e, this.itemId, gu.Subtitle)]
}
get rootPlaylistEntity() {
return this.getEntity(this.itemId)
}
get rootMediaOptionsTuple() {
var e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.mediaOptionListTuple;
return e ? [e[0].mediaOptions, e[1].mediaOptions, e[2].mediaOptions] : [
[],
[],
[]
]
}
get itemStartOffset() {
var e, t;
return null !== (e = this.rootPlaylistEntity) && void 0 !== e && e.itemStartOffset && ne(null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.itemStartOffset) ? null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.itemStartOffset : 0
}
get highestVideoCodec() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.highestVideoCodec
}
get baseUrl() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.baseUrl
}
get anchorTime() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.anchorTime
}
get discoSeqNum() {
var e;
return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.discoSeqNum) && void 0 !== e ? e : NaN
}
get discoSeqNum$() {
return this.selectEntity(this.itemId, "discoSeqNum")
}
get audioMediaSelectionGroup() {
var e;
return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.audioMediaSelectionGroup) && void 0 !== e ? e : null
}
get subtitleMediaSelectionGroup() {
var e;
return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.subtitleMediaSelectionGroup) && void 0 !== e ? e : null
}
get audioMediaSelectionOptions() {
var e;
return null !== (e = null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.audioMediaSelectionGroup) || void 0 === e ? void 0 : e.MediaSelectionGroupOptions) && void 0 !== e ? e : []
}
get subtitleMediaSelectionOptions() {
var e;
return null !== (e = null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.subtitleMediaSelectionGroup) || void 0 === e ? void 0 : e.MediaSelectionGroupOptions) && void 0 !== e ? e : []
}
get contentSteeringOption() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.contentSteeringOption
}
get masterVariableList() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.masterVariableList
}
get loadStats() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.loadStats
}
get isMediaPlaylist() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.isMediaPlaylist
}
getInitPTS(e) {
var t;
return null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.initPtsRecord[e]
}
get abrStatus$() {
return this.selectEntity(this.itemId, e => null == e ? void 0 : e.abrStatus)
}
get abrStatus() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus
}
get nextMaxAutoOptionId() {
var e;
return null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus) || void 0 === e ? void 0 : e.nextMaxAutoOptionId
}
get nextMinAutoOptionId() {
var e;
return null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus) || void 0 === e ? void 0 : e.nextMinAutoOptionId
}
initPTS$(t) {
return this.selectEntity(this.itemId, ({
initPtsRecord: e
}) => e[t])
}
get rootPlaylistEntity$() {
return this.selectEntity(this.itemId).pipe(ln(e => Boolean(e)), hr(e => e))
}
get rootPlaylistEntityAdded$() {
return this.selectEntityAction(Eo.Add).pipe(hr(e => e.map(e => this.getEntity(e))))
}
get rootMediaOptionsTuple$() {
return ed([this.selectEntity(this.itemId, e => e.mediaOptionListTuple[0].mediaOptions), this.selectEntity(this.itemId, e => e.mediaOptionListTuple[1].mediaOptions), this.selectEntity(this.itemId, e => e.mediaOptionListTuple[2].mediaOptions)])
}
get sessionData() {
var e;
return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.sessionData
}
get sessionData$() {
return this.selectEntity(this.itemId, ({
sessionData: e
}) => e).pipe(Kp())
}
get anchorTime$() {
return this.selectEntity(this.itemId, "anchorTime").pipe(La(e => {
var t;
return ne(null == e ? void 0 : e.pos) ? (null == e ? void 0 : e.pos) !== (null === (t = this.anchorTime) || void 0 === t ? void 0 : t.pos) ? (Qe().warn(`anchorTime doesn't match stored value! ${null==e?void 0:e.pos} !== ${null===(t=this.anchorTime)||void 0===t?void 0:t.pos}`), Ii) : $i(e) : Ii
}))
}
get pendingSeek$() {
return this.selectEntity(this.itemId, ({
pendingSeek: e
}) => e).pipe(Is((e, t) => e === t || "number" == typeof e && "number" == typeof t && isNaN(e) && isNaN(t)))
}
get enabledMediaOptionKeys$() {
return this.selectEntity(this.itemId, "enabledMediaOptionKeys").pipe(ln(e => Boolean(e)))
}
get enabledMediaOptionKeys() {
var e;
return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.enabledMediaOptionKeys) && void 0 !== e ? e : [Lu, Lu, Lu]
}
get enabledMediaOptionSwitchContexts() {
var e;
return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionSwitchContexts) && void 0 !== e ? e : [null, null, null]
}
enabledMediaOptionSwitchContextsByType$(t) {
return this.selectEntity(this.itemId, "mediaOptionSwitchContexts").pipe(hr(e => null == e ? void 0 : e[t]))
}
get enabledMediaOptions$() {
return ed([this.enabledMediaOptionByType$(gu.Variant), this.enabledMediaOptionByType$(gu.AltAudio), this.enabledMediaOptionByType$(gu.Subtitle)])
}
get enabledAVOptions$() {
return ed([this.enabledMediaOptionByType$(gu.Variant), this.enabledMediaOptionByType$(gu.AltAudio)])
}
rawEnabledMediaOptionByType$(t) {
return this.enabledMediaOptionKeys$.pipe(hr(e => {
const i = e[t];
return _u(i) && this.rootMediaOptionsTuple[t].find(e => {
return t = i, e.itemId === t.itemId && e.mediaOptionId === t.mediaOptionId;
var t
}) || Lu
}))
}
enabledMediaOptionByType$(e) {
return this.rawEnabledMediaOptionByType$(e).pipe(Is((e, t) => e.mediaOptionId === t.mediaOptionId && e.url === t.url))
}
enabledMediaOptionSwitchForType$(e) {
return this.rawEnabledMediaOptionByType$(e).pipe(bo(this.enabledMediaOptionSwitchContextsByType$(e)), Ra(null), ha(), hr(([e, t]) => ({
fromId: null == e ? void 0 : e[0].mediaOptionId,
toId: null == t ? void 0 : t[0].mediaOptionId,
switchContext: null == t ? void 0 : t[1]
})), Is((e, t) => e.fromId === t.fromId && e.toId === t.toId))
}
enableMediaOptionSwitchedForType$(t) {
return this.enabledMediaOptionByType$(t).pipe(La(e => Gu(Mr([$i(e), this.enabledMediaOptionSwitchContextsByType$(t).pipe(ha())]), ([, e]) => e[0] && !e[1])), hr(([e]) => e))
}
enabledMediaOptionIdByType(e) {
return this.getEntity(this.itemId).enabledMediaOptionKeys[e].mediaOptionId
}
get enabledVariantMediaOptionIdBeforeTrickplaySwitch() {
return this.getEntity(this.itemId).enabledVariantMediaOptionIdBeforeTrickplaySwitch
}
variantMediaOptionById(e) {
return this.mediaOptionListQueries[gu.Variant].mediaOptionFromId(e)
}
alternateMediaOptionById(e, t) {
return this.mediaOptionListQueries[e].mediaOptionFromId(t)
}
enabledAlternateMediaOptionByType(e) {
var t = this.enabledMediaOptionIdByType(e);
return this.alternateMediaOptionById(e, t)
}
get enabledVariantMediaOption() {
var e = this.enabledMediaOptionIdByType(gu.Variant);
return this.variantMediaOptionById(e)
}
lastLoadedMediaOptionByType(e) {
var t;
return null === (t = this.getEntity(this.itemId).lastLoadedMediaOptionKeys) || void 0 === t ? void 0 : t[e]
}
get nextMediaOptionsKeys$() {
return this.selectEntity(this.itemId, "nextMediaOptionKeys")
}
get preferredMediaOptions() {
return [this.mediaOptionListQueries[0].preferredMediaOptionList, this.mediaOptionListQueries[1].preferredMediaOptionList, this.mediaOptionListQueries[2].preferredMediaOptionList]
}
get preferredMediaOptions$() {
return ed([this.mediaOptionListQueries[0].preferredMediaOptionList$, this.mediaOptionListQueries[1].preferredMediaOptionList$, this.mediaOptionListQueries[2].preferredMediaOptionList$])
}
get filteredMediaOptions() {
return [this.mediaOptionListQueries[0].filteredMediaOptionList, this.mediaOptionListQueries[1].filteredMediaOptionList, this.mediaOptionListQueries[2].filteredMediaOptionList]
}
getDisabledMediaOption(e) {
return {
itemId: this.itemId,
mediaOptionType: e,
mediaOptionId: "Nah"
}
}
getEnabledMediaOptionMask() {
return this.enabledMediaOptionKeys.map(e => _u(e))
}
getPreferredMediaOptionsByType$(e) {
return this.mediaOptionListQueries[e].preferredMediaOptionList$
}
altMediaOptionHasValidUrl(e, t) {
t = this.alternateMediaOptionById(e, t);
return Boolean(null == t ? void 0 : t.url)
}
get hdrMode$() {
return this.mediaOptionListQueries[gu.Variant].hdrMode$
}
get maxHdcpLevel$() {
return this.mediaOptionListQueries[gu.Variant].maxHdcpLevel$
}
get currentPathwayID() {
return this.mediaOptionListQueries[gu.Variant].currentPathwayID
}
get preferredHost() {
return this.mediaOptionListQueries[gu.Variant].preferredHost
}
getErrorInfoByType(e) {
var t;
return null != (null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.errorsByType) ? this.rootPlaylistEntity.errorsByType[e] : null
}
getInFlightFragByType(e) {
var t;
return null !== (e = null === (t = null === (t = this.getEntity(this.itemId)) || void 0 === t ? void 0 : t.inFlightFrags) || void 0 === t ? void 0 : t[e]) && void 0 !== e ? e : null
}
getInFlightFragByType$(t) {
return this.selectEntity(this.itemId, e => {
return null === (e = null == e ? void 0 : e.inFlightFrags) || void 0 === e ? void 0 : e[t]
})
}
matchAlternates(e, t, i, r) {
t = ne(t) ? this.mediaOptionListQueries[gu.AltAudio].getMatchingAlternateWithPersistentId(t, e, r) : void 0, r = ne(i) ? this.mediaOptionListQueries[gu.Subtitle].getMatchingAlternateWithPersistentId(i, e, r) : void 0;
return [t || Lu, r || Lu]
}
getLegacyMatchingAlternateWithPersistentId(e, t, i) {
let r = this.mediaOptionListQueries[e].getMatchingAlternateWithPersistentId(t, i, []);
return r = r || this.mediaOptionListQueries[e].getMatchingAlternateWithPersistentId(t, void 0, []), r
}
isValidMediaOptionTuple(i, e) {
const r = e || this.getEnabledMediaOptionMask();
return [gu.Variant, gu.AltAudio, gu.Subtitle].reduce((e, t) => e && r[t] === _u(i[t]), !0)
}
matchGroup(e, t, i, r) {
var n = e.mediaOptionType;
return this.mediaOptionListQueries[n].matchGroup(e, t, i, r)
}
get preferHDR() {
return this.mediaOptionListQueries[gu.Variant].mediaOptionListInfo.preferHDR
}
}
const By = {
name: "rps"
};
class Uy {
constructor(e, t) {
this.store = e, this.logger = t
}
getQuery() {
return new kl(this.store)
}
getQueryForId(e) {
return new Fy(this.store, e)
}
set rootPlaylistEntity(e) {
Do("root.add.rootPlaylist"), this.store.add(e)
}
removeItems(e) {
Do(`root.add.remove ${JSON.stringify(e)}`), this.store.remove(e)
}
removeAll() {
Do("root.add.clear"), this.store.remove()
}
setRootPlaylistEntity(e, t) {
Do("root.set.rootPlaylistEntity"), this.store.update(e, e => t)
}
setSessionData(e, t) {
Do("root.set.sessionData"), this.store.update(e, e => {
e.sessionData = t
})
}
setAnchorTime(e, t) {
Do(`root.set.anchorTime: ${null==t?void 0:t.pos} ${null==t?void 0:t.discoSeqNum}`), this.store.update(e, e => {
e.anchorTime = t
})
}
setDiscoSeqNum(e, t) {
Do(`root.set.discoSeqNum: ${t}`), this.store.update(e, e => {
e.discoSeqNum = t
})
}
setPendingSeek(e, t) {
Do("root.set.pendingSeek"), this.store.update(e, e => {
e.pendingSeek = t
}), void 0 === t && fg().setUserSeek(t)
}
setEnabledMediaOptionSwitchContextByType(e, i, r, n) {
this.store.update(e, e => {
var t;
if (e.enabledMediaOptionKeys[i].mediaOptionId === r) {
const r = null !== (t = e.mediaOptionSwitchContexts) && void 0 !== t ? t : [null, null, null];
r[i] = n ? {
userInitiated: n.userInitiated,
switchPosition: n.switchPosition
} : null, e.mediaOptionSwitchContexts = r
} else Do(`root.set.mediaOptionSwitchContextByType ${r} doesn't match existing mediaOption ${e.enabledMediaOptionKeys[i].mediaOptionId}`)
})
}
setEnabledVariantMediaOptionIdBeforeTrickplaySwitch(e, t) {
this.store.update(e, e => {
e.enabledVariantMediaOptionIdBeforeTrickplaySwitch = t
})
}
setEnabledMediaOptionByType(r, n, s, a = !1, o) {
s = s || {
itemId: r,
mediaOptionType: n,
mediaOptionId: "Nah"
}, this.store.update(r, e => {
var t;
const i = null !== (t = [...e.enabledMediaOptionKeys]) ? t : [Lu, Lu, Lu];
if (i[n] = {
itemId: r,
mediaOptionId: s.mediaOptionId
}, this._updateEnabledMediaOptionKeys(e, i), a) {
const r = null !== (t = e.mediaOptionSwitchContexts) && void 0 !== t ? t : [null, null, null];
r[n] = o ? {
userInitiated: o.userInitiated,
switchPosition: o.switchPosition
} : null, e.mediaOptionSwitchContexts = r
}
})
}
_associateForcedSubtitleWithClosedCaption(e, t, i, r) {
if ((null == i ? void 0 : i.mediaType) === Su.CLOSEDCAPTION) {
t = r.variantMediaOptionById(t), r = r.mediaOptionListQueries[gu.Subtitle].packageAlternateMediaOption(t, i, !0);
if (r.url !== i.url) {
const n = jy(t, r, e.mediaOptionListTuple[gu.Subtitle].mediaOptions, Qe());
e.mediaOptionListTuple[gu.Subtitle].mediaOptions = n
}
}
}
_updateEnabledMediaOptionKeys(t, i) {
var e, r;
const n = null !== (e = t.enabledMediaOptionKeys) && void 0 !== e ? e : [Lu, Lu, Lu];
let s;
for (let e = 0; e < i.length; ++e) {
var a = i[e],
o = n[e].mediaOptionId !== a.mediaOptionId;
if (o && (n[e] = Object.assign({}, a)), e === gu.Variant) {
const i = this.getQueryForId(a.itemId).mediaOptionListQueries[e].mediaOptionList;
o ? t.abrStatus = (r = a.mediaOptionId, o = i, o = Xg(r, o), {
fragDownloadSlow: !1,
fragDownloadTooSlow: !1,
nextMinAutoOptionId: Lu.mediaOptionId,
nextMaxAutoOptionId: Lu.mediaOptionId,
highBWTrigger: o
}) : t.abrStatus.highBWTrigger = Xg(a.mediaOptionId, i), s = a
} else if (e === gu.Subtitle && _u(a)) {
const i = this.getQueryForId(a.itemId),
n = i.alternateMediaOptionById(e, a.mediaOptionId);
this._associateForcedSubtitleWithClosedCaption(t, s.mediaOptionId, n, i)
}
}
t.enabledMediaOptionKeys = n, t.nextMediaOptionKeys = void 0
}
setManualMode(e, t) {
this.store.update(e, e => {
e.manualMode = t
})
}
setEnabledMediaOptions(e, i) {
this.store.update(e, e => {
var t = i.map(({
mediaOptionId: e,
itemId: t
}) => ({
mediaOptionId: e,
itemId: t
}));
this._updateEnabledMediaOptionKeys(e, t)
})
}
setEnabledMediaOptionsAndSwitchContexts(e, i, r) {
this.store.update(e, e => {
var t = i.map(({
mediaOptionId: e,
itemId: t
}) => ({
mediaOptionId: e,
itemId: t
}));
this._updateEnabledMediaOptionKeys(e, t), e.mediaOptionSwitchContexts = r
})
}
setNextMediaOptions(e, i) {
Do(`root.set.nextMediaOptions: ${JSON.stringify(null==i?void 0:i.map(e=>e.mediaOptionId))}`), this.store.update(e, e => {
var t = i ? i.map(({
itemId: e,
mediaOptionId: t
}) => ({
itemId: e,
mediaOptionId: t
})) : null;
e.nextMediaOptionKeys = t
})
}
updateEnabledMediaOptions(e) {
Do("root.set.updateEnabledMediaOptions"), this.store.update(e, e => {
e.nextMediaOptionKeys && !0 !== e.manualMode && (Do(`root.set.updateEnabledMediaOptions ${JSON.stringify(e.nextMediaOptionKeys)}`), this._updateEnabledMediaOptionKeys(e, [...e.nextMediaOptionKeys])), e.nextMediaOptionKeys = void 0
})
}
setLastLoadedMediaOptionByType(r, n, s) {
Do(`root.set.lastLoadedMediaOptionByType: ${n} ${(s=s||{itemId:r,mediaOptionType:n,mediaOptionId:"Nah"}).mediaOptionId}`), this.store.update(r, e => {
var t;
const i = null !== (t = e.lastLoadedMediaOptionKeys) && void 0 !== t ? t : [Lu, Lu, Lu];
i[n] = {
itemId: r,
mediaOptionId: s.mediaOptionId
}, e.lastLoadedMediaOptionKeys = i
})
}
setPreferredHost(e, t) {
Do(`root.set.preferredHost: ${t}`), this.store.update(e, e => {
e && (e.mediaOptionListTuple[gu.Variant].preferredHost = t)
})
}
setViewportInfo(e, t) {
Do(`root.set.viewportInfo: ${JSON.stringify(t)}`), this.store.update(e, e => {
e && (e.mediaOptionListTuple[gu.Variant].viewportInfo = t)
})
}
static getExistingPersistentIds(e) {
var t;
const i = {},
r = null === (t = e.enabledMediaOptionKeys[gu.AltAudio]) || void 0 === t ? void 0 : t.mediaOptionId;
if ("Nah" !== r) {
const s = e.mediaOptionListTuple[gu.AltAudio],
t = Km(s.mediaOptions, Ny.kAllowFilters, s).find(e => e.mediaOptionId === r);
i.audioPersistentId = null == t ? void 0 : t.persistentID
}
const n = null === (t = e.enabledMediaOptionKeys[gu.Subtitle]) || void 0 === t ? void 0 : t.mediaOptionId;
if ("Nah" !== n) {
const s = e.mediaOptionListTuple[gu.Subtitle],
t = Km(s.mediaOptions, Ny.kAllowFilters, s).find(e => e.mediaOptionId === n);
i.subtitlePersistentId = null == t ? void 0 : t.persistentID
}
return i
}
static doUpdateRootHDRSwitch(e, t, i, r) {
const n = e.mediaOptionListTuple.map(e => Object.assign({}, e));
n[gu.Variant].preferHDR = t, n[gu.Variant].hasHdrLevels = i;
const s = mg(),
a = sy.getEntity(e.itemId),
o = Zf(e.itemId),
l = o.getBandwidthEstimate(s, null == a ? void 0 : a.serviceName),
d = o.getPlaylistEstimate(s, null == a ? void 0 : a.serviceName),
u = o.getFragEstimate(s, null == a ? void 0 : a.serviceName),
c = o.getBufferEstimate(s, null == a ? void 0 : a.serviceName),
h = {
targetDuration: u.maxDurationSec || (null == s ? void 0 : s.defaultTargetDuration),
targetStartupMs: null == s ? void 0 : s.targetStartupMs
},
p = Uy.getExistingPersistentIds(e);
return Qy(Object.assign(Object.assign({}, e), {
mediaOptionListTuple: n,
nextMediaOptionKeys: null
}), p, r, l, h, d, u, c)
}
switchToSDROnly(e) {
Do("root.switchToSDROnly"), this.store.update(e, e => {
var t = Uy.doUpdateRootHDRSwitch(e, !1, !1, this.logger)["mediaOptionListTuple"];
e.mediaOptionListTuple = t
})
}
setHDRPreference(e, i, r) {
Do(`root.set.HDRPreference: ${i}`), this.store.update(e, e => {
var t = e.mediaOptionListTuple[gu.Variant];
if (t.preferHDR !== i && (!i || t.hasHdrLevels)) {
t = Uy.doUpdateRootHDRSwitch(e, i, t.hasHdrLevels, this.logger);
if (r) return t;
e.mediaOptionListTuple = t.mediaOptionListTuple
}
})
}
setPathwayPriority(e, i) {
Do(`root.set.PathwayPriority: [ ${i.join(", ")} ]`), this.store.update(e, e => {
if (e) {
const t = e.mediaOptionListTuple[gu.Variant];
t.pathwayPriority = i, t.preferredHost = null
}
})
}
setCurrentPathwayID(e, t) {
Do(`root.set.currentPathwayID: ${t}`), this.store.update(e, e => {
e && (e.mediaOptionListTuple[gu.Variant].currentPathwayID = t)
})
}
setInitPTS(e, t, i, r, n, s) {
Do(`root.set.initPTS: ${e} ${t} variantDTS:${JSON.stringify(i)} timelineOffset: ${r}`), this.store.update(e, e => {
e.initPtsRecord[t] = {
variantDTS: i,
timelineOffset: r,
offsetTimestamp: n,
iframeMode: s
}
})
}
static prunePenaltyBox(e, t) {
return e.filter(e => !(e.expiry <= t))
}
static addToPenaltyBox(e, t, i) {
return e.push({
mediaOptionId: i,
expiry: t + 12e4
})
}
addToPenaltyBox(e, r, n) {
Do(`root.set.penaltyBox: ${r}: ${n}`), this.store.update(e, ({
mediaOptionListTuple: e
}) => {
const t = e[r],
i = performance.now();
t.penaltyBoxQueue = Uy.prunePenaltyBox(t.penaltyBoxQueue, i), Uy.addToPenaltyBox(t.penaltyBoxQueue, i, n)
})
}
prunePenaltyBox(e, r = null) {
Do(`root.set.prunePenaltyBox: ${r}`), this.store.update(e, ({
mediaOptionListTuple: e
}) => {
var e = r ? [e[r]] : e,
t = performance.now();
for (const i of e) i.penaltyBoxQueue = Uy.prunePenaltyBox(i.penaltyBoxQueue, t)
})
}
removePermanently(e, r, n) {
Do(`root.set.removePermanently: ${r}: ${n}`), this.store.update(e, ({
mediaOptionListTuple: e
}) => {
const t = e[r],
i = new Set(t.removed);
i.add(n), t.removed = Array.from(i)
})
}
moveAllWithMatchingHosts(e, r, n, s) {
Do(`root.set.moveAllMatchingHosts: ${r}:${n} remove:${s}`), this.store.update(e, ({
mediaOptionListTuple: e
}) => {
const t = e[r],
i = [...t.mediaOptions].filter(e => Au(n, e.url)).map(e => e.mediaOptionId);
if (s) {
const e = new Set([...t.removed, ...i]);
t.removed = Array.from(e)
} else {
const e = performance.now();
t.penaltyBoxQueue = Uy.prunePenaltyBox(t.penaltyBoxQueue, e);
for (const r of i) Uy.addToPenaltyBox(t.penaltyBoxQueue, e, r)
}
})
}
setMaxHdcpLevel(e, i, r = !1) {
Do(`root.set.maxHdcpLevel: ${i}`), this.store.update(e, ({
mediaOptionListTuple: e
}) => {
const t = e[gu.Variant];
(r || um(i) < um(t.maxHdcpLevel)) && (t.maxHdcpLevel = i)
})
}
updateConsecutiveTimeouts(e, i, r, n) {
this.store.update(e, e => {
const t = e.errorsByType || [{
timeouts: {
load: 0,
append: 0,
key: 0
}
}, {
timeouts: {
load: 0,
append: 0,
key: 0
}
}, {
timeouts: {
load: 0,
append: 0,
key: 0
}
}];
r ? ++t[i].timeouts[n] : t[i].timeouts[n] = 0, e.errorsByType = t
})
}
updateInflightFrag(l, d, u, c, h) {
Do("root.set.updateInflightFrag"), this.store.update(l, r => {
if (r.inFlightFrags || (r.inFlightFrags = [null, null]), !(d === gu.Subtitle || u && u.itemId !== l))
if (u) {
let {
start: e,
duration: t
} = u;
var {
mediaOptionId: n,
mediaSeqNum: s,
discoSeqNum: a
} = u, o = r.inFlightFrags[d];
let i = null == o ? void 0 : o.tstart;
c !== (null == o ? void 0 : o.state) && (i = performance.now()), $p(o, u) && (e = o.start, t = o.duration), r.inFlightFrags[d] = {
itemId: l,
mediaOptionId: n,
mediaSeqNum: s,
discoSeqNum: a,
start: e,
duration: t,
tstart: i,
state: c,
bwSample: Object.assign({}, h)
}
} else r.inFlightFrags[d] = null
})
}
setNextMaxAutoOptionId(e, t) {
Do(`root.set.nextMaxAutoOptionId: ${t}`), this.store.update(e, ({
abrStatus: e
}) => {
e.nextMaxAutoOptionId = t
})
}
setNextMinAutoOptionId(e, t) {
Do(`root.set.nextMinAutoOptionId: ${t}`), this.store.update(e, ({
abrStatus: e
}) => {
e.nextMinAutoOptionId = t
})
}
setHighBWTrigger(e, t) {
Do(`root.set.setHighBWTrigger: ${t}`), this.store.update(e, ({
abrStatus: e
}) => {
e.highBWTrigger = t
})
}
setFragLoadSlow(e, t) {
Do(`root.set.setFragLoadSlow ${e} ${JSON.stringify(t)}`), this.store.update(e, ({
abrStatus: e
}) => {
e.fragDownloadSlow = t.fragDownloadSlow, e.fragDownloadTooSlow = t.fragDownloadTooSlow
})
}
pickMediaOptionTupleByPersistentId(e, t, i, r = !1, n = !1) {
var s = e.enabledMediaOptionIdByType(gu.Variant),
s = e.variantMediaOptionById(s);
let a, o;
if (t === gu.AltAudio) {
const t = e.enabledAlternateMediaOptionByType(gu.Subtitle);
o = null == t ? void 0 : t.persistentID, a = i
} else {
const t = e.enabledAlternateMediaOptionByType(gu.AltAudio);
a = null == t ? void 0 : t.persistentID, o = i
}
const l = e.getEnabledMediaOptionMask();
return l[t] = !!(ne(i) && 0 <= i), s ? this.getBestMediaOptionTupleFromVariantAndPersistentId(e, s, a, o, l, void 0, r, n, !1) : [Lu, Lu, Lu]
}
getFallbackMediaOptionTupleFromMediaOptionId(e, t, i, r, n = !1, s = !1, a = !1) {
var o = r ? [r] : [i],
l = e.enabledMediaOptionIdByType(gu.Variant),
r = e.variantMediaOptionById(l),
l = t === gu.AltAudio ? e.alternateMediaOptionById(gu.AltAudio, i) : e.enabledAlternateMediaOptionByType(gu.AltAudio),
l = null == l ? void 0 : l.persistentID,
i = t === gu.Subtitle ? e.alternateMediaOptionById(gu.Subtitle, i) : e.enabledAlternateMediaOptionByType(gu.Subtitle),
i = null == i ? void 0 : i.persistentID;
return r ? this.getBestMediaOptionTupleFromVariantAndPersistentId(e, r, l, i, void 0, o, n, s, a) : [Lu, Lu, Lu]
}
hasFallbackMediaOptionTuple(e, t, i, r) {
var n = e.mediaOptionListQueries[t].mediaOptionFromId(i);
return e.isValidMediaOptionTuple(this.getFallbackMediaOptionTupleFromMediaOptionId(e, t, i, n.backingMediaOptionId, !1, r))
}
setLegacyAlternateMediaOption(e, t, i, r, n) {
var s = e.enabledMediaOptionIdByType(gu.Variant),
s = e.variantMediaOptionById(s),
s = e.getLegacyMatchingAlternateWithPersistentId(i, r, s);
s ? this.setEnabledMediaOptionByType(t, i, s, !0, n) : this.logger.warn(`${Nu[i]} can't find matching mediaOption for persistent id ${r}`)
}
setEnabledMediaOptionTupleWithMatchedGroups(t, i, e, r) {
const n = Ky(t),
s = this.pickMediaOptionTupleByPersistentId(n, i, e);
if (!n.isValidMediaOptionTuple(s)) return this.setLegacyAlternateMediaOption(n, t, i, e, r);
al(() => {
this.setEnabledMediaOptionByType(t, i, s[i], !0, r), s[gu.Variant].mediaOptionId !== n.enabledMediaOptionIdByType(gu.Variant) && this.setPreferredHost(t, Eu(s[gu.Variant].url)), this.setEnabledMediaOptionByType(t, gu.Variant, s[gu.Variant]);
var e = i === gu.AltAudio ? gu.Subtitle : gu.AltAudio;
s[e].mediaOptionId !== n.enabledMediaOptionIdByType(e) && this.setEnabledMediaOptionByType(t, e, s[e], !1)
})
}
canSwitchToSDR(e, t, i, r = !1) {
var n = e.mediaOptionListQueries[gu.Variant].mediaOptionFromId(t),
r = this.getFallbackMediaOptionTupleFromMediaOptionId(e, gu.Variant, t, n.backingMediaOptionId, !0, i, r);
return e.isValidMediaOptionTuple(r)
}
getBestMediaOptionTupleFromVariantAndPersistentId(t, e, i, r, n, s, a, o, l) {
var d, u = t.mediaOptionListQueries[gu.Variant].listFallbackVariants(e.mediaOptionId, a, o, l, s);
let c = [Lu, Lu, Lu];
for (let e = 0; e < u.length; ++e) {
const a = u[e];
if (d = t.matchAlternates(a, i, r, s), t.isValidMediaOptionTuple([a, ...d], n)) {
c = [a, ...d];
break
}
}
return c
}
}
const $y = new class extends fl {
constructor() {
super({}, {
name: "root-playlist-store",
idKey: "itemId",
producerFn: su
})
}
akitaPreAddEntity(e) {
return null == e.errorsByType ? Object.assign(Object.assign({}, e), {
errorsByType: [{
timeouts: {
load: 0,
append: 0,
key: 0
}
}, {
timeouts: {
load: 0,
append: 0,
key: 0
}
}, {
timeouts: {
load: 0,
append: 0,
key: 0
}
}]
}) : e
}
};
new kl($y);
let Vy = null;
function Ky(e) {
return new Fy($y, e)
}
const qy = (n, e, t, s, i) => {
const {
rootMediaOptionsTuple: r,
sessionKeys: a
} = n, o = Array.from(r[gu.Variant]), l = Array.from(r[gu.AltAudio]);
let d = !1,
u = !1,
c = o.map(e => (d = d || Boolean(e.videoCodec), u = u || Boolean(e.audioCodec) || Boolean(e.audioGroupId), e));
return d && u && (c = c.filter(({
videoCodec: e
}) => Boolean(e))), Ly(o, l, a, e, t, i).pipe(hr(({
hdrMediaOptions: e,
sdrMediaOptions: t
}) => {
var i = e.concat(t),
r = 0 < e.length;
return e.concat(t),
function(e, t, i, r) {
var {
itemId: n,
itemStartOffset: s,
rootMediaOptionsTuple: a,
audioMediaSelectionGroup: o,
subtitleMediaSelectionGroup: l
} = e, d = Array.from(a[gu.AltAudio]), u = Array.from(a[gu.Subtitle]), c = t.every(e => ne(e.score)), h = t.some(e => Wm(!0, e)), p = function(e, t) {
const i = [...e];
return t ? i.sort((e, t) => e.score - t.score || t.bitrate - e.bitrate) : i.sort((e, t) => e.bitrate - t.bitrate), i
}(t, c), f = e.baseUrl, t = null === (a = e.contentSteeringOption) || void 0 === a ? void 0 : a.initPathwayID, a = e.sessionData;
return {
itemId: n,
baseUrl: f,
mediaOptionListTuple: [{
mediaOptions: p,
hasHdrLevels: i,
hasIframeLevels: h,
hasScore: c,
preferHDR: r,
compatibleIds: null,
penaltyBoxQueue: [],
removed: [],
currentPathwayID: t
}, {
mediaOptions: d,
compatibleIds: null,
penaltyBoxQueue: [],
removed: []
}, {
mediaOptions: u,
penaltyBoxQueue: [],
removed: []
}],
audioMediaSelectionGroup: o,
subtitleMediaSelectionGroup: l,
enabledMediaOptionKeys: [Lu, Lu, Lu],
mediaOptionSwitchContexts: [null, null, null],
anchorTime: {
pos: 0
},
discoSeqNum: NaN,
pendingSeek: void 0,
itemStartOffset: s,
initPtsRecord: {},
contentSteeringOption: e.contentSteeringOption,
masterVariableList: e.masterVariableList,
loadStats: e.stats,
isMediaPlaylist: e.isMediaPlaylist,
abrStatus: {
fragDownloadSlow: !1,
fragDownloadTooSlow: !1,
nextMinAutoOptionId: Lu.mediaOptionId,
nextMaxAutoOptionId: Lu.mediaOptionId,
highBWTrigger: NaN
},
sessionData: a
}
}(n, i, r, s)
}))
};
function Hy(e, t, i, r, n, s, a) {
var o, l, d, u, c, h, p, f = e.mediaOptionListTuple[gu.Variant],
m = Km(f.mediaOptions, Xm.kAllowFilters, Object.assign(Object.assign({}, f), {
compatibleIds: null
})),
g = qm(f.preferredHost, m);
return {
firstVariant: (o = g, e = Fg, f = f.hasScore, t = t, i = i, r = r, n = n, s = s, a = a, !o || o.length < 1 || o.every(e => e.iframes) ? void t.warn("no non-iframe media option found") : ((o = f ? Bg(o, i, r, n, s, a) : (l = e, d = i, u = r, c = n, h = s, p = a, o.reduce((e, t) => {
if (t.iframes) return e;
let i = e;
const r = function(e, t, i, r, n, s, a) {
var o, l, d = (o = e.bitrate, u = e.height, (l = (e, t, i) => (e - t) * (e - i) <= 0)(o, t.minValidBitrate, t.maxValidBitrate) && l(u, t.minValidHeight, t.maxValidHeight) ? mu.VALID : mu.INVALID),
o = "PQ" === (c = e.videoRange) ? pu.PQ : "HLG" === c ? pu.HLG : "SDR" === c ? pu.SDR : pu.UNKNOWN,
{
videoCodecRank: u,
audioCodecRank: c
} = {
videoCodecRank: qp((l = e).videoCodec),
audioCodecRank: jp(l.audioCodec)
},
l = e.bitrate < t.maxPreferredBitrate ? mu.VALID : mu.INVALID,
t = e.audioChannelCount || 1,
a = i && r && n && s && !Ug(e, i, r, n, s, a) ? mu.INVALID : mu.VALID;
return new Qp(d, o, u, t, c, a, l, e.height)
}(t, l, d, u, c, h, p);
return (!e || r.isGreaterThan(e.bestRank) || r.isEqualTo(e.bestRank) && t.bitrate > e.selected.bitrate) && (i = {
selected: t,
bestRank: r
}), i
}, null).selected)) || t.warn("no valid first media option found"), o)),
filteredVariants: m,
preferredVariants: g
}
}
function jy(e, t, i) {
if ((null == t ? void 0 : t.mediaType) === Su.CLOSEDCAPTION) {
const r = Ny.pairForcedSubtitleMediaOptionWithClosedCaptionInList(e.subtitleGroupId, t, i);
if (r) return t = Object.assign(Object.assign({}, t), {
url: r.url,
backingMediaOptionId: r.mediaOptionId
}), i.map(e => e.mediaOptionId === t.mediaOptionId ? t : e)
}
return i
}
function Qy(e, t, i, r, n, s, a, o) {
var l;
const d = e.itemId,
u = e.mediaOptionListTuple[gu.Variant],
c = e.mediaOptionListTuple[gu.AltAudio],
h = e.mediaOptionListTuple[gu.Subtitle],
p = Km(c.mediaOptions, Ny.kAllowFilters, c),
f = Km(h.mediaOptions, Ny.kAllowFilters, h);
let {
firstVariant: m,
filteredVariants: g
} = Hy(e, i, r, n, s, a, o);
if (!m) {
const U = u.preferHDR;
u.preferHDR = !U && u.hasHdrLevels, u.preferHDR !== U && (i.warn(`No valid first variant found, toggling hdr preference=${U}->${u.preferHDR}`), {
firstVariant: m,
filteredVariants: g
} = Hy(e, i, r, n, s, a, o))
}
if (!m) throw new V(!0, "No valid first variant found", $.NoValidAlternates);
const y = Eu(m.url),
v = {
itemId: d,
mediaOptionId: null !== (o = null == m ? void 0 : m.mediaOptionId) && void 0 !== o ? o : null
},
S = null != p && p.length ? null === (o = ((i, r, e, n) => {
if (e) {
let t;
return t = ne(i) ? e.MediaSelectionGroupOptions.find(function(e) {
return e.MediaSelectionOptionsPersistentID === i
}) : e.MediaSelectionGroupOptions.find(function(e) {
return e.MediaSelectionOptionsIsDefault
}), t = t || e.MediaSelectionGroupOptions[0], n.find(e => (!r || e.groupId === r) && e.persistentID === (null == t ? void 0 : t.MediaSelectionOptionsPersistentID))
}
})(null == t ? void 0 : t.audioPersistentId, m.audioGroupId, e.audioMediaSelectionGroup, p)) || void 0 === o ? void 0 : o.mediaOptionId : null,
b = S ? {
itemId: d,
mediaOptionId: S
} : Lu,
T = ((i, r, n, s, a, o) => {
if (s) {
let t, e;
return t = ne(i) ? s.MediaSelectionGroupOptions.find(function(e) {
return e.MediaSelectionOptionsPersistentID === i
}) : s.MediaSelectionGroupOptions.find(function(e) {
return e.MediaSelectionOptionsIsDefault
}), t && (e = a.find(e => e.mediaType === Su.CLOSEDCAPTION ? (!r || e.groupId === r) && e.persistentID === t.MediaSelectionOptionsPersistentID : e.mediaType === Su.SUBTITLE ? (!n || e.groupId === n) && e.persistentID === t.MediaSelectionOptionsPersistentID : void o.warn(By, `subtitle media option has unknown type ${e.mediaType}`))), e
}
})(null == t ? void 0 : t.subtitlePersistentId, m.closedcaption, m.subtitleGroupId, e.subtitleMediaSelectionGroup, f, i),
E = null != f && f.length ? null == T ? void 0 : T.mediaOptionId : null,
I = E ? {
itemId: d,
mediaOptionId: E,
mediaOptionType: gu.Subtitle
} : Lu,
{
mediaOptions: w,
audioGroups: A,
subtitleGroups: O
} = (t = g, l = m, t.reduce((e, t) => {
if (((e, t) => {
let i = !0;
e.videoCodec && t.videoCodec && (i = be.isCompatibleVideoCodec(e.videoCodec, t.videoCodec));
let r = !1;
e.videoRange && t.videoRange ? r = e.videoRange == t.videoRange : e.videoRange || t.videoRange || (r = !0);
let n = !0;
return e.audioCodec && t.audioCodec && (n = be.isCompatibleAudioCodec(e.audioCodec, t.audioCodec)), i && r && n
})(l, t)) {
const l = t.audioGroupId;
l && e.audioGroups.add(l), e.mediaOptions.add(t)
}
var i = t.subtitleGroupId;
i && e.subtitleGroups.add(i);
t = t.closedcaption;
return t && e.closedCaptionGroups.add(t), e
}, {
mediaOptions: new Set,
audioGroups: new Set,
subtitleGroups: new Set,
closedCaptionGroups: new Set
})),
k = Array.from(w).map(e => e.mediaOptionId),
C = m.pathwayID,
D = Object.assign(Object.assign({}, u), {
compatibleIds: k,
preferredHost: y,
currentPathwayID: C
}),
M = [],
x = c.mediaOptions.reduce((e, t) => (A.has(t.groupId) && (e.persistentIds.add(t.persistentID), M.push(t.mediaOptionId), e.filteredAudioMediaOptions.push(t), e.altAudio || (e.altAudio = !!t.url)), e), {
filteredAudioMediaOptions: [],
persistentIds: new Set,
altAudio: !1
}),
P = Object.assign(Object.assign({}, c), {
compatibleIds: M
});
let R = e.audioMediaSelectionGroup;
const L = null == R ? void 0 : R.MediaSelectionGroupOptions;
if (L) {
const e = L.reduce((e, t) => (x.persistentIds.has(t.MediaSelectionOptionsPersistentID) && e.push(t), e), new Array);
R = Object.assign(Object.assign({}, R), {
MediaSelectionGroupOptions: e
})
}
h.mediaOptions = jy(m, T, h.mediaOptions);
const _ = h.mediaOptions.reduce((e, t) => (O.has(t.groupId) && (e.persistentIds.add(t.persistentID), e.filteredSubtitleMediaOptions.push(t)), e), {
filteredSubtitleMediaOptions: [],
persistentIds: new Set
});
let N = e.subtitleMediaSelectionGroup;
const F = null == N ? void 0 : N.MediaSelectionGroupOptions;
if (F) {
const e = F.reduce((e, t) => (_.persistentIds.has(t.MediaSelectionOptionsPersistentID) && e.push(t), e), new Array);
N = Object.assign(Object.assign({}, N), {
MediaSelectionGroupOptions: e
})
}
i = [D, P, h];
let B = new Map;
mg().useHighestVideoCodecPrivate && (B = null == D ? void 0 : D.mediaOptions.reduce((e, t) => {
const i = t.videoCodecList;
if (i)
for (const t of i) {
const i = Hp(t),
r = e.get(i);
be.isHigherCodecByFamily(r, t) && e.set(i, t)
}
return e
}, B)), B.size && B.forEach((e, t) => {});
t = {
fragDownloadSlow: !1,
fragDownloadTooSlow: !1,
nextMinAutoOptionId: Lu.mediaOptionId,
nextMaxAutoOptionId: Lu.mediaOptionId,
highBWTrigger: Xg(v.mediaOptionId, D.mediaOptions)
};
return Object.assign(Object.assign({}, e), {
enabledMediaOptionKeys: [v, b, I],
mediaOptionListTuple: i,
audioMediaSelectionGroup: R,
abrStatus: t,
highestVideoCodec: B
})
}
const Wy = (o, l, d, u, c, h, p) => e => e.pipe(tc("retrieveRootMediaOptions.input"), La(t => {
var e;
if (!t) return Ii;
const {
itemId: i,
platformInfo: r
} = t, n = Ky(i), s = l["logger"];
if (n.hasEntity(i)) return $i(n);
$y.setLoading(!0);
const a = performance.now();
return function(e, t, u, c, i) {
const {
itemId: h,
url: p,
itemStartOffset: f
} = e, r = Lc(e, t);
return Lm({
url: p,
onProgress: {
getData: !0,
cb: Iy
},
xhrSetup: c.xhrSetup
}, r, i).pipe(hr(({
responseText: e,
responseURL: t,
stats: i
}) => {
var r = c["keySystemPreference"];
if (t || (u.warn("Missing response url. Reusing request url as base url"), t = p), Rm.isMediaPlaylist(e)) {
const c = "media-pl-" + Zl(),
d = Rm.parseMediaOptionPlaylist(e, t, !0, r, {}, h, c, gu.Variant, u, f);
Nc(d.mediaOptionDetails);
var n = {
itemId: h,
mediaOptionId: c,
mediaOptionType: gu.Variant,
url: p,
bandwidth: 0,
bitrate: 0,
iframes: d.mediaOptionDetails.iframesOnly,
pathwayID: "."
};
return {
itemId: h,
itemStartOffset: f,
rootMediaOptionsTuple: [
[n],
[],
[]
],
stats: i,
baseUrl: t,
initialDetails: d.mediaOptionDetails,
isMediaPlaylist: !0
}
} {
const u = Rm.parseSessionData(e, t),
c = Rm.parseSessionKeys(e, t, r),
p = Rm.parseRootPlaylist(h, e, t, !0);
if (p.playlistParsingError) throw p.playlistParsingError;
var {
variantMediaOptions: s,
contentSteeringOption: a,
masterVariableList: o
} = p, l = Rm.parseRootPlaylistAlternateMediaOptions(h, e, t, p.variantMediaOptions, !0, o);
if (l.playlistParsingError) throw l.playlistParsingError;
var {
audioAlternateOptions: n,
subtitleAlternateOptions: r,
audioMediaSelectionGroup: e,
subtitleMediaSelectionGroup: l
} = l.alternateMediaInfo;
return {
itemId: h,
itemStartOffset: f,
rootMediaOptionsTuple: [s, n, r],
stats: i,
baseUrl: t,
audioMediaSelectionGroup: e,
subtitleMediaSelectionGroup: l,
contentSteeringOption: a,
sessionData: u,
sessionKeys: c,
masterVariableList: o
}
}
}), e => e.pipe(Vn(e => {
if (e instanceof pc) throw new dc(!1, "Timeout", 0, $.ManifestTimeoutError, !0);
if (e instanceof oc) throw new dc(!1, e.message, e.code, {
code: e.code,
text: "Manifest network error"
}, !1);
throw e
})))
}(t, o, s, d, null === (e = null === (e = fg()) || void 0 === e ? void 0 : e.getQuery()) || void 0 === e ? void 0 : e.extendMaxTTFB).pipe(Za(e => p.triggerManifestLoaded(e)), Za(({
initialDetails: e,
stats: t
}) => {
e && (e = e, t = t, Cg().archiveMediaOptionDetails(e, t, !0))
}), bo(u.displaySupportsHdr$), La(([e, t]) => qy(e, r, d, t, s)), hr(e => (l.rootPlaylistEntity = function(e, t, i, r, n, s) {
const {
itemId: a,
initialSeekTime: o
} = e, l = Zf(a), d = n.enableAdaptiveStartup ? l.getBandwidthEstimate(n, e.serviceName) : void 0, u = n.enableAdaptiveStartup ? l.getPlaylistEstimate(n, e.serviceName) : void 0, c = n.enableAdaptiveStartup ? l.getFragEstimate(n, e.serviceName) : void 0, h = n.enableAdaptiveStartup ? l.getBufferEstimate(n, e.serviceName) : void 0, p = performance.now() - r;
let f;
n.targetStartupMs > p ? f = n.targetStartupMs - p : (f = n.targetStartupMs, s.warn(`Manifest load took ${p}ms and exceeds targetStartupMs: ${n.targetStartupMs}; resetting targetStartupMs to ${n.targetStartupMs}`));
const m = n.enableAdaptiveStartup ? {
targetDuration: c.maxDurationSec || n.defaultTargetDuration,
targetStartupMs: f
} : void 0,
g = Qy(t, i, s, d, m, u, c, h);
return g.pendingSeek = o, g
}(t, e, c, a, d, s), n)), lg(i, null, Lc(t, o), 0, !1, n, l, h), Vs(() => {
$y.setLoading(!1)
}))
}), tc("retrieveRootMediaOptions.emit"));
function Gy(t, o, l, d, u, c, h) {
return e => e.pipe(Kp(), La(e => {
return e ? Mr([$i(e).pipe(Wy(t.manifestLoadPolicy, l, t, d, null, u, c)), (n = t, s = o, a = h.mux, new $t(e => {
const t = new Ty(n, s, a);
return e.next(t), () => {
t.destroy()
}
})), (i = t.trickPlaybackConfig, r = o, new $t(e => {
var t = new Zu(i, r);
return e.next(t), () => {}
}))]).pipe(hr(([e, t, i]) => ({
rootPlaylistQuery: e,
mediaParser: t,
iframeMachine: i
}))) : $i(null);
var i, r, n, s, a
}))
}
wc;
return class zy extends wc {
constructor(e = {}, t) {
var i;
if (super(), this.destroy$ = new Xt, this.mediaElement$ = new yi(null), this.publicQueriesInternal$ = new yi(null), this.mediaElementAdapter = null, this.rpcService = null, this.rpcClients = null, this.platformService = Af(), this.keySystemAdapter = null, this.legibleSystemAdapter = null, this.sessionID = Zl(), this.statsService = (Jf = Jf || new Xf(Yf), Jf), this.gaplessCapable = !0, this.teardownWG$ = new Xp, this.itemQueue = new ay, (e.liveSyncDurationCount || e.liveMaxLatencyDurationCount) && (e.liveSyncDuration || e.liveMaxLatencyDuration)) throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
const m = Object.assign(Object.assign({}, Ru), e);
if (m.maxRequiredStartDuration < m.minRequiredStartDuration || m.minRequiredStartDuration < 0) throw new Error("Illegal config: bad maxRequiredStartDuration or minRequiredStartDuration");
i = (this.hlsConfig = m).buildType, oe = "production" === i;
const r = this.sessionID;
let n = "silent";
e.debug && (n = m.debugLevel), au(!0), this.logger = null !== (i = this.logger) && void 0 !== i ? i : ([M, h = {}] = [r, (c = {
sendLogs: m.sendLogs || null,
level: "log" === n ? "debug" : n,
consoleOverride: "boolean" != typeof e.debug ? e.debug : void 0,
buildType: m.buildType
}, x = c.consoleOverride, Object.assign({
name: "hls",
timestamp: c.sendLogs ? Oe.stdTimeFunctions.epochTime : Oe.stdTimeFunctions.isoTime,
browser: {
asObject: !0,
serialize: !0,
transmit: {
send: (e, t) => {}
},
write: {
debug: qe.bind(null, Ke(x || console, "debug"), "debug"),
info: qe.bind(null, Ke(x || console, "info"), "info"),
warn: qe.bind(null, Ke(x || console, "warn"), "warn"),
error: qe.bind(null, Ke(x || console, "error"), "error"),
fatal: qe.bind(null, Ke(x || console, "error"), "fatal")
}
}
}, c))], Ue && Ue.sessionId === M ? Ue.warn("Logger Singleton already setup, returning existing singleton") : (Ue = Oe($e(h)).child({
sessionId: M,
name: "hls"
}), Ue.qe = e => Ue.info(e), Ue.sessionId = M), Ue), _o = !1, Lo && (delete window.$$stores, delete window.$$queries), this.hlsConfig.audioPrimingDelay = 0, this.rootPlaylistService = (x = this.logger, Vy = new Uy($y, x), Vy), this.customUrlLoader = Pc(), this.sessionDataLoader = new Fp(m, Cc, this.customUrlLoader.load, this.logger);
var s, a, o, l, d, u, c = m.liveMaxLatencyDurationCount,
h = m.liveSyncDurationCount;
if (ne(c) && ne(h) && c <= h) throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be gt "liveSyncDurationCount"');
if (ne(m.liveMaxLatencyDuration) && (m.liveMaxLatencyDuration <= m.liveSyncDuration || !ne(m.liveSyncDuration))) throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be gt "liveSyncDuration"');
const p = fg();
p.setHlsEntity({
id: r,
config: m
});
const f = Cg(),
g = new Tf(If),
y = (Rh = Rh || new xh(Ph), Rh);
this.accessLogInstance = new rm(this, r), this.rtcService = new Kf(this, m, this.accessLogInstance, this.logger), this.playerEvents = new Ng(this, this.logger, this.rtcService);
const v = (M = this.platformService, u = M, (() => {
if ("function" == typeof matchMedia) {
var e = matchMedia("(dynamic-range: high)"),
t = matchMedia("bad query");
if (e.media !== t.media) return an($i(e), rn(e, "change")).pipe(hr(e => e.matches))
}
return $i(!0)
})().pipe(Za(e => {
u.updateSupportsHdr(e)
})).pipe($a(Ii))),
S = this.mediaElement$.pipe((s = m, o = (a = this).logger, l = this.teardownWG$, d = this.rtcService, e => e.pipe(tc("playback.mediaElementServiceEpic.in"), La(e => {
if (!e) return $i(null);
const t = new vf(e, bf, s, a, o, l, d);
return t.openMediaSource(new MediaSource), an($i(t), t)
}), tc("playback.mediaElementServiceEpic.emit"))), Aa()),
b = this.itemQueue.activeItemById$.pipe(La(e => e ? tm(m, this.statsService, e, this.logger) : Ii));
this.rpcService = (() => {
let e = null;
return null != m.createRPCService && (e = Lf(m.createRPCService, xf)), m.enableWorker && null == e && (e = _f), null == e && (e = xf), e(this.logger)
})(), this.rpcClients = (x = this.rpcService, {
crypto: new kf(x),
mux: new Cf(x)
});
var T, E, I, w, A, O, k, C, D, c = Mr([this.itemQueue.activeItemById$.pipe(Gy(m, this.logger, this.rootPlaylistService, g, this.statsService, this.playerEvents, this.rpcClients), Za(e => {
var t = null == e ? void 0 : e.rootPlaylistQuery;
this.publicQueriesInternal$.next([t, null]), this.iframeMachine = null == e ? void 0 : e.iframeMachine, t && this.playerEvents.triggerManifestParsed(t)
})), S.pipe((I = this.itemQueue.removedItems$, w = y, A = m, O = g, C = (k = this).rtcService, D = this.logger, e => Mr([((n, s, a, o, l, d, u) => e.pipe(tc("[Keys] playback.keySystemServiceEpic.in"), La(r => r ? new $t(e => {
let t = new Dh(n, r, a, o, l, d, u);
const i = an($i(t), s.pipe(jr(e => t.removeKeysForItems(e)), $a(Ii))).subscribe(e);
return function() {
u.warn("[Keys] playback.keySystemServiceEpic.unsubscribe"), i.unsubscribe(), t.destroy().subscribe(), t = void 0
}
}) : $i(null)), tc("[Keys] playback.keySystemServiceEpic.emit")))(w, I, A, O, k, C, D), ((t, i, r) => e.pipe(tc("playback.legibleServiceEpic.in"), La(e => e ? an($i(e = new _p(e, t, i, r)), e) : $i(null)), tc("playback.legibleServiceEpic.emit")))(A, k, D), e]).pipe(hr(([e, t, i]) => ({
keySystemAdapter: e,
legibleSystemAdapter: t,
mediaSink: i
})))), Za(({
keySystemAdapter: e,
legibleSystemAdapter: t,
mediaSink: i
}) => {
this.keySystemAdapter = e, this.legibleSystemAdapter = t, this.mediaElementAdapter = i
}))]).pipe(hr(([e, t]) => {
var {
keySystemAdapter: i,
legibleSystemAdapter: r,
mediaSink: n
} = t;
if (!(e && i && r && n)) return null;
var {
rootPlaylistQuery: s,
iframeMachine: t,
mediaParser: e
} = e;
return {
logger: this.logger,
config: m,
platformService: this.platformService,
statsService: this.statsService,
rtcService: this.rtcService,
rpcClients: this.rpcClients,
rootPlaylistService: this.rootPlaylistService,
rootPlaylistQuery: s,
mediaLibraryService: f,
keySystemAdapter: i,
legibleSystemAdapter: r,
mediaSink: n,
mediaParser: e,
iframeMachine: t,
customUrlLoader: this.customUrlLoader,
gaplessInstance: this
}
}), Aa()).pipe(La(u => {
if (!u) return Ii;
const {
rootPlaylistQuery: t,
mediaSink: e,
mediaLibraryService: i
} = u;
this.publicQueriesInternal$.next([t, e.mediaQuery]);
const n = e.mediaQuery,
r = $i(u).pipe(vy()),
s = t.rootPlaylistEntity$.pipe(Kp(), Ds(1), Za(() => {
this.commitEarlySelection(u.logger)
})),
a = Gu(Mr([n.haveEnough$, t.sessionData$]), ([e]) => !0 === e, 1).pipe(La(([, e]) => this.sessionDataLoader.loadSessionData(e)), Za(e => {
this.rootPlaylistService.setSessionData(t.itemId, e)
}), Vn(e => (this.logger.error(e.message), Ii))),
o = Zf(t.itemId),
l = function(d, r, u, n, s) {
const a = u.mediaQuery;
return Gu(a.combinedBuffer$, e => 0 < (null == e ? void 0 : e.length)).pipe(La(() => {
var e = ed([a.seekTo$, a.bufferedSegmentsByType$(yu.Variant)]).pipe(hr(([e, t]) => {
const i = ne(null == e ? void 0 : e.pos) ? e.pos : a.currentTime,
r = t.find(e => e.startPTS <= i && e.endPTS > i),
n = a.getBufferInfo(i, d.maxBufferHole),
s = a.getCombinedBufferInfo(i, d.maxBufferHole);
return {
pos: i,
sbTuple: n,
combined: s,
playingFrag: null !== (t = null == r ? void 0 : r.frag) && void 0 !== t ? t : null
}
})),
t = ed([r.getInFlightFragByType$(gu.Variant), r.enabledMediaOptionByType$(gu.Variant)]).pipe(La(([e, t]) => {
var i = n.getQueryForOption(t);
return En($i(e), $i(t), i.mediaOptionDetails$)
}), hr(([e, t, i]) => [e, {
variant: t,
details: i
}])),
i = ed([s.bandwidthEstimate$, s.fragEstimate$, s.bufferEstimate$]);
return ed([a.readyState$, t, e, a.desiredRate$, i])
}), ao(100, tr, {
leading: !0,
trailing: !0
}), hr(([, e, t, i, r]) => {
var [n, s] = e, [a, e, r] = r;
let o = e,
l = r;
return e && (o = {
maxDurationSec: ne(e.maxDurationSec) ? e.maxDurationSec : d.defaultTargetDuration,
avgParseTimeMs: ne(e.avgParseTimeMs) ? e.avgParseTimeMs : d.statDefaults.fragParseTimeMs
}), r && (l = {
avgBufferCreateMs: ne(r.avgBufferCreateMs) ? r.avgBufferCreateMs : d.statDefaults.fragBufferCreationDelayMs,
avgInitFragAppendMs: ne(r.avgInitFragAppendMs) ? r.avgInitFragAppendMs : d.statDefaults.initFragAppendMs,
avgDataFragAppendMs: ne(r.avgDataFragAppendMs) ? r.avgDataFragAppendMs : d.statDefaults.dataFragAppendMs
}), a = Ey(d, n, s, t, i, a, o, l), u.haveEnough = a
}), Is(), Za(e => {}), $a(Ii))
}(m, (this.logger, t), e, i, o),
d = function() {
const {
config: e,
mediaSink: t,
rootPlaylistQuery: i,
mediaLibraryService: r,
gaplessInstance: n
} = u, s = t.mediaQuery, a = i.enabledAVOptions$.pipe(La(e => En(...e.map(e => _u(e) ? r.getQueryForOption(e).mediaOptionDetails$ : $i(null)))));
return Gu(s.combinedBuffer$, e => 0 < (null == e ? void 0 : e.length)).pipe($a(ed([a, s.msReadyState$, s.updating$, s.isIframeRate$, s.isBufferedToEnd$(e.maxBufferHole, !n.inGaplessMode)])), tc("checkForEndOfStream"), ln(([, e, t, i, r]) => "open" === e && !1 === t && !i && r), Za(([e]) => {
null != e[0] && e.every(e => null == e || !1 === e.liveOrEvent && !1 === e.iframesOnly) && !n.inGaplessMode && t.endStream()
}), $a(Ii))
}(),
c = function() {
const {
config: o,
iframeMachine: l,
mediaSink: i
} = u, d = i.mediaQuery;
return d.desiredRate$.pipe(La(a => Wp(a) ? bn(0, Math.abs(1e3 / a)).pipe(hr(() => {
let e = null;
const t = d.seekable;
if (!l.isStarted || t.length < 1) return e;
var i = l.iframeClockTimeSeconds,
r = o.leftMediaTimeToAutoPause,
n = t.start(0),
s = t.end(t.length - 1);
return 1 < a && s - i < r ? (e = {
newRate: 0,
postFlushSeek: s - r
}, l.pause()) : a < 0 && i - n < a / -2 && (e = {
newRate: 1,
postFlushSeek: n
}), e
}), Kp(), Za(({
newRate: e,
postFlushSeek: t
}) => {
i.postFlushSeek = t, i.desiredRate = e
}), $a(Ii)) : Ii))
}(),
h = (f = u).config.enableIFramePreloading ? function(t) {
const {
mediaSink: e,
rootPlaylistQuery: r,
mediaLibraryService: n
} = t, i = e.mediaQuery;
return ed([i.desiredRate$, i.waterLevelChangedForType$(yu.Variant)]).pipe(La(([e, t]) => Wp(e) || t !== Dp.AboveHighWater ? Ii : r.enabledMediaOptionByType$(gu.Variant).pipe(hr(e => {
var t = r.mediaOptionListQueries[gu.Variant].hasIframes,
i = null !== (i = null === (i = n.getQuery().getEntity(r.itemId)) || void 0 === i ? void 0 : i.liveOrEvent) && void 0 !== i && i;
return !t || i ? xm.DISABLED : e
}))), Ds(1), _s(e => function(e, t) {
const i = t.logger;
return e === xm.DISABLED ? $i(e) : function(e, t) {
const {
rootPlaylistQuery: i,
logger: r,
config: n,
mediaSink: s,
statsService: a
} = t, o = s.mediaQuery, l = a.getQueryForItem(i.itemId), d = Dg(e), u = jg(!0, n, i, d, o, l, r), c = i.variantMediaOptionById(u.variantMediaOption);
return Mg(t, c, !0)
}(e, t).pipe(_s(r => function(e) {
var {
mediaSink: t,
rootPlaylistQuery: i
} = e, t = Ig((t = t.mediaQuery).currentTime, i.discoSeqNum, 0, r, []);
return null !== (i = null == t ? void 0 : t.foundFrag) && void 0 !== i && i.mediaFragment ? (t = t.foundFrag.mediaFragment, en([_g(e, t.keyTagInfo, {
itemId: t.itemId,
mediaOptionId: t.mediaOptionId
}), xg(e, t)]).pipe(Za(() => {}), Zs(xm.SUCCESS))) : Vi("Unable to find fragment for iframe prefetch")
}(t)), Zs(xm.SUCCESS), Vn(e => (i.error(ry, `got error ${e.message} in prefetch`), $i(xm.ERRORED))))
}(e, t)), Vs(() => {}))
}(f) : $i(xm.DISABLED),
p = [s, r, a, l, Gu(ed([n.gotPlaying$, n.gotLoadStart$, n.readyState$]), ([e, t, i]) => !0 === e || !0 === t || 1 <= i).pipe(La(() => n.ended$), La(e => bn(0, e ? void 0 : 1e3)), Za(() => {
this.playbackInfo(m, n)
})), c, h, n.timeupdate$.pipe(hr(e => {
if (this.inGaplessMode && this.isPreloading && ne(this.loadingItem.itemStartOffset) && e >= this.loadingItem.itemStartOffset) {
const e = this.itemQueue.playingItem.itemId,
t = this.itemQueue.loadingItem.itemId,
i = {
prevItemId: e,
nextItemId: t,
nextStartTime: this.loadingItem.itemStartOffset,
nextDuration: n.msDuration - this.loadingItem.itemStartOffset
};
this.itemQueue.updatePlayingItemId(), this.trigger(P.ITEM_TRANSITIONED, i), this.rtcService.itemTransitioned(e, t)
}
})), this.updateLiveSeekableRange(t, e), d];
var f;
if (m.enablePerformanceLogging) {
this.logger.child({
name: "timing"
});
const u = En(...Bu.map(r => t.getInFlightFragByType$(r).pipe(Is((e, t) => (null == e ? void 0 : e.state) === (null == t ? void 0 : t.state)), Kp(), bo(n.bufferedRangeTuple$), Za(([e, t]) => {
const i = Object.assign(Object.assign({}, e), {
event: "fragment",
name: Nu[r],
buffered: void 0
});
"appended" === e.state && (i.buffered = t)
}), Vn(() => Ii)))),
e = En(...Fu.map(e => t.enabledMediaOptionByType$(e).pipe(La(t => null != (null == t ? void 0 : t.url) && _u(t) ? Dg(t).mediaOptionDetailsEntity$.pipe(Kp(), hr(e => ({
entity: e,
option: t
})), Is((e, t) => (null == e ? void 0 : e.entity.detailsLoading) === (null == t ? void 0 : t.entity.detailsLoading)), Za(({}) => {})) : Ii), Vn(() => Ii))));
p.push(u, e)
}
return an(...p)
})),
h = this.itemQueue.removedItems$.pipe(ll(e => {
var t;
t = e, Cg().remove(t), this.rootPlaylistService.removeItems(e)
})),
M = p.getQuery().userSeek$.pipe((T = this.itemQueue, E = this.rootPlaylistService, e => e.pipe(Kp(), La(e => en([$i(e), T.activeItemById$.pipe(Kp(), La(e => E.getQueryForId(e.itemId).rootPlaylistEntity$), Ds(1))])), hr(([e, t]) => (E.setPendingSeek(t.itemId, e), e))))),
x = p.getQuery().selectEntityAction(Eo.Add).pipe(Za(() => {
this.logger.warn(`new Hls instance added while old one still active sessionId:${r}`)
}));
an(S.pipe(Vn(() => Ii)), an(v, M, b, h, c, this.teardownWG$).pipe(Vn(e => this._handleError(e)))).pipe(Vs(() => {
var e, t;
try {
this.detachMedia(), this.trigger(P.DESTROYING), this.playerEvents.destroy(), null === (e = this.accessLogInstance) || void 0 === e || e.destroy(), null === (t = this.rtcService) || void 0 === t || t.destroy(), Cg().clear(), this.rootPlaylistService.removeAll(), this.itemQueue.clearQueue(), p.removeEntity(this.sessionID)
} catch (e) {
this.logger.error(`Got error in finalize ${e.message}`)
}
}), Va(fn(this.destroy$, x))).subscribe()
}
get publicQueries$() {
return this.publicQueriesInternal$.pipe(ln(e => Boolean(e) && Boolean(e[0]) && Boolean(e[1])))
}
get _activeRootQuery() {
var e = this.publicQueriesInternal$.value;
return null !== (e = null == e ? void 0 : e[0]) && void 0 !== e ? e : null
}
get _mediaElementQuery() {
var e = this.publicQueriesInternal$.value;
return null !== (e = null == e ? void 0 : e[1]) && void 0 !== e ? e : null
}
static get version() {
return "2.162.2"
}
static get Events() {
return P
}
get Events() {
return zy.Events
}
static get DefaultConfig() {
return de(Ru)
}
get DefaultConfig() {
return zy.DefaultConfig
}
static isSupported() {
try {
const e = window.MediaSource || window.WebKitMediaSource,
t = window.SourceBuffer || window.WebKitSourceBuffer,
i = e && "function" == typeof e.isTypeSupported && e.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"'),
r = !t || t.prototype && "function" == typeof t.prototype.appendBuffer && "function" == typeof t.prototype.remove;
return !!i && !!r
} catch (e) {
return !1
}
}
commitEarlySelection(e) {
var t = this.itemQueue.earlyAudioSelection;
ne(t) && (this.audioSelectedPersistentID = t, this.itemQueue.earlyAudioSelection = null), ne(t = this.itemQueue.earlySubtitleSelection) && (this.subtitleSelectedPersistentID = t, this.itemQueue.earlySubtitleSelection = null)
}
_handleError(i) {
var r;
try {
let t, e = i.message;
if (this.logger.error(`Got unhandled or fatal error ${e}`, i), null === (r = this.rtcService) || void 0 === r || r.handleError(i), t = i instanceof p ? i : new V(!0, i.message, $.InternalError), t.fatal && this.isPreloading && (this.logger.warn("Fatal error seen while preloading, calling dequeueSource"), this.dequeueSource("FatalErrorWhileLoading")), t.fatal) {
let e = Wu;
if (this.mediaElementAdapter) {
const r = this.mediaElementAdapter.mediaQuery,
n = r.getCombinedBufferInfo(r.currentTime, 0);
0 < (null == n ? void 0 : n.len) && (e = Gu(this.mediaElementAdapter.mediaQuery.stallInfo$, e => null != e).pipe(hr(() => {})))
}
return e.pipe(La(() => (this.trigger(P.ERROR, t), Ii)))
}
this.trigger(P.ERROR, t)
} catch (i) {
throw this.logger.error(`Error thrown inside _handleError ${i.message}`, i), i
}
return Ii
}
updateLiveSeekableRange(e, t) {
return e.enabledMediaOptionByType$(gu.Variant).pipe(La(e => {
const t = Dg(e);
let i = 0;
return t.mediaOptionDetailsEntity$.pipe(Kp(), ln(e => {
var t = null !== e.stats && !1 === e.detailsLoading && e.lastUpdateMillis > i;
return i = null !== (e = e.lastUpdateMillis) && void 0 !== e ? e : 0, t
}))
}), La(e => (0 === e.unchangedCount && (e.mediaOptionDetails.liveOrEvent ? t.updateLiveSeekableRange(e.mediaOptionDetails) : t.clearLiveSeekableRange()), Ii)))
}
playbackInfo(i, r) {
const n = this.mediaElement$.getValue();
if (n) {
const s = n.readyState >= n.HAVE_FUTURE_DATA,
a = {
readyToPlay: s,
playbackLikelyToKeepUp: r.haveEnough && s,
rate: n.playbackRate,
paused: n.paused,
position: n.currentTime,
duration: n.duration,
seekableTimeRanges: im.timeRangeToArray(n.seekable),
loadedTimeRanges: im.timeRangeToArray(n.buffered)
};
let e = 0,
t = 0;
if (im.isHtmlVideoElement(n)) {
const o = n.getVideoPlaybackQuality;
if (o && typeof o == typeof Function) {
const o = n.getVideoPlaybackQuality();
e = a.droppedVideoFrames = o.droppedVideoFrames, a.corruptedVideoFrames = o.corruptedVideoFrames, a.totalVideoFrames = o.totalVideoFrames, t = a.totalVideoFrames - e
}
} else im.isWebkitMediaElement(n) && (e = a.droppedVideoFrames = n.webkitDroppedFrameCount, t = a.decodedFrameCount = n.webkitDecodedFrameCount);
i.enablePerformanceLogging && r.getCombinedMediaSourceBufferInfo(i.maxBufferHole), null === (i = this.rtcService) || void 0 === i || i.handlePlaybackInfo(e, t)
}
}
get currentItem() {
return this.isPreloading ? this.playingItem : this.itemQueue.activeItem
}
get realCurrentTime() {
var e, t = this._mediaElementQuery;
if (!t) return NaN;
if (null !== (e = this.iframeMachine) && void 0 !== e && e.isStarted) {
const r = t.mediaElementDuration,
e = this.iframeMachine.iframeClockTimeSeconds;
return e > r ? r : e
}
let i = ne(t.postFlushSeek) ? t.postFlushSeek : t.currentTime;
return ne(i) && ne(null === (e = this.playingItem) || void 0 === e ? void 0 : e.itemStartOffset) && (i -= this.playingItem.itemStartOffset), i
}
set realCurrentTime(e) {
var t;
ne(null === (t = this.playingItem) || void 0 === t ? void 0 : t.itemStartOffset) && (e += this.playingItem.itemStartOffset), this.seekTo = e
}
get bufferedDuration() {
var e;
const t = this._mediaElementQuery;
return null !== (e = null == t ? void 0 : t.getBufferedDuration()) && void 0 !== e ? e : 0
}
get sessionData() {
var e = this._activeRootQuery;
return null == e ? void 0 : e.sessionData
}
get supportedFrameRates() {
const e = this.hlsConfig.trickPlaybackConfig.enabled,
t = [0, 1],
i = this._activeRootQuery,
r = Cg().getQuery();
return e && i && r.getEntity(i.itemId) && !1 === r.getEntity(i.itemId).liveOrEvent && t.push(8, 24, 48, 96), t
}
loadSource(e, i, t) {
var r, n, s, a, o, l;
if ("playready" === this.config.keySystemPreference && !this.config.enablePlayReadyKeySystem) throw new V(!0, "Playready key system is not supported now", $.UnsupportedKeySystemError);
if (!e || !e.trim().length) throw new V(!0, "Empty loadSource url", $.EmptyLoadSourceError);
if (e = bu.buildAbsoluteURL(window.location.href, e, {
alwaysNormalize: !0
}), i && Object.keys(i).filter(e => 0 <= ["itemId", "streamID"].indexOf(e)).reduce((e, t) => t in i ? Object.assign(e, {
[t]: i[t]
}) : e, {}), null !== (l = null == i ? void 0 : i.appData) && void 0 !== l && l.reportingAgent && (this.reportingAgent = i.appData.reportingAgent), null != i && i.userInfo && (this.userInfo = i.userInfo), null === (a = this.accessLogInstance) || void 0 === a || a.setupReporter(i.appData), null != i && i.platformInfo && this.platformService.updatePlatformInfo(i.platformInfo), function(e, t) {
if (t) {
const t = Eu(e);
return void 0 !== Iu.find(e => new RegExp(e).exec(t))
}
}(e, this.config.enableQueryParamsForITunes)) {
const d = {
language: i.language,
dsid: i.dsid,
subs: i.subs
};
r = e, n = null == i ? void 0 : i.platformInfo, s = d, o = n.model, l = n.manufacturer, o && l || Qe().warn(`Missing model/manufacturer in platformInfo model ${o} manufacturer ${l}`), o && l && (a = r, o = n.model, l = n.manufacturer, n = -1 !== a.indexOf("?"), o = encodeURIComponent(o), l = encodeURIComponent(l), r = (a = n ? a : a + "?") + wu.deviceName + l + wu.deviceModel + o), e = function(e, t) {
let i;
e = -1 !== e.indexOf("?") ? e : e + "?";
const r = Qe();
for (i in t) t[i] ? e += wu[i] + ("subs" === i ? encodeURIComponent(t[i]) : t[i]) : r.warn(`Missing ${i} info`);
return e
}(r, s), i.inheritQuery = !1
}
this.itemQueue.setQueueItem(`item:${null!==(s=null==i?void 0:i.itemId)&&void 0!==s?s:Zl()}`, e, t, null == i ? void 0 : i.platformInfo, null === (t = null == i ? void 0 : i.appData) || void 0 === t ? void 0 : t.serviceName), fg().setStartTime(void 0)
}
queueSource(e, t, i) {
var r;
null != t && t.userInfo && (this.userInfo = t.userInfo);
var n = null === (r = this._mediaElementQuery) || void 0 === r ? void 0 : r.getCombinedBufferInfo(null === (n = this._mediaElementQuery) || void 0 === n ? void 0 : n.currentTime, 0);
let s = 0;
n && (s = n.end), this.itemQueue.addQueueItem(`item:${null!==(n=null==t?void 0:t.itemId)&&void 0!==n?n:Zl()}`, e, i, null == t ? void 0 : t.platformInfo, s, null === (t = null == t ? void 0 : t.appData) || void 0 === t ? void 0 : t.serviceName)
}
dequeueSource(e = "ApplicationInitiated") {
if (!this.isPreloading && "InvalidFormat" === e && this.isFirstItem) return this.logger.error("First item has invalid format for gapless. Probably video. Disabling gapless."), void(this.gaplessCapable = !1);
var t, i;
this.isPreloading ? (t = this.loadingItem.url, i = this.loadingItem.itemId, this.mediaElementAdapter.flushData(yu.Variant, this.loadingItem.itemStartOffset, 1 / 0), this.mediaElementAdapter.msDuration = this.loadingItem.itemStartOffset, this.itemQueue.resetLoadingItem(), "InvalidFormat" !== e && "FatalErrorWhileLoading" !== e || (this.gaplessCapable = !1), this.triggerItemEvicted({
url: t,
itemId: i
}, e)) : this.logger.warn(`Nothing to dequeue, no item is preloading dequeue reason: ${e}`)
}
triggerItemEvicted(e, t) {
null !== e ? (t = {
url: e.url,
evictedItemId: e.itemId,
reason: t
}, Object.assign(Object.assign({}, t), {
url: le(e.url)
}), this.trigger(P.ITEM_EVICTED, t)) : this.logger.error("dequeueSource called with no playing or loading item")
}
endSource() {
this.gaplessCapable = !1, this.isPreloading && (this.logger.warn("EndSource called during preloading. Loading item will be removed"), this.mediaElementAdapter.flushData(yu.Variant, this.loadingItem.itemStartOffset, 1 / 0), this.mediaElementAdapter.msDuration = this.loadingItem.itemStartOffset, this.itemQueue.resetLoadingItem())
}
get inGaplessMode() {
return mg().gapless && this.gaplessCapable
}
get isPreloading() {
return this.itemQueue.isPreloading()
}
get isFirstItem() {
return this.itemQueue.isFirstItem
}
get loadingItem() {
return this.itemQueue.loadingItem
}
get playingItem() {
return this.itemQueue.playingItem
}
get url() {
return this.playingItem ? this.playingItem.url : this.loadingItem ? this.loadingItem.url : void 0
}
destroy() {
const t = this.logger;
return this.destroy$.next(), null != this.rpcService && (this.teardownWG$.add(), this.rpcService.teardown(e => {
e && t.error("RPCService teardown error:", e), this.teardownWG$.done()
}), this.rpcService = null), null != this.iframeMachine && (this.iframeMachine.destroy(), this.iframeMachine = null), this.teardownWG$.toPromise()
}
attachMedia(e) {
this.trigger(P.MEDIA_ATTACHING, {
media: e
}), this.mediaElement$.next(e), this.trigger(P.MEDIA_ATTACHED, {
media: e
})
}
detachMedia() {
var e;
this.mediaElement$.getValue() && (this.trigger(P.MEDIA_DETACHING), null === (e = this.rtcService) || void 0 === e || e.detachMedia(), null != this.iframeMachine && this.iframeMachine.stop(), this.mediaElement$.next(null), this.trigger(P.MEDIA_DETACHED))
}
handleResolvedUri(e, t) {
this.customUrlLoader.setCustomUrlResponse(e, {
uri: t.uri,
response: t
})
}
get variantOptions$() {
return this.publicQueries$.pipe(La(e => {
const [t, i] = e;
return Mr([t.preferredMediaOptions$, i.desiredRate$]).pipe(hr(([e]) => {
const t = i.isIframeRate;
return e[gu.Variant].filter(e => (null !== (e = e.iframes) && void 0 !== e && e) === t).map(e => e.mediaOptionId)
}))
}))
}
get altAudioOptions$() {
return this.publicQueries$.pipe(La(e => {
var [e] = e;
return $i(e.audioMediaSelectionOptions)
}))
}
get subtitleOptions$() {
return this.publicQueries$.pipe(La(e => {
var [e] = e;
return $i([{
MediaSelectionOptionsName: "Disable subtitle",
MediaSelectionOptionsPersistentID: -1
}].concat(e.subtitleMediaSelectionOptions))
}))
}
get levels() {
var e;
return null !== (e = null === (e = this._activeRootQuery) || void 0 === e ? void 0 : e.preferredMediaOptions[gu.Variant]) && void 0 !== e ? e : []
}
get audioTracks() {
var e;
return null !== (e = null === (e = this._activeRootQuery) || void 0 === e ? void 0 : e.preferredMediaOptions[gu.AltAudio]) && void 0 !== e ? e : []
}
get audioMediaOptions() {
var e;
return null !== (e = null === (e = this._activeRootQuery) || void 0 === e ? void 0 : e.audioMediaSelectionOptions) && void 0 !== e ? e : []
}
get subtitleMediaOptions() {
var e;
return null !== (e = null === (e = this._activeRootQuery) || void 0 === e ? void 0 : e.subtitleMediaSelectionOptions) && void 0 !== e ? e : []
}
get playbackLikelyToKeepUp() {
var e;
return null !== (e = null === (e = this._mediaElementQuery) || void 0 === e ? void 0 : e.playbackLikelyToKeepUp) && void 0 !== e && e
}
get duration$() {
return this.publicQueries$.pipe(La(e => {
var [, e] = e;
return e.mediaElementDuration$
}))
}
get timeupdate$() {
return this.publicQueries$.pipe(La(e => {
var [, e] = e;
return e.timeupdate$
}))
}
get playing$() {
return this.publicQueries$.pipe(La(e => {
var [, e] = e;
return e.gotPlaying$
}))
}
get desiredRate$() {
return this.publicQueries$.pipe(La(e => {
var [, e] = e;
return e.desiredRate$
}))
}
set desiredRate(e) {
null != e && this.setRate(e)
}
get desiredRate() {
var e;
return null !== (e = null === (e = this._mediaElementQuery) || void 0 === e ? void 0 : e.desiredRate) && void 0 !== e ? e : 0
}
get effectiveRate() {
var e;
return null !== (e = null === (e = this._mediaElementQuery) || void 0 === e ? void 0 : e.effectiveRate) && void 0 !== e ? e : 0
}
get iframeMode() {
var e;
return null !== (e = null === (e = this._mediaElementQuery) || void 0 === e ? void 0 : e.isIframeRate) && void 0 !== e && e
}
get accessLog() {
return this.accessLogInstance && this._activeRootQuery ? this.accessLogInstance.getAccessLog(this._activeRootQuery.itemId) : []
}
get errorLog() {
return this.accessLogInstance ? this.accessLogInstance.errorLog : []
}
setRate(e) {
var t;
const i = this.logger.child({
name: "iframes"
});
if (e === this.desiredRate) return -2;
const r = this.mediaElementAdapter;
if (!r || isNaN(e)) return i.warn("unable to switch to rate, missing adapter or newRate isNaN"), -1;
e = Number(e);
const n = Math.abs(e);
if (!this.supportedFrameRates.some(e => e === n)) return i.warn(`unsupported rate(${e})`), -3;
const s = Wp(e),
a = this.iframeMachine;
if (s) {
const e = this._activeRootQuery;
if (null == e || !e.mediaOptionListQueries[gu.Variant].hasIframes) return i.warn("no iframe variants available"), -1;
r.postFlushSeek = null
} else null != a && a.isStarted && !ne(null === (t = r.mediaQuery) || void 0 === t ? void 0 : t.postFlushSeek) && (a.pause(), r.postFlushSeek = a.iframeClockTimeSeconds);
return r.desiredRate = e, 0
}
get sessionData$() {
return this.publicQueries$.pipe(La(([e]) => e.sessionData$))
}
set skip(e) {
this._mediaElementQuery && (this.realCurrentTime = Math.max(0, this.realCurrentTime + e))
}
gaplessSeekTo(e) {
e < this.playingItem.itemStartOffset && (this.logger.warn(`[Gapless] Seeking past track boundary oldSeek=${e}, adjustedSeek=${this.playingItem.itemStartOffset}`), e = this.playingItem.itemStartOffset), this.isPreloading && (e > this.loadingItem.itemStartOffset && (this.logger.warn(`[Gapless] Seeking past track boundary oldSeek=${e}, adjustedSeek=${this.loadingItem.itemStartOffset}`), e = this.loadingItem.itemStartOffset), e < this._mediaElementQuery.getBufferInfo(this._mediaElementQuery.currentTime, this.config.maxBufferHole)[0].buffered.start && this.dequeueSource("SeekToUnbufferedTimeRanges")), fg().setUserSeek(e)
}
isIframeInternalSeek(e) {
return e === (null === (e = this.iframeMachine) || void 0 === e ? void 0 : e.mediaRootTime)
}
set seekTo(e) {
var t, i = Number(e);
if (ne(i))
if (this.inGaplessMode) this.gaplessSeekTo(i);
else {
const r = this.mediaElementAdapter;
!r || !ne(null === (t = r.mediaQuery) || void 0 === t ? void 0 : t.postFlushSeek) || r.mediaQuery.seekTo && !this.isIframeInternalSeek(r.mediaQuery.seekTo.pos) ? fg().setUserSeek(i) : r.schedulePostFlushSeek(i)
}
else this.logger.error(`[seek] got invalid seek value ${e}`)
}
seekToDate(e) {
fg().setUserSeek(e)
}
get availableProgramDateTime() {
return new Map(this._currentDateToMediaTimeTuple)
}
get _currentDateToMediaTimeTuple() {
if (!this._activeRootQuery) return [];
var e = this._activeRootQuery.enabledMediaOptionKeys[gu.Variant];
return _u(e) && null !== (e = null === (e = Cg().getQueryForOption(e).mediaOptionDetails) || void 0 === e ? void 0 : e.dateMediaTimePairs) && void 0 !== e ? e : []
}
get playingDate() {
return function(e, t) {
if (e && 0 !== e.length) {
const i = [...e].sort((e, t) => t[1] - e[1]),
r = null !== (e = i.find(([, e]) => e <= t)) && void 0 !== e ? e : i[i.length - 1],
[n, s] = r;
return new Date(n + 1e3 * (t - s))
}
}(this._currentDateToMediaTimeTuple, this.realCurrentTime)
}
set variantId(e) {}
set audioSelectedPersistentID(e) {
var t = this._activeRootQuery;
null != t && t.preferredMediaOptions[gu.AltAudio] ? (t = t.itemId, e !== this.audioSelectedPersistentID && this.rootPlaylistService.setEnabledMediaOptionTupleWithMatchedGroups(t, gu.AltAudio, e, {
userInitiated: !0
})) : !ne(e) || e < 0 || (this.logger.warn(`[audio] no active item, defer audio track selection: persistentId ${e}`), this.itemQueue.earlyAudioSelection = e)
}
get audioSelectedPersistentID() {
var e;
return this._activeRootQuery ? null === (e = this._activeRootQuery.enabledAlternateMediaOptionByType(gu.AltAudio)) || void 0 === e ? void 0 : e.persistentID : this.itemQueue.earlyAudioSelection
}
set subtitleSelectedPersistentID(e) {
var t = this._activeRootQuery,
i = null == t ? void 0 : t.preferredMediaOptions[gu.Subtitle];
i ? e !== this.subtitleSelectedPersistentID && (t = t.itemId, 0 === i.length && (!ne(e) || e < 0) || (ne(e) && -1 !== e ? this.rootPlaylistService.setEnabledMediaOptionTupleWithMatchedGroups(t, gu.Subtitle, e) : this.rootPlaylistService.setEnabledMediaOptionByType(t, gu.Subtitle, Lu))) : !ne(e) || e < 0 || (this.logger.warn(`[subtitle] no active item, defer subtitle track selection: persistentId ${e}`), this.itemQueue.earlySubtitleSelection = e)
}
get subtitleSelectedPersistentID() {
var e;
return this._activeRootQuery ? null === (e = this._activeRootQuery.enabledAlternateMediaOptionByType(gu.Subtitle)) || void 0 === e ? void 0 : e.persistentID : this.itemQueue.earlySubtitleSelection
}
get selectedMediaArray() {
const e = this._activeRootQuery;
if (!e) return [];
const t = [],
i = e.enabledAlternateMediaOptionByType(gu.AltAudio),
r = e.enabledAlternateMediaOptionByType(gu.Subtitle),
n = i ? e.audioMediaSelectionOptions.find(e => e.MediaSelectionOptionsPersistentID === i.persistentID) : void 0,
s = r ? e.subtitleMediaSelectionOptions.find(e => e.MediaSelectionOptionsPersistentID === r.persistentID) : void 0;
if (n) {
const e = {
MediaSelectionGroupMediaType: Su.AUDIO,
MediaSelectionOptionsPersistentID: n.MediaSelectionOptionsPersistentID
};
t.push(e)
}
if (s) {
let e = vu.NO;
s.MediaSelectionOptionsDisplaysNonForcedSubtitles && (e = s.MediaSelectionOptionsDisplaysNonForcedSubtitles);
const i = {
MediaSelectionGroupMediaType: Su.SUBTITLE,
MediaSelectionOptionsDisplaysNonForcedSubtitles: e,
MediaSelectionOptionsPersistentID: s.MediaSelectionOptionsPersistentID
};
t.push(i)
}
return t
}
set selectedMediaArray(e) {
this._activeRootQuery ? e.forEach(e => {
e.MediaSelectionGroupMediaType === Su.AUDIO || e.MediaSelectionOptionsMediaType === Su.AUDIO ? this.audioSelectedPersistentID = e.MediaSelectionOptionsPersistentID : e.MediaSelectionGroupMediaType !== Su.SUBTITLE && e.MediaSelectionOptionsMediaType !== Su.SUBTITLE && e.MediaSelectionOptionsMediaType !== Su.CLOSEDCAPTION || (this.subtitleSelectedPersistentID = e.MediaSelectionOptionsPersistentID)
}) : this.logger.warn("selectedMediaArray: no active item")
}
getHTMLTextTrack(e) {
return this.legibleSystemAdapter.getExistingHTMLTextTrackWithSubtitleTrackId(e)
}
get keysystems() {
return this.keySystemAdapter.availableKeySystems
}
setProtectionData(e) {
this.keySystemAdapter.initialize(e)
}
generateKeyRequest(e, t) {
this.keySystemAdapter.generateRequest(e, t), this.rtcService.licenseChallengeReceived({
keyuri: e
})
}
setLicenseResponse(e, t) {
this.keySystemAdapter.setLicenseResponse(e, t)
}
get bufferInfo$() {
return this.publicQueries$.pipe(La(e => {
const [, t] = e, i = fg().getQuery().currentConfig;
return an(t.timeupdate$, t.bufferedRangeTuple$).pipe(ao(1e3), hr(() => {
var e = t.currentTime;
return {
combined: t.getCombinedBufferInfo(e, i.maxBufferHole),
sbTuple: t.getBufferInfo(e, i.maxBufferHole)
}
}))
}))
}
bufferInfoByType$(t) {
return this.bufferInfo$.pipe(hr(e => null === (e = null == e ? void 0 : e.sbTuple) || void 0 === e ? void 0 : e[t]))
}
levelWithPersistentId(e) {
this.logger.warn("levelWithPersistentId is deprecated")
}
startLoad(e) {
this.logger.warn("startLoad is deprecated"), ne(e) && (this.logger.warn(`[seek] Seeking to ${null==e?void 0:e.toFixed(3)} via deprecated "startLoad" method. Use loadSource(url, options, startTime) instead.`), this.seekTo = e)
}
stopLoad() {}
get config() {
return Object.assign(Object.assign({}, de(mg())), {
set startPosition(e) {
Qe().warn(`Setting start position ${null==e?void 0:e.toFixed(3)} using deprecated method`), fg().setStartTime(e)
}
})
}
get media() {
return null != this.mediaElement$.value
}
set subtitleDisplay(e) {
this.logger.warn(`set subtitleDisplay ${e} is deprecated`)
}
}
}, "object" == typeof exports && "undefined" != typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define(t) : (e = "undefined" != typeof globalThis ? globalThis : e || Jy).Hls = t()
}(!1);
//# sourceMappingURL=hls.js.map
================================================
FILE: src/renderer/apple-hls.js
================================================
/*! For license information please see hls.js.LICENSE.txt
TL,DR: Don't misuse this file for piracy purpose, all rights of this file and its usage belong to Apple and media copyright holders*/
(function __HLS_UMD_BUNDLE__(__IN_WORKER__){const self = this;
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Hls = factory());
})(this, (function () { 'use strict';
function hasUMDWorker() {
return typeof __HLS_UMD_BUNDLE__ === 'function';
}
const check = (it) => it && it.Math === Math && it;
var global$1 = // eslint-disable-next-line no-undef
(check(typeof globalThis == 'object' && globalThis) ||
check(typeof window == 'object' && window) ||
check(typeof self == 'object' && self) ||
check(typeof global == 'object' && global) ||
Function('return this')());
class JSAESDecryptor {
constructor() {
this.keySize = null;
this.ksRows = null;
this.keySchedule = null;
this.invKeySchedule = null;
// Static after running initTable
this.rcon = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54];
this.subMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)];
this.invSubMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)];
this.sBox = new Uint32Array(256);
this.invSBox = new Uint32Array(256);
// Changes during runtime
this.key = new Uint32Array(0);
this.initTable();
}
// Using view.getUint32() also swaps the byte order.
uint8ArrayToUint32Array_(arrayBuffer) {
const view = new DataView(arrayBuffer);
const length = Math.floor(view.byteLength / 4);
const newArray = new Uint32Array(length);
for (let i = 0; i < length; i++) {
newArray[i] = view.getUint32(i * 4);
}
return newArray;
}
initTable() {
const { sBox } = this;
const { invSBox } = this;
const { subMix } = this;
const subMix0 = subMix[0];
const subMix1 = subMix[1];
const subMix2 = subMix[2];
const subMix3 = subMix[3];
const { invSubMix } = this;
const invSubMix0 = invSubMix[0];
const invSubMix1 = invSubMix[1];
const invSubMix2 = invSubMix[2];
const invSubMix3 = invSubMix[3];
const d = new Uint32Array(256);
let x = 0;
let xi = 0;
let i = 0;
for (i = 0; i < 256; i++) {
if (i < 128) {
d[i] = i << 1;
}
else {
d[i] = (i << 1) ^ 283;
}
}
for (i = 0; i < 256; i++) {
let sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
sx = (sx >>> 8) ^ (sx & 255) ^ 99;
sBox[x] = sx;
invSBox[sx] = x;
// Compute multiplication
const x2 = d[x];
const x4 = d[x2];
const x8 = d[x4];
// Compute sub/invSub bytes, mix columns tables
let t = (d[sx] * 257) ^ (sx * 16843008);
subMix0[x] = (t << 24) | (t >>> 8);
subMix1[x] = (t << 16) | (t >>> 16);
subMix2[x] = (t << 8) | (t >>> 24);
subMix3[x] = t;
// Compute inv sub bytes, inv mix columns tables
t = (x8 * 16843009) ^ (x4 * 65537) ^ (x2 * 257) ^ (x * 16843008);
invSubMix0[sx] = (t << 24) | (t >>> 8);
invSubMix1[sx] = (t << 16) | (t >>> 16);
invSubMix2[sx] = (t << 8) | (t >>> 24);
invSubMix3[sx] = t;
// Compute next counter
if (!x) {
x = xi = 1;
}
else {
x = x2 ^ d[d[d[x8 ^ x2]]];
xi ^= d[d[xi]];
}
}
}
expandKey(keyBuffer) {
// convert keyBuffer to Uint32Array
const key = this.uint8ArrayToUint32Array_(keyBuffer);
let sameKey = true;
let offset = 0;
while (offset < key.length && sameKey) {
sameKey = key[offset] === this.key[offset];
offset++;
}
if (sameKey) {
return;
}
this.key = key;
const keySize = (this.keySize = key.length);
if (keySize !== 4 && keySize !== 6 && keySize !== 8) {
throw new Error('Invalid aes key size=' + keySize);
}
const ksRows = (this.ksRows = (keySize + 6 + 1) * 4);
let ksRow;
let invKsRow;
const keySchedule = (this.keySchedule = new Uint32Array(ksRows));
const invKeySchedule = (this.invKeySchedule = new Uint32Array(ksRows));
const sbox = this.sBox;
const { rcon } = this;
const { invSubMix } = this;
const invSubMix0 = invSubMix[0];
const invSubMix1 = invSubMix[1];
const invSubMix2 = invSubMix[2];
const invSubMix3 = invSubMix[3];
let prev;
let t;
for (ksRow = 0; ksRow < ksRows; ksRow++) {
if (ksRow < keySize) {
prev = keySchedule[ksRow] = key[ksRow];
continue;
}
t = prev;
if (ksRow % keySize === 0) {
// Rot word
t = (t << 8) | (t >>> 24);
// Sub word
t = (sbox[t >>> 24] << 24) | (sbox[(t >>> 16) & 255] << 16) | (sbox[(t >>> 8) & 255] << 8) | sbox[t & 255];
// Mix Rcon
t ^= rcon[(ksRow / keySize) | 0] << 24;
}
else if (keySize > 6 && ksRow % keySize === 4) {
// Sub word
t = (sbox[t >>> 24] << 24) | (sbox[(t >>> 16) & 255] << 16) | (sbox[(t >>> 8) & 255] << 8) | sbox[t & 255];
}
keySchedule[ksRow] = prev = (keySchedule[ksRow - keySize] ^ t) >>> 0;
}
for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {
ksRow = ksRows - invKsRow;
if (invKsRow & 3) {
t = keySchedule[ksRow];
}
else {
t = keySchedule[ksRow - 4];
}
if (invKsRow < 4 || ksRow <= 4) {
invKeySchedule[invKsRow] = t;
}
else {
invKeySchedule[invKsRow] = invSubMix0[sbox[t >>> 24]] ^ invSubMix1[sbox[(t >>> 16) & 255]] ^ invSubMix2[sbox[(t >>> 8) & 255]] ^ invSubMix3[sbox[t & 255]];
}
invKeySchedule[invKsRow] = invKeySchedule[invKsRow] >>> 0;
}
}
// Adding this as a method greatly improves performance.
networkToHostOrderSwap(word) {
return (word << 24) | ((word & 65280) << 8) | ((word & 16711680) >> 8) | (word >>> 24);
}
decrypt(inputArrayBuffer, offset, aesIV) {
const nRounds = this.keySize + 6;
const { invKeySchedule } = this;
const invSBOX = this.invSBox;
const { invSubMix } = this;
const invSubMix0 = invSubMix[0];
const invSubMix1 = invSubMix[1];
const invSubMix2 = invSubMix[2];
const invSubMix3 = invSubMix[3];
const initVector = this.uint8ArrayToUint32Array_(aesIV);
let initVector0 = initVector[0];
let initVector1 = initVector[1];
let initVector2 = initVector[2];
let initVector3 = initVector[3];
const inputInt32 = new Int32Array(inputArrayBuffer);
const outputInt32 = new Int32Array(inputInt32.length);
let t0, t1, t2, t3;
let s0, s1, s2, s3;
let inputWords0, inputWords1, inputWords2, inputWords3;
let ksRow, i;
const swapWord = this.networkToHostOrderSwap;
while (offset < inputInt32.length) {
inputWords0 = swapWord(inputInt32[offset]);
inputWords1 = swapWord(inputInt32[offset + 1]);
inputWords2 = swapWord(inputInt32[offset + 2]);
inputWords3 = swapWord(inputInt32[offset + 3]);
s0 = inputWords0 ^ invKeySchedule[0];
s1 = inputWords3 ^ invKeySchedule[1];
s2 = inputWords2 ^ invKeySchedule[2];
s3 = inputWords1 ^ invKeySchedule[3];
ksRow = 4;
// Iterate through the rounds of decryption
for (i = 1; i < nRounds; i++) {
t0 = invSubMix0[s0 >>> 24] ^ invSubMix1[(s1 >> 16) & 255] ^ invSubMix2[(s2 >> 8) & 255] ^ invSubMix3[s3 & 255] ^ invKeySchedule[ksRow];
t1 = invSubMix0[s1 >>> 24] ^ invSubMix1[(s2 >> 16) & 255] ^ invSubMix2[(s3 >> 8) & 255] ^ invSubMix3[s0 & 255] ^ invKeySchedule[ksRow + 1];
t2 = invSubMix0[s2 >>> 24] ^ invSubMix1[(s3 >> 16) & 255] ^ invSubMix2[(s0 >> 8) & 255] ^ invSubMix3[s1 & 255] ^ invKeySchedule[ksRow + 2];
t3 = invSubMix0[s3 >>> 24] ^ invSubMix1[(s0 >> 16) & 255] ^ invSubMix2[(s1 >> 8) & 255] ^ invSubMix3[s2 & 255] ^ invKeySchedule[ksRow + 3];
// Update state
s0 = t0;
s1 = t1;
s2 = t2;
s3 = t3;
ksRow = ksRow + 4;
}
// Shift rows, sub bytes, add round key
t0 = (invSBOX[s0 >>> 24] << 24) ^ (invSBOX[(s1 >> 16) & 255] << 16) ^ (invSBOX[(s2 >> 8) & 255] << 8) ^ invSBOX[s3 & 255] ^ invKeySchedule[ksRow];
t1 = (invSBOX[s1 >>> 24] << 24) ^ (invSBOX[(s2 >> 16) & 255] << 16) ^ (invSBOX[(s3 >> 8) & 255] << 8) ^ invSBOX[s0 & 255] ^ invKeySchedule[ksRow + 1];
t2 = (invSBOX[s2 >>> 24] << 24) ^ (invSBOX[(s3 >> 16) & 255] << 16) ^ (invSBOX[(s0 >> 8) & 255] << 8) ^ invSBOX[s1 & 255] ^ invKeySchedule[ksRow + 2];
t3 = (invSBOX[s3 >>> 24] << 24) ^ (invSBOX[(s0 >> 16) & 255] << 16) ^ (invSBOX[(s1 >> 8) & 255] << 8) ^ invSBOX[s2 & 255] ^ invKeySchedule[ksRow + 3];
ksRow = ksRow + 3;
// Write
outputInt32[offset] = swapWord(t0 ^ initVector0);
outputInt32[offset + 1] = swapWord(t3 ^ initVector1);
outputInt32[offset + 2] = swapWord(t2 ^ initVector2);
outputInt32[offset + 3] = swapWord(t1 ^ initVector3);
// reset initVector to last 4 unsigned int
initVector0 = inputWords0;
initVector1 = inputWords1;
initVector2 = inputWords2;
initVector3 = inputWords3;
offset = offset + 4;
}
return outputInt32.buffer;
}
destroy() {
this.key = undefined;
this.keySize = undefined;
this.ksRows = undefined;
this.sBox = undefined;
this.invSBox = undefined;
this.subMix = undefined;
this.invSubMix = undefined;
this.keySchedule = undefined;
this.invKeySchedule = undefined;
this.rcon = undefined;
}
}
function removePadding(decryptedData) {
const decryptedDataView = new Uint8Array(decryptedData);
const padding = decryptedDataView[decryptedData.byteLength - 1];
const endOffset = decryptedData.byteLength - 1;
// Check for PKCS-7 padding: https://tools.ietf.org/html/rfc2315#section-10.3
let checkedBytes = 0;
if (padding >= 1 && padding <= 16) {
for (let i = endOffset; i > endOffset - padding; i--) {
if (decryptedDataView[i] !== padding) {
break;
}
checkedBytes++;
}
}
if (checkedBytes === padding) {
decryptedData = decryptedData.slice(0, endOffset - padding + 1); // keep 0 till 'endOffset - padding', both inclusive, to remove the padding bytes
}
return decryptedData;
}
// CryptoRPCServer can run in either Worker or main process depending on config.
// So we want to minimize the dependency for it in case it's running in Worker.
// Thus we use the vanilla RPCService interface that uses old-school callback
// patterns. It has zero dependency: no Promise, no RxJS, just plain JavaScript.
class CryptoRPCServer {
constructor(rpc, logger) {
this.rpc = rpc;
this.logger = logger;
this.decrypt = (key, iv, alg, cipherText, options) => callback => {
const crypto = global$1.crypto;
if ((options === null || options === void 0 ? void 0 : options.useJSCrypto) || !(crypto === null || crypto === void 0 ? void 0 : crypto.subtle)) {
/**
* JSCrypto
*/
const jsCrypto = new JSAESDecryptor();
let plainText;
jsCrypto.expandKey(key);
const result = jsCrypto.decrypt(cipherText, 0, iv);
if (options.plainTextLength) {
plainText = result.slice(0, options.plainTextLength); // The input buffer doesn't have padding, just return the expected bytes.
}
else {
plainText = removePadding(result);
}
this.logger.info(`[JSCrypto]: ${cipherText.byteLength} => ${plainText.byteLength} bytes`);
callback(plainText, undefined, [plainText]);
}
else {
/**
* WebCrypto
*/
crypto.subtle
.importKey('raw', key, alg, false, ['decrypt'])
.then((key) => crypto.subtle.decrypt({ name: alg, iv }, key, cipherText))
.then((plainText) => {
this.logger.info(`[WebCrypto]: ${cipherText.byteLength} => ${plainText.byteLength} bytes`);
callback(plainText, undefined, [plainText]);
})
.catch((error) => callback(undefined, error));
}
};
rpc.register('decrypt', this.decrypt);
}
}
const LoggerRPCClient = (rpcService) => {
const bindLogger = (bindings = []) => {
const logFn = (level) => (...args) => {
rpcService.invoke('logger.log', [bindings, level, ...args])((res, err) => {
if (err != null)
throw err;
});
};
const logger = {};
['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'qe'].forEach((k) => (logger[k] = logFn(k)));
logger.child = (b) => bindLogger([...bindings, b]);
return logger;
};
return bindLogger();
};
/**
* HLS Events
*
*
*
*
*/
/**
* @readonly
* @enum {string}
*/
var HlsEvent;
(function (HlsEvent) {
// fired before MediaSource is attaching to media element - data: { media }
HlsEvent["MEDIA_ATTACHING"] = "hlsMediaAttaching";
// fired when MediaSource has been succesfully attached to media element - data: { media }
HlsEvent["MEDIA_ATTACHED"] = "hlsMediaAttached";
// fired before detaching MediaSource from media element - data: { }
HlsEvent["MEDIA_DETACHING"] = "hlsMediaDetaching";
// fired when MediaSource has been detached from media element
HlsEvent["MEDIA_DETACHED"] = "hlsMediaDetached";
// fired when sourcebuffers have been created - data: { tracks : tracks }
HlsEvent["BUFFER_CREATED"] = "hlsBufferCreated";
// fired when we append a segment to the buffer - data: { segment: segment object }
HlsEvent["BUFFER_APPENDING"] = "hlsBufferAppending";
// fired when we are done with appending a media segment to the buffer - data : { parent : segment parent that triggered BUFFER_APPENDING, pending : nb of segments waiting for appending for this segment, timeRanges : bufferd time ranges }
HlsEvent["BUFFER_APPENDED"] = "hlsBufferAppended";
// fired when the media buffer has been flushed
HlsEvent["BUFFER_FLUSHED"] = "hlsBufferFlushed";
// fired to signal that a manifest loading starts - data: { url: manifestURL }
HlsEvent["MANIFEST_LOADING"] = "hlsManifestLoading";
// fired after manifest has been loaded - data: { levels : [available quality levels including iframe levels], audioTracks : [ available audio tracks], subtitleTracks : [ available subtitle tracks], url : manifestURL, stats : { trequest, tfirst, tload, mtime}, audioMediaSelectionGroup: audio selection group, subtitleMediaSelectionGroup: subtitle selection group}
HlsEvent["MANIFEST_LOADED"] = "hlsManifestLoaded";
// fired after manifest has been parsed - data: { levels : [available quality levels including iframe levels], firstLevel : index of first quality level appearing in Manifest, stats: stats, audio: audio codec, video: video codec, altAudio: if alternate audio present (true/false), audioTracks: audio tracks, audioMediaSelectionGroup: audio selection group}
HlsEvent["MANIFEST_PARSED"] = "hlsManifestParsed";
// fired when a level switch is requested - data: { level : id of new level }
HlsEvent["LEVEL_SWITCHING"] = "hlsLevelSwitching";
// fired when a level switch is effective - data: { level : id of new level }
HlsEvent["LEVEL_SWITCHED"] = "hlsLevelSwitched";
// fired when a level playlist loading starts - data: { url : level URL, level : level, persistentId: persistent id of level being loaded}
HlsEvent["LEVEL_LOADING"] = "hlsLevelLoading";
// fired when a level playlist loading finishes - data: { details : levelDetails object, level : level, persistentId : persistent id of loaded level, stats : { trequest, tfirst, tload, mtime}, playlistType : playlist type }
HlsEvent["LEVEL_LOADED"] = "hlsLevelLoaded";
// fired when a level's details have been updated based on previous details, after it has been loaded - data: { details : levelDetails object, level : id of updated level }
HlsEvent["LEVEL_UPDATED"] = "hlsLevelUpdated";
// fired when levels list has changed due to any error
HlsEvent["LEVELS_CHANGED"] = "hlsLevelsChanged";
// fired to notify that audio track lists has been updated - data: { audioTracks : audioTracks }
HlsEvent["AUDIO_TRACKS_UPDATED"] = "hlsAudioTracksUpdated";
// fired when an audio track switch occurs - data: { id : audio track id, type: track type, url: url } // deprecated in favor AUDIO_TRACK_SWITCHING
HlsEvent["AUDIO_TRACK_SWITCH"] = "hlsAudioTrackSwitch";
// fired when an audio track switch actually occurs - data: { id : audio track id }
HlsEvent["AUDIO_TRACK_SWITCHED"] = "hlsAudioTrackSwitched";
// fired when an audio track loading finishes - data: { details : levelDetails object, id : audio track id, stats : { trequest, tfirst, tload, mtime } }
HlsEvent["AUDIO_TRACK_LOADED"] = "hlsAudioTrackLoaded";
// fired to notify that subtitle track lists has been updated - data: { subtitleTracks : subtitleTracks }
HlsEvent["SUBTITLE_TRACKS_UPDATED"] = "hlsSubtitleTracksUpdated";
// fired to notify that subtitle HTML5 text tracks have been created - data: undefined
HlsEvent["SUBTITLE_TRACKS_CREATED"] = "hlsSubtitleTracksCreated";
// fired when an subtitle track switch occurs - data: { track : subtitle track }
HlsEvent["SUBTITLE_TRACK_SWITCH"] = "hlsSubtitleTrackSwitch";
// fired when inline webvtt styles have been parsed - data: { styles: styles }
HlsEvent["INLINE_STYLES_PARSED"] = "hlsInlineStylesParsed";
// fired when all the session data URI loading finished - data: { }
HlsEvent["SESSION_DATA_COMPLETE"] = "hlsSessionDataComplete";
// fired when a fragment loading starts - data: { frag : fragment object }
HlsEvent["FRAG_LOADING"] = "hlsFragLoading";
// fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : { trequest, tfirst, tload, length } }
HlsEvent["FRAG_LOADED"] = "hlsFragLoaded";
// fired when fragment remuxed MP4 boxes have all been appended into SourceBuffer - data: { id : demuxer id, frag : fragment object, stats : { trequest, tfirst, tload, tparsed, tappendStart, tbuffered, length, bwEstimate } }
HlsEvent["FRAG_BUFFERED"] = "hlsFragBuffered";
// fired when fragment matching with current media position is changing - data : { frag : fragment object }
HlsEvent["FRAG_CHANGED"] = "hlsFragChanged";
// Identifier for an internal error event - data: { type : error type, details : error details, fatal : emitter's suggestion whether the error is fatal or not. can be overruled by handler }
HlsEvent["INTERNAL_ERROR"] = "hlsInternalError";
// Identifier for an public error event - data: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data }
HlsEvent["ERROR"] = "hlsError";
// fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a media to the instance of hls.js to handle mid-rolls for example - data: { }
HlsEvent["DESTROYING"] = "hlsDestroying";
// Key request started data: { keyuri: '' , decryptdata: DecryptData object, timestamp: timestamp of the event }
HlsEvent["KEY_REQUEST_STARTED"] = "hlsKeyRequestStarted";
// data: { 'keyuri': 'licenseChallenge': Uint8Array(challengeBytes) keysystem: }
HlsEvent["LICENSE_CHALLENGE_CREATED"] = "hlsLicenseChallengeCreated";
// EME:
// Session remove() was called and returned license-release message. data: { keysystem: '', itemId: itemId, releaseRecord: { CDM specific record destruction } }
HlsEvent["LICENSE_RELEASED"] = "hlsLicenseReleased";
// fired when a decrypt key loading is completed - data: { decryptdata: '', keyuri: '', stats : { trequest, tfirst, tload }, timestamp: timestamp of the event }
HlsEvent["KEY_LOADED"] = "hlsKeyLoaded";
// We encountered a url that doesn't start with http data: { uri: ''}
HlsEvent["UNRESOLVED_URI_LOADING"] = "hlsUnresolvedUriLoading";
// fired when trickplay rate changing completed
HlsEvent["DESIRED_RATE_CHANGED"] = "hlsDesiredRateChanged";
// data: { playbackLikelyToKeepUp }
HlsEvent["PLAYER_STATE_CHANGE"] = "hlsPlayerStateChange";
// When seek starts data: {}
HlsEvent["SEEKING"] = "hlsSeeking";
// When seek ends data: {}
HlsEvent["SEEKED"] = "hlsSeeked";
// When stall detected. Stream controller decides if it will report an error. data: { isLowBufferStall: true|false }
HlsEvent["STALLED"] = "hlsStalled";
// When resumed from stall, either playback restart or user hit pause.
HlsEvent["RESUME_FROM_STALL"] = "hlsResumeFromStall";
// Item fully appended
HlsEvent["READY_FOR_NEXT_ITEM"] = "hlsReadyForNextItem";
// Playback transitioned to next item
HlsEvent["ITEM_TRANSITIONED"] = "hlsItemTransitioned";
// Evict loading item
HlsEvent["ITEM_EVICTED"] = "hlsItemEvicted";
// New EXT-X-DATERANGE data available
HlsEvent["DATERANGE_UPDATED"] = "hlsDaterangeUpdated";
})(HlsEvent || (HlsEvent = {}));
var HlsEvent$1 = HlsEvent;
/*
* Demuxer Events
*
*
*/
/**
* @readonly
* @enum {string}
*/
var DemuxerEvent;
(function (DemuxerEvent) {
// fired when Init Segment has been extracted from fragment - data: { tracks: tracks }
DemuxerEvent["FRAG_PARSING_INIT_SEGMENT"] = "hlsFragParsingInitSegment";
// fired when data have been extracted from fragment - data: { data1: segment, startPTS: start PTS, endPTS: end PTS, startDTS: start DTS, endDTS: end DTS, type: video / audio, nb: number of samples, dropped: is dropped }
DemuxerEvent["FRAG_PARSING_DATA"] = "hlsFragParsingData";
// fired when fragment parsing is completed
DemuxerEvent["FRAG_PARSED"] = "hlsFragParsed";
// fired when the first timestamp is found - data: { initPTS90k: initPTS90k }
DemuxerEvent["INIT_PTS_FOUND"] = "hlsInitPtsFound";
})(DemuxerEvent || (DemuxerEvent = {}));
/**
* HLS Error
*
*
*
*
*/
class HlsError extends Error {
constructor(type, details, fatal, reason, response) {
super(reason);
this.type = type;
this.details = details;
this.fatal = fatal;
this.reason = reason;
this.response = response;
this.handled = false;
}
}
// Inherited error codes from Core Media
const PlaylistNotReceived = { code: -12884, text: 'Playlist not received' };
const CryptResponseReceivedSlowly = { code: -16833, text: 'Crypt key received slowly' };
const LivePlaylistUpdateError = { code: -12888, text: 'Live playlist not updated' };
const NoResponseFromMediaRequest = { code: -12889, text: 'No response for fragment' };
const IncompatibleAsset = { code: -12927, text: 'IncompatibleAsset' };
const CorruptStream = { code: -16041, text: 'Corrupt fragment' };
const InternalError = { code: -12645, text: 'InternalException' };
const CantSwitchInTime = { code: -12644, text: 'CantSwitchInTime' };
const VideoDecoderBadDataErr = { code: -12909, text: 'Buffer error' };
const InsufficientDataAvailable = { code: -12928, text: 'Incomplete data' };
const AllocationFailed = { code: -12862, text: 'AllocationFailed' };
const PlaylistErrorMissingEXTM3U = { code: -12269, text: 'Response doesnt have #EXTM3U tag' };
const PlaylistErrorInvalidEntry = { code: -12264, text: 'Invalid entry' };
const PlaylistErrorBadTargetDuration = { code: -12271, text: 'Invalid targetduration' };
const NoValidAlternates = { code: -12925, text: 'No valid alternates' };
const FormatError = { code: -12642, text: 'Incorrect playlist format' };
// HLSJS Specific error codes
const UnsupportedKeySystemError = { code: -60000, text: 'Unsupported Key System' };
const EmptyLoadSourceError = { code: -60001, text: 'Empty loadSource url' };
const UndefinedItemIdError = { code: -60002, text: 'Undefined itemId' };
const ManifestParseError = { code: -60003, text: 'Manifest parse error' };
const DemuxWorkerError = { code: -60004, text: 'Demux worker error' };
const DecryptWorkerError = { code: -60005, text: 'Decrypt worker error' };
const OutOfRangeSeekError = { code: -60006, text: 'Seeked out of playable range' };
const ExceptionInKeyLoadError = { code: -60007, text: 'Exception in Key load' };
const FragmentAbortError$1 = { code: -60008, text: 'Fragment abort error' };
const ManifestTimeoutError = { code: -60009, text: 'Manifest Timeout Error' };
const PlaylistTimeoutError = { code: -60010, text: 'Playlist Timeout Error' };
const FragmentTimeoutError = { code: -60011, text: 'Fragment Timeout Error' };
const IncompleteSessionData = { code: -60012, text: 'Session data not complete after loading all items' };
const SessionDataLoadTimeout = { code: -60013, text: 'Session data load timeout' };
const FailedDemuxerSanityCheck = { code: -60014, text: 'Failed demuxer sanity check' };
const InvalidADTSSamplingIndex = { code: -60015, text: 'Invalid ADTS sampling index' };
const DemuxerNotFound = { code: -60016, text: 'No demux matching with content found' };
const InvalidInitTimestamp = { code: -60017, text: 'Invalid initPTS or initDTS' };
const NoAVSamplesFound = { code: -60018, text: 'no audio/video samples found' };
const NoTSSyncByteFound = { code: -60019, text: 'TS packet did not start with 0x47' };
const PESDidNotStartWithADTS = { code: -60020, text: 'AAC PES did not start with ADTS header' };
const NoADTSHeaderInPES = { code: -60021, text: 'No ADTS header found in AAC PES' };
const InvalidDolbyAudioMagic = { code: -60022, text: 'Invalid dolby audio magic' };
const FailedToAllocateVideoMdat = { code: -60023, text: 'Fail allocating video mdat' };
const FailedToAllocateAudioMdat = { code: -60024, text: 'Fail allocating audio mdat' };
const InsufficientEC3Data = { code: -60025, text: 'Error parsing ec-3, not enough data' };
const InvalidEC3Magic = { code: -60026, text: 'Invalid ec-3 magic' };
const ReservedStreamType = { code: -60027, text: 'Reserved stream type' };
const InsufficientAC3Data = { code: -60028, text: 'error parsing ac-3, not enough data' };
const InvalidAC3Magic = { code: -60029, text: 'Invalid ac-3 magic' };
const InvalidAC3SamplingRateCode = { code: -60030, text: 'Invalid ac-3 samplingRateCode' };
const PlaylistErrorInvalidEXTXDEFINE = { code: -61000, text: 'Encountered undefined/not imported EXT-X-DEFINE property' };
const PlaylistErrorMissingImportReference = { code: -61001, text: 'IMPORT references variable not in master playlist and/or NAME' };
const PlaylistErrorInvalidSERVERURI = { code: -61002, text: 'Encountered undefined/invalid SERVER-URI attribute for EXT-X-CONTENT-STEERING tag' };
const PlaylistErrorInvalidPATHWAYID = { code: -61003, text: 'Encountered invalid PATHWAY-ID attribute for EXT-X-CONTENT-STEERING tag' };
const PlaylistErrorInvalidSCORE = { code: -61004, text: 'Encountered negative/non-number SCORE property' };
const KeySystemFailedToUpdateSession = { code: -62000, text: 'KeySystem: Promise Rejected while updating session' };
const KeySystemFailedToGenerateLicenseRenewal = { code: -62001, text: 'KeySystem: Failed to generate license renewal' };
const KeySystemFailedToGenerateLicenseRequest = { code: -62002, text: 'KeySystem: Failed to generate license request' };
const KeySystemAbort = { code: -62003, text: 'KeySystem: Aborted' };
const KeySystemUnexpectedStateTransition = { code: -62004, text: 'KeySystem: Unexpected state transition' };
const KeySystemUnexpectedState = { code: -62005, text: 'KeySystem: Unexpected state' };
const KeySystemCDMUnknownError = { code: -62006, text: 'KeySystem: Unknown error from CDM' };
const KeySystemRequestTimedOut = { code: -62007, text: 'Key request timed out' };
const KeySystemUnexpectedMETHOD = { code: -62008, text: 'Unexpected METHOD attribute' };
const KeySystemUnmatchedString = { code: -62009, text: 'KeySystem: string does not match' };
const KeySystemInternalError = { code: -62010, text: 'KeySystem: internal-error' };
const KeySystemOutputRestricted = { code: -62011, text: 'KeySystem: output-restricted' };
const KeySystemSetupError = { code: -62012, text: 'KeySystem: setup error' };
const KeySystemFailedToInitialize = { code: -62013, text: 'KeySystem: could not initialize' };
const KeySystemFailedToCreateSession = { code: -62014, text: 'KeySystem: could not create session' };
const KeySystemUndefinedNavigator = { code: -62015, text: 'KeySystem: navigator undefined' };
const KeySystemNoKeySystemsToTry = { code: -62016, text: 'KeySystem: no key systems to try' };
const KeySystemNoConstructor = { code: -62017, text: 'KeySystem: No constructor' };
const KeySystemNoKeySystemAccess = { code: -62018, text: 'KeySystem: No KeySystemAccess' };
const KeySystemCertificateLoadError = { code: -62019, text: 'KeySystem: Certificate Load Error' };
class PlaylistParsingError extends HlsError {
constructor(type, details, fatal, reason, response) {
super(type, details, fatal, reason, response);
this.response = response;
}
}
const ErrorResponses = {
// Inherited error codes from Core Media
PlaylistNotReceived,
CryptResponseReceivedSlowly,
LivePlaylistUpdateError,
NoResponseFromMediaRequest,
IncompatibleAsset,
CorruptStream,
InternalError,
CantSwitchInTime,
VideoDecoderBadDataErr,
InsufficientDataAvailable,
AllocationFailed,
PlaylistErrorMissingEXTM3U,
PlaylistErrorInvalidEntry,
PlaylistErrorBadTargetDuration,
NoValidAlternates,
FormatError,
// HLSJS Specific error codes
UnsupportedKeySystemError,
EmptyLoadSourceError,
UndefinedItemIdError,
ManifestParseError,
DemuxWorkerError,
DecryptWorkerError,
OutOfRangeSeekError,
ExceptionInKeyLoadError,
FragmentAbortError: FragmentAbortError$1,
ManifestTimeoutError,
PlaylistTimeoutError,
FragmentTimeoutError,
IncompleteSessionData,
SessionDataLoadTimeout,
FailedDemuxerSanityCheck,
InvalidADTSSamplingIndex,
DemuxerNotFound,
InvalidAC3Magic,
InvalidInitTimestamp,
NoAVSamplesFound,
NoTSSyncByteFound,
PESDidNotStartWithADTS,
NoADTSHeaderInPES,
InvalidDolbyAudioMagic,
FailedToAllocateVideoMdat,
FailedToAllocateAudioMdat,
InsufficientEC3Data,
InvalidEC3Magic,
ReservedStreamType,
InsufficientAC3Data,
InvalidAC3SamplingRateCode,
PlaylistErrorInvalidEXTXDEFINE,
PlaylistErrorMissingImportReference,
PlaylistErrorInvalidSERVERURI,
PlaylistErrorInvalidPATHWAYID,
PlaylistErrorInvalidSCORE,
KeySystemFailedToUpdateSession,
KeySystemFailedToGenerateLicenseRenewal,
KeySystemFailedToGenerateLicenseRequest,
KeySystemAbort,
KeySystemUnexpectedStateTransition,
KeySystemUnexpectedState,
KeySystemCDMUnknownError,
KeySystemRequestTimedOut,
KeySystemUnexpectedMETHOD,
KeySystemUnmatchedString,
KeySystemInternalError,
KeySystemOutputRestricted,
KeySystemSetupError,
KeySystemFailedToInitialize,
KeySystemFailedToCreateSession,
KeySystemUndefinedNavigator,
KeySystemNoKeySystemsToTry,
KeySystemNoConstructor,
KeySystemNoKeySystemAccess,
KeySystemCertificateLoadError,
};
const ErrorTypes = {
// Identifier for a network error (loading error / timeout ...)
NETWORK_ERROR: 'networkError',
// Identifier for a media Error (video/parsing/mediasource error)
MEDIA_ERROR: 'mediaError',
// Identifier for a mux Error (demuxing/remuxing)
MUX_ERROR: 'muxError',
// Identifier for a key system error (EME)
KEY_SYSTEM_ERROR: 'keySystemError',
// Identifier for all other errors
OTHER_ERROR: 'otherError',
};
const ErrorDetails = {
// Identifier for a manifest load error - data: { url : faulty URL, response : { code: error code, text: error text }}
MANIFEST_LOAD_ERROR: 'manifestLoadError',
// Identifier for a manifest load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
MANIFEST_LOAD_TIMEOUT: 'manifestLoadTimeOut',
// Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason, response : { code: error code, text: error text }}
MANIFEST_PARSING_ERROR: 'manifestParsingError',
// Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason, response : { code: error code, text: error text }}
MANIFEST_INCOMPATIBLE_CODECS_ERROR: 'manifestIncompatibleCodecsError',
// Identifier for a manifest with only incompatible video-range error - data: { url : faulty URL, reason : error reason, response : { code: error code, text: error text }}
MANIFEST_INCOMPATIBLE_VIDEO_RANGE_ERROR: 'manifestIncompatibleVideoRangeError',
// Identifier for a level load error - data: { url : faulty URL, response : { code: error code, text: error text }}
LEVEL_LOAD_ERROR: 'levelLoadError',
// Identifier for a level load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
LEVEL_LOAD_TIMEOUT: 'levelLoadTimeOut',
// Identifier for a level switch error - data: { level : faulty level Id, event : error description, response : { code: error code, text: error text }}
LEVEL_SWITCH_ERROR: 'levelSwitchError',
// Identifier for an audio track load error - data: { url : faulty URL, response : { code: error code, text: error text }}
AUDIO_TRACK_LOAD_ERROR: 'audioTrackLoadError',
// Identifier for an audio track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
AUDIO_TRACK_LOAD_TIMEOUT: 'audioTrackLoadTimeOut',
// Identifier for an subtitle track load error - data: { url : faulty URL, response : { code: error code, text: error text }}
SUBTITLE_TRACK_LOAD_ERROR: 'subtitleTrackLoadError',
// Identifier for an subtitle track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
SUBTITLE_TRACK_LOAD_TIMEOUT: 'subtitleTrackLoadTimeout',
// Identifier for fragment load error - data: { frag : fragment object, response : { code: error code, text: error text }}
FRAG_LOAD_ERROR: 'fragLoadError',
// Identifier for fragment loop loading error - data: { frag : fragment object, fatal:, response: { code: error code, text: error text }}
FRAG_LOOP_LOADING_ERROR: 'fragLoopLoadingError',
// Identifier for fragment load timeout error - data: { frag : fragment object, response : { code: error code, text: error text }}
FRAG_LOAD_TIMEOUT: 'fragLoadTimeOut',
// Identifier for a fragment decryption error event - data: {id : demuxer Id,frag: fragment object, reason : parsing error description , response : { code: error code, text: error text }}
FRAG_DECRYPT_ERROR: 'fragDecryptError',
// Identifier for a fragment parsing error event - data: { id : demuxer Id, reason : parsing error description, response : { code: error code, text: error text } }
// will be renamed DEMUX_PARSING_ERROR and switched to MUX_ERROR in the next major release
FRAG_PARSING_ERROR: 'fragParsingError',
// Identifier for a remux alloc error event - data: { id : demuxer Id, frag : fragment object, bytes : nb of bytes on which allocation failed , reason : error text, response: { code: error code, text: error text }}
REMUX_ALLOC_ERROR: 'remuxAllocError',
// Triggered when an exception occurs while adding a sourceBuffer to MediaSource - data : { err : exception , mimeType : mimeType , response : { code: error code, text: error text }}
BUFFER_ADD_CODEC_ERROR: 'bufferAddCodecError',
// Identifier for a buffer append error - data: {append error description, response : { code: error code, text: error text }}
BUFFER_APPEND_ERROR: 'bufferAppendError',
// Identifier for a buffer appending error event - data: {appending error description, response : { code: error code, text: error text }}
BUFFER_APPENDING_ERROR: 'bufferAppendingError',
// Identifier for a buffer stalled error event - data: {fatal:, bufferLen: , response : { code: error code, text: error text }}
BUFFER_STALLED_ERROR: 'bufferStalledError',
// Identifier for a buffer full event - data: {fatal:, response : { code: error code, text: error text }}
BUFFER_FULL_ERROR: 'bufferFullError',
// Identifier for a buffer seek over hole event- data: {fatal:, response : { code: error code, text: error text }}
BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole',
// Identifier for a buffer nudge on stall (playback is stuck although currentTime is in a buffered area) data: {fatal:, response : { code: error code, text: error text }}
BUFFER_NUDGE_ON_STALL: 'bufferNudgeOnStall',
// Identifier for an internal exception happening inside hls.js while handling an event
// data: { url: , fatal:, response: { code: error code, text: error text } }
INTERNAL_EXCEPTION: 'internalException',
// Malformed WebVTT contents
WEBVTT_EXCEPTION: 'webVTTException',
// KEY REQUEST ERRORS
// Identifier for decrypt key load error - data: { decryptdata: DecryptData object, stats: { tfirstissue, tlastissue, failCount } response: {code: status code returned from server, text: error message}}
KEY_LOAD_ERROR: 'keyLoadError',
// Identifier for decrypt key load timeout error - data: { decryptdata: DecryptData object, stats: { tfirstissue, tlastissue, failCount }, response: { code: error code, text: error message }}
KEY_LOAD_TIMEOUT: 'keyLoadTimeOut',
// Identifier for CDM error - data: { decryptdata: DecryptData object, stats: { tfirstissue, tlastissue, failCount }, reason: error message, response: { code: error code, text: error message }}
KEY_SYSTEM_GENERIC_ERROR: 'keySystemGenericError',
// data: { url: , fatal:, response: { code: error code, text: error text } }
CERT_LOAD_ERROR: 'certificateLoadError',
// data: { url: , fatal:, response: { code: error code, text: error text } }
CERT_LOAD_TIMEOUT: 'certificateLoadTimeOut',
// Identifier for session data item load error - data: { sessionId: '', response : { code: error code, text: error text }}
SESSION_DATA_LOAD_ERROR: 'sessionDataLoadError',
// Identifier for session data item load timeout error - data: { sessionId: '' , response : { code: error code, text: error text }}
SESSION_DATA_LOAD_TIMEOUT: 'sessionDataLoadTimeOut',
// Identifier for a Conetent Steering manifest load error - data: { url : faulty URL, response : { code: error code, text: error text }}
STEERING_MANIFEST_LOAD_ERROR: 'steeringManifestLoadError',
// Identifier for a Conetent Steering manifest load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
STEERING_MANIFEST_LOAD_TIMEOUT: 'steeringManifestLoadTimeOut',
// Identifier for a Conetent Steering manifest parsing error - data: { url : faulty URL, reason : error reason, response : { code: error code, text: error text }}
STEERING_MANIFEST_PARSING_ERROR: 'steeringManifestParsingError',
};
/**
* @brief If no other error fits, use this error.
*/
class ExceptionError extends HlsError {
constructor(fatal, reason, response) {
super(ErrorTypes.OTHER_ERROR, ErrorDetails.INTERNAL_EXCEPTION, fatal, reason, response);
}
}
class FragParsingError extends HlsError {
constructor(fatal, reason, response) {
super(ErrorTypes.MEDIA_ERROR, ErrorDetails.FRAG_PARSING_ERROR, fatal, reason, response);
}
}
class RemuxAllocError extends HlsError {
constructor(fatal, reason, response, bytes) {
super(ErrorTypes.MUX_ERROR, ErrorDetails.REMUX_ALLOC_ERROR, fatal, reason, response);
this.bytes = bytes;
}
}
function convertTimestampToSeconds(ts) {
return ts.baseTime / ts.timescale;
}
function convertSecondsToTimestamp(sec, timescale) {
return {
baseTime: Math.floor(sec * timescale),
timescale,
};
}
function convertTimescale(ts, timescale) {
return {
baseTime: Math.floor((ts.baseTime * timescale) / ts.timescale),
timescale,
};
}
function determineMinTimestamp(a, b) {
const aSec = convertTimestampToSeconds(a);
const bSec = convertTimestampToSeconds(b);
return aSec < bSec ? a : b;
}
function determineMaxTimestamp(a, b) {
const aSec = convertTimestampToSeconds(a);
const bSec = convertTimestampToSeconds(b);
return aSec > bSec ? a : b;
}
/**
* @returns returns a - b in seconds
*/
function diffSeconds(a, b) {
return convertTimestampToSeconds(a) - convertTimestampToSeconds(b);
}
class EventEmitterPolyfill {
constructor() {
this.eventMap = {};
}
_on(eventName, eventRecord, prepend = false) {
if (this.eventMap[eventName] == null) {
this.eventMap[eventName] = [];
}
if (prepend) {
this.eventMap[eventName].splice(0, 0, eventRecord);
}
else {
this.eventMap[eventName].push(eventRecord);
}
return this;
}
_off(eventName, record) {
if (this.eventMap[eventName] != null) {
this.eventMap[eventName] = this.eventMap[eventName].filter(r => r.listener !== record.listener);
if (this.eventMap[eventName].length === 0) {
delete this.eventMap[eventName];
}
}
return this;
}
on(eventName, listener) {
return this._on(eventName, { listener, once: false });
}
off(eventName, listener) {
return this._off(eventName, { listener });
}
addListener(eventName, listener) {
return this.on(eventName, listener);
}
once(eventName, listener) {
return this._on(eventName, { listener, once: true });
}
removeListener(eventName, listener) {
return this.off(eventName, listener);
}
removeAllListeners(event) {
delete this.eventMap[event];
return this;
}
setMaxListeners(n) {
return this;
}
getMaxListeners() {
return Infinity;
}
// eslint-disable-next-line @typescript-eslint/ban-types
listeners(eventName) {
if (this.eventMap[eventName] == null) {
return [];
}
return this.eventMap[eventName].map(r => r.listener);
}
// eslint-disable-next-line @typescript-eslint/ban-types
rawListeners(eventName) {
return this.listeners(eventName);
}
emit(eventName, ...args) {
if (this.eventMap[eventName] == null) {
return false;
}
let emitted = false;
for (const record of this.eventMap[eventName]) {
try {
record.listener.apply(this, args);
// eslint-disable-next-line no-empty
}
catch (err) { }
emitted = true;
}
return emitted;
}
listenerCount(eventName) {
if (this.eventMap[eventName] == null) {
return 0;
}
return this.eventMap[eventName].length;
}
prependListener(eventName, listener) {
return this._on(eventName, { listener, once: false }, true);
}
prependOnceListener(eventName, listener) {
return this._on(eventName, { listener, once: true }, true);
}
eventNames() {
return Object.keys(this.eventMap);
}
}
const EventEmitter = typeof global$1.Buffer !== 'undefined' ? (r => r('events'))(require).EventEmitter : EventEmitterPolyfill;
/**
* Simple adapter sub-class of Nodejs-like EventEmitter.
*/
class Observer extends EventEmitter {
/**
* We simply want to pass along the event-name itself
* in every call to a handler, which is the purpose of our `trigger` method
* extending the standard API.
*/
trigger(event, data) {
this.emit(event, data);
}
}
const loggerName$l = { name: 'ADTS' };
const ADTS = {
getAudioConfig: function (observer, data, offset, audioCodec, logger) {
let adtsObjectType; // :int
let extensionSamplingIndex; // :int
let adtsChanelConfig; // :int
let config;
const userAgent = navigator.userAgent.toLowerCase();
const adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
// byte 2
adtsObjectType = ((data[offset + 2] & 192) >>> 6) + 1;
const adtsSamplingIndex = (data[offset + 2] & 60) >>> 2;
if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
const payload = new FragParsingError(true, `invalid ADTS sampling index:${adtsSamplingIndex}`, ErrorResponses.InvalidADTSSamplingIndex);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return;
}
adtsChanelConfig = (data[offset + 2] & 1) << 2;
// byte 3
adtsChanelConfig |= (data[offset + 3] & 192) >>> 6;
logger.info(loggerName$l, `manifest codec:${audioCodec},ADTS data:type:${adtsObjectType},samplingIndex:${adtsSamplingIndex}[${adtsSamplingRates[adtsSamplingIndex]}Hz],channelConfig:${adtsChanelConfig}`);
// firefox: freq less than 24kHz = AAC SBR (HE-AAC)
if (/firefox/i.test(userAgent)) {
if (adtsSamplingIndex >= 6) {
adtsObjectType = 5;
config = new Array(4);
// HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies
// there is a factor 2 between frame sample rate and output sample rate
// multiply frequency by 2 (see table below, equivalent to substract 3)
extensionSamplingIndex = adtsSamplingIndex - 3;
}
else {
adtsObjectType = 2;
config = new Array(2);
}
// Android : always use AAC
}
else if (userAgent.indexOf('android') !== -1) {
adtsObjectType = 2;
config = new Array(2);
}
else {
/* for other browsers (Chrome/Vivaldi/Opera ...)
always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...)
*/
adtsObjectType = 5;
config = new Array(4);
// if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz)
if ((audioCodec && (audioCodec.indexOf('mp4a.40.29') !== -1 || audioCodec.indexOf('mp4a.40.5') !== -1)) || (!audioCodec && adtsSamplingIndex >= 6)) {
// HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies
// there is a factor 2 between frame sample rate and output sample rate
// multiply frequency by 2 (see table below, equivalent to substract 3)
extensionSamplingIndex = adtsSamplingIndex - 3;
}
else {
// if (manifest codec is AAC) OR (manifest codec not specified and mono audio)
// Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC. This is not a problem with stereo.
if ((audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1) || (!audioCodec && adtsChanelConfig === 1)) {
adtsObjectType = 2;
config = new Array(2);
}
extensionSamplingIndex = adtsSamplingIndex;
}
}
/* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config
ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig()
Audio Profile / Audio Object Type
0: Null
1: AAC Main
2: AAC LC (Low Complexity)
3: AAC SSR (Scalable Sample Rate)
4: AAC LTP (Long Term Prediction)
5: SBR (Spectral Band Replication)
6: AAC Scalable
sampling freq
0: 96000 Hz
1: 88200 Hz
2: 64000 Hz
3: 48000 Hz
4: 44100 Hz
5: 32000 Hz
6: 24000 Hz
7: 22050 Hz
8: 16000 Hz
9: 12000 Hz
10: 11025 Hz
11: 8000 Hz
12: 7350 Hz
13: Reserved
14: Reserved
15: frequency is written explictly
Channel Configurations
These are the channel configurations:
0: Defined in AOT Specifc Config
1: 1 channel: front-center
2: 2 channels: front-left, front-right
*/
// audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1
config[0] = adtsObjectType << 3;
// samplingFrequencyIndex
config[0] |= (adtsSamplingIndex & 14) >> 1;
config[1] |= (adtsSamplingIndex & 1) << 7;
// channelConfiguration
config[1] |= adtsChanelConfig << 3;
if (adtsObjectType === 5) {
// extensionSamplingIndex
config[1] |= (extensionSamplingIndex & 14) >> 1;
config[2] = (extensionSamplingIndex & 1) << 7;
// adtsObjectType (force to 2, chrome is checking that object type is less than 5 ???
// https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc
config[2] |= 2 << 2;
config[3] = 0;
}
const audioConfig = { esdsConfig: config, samplerate: adtsSamplingRates[adtsSamplingIndex], channelCount: adtsChanelConfig, segmentCodec: 'aac', codec: 'mp4a.40.' + adtsObjectType };
return audioConfig;
},
};
class DemuxerBase {
constructor(observer, remuxer, config, typeSupported, logger) {
this.observer = observer;
this.remuxer = remuxer;
this.config = config;
this.typeSupported = typeSupported;
this.logger = logger;
}
static probe(data, logger) {
throw new Error('Method not implemented');
}
resetTimeStamp(initPTS90k) { }
resetInitSegment(initSegment, duration, keyTagInfo, discontinuity) { }
destroy() { }
}
class EsDemuxer extends DemuxerBase {
constructor(observer, remuxer, config, typeSupported, logger) {
super(observer, remuxer, config, typeSupported, logger);
this.observer = observer;
this.remuxer = remuxer;
this.config = config;
this.typeSupported = typeSupported;
this.logger = logger;
this.esRemuxer = remuxer;
}
}
class RemuxerBase {
constructor(observer, config, logger) {
this.observer = observer;
this.config = config;
this.logger = logger;
}
resetInitSegment() { }
resetTimeStamp(initPTS90k) { }
destroy() { }
}
/*
* 2018 Apple Inc. All rights reserved.
*/
var _a$1;
let te;
let td;
const BrowserBufferUtils = {
/**
* Convert a string object into a uint8Array containing utf-8 encoded text
* @param str The string to convert
* @returns A uint8Array containing utf-8 encoded text
*/
strToUtf8array(str) {
if (!te) {
te = new TextEncoder();
}
return te.encode(str);
},
/**
* Convert a uint8Array containing utf-8 encoded text into a string object
* @param array The array to convert containing utf-8 encoded text
* @returns A DOMString containing the decoded text
*/
utf8arrayToStr(array) {
if (!td) {
td = new TextDecoder('utf-8');
}
return td.decode(array);
},
};
const NodeJSBufferUtils = {
/**
* Convert a string object into a uint8Array containing utf-8 encoded text
* @param str The string to convert
* @returns A uint8Array containing utf-8 encoded text
*/
strToUtf8array(str) {
const buffer = global$1.Buffer.from(str, 'utf-8');
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
},
/**
* Convert a uint8Array containing utf-8 encoded text into a string object
* @param array The array to convert containing utf-8 encoded text
* @returns A DOMString containing the decoded text
*/
utf8arrayToStr(array) {
return global$1.Buffer.from(array).toString('utf-8');
},
};
const FallbackBufferUtils = {
/**
* Convert a string object into a uint8Array containing utf-8 encoded text
* @param str The string to convert
* @returns A uint8Array containing utf-8 encoded text
*/
strToUtf8array(str) {
const utf8 = unescape(encodeURIComponent(str));
const result = new Uint8Array(utf8.length);
for (let i = 0; i < utf8.length; i++) {
result[i] = utf8.charCodeAt(i);
}
return result;
},
/**
* Convert a uint8Array containing utf-8 encoded text into a string object
* @param array The array to convert containing utf-8 encoded text
* @returns A DOMString containing the decoded text
*/
utf8arrayToStr(array) {
return String.fromCharCode.apply(null, Array.from(array));
},
};
let BufferUtils = FallbackBufferUtils;
if (typeof TextEncoder !== 'undefined' && typeof TextDecoder !== 'undefined') {
BufferUtils = BrowserBufferUtils;
}
else if (typeof ((_a$1 = global$1.Buffer) === null || _a$1 === void 0 ? void 0 : _a$1.from) === 'function') {
BufferUtils = NodeJSBufferUtils;
}
const loggerName$k = { name: 'ID3' };
class ID3 {
// TODO: I am not comfortable with infinite loop ....
constructor(data, logger) {
this.logger = logger;
this._hasTimeStamp = false;
this._audioType = null;
this._length = 0;
this._frames = [];
let offset = 0, tagSize, endPos, header, len;
do {
header = ID3.readUTF(data, offset, 3);
offset += 3;
// first check for ID3 header
if (header === 'ID3') {
// v2.* tags only
// skip 16 bit version
this._minor = data[offset++];
this._revision = data[offset++];
const tagFlags = data[offset++]; // 1 byte flag (top 3 bits used)
if (tagFlags & 128) {
// is unsynchroized
this._unsynchronized = true;
this.logger.error(loggerName$k, 'id3 tag is unsynchronized');
}
if (tagFlags & 64) {
this._hasExtendedHeader = true;
this.logger.warn(loggerName$k, 'id3 tag has extended header');
}
// retrieve tag(s) length
// The ID3v2 tag size is the sum of the byte length of the extended
// header, the padding and the frames after unsynchronisation. If a
// footer is present this equals to ('total size' - 20) bytes, otherwise
// ('total size' - 10) bytes.
tagSize = ID3.readSynchSafeUint32(data.subarray(offset, offset + 4));
offset += 4;
endPos = offset + tagSize; // tagSize accounts for extended header
if (this._hasExtendedHeader) {
// has extended header
const extendedHeaderSize = ID3.readSynchSafeUint32(data.subarray(offset, offset + 4));
this.logger.warn(loggerName$k, `id3 tag has ${extendedHeaderSize}-byte extended header. usually 6 or 10 bytes`);
offset += extendedHeaderSize;
}
// read ID3 frames
if (this.minor > 2) {
this._parseID3Frames(data, offset, endPos);
}
else {
this.logger.error(loggerName$k, '[id3] doesn\'t support older than v2.3 tags');
}
offset = endPos;
}
else if (header === '3DI') {
// http://id3.org/id3v2.4.0-structure chapter 3.4. ID3v2 footer
offset += 7;
}
else {
offset -= 3;
len = offset;
if (len) {
if (!this.hasTimeStamp) {
this.logger.warn(loggerName$k, 'ID3 tag found, but no timestamp');
}
this._length = len;
this._payload = data.slice(0, len);
}
return;
}
} while (true); // eslint-disable-line
}
static isHeader(data, offset) {
if (data[offset] === 73 && data[offset + 1] === 68 && data[offset + 2] === 51) {
// check version is within range
if (data[offset + 3] < 255 && data[offset + 4] < 255) {
// check size is within range
if (data[offset + 6] < 128 && data[offset + 7] < 128 && data[offset + 8] < 128 && data[offset + 9] < 128) {
return true;
}
}
}
return false;
}
static readSynchSafeUint32(data) {
return (data[0] & 127) * 2097152 + (data[1] & 127) * 16384 + (data[2] & 127) * 128 + (data[3] & 127);
}
static readUTF(data, start, len) {
let result = '', offset = start;
const end = start + len;
do {
result += String.fromCharCode(data[offset++]);
} while (offset < end);
return result;
}
isID3Frame(data, offset) {
if (data[offset + 4] < 128 && data[offset + 5] < 128 && data[offset + 6] < 128 && data[offset + 7] < 128) {
return true;
}
return false;
}
decodeID3Frame(frame) {
if (frame.type === 'TXXX') {
return this.decodeTxxxFrame(frame);
}
else if (frame.type === 'WXXX') {
return this.decodeWxxxFrame(frame);
}
else if (frame.type === 'PRIV') {
return this.decodePrivFrame(frame);
}
else if (frame.type[0] === 'T') {
return this.decodeTextFrame(frame);
}
else {
return { key: frame.type, data: frame.data };
}
}
decodeTxxxFrame(frame) {
/*
Format:
[0] = {Text Encoding}
[1-?] = {Description}\0{Value}
*/
if (frame.size < 2) {
return undefined;
}
if (frame.data[0] !== 3) {
// only support UTF-8
return undefined;
}
let index = 1;
const description = this.id3utf8ArrayToStr(frame.data.subarray(index));
index += description.length + 1;
const value = this.id3utf8ArrayToStr(frame.data.subarray(index));
return { key: 'TXXX', description, data: value };
}
decodeWxxxFrame(frame) {
/*
Format:
[0] = {Text Encoding}
[1-?] = {Description}\0{Value}
*/
if (frame.size < 2) {
return undefined;
}
if (frame.data[0] !== 3) {
// only support UTF-8
return undefined;
}
let index = 1;
const description = this.id3utf8ArrayToStr(frame.data.subarray(index));
index += description.length + 1;
// Need to use the BufferUtils version of utf8arrayToStr since it works
// with arrays that doesn't have a '\0' in the end of the array.
const value = BufferUtils.utf8arrayToStr(frame.data.subarray(index));
return { key: 'WXXX', description, data: value };
}
decodeTextFrame(frame) {
/*
Format:
[0] = {Text Encoding}
[1-?] = {Value}
*/
if (frame.size < 2) {
return undefined;
}
if (frame.data[0] !== 3) {
// only support UTF-8
return undefined;
}
const data = frame.data.subarray(1);
return { key: frame.type, data: this.id3utf8ArrayToStr(data) };
}
decodePrivFrame(frame) {
/*
Format: \0
*/
if (frame.size < 2) {
return undefined;
}
const owner = this.id3utf8ArrayToStr(frame.data);
const privateData = frame.data.slice(owner.length + 1);
return { key: 'PRIV', info: owner, data: privateData };
}
_extractID3Frame(data, frameId, frameLen, frameBodyOffset, endPos) {
const frameEnd = frameBodyOffset + frameLen;
let frame;
if (frameEnd <= endPos) {
frame = { type: frameId, data: data.slice(frameBodyOffset, frameEnd) };
}
else {
this.logger.error(loggerName$k, `id3 frame ${frameId} size ${frameLen} exceeded ${endPos}`);
}
return frame;
}
_parseID3Frames(data, offset, endPos) {
let tagId, tagLen, tagStart, timestamp;
while (offset + 8 <= endPos) {
this.logger.info(loggerName$k, `[id3] _parseID3Frames ${offset} ${endPos}`);
if (!this.isID3Frame(data, offset)) {
this.logger.error(loggerName$k, `[id3] illegal id3 frame @ offset ${offset}. skip this id3 tag`);
return;
}
tagId = ID3.readUTF(data, offset, 4);
offset += 4;
if (tagId === '') {
this.logger.info(loggerName$k, '[id3] empty tagId. padding.');
return;
}
tagLen = ID3.readSynchSafeUint32(data.subarray(offset, offset + 4));
if (tagLen === 0) {
this.logger.info(loggerName$k, '[id3] zero tag length. padding.');
return;
}
offset += 4;
data[offset++] << (8 + data[offset++]);
tagStart = offset;
this.logger.info(loggerName$k, '[id3] tag id:' + tagId + ' tagLen ' + tagLen + ' offset ' + offset + ' endPos ' + endPos);
this.logger.qe({ critical: true, name: 'id3Parsed', data: { tagId, tagLen, offset, endPos } });
const frame = this._extractID3Frame(data, tagId, tagLen, tagStart, endPos);
if (frame) {
const id3Frame = this.decodeID3Frame(frame);
this._frames.push(id3Frame);
}
switch (tagId) {
case 'PRIV':
// this.logger.info(loggerName, 'parse frame:' + Hex.hexDump(data.subarray(offset,endPos)));
// owner should be "com.apple.streaming.transportStreamTimestamp"
if (tagLen === 53 && ID3.readUTF(data, offset, 44) === 'com.apple.streaming.transportStreamTimestamp') {
offset += 44;
// smelling even better ! we found the right descriptor
// skip null character (string end) + 3 first bytes
offset += 4;
// timestamp is 33 bit expressed as a big-endian eight-octet number, with the upper 31 bits set to zero.
const pts33Bit = data[offset++] & 1;
this._hasTimeStamp = true;
timestamp = ((data[offset++] << 23) + (data[offset++] << 15) + (data[offset++] << 7) + data[offset++]) / 45;
if (pts33Bit) {
timestamp += 47721858.84; // 2^32 / 90
}
timestamp = Math.round(timestamp);
this.logger.info(loggerName$k, `ID3 timestamp found: ${timestamp}`);
this._timeStamp = timestamp;
}
else if (tagLen >= 45 && ID3.readUTF(data, offset, 36) === 'com.apple.streaming.audioDescription') {
offset += 37; // skip tag and null terminator
this._audioType = ID3.readUTF(data, offset, 4);
offset += 4;
// skip everything else for now, don't think we need anything from the audio setup
offset += tagLen - 41;
this.logger.info(loggerName$k, `ID3 audio description found: ${this._audioType}`);
}
else {
offset += tagLen;
}
break;
default:
{
offset += tagLen;
}
break;
}
this.logger.info(loggerName$k, `[id3] ${tagId} default tagLen ${tagLen} offset ${offset} endPos ${endPos}`);
}
}
// id3utf8ArrayToStr is different from BufferUtils.utfarrayToStr. It exists when the string ends.
// BufferUtils.utfarrayToStr will decode the entire array.
// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
/** utf.js - UTF-8 <=> UTF-16 convertion
*
* Copyright (C) 1999 Masanao Izumo
* Version: 1.0
* LastModified: Dec 25 1999
* This library is free. You can redistribute it and/or modify it.
*/
id3utf8ArrayToStr(array) {
let char2;
let char3;
let out = '';
let i = 0;
const length = array.length;
while (i < length) {
const c = array[i++];
switch (c >> 4) {
case 0:
return out;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12:
case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 31) << 6) | (char2 & 63));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(((c & 15) << 12) | ((char2 & 63) << 6) | ((char3 & 63) << 0));
break;
}
}
}
get hasTimeStamp() {
return this._hasTimeStamp;
}
get timeStamp() {
return this._timeStamp;
}
get audioType() {
return this._audioType;
}
get length() {
return this._length;
}
get payload() {
return this._payload;
}
get frames() {
return this._frames;
}
get minor() {
return this._minor;
}
get revision() {
return this._revision;
}
}
var ID3$1 = ID3;
const loggerName$j = { name: 'AACDemuxer' };
class AACDemuxer extends EsDemuxer {
resetInitSegment(initSegment, duration) {
this.audioConfig = undefined;
this.audioTrack = undefined;
this.duration = duration;
}
static probe(data, logger) {
// check if data contains ID3 timestamp and ADTS sync word
const id3 = new ID3$1(data, logger);
let offset, length;
// Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
// Layer bits (position 14 and 15) in header should be always 0 for ADTS
// More info https://wiki.multimedia.cx/index.php?title=ADTS
for (offset = id3.length, length = Math.min(data.length - 1, offset + 100); offset < length; offset++) {
if (data[offset] === 255 && (data[offset + 1] & 246) === 240) {
return true;
}
}
return false;
}
// feed incoming data to the front of the parsing pipeline
append(data, timeOffset, contiguous, accurateTimeOffset, keyTagInfo) {
const id3 = new ID3$1(data, this.logger);
const pts = id3.hasTimeStamp ? 90 * id3.timeStamp : 90000 * timeOffset;
if (!id3.hasTimeStamp) {
this.logger.info(loggerName$j, `missing id3 timestamp at timeOffset ${timeOffset.toFixed(3)}`);
}
let frameLength, frameIndex, offset, headerLength, stamp, length;
let aacSample;
let id3Track = undefined;
let frames = undefined;
let payload = undefined;
if (id3.length) {
payload = id3.payload;
if (id3.frames.length) {
frames = id3.frames;
}
this.logger.info(loggerName$j, `[id3] init id3 tag pts=${pts} frames=${id3.frames.length}`);
id3Track = { id3Samples: [{ pts: pts, dts: pts, data: payload, frames: frames }], inputTimescale: 90000 };
}
// Look for ADTS header
for (offset = id3.length, length = data.length; offset < length - 1; offset++) {
if (data[offset] === 255 && (data[offset + 1] & 246) === 240) {
break;
}
}
if (!this.audioConfig) {
this.audioConfig = ADTS.getAudioConfig(this.observer, data, offset, undefined, this.logger);
if (!this.audioConfig) {
throw 'failed to parse adts config';
}
this.logger.info(loggerName$j, `parsed codec:${this.audioConfig.codec},rate:${this.audioConfig.samplerate},nb channel:${this.audioConfig.channelCount}`);
}
if (!this.audioTrack) {
const info = { id: 258, inputTimescale: 90000, timescale: NaN, duration: this.duration, encrypted: false, keyTagInfo };
const parsingData = { len: 0, sequenceNumber: 0, esSamples: [] };
this.audioTrack = { info, parsingData, type: 'audio', config: this.audioConfig };
}
if (id3.audioType === 'zaac' || id3.audioType === 'zach' || id3.audioType === 'zacp') {
this.audioTrack.info.encrypted = true;
this.logger.info(loggerName$j, 'found encrypted aac');
}
frameIndex = 0;
const frameDuration = 92160000 / this.audioConfig.samplerate;
while (offset + 5 < length) {
// The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header
headerLength = data[offset + 1] & 1 ? 7 : 9;
// retrieve frame size
frameLength = ((data[offset + 3] & 3) << 11) | (data[offset + 4] << 3) | ((data[offset + 5] & 224) >>> 5);
frameLength -= headerLength;
// stamp = pes.pts;
if (frameLength > 0 && offset + headerLength + frameLength <= length) {
stamp = pts + frameIndex * frameDuration;
aacSample = { unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp, keyTagInfo: keyTagInfo };
this.audioTrack.parsingData.esSamples.push(aacSample);
this.audioTrack.parsingData.len += frameLength;
offset += frameLength + headerLength;
frameIndex++;
// look for ADTS header (0xFFFx)
for (; offset < length - 1; offset++) {
if (ID3$1.isHeader(data, offset)) {
const embedId3 = new ID3$1(data.subarray(offset), this.logger);
if (embedId3.length > 0) {
offset += embedId3.length; // parses the interleaved ID3 packet
const localPts = embedId3.hasTimeStamp ? 90 * embedId3.timeStamp : pts;
id3Track.id3Samples.push({ pts: localPts, dts: localPts, data: embedId3.payload, frames: embedId3.frames });
}
else {
this.logger.error(loggerName$j, `[id3] invalid length ${length}`);
}
}
if (data[offset] === 255 && (data[offset + 1] & 246) === 240) {
break;
}
}
}
else {
break;
}
}
this.esRemuxer.remuxEsTracks(this.audioTrack, undefined, id3Track, undefined, timeOffset, contiguous, accurateTimeOffset, keyTagInfo);
}
}
/*
* Utility methods to perform bit manipulations.
*
* 2019 Apple Inc. All rights reserved.
*/
class BitstreamUtils {
/**
* This method is used to read a value from a bit-range in the data buffer.
*
* @param {Uint8Array} data - Data buffer.
* @param {BitStream} bitStream - Current position in the data buffer; gets updated by this method.
* @param {number} numBits - Total number of bits to read.
*
* @return {number} Numeric value of the bits read.
*
* Usage: bsReadAndUpdate(data, {byteOffset: 1, usedBits: 3}, 7)
* => will read 5 bits from data[1] and 2 bits from data[2] and return the numeric value of those 7 bits.
* => will update the bitStream to {byteOffset: 2, usedBits: 2}
*/
bsReadAndUpdate(data, bitStream, numBits) {
const result = this.readBits(data, bitStream, numBits);
this.updateOffset(bitStream, numBits);
return result;
}
/**
* This method is used to write a value to a bit-range in the data buffer.
*
* @param {Uint8Array} data - Data buffer.
* @param {BitStream} bitStream - Current position in the data buffer; gets updated by this method.
* @param {number} numBits - Total number of bits to write.
* @param {number} value - The value to write.
*
* Usage: bsWriteAndUpdate(data, {byteOffset: 1, usedBits: 3}, 7)
* => will write most significant 5 bits of value to data[1] and remaining 4 bits to data[2].
* => will update the bitStream to {byteOffset: 2, usedBits: 2}
*/
bsWriteAndUpdate(data, bitStream, numBits, value) {
const result = this.writeBits(data, bitStream, numBits, value);
this.updateOffset(bitStream, numBits);
return result;
}
/**
* This method is used to update the bitStream offsets.
*
* @param {BitStream} bitStream - Current offset (In) / New offset (Out).
* @param {number} numBits - Total number of bits to skip.
*
* Usage: bsSkip({byteOffset: 1, usedBits: 3}, 7)
* => will update the bitStream to {byteOffset: 2, usedBits: 2}
*/
bsSkip(bitStream, numBits) {
this.updateOffset(bitStream, numBits);
}
// private helper methods
readBits(data, bitStream, numBits) {
if (!data || !bitStream) {
return undefined;
}
let offset = bitStream.byteOffset;
const { usedBits } = bitStream;
if (usedBits >= 8 || usedBits + numBits > 32) {
return undefined;
}
let result;
// some strong typed variables for reliable bit manipulation
const temp = new Uint32Array(1); // unsigned 32 bit for temporary storage
const mask = new Uint32Array(1); // unsigned 32 bit mask value
const byte = new Uint8Array(1); // unsigned 8 bit for temporary storage
if (usedBits >= 8 || numBits > 32) {
return undefined;
}
/*
* read msb to lsb from data[offset] starting from the first unused bit of data[offset]
* for e.g. data[0] => 11110010
* data[1] => 00111101
* data[2] => 00101001
* numBits => 18
* usedBits => 2
* byteOffset => 0
* will fetch bits
* data[0] => xx100011
* data[1] => 11011100
* data[2] => 1011xxxx
* and return
* 00000000 00000010 00111101 11001011
*/
if (usedBits) {
// read unused bits from the partial byte
const bits = 8 - usedBits;
const shift = numBits < bits ? bits - numBits : 0;
mask[0] = 4278190080 >>> (32 - bits);
result = (data[offset] & mask[0]) >>> shift;
offset += 1;
numBits -= bits;
}
while (numBits > 0) {
byte[0] = data[offset];
// read remaining bits, upto 8 bits at a time
const bits = Math.min(numBits, 8);
const shift = 8 - bits;
mask[0] = (4278190080 >>> (24 + shift)) << shift;
temp[0] = (byte[0] & mask[0]) >> shift;
result = !result ? temp[0] : (result << bits) | temp[0];
offset += 1;
numBits -= bits;
}
return result;
}
writeBits(data, bitStream, numBits, value) {
if (!data || !bitStream) {
return undefined;
}
let offset = bitStream.byteOffset;
const { usedBits } = bitStream;
if (usedBits >= 8 || usedBits + numBits > 32) {
return undefined;
}
// some strong typed variables for reliable bit manipulation
const tval = new Uint32Array(1); // unsigned 32 bit to store the incoming value
const temp = new Uint32Array(1); // unsigned 32 bit for temporary storage
const mask = new Uint32Array(1); // unsigned 32 bit mask value
const byte = new Uint8Array(1); // unsigned 8 bit for temporary storage
tval[0] = value;
/*
* write msb to lsb from value into data[offset] starting from the first unused bit of data[offset]
* for e.g. value => 00000000 00000010 00111101 11001011
* numBits => 18
* usedBits => 2
* byteOffset => 0
* will get written as
* data[0] => xx100011
* data[1] => 11011100
* data[2] => 1011xxxx
*/
if (usedBits) {
// left align the value, mask the bits, and then right align to exclude the used bits
temp[0] = tval[0] << (32 - numBits);
mask[0] = 4278190080;
byte[0] = (temp[0] & mask[0]) >>> (24 + usedBits);
// clear the bits and write
data[offset] &= ~(mask[0] >>> (24 + usedBits));
data[offset] |= byte[0];
offset += 1;
numBits -= 8 - usedBits;
}
while (numBits > 0) {
// left align the remaining bits of value and write in blocks of 8
temp[0] = tval[0] << (32 - numBits);
mask[0] = 4278190080;
byte[0] = (temp[0] & mask[0]) >>> 24;
// right align the mask, and then right shift and left shift to clear the used bits
const shift = numBits < 0 ? 8 - numBits : 0;
data[offset] &= ~(((mask[0] >>> 24) >>> shift) << shift);
// write the bits
data[offset] |= byte[0];
numBits -= 8;
offset += 1;
}
return 0;
}
updateOffset(bitStream, numBits) {
if (!bitStream || !numBits || bitStream.usedBits + numBits > 32) {
return;
}
// calculate the number of bits seen in the current byte offset
const bitsSeenInByte = bitStream.usedBits % 8;
// calculate the bytes and bits based on the last read/write operation
const bytesAdvanced = Math.floor((bitsSeenInByte + numBits) / 8);
const bitsAdvanced = (bitsSeenInByte + numBits) % 8;
// update the new position
bitStream.byteOffset += bytesAdvanced;
bitStream.usedBits = bitsAdvanced;
}
}
const loggerName$i = { name: 'Dolby' };
const samplingRateMap = [48000, 44100, 32000];
const frameSizeMap = [
64,
69,
96,
64,
70,
96,
80,
87,
120,
80,
88,
120,
96,
104,
144,
96,
105,
144,
112,
121,
168,
112,
122,
168,
128,
139,
192,
128,
140,
192,
160,
174,
240,
160,
175,
240,
192,
208,
288,
192,
209,
288,
224,
243,
336,
224,
244,
336,
256,
278,
384,
256,
279,
384,
320,
348,
480,
320,
349,
480,
384,
417,
576,
384,
418,
576,
448,
487,
672,
448,
488,
672,
512,
557,
768,
512,
558,
768,
640,
696,
960,
640,
697,
960,
768,
835,
1152,
768,
836,
1152,
896,
975,
1344,
896,
976,
1344,
1024,
1114,
1536,
1024,
1115,
1536,
1152,
1253,
1728,
1152,
1254,
1728,
1280,
1393,
1920,
1280,
1394,
1920,
];
const Dolby = {
getFrameDuration: function (config, timescale) {
return (1536 / config.samplerate) * timescale;
},
getAudioConfig: function (observer, data, offset, logger) {
let payload;
if (offset + 8 > data.length) {
payload = new FragParsingError(true, 'error parsing ac-3, not enough data', ErrorResponses.InsufficientAC3Data);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
if (data[offset] !== 11 || data[offset + 1] !== 119) {
// payload = { type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'invalid ac-3 magic' };
payload = new FragParsingError(true, 'invalid ac-3 magic', ErrorResponses.InvalidAC3Magic);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
const samplingRateCode = data[offset + 4] >> 6;
if (samplingRateCode >= 3) {
payload = new FragParsingError(true, `invalid ac-3 samplingRateCode:${samplingRateCode}`, ErrorResponses.InvalidAC3SamplingRateCode);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
// get frame size
const frameSizeCode = data[offset + 4] & 63;
const frameLength = frameSizeMap[frameSizeCode * 3 + samplingRateCode] * 2;
const channelMode = data[offset + 6] >> 5;
let skipCount = 0;
if (channelMode === 2) {
skipCount += 2;
}
else {
if (channelMode & 1 && channelMode !== 1) {
skipCount += 2;
}
if (channelMode & 4) {
skipCount += 2;
}
}
const lfeon = (((data[offset + 6] << 8) | data[offset + 7]) >> (12 - skipCount)) & 1;
const channelsMap = [2, 1, 2, 3, 3, 4, 4, 5];
const channelCount = channelsMap[channelMode] + lfeon;
const bsid = data[offset + 5] >> 3;
const bsmod = data[offset + 5] & 7;
const extraData = (samplingRateCode << 22) | (bsid << 17) | (bsmod << 14) | (channelMode << 11) | (lfeon << 10) | ((frameSizeCode >> 1) << 5);
const samplerate = samplingRateMap[samplingRateCode];
logger.info(loggerName$i, `parsed codec: ac-3, rate:${samplerate}, nb channel:${channelCount}, first frameLength:${frameLength}`);
const audioConfig = { samplerate: samplerate, channelCount: channelCount, segmentCodec: 'ac3', codec: 'ac-3', extraData: extraData };
return audioConfig;
},
getFrameLength: function (observer, data, offset) {
let payload;
if (offset + 8 > data.length) {
payload = new FragParsingError(true, 'error parsing ac-3, not enough data', ErrorResponses.InsufficientAC3Data);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
if (data[offset] !== 11 || data[offset + 1] !== 119) {
payload = new FragParsingError(true, 'invalid ac-3 magic', ErrorResponses.InvalidAC3Magic);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
const samplingRateCode = data[offset + 4] >> 6;
if (samplingRateCode >= 3) {
payload = new FragParsingError(true, `invalid ac-3 samplingRateCode:${samplingRateCode}`, ErrorResponses.InvalidAC3SamplingRateCode);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
// get frame size
const frameSizeCode = data[offset + 4] & 63;
return frameSizeMap[frameSizeCode * 3 + samplingRateCode] * 2;
},
};
const loggerName$h = { name: 'AC3Demuxer' };
class AC3Demuxer extends EsDemuxer {
resetInitSegment(initSegment, duration) {
this.audioConfig = undefined;
this.audioTrack = undefined;
this.duration = duration;
}
static probe(data, logger) {
// check if data contains ID3 timestamp and AC3 sync bytes
const id3 = new ID3$1(data, logger), offset = id3.length;
// look for the ac-3 sync bytes
if (id3.hasTimeStamp && data[offset] === 11 && data[offset + 1] === 119) {
// check the bsid to confirm ac-3
const bu = new BitstreamUtils();
const bsid = bu.bsReadAndUpdate(data, { byteOffset: offset + 5, usedBits: 0 }, 5);
if (bsid < 16) {
return true;
}
}
return false;
}
// feed incoming data to the front of the parsing pipeline
append(data, timeOffset, contiguous, accurateTimeOffset, keyTagInfo) {
const id3 = new ID3$1(data, this.logger);
const pts = 90 * id3.timeStamp;
const length = data.byteLength;
let frameIndex = 0;
let offset = id3.length;
if (!this.audioConfig) {
this.audioConfig = Dolby.getAudioConfig(this.observer, data, offset, this.logger);
}
if (!this.audioConfig) {
throw 'failed to parse ac3 config';
}
if (!this.audioTrack) {
const info = { id: 258, inputTimescale: 90000, timescale: NaN, duration: this.duration, encrypted: false, keyTagInfo };
const parsingData = { len: 0, sequenceNumber: 0, esSamples: [] };
this.audioTrack = { info, parsingData, type: 'audio', config: this.audioConfig };
}
const frameDuration = Dolby.getFrameDuration(this.audioConfig, this.audioTrack.info.inputTimescale); // (1536 / this.audioConfig.samplerate) * this.audioTrack.inputTimescale;
if (id3.audioType === 'zac3') {
this.audioTrack.info.encrypted = true;
this.logger.info(loggerName$h, 'found encrypted ac3');
}
while (offset < length) {
if (ID3$1.isHeader(data, offset)) {
const id3 = new ID3$1(data.subarray(offset), this.logger);
offset += id3.length; // skip the interleaved ID3 packet
}
if (data[offset] !== 11 || data[offset + 1] !== 119) {
const payload = new FragParsingError(true, 'invalid ac-3 magic', ErrorResponses.InvalidAC3Magic);
this.observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return;
}
const frameLength = Dolby.getFrameLength(this.observer, data, offset);
const stamp = pts + frameIndex * frameDuration;
const ac3Sample = { unit: data.subarray(offset, offset + frameLength), pts: stamp, dts: stamp, keyTagInfo: keyTagInfo };
this.audioTrack.parsingData.esSamples.push(ac3Sample);
this.audioTrack.parsingData.len += frameLength;
offset += frameLength;
frameIndex++;
}
this.esRemuxer.remuxEsTracks(this.audioTrack, undefined, { id3Samples: [{ pts: pts, dts: pts, data: id3.payload, frames: id3.frames }], inputTimescale: this.audioTrack.info.inputTimescale }, undefined, timeOffset, contiguous, accurateTimeOffset, keyTagInfo);
}
}
const loggerName$g = { name: 'DDPlus' };
const DDPlus = {
getFrameLength: function (observer, data, offset, logger) {
const bs = new BitstreamUtils();
let firstIndSubstream = false;
let totalFrameLength = 0;
let payload;
while (offset < data.length) {
if (offset + 8 > data.length) {
payload = new FragParsingError(true, 'error parsing ec-3, not enough data', ErrorResponses.InsufficientEC3Data);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
// skip the ID3 packet, if present
let id3Length = 0;
if (ID3$1.isHeader(data, offset)) {
const id3 = new ID3$1(data.subarray(offset), logger);
id3Length = id3.length || 0;
offset += id3Length;
}
// get syncword (16 bits)
if (data[offset] !== 11 || data[offset + 1] !== 119) {
payload = new FragParsingError(true, 'invalid ec-3 magic', ErrorResponses.InvalidEC3Magic);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
// skip the syncword and start parsing
const bitStream = { byteOffset: offset + 2, usedBits: 0 };
// get strmtyp & substreamid
const strmtyp = bs.bsReadAndUpdate(data, bitStream, 2);
const substreamid = bs.bsReadAndUpdate(data, bitStream, 3);
if (strmtyp === 0 || strmtyp === 2) {
if (firstIndSubstream === true) {
if (substreamid === 0) {
// we're seen all dependent sub-streams
break;
}
}
else {
firstIndSubstream = true; // mark that the first independent substream is seen
}
}
else if (strmtyp !== 1) {
payload = new FragParsingError(true, 'reserved stream type', ErrorResponses.ReservedStreamType);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
// get frmsiz
const frmsiz = bs.bsReadAndUpdate(data, bitStream, 11);
// advance to the next syncframe
const frameLength = (frmsiz + 1) * 2;
offset += frameLength;
totalFrameLength += frameLength + (id3Length || 0);
}
return totalFrameLength;
},
getAudioConfig: function (observer, data, offset, logger) {
const frameInfo = {
frmsiz: 0,
fscod: 0,
numblkscod: 0,
acmod: 0,
lfeon: 0,
bsid: 0,
strmtyp: 0,
substreamid: 0,
chanmape: 0,
chanmap: 0,
mixdef: 0,
mixdeflen: 0,
bsmod: 0,
};
const sampleInfo = {
fscod: 0,
acmod: 0,
lfeon: 0,
bsid: 0,
bsmod: 0,
chan_loc: 0,
data_rate: 0,
num_ind_sub: 0,
num_dep_sub: [],
complexity_index_type_a: 0,
};
const bs = new BitstreamUtils();
let firstIndSubstream = false;
let totalFrameLength = 0;
let payload;
while (offset < data.length) {
if (offset + 8 > data.length) {
payload = new FragParsingError(true, 'error parsing ec-3, not enough data', ErrorResponses.InsufficientEC3Data);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
// skip the ID3 packet, if present
let id3Length = 0;
if (ID3$1.isHeader(data, offset)) {
const id3 = new ID3$1(data.subarray(offset), logger);
id3Length = id3.length || 0;
offset += id3Length;
}
// get syncword (16 bits)
if (data[offset] !== 11 || data[offset + 1] !== 119) {
payload = new FragParsingError(true, 'invalid ec-3 magic', ErrorResponses.InvalidEC3Magic);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
// skip the syncword and start parsing
const bitStream = { byteOffset: offset + 2, usedBits: 0 };
// get strmtyp & substreamid
frameInfo.strmtyp = bs.bsReadAndUpdate(data, bitStream, 2);
frameInfo.substreamid = bs.bsReadAndUpdate(data, bitStream, 3);
if (frameInfo.strmtyp === 0 || frameInfo.strmtyp === 2) {
if (firstIndSubstream === true) {
if (frameInfo.substreamid === 0) {
// we're seen all dependent sub-streams
break;
}
}
else {
firstIndSubstream = true; // mark that the first independent substream is seen
}
sampleInfo.num_ind_sub++; // independent substream
sampleInfo.num_dep_sub.push(0); // initialize the dependent sub-stream count to 0
}
else if (frameInfo.strmtyp === 1) {
sampleInfo.num_dep_sub[sampleInfo.num_ind_sub - 1]++; // dependent substream
}
else {
payload = new FragParsingError(true, 'reserved stream type', ErrorResponses.ReservedStreamType);
observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return undefined;
}
// get frmsiz
frameInfo.frmsiz = bs.bsReadAndUpdate(data, bitStream, 11);
// get fscod, numblkscod
frameInfo.fscod = bs.bsReadAndUpdate(data, bitStream, 2);
if (frameInfo.fscod === 3) {
bs.bsSkip(bitStream, 2);
frameInfo.numblkscod = 3;
}
else {
frameInfo.numblkscod = bs.bsReadAndUpdate(data, bitStream, 2);
}
// get acmod
frameInfo.acmod = bs.bsReadAndUpdate(data, bitStream, 3);
// get lfeon
frameInfo.lfeon = bs.bsReadAndUpdate(data, bitStream, 1);
// get bsid
frameInfo.bsid = bs.bsReadAndUpdate(data, bitStream, 5);
bs.bsSkip(bitStream, 5);
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 8);
}
if (frameInfo.acmod === 0) {
bs.bsSkip(bitStream, 5);
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 8);
}
}
if (frameInfo.strmtyp === 1) {
// get chanmape
frameInfo.chanmape = bs.bsReadAndUpdate(data, bitStream, 1);
if (frameInfo.chanmape) {
// get chanmap
frameInfo.chanmap = bs.bsReadAndUpdate(data, bitStream, 16);
}
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
if (frameInfo.acmod > 2) {
bs.bsSkip(bitStream, 2);
}
if (frameInfo.acmod & 1 && frameInfo.acmod > 2) {
bs.bsSkip(bitStream, 6);
}
if (frameInfo.acmod & 4) {
bs.bsSkip(bitStream, 6);
}
if (frameInfo.lfeon) {
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 5);
}
}
if (frameInfo.strmtyp === 0) {
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 6);
}
if (frameInfo.acmod === 0) {
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 6);
}
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 6);
}
// get mixdef
frameInfo.mixdef = bs.bsReadAndUpdate(data, bitStream, 2);
if (frameInfo.mixdef === 1) {
bs.bsSkip(bitStream, 5);
}
else if (frameInfo.mixdef === 2) {
bs.bsSkip(bitStream, 12);
}
else if (frameInfo.mixdef === 3) {
// get mixdeflen
frameInfo.mixdeflen = bs.bsReadAndUpdate(data, bitStream, 5);
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 5);
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 4);
}
}
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 5);
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 7);
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 8);
}
}
}
// skip entire block that includes mixdata and mixdatafill
const skipBytes = frameInfo.mixdeflen + 2 + (bitStream.usedBits ? 1 : 0);
bitStream.byteOffset += skipBytes;
}
if (frameInfo.acmod < 2) {
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 14);
}
if (frameInfo.acmod === 0) {
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 14);
}
}
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
if (frameInfo.numblkscod === 0) {
bs.bsSkip(bitStream, 5);
}
else {
for (let i = 0; i < frameInfo.numblkscod; i++) {
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 5);
}
}
}
}
}
}
frameInfo.bsmod = 0;
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
frameInfo.bsmod = bs.bsReadAndUpdate(data, bitStream, 3);
bs.bsSkip(bitStream, 2);
if (frameInfo.acmod === 2) {
bs.bsSkip(bitStream, 4);
}
if (frameInfo.acmod >= 6) {
bs.bsSkip(bitStream, 2);
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 8);
}
if (frameInfo.acmod === 0) {
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
bs.bsSkip(bitStream, 8);
}
}
if (frameInfo.fscod < 3) {
bs.bsSkip(bitStream, 1);
}
}
if (frameInfo.strmtyp === 0 && frameInfo.numblkscod !== 3) {
bs.bsSkip(bitStream, 1);
}
if (frameInfo.strmtyp === 2) {
let blkid;
if (frameInfo.numblkscod === 3) {
blkid = 1;
}
else {
blkid = bs.bsReadAndUpdate(data, bitStream, 1);
}
if (blkid) {
bs.bsReadAndUpdate(data, bitStream, 6);
}
}
if (bs.bsReadAndUpdate(data, bitStream, 1)) {
const addbsil = bs.bsReadAndUpdate(data, bitStream, 6);
if (frameInfo.strmtyp === 0 && frameInfo.substreamid === 0 && addbsil === 1) {
const flag_ec3_extension_type_reserved = bs.bsReadAndUpdate(data, bitStream, 7);
const flag_ec3_extension_type_a = bs.bsReadAndUpdate(data, bitStream, 1);
const complexity_index_type_a = bs.bsReadAndUpdate(data, bitStream, 8);
// Make sure the values are in range and if yes, flag ATMOS
if (flag_ec3_extension_type_reserved === 0 && flag_ec3_extension_type_a === 1 && complexity_index_type_a >= 1 && complexity_index_type_a <= 16) {
sampleInfo.complexity_index_type_a = complexity_index_type_a;
}
}
}
// find channel map
if (frameInfo.chanmape) {
sampleInfo.chan_loc |= frameInfo.chanmap;
}
else {
// look up channel map using acmod
const acmodToChannelMap = [
40960,
16384,
40960,
57344,
41472,
57856,
47104,
63488,
];
sampleInfo.chan_loc |= acmodToChannelMap[frameInfo.acmod];
}
if (frameInfo.strmtyp === 0) {
sampleInfo.fscod = frameInfo.fscod;
sampleInfo.bsid = frameInfo.bsid;
sampleInfo.bsmod = frameInfo.bsmod;
sampleInfo.acmod = frameInfo.acmod;
sampleInfo.lfeon = frameInfo.lfeon;
}
sampleInfo.chan_loc |= frameInfo.lfeon ? 1 : 0;
// advance to the next syncframe
const frameLength = (frameInfo.frmsiz + 1) * 2;
offset += frameLength;
totalFrameLength += frameLength + (id3Length || 0);
}
let channelCount = 0;
// get channel count
for (let i = 0; i < 16; i++) {
if (sampleInfo.chan_loc & (1 << i)) {
channelCount++;
}
}
if (sampleInfo.lfeon) {
channelCount++;
}
// generate DD+ magic cookie
let cookieSize = 10 + sampleInfo.num_ind_sub * 3;
const samplingRateMap = [48000, 44100, 32000];
const samplerate = samplingRateMap[sampleInfo.fscod];
sampleInfo.data_rate = (samplerate / 1536) * totalFrameLength * 8;
cookieSize = 10 + sampleInfo.num_ind_sub * 3;
for (let i = 0; i < sampleInfo.num_ind_sub; i++) {
if (sampleInfo.num_dep_sub[i] > 0) {
cookieSize++;
}
}
// for ATMOS
if (sampleInfo.complexity_index_type_a > 0) {
cookieSize += 2;
}
// write the cookie
const extraDataBytes = new Uint8Array(cookieSize);
const bitStream = { byteOffset: 0, usedBits: 0 };
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 32, cookieSize);
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 32, 1684366131); // 'dec3'
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 13, sampleInfo.data_rate); // data_rate
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 3, sampleInfo.num_ind_sub); // num_ind_sub
for (let i = 0; i < sampleInfo.num_ind_sub; i++) {
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 2, sampleInfo.fscod); // fscod
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 5, sampleInfo.bsid); // bsid
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 1, 0); // reserved
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 1, i === 0 ? 0 : 1); // asvc
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 3, sampleInfo.bsmod); // bsmod
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 3, sampleInfo.acmod); // acmod
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 1, sampleInfo.lfeon); // lfeon
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 3, 0); // reserved
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 4, sampleInfo.num_dep_sub[i]); // num_dep_sub
if (sampleInfo.num_dep_sub[i] > 0) {
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 9, sampleInfo.chan_loc); // chan_loc
}
else {
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 1, 0); // reserved
}
}
if (sampleInfo.complexity_index_type_a > 0) {
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 7, 0); // flag_ec3_extension_type_reserved; reserved as 0
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 1, 1); // flag_ec3_extension_type_a
bs.bsWriteAndUpdate(extraDataBytes, bitStream, 8, sampleInfo.complexity_index_type_a); // complexity_index_type_a
}
logger.debug(loggerName$g, `EC3 sampleInfo:${JSON.stringify(sampleInfo)}`);
logger.info(loggerName$g, `parsed codec:ec-3, isAtmos: ${sampleInfo.complexity_index_type_a > 0}, rate:${samplerate}, nb channel:${channelCount}, first totalFrameLength:${totalFrameLength}`);
const audioConfig = { samplerate: samplerate, channelCount: channelCount, segmentCodec: 'ec3', codec: 'ec-3', extraDataBytes: extraDataBytes };
return audioConfig;
},
};
var DDPlus$1 = DDPlus;
const loggerName$f = { name: 'EC3Demuxer' };
class EC3Demuxer extends EsDemuxer {
resetInitSegment(initSegment, duration) {
this.audioConfig = undefined;
this.audioTrack = undefined;
this.duration = duration;
}
static probe(data, logger) {
// check if data contains ID3 timestamp and EC3 sync bytes
const id3 = new ID3$1(data, logger), offset = id3.length;
// look for the ec-3 sync bytes
if (id3.hasTimeStamp && data[offset] === 11 && data[offset + 1] === 119) {
// check the bsid to confirm ec-3
const bu = new BitstreamUtils();
const bsid = bu.bsReadAndUpdate(data, { byteOffset: offset + 5, usedBits: 0 }, 5);
if (bsid === 16) {
return true;
}
}
return false;
}
// feed incoming data to the front of the parsing pipeline
append(data, timeOffset, contiguous, accurateTimeOffset, keyTagInfo) {
const id3 = new ID3$1(data, this.logger);
const pts = 90 * id3.timeStamp;
const length = data.length;
let frameIndex = 0;
let offset = id3.length;
if (!this.audioConfig) {
this.audioConfig = DDPlus$1.getAudioConfig(this.observer, data, offset, this.logger);
}
if (!this.audioConfig) {
throw 'failed to parse ec-3 config';
}
if (!this.audioTrack) {
const info = { id: 258, inputTimescale: 90000, timescale: NaN, duration: this.duration, encrypted: false, keyTagInfo };
const parsingData = { len: 0, sequenceNumber: 0, esSamples: [] };
this.audioTrack = { info, parsingData, type: 'audio', config: this.audioConfig };
}
const frameDuration = Dolby.getFrameDuration(this.audioConfig, this.audioTrack.info.inputTimescale); // (1536 / this.audioConfig.samplerate) * this.audioTrack.inputTimescale;
if (id3.audioType === 'zec3') {
this.audioTrack.info.encrypted = true;
this.logger.info(loggerName$f, 'found encrypted ec3');
}
while (offset < length) {
const frameLength = DDPlus$1.getFrameLength(this.observer, data, offset, this.logger);
const stamp = pts + frameIndex * frameDuration;
const ec3Sample = { unit: data.subarray(offset, offset + frameLength), pts: stamp, dts: stamp, keyTagInfo: keyTagInfo };
this.audioTrack.parsingData.esSamples.push(ec3Sample);
this.audioTrack.parsingData.len += frameLength;
offset += frameLength;
frameIndex++;
}
this.esRemuxer.remuxEsTracks(this.audioTrack, undefined, { id3Samples: [{ pts: pts, dts: pts, data: id3.payload, frames: id3.frames }], inputTimescale: this.audioTrack.info.inputTimescale }, undefined, timeOffset, contiguous, accurateTimeOffset, keyTagInfo);
}
}
const MpegAudio = {
BitratesMap: [
32,
64,
96,
128,
160,
192,
224,
256,
288,
320,
352,
384,
416,
448,
32,
48,
56,
64,
80,
96,
112,
128,
160,
192,
224,
256,
320,
384,
32,
40,
48,
56,
64,
80,
96,
112,
128,
160,
192,
224,
256,
320,
32,
48,
56,
64,
80,
96,
112,
128,
144,
160,
176,
192,
224,
256,
8,
16,
24,
32,
40,
48,
56,
64,
80,
96,
112,
128,
144,
160,
],
SamplingRateMap: [44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000],
SamplesCoefficients: [
// MPEG 2.5
[
0,
72,
144,
12,
],
// Reserved
[
0,
0,
0,
0,
],
// MPEG 2
[
0,
72,
144,
12,
],
// MPEG 1
[
0,
144,
144,
12,
],
],
BytesInSlot: [
0,
1,
1,
4,
],
onFrame: function (parsingData, data, bitRate, samplerate, channelCount, frameIndex, pts) {
const frameDuration = 103680000 / samplerate;
const stamp = pts + frameIndex * frameDuration;
parsingData.esSamples.push({ unit: data, pts: stamp, dts: stamp });
parsingData.len += data.length;
},
onNoise: function (data, logger) {
logger.warn('mpeg audio has noise: ' + data.length + ' bytes');
},
parseFrames: function (parsingData, data, start, end, frameIndex, pts, logger) {
const BitratesMap = [
32,
64,
96,
128,
160,
192,
224,
256,
288,
320,
352,
384,
416,
448,
32,
48,
56,
64,
80,
96,
112,
128,
160,
192,
224,
256,
320,
384,
32,
40,
48,
56,
64,
80,
96,
112,
128,
160,
192,
224,
256,
320,
32,
48,
56,
64,
80,
96,
112,
128,
144,
160,
176,
192,
224,
256,
8,
16,
24,
32,
40,
48,
56,
64,
80,
96,
112,
128,
144,
160,
];
const SamplingRateMap = [44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000];
if (start + 2 > end) {
return -1; // we need at least 2 bytes to detect sync pattern
}
if (data[start] === 255 || (data[start + 1] & 224) === 224) {
// Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference
if (start + 24 > end) {
return -1;
}
const headerB = (data[start + 1] >> 3) & 3;
const headerC = (data[start + 1] >> 1) & 3;
const headerE = (data[start + 2] >> 4) & 15;
const headerF = (data[start + 2] >> 2) & 3;
const headerG = !!(data[start + 2] & 2);
if (headerB !== 1 && headerE !== 0 && headerE !== 15 && headerF !== 3) {
const columnInBitrates = headerB === 3 ? 3 - headerC : headerC === 3 ? 3 : 4;
const bitRate = BitratesMap[columnInBitrates * 14 + headerE - 1] * 1000;
const columnInSampleRates = headerB === 3 ? 0 : headerB === 2 ? 1 : 2;
const sampleRate = SamplingRateMap[columnInSampleRates * 3 + headerF];
const padding = headerG ? 1 : 0;
const channelCount = data[start + 3] >> 6 === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono)
const frameLength = headerC === 3 ? (((headerB === 3 ? 12 : 6) * bitRate) / sampleRate + padding) << 2 : (((headerB === 3 ? 144 : 72) * bitRate) / sampleRate + padding) | 0;
if (start + frameLength > end) {
return -1;
}
MpegAudio.onFrame(parsingData, data.subarray(start, start + frameLength), bitRate, sampleRate, channelCount, frameIndex, pts);
return frameLength;
}
}
// noise or ID3, trying to skip
let offset = start + 2;
while (offset < end) {
if (data[offset - 1] === 255 && (data[offset] & 224) === 224) {
// sync pattern is found
MpegAudio.onNoise(data.subarray(start, offset - 1), logger);
return offset - start - 1;
}
offset++;
}
return -1;
},
parse: function (parsingData, data, offset, pts, logger) {
const length = data.length;
let frameIndex = 0;
let parsed;
while (offset < length && (parsed = MpegAudio.parseFrames(parsingData, data, offset, length, frameIndex++, pts, logger)) > 0) {
offset += parsed;
}
},
getAudioConfig: function (data, offset) {
const headerB = (data[offset + 1] >> 3) & 3;
const headerC = (data[offset + 1] >> 1) & 3;
const headerE = (data[offset + 2] >> 4) & 15;
const headerF = (data[offset + 2] >> 2) & 3;
const headerG = (data[offset + 2] >> 1) & 1;
if (headerB !== 1 && headerE !== 0 && headerE !== 15 && headerF !== 3) {
const columnInBitrates = headerB === 3 ? 3 - headerC : headerC === 3 ? 3 : 4;
const bitRate = MpegAudio.BitratesMap[columnInBitrates * 14 + headerE - 1] * 1000;
const columnInSampleRates = headerB === 3 ? 0 : headerB === 2 ? 1 : 2;
const samplerate = MpegAudio.SamplingRateMap[columnInSampleRates * 3 + headerF];
const channelCount = data[offset + 3] >> 6 === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono)
const sampleCoefficient = MpegAudio.SamplesCoefficients[headerB][headerC];
const bytesInSlot = MpegAudio.BytesInSlot[headerC];
const frameLength = parseInt(((sampleCoefficient * bitRate) / samplerate + headerG), 10) * bytesInSlot;
const result = { segmentCodec: 'mp3', codec: 'mp3', samplerate, channelCount, frameLength };
return result;
}
return undefined;
},
isHeaderPattern: function (data, offset) {
return data[offset] === 255 && (data[offset + 1] & 224) === 224 && (data[offset + 1] & 6) !== 0;
},
probe: function (data, offset) {
// same as isHeader but we also check that MPEG frame follows last MPEG frame
// or end of data is reached
if (offset + 1 < data.length && MpegAudio.isHeaderPattern(data, offset)) {
// MPEG header Length
const headerLength = 4;
// MPEG frame Length
const header = MpegAudio.getAudioConfig(data, offset);
let frameLength = headerLength;
if (header && header.frameLength) {
frameLength = header.frameLength;
}
const newOffset = offset + frameLength;
if (newOffset === data.length || (newOffset + 1 < data.length && MpegAudio.isHeaderPattern(data, newOffset))) {
return true;
}
}
return false;
},
};
var MpegAudio$1 = MpegAudio;
const loggerName$e = { name: 'MP3Demuxer' };
class MP3Demuxer extends EsDemuxer {
resetInitSegment(initSegment, duration) {
this.audioConfig = undefined;
this.audioTrack = undefined;
this.duration = duration;
}
static probe(data, logger) {
// check if data contains ID3 timestamp and MPEG sync word
const id3 = new ID3$1(data, logger);
let offset, length;
if (id3.hasTimeStamp) {
// Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
// Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
// More info http://www.mp3-tech.org/programmer/frame_header.html
for (offset = id3.length, length = Math.min(data.length - 1, offset + 100); offset < length; offset++) {
if (MpegAudio$1.probe(data, offset)) {
logger.warn(loggerName$e, 'MPEG Audio sync word found !');
return true;
}
}
}
return false;
}
// feed incoming data to the front of the parsing pipeline
append(data, timeOffset, contiguous, accurateTimeOffset, keyTagInfo) {
const id3 = new ID3$1(data, this.logger);
const pts = 90 * id3.timeStamp;
if (!this.audioConfig) {
this.audioConfig = MpegAudio$1.getAudioConfig(data, id3.length);
}
if (!this.audioConfig) {
throw 'unable to parse mp3 header';
}
if (!this.audioTrack) {
const info = { id: 258, inputTimescale: 90000, timescale: NaN, duration: this.duration, encrypted: false, keyTagInfo };
const parsingData = { len: 0, sequenceNumber: 0, esSamples: [] };
this.audioTrack = { info, parsingData, type: 'audio', config: this.audioConfig };
}
MpegAudio$1.parse(this.audioTrack.parsingData, data, id3.length, pts, this.logger);
this.esRemuxer.remuxEsTracks(this.audioTrack, undefined, { id3Samples: [{ pts: pts, dts: pts, data: id3.payload, frames: id3.frames }], inputTimescale: 90000 }, undefined, timeOffset, contiguous, accurateTimeOffset);
}
}
/**
* AAC Helper
*
*
*
*
*/
function getSilentFrame(codec, channelCount) {
switch (codec) {
case 'mp4a.40.2':
if (channelCount === 1) {
return new Uint8Array([0, 200, 0, 128, 35, 128]);
}
else if (channelCount === 2) {
return new Uint8Array([33, 0, 73, 144, 2, 25, 0, 35, 128]);
}
else if (channelCount === 3) {
return new Uint8Array([0, 200, 0, 128, 32, 132, 1, 38, 64, 8, 100, 0, 142]);
}
else if (channelCount === 4) {
return new Uint8Array([0, 200, 0, 128, 32, 132, 1, 38, 64, 8, 100, 0, 128, 44, 128, 8, 2, 56]);
}
else if (channelCount === 5) {
return new Uint8Array([0, 200, 0, 128, 32, 132, 1, 38, 64, 8, 100, 0, 130, 48, 4, 153, 0, 33, 144, 2, 56]);
}
else if (channelCount === 6) {
return new Uint8Array([0, 200, 0, 128, 32, 132, 1, 38, 64, 8, 100, 0, 130, 48, 4, 153, 0, 33, 144, 2, 0, 178, 0, 32, 8, 224]);
}
break;
// handle HE-AAC below (mp4a.40.5 / mp4a.40.29)
default:
if (channelCount === 1) {
// ffmpeg -y -f lavfi -i "aevalsrc=0:d=0.05" -c:a libfdk_aac -profile:a aac_he -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
return new Uint8Array([
1,
64,
34,
128,
163,
78,
230,
128,
186,
8,
0,
0,
0,
28,
6,
241,
193,
10,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
94,
]);
}
else if (channelCount === 2) {
// ffmpeg -y -f lavfi -i "aevalsrc=0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
return new Uint8Array([
1,
64,
34,
128,
163,
94,
230,
128,
186,
8,
0,
0,
0,
0,
149,
0,
6,
241,
161,
10,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
94,
]);
}
else if (channelCount === 3) {
// ffmpeg -y -f lavfi -i "aevalsrc=0|0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
return new Uint8Array([
1,
64,
34,
128,
163,
94,
230,
128,
186,
8,
0,
0,
0,
0,
149,
0,
6,
241,
161,
10,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
90,
94,
]);
}
break;
}
return null;
}
function isFiniteNumber(value) {
return typeof value === 'number' && isFinite(value);
}
/**
* For getting float string for a given value with type checking
* @param val Number
* @param precision Number of digits after decimal
*/
function toFixed(val, precision) {
if (isFiniteNumber(val)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return val.toFixed(precision);
}
return `${val}`;
}
/**
* Stringify except print numbers with fixed precision
* @param obj the value to stringify
* @param precision Number of digits after decimal. Default 3
*/
function stringifyWithPrecision(obj, precision = 3) {
return JSON.stringify(obj, (_key, value) => {
return !isNaN(value) && (value === null || value === void 0 ? void 0 : value.toFixed) ? Number(value === null || value === void 0 ? void 0 : value.toFixed(precision)) : value;
});
}
/**
* Replace all occurrences of an instance in a string
*
* @param {string|RegExp} search - What to change
* @param {string} replacement - Replace search for this
* @param {string} target - Target string to have elements replaced
* @returns {string}
*/
const replaceAll = (search, replacement, target = '') => target.split(search).join(replacement);
let shouldRedactUrl = true;
function setupRedactUrl(buildType) {
shouldRedactUrl = buildType === 'production';
}
function redactUrl(url) {
return shouldRedactUrl ? '' : url;
}
// Naive deep copy of any serializable object
// shallow copy for function, symbol
function deepCpy(obj) {
if (!obj) {
return obj;
}
switch (typeof obj) {
case 'object':
if (Array.isArray(obj)) {
return obj.map(deepCpy);
}
const result = {};
for (const [key, value] of Object.entries(obj)) {
result[key] = deepCpy(value);
}
return result;
default:
return obj;
}
}
function urlRedactedLevelInfo(indata) {
const outdata = [...indata];
for (let i = 0; i < outdata.length; i++) {
outdata[i] = Object.assign({}, outdata[i]);
outdata[i].url = redactUrl(outdata[i].url);
if (outdata[i].attrs) {
outdata[i].attrs = Object.assign({}, outdata[i].attrs);
outdata[i].attrs.URI = redactUrl(outdata[i].attrs.URI);
}
}
return outdata;
}
function urlRedactedAltMediaOption(indata) {
const outdata = [...indata];
for (let i = 0; i < outdata.length; i++) {
outdata[i] = Object.assign({}, outdata[i]);
outdata[i].url = redactUrl(outdata[i].url);
}
return outdata;
}
/**
* Generate MP4 Box
*
*
*
*
*/
const UINT32_MAX$1 = Math.pow(2, 32) - 1;
class MP4 {
static init() {
MP4.types = {
avc1: [],
avcC: [],
btrt: [],
dinf: [],
dref: [],
esds: [],
free: [],
ftyp: [],
hdlr: [],
mdat: [],
mdhd: [],
mdia: [],
mfhd: [],
minf: [],
moof: [],
moov: [],
mp4a: [],
'.mp3': [],
dac3: [],
'ac-3': [],
dec3: [],
'ec-3': [],
mvex: [],
mvhd: [],
pasp: [],
sdtp: [],
stbl: [],
stco: [],
stsc: [],
stsd: [],
stsz: [],
stts: [],
tfdt: [],
tfhd: [],
traf: [],
trak: [],
trun: [],
trex: [],
tkhd: [],
vmhd: [],
smhd: [],
uuid: [],
encv: [],
enca: [],
// map encryption boxes
frma: [],
schm: [],
schi: [],
senc: [],
saio: [],
saiz: [],
sinf: [],
tenc: [],
// moof encryption boxes
sbgp: [],
seig: [],
sgpd: [],
pssh: [],
};
let i;
for (i in MP4.types) {
// eslint-disable-next-line no-prototype-builtins
if (MP4.types.hasOwnProperty(i)) {
MP4.types[i] = [i.charCodeAt(0), i.charCodeAt(1), i.charCodeAt(2), i.charCodeAt(3)];
}
}
const videoHdlr = 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,
]);
const audioHdlr = 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,
]);
MP4.HDLR_TYPES = {
video: videoHdlr,
audio: audioHdlr,
};
const dref = new Uint8Array([
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
12,
117,
114,
108,
32,
0,
0,
0,
1,
]);
const stco = new Uint8Array([
0,
0,
0,
0,
0,
0,
0,
0,
]);
MP4.STTS = MP4.STSC = MP4.STCO = stco;
MP4.STSZ = new Uint8Array([
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
]);
MP4.VMHD = new Uint8Array([
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
]);
MP4.SMHD = new Uint8Array([
0,
0,
0,
0,
0,
0,
0,
0,
]);
MP4.STSD = new Uint8Array([
0,
0,
0,
0,
0,
0,
0,
1,
]); // entry_count
const majorBrand = new Uint8Array([105, 115, 111, 109]); // isom
const avc1Brand = new Uint8Array([97, 118, 99, 49]); // avc1
const minorVersion = new Uint8Array([0, 0, 0, 1]);
MP4.FTYP = MP4.box(MP4.types.ftyp, majorBrand, minorVersion, majorBrand, avc1Brand);
MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref));
}
static set16(num, data, index) {
data[index] = (num >> 8) & 255;
data[index + 1] = num & 255;
return index + 2;
}
static set32(num, data, index) {
data[index] = (num >> 24) & 255;
data[index + 1] = (num >> 16) & 255;
data[index + 2] = (num >> 8) & 255;
data[index + 3] = num & 255;
return index + 4;
}
static box(type, ...params) {
// eslint-disable-next-line prefer-rest-params
const payload = Array.prototype.slice.call(arguments, 1);
let size = 8, i = payload.length;
const len = i;
// calculate the total size we need to allocate
while (i--) {
size += payload[i].byteLength;
}
const result = new Uint8Array(size);
result[0] = (size >> 24) & 255;
result[1] = (size >> 16) & 255;
result[2] = (size >> 8) & 255;
result[3] = size & 255;
result.set(type, 4);
// copy the payload into the result
for (i = 0, size = 8; i < len; i++) {
// copy payload[i] array @ offset size
result.set(payload[i], size);
size += payload[i].byteLength;
}
return result;
}
static hdlr(type) {
return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]);
}
static mdat(data) {
return MP4.box(MP4.types.mdat, data);
}
static mdhd(timescale, duration) {
duration *= timescale;
const upperWordDuration = Math.floor(duration / (UINT32_MAX$1 + 1));
const lowerWordDuration = Math.floor(duration % (UINT32_MAX$1 + 1));
return MP4.box(MP4.types.mdhd, new Uint8Array([
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
0,
0,
0,
0,
0,
0,
0,
3,
(timescale >> 24) & 255,
(timescale >> 16) & 255,
(timescale >> 8) & 255,
timescale & 255,
upperWordDuration >> 24,
(upperWordDuration >> 16) & 255,
(upperWordDuration >> 8) & 255,
upperWordDuration & 255,
lowerWordDuration >> 24,
(lowerWordDuration >> 16) & 255,
(lowerWordDuration >> 8) & 255,
lowerWordDuration & 255,
85,
196,
0,
0,
]));
}
static mdia(track) {
const mdhd = MP4.mdhd(track.info.timescale, track.info.duration);
const hdlr = MP4.hdlr(track.type);
const minf = MP4.minf(track);
return MP4.box(MP4.types.mdia, mdhd, hdlr, minf);
}
static mfhd(sequenceNumber) {
return MP4.box(MP4.types.mfhd, new Uint8Array([
0,
0,
0,
0,
sequenceNumber >> 24,
(sequenceNumber >> 16) & 255,
(sequenceNumber >> 8) & 255,
sequenceNumber & 255, // sequence_number
]));
}
static minf(track) {
if (track.type === 'audio') {
return MP4.box(MP4.types.minf, MP4.box(MP4.types.smhd, MP4.SMHD), MP4.DINF, MP4.stbl(track));
}
else {
return MP4.box(MP4.types.minf, MP4.box(MP4.types.vmhd, MP4.VMHD), MP4.DINF, MP4.stbl(track));
}
}
static moof(baseMediaDecodeTime, track) {
if (!MP4.types) {
MP4.init();
}
const traf = MP4.traf(track, baseMediaDecodeTime);
const moof = MP4.box(MP4.types.moof, MP4.mfhd(track.sequenceNumber), traf);
return moof;
}
/**
* @param tracks... (optional) {array} the tracks associated with this movie
*/
static moov(tracks) {
let i = tracks.length;
const boxes = [];
while (i--) {
boxes[i] = MP4.trak(tracks[i]);
}
return MP4.box.apply(null, [MP4.types.moov, MP4.mvhd(tracks[0].info.timescale, tracks[0].info.duration)].concat(boxes).concat(MP4.mvex(tracks)));
}
static mvex(tracks) {
let i = tracks.length;
const boxes = [];
while (i--) {
boxes[i] = MP4.trex(tracks[i]);
}
return MP4.box(MP4.types.mvex, ...boxes);
// return MP4.box.apply(null, [MP4.types.mvex, .concat(boxes));
}
static mvhd(timescale, duration) {
duration *= timescale;
const upperWordDuration = Math.floor(duration / (UINT32_MAX$1 + 1));
const lowerWordDuration = Math.floor(duration % (UINT32_MAX$1 + 1));
const bytes = new Uint8Array([
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
0,
0,
0,
0,
0,
0,
0,
3,
(timescale >> 24) & 255,
(timescale >> 16) & 255,
(timescale >> 8) & 255,
timescale & 255,
upperWordDuration >> 24,
(upperWordDuration >> 16) & 255,
(upperWordDuration >> 8) & 255,
upperWordDuration & 255,
lowerWordDuration >> 24,
(lowerWordDuration >> 16) & 255,
(lowerWordDuration >> 8) & 255,
lowerWordDuration & 255,
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 MP4.box(MP4.types.mvhd, bytes);
}
static sdtp(track) {
const samples = track.samples || [], bytes = new Uint8Array(4 + samples.length);
let 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 MP4.box(MP4.types.sdtp, bytes);
}
static stbl(track) {
const stsd = MP4.stsd(track);
const stts = MP4.box(MP4.types.stts, MP4.STTS);
const stsc = MP4.box(MP4.types.stsc, MP4.STSC);
const stsz = MP4.box(MP4.types.stsz, MP4.STSZ);
const stco = MP4.box(MP4.types.stco, MP4.STCO);
return MP4.box(MP4.types.stbl, stsd, stts, stsc, stsz, stco);
}
static avc1(track) {
let sps = [], pps = [], i, data, len;
// assemble the SPSs
const codingName = track.info.encrypted ? MP4.types.encv : MP4.types.avc1;
for (i = 0; i < track.config.sps.length; i++) {
data = track.config.sps[i];
len = data.byteLength;
sps.push((len >>> 8) & 255);
sps.push(len & 255);
sps = sps.concat(Array.prototype.slice.call(data)); // SPS
}
// assemble the PPSs
for (i = 0; i < track.config.pps.length; i++) {
data = track.config.pps[i];
len = data.byteLength;
pps.push((len >>> 8) & 255);
pps.push(len & 255);
pps = pps.concat(Array.prototype.slice.call(data));
}
const avcc = MP4.box(MP4.types.avcC, new Uint8Array([
1,
sps[3],
sps[4],
sps[5],
255,
224 | track.config.sps.length, // 3bit reserved (111) + numOfSequenceParameterSets
]
.concat(sps)
.concat([
track.config.pps.length, // numOfPictureParameterSets
])
.concat(pps))), // "PPS"
width = track.config.width, height = track.config.height, hSpacing = track.config.pixelRatio[0], vSpacing = track.config.pixelRatio[1];
// console.log('avcc:' + Hex.hexDump(avcc));
const sinf = track.info.encrypted && track.info.keyTagInfo ? MP4.sinf(track.info.keyTagInfo, track.type, MP4.types.avc1) : new Uint8Array();
// console.log('video sinf:' + Hex.hexDump(sinf));
return MP4.box(codingName, 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,
(width >> 8) & 255,
width & 255,
(height >> 8) & 255,
height & 255,
0,
72,
0,
0,
0,
72,
0,
0,
0,
0,
0,
0,
0,
1,
18,
100,
97,
105,
108,
121,
109,
111,
116,
105,
111,
110,
47,
104,
108,
115,
46,
106,
115,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
24,
17,
17,
]), // pre_defined = -1
avcc, sinf, MP4.box(MP4.types.btrt, new Uint8Array([
0,
28,
156,
128,
0,
45,
198,
192,
0,
45,
198,
192,
])), // avgBitrate
MP4.box(MP4.types.pasp, new Uint8Array([
hSpacing >> 24,
(hSpacing >> 16) & 255,
(hSpacing >> 8) & 255,
hSpacing & 255,
vSpacing >> 24,
(vSpacing >> 16) & 255,
(vSpacing >> 8) & 255,
vSpacing & 255,
])));
}
static esds(config) {
const configlen = config.esdsConfig.length;
return new Uint8Array([
0,
0,
0,
0,
3,
23 + configlen,
0,
1,
0,
4,
15 + configlen,
64,
21,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5,
]
.concat([configlen])
.concat(config.esdsConfig)
.concat([6, 1, 2])); // GASpecificConfig)); // length + audio config descriptor
}
static audioStsd(config) {
const samplerate = config.samplerate;
return new Uint8Array([
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
config.channelCount,
0,
16,
0,
0,
0,
0,
(samplerate >> 8) & 255,
samplerate & 255,
0,
0,
]);
}
static dac3(config) {
const extraData = config.extraData;
return new Uint8Array([(extraData >> 16) & 255, (extraData >> 8) & 255, extraData & 255]);
}
static dec3(config) {
return config.extraDataBytes;
}
static mp4a(info, config) {
let codingName = MP4.types.mp4a;
let sinf = null;
if (info.encrypted && info.keyTagInfo) {
codingName = MP4.types.enca;
sinf = MP4.sinf(info.keyTagInfo, 'audio', MP4.types.mp4a);
}
else {
sinf = new Uint8Array();
}
const stsd = MP4.audioStsd(config);
const esds = MP4.box(MP4.types.esds, MP4.esds(config));
return MP4.box(codingName, stsd, esds, sinf);
}
static mp3(config) {
return MP4.box(MP4.types['.mp3'], MP4.audioStsd(config));
}
static ac3(info, config) {
let codingName = MP4.types['ac-3'];
let sinf = null;
if (info.encrypted && info.keyTagInfo) {
codingName = MP4.types.enca;
sinf = MP4.sinf(info.keyTagInfo, 'audio', MP4.types['ac-3']);
}
else {
sinf = new Uint8Array();
}
return MP4.box(codingName, MP4.audioStsd(config), MP4.box(MP4.types.dac3, MP4.dac3(config)), sinf);
}
static ec3(info, config) {
let codingName = MP4.types['ec-3'];
let sinf = null;
if (info.encrypted && info.keyTagInfo) {
codingName = MP4.types.enca;
sinf = MP4.sinf(info.keyTagInfo, 'audio', MP4.types['ec-3']);
}
else {
sinf = new Uint8Array();
}
return MP4.box(codingName, MP4.audioStsd(config), MP4.box(MP4.types.dec3, MP4.dec3(config)), sinf);
}
static stsd(track) {
if (track.type === 'audio') {
if (track.config.segmentCodec === 'mp3' && track.config.codec === 'mp3') {
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp3(track.config));
}
if (track.config.segmentCodec === 'ac3') {
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track.info, track.config));
}
else if (track.config.segmentCodec === 'ec3') {
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ec3(track.info, track.config));
}
else if (track.config.segmentCodec === 'aac') {
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track.info, track.config));
}
else {
throw `unknown segmentCodec ${track.config.segmentCodec}`;
}
}
else {
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
}
}
static tkhd(track) {
const id = track.info.id;
const duration = track.info.duration * track.info.timescale;
const upperWordDuration = Math.floor(duration / (UINT32_MAX$1 + 1));
const lowerWordDuration = Math.floor(duration % (UINT32_MAX$1 + 1));
let width = 0;
let height = 0;
if (track.type === 'video') {
width = track.config.width;
height = track.config.height;
}
return MP4.box(MP4.types.tkhd, new Uint8Array([
1,
0,
0,
7,
0,
0,
0,
0,
0,
0,
0,
2,
0,
0,
0,
0,
0,
0,
0,
3,
(id >> 24) & 255,
(id >> 16) & 255,
(id >> 8) & 255,
id & 255,
0,
0,
0,
0,
upperWordDuration >> 24,
(upperWordDuration >> 16) & 255,
(upperWordDuration >> 8) & 255,
upperWordDuration & 255,
lowerWordDuration >> 24,
(lowerWordDuration >> 16) & 255,
(lowerWordDuration >> 8) & 255,
lowerWordDuration & 255,
0,
0,
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,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
64,
0,
0,
0,
(width >> 8) & 255,
width & 255,
0,
0,
(height >> 8) & 255,
height & 255,
0,
0,
]));
}
static traf(track, baseMediaDecodeTime) {
const sencOffset = 76; // mdat header
const sampleEncryptionBoxTuple = MP4.senc(track);
const sampleDependencyTable = MP4.sdtp(track), sampleEncryptionBox = sampleEncryptionBoxTuple.boxData, sampleEncryptionOffsetBox = sampleEncryptionBox.length ? MP4.saio(sencOffset) : new Uint8Array(), sampleEncryptionSizeBox = sampleEncryptionBox.length ? MP4.saiz(sampleEncryptionBoxTuple.defaultSampleInfoSize, sampleEncryptionBoxTuple.sampleInfoSizes) : new Uint8Array(), sampleToGroupBox = MP4.sbgp(track), sampleGroupDescriptionBox = MP4.sgpd(track), id = track.id, upperWordBaseMediaDecodeTime = Math.floor(baseMediaDecodeTime / (UINT32_MAX$1 + 1)), lowerWordBaseMediaDecodeTime = Math.floor(baseMediaDecodeTime % (UINT32_MAX$1 + 1));
// console.log('sampleToGroupBox:' + Hex.hexDump(sampleToGroupBox));
// console.log('sampleGroupDescriptionBox:' + Hex.hexDump(sampleGroupDescriptionBox));
return MP4.box(MP4.types.traf, MP4.box(MP4.types.tfhd, new Uint8Array([
0,
2,
0,
0,
id >> 24,
(id >> 16) & 255,
(id >> 8) & 255,
id & 255, // track_ID
])), MP4.box(MP4.types.tfdt, new Uint8Array([
1,
0,
0,
0,
upperWordBaseMediaDecodeTime >> 24,
(upperWordBaseMediaDecodeTime >> 16) & 255,
(upperWordBaseMediaDecodeTime >> 8) & 255,
upperWordBaseMediaDecodeTime & 255,
lowerWordBaseMediaDecodeTime >> 24,
(lowerWordBaseMediaDecodeTime >> 16) & 255,
(lowerWordBaseMediaDecodeTime >> 8) & 255,
lowerWordBaseMediaDecodeTime & 255,
])), sampleEncryptionBox, sampleEncryptionOffsetBox, sampleEncryptionSizeBox, sampleToGroupBox, sampleGroupDescriptionBox, MP4.trun(track, sampleDependencyTable.length +
sampleEncryptionBox.length +
sampleToGroupBox.length +
sampleGroupDescriptionBox.length +
sampleEncryptionOffsetBox.length +
sampleEncryptionSizeBox.length + 16 + // tfhd
20 + // tfdt
8 + // traf header
16 + // mfhd
8 + // moof header
8), // mdat header
sampleDependencyTable);
}
/**
* Generate a track box.
* @param track {object} a track definition
* @return {Uint8Array} the track box
*/
static trak(track) {
if ('trakData' in track) {
// cached trak
return track.trakData;
}
track.info.duration = track.info.duration || 4294967295;
const trak = MP4.types.trak;
const thkd = MP4.tkhd(track);
const mdia = MP4.mdia(track);
return MP4.box(trak, thkd, mdia);
}
static trex(track) {
const id = track.info.id;
return MP4.box(MP4.types.trex, new Uint8Array([
0,
0,
0,
0,
id >> 24,
(id >> 16) & 255,
(id >> 8) & 255,
id & 255,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
1,
]));
}
static trun(track, offset) {
const samples = track.samples || [], len = samples.length, arraylen = 12 + 16 * len, array = new Uint8Array(arraylen);
let i, sample, duration, size, flags, cts;
offset += 8 + arraylen;
array.set([
0,
0,
15,
1,
(len >>> 24) & 255,
(len >>> 16) & 255,
(len >>> 8) & 255,
len & 255,
(offset >>> 24) & 255,
(offset >>> 16) & 255,
(offset >>> 8) & 255,
offset & 255, // data_offset
], 0);
for (i = 0; i < len; i++) {
sample = samples[i];
duration = sample.duration;
size = sample.size;
flags = sample.flags;
cts = sample.cts;
array.set([
(duration >>> 24) & 255,
(duration >>> 16) & 255,
(duration >>> 8) & 255,
duration & 255,
(size >>> 24) & 255,
(size >>> 16) & 255,
(size >>> 8) & 255,
size & 255,
(flags.isLeading << 2) | flags.dependsOn,
(flags.isDependedOn << 6) | (flags.hasRedundancy << 4) | (flags.paddingValue << 1) | flags.isNonSync,
flags.degradPrio & (240 << 8),
flags.degradPrio & 15,
(cts >>> 24) & 255,
(cts >>> 16) & 255,
(cts >>> 8) & 255,
cts & 255, // sample_composition_time_offset
], 12 + 16 * i);
}
return MP4.box(MP4.types.trun, array);
}
static initSegment(tracks) {
if (!MP4.types) {
MP4.init();
}
const movie = MP4.moov(tracks);
const result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength);
result.set(MP4.FTYP);
result.set(movie, MP4.FTYP.byteLength);
return result;
}
// encryption boxes
static saio(sencOffset) {
const subOffset = sencOffset + 4 + 4; // skip version/flags and sample_count
return MP4.box(MP4.types.saio, new Uint8Array([
0,
0,
0,
0,
0,
0,
0,
1,
(subOffset >> 24) & 255,
(subOffset >> 16) & 255,
(subOffset >> 8) & 255,
subOffset & 255,
]));
}
static saiz(defaultSampleInfoSize, sampleInfoSizes) {
if (!isFiniteNumber(defaultSampleInfoSize)) {
defaultSampleInfoSize = 0;
}
const sampleCount = sampleInfoSizes.length;
const perSampleSizeData = defaultSampleInfoSize === 0 ? new Uint8Array(sampleInfoSizes) : new Uint8Array();
return MP4.box(MP4.types.saiz, new Uint8Array([
0,
0,
0,
0,
defaultSampleInfoSize,
(sampleCount >> 24) & 255,
(sampleCount >> 16) & 255,
(sampleCount >> 8) & 255,
sampleCount & 255,
]), perSampleSizeData);
}
static senc(track) {
const samples = track.samples || [], sampleCount = samples.length;
let totalSubsamples = 0;
let lastSize = NaN;
let hasDefaultSampleSize = true;
const sampleInfoSizes = [];
if (!track.encrypted || sampleCount <= 0) {
return { boxData: new Uint8Array(), sampleInfoSizes, defaultSampleInfoSize: 0 };
}
const defaultPerSampleIVSize = track.defaultPerSampleIVSize ? track.defaultPerSampleIVSize : 0;
for (const sample of samples) {
if (sample.subsamples) {
totalSubsamples += sample.subsamples.length;
}
}
if (totalSubsamples <= 0) {
// don't create a senc if there are no subsamples
return { boxData: new Uint8Array(), sampleInfoSizes, defaultSampleInfoSize: 0 };
}
// 4 bytes for sample_count
// 2 bytes per sample for subsample_count
// 6 bytes per subsample for unsigned int(16) BytesOfClearData and unsigned int(32) BytesOfProtectedData;
// defaultPerSampleIVSize bytes per sample
const boxdata = new Uint8Array(4 + (sampleCount * 2 + sampleCount * defaultPerSampleIVSize + totalSubsamples * 6));
let offset = this.set32(sampleCount, boxdata, 0);
for (const sample of samples) {
const subsamples = sample.subsamples ? sample.subsamples : [];
let subsampleSize = 2; // size in bytes of the subsample entry - start with 2 for the subsample count
if (sample.iv) {
// per sample IV from cenc aux data
boxdata.set(sample.iv, offset);
offset += sample.iv.byteLength;
subsampleSize += sample.iv.byteLength;
}
offset = this.set16(subsamples.length, boxdata, offset);
for (const subsample of subsamples) {
offset = this.set16(subsample[0], boxdata, offset);
offset = this.set32(subsample[1], boxdata, offset);
subsampleSize += 6;
}
sampleInfoSizes.push(subsampleSize);
if (!isFiniteNumber(lastSize)) {
lastSize = subsampleSize;
}
hasDefaultSampleSize = hasDefaultSampleSize && lastSize === subsampleSize;
lastSize = subsampleSize;
}
const boxData = MP4.box(MP4.types.senc, new Uint8Array([
0,
0,
0,
2,
]), boxdata);
return { boxData, defaultSampleInfoSize: hasDefaultSampleSize ? lastSize : 0, sampleInfoSizes };
}
static sinf(decryptdata, type, originalCodingName) {
return MP4.box(MP4.types.sinf, MP4.frma(originalCodingName), MP4.schm(), MP4.schi(decryptdata, type));
}
static frma(originalCodingName) {
return MP4.box(MP4.types.frma, new Uint8Array(originalCodingName));
}
static schm() {
return MP4.box(MP4.types.schm, new Uint8Array([
0,
0,
0,
0,
99,
98,
99,
115,
0,
1,
0,
0,
]));
}
static schi(decryptdata, type) {
return MP4.box(MP4.types.schi, MP4.tenc(decryptdata, type));
}
static tenc(decryptdata, trackType) {
let skipPattern = 0;
if (trackType === 'video') {
skipPattern = 25; // 1 default_crypt_byte_block, 9 default_skip_byte_block
}
const defaultIV = new Uint8Array(17);
defaultIV[0] = 16; // default_constant_IV_size (16)
if (decryptdata.iv && decryptdata.iv.byteLength === 16) {
defaultIV.set(decryptdata.iv, 1);
}
if (!decryptdata.keyId) {
throw 'tenc: no key id found in decryptdata';
}
return MP4.box(MP4.types.tenc, new Uint8Array([
1,
0,
0,
0,
0,
skipPattern,
1,
0,
]), decryptdata.keyId, // default_KID, 16 bytes
defaultIV);
}
// only using this to write seig entries
static sbgp(track) {
if (!track.encrypted || track.samples.length === 0 || !track.samples[0].keyTagInfo) {
return new Uint8Array();
}
// at this point we're assuming all samples in the track have the same key id
// this should hold true for the current ts/mp4 remux path
const sampleCount = track.samples.length;
return MP4.box(MP4.types.sbgp, new Uint8Array([
0,
0,
0,
0,
]), new Uint8Array(MP4.types.seig), // grouping_type
new Uint8Array([
0,
0,
0,
1,
(sampleCount >> 24) & 255,
(sampleCount >> 16) & 255,
(sampleCount >> 8) & 255,
sampleCount & 255,
0,
1,
0,
1,
]));
}
// only using this to write seig entries
static sgpd(track) {
if (!track.encrypted || track.samples.length === 0 || !track.samples[0].keyTagInfo) {
return new Uint8Array();
}
const sDecryptdata = track.samples[0].keyTagInfo;
let skipPattern = 0;
if (track.type === 'video') {
skipPattern = 25; // 1 default_crypt_byte_block, 9 default_skip_byte_block
}
const sizeAndIv = new Uint8Array(17);
sizeAndIv[0] = 16;
if (sDecryptdata.iv) {
sizeAndIv.set(sDecryptdata.iv, 1);
}
if (!sDecryptdata.keyId) {
throw 'sgpd: no keyid in decryptdata';
}
return MP4.box(MP4.types.sgpd, new Uint8Array([
1,
0,
0,
0,
]), new Uint8Array(MP4.types.seig), // grouping_type
new Uint8Array([
0,
0,
0,
37,
0,
0,
0,
1,
]), new Uint8Array([
0,
skipPattern,
1,
0,
]), sDecryptdata.keyId, sizeAndIv);
}
/**
* @param {Uint8Array} systemId 16 bytes
* @param {array of Uint8Array} keyids The list of key ids described by this PSSH box
* @param {Uint8Array} An arbitrary buffer of data to be used in the data field of the PSSH box
* @returns {Uint8Array} Bytes representing a PSSH box
*/
static pssh(systemId, keyids, data) {
if (!MP4.types) {
MP4.init();
}
if (!systemId) {
throw new TypeError('Bad system id');
}
if (systemId.byteLength !== 16) {
throw new RangeError('Invalid system id');
}
let version;
let kids;
if (keyids) {
version = 1;
kids = new Uint8Array(keyids.length * 16);
for (let ix = 0; ix < keyids.length; ix++) {
const k = keyids[ix]; // uint8array
if (k.byteLength !== 16) {
throw new RangeError('Invalid key');
}
kids.set(k, ix * 16);
}
}
else {
version = 0;
kids = new Uint8Array();
}
let kidCount;
if (version > 0) {
kidCount = new Uint8Array(4);
if (keyids.length > 0) {
new DataView(kidCount.buffer).setUint32(0, keyids.length, false); // Big endian
}
}
else {
kidCount = new Uint8Array();
}
const dataSize = new Uint8Array(4); // Mandatory field
if (data && data.byteLength > 0) {
new DataView(dataSize.buffer).setUint32(0, data.byteLength, false); // Big endian
}
return MP4.box(MP4.types.pssh, new Uint8Array([
version,
0,
0,
0,
]), systemId, // 16 bytes
kidCount, kids, dataSize, data || new Uint8Array());
}
}
var MP4$1 = MP4;
var VideoDynamicRangeType;
(function (VideoDynamicRangeType) {
// should be same as AirPlayVideoDynamicRangeFormat
VideoDynamicRangeType[VideoDynamicRangeType["SDR"] = 0] = "SDR";
VideoDynamicRangeType[VideoDynamicRangeType["HDR"] = 1] = "HDR";
VideoDynamicRangeType[VideoDynamicRangeType["HDR10"] = 2] = "HDR10";
VideoDynamicRangeType[VideoDynamicRangeType["DolbyVision"] = 3] = "DolbyVision";
VideoDynamicRangeType[VideoDynamicRangeType["HLG"] = 4] = "HLG";
})(VideoDynamicRangeType || (VideoDynamicRangeType = {}));
var CompressionType;
(function (CompressionType) {
// should be same as AirPlayCompressionType
CompressionType[CompressionType["H264"] = 16] = "H264";
CompressionType[CompressionType["HEVC"] = 64] = "HEVC";
CompressionType[CompressionType["VP09"] = 65] = "VP09";
})(CompressionType || (CompressionType = {}));
// import { AudioSegmentCodecType } from '../types/tracks';
/*
* 2018 Apple Inc. All rights reserved.
*/
const ac3Codecs = new Set(['ac-3', 'mp4a.a5', 'mp4a.A5']);
const ec3Codecs = new Set(['ec-3', 'mp4a.a6', 'mp4a.A6']);
const SampleDurationMap = { aac: 1024, mp3: 1024, ac3: 1536, ec3: 1536 };
const MediaUtil = {
isAC3(codec) {
return Boolean(codec && ac3Codecs.has(codec));
},
isEC3(codec) {
return Boolean(codec && ec3Codecs.has(codec));
},
isDolbyAtmos(codec, channels) {
const parameters = channels.split('/');
return Boolean(MediaUtil.isEC3(codec) && parameters.length > 1 && parameters[1].split(',').find((x) => x === 'JOC'));
},
isAAC(codec) {
let match;
return Boolean(codec && (codec === 'aac' || ((match = codec.match(/^mp4a\.40\.(.*)/)) !== null && match[1] !== '34')));
},
isMP3(codec) {
let match;
return Boolean(codec && (codec === 'mp3' || ((match = codec.match(/^mp4a\.40\.(.*)/)) !== null && match[1] === '34')));
},
isAVC(codec) {
// basic match without validation
return Boolean(codec && codec.match(/^avc[13]\.(.*)/));
},
isXHEAAC: function (codec) {
return Boolean(codec === 'mp4a.40.42');
},
isALAC: function (codec) {
return Boolean(codec === 'alac');
},
isFLAC: function (codec) {
return Boolean(codec === 'fLaC');
},
isHEVC(codec) {
// basic match without validation
return Boolean(codec && codec.match(/^(hev|hvc)1\..*/));
},
isDolby(codec) {
return Boolean(codec && codec.match(/^dv(h1|he|a1|av)\..*/));
},
isVP09(codec) {
// basic match without validation
return Boolean(codec && codec.match(/^vp09\..*/));
},
isCompatibleCodecString(c1, c2) {
const codecs1 = c1.split(',');
const codecs2 = c2.split(',');
const videoCodec1 = codecs1.filter((codec) => MediaUtil.isVideoCodec(codec));
const videoCodec2 = codecs2.filter((codec) => MediaUtil.isVideoCodec(codec));
const audioCodec1 = codecs1.filter((codec) => MediaUtil.isAudioCodec(codec));
const audioCodec2 = codecs2.filter((codec) => MediaUtil.isAudioCodec(codec));
const videoOk = (videoCodec1.length === 0 && videoCodec2.length === 0) || (videoCodec1.length === videoCodec2.length && MediaUtil.isCompatibleVideoCodec(videoCodec1[0], videoCodec2[0]));
const audioOk = (audioCodec1.length === 0 && audioCodec2.length === 0) || (audioCodec1.length === audioCodec2.length && MediaUtil.isCompatibleAudioCodec(audioCodec1[0], audioCodec2[0]));
return videoOk && audioOk;
},
isVideoCodec(codec) {
return MediaUtil.isAVC(codec) || MediaUtil.isDolby(codec) || MediaUtil.isHEVC(codec) || MediaUtil.isVP09(codec);
},
isAudioCodec(codec) {
return MediaUtil.isAC3(codec) || MediaUtil.isEC3(codec) || MediaUtil.isAAC(codec) || MediaUtil.isMP3(codec);
},
isCompatibleVideoCodec(c1, c2) {
return Boolean(c1 &&
c2 &&
(c1 === c2 ||
(MediaUtil.isDolby(c1) && MediaUtil.isDolby(c2)) ||
(MediaUtil.isHEVC(c1) && MediaUtil.isHEVC(c2)) ||
(MediaUtil.isAVC(c1) && MediaUtil.isAVC(c2)) ||
(MediaUtil.isVP09(c1) && MediaUtil.isVP09(c2))));
},
isCompatibleAudioCodec(c1, c2) {
return Boolean(c1 &&
c2 &&
(c1 === c2 ||
(MediaUtil.isAAC(c1) && MediaUtil.isAAC(c2)) ||
(MediaUtil.isAC3(c1) && MediaUtil.isAC3(c2)) ||
(MediaUtil.isEC3(c1) && MediaUtil.isEC3(c2)) ||
(MediaUtil.isMP3(c1) && MediaUtil.isMP3(c2))));
},
getSegmentCodec(audioCodec) {
let segmentCodec;
if (MediaUtil.isAAC(audioCodec)) {
segmentCodec = 'aac';
}
else if (MediaUtil.isAC3(audioCodec)) {
segmentCodec = 'ac3';
}
else if (MediaUtil.isEC3(audioCodec)) {
segmentCodec = 'ec3';
}
else if (audioCodec === 'mp3') {
segmentCodec = 'mp3';
}
else {
throw new Error(`invalid audio config, codec ${audioCodec}`);
}
return segmentCodec;
},
getChannelCount(channels) {
if (!channels) {
return 0;
}
const parameters = channels.split('/');
const channelCount = parseInt(parameters[0]);
if (!isFiniteNumber(channelCount)) {
return 0;
}
return channelCount;
},
avc1toavcoti(codec) {
var _a, _b;
const avcdata = codec.split('.');
let result;
if (avcdata.length > 2) {
result = avcdata.shift() + '.';
result += parseInt((_a = avcdata.shift()) !== null && _a !== void 0 ? _a : '').toString(16);
result += ('000' + parseInt((_b = avcdata.shift()) !== null && _b !== void 0 ? _b : '').toString(16)).substr(-4);
}
else {
result = codec;
}
return result;
},
getDynamicRangeType(videoRange, videoCodec) {
let type = VideoDynamicRangeType.SDR; // default to SDR
if (videoRange === 'PQ' && MediaUtil.isDolby(videoCodec)) {
type = VideoDynamicRangeType.DolbyVision;
}
else if (videoRange === 'PQ' && (MediaUtil.isHEVC(videoCodec) || MediaUtil.isVP09(videoCodec))) {
type = VideoDynamicRangeType.HDR10;
}
else if (videoRange === 'HLG' && (videoCodec.indexOf('hvc1') !== -1 || MediaUtil.isVP09(videoCodec))) {
type = VideoDynamicRangeType.HLG;
}
return type;
},
getCompressionType(videoCodec) {
let compressionType = CompressionType.H264;
if (MediaUtil.isHEVC(videoCodec) || MediaUtil.isDolby(videoCodec)) {
compressionType = CompressionType.HEVC;
}
else if (MediaUtil.isVP09(videoCodec)) {
compressionType = CompressionType.VP09;
}
return compressionType;
},
isHigherCodecByFamily(currentCodec, newCodec) {
if (!currentCodec) {
return true;
}
const splitCurrentCodec = currentCodec.split('.');
const splitNewCodec = newCodec.split('.');
if (splitCurrentCodec[0] !== splitNewCodec[0]) {
throw new Error(`mismatch in codec family current/new: ${splitCurrentCodec[0]}/${splitNewCodec[0]}`);
}
switch (splitCurrentCodec[0]) {
case 'avc1':
case 'avc3':
return splitNewCodec[1] > splitCurrentCodec[1];
case 'vp09':
return newCodec > currentCodec;
case 'hvc1':
case 'hev1':
const currentTier = splitCurrentCodec[3].substring(0, 1) === 'H' ? 1 : 0;
const currentLevel = splitCurrentCodec[3].substring(1);
const newTier = splitNewCodec[3].substring(0, 1) === 'H' ? 1 : 0;
const newLevel = splitNewCodec[3].substring(1);
return splitNewCodec[1] > splitCurrentCodec[1] || splitNewCodec[2] > splitCurrentCodec[2] || newTier > currentTier || newLevel > currentLevel;
case 'dvh1':
return splitNewCodec[1] > splitCurrentCodec[1] || splitNewCodec[2] > splitCurrentCodec[2];
}
},
};
class SilentAudio {
static getTrack(observer, id, codec, channelCount, logger) {
let track;
const segmentCodec = MediaUtil.getSegmentCodec(codec);
switch (segmentCodec) {
case 'aac':
{
let config;
if (channelCount === 1) {
config = ADTS.getAudioConfig(observer, new Uint8Array([255, 241, 92, 64, 1, 127, 252]), 0, codec, logger);
}
else {
config = ADTS.getAudioConfig(observer, new Uint8Array([255, 241, 92, 128, 1, 191, 252]), 0, codec, logger);
}
if (config) {
const info = { id, timescale: config.samplerate, duration: 0, encrypted: false, keyTagInfo: undefined };
track = { type: 'audio', info, config };
}
}
break;
case 'ac3':
case 'ec3':
{
const config = Dolby.getAudioConfig(observer, new Uint8Array([11, 119, 69, 17, 128, 64, 47, 132]), 0, logger);
if (config) {
const info = { id, timescale: config.samplerate, duration: 0, encrypted: false, keyTagInfo: undefined };
track = { type: 'audio', info, config };
}
}
break;
}
return track;
}
static getSample(codec, channelCount) {
let sample;
switch (codec) {
case 'mp4a.40.2':
case 'mp4a.40.5':
if (channelCount === 1) {
sample = new Uint8Array([0, 208, 0, 7]);
}
else {
sample = new Uint8Array([33, 0, 3, 64, 104, 28]);
}
break;
case 'ac-3':
case 'ec-3':
sample = new Uint8Array([
11,
119,
69,
17,
128,
64,
47,
132,
41,
3,
253,
214,
124,
253,
243,
215,
233,
95,
185,
123,
78,
20,
40,
106,
97,
190,
74,
253,
43,
218,
208,
140,
191,
176,
144,
120,
214,
181,
44,
124,
129,
251,
91,
109,
187,
109,
198,
225,
43,
172,
116,
140,
176,
123,
38,
144,
211,
247,
225,
64,
29,
53,
175,
96,
16,
57,
121,
87,
78,
203,
81,
37,
7,
72,
228,
132,
37,
169,
38,
231,
97,
229,
247,
194,
208,
8,
12,
83,
74,
139,
137,
17,
22,
26,
221,
203,
107,
113,
94,
93,
75,
33,
208,
247,
146,
105,
39,
143,
6,
36,
1,
227,
108,
70,
11,
180,
152,
218,
182,
218,
209,
59,
85,
104,
201,
70,
37,
82,
219,
68,
55,
225,
144,
99,
149,
0,
119,
26,
14,
69,
164,
241,
204,
222,
81,
177,
142,
80,
20,
100,
97,
143,
101,
221,
140,
113,
31,
208,
124,
25,
64,
29,
49,
77,
140,
30,
155,
74,
214,
204,
138,
229,
109,
172,
95,
130,
70,
230,
134,
88,
59,
179,
212,
155,
232,
0,
0,
0,
0,
0,
173,
234,
]);
break;
}
return sample;
}
static getSegment(silentTrack, sequenceNumber, startDtsTimescale, segmentDuration) {
if (!silentTrack) {
return;
}
const { timescale } = silentTrack.info;
const { segmentCodec } = silentTrack.config;
const silentFrame = SilentAudio.getSample(silentTrack.config.codec, silentTrack.config.channelCount);
if (!silentFrame) {
return;
}
const samples = [];
const track = {
id: silentTrack.info.id,
sequenceNumber,
type: 'audio',
encrypted: false,
samples,
defaultPerSampleIVSize: 0,
};
const sampleDuration = SampleDurationMap[segmentCodec];
const nbSamples = Math.ceil((segmentDuration * timescale) / sampleDuration);
const baseTime = Math.round(nbSamples * sampleDuration + startDtsTimescale);
const endTs = { baseTime, timescale };
let offset = 0;
const mdatSize = nbSamples * silentFrame.byteLength + 8;
const mdat = new Uint8Array(mdatSize);
mdat[0] = (mdatSize >> 24) & 255;
mdat[1] = (mdatSize >> 16) & 255;
mdat[2] = (mdatSize >> 8) & 255;
mdat[3] = mdatSize & 255;
if (!MP4$1.types) {
MP4$1.init();
}
mdat.set(MP4$1.types.mdat, 4);
offset += 8;
for (let i = 0; i < nbSamples; i++) {
samples.push({
duration: sampleDuration,
size: silentFrame.byteLength,
cts: 0,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: 1,
isNonSync: 0,
paddingValue: 0,
},
});
mdat.set(silentFrame, offset);
offset += silentFrame.byteLength;
}
const moof = MP4$1.moof(startDtsTimescale, track);
const silentFragData = new Uint8Array(moof.byteLength + mdat.byteLength);
silentFragData.set(moof);
silentFragData.set(mdat, moof.byteLength);
return { silentFragData, endTs };
}
}
// 10 seconds
const MAX_SILENT_FRAME_DURATION = 10000;
class EsRemuxer extends RemuxerBase {
constructor(observer, config, typeSupported, vendor, logger) {
super(observer, config, logger);
this.typeSupported = typeSupported;
this.isVideoContiguous = false;
this.logger = logger.child({ name: 'EsRemuxer' });
const userAgent = navigator.userAgent;
this.isSafari = vendor && vendor.indexOf('Apple') > -1 && userAgent && !userAgent.match('CriOS');
}
resetTimeStamp(defaultTimeStamp) {
this._initPTS = this._initDTS = defaultTimeStamp;
}
resetInitSegment() {
this.currentInitTrack = undefined;
this._silentAudioTrack = undefined;
}
/**
* @param timeOffset The position in the media element corresponding to this fragment when playback rate = 1
* @param contiguous Whether this fragment is contiguous with previously appended fragment
* @param accurateTimeOffset Whether timeOffset is reliable
* @param keyTagInfo Information from EXT-X-KEY tag
* @param iframeMediaStart in iframe mode, the desired start DTS of the remuxed fragment
* @param iframeDuration in iframe mode, the desired duration of the remuxed fragment
*/
remuxEsTracks(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset, keyTagInfo, iframeMediaStart, iframeDuration) {
var _a;
if (!contiguous) {
this.isVideoContiguous = false;
}
// generate Init Segment if needed
let silentAudioSegment;
const timelineOffset = typeof iframeMediaStart === 'undefined' ? timeOffset : iframeMediaStart;
if (!this.currentInitTrack) {
if (audioTrack && audioTrack.config.codec) {
// when we start out in non-iframe mode we need to store the audio parameters
// we won't get this info from the iframe playlist since the demuxer will skip audio samples
this._audioTrackInfo = { id: audioTrack.info.id, codec: audioTrack.config.codec, channelCount: audioTrack.config.channelCount };
}
if (videoTrack && iframeDuration && this._audioTrackInfo) {
const silentAudioBase = SilentAudio.getTrack(this.observer, this._audioTrackInfo.id, this._audioTrackInfo.codec, this._audioTrackInfo.channelCount, this.logger);
if (silentAudioBase) {
this._silentAudioTrack = Object.assign(Object.assign({}, silentAudioBase), { info: Object.assign(Object.assign({}, silentAudioBase.info), { inputTimescale: 90000 }), parsingData: { len: 0, sequenceNumber: 0, esSamples: [] } });
// need to populate samples for generateIS
const segmentStartPTS = this._initPTS + Math.round(timelineOffset * this._silentAudioTrack.info.timescale);
silentAudioSegment = SilentAudio.getSegment(this._silentAudioTrack, videoTrack.parsingData.sequenceNumber, segmentStartPTS, iframeDuration);
videoTrack.parsingData.sequenceNumber++;
}
}
else {
this._silentAudioTrack = undefined;
}
this.updateInitPTSDTS(videoTrack, audioTrack, timeOffset); // Use real audioTrack info to update PTSDTS
this.generateIS(this._silentAudioTrack ? this._silentAudioTrack : audioTrack, videoTrack);
}
if (this.currentInitTrack) {
const remuxVideo = videoTrack && videoTrack.parsingData.esSamples.length;
const isVideoContiguous = this.isVideoContiguous;
let audioData, videoData;
// Purposefully remuxing audio before video, so that remuxVideo can use nextAudioPts, which is
// calculated in remuxAudio.
if (videoTrack && iframeDuration && this._silentAudioTrack && !silentAudioSegment) {
// samples could have been generated before init segment generation
const segmentStartPTS = this._initPTS + Math.round((timelineOffset + this.config.audioPrimingDelay) * this._silentAudioTrack.info.timescale);
silentAudioSegment = SilentAudio.getSegment(this._silentAudioTrack, videoTrack.parsingData.sequenceNumber, segmentStartPTS, iframeDuration);
}
if (audioTrack && audioTrack.parsingData.esSamples.length) {
// if initSegment was generated without video samples, regenerate it again
if (!isFiniteNumber(audioTrack.info.timescale)) {
this.logger.warn('regenerate InitSegment as audio detected');
this.updateInitPTSDTS(videoTrack, audioTrack, timeOffset); // Use real audioTrack info to update PTSDTS
this.generateIS(audioTrack, videoTrack);
}
audioData = this.remuxAudio(audioTrack, timelineOffset, contiguous, accurateTimeOffset, keyTagInfo);
if (remuxVideo) {
let audioTrackLength;
if (audioData) {
audioTrackLength = convertTimestampToSeconds(audioData.endPTS) - convertTimestampToSeconds(audioData.startPTS);
}
// if initSegment was generated without video samples, regenerate it again
if (!isFiniteNumber(videoTrack.info.timescale)) {
this.logger.warn('regenerate InitSegment as video detected');
this.updateInitPTSDTS(videoTrack, audioTrack, timeOffset); // Use real audioTrack info to update PTSDTS
this.generateIS(audioTrack, videoTrack);
}
videoData = this.remuxVideo(videoTrack, timelineOffset, isVideoContiguous, audioTrackLength, iframeDuration);
}
}
else {
if (remuxVideo) {
videoData = this.remuxVideo(videoTrack, timelineOffset, isVideoContiguous, undefined, iframeDuration);
}
if (videoData && audioTrack && audioTrack.config.codec) {
audioData = this.remuxEmptyAudio(audioTrack, timelineOffset, contiguous, accurateTimeOffset, videoData, keyTagInfo);
}
}
let parsingData;
if (silentAudioSegment) {
parsingData = {
data1: videoData.data1,
data2: silentAudioSegment.silentFragData,
startDTS: videoData.startDTS,
startPTS: videoData.startPTS,
endDTS: determineMaxTimestamp(videoData.endDTS, silentAudioSegment.endTs),
endPTS: determineMaxTimestamp(videoData.endPTS, silentAudioSegment.endTs),
type: 'audiovideo',
track: this.currentInitTrack,
};
}
else if (videoData && audioData) {
parsingData = {
data1: videoData.data1,
data2: audioData.data1,
startDTS: determineMinTimestamp(videoData.startDTS, audioData.startDTS),
startPTS: determineMinTimestamp(videoData.startPTS, audioData.startPTS),
endDTS: determineMaxTimestamp(videoData.endDTS, audioData.endDTS),
endPTS: determineMaxTimestamp(videoData.endPTS, audioData.endPTS),
type: 'audiovideo',
track: this.currentInitTrack,
dropped: videoData.dropped,
framesWithoutIDR: videoData.framesWithoutIDR,
firstKeyframePts: videoData.firstKeyframePts,
};
}
else if (videoData) {
parsingData = {
data1: videoData.data1,
startDTS: videoData.startDTS,
startPTS: videoData.startPTS,
endDTS: videoData.endDTS,
endPTS: videoData.endPTS,
type: 'video',
track: this.currentInitTrack,
dropped: videoData.dropped,
framesWithoutIDR: videoData.framesWithoutIDR,
firstKeyframePts: videoData.firstKeyframePts,
};
}
else if (audioData) {
parsingData = {
data1: audioData.data1,
startDTS: audioData.startDTS,
startPTS: audioData.startPTS,
endDTS: audioData.endDTS,
endPTS: audioData.endPTS,
type: 'audio',
track: this.currentInitTrack,
};
}
else {
this.logger.error('Missing video and audio data');
}
if (textTrack && textTrack.captionSamples.length) {
this.remuxText(textTrack, parsingData);
}
if ((_a = id3Track === null || id3Track === void 0 ? void 0 : id3Track.id3Samples) === null || _a === void 0 ? void 0 : _a.length) {
this.remuxID3(id3Track, parsingData);
}
this.observer.trigger(DemuxerEvent.FRAG_PARSING_DATA, parsingData);
}
else {
this.logger.error('failed to generate IS');
}
// notify end of parsing
this.observer.trigger(DemuxerEvent.FRAG_PARSED);
}
/**
* @param videoTrack
* @param audioTrack
* @param timeOffset Position in media element corresponding to the beginning of this segment
*/
updateInitPTSDTS(videoTrack, audioTrack, timeOffset) {
let initPTS = Infinity, initDTS = Infinity;
const videoSamples = videoTrack ? videoTrack.parsingData.esSamples : [];
const audioSamples = audioTrack ? audioTrack.parsingData.esSamples : [];
if (isFiniteNumber(this._initPTS)) {
return;
}
if (audioTrack && audioSamples.length) {
// remember first PTS of this demuxing context. for audio, PTS = DTS
initPTS = initDTS = audioSamples[0].pts - audioTrack.info.inputTimescale * timeOffset;
}
if (videoTrack && videoSamples.length) {
// let's use input time scale as MP4 video timescale
// we use input time scale straight away to avoid rounding issues on frame duration / cts computation
const inputTimeScale = videoTrack.info.inputTimescale;
videoTrack.info.timescale = inputTimeScale;
initPTS = Math.min(initPTS, getVideoStartPts(videoSamples) - inputTimeScale * timeOffset);
initDTS = Math.min(initDTS, videoSamples[0].dts - inputTimeScale * timeOffset);
this.observer.trigger(DemuxerEvent.INIT_PTS_FOUND, { initPTS: convertSecondsToTimestamp(initPTS, inputTimeScale) });
}
if (isFiniteNumber(initPTS) && isFiniteNumber(initDTS)) {
this._initPTS = initPTS;
this._initDTS = initDTS;
}
else {
const payload = new FragParsingError(false, 'invalid initPTS or initDTS', ErrorResponses.InvalidInitTimestamp);
this.observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
}
}
generateIS(audioTrack, videoTrack) {
// const observer = this.observer;
const videoSamples = videoTrack ? videoTrack.parsingData.esSamples : [];
const typeSupported = this.typeSupported;
let container = 'audio/mp4';
let track;
if (audioTrack && videoTrack && videoSamples.length) {
const inputTimeScale = videoTrack.info.inputTimescale;
videoTrack.info.timescale = inputTimeScale;
audioTrack.info.timescale = audioTrack.config.samplerate;
const initSegment = MP4.initSegment([videoTrack, audioTrack]);
track = {
type: 'audiovideo',
container: 'video/mp4',
codec: `${videoTrack.config.codec},${audioTrack.config.codec}`,
initSegment,
};
}
else if (audioTrack) {
// let's use audio sampling rate as MP4 time scale.
// rationale is that there is a integer nb of audio frames per audio sample (1024 for AAC)
// using audio sampling rate here helps having an integer MP4 frame duration
// this avoids potential rounding issue and AV sync issue
audioTrack.info.timescale = audioTrack.config.samplerate;
this.logger.info(`audio sampling rate : ${audioTrack.config.samplerate}`);
switch (audioTrack.config.segmentCodec) {
case 'mp3':
if (typeSupported.mpeg) {
// Chrome and Safari
container = 'audio/mpeg';
audioTrack.config.codec = '';
}
else if (typeSupported.mp3) {
// Firefox
audioTrack.config.codec = 'mp3';
}
break;
}
const initSegment = audioTrack.config.segmentCodec === 'mp3' && typeSupported.mpeg ? new Uint8Array() : MP4.initSegment([audioTrack]);
track = {
type: 'audio',
container: container,
codec: audioTrack.config.codec,
initSegment,
};
}
else if (videoTrack && videoSamples.length) {
// let's use input time scale as MP4 video timescale
// we use input time scale straight away to avoid rounding issues on frame duration / cts computation
const inputTimeScale = videoTrack.info.inputTimescale;
videoTrack.info.timescale = inputTimeScale;
const initSegment = MP4.initSegment([videoTrack]);
track = {
type: 'video',
container: 'video/mp4',
codec: videoTrack.config.codec,
initSegment,
};
}
if (track) {
this.currentInitTrack = track;
const data = { track };
this.observer.trigger(DemuxerEvent.FRAG_PARSING_INIT_SEGMENT, data);
}
else {
const payload = new FragParsingError(false, 'no audio/video samples found', ErrorResponses.NoAVSamplesFound);
this.observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
}
}
remuxVideo(track, timeOffset, contiguous, audioTrackLength, iframeDuration) {
let offset = 8;
let mp4SampleDuration;
let mdat;
let firstPTS;
let firstDTS;
let lastPTS;
let lastDTS;
let dropped = track.parsingData.dropped;
const dropFrames = !contiguous && this.config.forceKeyFrameOnDiscontinuity;
const inputSamples = track.parsingData.esSamples;
const timeScale = track.info.inputTimescale;
const outputSamples = [];
const encrypted = track.info.encrypted;
// PTS is coded on 33bits, and can loop from -2^32 to 2^32
// normalizePts will make PTS/DTS value monotonic, we use last known DTS value as reference value
let nextAvcDts;
// contiguous fragments are consecutive fragments from same quality level (same level, new SN = old SN + 1)
if (contiguous) {
// if parsed fragment is contiguous with last one, let's use last DTS value as reference
nextAvcDts = this.nextAvcDts;
}
else {
// if not contiguous, let's use sample
nextAvcDts = normalizePts(inputSamples[0].dts, inputSamples[0].pts);
}
inputSamples.forEach(function (sample) {
sample.pts = normalizePts(sample.pts, nextAvcDts);
sample.dts = normalizePts(sample.dts, nextAvcDts);
});
// sort video samples by DTS then PTS then demux id order
inputSamples.sort(function (a, b) {
const deltadts = a.dts - b.dts;
const deltapts = a.pts - b.pts;
return deltadts ? deltadts : deltapts ? deltapts : a.id - b.id;
});
let firstKeyframePts;
const firstKeyframeIndex = inputSamples.findIndex((sample) => sample.key);
if (inputSamples[firstKeyframeIndex]) {
firstKeyframePts = inputSamples[firstKeyframeIndex].pts;
}
if (dropFrames) {
if (firstKeyframeIndex > 0) {
this.logger.warn(`Dropped ${firstKeyframeIndex} out of ${inputSamples.length} video samples due to a missing keyframe`);
inputSamples.splice(0, firstKeyframeIndex);
dropped += firstKeyframeIndex;
}
else if (firstKeyframeIndex === -1) {
this.logger.warn(`No keyframe found out of ${inputSamples.length} video samples`);
dropped += inputSamples.length;
}
}
const firstSample = inputSamples[0];
const lastSample = inputSamples[inputSamples.length - 1];
// handle broken streams with PTS < DTS, tolerance up 200ms (18000 in 90kHz timescale)
const PTSDTSshift = inputSamples.reduce((prev, curr) => Math.max(Math.min(prev, curr.pts - curr.dts), -18000), 0);
if (PTSDTSshift < 0) {
this.logger.warn(`PTS < DTS detected in video samples, shifting DTS by ${Math.round(PTSDTSshift / 90)} ms to overcome this issue`);
for (let i = 0; i < inputSamples.length; i++) {
inputSamples[i].dts += PTSDTSshift;
}
}
const isSafari = this.isSafari;
// on Safari let's signal the same sample duration for all samples
// sample duration (as expected by trun MP4 boxes), should be the delta between sample DTS
// set this constant duration as being the avg delta between consecutive DTS.
mp4SampleDuration = Math.round((lastSample.dts - firstSample.dts) / (inputSamples.length - 1));
// compute first DTS/PTS, normalize them against reference value
firstDTS = Math.max(firstSample.dts, 0);
firstPTS = Math.max(firstSample.pts, 0);
if (isFiniteNumber(iframeDuration)) {
firstDTS = timeOffset * timeScale;
firstPTS = timeOffset * timeScale;
}
// if fragment are contiguous, detect hole/overlapping between fragments
if (contiguous) {
// check timestamp continuity across consecutive fragments (this is to remove inter-fragment gap/hole)
const delta = firstDTS - nextAvcDts;
const foundHole = delta > mp4SampleDuration;
const foundOverlap = delta < -1;
if (foundHole || foundOverlap) {
if (foundHole) {
this.logger.warn(`AVC: ${delta}/90000 hole between fragments detected`);
}
else {
this.logger.warn(`AVC: ${delta}/90000 overlapping between fragments detected`);
}
}
}
let nbNalu = 0;
let naluLen = 0;
const nbSamples = inputSamples.length;
for (let i = 0; i < nbSamples; i++) {
// compute total/avc sample length and nb of NAL units
const sample = inputSamples[i], units = sample.units, nbUnits = units.length;
let sampleLen = 0;
for (let j = 0; j < nbUnits; j++) {
sampleLen += units[j].data.length;
}
naluLen += sampleLen;
nbNalu += nbUnits;
sample.length = sampleLen;
// normalize PTS/DTS
if (isSafari) {
// sample DTS is computed using a constant decoding offset (mp4SampleDuration) between samples
sample.dts = firstDTS + i * mp4SampleDuration;
}
else {
// ensure sample monotonic DTS
sample.dts = Math.max(sample.dts, firstDTS);
}
// ensure that computed value is greater or equal than sample DTS
sample.pts = Math.max(sample.pts, sample.dts);
}
// compute lastPTS/lastDTS
lastDTS = Math.max(lastSample.dts, 0);
lastPTS = Math.max(lastSample.pts, 0, lastDTS);
if (isFiniteNumber(iframeDuration)) {
lastDTS = timeOffset * timeScale;
lastPTS = timeOffset * timeScale;
}
/* concatenate the video data and construct the mdat in place
(need 8 more bytes to fill length and mpdat type) */
const mdatSize = naluLen + 4 * nbNalu + 8;
try {
mdat = new Uint8Array(mdatSize);
}
catch (err) {
const payload = new RemuxAllocError(false, `fail allocating video mdat ${mdatSize}`, ErrorResponses.FailedToAllocateVideoMdat, mdatSize);
this.observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return;
}
const view = new DataView(mdat.buffer);
view.setUint32(0, mdatSize);
mdat.set(MP4.types.mdat, 4);
for (let i = 0; i < nbSamples; i++) {
const avcSample = inputSamples[i], avcSampleUnits = avcSample.units;
let mp4SampleLength = 0, compositionTimeOffset;
// convert NALU bitstream to MP4 format (prepend NALU with size field)
const subsamples = [];
let bytesClear = 0;
for (let j = 0, nbUnits = avcSampleUnits.length; j < nbUnits; j++) {
const unit = avcSampleUnits[j], unitData = unit.data, unitDataLen = unit.data.byteLength;
view.setUint32(offset, unitDataLen);
offset += 4;
mdat.set(unitData, offset);
offset += unitDataLen;
mp4SampleLength += 4 + unitDataLen;
if (encrypted) {
if (unitDataLen <= 48 || (unit.type !== 1 && unit.type !== 5)) {
bytesClear += 4 + unitDataLen;
}
else {
let encryptedDataLen = unitDataLen - 32;
if (encryptedDataLen % 16 === 0) {
encryptedDataLen -= 16; // different than fMP4 encryption - TS always requires at least 1 clear byte at the end
}
subsamples.push([bytesClear + 36, encryptedDataLen]);
bytesClear = unitDataLen - 32 - encryptedDataLen;
}
}
}
if (bytesClear > 0) {
subsamples.push([bytesClear, 0]);
}
if (!isSafari) {
// expected sample duration is the Decoding Timestamp diff of consecutive samples
if (i < nbSamples - 1) {
mp4SampleDuration = inputSamples[i + 1].dts - avcSample.dts;
}
else {
const config = this.config, lastFrameDuration = avcSample.dts - inputSamples[i > 0 ? i - 1 : i].dts;
if (config.stretchShortVideoTrack) {
// In some cases, a segment's audio track duration may exceed the video track duration.
// Since we've already remuxed audio, and we know how long the audio track is, we look to
// see if the delta to the next segment is longer than the minimum of maxBufferHole and
// maxSeekHole. If so, playback would potentially get stuck, so we artificially inflate
// the duration of the last frame to minimize any potential gap between segments.
const maxBufferHole = config.maxBufferHole, maxSeekHole = config.maxSeekHole, gapTolerance = Math.floor(Math.min(maxBufferHole, maxSeekHole) * timeScale), deltaToFrameEnd = (audioTrackLength ? firstPTS + audioTrackLength * timeScale : this.nextAudioPts) - avcSample.pts;
if (deltaToFrameEnd > gapTolerance) {
// We subtract lastFrameDuration from deltaToFrameEnd to try to prevent any video
// frame overlap. maxBufferHole/maxSeekHole should be >> lastFrameDuration anyway.
mp4SampleDuration = deltaToFrameEnd - lastFrameDuration;
if (mp4SampleDuration < 0) {
mp4SampleDuration = lastFrameDuration;
}
this.logger.info(`It is approximately ${deltaToFrameEnd / 90} ms to the next segment; using duration ${mp4SampleDuration / 90} ms for the last video frame.`);
}
else {
mp4SampleDuration = lastFrameDuration;
}
}
else {
mp4SampleDuration = lastFrameDuration;
}
}
compositionTimeOffset = Math.round(avcSample.pts - avcSample.dts);
}
else {
compositionTimeOffset = Math.max(0, mp4SampleDuration * Math.round((avcSample.pts - avcSample.dts) / mp4SampleDuration));
}
if (isFiniteNumber(iframeDuration)) {
compositionTimeOffset = 0;
mp4SampleDuration = iframeDuration * timeScale;
}
outputSamples.push({
size: mp4SampleLength,
// constant duration
duration: mp4SampleDuration,
cts: compositionTimeOffset,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: avcSample.key ? 2 : 1,
isNonSync: avcSample.key ? 0 : 1,
paddingValue: 0,
},
keyTagInfo: avcSample.keyTagInfo,
subsamples: subsamples,
});
}
// next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
this.nextAvcDts = lastDTS + mp4SampleDuration;
this.isVideoContiguous = true;
if (outputSamples.length && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
const flags = outputSamples[0].flags;
// chrome workaround, mark first sample as being a Random Access Point to avoid sourcebuffer append issue
// https://code.google.com/p/chromium/issues/detail?id=229412
flags.dependsOn = 2;
flags.isNonSync = 0;
}
const moofSegment = {
sequenceNumber: track.parsingData.sequenceNumber++,
id: track.info.id,
type: track.type,
encrypted: track.info.encrypted,
samples: outputSamples,
defaultPerSampleIVSize: 0,
};
const moof = MP4.moof(firstDTS + this.config.audioPrimingDelay * timeScale, moofSegment);
track.parsingData.esSamples = [];
const fullSegment = new Uint8Array(moof.byteLength + mdat.byteLength);
fullSegment.set(moof);
fullSegment.set(mdat, moof.byteLength);
const type = 'video';
const data = {
data1: fullSegment,
startPTS: convertSecondsToTimestamp(firstPTS / timeScale, timeScale),
endPTS: convertSecondsToTimestamp((lastPTS + mp4SampleDuration) / timeScale, timeScale),
startDTS: convertSecondsToTimestamp(firstDTS / timeScale, timeScale),
endDTS: convertSecondsToTimestamp(this.nextAvcDts / timeScale, timeScale),
type,
dropped,
framesWithoutIDR: firstKeyframeIndex,
firstKeyframePts: convertSecondsToTimestamp(firstKeyframePts / timeScale, timeScale),
};
return data;
}
remuxAudio(track, timeOffset, contiguous, accurateTimeOffset, keyTagInfo) {
const inputTimeScale = track.info.inputTimescale, mp4timeScale = track.info.timescale, scaleFactor = inputTimeScale / mp4timeScale, mp4SampleDuration = track.config.segmentCodec === 'aac' ? 1024 : track.config.segmentCodec === 'mp3' ? 1152 : 1536, inputSampleDuration = mp4SampleDuration * scaleFactor, rawMPEG = track.config.segmentCodec === 'mp3' && this.typeSupported.mpeg, outputSamples = [], encrypted = track.info.encrypted, timeOffsetMpegTS = this._initPTS + timeOffset * inputTimeScale;
let view, offset = rawMPEG ? 0 : 8, audioSample, mp4Sample, unit, mdat, moof, firstPTS, firstDTS, lastDTS, pts, dts, fillFrame, newStamp, nextAudioPts;
const bu = new BitstreamUtils();
const inputSamples = track.parsingData.esSamples;
// for audio samples, also consider consecutive fragments as being contiguous (even if a level switch occurs),
// for sake of clarity:
// consecutive fragments are frags with
// - less than 100ms gaps between new time offset (if accurate) and next expected PTS OR
// - less than 20 audio frames distance
// contiguous fragments are consecutive fragments from same quality level (same level, new SN = old SN + 1)
// this helps ensuring audio continuity
// and this also avoids audio glitches/cut when switching quality, or reporting wrong duration on first audio frame
nextAudioPts = this.nextAudioPts;
contiguous =
contiguous ||
(inputSamples.length &&
nextAudioPts &&
((accurateTimeOffset && Math.abs(timeOffsetMpegTS - nextAudioPts) < 9000) || Math.abs(normalizePts(inputSamples[0].pts - nextAudioPts, timeOffsetMpegTS)) < 20 * inputSampleDuration));
if (!contiguous) {
// if fragments are not contiguous, let's use sample
nextAudioPts = normalizePts(inputSamples[0].pts, this._initPTS);
}
// compute normalized PTS
inputSamples.forEach(function (sample) {
sample.pts = sample.dts = normalizePts(sample.pts, nextAudioPts);
});
// If the audio track is missing samples, the frames seem to get "left-shifted" within the
// resulting mp4 segment, causing sync issues and leaving gaps at the end of the audio segment.
// In an effort to prevent this from happening, we inject frames here where there are gaps.
// When possible, we inject a silent frame; when that's not possible, we duplicate the last
// frame.
// only inject/drop audio frames in case time offset is accurate
if (accurateTimeOffset && track.config.segmentCodec === 'aac') {
for (let i = 0, nextPts = nextAudioPts; i < inputSamples.length;) {
// First, let's see how far off this frame is from where we expect it to be
const sample = inputSamples[i];
pts = sample.pts;
const delta = pts - nextPts;
const duration = Math.abs((1000 * delta) / inputTimeScale);
// If we're overlapping by more than a duration, drop this sample
if (delta <= -inputSampleDuration) {
this.logger.warn(`Dropping 1 audio frame @ ${(nextPts / inputTimeScale).toFixed(3)}s due to ${duration} ms overlap.`);
inputSamples.splice(i, 1);
track.parsingData.len -= sample.unit.length;
// Don't touch nextPtsNorm or i
// Insert missing frames if:
// 1: We're more than one frame away
// 2: Not more than MAX_SILENT_FRAME_DURATION away
// 3: currentTime (aka nextPtsNorm) is not 0
}
else if (delta >= inputSampleDuration && duration < MAX_SILENT_FRAME_DURATION && nextPts) {
const missing = Math.round(delta / inputSampleDuration);
this.logger.warn(`Injecting ${missing} audio frame @ ${(nextPts / inputTimeScale).toFixed(3)}s due to ${Math.round((1000 * delta) / inputTimeScale)} ms gap.`);
for (let j = 0; j < missing; j++) {
newStamp = Math.max(nextPts, 0);
fillFrame = getSilentFrame(track.config.codec, track.config.channelCount);
if (!fillFrame) {
this.logger.warn('Unable to get silent frame for given audio codec; duplicating last frame instead.');
fillFrame = sample.unit.subarray(0);
}
inputSamples.splice(i, 0, { unit: fillFrame, pts: newStamp, dts: newStamp, keyTagInfo: keyTagInfo });
track.parsingData.len += fillFrame.length;
nextPts += inputSampleDuration;
i += 1;
}
// Adjust sample to next expected pts
sample.pts = sample.dts = nextPts;
nextPts += inputSampleDuration;
i += 1;
// Otherwise, just adjust pts
}
else {
nextPts += inputSampleDuration;
if (i === 0) {
sample.pts = sample.dts = nextAudioPts;
}
else {
sample.pts = sample.dts = inputSamples[i - 1].pts + inputSampleDuration;
}
i += 1;
}
}
}
for (let j = 0, nbSamples = inputSamples.length; j < nbSamples; j++) {
audioSample = inputSamples[j];
unit = audioSample.unit;
pts = audioSample.pts;
dts = audioSample.dts;
// if not first sample
if (lastDTS !== undefined) {
mp4Sample.duration = Math.round((dts - lastDTS) / scaleFactor);
}
else {
const delta = Math.round((1000 * (pts - nextAudioPts)) / inputTimeScale);
let numMissingFrames = 0;
// if fragment are contiguous, detect hole/overlapping between fragments
// contiguous fragments are consecutive fragments from same quality level (same level, new SN = old SN + 1)
if (contiguous && track.config.segmentCodec === 'aac') {
// log delta
if (delta) {
if (delta > 0 && delta < MAX_SILENT_FRAME_DURATION) {
numMissingFrames = Math.round((pts - nextAudioPts) / inputSampleDuration);
this.logger.info(`${delta} ms hole between AAC samples detected,filling it`);
if (numMissingFrames > 0) {
fillFrame = getSilentFrame(track.config.codec, track.config.channelCount);
if (!fillFrame) {
fillFrame = unit.subarray(0);
}
track.parsingData.len += numMissingFrames * fillFrame.length;
}
// if we have frame overlap, overlapping for more than half a frame duraion
}
else if (delta < -12) {
// drop overlapping audio frames... browser will deal with it
this.logger.info(`drop overlapping AAC sample, expected/parsed/delta:${(nextAudioPts / inputTimeScale).toFixed(3)}s/${(pts / inputTimeScale).toFixed(3)}s/${-delta}ms`);
track.parsingData.len -= unit.byteLength;
continue;
}
// set PTS/DTS to expected PTS/DTS
pts = dts = nextAudioPts;
}
}
// remember first PTS of our audioSamples, ensure value is positive
firstPTS = Math.max(0, pts);
firstDTS = Math.max(0, dts);
if (track.parsingData.len > 0) {
/* concatenate the audio data and construct the mdat in place
(need 8 more bytes to fill length and mdat type) */
const mdatSize = rawMPEG ? track.parsingData.len : track.parsingData.len + 8;
try {
mdat = new Uint8Array(mdatSize);
}
catch (err) {
const payload = new RemuxAllocError(false, `fail allocating audio mdat ${mdatSize}`, ErrorResponses.FailedToAllocateAudioMdat, mdatSize);
this.observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return;
}
if (!rawMPEG) {
view = new DataView(mdat.buffer);
view.setUint32(0, mdatSize);
mdat.set(MP4.types.mdat, 4);
}
}
else {
// no audio samples
return;
}
for (let i = 0; i < numMissingFrames; i++) {
newStamp = pts - (numMissingFrames - i) * inputSampleDuration;
fillFrame = getSilentFrame(track.config.codec, track.config.channelCount);
if (!fillFrame) {
this.logger.warn('Unable to get silent frame for given audio codec; duplicating this frame instead.');
fillFrame = unit.subarray(0);
}
mdat.set(fillFrame, offset);
offset += fillFrame.byteLength;
mp4Sample = {
size: fillFrame.byteLength,
cts: 0,
duration: 1024,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: 1,
paddingValue: 0,
isNonSync: 0,
},
keyTagInfo: audioSample.keyTagInfo,
subsamples: encrypted ? [[fillFrame.byteLength, 0]] : [],
};
outputSamples.push(mp4Sample);
}
}
mdat.set(unit, offset);
const unitLen = unit.byteLength;
offset += unitLen;
const subsamples = [];
if (encrypted) {
if (track.config.segmentCodec === 'ec3') {
let bytesSeen = 0;
// for ec3, a protected block is a single sync frame; the sample may have one or more sync frames
while (bytesSeen < unit.byteLength) {
const frameLength = (bu.bsReadAndUpdate(unit, { byteOffset: bytesSeen + 2, usedBits: 5 }, 11) + 1) * 2;
bytesSeen += frameLength;
const clearBytes = Math.min(frameLength, 16); // 16 bytes in the clear
subsamples.push([clearBytes, frameLength - clearBytes]);
}
}
else {
const clearBytes = Math.min(unitLen, 16); // both aac and ac3 have 16 bytes in the clear
subsamples.push([clearBytes, unitLen - clearBytes]);
}
}
mp4Sample = {
size: unitLen,
cts: 0,
duration: 0,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: 1,
paddingValue: 0,
isNonSync: 0,
},
keyTagInfo: audioSample.keyTagInfo,
subsamples: subsamples,
};
outputSamples.push(mp4Sample);
lastDTS = dts;
}
let lastSampleDuration = 0;
const nbSamples = outputSamples.length;
// set last sample duration as being identical to previous sample
if (nbSamples >= 2) {
lastSampleDuration = outputSamples[nbSamples - 2].duration;
mp4Sample.duration = lastSampleDuration;
}
if (nbSamples) {
// next audio sample PTS should be equal to last sample PTS + duration
this.nextAudioPts = pts + scaleFactor * lastSampleDuration;
track.parsingData.len = 0;
if (rawMPEG) {
moof = new Uint8Array();
}
else {
const moofSegment = {
sequenceNumber: track.parsingData.sequenceNumber++,
id: track.info.id,
type: track.type,
encrypted: track.info.encrypted,
samples: outputSamples,
defaultPerSampleIVSize: 0,
};
moof = MP4.moof((firstDTS + this.config.audioPrimingDelay * inputTimeScale) / scaleFactor, moofSegment);
}
const fullSegment = new Uint8Array(moof.byteLength + mdat.byteLength);
fullSegment.set(moof);
fullSegment.set(mdat, moof.byteLength);
track.parsingData.esSamples = [];
const audioData = {
data1: fullSegment,
startPTS: convertSecondsToTimestamp(firstPTS / inputTimeScale, inputTimeScale),
endPTS: convertSecondsToTimestamp(this.nextAudioPts / inputTimeScale, inputTimeScale),
startDTS: convertSecondsToTimestamp(firstDTS / inputTimeScale, inputTimeScale),
endDTS: convertSecondsToTimestamp((dts + scaleFactor * lastSampleDuration) / inputTimeScale, inputTimeScale),
type: 'audio',
};
return audioData;
}
return null;
}
remuxEmptyAudio(track, timeOffset, contiguous, accurateTimeOffset, videoData, keyTagInfo) {
const inputTimeScale = track.info.inputTimescale, mp4timeScale = track.config.samplerate ? track.config.samplerate : inputTimeScale, scaleFactor = inputTimeScale / mp4timeScale, nextAudioPts = this.nextAudioPts,
// sync with video's timestamp
startDTS = (nextAudioPts !== undefined ? nextAudioPts : convertTimestampToSeconds(videoData.startDTS) * inputTimeScale) + this._initDTS, endDTS = convertTimestampToSeconds(videoData.endDTS) * inputTimeScale + this._initDTS,
// one sample's duration value
sampleDuration = 1024, frameDuration = scaleFactor * sampleDuration,
// samples count of this segment's duration
nbSamples = Math.ceil((endDTS - startDTS) / frameDuration),
// silent frame
silentFrame = getSilentFrame(track.config.codec, track.config.channelCount);
this.logger.warn('remux empty Audio');
// Can't remux if we can't generate a silent frame...
if (!silentFrame) {
this.logger.error('Unable to remuxEmptyAudio since we were unable to get a silent frame for given audio codec!');
return null;
}
const samples = [];
for (let i = 0; i < nbSamples; i++) {
const stamp = startDTS + i * frameDuration;
samples.push({ unit: silentFrame, pts: stamp, dts: stamp, keyTagInfo: keyTagInfo });
track.parsingData.len += silentFrame.length;
}
track.parsingData.esSamples = samples;
return this.remuxAudio(track, timeOffset, contiguous, accurateTimeOffset, keyTagInfo);
}
remuxID3(track, parsingData) {
const length = track.id3Samples.length;
let sample;
const inputTimeScale = track.inputTimescale;
// consume samples
if (length) {
for (let index = 0; index < length; index++) {
sample = track.id3Samples[index];
// setting id3 pts, dts to relative time
sample.pts = sample.pts / inputTimeScale;
sample.dts = sample.dts / inputTimeScale;
}
parsingData.id3Samples = track.id3Samples;
}
track.id3Samples = [];
}
remuxText(track, parsingData) {
track.captionSamples.sort(function (a, b) {
return a.pts - b.pts;
});
const length = track.captionSamples.length;
let sample;
const inputTimeScale = track.inputTimescale;
// consume samples
if (length) {
for (let index = 0; index < length; index++) {
sample = track.captionSamples[index];
// setting text pts, dts to relative time
sample.pts = sample.pts / inputTimeScale;
}
if (!parsingData.captionData) {
parsingData.captionData = {};
}
parsingData.captionData.ts = track.captionSamples;
}
track.captionSamples = [];
}
}
function normalizePts(value, reference) {
let offset;
if (reference === undefined) {
return value;
}
if (reference < value) {
// - 2^33
offset = -8589934592;
}
else {
// + 2^33
offset = 8589934592;
}
/* PTS is 33bit (from 0 to 2^33 -1)
if diff between value and reference is bigger than half of the amplitude (2^32) then it means that
PTS looping occured. fill the gap */
while (Math.abs(value - reference) > 4294967296) {
value += offset;
}
return value;
}
function getVideoStartPts(videoSamples) {
const startPTS = videoSamples.reduce((minPTS, sample) => {
const delta = sample.pts - minPTS;
if (delta < -4294967296) {
// 2^32, see normalizePts for reasoning, but we're hitting a rollover here, and we don't want that to impact the timeOffset calculation
return normalizePts(minPTS, sample.pts);
}
else if (delta > 0) {
return minPTS;
}
else {
return sample.pts;
}
}, videoSamples[0].pts);
return startPTS;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function tryStringify (o) {
try { return JSON.stringify(o) } catch(e) { return '"[Circular]"' }
}
var quickFormatUnescaped = format$1;
function format$1(f, args, opts) {
var ss = (opts && opts.stringify) || tryStringify;
var offset = 1;
if (typeof f === 'object' && f !== null) {
var len = args.length + offset;
if (len === 1) return f
var objects = new Array(len);
objects[0] = ss(f);
for (var index = 1; index < len; index++) {
objects[index] = ss(args[index]);
}
return objects.join(' ')
}
if (typeof f !== 'string') {
return f
}
var argLen = args.length;
if (argLen === 0) return f
var str = '';
var a = 1 - offset;
var lastPos = -1;
var flen = (f && f.length) || 0;
for (var i = 0; i < flen;) {
if (f.charCodeAt(i) === 37 && i + 1 < flen) {
lastPos = lastPos > -1 ? lastPos : 0;
switch (f.charCodeAt(i + 1)) {
case 100: // 'd'
if (a >= argLen)
break
if (lastPos < i)
str += f.slice(lastPos, i);
if (args[a] == null) break
str += Number(args[a]);
lastPos = i = i + 2;
break
case 79: // 'O'
case 111: // 'o'
case 106: // 'j'
if (a >= argLen)
break
if (lastPos < i)
str += f.slice(lastPos, i);
if (args[a] === undefined) break
var type = typeof args[a];
if (type === 'string') {
str += '\'' + args[a] + '\'';
lastPos = i + 2;
i++;
break
}
if (type === 'function') {
str += args[a].name || '';
lastPos = i + 2;
i++;
break
}
str += ss(args[a]);
lastPos = i + 2;
i++;
break
case 115: // 's'
if (a >= argLen)
break
if (lastPos < i)
str += f.slice(lastPos, i);
str += String(args[a]);
lastPos = i + 2;
i++;
break
case 37: // '%'
if (lastPos < i)
str += f.slice(lastPos, i);
str += '%';
lastPos = i + 2;
i++;
break
}
++a;
}
++i;
}
if (lastPos === -1)
return f
else if (lastPos < flen) {
str += f.slice(lastPos);
}
return str
}
const format = quickFormatUnescaped;
var browser = pino;
const _console = pfGlobalThisOrFallback().console || {};
const stdSerializers = {
mapHttpRequest: mock,
mapHttpResponse: mock,
wrapRequestSerializer: passthrough,
wrapResponseSerializer: passthrough,
wrapErrorSerializer: passthrough,
req: mock,
res: mock,
err: asErrValue
};
function shouldSerialize (serialize, serializers) {
if (Array.isArray(serialize)) {
const hasToFilter = serialize.filter(function (k) {
return k !== '!stdSerializers.err'
});
return hasToFilter
} else if (serialize === true) {
return Object.keys(serializers)
}
return false
}
function pino (opts) {
opts = opts || {};
opts.browser = opts.browser || {};
const transmit = opts.browser.transmit;
if (transmit && typeof transmit.send !== 'function') { throw Error('pino: transmit option must have a send function') }
const proto = opts.browser.write || _console;
if (opts.browser.write) opts.browser.asObject = true;
const serializers = opts.serializers || {};
const serialize = shouldSerialize(opts.browser.serialize, serializers);
let stdErrSerialize = opts.browser.serialize;
if (
Array.isArray(opts.browser.serialize) &&
opts.browser.serialize.indexOf('!stdSerializers.err') > -1
) stdErrSerialize = false;
const levels = ['error', 'fatal', 'warn', 'info', 'debug', 'trace'];
if (typeof proto === 'function') {
proto.error = proto.fatal = proto.warn =
proto.info = proto.debug = proto.trace = proto;
}
if (opts.enabled === false) opts.level = 'silent';
const level = opts.level || 'info';
const logger = Object.create(proto);
if (!logger.log) logger.log = noop$2;
Object.defineProperty(logger, 'levelVal', {
get: getLevelVal
});
Object.defineProperty(logger, 'level', {
get: getLevel,
set: setLevel
});
const setOpts = {
transmit,
serialize,
asObject: opts.browser.asObject,
levels,
timestamp: getTimeFunction(opts)
};
logger.levels = pino.levels;
logger.level = level;
logger.setMaxListeners = logger.getMaxListeners =
logger.emit = logger.addListener = logger.on =
logger.prependListener = logger.once =
logger.prependOnceListener = logger.removeListener =
logger.removeAllListeners = logger.listeners =
logger.listenerCount = logger.eventNames =
logger.write = logger.flush = noop$2;
logger.serializers = serializers;
logger._serialize = serialize;
logger._stdErrSerialize = stdErrSerialize;
logger.child = child;
if (transmit) logger._logEvent = createLogEventShape();
function getLevelVal () {
return this.level === 'silent'
? Infinity
: this.levels.values[this.level]
}
function getLevel () {
return this._level
}
function setLevel (level) {
if (level !== 'silent' && !this.levels.values[level]) {
throw Error('unknown level ' + level)
}
this._level = level;
set$1(setOpts, logger, 'error', 'log'); // <-- must stay first
set$1(setOpts, logger, 'fatal', 'error');
set$1(setOpts, logger, 'warn', 'error');
set$1(setOpts, logger, 'info', 'log');
set$1(setOpts, logger, 'debug', 'log');
set$1(setOpts, logger, 'trace', 'log');
}
function child (bindings) {
if (!bindings) {
throw new Error('missing bindings for child Pino')
}
const bindingsSerializers = bindings.serializers;
if (serialize && bindingsSerializers) {
var childSerializers = Object.assign({}, serializers, bindingsSerializers);
var childSerialize = opts.browser.serialize === true
? Object.keys(childSerializers)
: serialize;
delete bindings.serializers;
applySerializers([bindings], childSerialize, childSerializers, this._stdErrSerialize);
}
function Child (parent) {
this._childLevel = (parent._childLevel | 0) + 1;
this.error = bind(parent, bindings, 'error');
this.fatal = bind(parent, bindings, 'fatal');
this.warn = bind(parent, bindings, 'warn');
this.info = bind(parent, bindings, 'info');
this.debug = bind(parent, bindings, 'debug');
this.trace = bind(parent, bindings, 'trace');
if (childSerializers) {
this.serializers = childSerializers;
this._serialize = childSerialize;
}
if (transmit) {
this._logEvent = createLogEventShape(
[].concat(parent._logEvent.bindings, bindings)
);
}
}
Child.prototype = this;
return new Child(this)
}
return logger
}
pino.levels = {
values: {
fatal: 60,
error: 50,
warn: 40,
info: 30,
debug: 20,
trace: 10
},
labels: {
10: 'trace',
20: 'debug',
30: 'info',
40: 'warn',
50: 'error',
60: 'fatal'
}
};
pino.stdSerializers = stdSerializers;
pino.stdTimeFunctions = Object.assign({}, { nullTime, epochTime, unixTime, isoTime });
function set$1 (opts, logger, level, fallback) {
const proto = Object.getPrototypeOf(logger);
logger[level] = logger.levelVal > logger.levels.values[level]
? noop$2
: (proto[level] ? proto[level] : (_console[level] || _console[fallback] || noop$2));
wrap(opts, logger, level);
}
function wrap (opts, logger, level) {
if (!opts.transmit && logger[level] === noop$2) return
logger[level] = (function (write) {
return function LOG () {
const ts = opts.timestamp();
const args = new Array(arguments.length);
const proto = (Object.getPrototypeOf && Object.getPrototypeOf(this) === _console) ? _console : this;
for (var i = 0; i < args.length; i++) args[i] = arguments[i];
if (opts.serialize && !opts.asObject) {
applySerializers(args, this._serialize, this.serializers, this._stdErrSerialize);
}
if (opts.asObject) write.call(proto, asObject(this, level, args, ts));
else write.apply(proto, args);
if (opts.transmit) {
const transmitLevel = opts.transmit.level || logger.level;
const transmitValue = pino.levels.values[transmitLevel];
const methodValue = pino.levels.values[level];
if (methodValue < transmitValue) return
transmit(this, {
ts,
methodLevel: level,
methodValue,
transmitLevel,
transmitValue: pino.levels.values[opts.transmit.level || logger.level],
send: opts.transmit.send,
val: logger.levelVal
}, args);
}
}
})(logger[level]);
}
function asObject (logger, level, args, ts) {
if (logger._serialize) applySerializers(args, logger._serialize, logger.serializers, logger._stdErrSerialize);
const argsCloned = args.slice();
let msg = argsCloned[0];
const o = {};
if (ts) {
o.time = ts;
}
o.level = pino.levels.values[level];
let lvl = (logger._childLevel | 0) + 1;
if (lvl < 1) lvl = 1;
// deliberate, catching objects, arrays
if (msg !== null && typeof msg === 'object') {
while (lvl-- && typeof argsCloned[0] === 'object') {
Object.assign(o, argsCloned.shift());
}
msg = argsCloned.length ? format(argsCloned.shift(), argsCloned) : undefined;
} else if (typeof msg === 'string') msg = format(argsCloned.shift(), argsCloned);
if (msg !== undefined) o.msg = msg;
return o
}
function applySerializers (args, serialize, serializers, stdErrSerialize) {
for (const i in args) {
if (stdErrSerialize && args[i] instanceof Error) {
args[i] = pino.stdSerializers.err(args[i]);
} else if (typeof args[i] === 'object' && !Array.isArray(args[i])) {
for (const k in args[i]) {
if (serialize && serialize.indexOf(k) > -1 && k in serializers) {
args[i][k] = serializers[k](args[i][k]);
}
}
}
}
}
function bind (parent, bindings, level) {
return function () {
try{
const args = new Array(1 + arguments.length);
args[0] = bindings;
for (var i = 1; i < args.length; i++) {
args[i] = arguments[i - 1];
}
return parent[level].apply(this, args)}
catch(e){
}
}
}
function transmit (logger, opts, args) {
const send = opts.send;
const ts = opts.ts;
const methodLevel = opts.methodLevel;
const methodValue = opts.methodValue;
const val = opts.val;
const bindings = logger._logEvent.bindings;
applySerializers(
args,
logger._serialize || Object.keys(logger.serializers),
logger.serializers,
logger._stdErrSerialize === undefined ? true : logger._stdErrSerialize
);
logger._logEvent.ts = ts;
logger._logEvent.messages = args.filter(function (arg) {
// bindings can only be objects, so reference equality check via indexOf is fine
return bindings.indexOf(arg) === -1
});
logger._logEvent.level.label = methodLevel;
logger._logEvent.level.value = methodValue;
send(methodLevel, logger._logEvent, val);
logger._logEvent = createLogEventShape(bindings);
}
function createLogEventShape (bindings) {
return {
ts: 0,
messages: [],
bindings: bindings || [],
level: { label: '', value: 0 }
}
}
function asErrValue (err) {
const obj = {
type: err.constructor.name,
msg: err.message,
stack: err.stack
};
for (const key in err) {
if (obj[key] === undefined) {
obj[key] = err[key];
}
}
return obj
}
function getTimeFunction (opts) {
if (typeof opts.timestamp === 'function') {
return opts.timestamp
}
if (opts.timestamp === false) {
return nullTime
}
return epochTime
}
function mock () { return {} }
function passthrough (a) { return a }
function noop$2 () {}
function nullTime () { return false }
function epochTime () { return Date.now() }
function unixTime () { return Math.round(Date.now() / 1000.0) }
function isoTime () { return new Date(Date.now()).toISOString() } // using Date.now() for testability
/* eslint-disable */
/* istanbul ignore next */
function pfGlobalThisOrFallback () {
function defd (o) { return typeof o !== 'undefined' && o }
try {
if (typeof globalThis !== 'undefined') return globalThis
Object.defineProperty(Object.prototype, 'globalThis', {
get: function () {
delete Object.prototype.globalThis;
return (this.globalThis = this)
},
configurable: true
});
return globalThis
} catch (e) {
return defd(self) || defd(window) || defd(this) || {}
}
}
let LoggerSingleton;
function addQELevel(options = {}) {
return Object.assign(Object.assign({}, options), { customLevels: Object.assign(Object.assign({}, (options.customLevels || {})), { qe: 35 }) });
}
const setupLoggerSingleton = (sessionId, name, options = {}, stream) => {
if (!LoggerSingleton || LoggerSingleton.sessionId !== sessionId) {
LoggerSingleton = browser(addQELevel(options)).child({ sessionId, name: name });
LoggerSingleton.qe = (msg) => LoggerSingleton.info(msg);
LoggerSingleton.sessionId = sessionId;
}
else {
LoggerSingleton.warn('Logger Singleton already setup, returning existing singleton');
}
return LoggerSingleton;
};
/**
* Get the configuration for the Pino logger
*
* @param {object} config - Configuration that overrides/extends the defaults set by this function
* @return {object}
*/
function getLoggerConfig(config = {}) {
const { consoleOverride } = config;
return Object.assign({ name: 'hls', timestamp: !config.sendLogs ? browser.stdTimeFunctions.isoTime : browser.stdTimeFunctions.epochTime, browser: {
asObject: true,
serialize: true,
transmit: {
send: (level, logEvent) => {
if (config.sendLogs && logEvent) {
config.sendLogs(level, logEvent); // Custom send function
}
},
},
write: {
debug: consoleWriteFn.bind(null, logFn(consoleOverride || console, 'debug'), 'debug'),
info: consoleWriteFn.bind(null, logFn(consoleOverride || console, 'info'), 'info'),
warn: consoleWriteFn.bind(null, logFn(consoleOverride || console, 'warn'), 'warn'),
error: consoleWriteFn.bind(null, logFn(consoleOverride || console, 'error'), 'error'),
fatal: consoleWriteFn.bind(null, logFn(consoleOverride || console, 'error'), 'fatal'),
},
} }, config);
}
const noop$1 = () => { };
function logFn(consoleObj, consoleLevel) {
consoleObj = consoleLevel in consoleObj ? consoleObj : console;
const logFn = consoleObj[consoleLevel] || consoleObj.log;
if (logFn) {
return logFn.bind(consoleObj);
}
return noop$1;
}
function consoleWriteFn(method, logLevel, o) {
const { time, sessionId, critical, name, msg } = o;
let logData = '';
if ('data' in o) {
try {
const keys = [];
const refs = [];
logData = JSON.stringify(o.data, (key, value) => {
if (typeof value === 'object' && value !== null) {
const circularRefIndex = refs.indexOf(value);
if (circularRefIndex !== -1) {
return `[Circular object reference: '${keys[circularRefIndex]}']`;
}
keys.push(key);
refs.push(value);
}
return value;
});
}
catch (e) {
logData = `Log serialization error: "${e}"`;
}
}
method(`${getCustomLocaleTimeString(time)}| [SessionID: ${sessionId}] | [${logLevel}] >${critical ? ' [QE Critical]' : ''} [${name}] ${msg ? msg : ''} ${logData}`);
}
/**
* Returns local date and time with millisecond precision and timezone identifier
*/
function getCustomLocaleTimeString(isoDateTime) {
const date = new Date(isoDateTime);
const off = date.getTimezoneOffset();
const hrs = pad(Math.floor(Math.abs(off) / 60));
const min = pad(Math.abs(off) % 60);
let tz = off <= 0 ? 'UTC+' + hrs : 'UTC-' + hrs;
tz = min ? tz + ':' + min : tz;
return (date.getFullYear() + '-' +
pad(date.getMonth() + 1) + '-' +
pad(date.getDate()) + ' ' +
pad(date.getHours()) + ':' +
pad(date.getMinutes()) + ':' +
pad(date.getSeconds()) + '.' +
(date.getMilliseconds() / 1000).toFixed(3).slice(2, 5) + ' ' +
tz);
}
/** Print Helpers **/
function pad(number) {
if (number < 10) {
return '0' + number;
}
return number.toString();
}
/**
* getLogger get the logger singleton defined in hls.ts
*
* Usage:
* getLogger().info({ name: "yourModuleName" }, 'msg to log');
* if you do not provide { name: "yourModuleName" }, log line will have 'name: "hls"'. A default name
*/
const getLogger = () => {
if (!LoggerSingleton) {
LoggerSingleton = browser(addQELevel()).child({ name: 'hls' });
LoggerSingleton.qe = (msg) => LoggerSingleton.info(msg);
LoggerSingleton.warn('getLogger called without hls object instantiated, returning a logger that is not configured');
}
return LoggerSingleton;
};
const MuxerHelper = {
bin2str(buffer) {
return String.fromCharCode.apply(null, Array.from(buffer));
},
readUint16(buffer, offset) {
const val = (buffer[offset] << 8) | buffer[offset + 1];
return val < 0 ? 65536 + val : val;
},
readSint32(buffer, offset) {
const val = (buffer[offset] << 24) | (buffer[offset + 1] << 16) | (buffer[offset + 2] << 8) | buffer[offset + 3];
return val;
},
readUint32(buffer, offset) {
const val = MuxerHelper.readSint32(buffer, offset);
return val < 0 ? 4294967296 + val : val;
},
writeUint32(buffer, offset, value) {
buffer[offset] = value >> 24;
buffer[offset + 1] = (value >> 16) & 255;
buffer[offset + 2] = (value >> 8) & 255;
buffer[offset + 3] = value & 255;
},
readUint64(buffer, offset) {
let result = MuxerHelper.readUint32(buffer, offset);
result *= Math.pow(2, 32);
result += MuxerHelper.readUint32(buffer, offset + 4);
return result;
},
writeUint64(buffer, offset, value) {
const UINT32_MAX = Math.pow(2, 32) - 1;
const upper = Math.floor(value / (UINT32_MAX + 1));
const lower = Math.floor(value % (UINT32_MAX + 1));
MuxerHelper.writeUint32(buffer, offset, upper);
MuxerHelper.writeUint32(buffer, offset + 4, lower);
},
// Find the data for a box specified by its path
findBox(data, path) {
let results = [];
let ix;
let size;
let type;
let end;
let subresults;
if (!path.length) {
// short-circuit the search for empty paths
return [];
}
for (ix = 0; ix < data.byteLength;) {
size = MuxerHelper.readUint32(data, ix);
type = MuxerHelper.bin2str(data.subarray(ix + 4, ix + 8));
end = size > 1 ? ix + 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(ix + 8, end));
}
else {
// recursively search for the next box along the path
subresults = MuxerHelper.findBox(data.subarray(ix + 8, end), path.slice(1));
if (subresults.length) {
results = results.concat(subresults);
}
}
}
ix = end;
}
// we've finished searching all of data
return results;
},
// Find the offset and data for a box specified by its path
findBoxWithOffset(data, offset, path, walkedPath) {
let results = [];
let ix;
let size;
let type;
let end;
let subresults;
if (!path.length) {
// short-circuit the search for empty paths
return [];
}
for (ix = 0; ix < data.byteLength;) {
size = MuxerHelper.readUint32(data, ix);
type = MuxerHelper.bin2str(data.subarray(ix + 4, ix + 8));
end = size > 1 ? ix + size : data.byteLength;
if (type === path[0]) {
if (walkedPath) {
walkedPath.push({ offset: ix + offset, type: type, size: size });
}
if (path.length === 1) {
// this is the end of the path and we've found the box we were
// looking for
results.push({ offset: ix + offset, type: type, data: data.subarray(ix + 8, end), boxSize: size, walkedPath: walkedPath ? walkedPath.slice(0) : undefined });
}
else {
// recursively search for the next box along the path
subresults = MuxerHelper.findBoxWithOffset(data.subarray(ix + 8, end), ix + offset + 8, path.slice(1), walkedPath ? walkedPath.slice(0) : undefined);
if (subresults.length) {
results = results.concat(subresults);
walkedPath = walkedPath ? walkedPath.slice(0, -1) : undefined;
}
}
}
ix = end;
}
// we've finished searching all of data
return results;
},
};
/**
* Hex dumper class
*
*
*
*
*/
const Hex = {
hexDump: function (array, limit = Infinity) {
if (!array) {
return '';
}
const buffer = new Uint8Array(array);
let i, str = '';
for (i = 0; i < buffer.length && i < limit; i++) {
let h = buffer[i].toString(16);
if (h.length < 2) {
h = '0' + h;
}
str += h;
}
return str;
},
};
var Hex$1 = Hex;
const loggerName$d = { name: 'MP4EncryptionRemuxer' };
class MP4EncryptionRemuxer extends RemuxerBase {
constructor(observer, config, typeSupported, vendor, logger) {
super(observer, config, logger);
}
static _isCommonEncryptionInternal(decryptMethod) {
return Boolean(decryptMethod && !(decryptMethod === 'NONE' || decryptMethod === 'AES-128'));
}
static remuxInitSegment(initSegment, logger, keyTagInfo, sinfArray) {
if (!keyTagInfo) {
return initSegment;
}
let remuxedInitSegment = initSegment;
if (MP4EncryptionRemuxer._isCommonEncryptionInternal(keyTagInfo.method)) {
const keyId = keyTagInfo.keyId;
let isCbc2 = false;
const newTraks = []; // list of trak boxes
const traks = MuxerHelper.findBoxWithOffset(initSegment, 0, ['moov', 'trak']);
logger.info(loggerName$d, 'trying to patch map');
traks.forEach((trakTuple) => {
const trak = trakTuple.data;
let mediaType;
let encBoxChildrenOffset = 0;
const stsdTuple = MuxerHelper.findBoxWithOffset(trak, 0, ['mdia', 'minf', 'stbl', 'stsd'], [])[0];
// skip the sample entry count
const sampleEntries = stsdTuple.data.subarray(8);
let isAudio = true;
let encBoxes = MuxerHelper.findBoxWithOffset(sampleEntries, stsdTuple.offset + 16, ['enca']);
if (encBoxes.length === 0) {
isAudio = false;
encBoxes = MuxerHelper.findBoxWithOffset(sampleEntries, stsdTuple.offset + 16, ['encv']);
}
encBoxes.forEach((encBoxTuple) => {
let encBoxChildren = null;
let newTrak = null;
if (isAudio) {
// encrypted AudioSampleEntry - skip 28 bytes
encBoxChildren = encBoxTuple.data.subarray(28);
mediaType = 'audio';
encBoxChildrenOffset = stsdTuple.offset + 16 + 8 + 28;
}
else {
// encrypted VisualSampleEntry - skip 78 bytes
encBoxChildren = encBoxTuple.data.subarray(78);
mediaType = 'video';
encBoxChildrenOffset = stsdTuple.offset + 16 + 8 + 78;
}
if (encBoxChildren) {
const sinfTuples = MuxerHelper.findBoxWithOffset(encBoxChildren, encBoxChildrenOffset, ['sinf']);
sinfTuples.forEach((sinfTuple) => {
const sinf = sinfTuple.data;
const frma = MuxerHelper.findBox(sinf, ['frma'])[0];
const schm = MuxerHelper.findBox(sinf, ['schm'])[0];
if (!frma) {
logger.error(loggerName$d, 'missing frma box');
return;
}
else if (!schm) {
logger.error(loggerName$d, 'missing schm box');
return;
}
const scheme = MuxerHelper.bin2str(schm.subarray(4, 8));
const format = MuxerHelper.bin2str(frma.subarray(0, 4));
if (format === 'aac ') {
if (!MP4$1.types) {
MP4$1.init();
}
logger.info(loggerName$d, 'found frma with type \'aac \', patching to \'mp4a\'');
frma.set(MP4$1.types.mp4a, 0);
}
if (scheme === 'cbcs' || scheme === 'cenc') {
if (sinfArray) {
sinfArray.push(sinf); // used for unit tests until we get a more generic parser
}
const tenc = MuxerHelper.findBox(sinf, ['schi', 'tenc'])[0];
if (tenc) {
const kKeyIdOffset = 8; // keyID offset is always 8 within the tenc box
// Look for default key id:
const tencKeyId = tenc.subarray(kKeyIdOffset, kKeyIdOffset + 16);
logger.info(loggerName$d, `found 'tenc' patching map with keyId default:${Hex$1.hexDump(tencKeyId)}->${Hex$1.hexDump(keyId)}`);
tenc.set(keyId, kKeyIdOffset);
// we may not need to do this, but at some point we were authoring content with zeros for the IV
// chrome does use this value, so set it to be safe
const defaultIsProtected = tenc[6];
const defaultPerSampleIVSize = tenc[7];
if (defaultIsProtected === 1 && defaultPerSampleIVSize === 0) {
const defaultConstantIVSize = tenc[24];
if (defaultConstantIVSize > 0 && keyTagInfo.iv && defaultConstantIVSize === keyTagInfo.iv.length) {
logger.info(loggerName$d, 'patching iv for good measure');
tenc.set(keyTagInfo.iv, 25);
}
}
}
}
else if (scheme === 'cbc2') {
logger.info(loggerName$d, 'found \'cbc2\' scheme, converting to \'cbcs\'');
isCbc2 = true;
if (!MP4$1.types) {
MP4$1.init();
}
// create a sinf from the existing format and new scheme and scheme info boxes
const frmaTuple = MuxerHelper.findBoxWithOffset(sinf, 0, ['frma'])[0];
const newSchi = MP4$1.box(MP4$1.types.schi, MP4$1.tenc(keyTagInfo, mediaType));
const newSinf = MP4$1.box(MP4$1.types.sinf, sinf.subarray(frmaTuple.offset, frmaTuple.boxSize), MP4$1.schm(), newSchi);
// create a new track from the existing trak with the new sinf spliced in
newTrak = MP4$1.box(MP4$1.types.trak, trak.subarray(0, sinfTuple.offset), newSinf, trak.subarray(sinfTuple.offset + sinfTuple.boxSize));
const newTrackData = newTrak.subarray(8);
// need to update all the sizes down the box path in the new track
// we can re-use the offsets from the already parsed path since they're before the splice point
const sizeIncrease = newSinf.byteLength - sinfTuple.boxSize;
if (stsdTuple.walkedPath) {
stsdTuple.walkedPath.push({ type: 'stsd', offset: encBoxTuple.offset, size: encBoxTuple.boxSize }); // enc* offset is special
stsdTuple.walkedPath.forEach((step) => {
MuxerHelper.writeUint32(newTrackData, step.offset, step.size + sizeIncrease);
});
}
}
});
}
if (!newTrak) {
newTrak = initSegment.subarray(trakTuple.offset, trakTuple.offset + trakTuple.boxSize);
}
newTraks.push(newTrak);
});
const edtsTuple = MuxerHelper.findBoxWithOffset(trak, 0, ['edts'])[0];
if (edtsTuple) {
if (!MP4$1.types) {
MP4$1.init();
}
logger.info(loggerName$d, 'overwriting edts box');
trak.set(MP4$1.types.free, edtsTuple.offset + 4);
}
});
if (isCbc2) {
const cbcsInitSegment = MP4EncryptionRemuxer.remuxCbc2InitSegment(initSegment, newTraks, logger);
remuxedInitSegment = cbcsInitSegment ? cbcsInitSegment : initSegment;
}
}
return remuxedInitSegment;
}
/**
* @param traksToAppend Array of trak boxes to replace traks in initSegment with.
*/
static remuxCbc2InitSegment(initSegment, traksToAppend, logger) {
const ftypTuple = MuxerHelper.findBoxWithOffset(initSegment, 0, ['ftyp'])[0];
if (!ftypTuple) {
logger.error(loggerName$d, 'no ftyp found');
return;
}
const moovTuple = MuxerHelper.findBoxWithOffset(initSegment, ftypTuple.boxSize, ['moov'])[0];
let moovChildren = [];
let ix = 0;
while (ix < moovTuple.data.byteLength) {
const size = MuxerHelper.readUint32(moovTuple.data, ix);
const type = MuxerHelper.bin2str(moovTuple.data.subarray(ix + 4, ix + 8));
const end = size > 1 ? ix + size : moovTuple.data.byteLength;
switch (type) {
case 'trak': {
if (traksToAppend) {
// Just append these here where the traks used to be
moovChildren = moovChildren.concat(traksToAppend);
traksToAppend = undefined;
}
break;
}
default:
moovChildren.push(moovTuple.data.subarray(ix, end));
break;
}
ix = end;
}
const newMoov = MP4$1.box(MP4$1.types.moov, ...moovChildren);
const newInitSegment = new Uint8Array(ftypTuple.boxSize + newMoov.byteLength);
newInitSegment.set(initSegment.subarray(0, ftypTuple.boxSize));
newInitSegment.set(newMoov, ftypTuple.boxSize);
return newInitSegment;
}
static remuxOverflowSegment(data, logger) {
if (!MP4$1.types) {
MP4$1.init();
}
const tfdts = MuxerHelper.findBoxWithOffset(data, 0, ['moof', 'traf', 'tfdt'], []);
let newDataSize = data.byteLength;
let newData;
// total all tfdts in segment so we know the size increase (can have multiple moofs in a segment)
tfdts.forEach((tfdt) => {
// increase the data size by 4 bytes for each 32 bit tfdt
if (tfdt.data[0] === 0) {
newDataSize += 4;
}
});
if (newDataSize > data.byteLength) {
newData = new Uint8Array(newDataSize);
let newOffset = 0;
let dataBoxIndex = 0;
while (dataBoxIndex < data.byteLength) {
const size = MuxerHelper.readUint32(data, dataBoxIndex);
const type = MuxerHelper.bin2str(data.subarray(dataBoxIndex + 4, dataBoxIndex + 8));
const dataBoxEnd = size > 1 ? dataBoxIndex + size : data.byteLength;
if (type === 'moof') {
const newMoof = MP4EncryptionRemuxer.remuxOverflowMoof(data.subarray(dataBoxIndex + 8, dataBoxEnd));
newData.set(newMoof, newOffset);
newOffset += newMoof.byteLength;
}
else {
newData.set(data.subarray(dataBoxIndex, dataBoxEnd), newOffset);
newOffset += size;
}
dataBoxIndex = dataBoxEnd;
}
}
else {
logger.warn(loggerName$d, 'no increase in size');
}
return newData ? newData : data;
}
static remuxOverflowMoof(moofData) {
let moofIndex = 0;
const moofChildren = [];
while (moofIndex < moofData.byteLength) {
const size = MuxerHelper.readUint32(moofData, moofIndex);
const type = MuxerHelper.bin2str(moofData.subarray(moofIndex + 4, moofIndex + 8));
if (type === 'traf') {
const newTraf = MP4EncryptionRemuxer.remuxOverflowTraf(moofData.subarray(moofIndex + 8, moofIndex + size));
moofChildren.push(newTraf);
}
else {
moofChildren.push(moofData.subarray(moofIndex, moofIndex + size));
}
moofIndex = size > 1 ? moofIndex + size : moofData.byteLength;
}
const newMoof = MP4$1.box(MP4$1.types.moof, ...moofChildren);
const sizeDiff = newMoof.byteLength - moofData.byteLength - 8; // moofData doesn't include header, so subtract 8
const truns = MuxerHelper.findBoxWithOffset(newMoof, 0, ['moof', 'traf', 'trun'], []);
truns.forEach((trun) => {
const dataOffsetPresent = (trun.data[3] & 1) !== 0;
if (dataOffsetPresent) {
const dataOffset = MuxerHelper.readUint32(trun.data, 8);
MuxerHelper.writeUint32(trun.data, 8, dataOffset + sizeDiff);
}
});
const saios = MuxerHelper.findBoxWithOffset(newMoof, 0, ['moof', 'traf', 'saio'], []);
saios.forEach((saio) => {
const version = saio.data[0] & 1;
let dataOffset = 4;
if (saio.data[3] & 1) {
// aux info type and parameter
dataOffset += 8;
}
const ec = MuxerHelper.readUint32(saio.data, dataOffset);
dataOffset += 4;
if (!version) {
for (let i = 0; i < ec; i++) {
const value = MuxerHelper.readUint32(saio.data, dataOffset);
MuxerHelper.writeUint32(saio.data, dataOffset, value + sizeDiff);
dataOffset += 4;
}
}
else {
for (let i = 0; i < ec; i++) {
const value = MuxerHelper.readUint64(saio.data, dataOffset);
MuxerHelper.writeUint64(saio.data, dataOffset, value + sizeDiff);
dataOffset += 8;
}
}
});
return newMoof;
}
static remuxOverflowTraf(trafData) {
let trafIndex = 0;
const trafChildren = [];
while (trafIndex < trafData.byteLength) {
const size = MuxerHelper.readUint32(trafData, trafIndex);
const type = MuxerHelper.bin2str(trafData.subarray(trafIndex + 4, trafIndex + 8));
if (type === 'tfdt' && trafData[trafIndex + 8] === 0) {
const tfdtValue = MuxerHelper.readUint32(trafData, trafIndex + 12);
const newTfdt = MP4$1.box(MP4$1.types.tfdt, new Uint8Array([
1,
0,
0,
0,
0,
0,
0,
0,
tfdtValue >> 24,
(tfdtValue >> 16) & 255,
(tfdtValue >> 8) & 255,
tfdtValue & 255,
]));
trafChildren.push(newTfdt);
}
else {
trafChildren.push(trafData.subarray(trafIndex, trafIndex + size));
}
trafIndex = size > 1 ? trafIndex + size : trafData.byteLength;
}
const newTraf = MP4$1.box(MP4$1.types.traf, ...trafChildren);
return newTraf;
}
remuxText(track, parsingData) {
track.captionSamples.sort(function (a, b) {
return a.pts - b.pts;
});
const length = track.captionSamples.length;
if (length) {
if (!parsingData.captionData) {
parsingData.captionData = {};
}
parsingData.captionData.mp4 = track.captionSamples;
}
track.captionSamples = [];
}
remuxIFrame(startDTS, videoTrack, audioTrack, iframeDuration, track) {
if (!videoTrack.samples || !videoTrack.samples.length || !videoTrack.samples[0].data) {
return null;
}
let streamType;
const moof = MP4$1.moof(startDTS * videoTrack.timescale, videoTrack);
const iframeSegment = new Uint8Array(moof.byteLength + videoTrack.samples[0].data.byteLength + 8);
iframeSegment.set(moof);
MuxerHelper.writeUint32(iframeSegment, moof.byteLength, videoTrack.samples[0].data.byteLength + 8);
iframeSegment.set(MP4$1.types.mdat, moof.byteLength + 4);
iframeSegment.set(videoTrack.samples[0].data, moof.byteLength + 8);
videoTrack.sequenceNumber++;
const videoTimescale = videoTrack.timescale;
const videoEndTs = convertSecondsToTimestamp(startDTS + iframeDuration, videoTimescale);
const videoStartTs = convertSecondsToTimestamp(startDTS, videoTimescale);
let endTs;
let audioSegment;
if (audioTrack) {
streamType = 'audiovideo';
audioTrack.sequenceNumber = videoTrack.sequenceNumber;
videoTrack.sequenceNumber++;
audioSegment = SilentAudio.getSegment(audioTrack, audioTrack.sequenceNumber, startDTS * audioTrack.info.timescale, iframeDuration);
endTs = determineMaxTimestamp(audioSegment.endTs, videoEndTs);
}
else {
streamType = 'video';
endTs = videoEndTs;
}
const data = {
data1: iframeSegment,
data2: audioSegment === null || audioSegment === void 0 ? void 0 : audioSegment.silentFragData,
startPTS: videoStartTs,
startDTS: videoStartTs,
endPTS: endTs,
endDTS: endTs,
type: streamType,
dropped: 0,
track,
};
// send the data
this.observer.trigger(DemuxerEvent.FRAG_PARSING_DATA, data);
// notify end of parsing
this.observer.trigger(DemuxerEvent.FRAG_PARSED);
}
remuxEmsgAndRawData(audioDuration, hasAudio, videoDuration, hasVideo, textTrack, id3Track, timeOffset, timescale, rawFragment, track) {
let streamType;
if (hasAudio && hasVideo) {
streamType = 'audiovideo';
}
else if (hasAudio) {
streamType = 'audio';
}
else if (hasVideo) {
streamType = 'video';
}
const fragDuration = Math.max(videoDuration, audioDuration);
const data = {
data1: rawFragment,
track,
startPTS: convertSecondsToTimestamp(timeOffset, timescale),
startDTS: convertSecondsToTimestamp(timeOffset, timescale),
endPTS: undefined,
endDTS: undefined,
type: streamType,
dropped: 0,
};
if (fragDuration) {
data.endPTS = convertSecondsToTimestamp(timeOffset + fragDuration, timescale);
data.endDTS = convertSecondsToTimestamp(timeOffset + fragDuration, timescale);
}
if (textTrack && textTrack.captionSamples.length) {
this.remuxText(textTrack, data);
}
if (id3Track && id3Track.id3Samples.length > 0) {
this.remuxID3(id3Track, data);
}
this.observer.trigger(DemuxerEvent.FRAG_PARSING_DATA, data);
this.observer.trigger(DemuxerEvent.FRAG_PARSED);
return data;
}
remuxID3(track, parsingData) {
let sample;
const length = track.id3Samples.length;
const PTSOffset = 10;
const DTSOffset = 10;
if (length) {
for (let index = 0; index < length; index++) {
sample = track.id3Samples[index];
// emsg pts is aligned with media content and have 10s offset to avoid negative time in audio samples
sample.pts = sample.pts - PTSOffset;
sample.dts = sample.dts - DTSOffset;
}
parsingData.id3Samples = [...track.id3Samples];
}
track.id3Samples = [];
}
}
const UINT32_MAX = Math.pow(2, 32) - 1;
const MAX_UPPER_32_VALUE = Math.pow(2, 20) - 1; // 52 bit integer float precision
const LARGE_TIMESCALE = 1000000;
const loggerName$c = { name: 'MP4Demuxer' };
class MP4Demuxer extends DemuxerBase {
constructor(observer, remuxer, config, typeSupported = undefined, logger) {
super(observer, remuxer, config, {}, logger);
this.mp4Remuxer = remuxer;
// may need a little headroom for priming audio samples, so shift everything by the max value we expect
// that should be 2112 audio samples at 22050 hz
this.audioPrimingDelay = config.audioPrimingDelay;
if (this.audioPrimingDelay > 0) {
this.logger.info(loggerName$c, `using audioPrimingDelay of ${this.audioPrimingDelay}`);
}
}
resetTimeStamp(initPTS90k) {
if (isFiniteNumber(initPTS90k)) {
if (this.initData.audio && !this.initData.video) {
// if this is an audio only track go ahead and convert initPTS to the sample rate to avoid cumulative rounding errors
this.initPtsTs = { baseTime: Math.round((initPTS90k * this.initData.audio.timescale) / 90000), timescale: this.initData.audio.timescale };
}
else {
this.initPtsTs = { baseTime: initPTS90k, timescale: 90000 };
}
}
else {
this.initPtsTs = undefined;
}
}
static isHEVCFlavor(codec) {
if (!codec) {
return false;
}
const delimit = codec.indexOf('.');
const baseCodec = delimit < 0 ? codec : codec.substring(0, delimit);
return (baseCodec === 'hvc1' ||
baseCodec === 'hev1' /*
baseCodec === 'phvc' ||
baseCodec === 'ehvc' ||
baseCodec === 'zhvc' ||*/
||
baseCodec === 'chvc' ||
baseCodec === 'qhvc' ||
baseCodec === 'qhev' ||
baseCodec === 'muxa' ||
// Dolby Vision
baseCodec === 'dvh1' ||
baseCodec === 'dvhe' /*
baseCodec === 'ddh1' ||
baseCodec === 'zdh1' ||*/
||
baseCodec === 'cdh1' ||
baseCodec === 'qdh1' ||
baseCodec === 'qdhe');
}
resetInitSegment(initSegment, duration, keyTagInfo) {
// jshint unused:false
this._silentAudioTrack = undefined;
if (initSegment && initSegment.byteLength) {
const remuxedInitSegment = MP4EncryptionRemuxer.remuxInitSegment(initSegment, this.logger, keyTagInfo);
const initData = (this.initData = MP4Demuxer.parseInitSegment(remuxedInitSegment));
let track;
if (initData.foundLargeTimescale) {
this.logger.warn(loggerName$c, 'large timescale found, will check for 32 bit tfdts');
}
const parsedAudioCodec = initData.audioCodec;
const parsedVideoCodec = initData.videoCodec;
if (initData.audio && initData.video) {
track = { type: 'audiovideo', container: 'video/mp4', codec: parsedAudioCodec + ',' + parsedVideoCodec, initSegment: remuxedInitSegment };
}
else {
if (initData.audio && parsedAudioCodec) {
track = { type: 'audio', container: 'audio/mp4', codec: parsedAudioCodec, initSegment: remuxedInitSegment };
}
if (initData.video && parsedVideoCodec) {
track = { type: 'video', container: 'video/mp4', codec: parsedVideoCodec, initSegment: remuxedInitSegment };
}
}
if (initData.video) {
// needed to generate moofs for iframe mode frames
// we need the track data to create a new moof for muxed iframe mode
const parsedVideoTrack = initData.video;
const trakData = initSegment.subarray(parsedVideoTrack.trakOffset, parsedVideoTrack.trakOffset + parsedVideoTrack.trakSize);
this._videoTrack = Object.assign(Object.assign({}, parsedVideoTrack), { info: { id: parsedVideoTrack.id, timescale: parsedVideoTrack.timescale, duration }, trakData: trakData, sequenceNumber: 0, samples: [] });
this.trySEICaptions = !MediaUtil.isVP09(parsedVideoCodec);
this._captionTrack = Object.assign(Object.assign({}, initData.caption), { sequenceNumber: 0, captionSamples: [] });
this.logger.info(loggerName$c, 'assume SEI closed caption exists');
}
if (initData.audio && parsedAudioCodec) {
// only need id and codec for silent audio generation
this._audioTrack = Object.assign({}, initData.audio);
}
if (initData.caption) {
// use clcp track if present
this.trySEICaptions = false;
this.logger.info(loggerName$c, `use clcp track id ${initData.caption.id}`);
this._captionTrack = Object.assign(Object.assign({}, initData.caption), { sequenceNumber: 0, captionSamples: [] });
}
this.remuxedInitDataTrack = track;
const eventData = { track };
this.observer.trigger(DemuxerEvent.FRAG_PARSING_INIT_SEGMENT, eventData);
}
}
static probe(data, logger) {
// ensure we find a moof box in the first 128kB
return MuxerHelper.findBox(data.subarray(0, Math.min(data.length, 512000)), ['moof']).length > 0;
}
static parseHvcC(data) {
let codecConfig;
if (data) {
const version = data[0];
if (version === 1) {
const tmpByte = data[1];
codecConfig = {
profileSpace: tmpByte >> 6,
tierFlag: (tmpByte & 32) >> 5 ? 'H' : 'L',
profileIDC: tmpByte & 31,
profileCompat: MuxerHelper.readUint32(data, 2),
constraintIndicator: data.subarray(6, 12),
levelIDC: data[12],
};
}
else {
getLogger().warn(loggerName$c, `Unhandled version ${version} in hvcC box`);
}
}
else {
getLogger().warn(loggerName$c, 'No hvcC box');
}
return codecConfig;
}
static hvcCToCodecString(baseCodecType, codecConfig) {
const profileSpaceStr = codecConfig.profileSpace ? String.fromCharCode(codecConfig.profileSpace + 'A' - 1) : '';
const codecString = baseCodecType + '.' + profileSpaceStr + codecConfig.profileIDC + '.' + codecConfig.profileCompat.toString(16).toUpperCase() + '.' + codecConfig.tierFlag + codecConfig.levelIDC;
// append constraint indicators, ignoring trailing zero bytes
let constraintIndicatorStr = '';
for (let i = codecConfig.constraintIndicator.length - 1; i >= 0; --i) {
const byte = codecConfig.constraintIndicator[i];
if (!(byte === 0 && constraintIndicatorStr === '')) {
const encodedByte = byte.toString(16).toUpperCase();
constraintIndicatorStr = '.' + (constraintIndicatorStr === '' ? encodedByte : encodedByte + constraintIndicatorStr);
}
}
return codecString + constraintIndicatorStr;
}
static parseDvcC(data) {
let codecConfig;
if (data) {
codecConfig = {
versionMajor: data[0],
versionMinor: data[1],
profile: (data[2] >> 1) & 127,
level: ((data[2] << 5) & 32) | ((data[3] >> 3) & 31),
};
}
else {
getLogger().warn(loggerName$c, 'No dvcC box');
}
return codecConfig;
}
static dvcCToCodecString(baseCodecType, codecConfig) {
const profileStr = MP4Demuxer.checkAndAddLeadingZero(codecConfig.profile);
const levelStr = MP4Demuxer.checkAndAddLeadingZero(codecConfig.level);
return baseCodecType + '.' + profileStr + '.' + levelStr;
}
static parseVpcC(data) {
let codecConfig;
if (data) {
codecConfig = {
profile: data[4],
level: data[5],
bitDepth: (data[6] >> 4) & 15,
};
}
else {
getLogger().warn(loggerName$c, 'No vpcC box');
}
return codecConfig;
}
static vpcCToCodecString(baseCodecType, codecConfig) {
const profileStr = MP4Demuxer.checkAndAddLeadingZero(codecConfig.profile);
const levelStr = MP4Demuxer.checkAndAddLeadingZero(codecConfig.level);
const subsampling = MP4Demuxer.checkAndAddLeadingZero(codecConfig.bitDepth);
return baseCodecType + '.' + profileStr + '.' + levelStr + '.' + subsampling;
}
static checkAndAddLeadingZero(num) {
return (num < 10 ? '0' : '') + num;
}
/**
* Parses an MP4 initialization segment and extracts stream type and
* 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
* moov > trak > mdia > hdlr
* ```
* @param init {Uint8Array} the bytes of the init segment
* @return {object} a hash of track type to timescale values or null if
* the init segment is malformed.
*/
static parseInitSegment(initSegment) {
const result = { foundLargeTimescale: false, tracksById: {} };
const traksTuple = MuxerHelper.findBoxWithOffset(initSegment, 0, ['moov', 'trak']);
traksTuple.forEach((trakTuple) => {
const trak = trakTuple.data;
const tkhd = MuxerHelper.findBox(trak, ['tkhd'])[0];
if (tkhd) {
let version = tkhd[0];
const index = version === 0 ? 12 : 20;
const id = MuxerHelper.readUint32(tkhd, index);
const mdhd = MuxerHelper.findBox(trak, ['mdia', 'mdhd'])[0];
if (mdhd) {
version = mdhd[0];
let timescaleIndex = version === 0 ? 12 : 20;
const timescale = MuxerHelper.readUint32(mdhd, timescaleIndex);
timescaleIndex += 4;
if (timescale >= LARGE_TIMESCALE) {
result.foundLargeTimescale = true;
}
const duration = version === 0 ? MuxerHelper.readUint32(mdhd, timescaleIndex) : 0; // TODO: read 64 bit? Maybe we don't care, but TS sets this value and we're trying to share track data
const hdlr = MuxerHelper.findBox(trak, ['mdia', 'hdlr'])[0];
if (hdlr) {
const hdlrType = MuxerHelper.bin2str(hdlr.subarray(8, 12));
const hdlrToTypeMap = { soun: 'audio', vide: 'video', clcp: 'caption' };
const type = hdlrToTypeMap[hdlrType] || hdlrType;
if (type) {
// extract codec info. TODO : parse codec details to be able to build MIME type
const codecBoxes = MuxerHelper.findBox(trak, ['mdia', 'minf', 'stbl', 'stsd']);
let codecType;
if (codecBoxes.length) {
const codecBox = codecBoxes[0];
codecType = MuxerHelper.bin2str(codecBox.subarray(12, 16));
getLogger().info(loggerName$c, `MP4Demuxer:${type}:${codecType} found`);
const stsdData = MP4Demuxer.parseStsd(codecBox);
let newTrack;
if (type === 'caption') {
const captionTrack = Object.assign({ id, type, timescale, duration, isTimingTrack: false, sequenceNumber: 0, captionSamples: [] }, stsdData);
result.caption = captionTrack;
newTrack = captionTrack;
}
else {
const mediaTrack = Object.assign({ id,
type,
timescale,
duration, isTimingTrack: true, trakOffset: trakTuple.offset, trakSize: trakTuple.boxSize, sequenceNumber: 0, samples: [], fragmentDuration: 0 }, stsdData);
if (type === 'video') {
result.video = mediaTrack;
result.videoCodec = mediaTrack.codec;
}
else {
result.audio = mediaTrack;
result.audioCodec = mediaTrack.codec;
}
newTrack = mediaTrack;
}
result.tracksById[id] = newTrack;
}
}
}
}
}
});
const trexTuple = MuxerHelper.findBoxWithOffset(initSegment, 0, ['moov', 'mvex', 'trex']);
trexTuple.forEach((trexTuple) => {
const trex = trexTuple.data;
const id = MuxerHelper.readUint32(trex, 4);
const defaultSampleSize = MuxerHelper.readUint32(trex, 16);
result.tracksById[id].defaultSampleSize = defaultSampleSize;
});
return result;
}
static parseStsd(stsd) {
let defaultPerSampleIVSize;
let codec;
// skip the sample entry count
const sampleEntries = stsd.subarray(8);
let baseCodecType = MuxerHelper.bin2str(sampleEntries.subarray(4, 8));
let encBox = null;
let encBoxChildren = null;
if (baseCodecType === 'enca') {
// audio
encBox = MuxerHelper.findBox(sampleEntries, ['enca'])[0];
encBoxChildren = encBox.subarray(28);
}
else if (baseCodecType === 'encv') {
// video
encBox = MuxerHelper.findBox(sampleEntries, ['encv'])[0];
// FIXME: May have optional clap and pasp atoms after 78 bytes
encBoxChildren = encBox.subarray(78);
}
const encrypted = !!encBoxChildren;
defaultPerSampleIVSize = 0;
if (encBoxChildren) {
const sinfs = MuxerHelper.findBox(encBoxChildren, ['sinf']);
sinfs.forEach((sinf) => {
const schm = MuxerHelper.findBox(sinf, ['schm'])[0];
if (schm) {
const scheme = MuxerHelper.bin2str(schm.subarray(4, 8));
if (scheme === 'cbcs' || scheme === 'cenc') {
const frma = MuxerHelper.findBox(sinf, ['frma'])[0];
if (frma) {
// for encrypted content baseCodecType will be in frma
baseCodecType = MuxerHelper.bin2str(frma);
}
const tenc = MuxerHelper.findBox(sinf, ['schi', 'tenc'])[0];
if (tenc) {
defaultPerSampleIVSize = tenc[7];
}
}
}
});
}
let codecConfig;
const sampleEntriesEnd = sampleEntries.subarray(86);
switch (baseCodecType) {
case 'mp4a':
codec = 'mp4a.40.5';
break;
case 'ac-3':
case 'ec-3':
case 'alac':
case 'fLaC':
codec = baseCodecType;
break;
case 'avc1':
case 'avc3':
codec = baseCodecType + '.640028';
break;
case 'hvc1':
case 'hev1':
const hvcCBox = MuxerHelper.findBox(sampleEntriesEnd, ['hvcC'])[0]; // There may be other atoms right after sampleEntries
codecConfig = MP4Demuxer.parseHvcC(hvcCBox);
codec = codecConfig ? MP4Demuxer.hvcCToCodecString(baseCodecType, codecConfig) : baseCodecType + '.2.4.H150.B0';
break;
case 'dvh1':
case 'dvhe':
const dvcCBox = MuxerHelper.findBox(sampleEntriesEnd, ['dvcC'])[0];
codecConfig = MP4Demuxer.parseDvcC(dvcCBox);
codec = codecConfig ? MP4Demuxer.dvcCToCodecString(baseCodecType, codecConfig) : baseCodecType + '.05.01';
break;
case 'c608':
codec = baseCodecType;
break;
case 'vp09':
const vpcCBox = MuxerHelper.findBox(sampleEntriesEnd, ['vpcC'])[0];
codecConfig = MP4Demuxer.parseVpcC(vpcCBox);
codec = MP4Demuxer.vpcCToCodecString(baseCodecType, codecConfig);
break;
default:
codec = baseCodecType;
break;
}
return { codec, encrypted, defaultPerSampleIVSize };
}
static has32BitTfdts(fragment) {
const tfdts = MuxerHelper.findBox(fragment, ['moof', 'traf', 'tfdt']);
let found = false;
tfdts.forEach((tfdt) => {
if (tfdt[0] === 0) {
// version 0 means 32 bit tfdt
found = true;
}
});
return found;
}
/**
* 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
*/
static getStartDtsTs(initData, fragment) {
// we need info from two childrend of each track fragment box
const trafs = MuxerHelper.findBox(fragment, ['moof', 'traf']);
let minTime = Number.MAX_SAFE_INTEGER;
let result;
// determine the start times for each track
trafs.map(function (traf) {
return MuxerHelper.findBox(traf, ['tfhd']).forEach((tfhd) => {
// get the track id from the tfhd
const id = MuxerHelper.readUint32(tfhd, 4);
const parsedTrak = initData.tracksById[id];
let timescale;
if (!parsedTrak) {
return;
}
if (parsedTrak.isTimingTrack) {
// assume a 90kHz clock if no timescale was specified
timescale = parsedTrak.timescale || 90000;
}
else {
return Infinity; // Should just not be considered for time calculation
}
// get the base media decode time from the tfdt
const tfdtTimes = MuxerHelper.findBox(traf, ['tfdt']).map(function (tfdt) {
let result;
const version = tfdt[0];
result = MuxerHelper.readUint32(tfdt, 4);
if (version === 1) {
if (result > MAX_UPPER_32_VALUE) {
getLogger().warn(loggerName$c, `Value larger than can be represented by float for upper 32 bits ${result}`);
}
result *= Math.pow(2, 32);
result += MuxerHelper.readUint32(tfdt, 8);
}
return result;
});
const baseTime = tfdtTimes.length > 0 ? tfdtTimes[0] : Infinity;
if (isFinite(baseTime) && baseTime / timescale < minTime) {
minTime = baseTime / timescale;
result = { baseTime, timescale };
}
});
});
return result;
}
static offsetStartDTS(initData, fragment, timeOffsetTs, audioPrimingDelaySec) {
MuxerHelper.findBox(fragment, ['moof', 'traf']).map(function (traf) {
return MuxerHelper.findBox(traf, ['tfhd']).map(function (tfhd) {
// get the track id from the tfhd
const id = MuxerHelper.readUint32(tfhd, 4);
const parsedTrak = initData.tracksById[id];
if (!parsedTrak) {
return;
}
// assume a 90kHz clock if no timescale was specified
const timescale = parsedTrak.timescale || 90000;
const audioPrimingOffset = parsedTrak.type === 'caption' ? 0 : audioPrimingDelaySec;
// get the base media decode time from the tfdt
MuxerHelper.findBox(traf, ['tfdt']).map(function (tfdt) {
const version = tfdt[0];
const mediaType = parsedTrak.type;
if (version === 0) {
const baseMediaDecodeTime = MuxerHelper.readUint32(tfdt, 4);
let offsetBaseMediaDecodeTime = baseMediaDecodeTime - Math.round((timeOffsetTs.baseTime * timescale) / timeOffsetTs.timescale);
// need to make sure video doesn't go negative after timestampOffset is applied
if (mediaType === 'video' && offsetBaseMediaDecodeTime < 0) {
getLogger().warn(loggerName$c, `video tdft would have gone negative by ${offsetBaseMediaDecodeTime / timescale} seconds`);
offsetBaseMediaDecodeTime = 0;
}
offsetBaseMediaDecodeTime = offsetBaseMediaDecodeTime + Math.round(audioPrimingOffset * timescale);
offsetBaseMediaDecodeTime = Math.max(offsetBaseMediaDecodeTime, 0);
MuxerHelper.writeUint32(tfdt, 4, offsetBaseMediaDecodeTime);
}
else {
const baseMediaDecodeTime = MuxerHelper.readUint32(tfdt, 4);
if (baseMediaDecodeTime > MAX_UPPER_32_VALUE) {
getLogger().error(loggerName$c, `baseMediaDecodeTime larger than can be represented by float for upper 32 bits ${baseMediaDecodeTime}`);
}
let offsetBaseMediaDecodeTime = baseMediaDecodeTime;
offsetBaseMediaDecodeTime *= Math.pow(2, 32);
offsetBaseMediaDecodeTime += MuxerHelper.readUint32(tfdt, 8);
offsetBaseMediaDecodeTime = offsetBaseMediaDecodeTime - Math.round((timeOffsetTs.baseTime * timescale) / timeOffsetTs.timescale);
// need to make sure video doesn't go negative after timestampOffset is applied
if (mediaType === 'video' && offsetBaseMediaDecodeTime < 0) {
getLogger().warn(loggerName$c, `video tdft would have gone negative by ${offsetBaseMediaDecodeTime / timescale} seconds`);
offsetBaseMediaDecodeTime = 0;
}
offsetBaseMediaDecodeTime = offsetBaseMediaDecodeTime + Math.round(audioPrimingOffset * timescale);
offsetBaseMediaDecodeTime = Math.max(offsetBaseMediaDecodeTime, 0);
const upper = Math.floor(offsetBaseMediaDecodeTime / (UINT32_MAX + 1));
const lower = Math.floor(offsetBaseMediaDecodeTime % (UINT32_MAX + 1));
MuxerHelper.writeUint32(tfdt, 4, upper);
MuxerHelper.writeUint32(tfdt, 8, lower);
}
});
});
});
}
static writeStartDTS(initData, fragmentData, startDTS) {
MuxerHelper.findBox(fragmentData, ['moof', 'traf']).map(function (traf) {
return MuxerHelper.findBox(traf, ['tfhd']).map(function (tfhd) {
// get the track id from the tfhd
const id = MuxerHelper.readUint32(tfhd, 4);
const parsedTrak = initData.tracksById[id];
if (!parsedTrak) {
return;
}
// assume a 90kHz clock if no timescale was specified
const timescale = parsedTrak.timescale || 90000;
// everything is in decimal seconds, so we need round timestamps or they'll get truncated and lose accuracy
const roundedStartDTS = Math.round(startDTS * timescale) / timescale;
if (Math.abs(roundedStartDTS - startDTS) > 0.01) {
// the rounding errors should be very small since we snap durations to the timescale
getLogger().warn(loggerName$c, `[iframes] large rounding error when adjusting timestamps, startDTS: ${startDTS}, roundedStartDTS: ${roundedStartDTS}`);
}
// get the base media decode time from the tfdt
MuxerHelper.findBox(traf, ['tfdt']).map(function (tfdt) {
const version = tfdt[0];
if (version === 0) {
MuxerHelper.writeUint32(tfdt, 4, roundedStartDTS * timescale);
}
else {
let baseMediaDecodeTime = roundedStartDTS * timescale;
baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0);
const upper = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1));
const lower = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1));
MuxerHelper.writeUint32(tfdt, 4, upper);
MuxerHelper.writeUint32(tfdt, 8, lower);
}
});
});
});
}
static parseSAIO(saio) {
let subsampleOffset = 0;
let offset = 0;
const version = saio[0];
const flags = MuxerHelper.readUint32(saio, 0) & 16777215;
offset += 4;
if ((flags & 1) !== 0) {
offset += 8;
}
const entryCount = MuxerHelper.readUint32(saio, offset) & 16777215;
if (entryCount === 1) {
offset += 4;
subsampleOffset = MuxerHelper.readUint32(saio, offset);
if (version === 1) {
offset += 4;
subsampleOffset *= Math.pow(2, 32);
subsampleOffset += MuxerHelper.readUint32(saio, offset);
}
}
else {
getLogger().error(loggerName$c, `saio entry count error, count is: ${entryCount}`);
}
return subsampleOffset;
}
static parseSAIZ(saiz) {
let sampleSize = 0;
let offset = 0;
const flags = MuxerHelper.readUint32(saiz, 0) & 16777215;
offset += 4;
if ((flags & 1) !== 0) {
offset += 8;
}
sampleSize = saiz[offset];
offset++;
// let sampleCount = MP4Demuxer.readUint32(saiz, offset);
offset += 4; // just get the first sample
if (sampleSize === 0) {
sampleSize = saiz[offset];
}
return sampleSize;
}
static parseSubsample(perSampleIVSize, entry) {
const sampleAuxInfo = { subsamples: [] };
let offset = 0;
if (perSampleIVSize) {
sampleAuxInfo.iv = entry.subarray(0, perSampleIVSize);
offset += perSampleIVSize;
}
offset += 2; // skip entry length
// need at least 6 bytes to read a subsample entry
while (offset + 6 <= entry.byteLength) {
const bytesClear = MuxerHelper.readUint16(entry, offset);
offset += 2;
const bytesEncrypted = MuxerHelper.readUint32(entry, offset);
offset += 4;
sampleAuxInfo.subsamples.push([bytesClear, bytesEncrypted]);
}
return sampleAuxInfo;
}
static isSEIMessage(isHEVCFlavor, naluType) {
return isHEVCFlavor ? naluType === 39 || naluType === 40 : naluType === 6;
}
static parseCLCPSample(fragment, startSampleOffset, sampleSize) {
let sampleIndex = 0;
const samples = [];
let totalSize = 0;
while (sampleIndex < sampleSize) {
let sampleOffset = startSampleOffset + sampleIndex;
const cdatSize = MuxerHelper.readUint32(fragment, sampleOffset); // get actual cdat size
sampleOffset += 4;
const cdatType = MuxerHelper.bin2str(fragment.subarray(sampleOffset, sampleOffset + 4));
sampleOffset += 4;
if (cdatType === 'cdat') {
if (cdatSize !== sampleSize) {
getLogger().debug(loggerName$c, `clcp track: cdatSize ${cdatSize} @ offset ${sampleOffset}; sampleSize ${sampleSize}`);
}
const actualDataSize = cdatSize - 8;
const rawData = fragment.subarray(sampleOffset, sampleOffset + actualDataSize);
totalSize += actualDataSize;
samples.push(rawData);
sampleIndex += cdatSize; // actualDataSize + 8
}
else {
getLogger().debug(loggerName$c, `clcp track: unknown atom type ${cdatType}`);
break;
}
}
return { cdatList: samples, cdatTotalSize: totalSize };
}
// TODOs:
// * Parse cdt2 data
// * Handle 64-bit length in tfhd > baseDataOffset
static parseSamples(startDTS, fragment, track, iframeDuration, useSEICaptions, maxSamples) {
const timescale = track.timescale;
const trackId = track.id;
let pts = startDTS;
let parsedSampleCount = 0;
let sampleAuxInfo;
let isHEVCFlavor = false;
const moofs = MuxerHelper.findBoxWithOffset(fragment, 0, ['moof']);
moofs.map(function (moofTuple) {
const moof = moofTuple.data;
const moofOffset = moofTuple.offset;
const trafs = MuxerHelper.findBox(moof, ['traf']);
trafs.map(function (traf) {
// get the base media decode time from the tfdt
const baseTime = MuxerHelper.findBox(traf, ['tfdt']).map(function (tfdt) {
let result;
const version = tfdt[0];
result = MuxerHelper.readUint32(tfdt, 4);
if (version === 1) {
result *= Math.pow(2, 32);
result += MuxerHelper.readUint32(tfdt, 8);
}
return result / timescale;
})[0];
if (baseTime !== undefined) {
pts = baseTime;
}
return MuxerHelper.findBox(traf, ['tfhd']).map(function (tfhd) {
// tfhd default values
const id = MuxerHelper.readUint32(tfhd, 4);
const tfhdFlags = MuxerHelper.readUint32(tfhd, 0) & 16777215;
const baseDataOffsetPresent = (tfhdFlags & 1) !== 0;
const sampleDescriptionIndexPresent = (tfhdFlags & 2) !== 0;
const defaultSampleDurationPresent = (tfhdFlags & 8) !== 0;
let defaultSampleDuration = 0;
const defaultSampleSizePresent = (tfhdFlags & 16) !== 0;
let defaultSampleSize = 0;
const defaultSampleFlagsPresent = (tfhdFlags & 32) !== 0;
// let durationIsEmpty = (tfhdFlags & 0x010000) !== 0;
// let defaultBaseIsMoof = (tfhdFlags & 0x020000) !== 0;
let tfhdOffset = 8;
if (isFiniteNumber(track.defaultSampleSize)) {
defaultSampleSize = track.defaultSampleSize;
}
if (id === trackId) {
if (baseDataOffsetPresent) {
MuxerHelper.readUint32(tfhd, tfhdOffset); // Should be 64-bit
tfhdOffset += 4;
const mustBeZeroes = MuxerHelper.readUint32(tfhd, tfhdOffset);
tfhdOffset += 4;
if (mustBeZeroes !== 0) {
getLogger().info(loggerName$c, 'tfhd baseDataOffset has 64-bit value. Caption should be turned off');
}
}
if (sampleDescriptionIndexPresent) {
MuxerHelper.readUint32(tfhd, tfhdOffset);
tfhdOffset += 4;
}
if (defaultSampleDurationPresent) {
defaultSampleDuration = MuxerHelper.readUint32(tfhd, tfhdOffset);
tfhdOffset += 4;
}
if (defaultSampleSizePresent) {
defaultSampleSize = MuxerHelper.readUint32(tfhd, tfhdOffset);
tfhdOffset += 4;
}
if (defaultSampleFlagsPresent) {
MuxerHelper.readUint32(tfhd, tfhdOffset);
tfhdOffset += 4;
}
if (track.type === 'video') {
let subsampleOffset = 0, subsampleSize = 0;
// only use the first one
MuxerHelper.findBox(traf, ['saio']).map(function (saio) {
subsampleOffset = MP4Demuxer.parseSAIO(saio);
});
MuxerHelper.findBox(traf, ['saiz']).map(function (saiz) {
subsampleSize = MP4Demuxer.parseSAIZ(saiz);
});
if (subsampleOffset && subsampleSize) {
sampleAuxInfo = MP4Demuxer.parseSubsample(track.defaultPerSampleIVSize, fragment.subarray(subsampleOffset, subsampleOffset + subsampleSize));
}
isHEVCFlavor = MP4Demuxer.isHEVCFlavor(track.codec);
}
MuxerHelper.findBox(traf, ['trun']).map(function (trun) {
// trun specific values
const version = trun[0];
const flags = MuxerHelper.readUint32(trun, 0) & 16777215;
const dataOffsetPresent = (flags & 1) !== 0;
let dataOffset = 0;
const firstSampleFlagsPresent = (flags & 4) !== 0;
const sampleDurationPresent = (flags & 256) !== 0;
let sampleDuration = 0;
const sampleSizePresent = (flags & 512) !== 0;
let sampleSize = 0;
const sampleFlagsPresent = (flags & 1024) !== 0;
const sampleCompositionOffsetsPresent = (flags & 2048) !== 0;
let compositionOffset = 0;
const sampleCount = MuxerHelper.readUint32(trun, 4);
let trunOffset = 8; // past version, flags, and sample count
if (dataOffsetPresent) {
dataOffset = MuxerHelper.readUint32(trun, trunOffset);
trunOffset += 4;
}
if (firstSampleFlagsPresent) {
trunOffset += 4;
}
let sampleOffset = dataOffset + moofOffset;
for (let ix = 0; ix < sampleCount && (maxSamples < 0 || parsedSampleCount < maxSamples); ix++) {
if (sampleDurationPresent) {
sampleDuration = MuxerHelper.readUint32(trun, trunOffset);
trunOffset += 4;
}
else {
sampleDuration = defaultSampleDuration;
}
if (sampleSizePresent) {
sampleSize = MuxerHelper.readUint32(trun, trunOffset);
trunOffset += 4;
}
else {
sampleSize = defaultSampleSize;
}
if (sampleFlagsPresent) {
trunOffset += 4;
}
if (sampleCompositionOffsetsPresent) {
if (version === 0) {
compositionOffset = MuxerHelper.readUint32(trun, trunOffset);
}
else {
compositionOffset = MuxerHelper.readSint32(trun, trunOffset);
}
trunOffset += 4;
}
// TODO: make this more generic
if (track.type === 'video') {
if (!isFiniteNumber(iframeDuration)) {
// non iframe
track.fragmentDuration += sampleDuration;
if (useSEICaptions) {
let naluTotalSize = 0;
// hijacking sei parsing to get video duration
while (naluTotalSize < sampleSize) {
const naluSize = MuxerHelper.readUint32(fragment, sampleOffset);
sampleOffset += 4;
const naluType = fragment[sampleOffset] & 31;
if (!track.seiSamples) {
track.seiSamples = [];
}
if (MP4Demuxer.isSEIMessage(isHEVCFlavor, naluType)) {
const sampleData = fragment.subarray(sampleOffset, sampleOffset + naluSize);
track.seiSamples.push({ pts: pts + compositionOffset / timescale, type: naluType, data: sampleData, sampleOffset: sampleOffset, naluSize: naluSize });
}
sampleOffset += naluSize;
naluTotalSize += naluSize + 4;
}
}
}
else {
// iframe
track.samples.push({
data: fragment.subarray(sampleOffset, sampleOffset + sampleSize),
size: sampleSize,
duration: iframeDuration * timescale,
cts: 0,
flags: {
isLeading: 0,
isDependedOn: 0,
hasRedundancy: 0,
degradPrio: 0,
dependsOn: 2,
isNonSync: 0,
paddingValue: 0,
},
subsamples: sampleAuxInfo ? sampleAuxInfo.subsamples : [],
iv: sampleAuxInfo ? sampleAuxInfo.iv : undefined,
});
}
}
else if (track.type === 'audio') {
track.fragmentDuration += sampleDuration;
}
else if (track.type === 'caption') {
const { cdatList, cdatTotalSize } = MP4Demuxer.parseCLCPSample(fragment, sampleOffset, sampleSize);
sampleOffset += sampleSize;
if (cdatList.length) {
let cdatArray;
if (cdatList.length === 1) {
cdatArray = new Uint8Array(cdatList[0]);
}
else if (cdatList.length > 1) {
let offset = 0;
cdatArray = new Uint8Array(cdatTotalSize);
for (const arr of cdatList) {
cdatArray.set(arr, offset);
offset += arr.length;
}
}
track.captionSamples.push({ type: 3, pts: pts, bytes: cdatArray });
}
}
parsedSampleCount++;
pts += sampleDuration / timescale;
} // for ix
}); // trun map
} // if (id == trackId)
}); // tfhd map
}); // traf map
}); // moof map
}
static parseEmsg(data) {
const version = data[0];
let schemeIdUri = '';
let value = '';
let timeScale;
let presentationTimeDelta;
let presentationTime;
let eventDuration;
let id;
let offset = 0;
if (version === 0) {
while (MuxerHelper.bin2str(data.subarray(offset, offset + 1)) !== '\0') {
schemeIdUri += MuxerHelper.bin2str(data.subarray(offset, offset + 1));
offset += 1;
}
schemeIdUri += MuxerHelper.bin2str(data.subarray(offset, offset + 1));
offset += 1;
while (MuxerHelper.bin2str(data.subarray(offset, offset + 1)) !== '\0') {
value += MuxerHelper.bin2str(data.subarray(offset, offset + 1));
offset += 1;
}
value += MuxerHelper.bin2str(data.subarray(offset, offset + 1));
offset += 1;
timeScale = MuxerHelper.readUint32(data, 12);
presentationTimeDelta = MuxerHelper.readUint32(data, 16);
eventDuration = MuxerHelper.readUint32(data, 20);
id = MuxerHelper.readUint32(data, 24);
offset = 28;
}
else {
offset += 4;
timeScale = MuxerHelper.readUint32(data, offset);
offset += 4;
const leftPresentationTime = MuxerHelper.readUint32(data, offset);
offset += 4;
const rightPresentationTime = MuxerHelper.readUint32(data, offset);
offset += 4;
presentationTime = Math.pow(2, 32) * leftPresentationTime + rightPresentationTime;
if (!Number.isSafeInteger(presentationTime)) {
presentationTime = Number.MAX_SAFE_INTEGER;
getLogger().warn(loggerName$c, 'Presentation time exceeds safe integer limit and wrapped to max safe integer in parsing emsg box');
}
eventDuration = MuxerHelper.readUint32(data, offset);
offset += 4;
id = MuxerHelper.readUint32(data, offset);
offset += 4;
while (MuxerHelper.bin2str(data.subarray(offset, offset + 1)) !== '\0') {
schemeIdUri += MuxerHelper.bin2str(data.subarray(offset, offset + 1));
offset += 1;
}
schemeIdUri += MuxerHelper.bin2str(data.subarray(offset, offset + 1));
offset += 1;
while (MuxerHelper.bin2str(data.subarray(offset, offset + 1)) !== '\0') {
value += MuxerHelper.bin2str(data.subarray(offset, offset + 1));
offset += 1;
}
value += MuxerHelper.bin2str(data.subarray(offset, offset + 1));
offset += 1;
}
const payload = data.subarray(offset, data.byteLength);
return { schemeIdUri, value, timeScale, presentationTime, presentationTimeDelta, eventDuration, id, payload };
}
static extractID3PayloadCreateID3Track(emsgInfo, timeOffset, id3Track, logger) {
const id3 = new ID3$1(emsgInfo.payload, logger);
const data = new Uint8Array(emsgInfo.payload);
const length = data.byteLength;
let frameIndex = 0;
let offset = 0;
const pts = isFiniteNumber(emsgInfo.presentationTime) ? emsgInfo.presentationTime / emsgInfo.timeScale : timeOffset + emsgInfo.presentationTimeDelta / emsgInfo.timeScale;
if (!isFiniteNumber(pts)) {
getLogger().error(loggerName$c, 'No pts found in emsg info when extracting ID3 payload');
return;
}
const frameDuration = emsgInfo.eventDuration;
const header = data.subarray(0, 10);
const fileIdentifier = MuxerHelper.bin2str(header.subarray(offset, offset + 3));
offset += 3;
if (fileIdentifier !== 'ID3') {
getLogger().error(loggerName$c, 'No ID3 tag found when extracting ID3 payload');
}
// skip versions
offset += 2;
const flags = data.subarray(offset, offset + 1);
const extendedHeader = flags[0] & 64;
const footerPresent = flags[0] & 16;
offset += 1;
ID3$1.readSynchSafeUint32(data.subarray(offset, offset + 4));
offset += 4;
if (extendedHeader) {
const extHeaderSize = ID3$1.readSynchSafeUint32(data.subarray(offset, offset + 4));
offset += 4;
offset += extHeaderSize;
}
while (offset + 2 < length) {
let frameId = '';
frameId += MuxerHelper.bin2str(data.subarray(offset, offset + 4));
offset += 4;
const frameLength = ID3$1.readSynchSafeUint32(data.subarray(offset, offset + 4));
offset += 4;
const stamp = pts + frameIndex * frameDuration;
const id3Sample = { data: data, pts: stamp, dts: stamp, keyTagInfo: undefined, frames: id3.frames };
id3Track.id3Samples.push(id3Sample);
offset += frameLength;
frameIndex++;
if (footerPresent) {
const di3 = MuxerHelper.bin2str(data.subarray(offset, offset + 3));
if (di3 !== 'DI3') {
getLogger().error(loggerName$c, 'End should be DI3 if footer present in extracting ID3 payload');
}
offset += 3;
// skip remaining 7 bits
offset += 7;
}
}
if (offset + 2 === length) {
const padding = MuxerHelper.readUint16(data, offset);
if (padding !== 0) {
getLogger().warn(loggerName$c, 'Padding should be 0 when extracting ID3 payload');
}
}
}
/**
* @param data
* @param timeOffset The position in the media element corresponding to this fragment at rate 1
* @param contiguous Contiguous with previously appeneded fragment
* @param keyTagInfo Object describing information about the key that was used to encrypt data
* @param iframeMediaStart If remuxing for iframe, the time in media element to remux fragment to
* @param iframeDuration If remuxing for iframe, the duration to remux fragment to
*/
append(data, timeOffset, contiguous, accurateTimeOffset, keyTagInfo, iframeMediaStart, iframeDuration) {
let initData = this.initData;
let videoDuration = 0, audioDuration = 0;
let hasVideo = false, hasAudio = false;
if (typeof initData === 'undefined') {
this.resetInitSegment(data, 0);
initData = this.initData;
}
let initPtsTs = this.initPtsTs;
let startDtsTs;
if (!initPtsTs) {
startDtsTs = MP4Demuxer.getStartDtsTs(initData, data);
this.initPtsTs = initPtsTs = { baseTime: startDtsTs.baseTime - Math.round(timeOffset * startDtsTs.timescale), timescale: startDtsTs.timescale };
this.observer.trigger(DemuxerEvent.INIT_PTS_FOUND, { initPTS: initPtsTs });
}
if (initData.foundLargeTimescale && MP4Demuxer.has32BitTfdts(data) && !iframeDuration) {
data = MP4EncryptionRemuxer.remuxOverflowSegment(data, this.logger);
}
// Don't remux start DTS, will be adjusted in source buffer timestampOffset instead
startDtsTs = MP4Demuxer.getStartDtsTs(initData, data);
const emsgs = MuxerHelper.findBox(data, ['emsg']);
if (initData.video && initData.video.encrypted) {
// Check for 'senc' or 'saiz' && 'saio'
const trafs = MuxerHelper.findBox(data, ['moof', 'traf']);
const gotSubsamples = trafs.find(function (traf) {
return Boolean(MuxerHelper.findBox(traf, ['senc'])[0] || (MuxerHelper.findBox(traf, ['saiz'])[0] && MuxerHelper.findBox(traf, ['saio'])[0]));
});
if (!gotSubsamples) {
this.logger.warn(loggerName$c, `Missing subsample information for encrypted content codec=${initData.videoCodec}`);
}
}
if (iframeDuration) {
const timescale = this._videoTrack.timescale;
// snap the iframe durations so added the durations will result in timestamps that are always accurately representable when converted to uints
// we want to use ceil so durations aren't reduced, otherwise the same iframe could get chosen in the next round.
iframeDuration = Math.ceil(iframeDuration * timescale) / timescale;
// iframe timestamps are written directly, not offset, so we have to add the audioPrimingDelay since it'll
// still be shifted by the sourceBuffer.timestampOffset
const startDtsSec = (startDtsTs.baseTime + this.audioPrimingDelay * startDtsTs.timescale) / startDtsTs.timescale;
if (this._videoTrack && this._audioTrack && !this._silentAudioTrack) {
const silentTrackBase = SilentAudio.getTrack(this.observer, this._audioTrack.id, this._audioTrack.codec, 2, this.logger);
if (!silentTrackBase) {
throw `unable to create silent audio track for codec ${this._audioTrack.codec}`;
}
this._silentAudioTrack = Object.assign(Object.assign({}, silentTrackBase), { sequenceNumber: 0 });
const iframeInitSegment = MP4$1.initSegment([this._videoTrack, this._silentAudioTrack]);
this.remuxedInitDataTrack = { type: 'audiovideo', container: 'video/mp4', codec: this._silentAudioTrack.config.codec + ',' + this._videoTrack.codec, initSegment: iframeInitSegment };
const data = { track: this.remuxedInitDataTrack };
this.observer.trigger(DemuxerEvent.FRAG_PARSING_INIT_SEGMENT, data);
}
MP4Demuxer.parseSamples(startDtsSec, data, this._videoTrack, iframeDuration, false, 1);
this.mp4Remuxer.remuxIFrame(startDtsSec, this._videoTrack, this._silentAudioTrack, iframeDuration, this.remuxedInitDataTrack);
this._videoTrack.samples = [];
}
else {
let startDtsSec = (startDtsTs.baseTime - this.audioPrimingDelay * startDtsTs.timescale) / startDtsTs.timescale;
startDtsSec = Math.max(0, startDtsSec);
if (emsgs && emsgs.length > 0) {
const emsgsInfos = emsgs.map((emsg) => {
const emsgInfo = MP4Demuxer.parseEmsg(emsg);
// HLSJS only processes id3 tags in emsgs
if (emsgInfo.schemeIdUri === 'https://aomedia.org/emsg/ID3\0' && !this._id3Track) {
this._id3Track = { id3Samples: [], inputTimescale: 90000 };
}
return emsgInfo;
});
if (this._id3Track) {
emsgsInfos.map((emsgInfo) => {
MP4Demuxer.extractID3PayloadCreateID3Track(emsgInfo, timeOffset, this._id3Track, this.logger);
});
}
}
if (this._videoTrack) {
MP4Demuxer.parseSamples(startDtsSec, data, this._videoTrack, undefined, this.trySEICaptions, -1);
videoDuration = this._videoTrack.fragmentDuration / this._videoTrack.timescale;
hasVideo = true;
this._videoTrack.fragmentDuration = 0;
this.logger.info(loggerName$c, `frag video duration: ${videoDuration}`);
if (this.trySEICaptions) {
MP4Demuxer.extractSEICaptionsFromNALu(this._videoTrack.seiSamples, this._captionTrack);
this._videoTrack.seiSamples = [];
this.logger.info(loggerName$c, `sei samples: ${this._captionTrack.captionSamples.length}`);
}
else if (this._captionTrack) {
// clcp text track
MP4Demuxer.parseSamples(startDtsSec, data, this._captionTrack, undefined, false, Number.MAX_SAFE_INTEGER);
}
}
if (this._audioTrack) {
MP4Demuxer.parseSamples(startDtsSec, data, this._audioTrack, undefined, false, -1);
audioDuration = this._audioTrack.fragmentDuration / this._audioTrack.timescale;
hasAudio = true;
this._audioTrack.fragmentDuration = 0;
}
this.mp4Remuxer.remuxEmsgAndRawData(audioDuration, hasAudio, videoDuration, hasVideo, this._captionTrack, this._id3Track, startDtsSec, startDtsTs.timescale, data, this.remuxedInitDataTrack);
if (this._id3Track) {
this._id3Track.id3Samples = [];
}
}
}
static extractSEICaptionsFromNALu(units, textTrack) {
if (!units) {
return;
}
for (let u = 0; u < units.length; ++u) {
const unit = units[u];
const pts = unit.pts;
let seiPtr = 0;
seiPtr++;
let payloadType = 0;
let payloadSize = 0;
let endOfCaptions = false;
let b = 0;
while (!endOfCaptions && seiPtr < unit.data.length) {
payloadType = 0;
do {
if (seiPtr >= unit.data.length) {
break;
}
b = unit.data[seiPtr++];
payloadType += b;
} while (b === 255);
// Parse payload size.
payloadSize = 0;
do {
if (seiPtr >= unit.data.length) {
break;
}
b = unit.data[seiPtr++];
payloadSize += b;
} while (b === 255);
const leftOver = unit.data.length - seiPtr;
if (payloadType === 4 && seiPtr < unit.data.length) {
endOfCaptions = true;
const countryCode = unit.data[seiPtr++];
if (countryCode === 181) {
const providerCode = MuxerHelper.readUint16(unit.data, seiPtr);
seiPtr += 2;
if (providerCode === 49) {
const userStructure = MuxerHelper.readUint32(unit.data, seiPtr);
seiPtr += 4;
if (userStructure === 1195456820) {
const userDataType = unit.data[seiPtr++];
// Raw CEA-608 bytes wrapped in CEA-708 packet
if (userDataType === 3) {
const firstByte = unit.data[seiPtr++];
seiPtr++; // skip second byte
const totalCCs = 31 & firstByte;
const enabled = 64 & firstByte;
const byteArray = [];
if (enabled) {
for (let i = 0; i < totalCCs; i++) {
const ccData = unit.data[seiPtr++];
const ccDataChecked = ccData & 252;
if (ccData === ccDataChecked) {
// valid ccData
const ccType = ccData & 3;
if (0 === ccType || 1 === ccType) {
// Exclude CEA708 CC data.
const b1 = unit.data[seiPtr++];
const b2 = unit.data[seiPtr++];
byteArray.push(b1);
byteArray.push(b2);
}
}
else {
seiPtr += 2; // Skip byte pair too
}
}
}
if (byteArray.length > 0) {
textTrack.captionSamples.push({ type: 3, pts: pts, bytes: byteArray });
}
}
}
}
}
}
else if (payloadSize < leftOver) {
seiPtr += payloadSize;
}
else if (payloadSize > leftOver) {
break;
}
}
}
return textTrack;
}
}
const loggerName$b = { name: 'ExpGolomb' };
class ExpGolomb {
constructor(data, logger) {
this.data = data;
this.logger = logger;
// the number of bytes left to examine in this.data
this._bytesAvailable = data.byteLength;
// the current word being examined
this.word = 0; // :uint
// the number of bits left to examine in the current word
this.bitsAvailable = 0; // :uint
}
get bytesAvailable() {
return this._bytesAvailable;
}
loadWord() {
const data = this.data, bytesAvailable = this._bytesAvailable, position = data.byteLength - bytesAvailable, workingBytes = new Uint8Array(4), availableBytes = Math.min(4, bytesAvailable);
if (availableBytes === 0) {
throw new Error('no bytes available');
}
workingBytes.set(data.subarray(position, position + availableBytes));
this.word = new DataView(workingBytes.buffer).getUint32(0);
// track the amount of this.data that has been processed
this.bitsAvailable = availableBytes * 8;
this._bytesAvailable -= availableBytes;
}
skipBits(count) {
let skipBytes; // :int
if (this.bitsAvailable > count) {
this.word <<= count;
this.bitsAvailable -= count;
}
else {
count -= this.bitsAvailable;
skipBytes = count >> 3;
count -= skipBytes >> 3;
this._bytesAvailable -= skipBytes;
this.loadWord();
this.word <<= count;
this.bitsAvailable -= count;
}
}
readBits(size) {
let bits = Math.min(this.bitsAvailable, size); // :uint
const valu = this.word >>> (32 - bits); // :uint
if (size > 32) {
this.logger.error(loggerName$b, 'Cannot read more than 32 bits at a time');
}
this.bitsAvailable -= bits;
if (this.bitsAvailable > 0) {
this.word <<= bits;
}
else if (this._bytesAvailable > 0) {
this.loadWord();
}
bits = size - bits;
if (bits > 0 && this.bitsAvailable) {
return (valu << bits) | this.readBits(bits);
}
else {
return valu;
}
}
// ():uint
skipLZ() {
let leadingZeroCount; // :uint
for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) {
if (0 !== (this.word & (2147483648 >>> leadingZeroCount))) {
// the first bit of working word is 1
this.word <<= leadingZeroCount;
this.bitsAvailable -= leadingZeroCount;
return leadingZeroCount;
}
}
// we exhausted word and still have not found a 1
this.loadWord();
return leadingZeroCount + this.skipLZ();
}
// ():void
skipUEG() {
this.skipBits(1 + this.skipLZ());
}
// ():void
skipEG() {
this.skipBits(1 + this.skipLZ());
}
// ():uint
readUEG() {
const clz = this.skipLZ(); // :uint
return this.readBits(clz + 1) - 1;
}
// ():int
readEG() {
const valu = this.readUEG(); // :int
if (1 & 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
}
else {
return -1 * (valu >>> 1); // divide by two then make it negative
}
}
// Some convenience functions
// :Boolean
readBoolean() {
return 1 === this.readBits(1);
}
// ():int
readUByte() {
return this.readBits(8);
}
// ():int
readUShort() {
return this.readBits(16);
}
// ():int
readUInt() {
return this.readBits(32);
}
/**
* 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
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
*/
skipScalingList(count) {
let lastScale = 8, nextScale = 8, j, deltaScale;
for (j = 0; j < count; j++) {
if (nextScale !== 0) {
deltaScale = this.readEG();
nextScale = (lastScale + deltaScale + 256) % 256;
}
lastScale = nextScale === 0 ? lastScale : nextScale;
}
}
/**
* 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.
*/
readSPS() {
let frameCropLeftOffset = 0, frameCropRightOffset = 0, frameCropTopOffset = 0, frameCropBottomOffset = 0, numRefFramesInPicOrderCntCycle, scalingListCount, i;
const readUByte = this.readUByte.bind(this), readBits = this.readBits.bind(this), readUEG = this.readUEG.bind(this), readBoolean = this.readBoolean.bind(this), skipBits = this.skipBits.bind(this), skipEG = this.skipEG.bind(this), skipUEG = this.skipUEG.bind(this), skipScalingList = this.skipScalingList.bind(this);
readUByte();
const profileIdc = readUByte(); // profile_idc
readBits(5); // constraint_set[0-4]_flag, u(5)
skipBits(3); // reserved_zero_3bits u(3),
readUByte(); // level_idc u(8)
skipUEG(); // seq_parameter_set_id
// some profiles have more optional data we don't need
if (profileIdc === 100 ||
profileIdc === 110 ||
profileIdc === 122 ||
profileIdc === 244 ||
profileIdc === 44 ||
profileIdc === 83 ||
profileIdc === 86 ||
profileIdc === 118 ||
profileIdc === 128) {
const chromaFormatIdc = readUEG();
if (chromaFormatIdc === 3) {
skipBits(1); // separate_colour_plane_flag
}
skipUEG(); // bit_depth_luma_minus8
skipUEG(); // bit_depth_chroma_minus8
skipBits(1); // qpprime_y_zero_transform_bypass_flag
if (readBoolean()) {
// seq_scaling_matrix_present_flag
scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
for (i = 0; i < scalingListCount; i++) {
if (readBoolean()) {
// seq_scaling_list_present_flag[ i ]
if (i < 6) {
skipScalingList(16);
}
else {
skipScalingList(64);
}
}
}
}
}
skipUEG(); // log2_max_frame_num_minus4
const picOrderCntType = readUEG();
if (picOrderCntType === 0) {
readUEG(); // log2_max_pic_order_cnt_lsb_minus4
}
else if (picOrderCntType === 1) {
skipBits(1); // delta_pic_order_always_zero_flag
skipEG(); // offset_for_non_ref_pic
skipEG(); // offset_for_top_to_bottom_field
numRefFramesInPicOrderCntCycle = readUEG();
for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
skipEG(); // offset_for_ref_frame[ i ]
}
}
skipUEG(); // max_num_ref_frames
skipBits(1); // gaps_in_frame_num_value_allowed_flag
const picWidthInMbsMinus1 = readUEG();
const picHeightInMapUnitsMinus1 = readUEG();
const frameMbsOnlyFlag = readBits(1);
if (frameMbsOnlyFlag === 0) {
skipBits(1); // mb_adaptive_frame_field_flag
}
skipBits(1); // direct_8x8_inference_flag
if (readBoolean()) {
// frame_cropping_flag
frameCropLeftOffset = readUEG();
frameCropRightOffset = readUEG();
frameCropTopOffset = readUEG();
frameCropBottomOffset = readUEG();
}
let pixelRatio = [1, 1];
if (readBoolean()) {
// vui_parameters_present_flag
if (readBoolean()) {
// aspect_ratio_info_present_flag
const aspectRatioIdc = readUByte();
switch (aspectRatioIdc) {
case 1:
pixelRatio = [1, 1];
break;
case 2:
pixelRatio = [12, 11];
break;
case 3:
pixelRatio = [10, 11];
break;
case 4:
pixelRatio = [16, 11];
break;
case 5:
pixelRatio = [40, 33];
break;
case 6:
pixelRatio = [24, 11];
break;
case 7:
pixelRatio = [20, 11];
break;
case 8:
pixelRatio = [32, 11];
break;
case 9:
pixelRatio = [80, 33];
break;
case 10:
pixelRatio = [18, 11];
break;
case 11:
pixelRatio = [15, 11];
break;
case 12:
pixelRatio = [64, 33];
break;
case 13:
pixelRatio = [160, 99];
break;
case 14:
pixelRatio = [4, 3];
break;
case 15:
pixelRatio = [3, 2];
break;
case 16:
pixelRatio = [2, 1];
break;
case 255: {
pixelRatio = [(readUByte() << 8) | readUByte(), (readUByte() << 8) | readUByte()];
break;
}
}
}
}
return {
width: Math.ceil((picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2),
height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - (frameMbsOnlyFlag ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset),
pixelRatio: pixelRatio,
};
}
readSliceType() {
// skip NALu type
this.readUByte();
// discard first_mb_in_slice
this.readUEG();
// return slice_type
return this.readUEG();
}
}
const TIMESCALE = 90000;
const loggerName$a = { name: 'TS Demuxer' };
function isCompleteVideoConfig(config) {
const is = typeof config.codec === 'string' &&
Array.isArray(config.sps) &&
Array.isArray(config.pps) &&
typeof config.width === 'number' &&
typeof config.height === 'number' &&
Array.isArray(config.pixelRatio);
return is;
}
class TsDemuxer extends EsDemuxer {
constructor(observer, remuxer, config, typeSupported, logger) {
super(observer, remuxer, config, typeSupported, logger);
}
static probe(data, logger) {
// a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and one PID, each starting with 0x47
if (data.length >= 564 && data[0] === 71 && data[188] === 71 && data[376] === 71) {
return true;
}
else {
return false;
}
}
resetInitSegment(initSegment, duration, keyTagInfo) {
this.pmtParsed = false;
this._pmtId = -1;
const baseInfo = { id: -1, inputTimescale: TIMESCALE, timescale: NaN, duration: 0, encrypted: keyTagInfo && keyTagInfo.isEncrypted, keyTagInfo };
const baseParsingInfo = { len: 0, sequenceNumber: 0 };
this._avcContext = { info: Object.assign({}, baseInfo), parsingData: Object.assign(Object.assign({}, baseParsingInfo), { esSamples: new Array(), dropped: 0 }), config: {}, container: 'video/mp2t', type: 'video' };
this._audioContext = { info: Object.assign({}, baseInfo), parsingData: Object.assign(Object.assign({}, baseParsingInfo), { esSamples: new Array() }), container: 'video/mp2t', type: 'audio' };
this._id3Track = { id: -1, inputTimescale: TIMESCALE, id3Samples: [] };
this._txtTrack = { inputTimescale: TIMESCALE, captionSamples: [] };
this._duration = duration;
this._initSegment = initSegment;
}
// feed incoming data to the front of the parsing pipeline
append(data, timeOffset, contiguous, accurateTimeOffset, keyTagInfo, iframeMediaStart, iframeDuration) {
let start, stt, pid, atf, offset, pes, unknownPIDs = false;
this.contiguous = contiguous;
const avcContext = this._avcContext, audioContext = this._audioContext, id3Track = this._id3Track;
let pmtParsed = this.pmtParsed, avcId = avcContext.info.id, audioId = audioContext.info.id, id3Id = id3Track.id, pmtId = this._pmtId, avcData = avcContext.pesData, audioData = audioContext.pesData, id3Data = id3Track.pesData;
this.iframeMode = typeof iframeDuration !== 'undefined';
if (this._initSegment && this._initSegment.byteLength > 0) {
// if there's an init segment then it needs to be prepended to the first data
const newData = new Uint8Array(this._initSegment.byteLength + data.byteLength);
newData.set(this._initSegment);
newData.set(data, this._initSegment.byteLength);
this._initSegment = undefined;
// make sure its still valid TS
if (newData[0] === 71) {
data = newData;
}
}
let len = data.length;
// don't parse last TS packet if incomplete
len -= len % 188;
// loop through TS packets
for (start = 0; start < len; start += 188) {
if (data[start] === 71) {
// payload unit start indicator - pes immediately follows the ts header
stt = !!(data[start + 1] & 64);
// pid is a 13-bit field starting at the last bit of TS[1]
pid = ((data[start + 1] & 31) << 8) + data[start + 2];
atf = (data[start + 3] & 48) >> 4;
// if an adaption field is present, its length is specified by the fifth byte of the TS packet header.
if (atf > 1) {
offset = start + 5 + data[start + 4];
// continue if there is only adaptation field
if (offset === start + 188) {
continue;
}
}
else {
offset = start + 4;
}
switch (pid) {
case avcId:
if (stt) {
if (avcData && (pes = this._parsePES(avcData))) {
// new pes is starting and we have an current one, therefore the current pes is complete, so lets parse it
this._parseAVCPES(pes, false);
}
// reset the current pes data
avcData = { data: [], size: 0, keyTagInfo: keyTagInfo };
}
if (avcData) {
avcData.data.push(data.subarray(offset, start + 188));
avcData.size += start + 188 - offset;
}
break;
case audioId:
if (stt && !this.iframeMode) {
if (audioData && (pes = this._parsePES(audioData))) {
switch (audioContext.segmentCodec) {
case 'aac':
this._parseAACPES(pes);
break;
case 'mp3':
this._parseMPEGPES(pes);
break;
case 'ac3':
case 'ec3':
this._parseDolbyPES(pes);
break;
}
}
audioData = { data: [], size: 0, keyTagInfo: keyTagInfo };
}
if (audioData) {
audioData.data.push(data.subarray(offset, start + 188));
audioData.size += start + 188 - offset;
}
break;
case id3Id:
if (stt) {
if (id3Data && (pes = this._parsePES(id3Data))) {
id3Track.id3Samples.push(pes);
}
id3Data = { data: [], size: 0 };
}
if (id3Data) {
id3Data.data.push(data.subarray(offset, start + 188));
id3Data.size += start + 188 - offset;
}
break;
case 0:
if (stt) {
offset += data[offset] + 1;
}
pmtId = this._pmtId = this._parsePAT(data, offset);
break;
case pmtId:
if (stt) {
offset += data[offset] + 1;
}
const parsedPIDs = this._parsePMT(data, offset, this.typeSupported);
// only update track id if track PID found while parsing PMT
// this is to avoid resetting the PID to -1 in case
// track PID transiently disappears from the stream
// this could happen in case of transient missing audio samples for example
avcId = parsedPIDs.avcId;
if (avcId > 0) {
avcContext.info.id = avcId;
avcContext.info.encrypted = parsedPIDs.videoEncrypted;
}
audioId = parsedPIDs.audioId;
if (audioId > 0) {
audioContext.info.id = audioId;
audioContext.segmentCodec = parsedPIDs.audioSegmentCodec;
audioContext.info.encrypted = parsedPIDs.audioEncrypted;
}
id3Id = parsedPIDs.id3Id;
if (id3Id > 0) {
id3Track.id = id3Id;
}
if (unknownPIDs && !pmtParsed) {
this.logger.info(loggerName$a, 'reparse from beginning');
unknownPIDs = false;
// we set it to -188, the += 188 in the for loop will reset start to 0
start = -188;
}
pmtParsed = this.pmtParsed = true;
break;
case 17: // eslint-disable-line
case 8191:
break;
default:
unknownPIDs = true;
break;
}
}
else {
const payload = new FragParsingError(false, 'TS packet did not start with 0x47', ErrorResponses.NoTSSyncByteFound);
this.observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return;
}
}
// try to parse last PES packets
if (avcData && (pes = this._parsePES(avcData))) {
this._parseAVCPES(pes, true);
avcContext.pesData = undefined;
}
else {
// either avcData null or PES truncated, keep it for next frag parsing
avcContext.pesData = avcData;
}
if (audioData && (pes = this._parsePES(audioData))) {
switch (audioContext.segmentCodec) {
case 'aac':
this._parseAACPES(pes);
break;
case 'mp3':
this._parseMPEGPES(pes);
break;
case 'ac3':
case 'ec3':
this._parseDolbyPES(pes);
break;
}
audioContext.pesData = undefined;
}
else {
if (audioData && audioData.size) {
this.logger.warn(loggerName$a, 'last AAC PES packet truncated,might overlap between fragments');
}
// either audioData null or PES truncated, keep it for next frag parsing
audioContext.pesData = audioData;
}
if (id3Data && (pes = this._parsePES(id3Data))) {
id3Track.id3Samples.push(pes);
id3Track.pesData = undefined;
}
else {
// either id3Data null or PES truncated, keep it for next frag parsing
id3Track.pesData = id3Data;
}
let audioTrack;
if (audioContext.config && audioContext.segmentCodec) {
audioTrack = { type: 'audio', info: audioContext.info, config: audioContext.config, parsingData: audioContext.parsingData };
}
let videoTrack;
const pc = avcContext.config;
if (isCompleteVideoConfig(pc)) {
videoTrack = { type: 'video', info: avcContext.info, config: pc, parsingData: avcContext.parsingData };
}
this.esRemuxer.remuxEsTracks(audioTrack, videoTrack, id3Track, this._txtTrack, timeOffset, contiguous, accurateTimeOffset, keyTagInfo, iframeMediaStart, iframeDuration);
}
destroy() {
this._duration = 0;
}
_parsePAT(data, offset) {
// skip the PSI header and parse the first PMT entry
return ((data[offset + 10] & 31) << 8) | data[offset + 11];
}
_parsePMT(data, offset, typeSupported) {
let pid; // result = { audio : -1, avc : -1, id3 : -1, segmentCodec : 'aac', videoEncrypted : false, audioEncrypted :false };
const result = {
audioId: -1,
avcId: -1,
id3Id: -1,
audioEncrypted: false,
videoEncrypted: false,
};
const sectionLength = ((data[offset + 1] & 15) << 8) | data[offset + 2];
const tableEnd = offset + 3 + sectionLength - 4;
// to determine where the table is, we have to figure out how
// long the program info descriptors are
const programInfoLength = ((data[offset + 10] & 15) << 8) | data[offset + 11];
// advance the offset to the first entry in the mapping table
offset += 12 + programInfoLength;
while (offset < tableEnd) {
pid = ((data[offset + 1] & 31) << 8) | data[offset + 2];
switch (data[offset]) {
case 207:
result.audioEncrypted = true;
/* falls through */
// ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio)
case 15:
// logger.info('AAC PID:' + pid);
if (result.audioId === -1) {
result.audioId = pid;
result.audioSegmentCodec = 'aac';
}
break;
// Packetized metadata (ID3)
case 21:
// logger.info('ID3 PID:' + pid);
if (result.id3Id === -1) {
result.id3Id = pid;
}
break;
case 219:
result.videoEncrypted = true;
/* falls through */
// ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video)
case 27:
// logger.info('AVC PID:' + pid);
if (result.avcId === -1) {
result.avcId = pid;
}
break;
// ISO/IEC 11172-3 (MPEG-1 audio)
// or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio)
case 3:
case 4:
// logger.info('MPEG PID:' + pid);
if (typeSupported.mpeg !== true && typeSupported.mp3 !== true) {
this.logger.warn(loggerName$a, 'MPEG audio found, not supported in this browser for now');
}
else if (result.audioId === -1) {
result.audioId = pid;
result.audioSegmentCodec = 'mp3';
}
break;
case 193:
result.audioEncrypted = true;
this.logger.info(loggerName$a, 'TS encrypted AC-3 audio found');
/* falls through */
case 129:
if (typeSupported.ac3 !== true) {
this.logger.warn(loggerName$a, 'AC-3 audio found, not supported in this browser for now');
}
else if (result.audioId === -1) {
result.audioId = pid;
result.audioSegmentCodec = 'ac3';
}
break;
case 194:
result.audioEncrypted = true;
this.logger.info(loggerName$a, 'TS encrypted EC-3 audio found');
/* falls through */
case 135:
if (typeSupported.ec3 !== true) {
this.logger.warn(loggerName$a, 'EC-3 audio found, not supported in this browser for now');
}
else if (result.audioId === -1) {
result.audioId = pid;
result.audioSegmentCodec = 'ec3';
}
break;
case 36:
this.logger.warn(loggerName$a, 'HEVC stream type found, not supported for now');
break;
default:
this.logger.warn(loggerName$a, 'unkown stream type:' + data[offset]);
break;
}
// move to the next table entry
// skip past the elementary stream descriptors, if present
offset += (((data[offset + 3] & 15) << 8) | data[offset + 4]) + 5;
}
return result;
}
_parsePES(stream) {
let i = 0, frag, pesFlags, pesLen, pesHdrLen, pesData, payloadStartOffset;
const data = stream.data, keyTagInfo = stream.keyTagInfo;
let pesPts = NaN, pesDts = NaN;
// safety check
if (!stream || stream.size === 0) {
return undefined;
}
// we might need up to 19 bytes to read PES header
// if first chunk of data is less than 19 bytes, let's merge it with following ones until we get 19 bytes
// usually only one merge is needed (and this is rare ...)
while (data[0].length < 19 && data.length > 1) {
const newData = new Uint8Array(data[0].length + data[1].length);
newData.set(data[0]);
newData.set(data[1], data[0].length);
data[0] = newData;
data.splice(1, 1);
}
// retrieve PTS/DTS from first fragment
frag = data[0];
const pesPrefix = (frag[0] << 16) + (frag[1] << 8) + frag[2];
if (pesPrefix === 1) {
pesLen = (frag[4] << 8) + frag[5];
// if PES parsed length is not zero and greater than total received length, stop parsing. PES might be truncated
// minus 6 : PES header size
if (pesLen && pesLen > stream.size - 6) {
return undefined;
}
pesFlags = frag[7];
if (pesFlags & 192) {
/* PES header described here : http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
as PTS / DTS is 33 bit we cannot use bitwise operator in JS,
as Bitwise operators treat their operands as a sequence of 32 bits */
pesPts =
(frag[9] & 14) * 536870912 + // 1 << 29
(frag[10] & 255) * 4194304 + // 1 << 22
(frag[11] & 254) * 16384 + // 1 << 14
(frag[12] & 255) * 128 + // 1 << 7
(frag[13] & 254) / 2;
if (pesFlags & 64) {
pesDts =
(frag[14] & 14) * 536870912 + // 1 << 29
(frag[15] & 255) * 4194304 + // 1 << 22
(frag[16] & 254) * 16384 + // 1 << 14
(frag[17] & 255) * 128 + // 1 << 7
(frag[18] & 254) / 2;
if (pesPts - pesDts > 5400000) {
this.logger.warn(loggerName$a, `${Math.round((pesPts - pesDts) / 90000)}s delta between PTS and DTS, align them`);
pesPts = pesDts;
}
}
else {
pesDts = pesPts;
}
}
pesHdrLen = frag[8];
// 9 bytes : 6 bytes for PES header + 3 bytes for PES extension
payloadStartOffset = pesHdrLen + 9;
stream.size -= payloadStartOffset;
// reassemble PES packet
pesData = new Uint8Array(stream.size);
for (let j = 0, dataLen = data.length; j < dataLen; j++) {
frag = data[j];
let len = frag.byteLength;
if (payloadStartOffset) {
if (payloadStartOffset > len) {
// trim full frag if PES header bigger than frag
payloadStartOffset -= len;
continue;
}
else {
// trim partial frag if PES header smaller than frag
frag = frag.subarray(payloadStartOffset);
len -= payloadStartOffset;
payloadStartOffset = 0;
}
}
pesData.set(frag, i);
i += len;
}
if (pesLen) {
// payload size : remove PES header + PES extension
pesLen -= pesHdrLen + 3;
}
return { data: pesData, pts: pesPts, dts: pesDts, len: pesLen, keyTagInfo: keyTagInfo };
}
else {
return undefined;
}
}
pushAccesUnit(avcContext, keyTagInfo) {
const avcSample = avcContext.avcSample;
if (avcSample && avcSample.units.length && avcSample.frame) {
const samples = avcContext.parsingData.esSamples;
const nbSamples = samples.length;
if (avcSample.key === true || (avcContext.config.sps && (nbSamples || this.contiguous))) {
avcSample.id = nbSamples;
avcSample.keyTagInfo = keyTagInfo;
if (avcContext.info.encrypted) {
const units = avcSample.units;
units.forEach((unit) => {
if (unit.data.byteLength > 48) {
switch (unit.type) {
case 1:
case 5:
// need to remove EPBs from encrypted NALs now that they're parsed into units
unit.data = this.discardEPB(unit.data);
break;
}
}
});
}
}
if (!nbSamples && !isFinite(avcSample.pts)) {
// dropping samples, no timestamp found
avcContext.parsingData.dropped++;
return;
}
samples.push(avcSample);
}
if (avcSample && avcSample.debug.length) {
this.logger.info(loggerName$a, avcSample.pts + '/' + avcSample.dts + ':' + avcSample.debug);
}
}
_parseAVCPES(pes, last) {
if (!pes.data) {
throw 'invalid pes data';
}
const avcContext = this._avcContext, units = this._parseAVCNALu(pes.data);
let expGolombDecoder, avcSample = avcContext.avcSample, push, i;
const keyTagInfo = pes.keyTagInfo;
// free pes.data to save up some memory
pes.data = undefined;
units.forEach((unit) => {
switch (unit.type) {
// NDR
case 1:
if (avcSample && !this.iframeMode) {
// TODO: demuxer needs better support for partial nal units
push = true;
avcSample.frame = true;
// retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
const data = unit.data;
if (data.length > 4) {
const sliceType = new ExpGolomb(data, this.logger).readSliceType();
// 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
// SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
// An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
// I slice: A slice that is not an SI slice that is decoded using intra prediction only.
// if (sliceType === 2 || sliceType === 7) {
if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
avcSample.key = true;
}
}
}
break;
// IDR
case 5:
push = true;
if (avcSample) {
// handle PES not starting with AUD
if (!avcSample) {
avcSample = avcContext.avcSample = this._createAVCSample(true, pes.pts, pes.dts, '');
}
avcSample.key = true;
avcSample.frame = true;
}
break;
// SEI
case 6:
push = true;
expGolombDecoder = new ExpGolomb(this.discardEPB(unit.data), this.logger);
// skip frameType
expGolombDecoder.readUByte();
let payloadType = 0;
let payloadSize = 0;
let endOfCaptions = false;
let b = 0;
while (!endOfCaptions && expGolombDecoder.bytesAvailable > 1) {
payloadType = 0;
do {
b = expGolombDecoder.readUByte();
payloadType += b;
} while (b === 255);
// Parse payload size.
payloadSize = 0;
do {
b = expGolombDecoder.readUByte();
payloadSize += b;
} while (b === 255);
// TODO: there can be more than one payload in an SEI packet...
// TODO: need to read type and size in a while loop to get them all
if (payloadType === 4 && expGolombDecoder.bytesAvailable !== 0) {
endOfCaptions = true;
const countryCode = expGolombDecoder.readUByte();
if (countryCode === 181) {
const providerCode = expGolombDecoder.readUShort();
if (providerCode === 49) {
const userStructure = expGolombDecoder.readUInt();
if (userStructure === 1195456820) {
const userDataType = expGolombDecoder.readUByte();
// Raw CEA-608 bytes wrapped in CEA-708 packet
if (userDataType === 3) {
const firstByte = expGolombDecoder.readUByte();
const secondByte = expGolombDecoder.readUByte();
const totalCCs = 31 & firstByte;
const byteArray = [firstByte, secondByte];
for (i = 0; i < totalCCs; i++) {
// 3 bytes per CC
byteArray.push(expGolombDecoder.readUByte());
byteArray.push(expGolombDecoder.readUByte());
byteArray.push(expGolombDecoder.readUByte());
}
this._insertSampleInOrder(this._txtTrack.captionSamples, { type: 3, pts: pes.pts, bytes: byteArray });
}
}
}
}
}
else if (payloadSize < expGolombDecoder.bytesAvailable) {
for (i = 0; i < payloadSize; i++) {
expGolombDecoder.readUByte();
}
}
}
break;
// SPS
case 7:
push = true;
if (!avcContext.config.sps) {
expGolombDecoder = new ExpGolomb(unit.data, this.logger);
const config = expGolombDecoder.readSPS();
avcContext.config.width = config.width;
avcContext.config.height = config.height;
avcContext.config.pixelRatio = config.pixelRatio;
avcContext.config.sps = [unit.data];
avcContext.info.duration = this._duration;
const codecarray = unit.data.subarray(1, 4);
let codecstring = 'avc1.';
for (i = 0; i < 3; i++) {
let h = codecarray[i].toString(16);
if (h.length < 2) {
h = '0' + h;
}
codecstring += h;
}
avcContext.config.codec = codecstring;
}
break;
// PPS
case 8:
push = true;
if (!avcContext.config.pps) {
avcContext.config.pps = [unit.data];
}
break;
// AUD
case 9:
push = false;
if (avcSample) {
this.pushAccesUnit(avcContext, keyTagInfo);
}
avcSample = avcContext.avcSample = this._createAVCSample(false, pes.pts, pes.dts, '');
break;
// Filler Data
case 12:
push = false;
break;
default:
push = false;
if (avcSample) {
avcSample.debug += 'unknown NAL ' + unit.type + ' ';
}
break;
}
if (avcSample && push) {
const units = avcSample.units;
units.push(unit);
}
});
// if last PES packet, push samples
if (last && avcSample) {
this.pushAccesUnit(avcContext, keyTagInfo);
avcContext.avcSample = undefined;
}
}
_createAVCSample(key, pts, dts, debug) {
return { id: NaN, key: key, pts: pts, dts: dts, units: new Array(), debug: debug };
}
_insertSampleInOrder(arr, data) {
const len = arr.length;
if (len > 0) {
if (data.pts >= arr[len - 1].pts) {
arr.push(data);
}
else {
for (let pos = len - 1; pos >= 0; pos--) {
if (data.pts < arr[pos].pts) {
arr.splice(pos, 0, data);
break;
}
}
}
}
else {
arr.push(data);
}
}
_getLastNalUnit() {
const avcContext = this._avcContext;
let avcSample = avcContext.avcSample, lastUnit;
// try to fallback to previous sample if current one is empty
if (!avcSample || avcSample.units.length === 0) {
const samples = avcContext.parsingData.esSamples;
avcSample = samples[samples.length - 1];
}
if (avcSample) {
const units = avcSample.units;
lastUnit = units[units.length - 1];
}
return lastUnit;
}
_parseAVCNALu(array) {
const len = array.byteLength;
let i = 0, value, overflow;
const avcContext = this._avcContext;
let state = avcContext.naluState || 0;
const lastState = state;
const units = [];
let unit, unitType, lastUnitStart = -1, lastUnitType;
if (state === -1) {
// special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
lastUnitStart = 0;
// NALu type is value read from offset 0
lastUnitType = array[0] & 31;
state = 0;
i = 1;
}
while (i < len) {
value = array[i++];
// optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
if (!state) {
state = value ? 0 : 1;
continue;
}
if (state === 1) {
state = value ? 0 : 2;
continue;
}
// here we have state either equal to 2 or 3
if (!value) {
state = 3;
}
else if (value === 1) {
if (lastUnitStart >= 0) {
unit = { data: array.subarray(lastUnitStart, i - state - 1), type: lastUnitType };
units.push(unit);
}
else {
// lastUnitStart is -1 => this is the first start code found in this PES packet
// first check if start code delimiter is overlapping between 2 PES packets,
// ie it started in last packet (lastState not zero)
// and ended at the beginning of this PES packet (i <= 4 - lastState)
const lastUnit = this._getLastNalUnit();
if (lastUnit) {
if (lastState && i <= 4 - lastState) {
// start delimiter overlapping between PES packets
// strip start delimiter bytes from the end of last NAL unit
// check if lastUnit had a state different from zero
if (lastUnit.state) {
// strip last bytes
lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
}
}
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
overflow = i - state - 1;
if (overflow > 0) {
const tmp = new Uint8Array(lastUnit.data.byteLength + overflow);
tmp.set(lastUnit.data, 0);
tmp.set(array.subarray(0, overflow), lastUnit.data.byteLength);
lastUnit.data = tmp;
lastUnit.state = 0;
}
}
}
// check if we can read unit type
if (i < len) {
unitType = array[i] & 31;
lastUnitStart = i;
lastUnitType = unitType;
state = 0;
}
else {
// not enough byte to read unit type. let's read it on next PES parsing
state = -1;
}
}
else {
state = 0;
}
}
if (lastUnitStart >= 0 && state >= 0) {
unit = { data: array.subarray(lastUnitStart, len), type: lastUnitType, state };
units.push(unit);
}
// no NALu found
if (units.length === 0) {
// append pes.data to previous NAL unit
const lastUnit = this._getLastNalUnit();
if (lastUnit) {
const tmp = new Uint8Array(lastUnit.data.byteLength + array.byteLength);
tmp.set(lastUnit.data, 0);
tmp.set(array, lastUnit.data.byteLength);
lastUnit.data = tmp;
}
}
avcContext.naluState = state;
return units;
}
/**
* remove Emulation Prevention bytes from a RBSP
*/
discardEPB(data) {
const length = data.byteLength, EPBPositions = [];
let i = 1;
// Find all `Emulation Prevention Bytes`
while (i < length - 2) {
if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 3) {
EPBPositions.push(i + 2);
i += 2;
}
else {
i++;
}
}
// If no Emulation Prevention Bytes were found just return the original
// array
if (EPBPositions.length === 0) {
return data;
}
// Create a new array to hold the NAL unit data
const newLength = length - EPBPositions.length;
const newData = new Uint8Array(newLength);
let sourceIndex = 0;
for (i = 0; i < newLength; sourceIndex++, i++) {
if (sourceIndex === EPBPositions[0]) {
// Skip this byte
sourceIndex++;
// Remove this position index
EPBPositions.shift();
}
newData[i] = data[sourceIndex];
}
return newData;
}
_parseAACPES(pes) {
const audioContext = this._audioContext, audioLastPTS = audioContext.audioLastPTS, startOffset = 0, keyTagInfo = pes.keyTagInfo;
let data = pes.data, pts = pes.pts, audioOverFlow = audioContext.audioOverFlow, frameLength, frameIndex, offset, headerLength, stamp, len, aacSample;
if (audioOverFlow) {
const tmp = new Uint8Array(audioOverFlow.byteLength + data.byteLength);
tmp.set(audioOverFlow, 0);
tmp.set(data, audioOverFlow.byteLength);
data = tmp;
}
// look for ADTS header (0xFFFx)
for (offset = startOffset, len = data.length; offset < len - 1; offset++) {
if (data[offset] === 255 && (data[offset + 1] & 240) === 240) {
break;
}
}
// if ADTS header does not start straight from the beginning of the PES payload, raise an error
if (offset) {
let reason, fatal, response;
if (offset < len - 1) {
reason = `AAC PES did not start with ADTS header,offset:${offset}`;
fatal = false;
response = ErrorResponses.PESDidNotStartWithADTS;
}
else {
reason = 'no ADTS header found in AAC PES';
fatal = true;
response = ErrorResponses.NoADTSHeaderInPES;
}
this.logger.warn(loggerName$a, `parsing error:${reason}`);
const payload = new FragParsingError(fatal, reason, response);
this.observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
if (fatal) {
return;
}
}
if (!audioContext.config) {
const config = ADTS.getAudioConfig(this.observer, data, offset, undefined, this.logger);
if (!config) {
throw 'unable to parse adts header';
}
audioContext.config = config;
this.logger.info(loggerName$a, `parsed codec:${config.codec},rate:${config.samplerate},nb channel:${config.channelCount}`);
}
frameIndex = 0;
const frameDuration = 92160000 / audioContext.config.samplerate;
// if last AAC frame is overflowing, we should ensure timestamps are contiguous:
// first sample PTS should be equal to last sample PTS + frameDuration
if (audioOverFlow && audioLastPTS) {
const newPTS = audioLastPTS + frameDuration;
if (Math.abs(newPTS - pts) > 1) {
this.logger.info(loggerName$a, `AAC: align PTS for overlapping frames by ${Math.round((newPTS - pts) / 90)}`);
pts = newPTS;
}
}
while (offset + 5 < len) {
// The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header
headerLength = data[offset + 1] & 1 ? 7 : 9;
// retrieve frame size
frameLength = ((data[offset + 3] & 3) << 11) | (data[offset + 4] << 3) | ((data[offset + 5] & 224) >>> 5);
frameLength -= headerLength;
if (frameLength > 0 && offset + headerLength + frameLength <= len) {
stamp = pts + frameIndex * frameDuration;
aacSample = { unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp, keyTagInfo: keyTagInfo };
audioContext.parsingData.esSamples.push(aacSample);
audioContext.parsingData.len += frameLength;
offset += frameLength + headerLength;
frameIndex++;
// look for ADTS header (0xFFFx)
for (; offset < len - 1; offset++) {
if (data[offset] === 255 && (data[offset + 1] & 240) === 240) {
break;
}
}
}
else {
break;
}
}
if (offset < len) {
audioOverFlow = data.subarray(offset, len);
}
else {
audioOverFlow = undefined;
}
audioContext.audioOverFlow = audioOverFlow;
audioContext.audioLastPTS = stamp;
}
_parseMPEGPES(pes) {
if (this._audioContext.segmentCodec === 'mp3') {
MpegAudio$1.parse(this._audioContext.parsingData, pes.data, 0, pes.pts, this.logger);
}
}
_parseDolbyPES(pes) {
const audioContext = this._audioContext;
let data = pes.data;
let pts = pes.pts;
const keyTagInfo = pes.keyTagInfo;
let frameIndex = 0;
let offset = 0;
let audioOverFlow = audioContext.audioOverFlow;
const audioLastPTS = audioContext.audioLastPTS;
if (!audioContext.config) {
let config;
if (audioContext.segmentCodec === 'ac3') {
config = Dolby.getAudioConfig(this.observer, data, offset, this.logger);
}
else if (audioContext.segmentCodec === 'ec3') {
config = DDPlus$1.getAudioConfig(this.observer, data, offset, this.logger);
}
if (!config) {
throw 'unable to parse dolby header';
}
audioContext.config = config;
}
if (audioContext.config.segmentCodec !== 'ac3' && audioContext.config.segmentCodec !== 'ec3') {
throw 'unexpected config type';
}
const frameDuration = (1536 / audioContext.config.samplerate) * audioContext.info.inputTimescale;
if (audioOverFlow) {
const tmp = new Uint8Array(audioOverFlow.byteLength + data.byteLength);
tmp.set(audioOverFlow, 0);
tmp.set(data, audioOverFlow.byteLength);
data = tmp;
}
const length = data.length;
if (audioOverFlow && audioLastPTS) {
const newPTS = audioLastPTS + frameDuration;
if (Math.abs(newPTS - pts) > 1) {
pts = newPTS;
}
}
let frameLength = 0;
while (offset + frameLength <= length) {
if (data[offset] !== 11 || data[offset + 1] !== 119) {
const payload = new FragParsingError(true, 'invalid dolby audio magic', ErrorResponses.InvalidDolbyAudioMagic);
this.observer.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return;
}
if (audioContext.segmentCodec === 'ac3') {
frameLength = Dolby.getFrameLength(this.observer, data, offset);
}
else if (audioContext.segmentCodec === 'ec3') {
frameLength = DDPlus$1.getFrameLength(this.observer, data, offset, this.logger);
}
const stamp = pts + frameIndex * frameDuration;
audioContext.audioLastPTS = stamp;
const dolbySample = { unit: data.subarray(offset, offset + frameLength), pts: stamp, dts: stamp, keyTagInfo: keyTagInfo };
audioContext.parsingData.esSamples.push(dolbySample);
audioContext.info.duration = this._duration;
audioContext.parsingData.len += frameLength;
offset += frameLength;
frameIndex++;
}
if (offset < length) {
audioOverFlow = data.subarray(offset, length);
}
else {
audioOverFlow = undefined;
}
audioContext.audioOverFlow = audioOverFlow;
}
}
var TsDemuxer$1 = TsDemuxer;
class DemuxerInline extends Observer {
constructor(typeSupported, config, vendor, logger) {
super();
this.typeSupported = typeSupported;
this.config = config;
this.vendor = vendor;
this.logger = logger;
}
destroy() {
this.removeAllListeners();
const demuxer = this.demuxer;
const remuxer = this.remuxer;
if (demuxer) {
demuxer.destroy();
}
if (remuxer) {
remuxer.destroy();
}
}
push(data, keyTagInfo, initSegment, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS, iframeMediaStart, iframeDuration) {
if (!data) {
// if data is undefined and this.probeFn exists,
// all the demuxers will fail probing. We will still end up with the old probeFn.
// We will push Uint8Array(undefined) to the demuxer that owns this.probeFn, which will be fatal
return;
}
let demuxer = this.demuxer;
const _data = new Uint8Array(data);
if (!demuxer ||
// in case of continuity change, we might switch from content type (AAC container to TS container for example). this is signaled through the discontinuity argument.
// also a variant switch can also change the content type (TS container to fMP4 contaner for example). this is signaled through the trackSwitch argument.
// so let's check that current demuxer is still valid
((discontinuity || trackSwitch) && !this.probeFn(_data, this.logger))) {
const { typeSupported, config } = this;
const muxConfig = [
{ demux: MP4Demuxer, remux: MP4EncryptionRemuxer },
{ demux: TsDemuxer$1, remux: EsRemuxer },
{ demux: EC3Demuxer, remux: EsRemuxer },
{ demux: AC3Demuxer, remux: EsRemuxer },
{ demux: AACDemuxer, remux: EsRemuxer },
{ demux: MP3Demuxer, remux: EsRemuxer },
]; // move MP3Demuxer to last to avoid false positive mp3 detection.
// probe for content type
for (const mux of muxConfig) {
const { probe } = mux.demux;
if (probe(_data, this.logger)) {
this.remuxer = new mux.remux(this, config, typeSupported, this.vendor, this.logger);
demuxer = new mux.demux(this, this.remuxer, config, typeSupported, this.logger);
this.probeFn = probe;
break;
}
}
if (!demuxer) {
const payload = new FragParsingError(true, 'no demux matching with content found', ErrorResponses.DemuxerNotFound);
this.trigger(HlsEvent$1.INTERNAL_ERROR, payload);
return;
}
this.demuxer = demuxer;
}
const remuxer = this.remuxer;
const keyChange = !this.lastKeyTagInfo || (keyTagInfo && keyTagInfo.method !== 'NONE' && this.lastKeyTagInfo.uri !== keyTagInfo.uri);
this.lastKeyTagInfo = keyTagInfo;
if (discontinuity || trackSwitch || keyChange) {
// resetInitSegment error handling may need to know if we are in a discontinuity or track switch
demuxer.resetInitSegment(new Uint8Array(initSegment), duration, keyTagInfo, discontinuity);
remuxer.resetInitSegment();
}
if (discontinuity) {
const pts = defaultInitPTS ? convertTimestampToSeconds(defaultInitPTS) : undefined;
demuxer.resetTimeStamp(pts);
remuxer.resetTimeStamp(pts);
}
demuxer.append(_data, timeOffset, contiguous, accurateTimeOffset, keyTagInfo, iframeMediaStart, iframeDuration);
}
}
function generateUniqueID() {
let id = `${Date.now()}-${Math.random()}`;
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
id += `-${performance.now()}`;
}
return id;
}
class DemuxRPCServer {
constructor(rpc, logger) {
this.rpc = rpc;
this.logger = logger;
this.init = (typeSupported, config, vendor) => callback => {
const demuxSessionID = generateUniqueID();
const demuxer = (this.demuxers[demuxSessionID] = new DemuxerInline(typeSupported, config, vendor, this.logger));
[
DemuxerEvent.INIT_PTS_FOUND,
DemuxerEvent.FRAG_PARSING_INIT_SEGMENT,
DemuxerEvent.FRAG_PARSING_DATA,
DemuxerEvent.FRAG_PARSED,
HlsEvent$1.INTERNAL_ERROR
].forEach(event => {
demuxer.on(event, (data) => this.rpc.invoke('demuxer.event', [demuxSessionID, event, data])(() => { }));
});
callback(demuxSessionID);
};
this.push = (id, data, keyTagInfo, initSegment, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS, iframeMediaStart, iframeDuration) => callback => {
const demuxer = this.demuxers[id];
if (!demuxer) {
callback(undefined, `Demuxer with id "${id}" does not exist on push`);
return;
}
demuxer.push(data, keyTagInfo, initSegment, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS, iframeMediaStart, iframeDuration);
callback();
};
this.destroy = (id) => callback => {
const demuxer = this.demuxers[id];
if (!demuxer) {
this.logger.error(`Demuxer with id "${id}" does not exist on destroy`);
return;
}
demuxer.destroy();
delete this.demuxers[id];
callback();
};
this.demuxers = {};
rpc.register('demuxer.init', this.init);
rpc.register('demuxer.push', this.push);
rpc.register('demuxer.destroy', this.destroy);
}
}
// RPCWorkerService has client and server counterparts, where the service server
// runs in a Web Worker process, while the client remains in the main process.
class RPCWorkerService {
constructor(worker) {
this.worker = worker;
this.handlers = {};
this.deferers = {};
this._messageHandler = (event) => {
const { type, id, command, args, result, error } = event.data;
if (type === RPCWorkerMessageType.Invoke) {
try {
if (this.handlers[command] == null) {
throw new Error(`command ${command} not found`);
}
this.handlers[command](...args)(this._respond.bind(this, id, command));
}
catch (error) {
this._respond(id, command, null, new Error(`command ${command} not found`));
}
}
else if (type === RPCWorkerMessageType.Result) {
if (this.deferers[id] == null) {
return;
}
this.deferers[id](result, error);
delete this.deferers[id];
}
};
worker.addEventListener('message', this._messageHandler);
}
register(command, handler) {
if (this.handlers[command] != null) {
return false;
}
this.handlers[command] = handler;
}
unregister(command) {
if (this.handlers[command] != null) {
return false;
}
delete this.handlers[command];
}
invoke(command, args, transfer) {
return (callback = RPCWorkerService._fallbackCallback) => {
const id = generateUniqueID();
this.deferers[id] = callback;
const message = {
type: RPCWorkerMessageType.Invoke,
id,
command,
args,
};
this._send(message, transfer);
};
}
teardown(done) {
this.worker.removeEventListener('message', this._messageHandler);
done();
}
_respond(id, command, result, error, transfer) {
if (error instanceof Error) {
error = `[${error.name}] ${error.message}\n${error.stack}`;
}
const message = {
type: RPCWorkerMessageType.Result,
id,
command,
result,
error,
};
this._send(message, transfer);
}
_send(message, transfer = []) {
this.worker.postMessage(message, transfer.map((value) => (ArrayBuffer.isView(value) ? value.buffer : value)).filter((value) => value !== undefined));
}
}
RPCWorkerService._fallbackCallback = (result, error) => {
if (error != null) {
throw error;
}
};
var RPCWorkerMessageType;
(function (RPCWorkerMessageType) {
RPCWorkerMessageType[RPCWorkerMessageType["Invoke"] = 0] = "Invoke";
RPCWorkerMessageType[RPCWorkerMessageType["Result"] = 1] = "Result";
})(RPCWorkerMessageType || (RPCWorkerMessageType = {}));
// Minimal polyfill
// ArrayBuffer.isView() is relatively new
// https://caniuse.com/?search=arraybuffer
if (!ArrayBuffer['isView']) {
ArrayBuffer.isView = function isView(a) {
return a !== null && typeof a === 'object' && a['buffer'] instanceof ArrayBuffer;
};
}
const startWorker = () => {
const ctx = global$1;
const rpcService = new RPCWorkerService(ctx);
const logger = LoggerRPCClient(rpcService);
new CryptoRPCServer(rpcService, logger);
new DemuxRPCServer(rpcService, logger);
logger.info('WebWorker RPCService has started');
};
if (hasUMDWorker() && typeof __IN_WORKER__ !== 'undefined' && __IN_WORKER__) {
startWorker();
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate$2(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}
/** @deprecated */
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function isFunction$1(x) {
return typeof x === 'function';
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var _enable_super_gross_mode_that_will_cause_bad_things = false;
var config = {
Promise: undefined,
set useDeprecatedSynchronousErrorHandling(value) {
_enable_super_gross_mode_that_will_cause_bad_things = value;
},
get useDeprecatedSynchronousErrorHandling() {
return _enable_super_gross_mode_that_will_cause_bad_things;
},
};
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function hostReportError(err) {
setTimeout(function () { throw err; }, 0);
}
/** PURE_IMPORTS_START _config,_util_hostReportError PURE_IMPORTS_END */
var empty$1 = {
closed: true,
next: function (value) { },
error: function (err) {
if (config.useDeprecatedSynchronousErrorHandling) {
throw err;
}
else {
hostReportError(err);
}
},
complete: function () { }
};
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var isArray$1 = /*@__PURE__*/ (function () { return Array.isArray || (function (x) { return x && typeof x.length === 'number'; }); })();
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function isObject$1(x) {
return x !== null && typeof x === 'object';
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var UnsubscriptionErrorImpl = /*@__PURE__*/ (function () {
function UnsubscriptionErrorImpl(errors) {
Error.call(this);
this.message = errors ?
errors.length + " errors occurred during unsubscription:\n" + errors.map(function (err, i) { return i + 1 + ") " + err.toString(); }).join('\n ') : '';
this.name = 'UnsubscriptionError';
this.errors = errors;
return this;
}
UnsubscriptionErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
return UnsubscriptionErrorImpl;
})();
var UnsubscriptionError = UnsubscriptionErrorImpl;
/** PURE_IMPORTS_START _util_isArray,_util_isObject,_util_isFunction,_util_UnsubscriptionError PURE_IMPORTS_END */
var Subscription = /*@__PURE__*/ (function () {
function Subscription(unsubscribe) {
this.closed = false;
this._parentOrParents = null;
this._subscriptions = null;
if (unsubscribe) {
this._ctorUnsubscribe = true;
this._unsubscribe = unsubscribe;
}
}
Subscription.prototype.unsubscribe = function () {
var errors;
if (this.closed) {
return;
}
var _a = this, _parentOrParents = _a._parentOrParents, _ctorUnsubscribe = _a._ctorUnsubscribe, _unsubscribe = _a._unsubscribe, _subscriptions = _a._subscriptions;
this.closed = true;
this._parentOrParents = null;
this._subscriptions = null;
if (_parentOrParents instanceof Subscription) {
_parentOrParents.remove(this);
}
else if (_parentOrParents !== null) {
for (var index = 0; index < _parentOrParents.length; ++index) {
var parent_1 = _parentOrParents[index];
parent_1.remove(this);
}
}
if (isFunction$1(_unsubscribe)) {
if (_ctorUnsubscribe) {
this._unsubscribe = undefined;
}
try {
_unsubscribe.call(this);
}
catch (e) {
errors = e instanceof UnsubscriptionError ? flattenUnsubscriptionErrors(e.errors) : [e];
}
}
if (isArray$1(_subscriptions)) {
var index = -1;
var len = _subscriptions.length;
while (++index < len) {
var sub = _subscriptions[index];
if (isObject$1(sub)) {
try {
sub.unsubscribe();
}
catch (e) {
errors = errors || [];
if (e instanceof UnsubscriptionError) {
errors = errors.concat(flattenUnsubscriptionErrors(e.errors));
}
else {
errors.push(e);
}
}
}
}
}
if (errors) {
throw new UnsubscriptionError(errors);
}
};
Subscription.prototype.add = function (teardown) {
var subscription = teardown;
if (!teardown) {
return Subscription.EMPTY;
}
switch (typeof teardown) {
case 'function':
subscription = new Subscription(teardown);
case 'object':
if (subscription === this || subscription.closed || typeof subscription.unsubscribe !== 'function') {
return subscription;
}
else if (this.closed) {
subscription.unsubscribe();
return subscription;
}
else if (!(subscription instanceof Subscription)) {
var tmp = subscription;
subscription = new Subscription();
subscription._subscriptions = [tmp];
}
break;
default: {
throw new Error('unrecognized teardown ' + teardown + ' added to Subscription.');
}
}
var _parentOrParents = subscription._parentOrParents;
if (_parentOrParents === null) {
subscription._parentOrParents = this;
}
else if (_parentOrParents instanceof Subscription) {
if (_parentOrParents === this) {
return subscription;
}
subscription._parentOrParents = [_parentOrParents, this];
}
else if (_parentOrParents.indexOf(this) === -1) {
_parentOrParents.push(this);
}
else {
return subscription;
}
var subscriptions = this._subscriptions;
if (subscriptions === null) {
this._subscriptions = [subscription];
}
else {
subscriptions.push(subscription);
}
return subscription;
};
Subscription.prototype.remove = function (subscription) {
var subscriptions = this._subscriptions;
if (subscriptions) {
var subscriptionIndex = subscriptions.indexOf(subscription);
if (subscriptionIndex !== -1) {
subscriptions.splice(subscriptionIndex, 1);
}
}
};
Subscription.EMPTY = (function (empty) {
empty.closed = true;
return empty;
}(new Subscription()));
return Subscription;
}());
function flattenUnsubscriptionErrors(errors) {
return errors.reduce(function (errs, err) { return errs.concat((err instanceof UnsubscriptionError) ? err.errors : err); }, []);
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var rxSubscriber = /*@__PURE__*/ (function () {
return typeof Symbol === 'function'
? /*@__PURE__*/ Symbol('rxSubscriber')
: '@@rxSubscriber_' + /*@__PURE__*/ Math.random();
})();
/** PURE_IMPORTS_START tslib,_util_isFunction,_Observer,_Subscription,_internal_symbol_rxSubscriber,_config,_util_hostReportError PURE_IMPORTS_END */
var Subscriber = /*@__PURE__*/ (function (_super) {
__extends(Subscriber, _super);
function Subscriber(destinationOrNext, error, complete) {
var _this = _super.call(this) || this;
_this.syncErrorValue = null;
_this.syncErrorThrown = false;
_this.syncErrorThrowable = false;
_this.isStopped = false;
switch (arguments.length) {
case 0:
_this.destination = empty$1;
break;
case 1:
if (!destinationOrNext) {
_this.destination = empty$1;
break;
}
if (typeof destinationOrNext === 'object') {
if (destinationOrNext instanceof Subscriber) {
_this.syncErrorThrowable = destinationOrNext.syncErrorThrowable;
_this.destination = destinationOrNext;
destinationOrNext.add(_this);
}
else {
_this.syncErrorThrowable = true;
_this.destination = new SafeSubscriber(_this, destinationOrNext);
}
break;
}
default:
_this.syncErrorThrowable = true;
_this.destination = new SafeSubscriber(_this, destinationOrNext, error, complete);
break;
}
return _this;
}
Subscriber.prototype[rxSubscriber] = function () { return this; };
Subscriber.create = function (next, error, complete) {
var subscriber = new Subscriber(next, error, complete);
subscriber.syncErrorThrowable = false;
return subscriber;
};
Subscriber.prototype.next = function (value) {
if (!this.isStopped) {
this._next(value);
}
};
Subscriber.prototype.error = function (err) {
if (!this.isStopped) {
this.isStopped = true;
this._error(err);
}
};
Subscriber.prototype.complete = function () {
if (!this.isStopped) {
this.isStopped = true;
this._complete();
}
};
Subscriber.prototype.unsubscribe = function () {
if (this.closed) {
return;
}
this.isStopped = true;
_super.prototype.unsubscribe.call(this);
};
Subscriber.prototype._next = function (value) {
this.destination.next(value);
};
Subscriber.prototype._error = function (err) {
this.destination.error(err);
this.unsubscribe();
};
Subscriber.prototype._complete = function () {
this.destination.complete();
this.unsubscribe();
};
Subscriber.prototype._unsubscribeAndRecycle = function () {
var _parentOrParents = this._parentOrParents;
this._parentOrParents = null;
this.unsubscribe();
this.closed = false;
this.isStopped = false;
this._parentOrParents = _parentOrParents;
return this;
};
return Subscriber;
}(Subscription));
var SafeSubscriber = /*@__PURE__*/ (function (_super) {
__extends(SafeSubscriber, _super);
function SafeSubscriber(_parentSubscriber, observerOrNext, error, complete) {
var _this = _super.call(this) || this;
_this._parentSubscriber = _parentSubscriber;
var next;
var context = _this;
if (isFunction$1(observerOrNext)) {
next = observerOrNext;
}
else if (observerOrNext) {
next = observerOrNext.next;
error = observerOrNext.error;
complete = observerOrNext.complete;
if (observerOrNext !== empty$1) {
context = Object.create(observerOrNext);
if (isFunction$1(context.unsubscribe)) {
_this.add(context.unsubscribe.bind(context));
}
context.unsubscribe = _this.unsubscribe.bind(_this);
}
}
_this._context = context;
_this._next = next;
_this._error = error;
_this._complete = complete;
return _this;
}
SafeSubscriber.prototype.next = function (value) {
if (!this.isStopped && this._next) {
var _parentSubscriber = this._parentSubscriber;
if (!config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
this.__tryOrUnsub(this._next, value);
}
else if (this.__tryOrSetError(_parentSubscriber, this._next, value)) {
this.unsubscribe();
}
}
};
SafeSubscriber.prototype.error = function (err) {
if (!this.isStopped) {
var _parentSubscriber = this._parentSubscriber;
var useDeprecatedSynchronousErrorHandling = config.useDeprecatedSynchronousErrorHandling;
if (this._error) {
if (!useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
this.__tryOrUnsub(this._error, err);
this.unsubscribe();
}
else {
this.__tryOrSetError(_parentSubscriber, this._error, err);
this.unsubscribe();
}
}
else if (!_parentSubscriber.syncErrorThrowable) {
this.unsubscribe();
if (useDeprecatedSynchronousErrorHandling) {
throw err;
}
hostReportError(err);
}
else {
if (useDeprecatedSynchronousErrorHandling) {
_parentSubscriber.syncErrorValue = err;
_parentSubscriber.syncErrorThrown = true;
}
else {
hostReportError(err);
}
this.unsubscribe();
}
}
};
SafeSubscriber.prototype.complete = function () {
var _this = this;
if (!this.isStopped) {
var _parentSubscriber = this._parentSubscriber;
if (this._complete) {
var wrappedComplete = function () { return _this._complete.call(_this._context); };
if (!config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
this.__tryOrUnsub(wrappedComplete);
this.unsubscribe();
}
else {
this.__tryOrSetError(_parentSubscriber, wrappedComplete);
this.unsubscribe();
}
}
else {
this.unsubscribe();
}
}
};
SafeSubscriber.prototype.__tryOrUnsub = function (fn, value) {
try {
fn.call(this._context, value);
}
catch (err) {
this.unsubscribe();
if (config.useDeprecatedSynchronousErrorHandling) {
throw err;
}
else {
hostReportError(err);
}
}
};
SafeSubscriber.prototype.__tryOrSetError = function (parent, fn, value) {
if (!config.useDeprecatedSynchronousErrorHandling) {
throw new Error('bad call');
}
try {
fn.call(this._context, value);
}
catch (err) {
if (config.useDeprecatedSynchronousErrorHandling) {
parent.syncErrorValue = err;
parent.syncErrorThrown = true;
return true;
}
else {
hostReportError(err);
return true;
}
}
return false;
};
SafeSubscriber.prototype._unsubscribe = function () {
var _parentSubscriber = this._parentSubscriber;
this._context = null;
this._parentSubscriber = null;
_parentSubscriber.unsubscribe();
};
return SafeSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START _Subscriber PURE_IMPORTS_END */
function canReportError(observer) {
while (observer) {
var _a = observer, closed_1 = _a.closed, destination = _a.destination, isStopped = _a.isStopped;
if (closed_1 || isStopped) {
return false;
}
else if (destination && destination instanceof Subscriber) {
observer = destination;
}
else {
observer = null;
}
}
return true;
}
/** PURE_IMPORTS_START _Subscriber,_symbol_rxSubscriber,_Observer PURE_IMPORTS_END */
function toSubscriber(nextOrObserver, error, complete) {
if (nextOrObserver) {
if (nextOrObserver instanceof Subscriber) {
return nextOrObserver;
}
if (nextOrObserver[rxSubscriber]) {
return nextOrObserver[rxSubscriber]();
}
}
if (!nextOrObserver && !error && !complete) {
return new Subscriber(empty$1);
}
return new Subscriber(nextOrObserver, error, complete);
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var observable = /*@__PURE__*/ (function () { return typeof Symbol === 'function' && Symbol.observable || '@@observable'; })();
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function identity(x) {
return x;
}
/** PURE_IMPORTS_START _identity PURE_IMPORTS_END */
function pipe() {
var fns = [];
for (var _i = 0; _i < arguments.length; _i++) {
fns[_i] = arguments[_i];
}
return pipeFromArray(fns);
}
function pipeFromArray(fns) {
if (fns.length === 0) {
return identity;
}
if (fns.length === 1) {
return fns[0];
}
return function piped(input) {
return fns.reduce(function (prev, fn) { return fn(prev); }, input);
};
}
/** PURE_IMPORTS_START _util_canReportError,_util_toSubscriber,_symbol_observable,_util_pipe,_config PURE_IMPORTS_END */
var Observable = /*@__PURE__*/ (function () {
function Observable(subscribe) {
this._isScalar = false;
if (subscribe) {
this._subscribe = subscribe;
}
}
Observable.prototype.lift = function (operator) {
var observable = new Observable();
observable.source = this;
observable.operator = operator;
return observable;
};
Observable.prototype.subscribe = function (observerOrNext, error, complete) {
var operator = this.operator;
var sink = toSubscriber(observerOrNext, error, complete);
if (operator) {
sink.add(operator.call(sink, this.source));
}
else {
sink.add(this.source || (config.useDeprecatedSynchronousErrorHandling && !sink.syncErrorThrowable) ?
this._subscribe(sink) :
this._trySubscribe(sink));
}
if (config.useDeprecatedSynchronousErrorHandling) {
if (sink.syncErrorThrowable) {
sink.syncErrorThrowable = false;
if (sink.syncErrorThrown) {
throw sink.syncErrorValue;
}
}
}
return sink;
};
Observable.prototype._trySubscribe = function (sink) {
try {
return this._subscribe(sink);
}
catch (err) {
if (config.useDeprecatedSynchronousErrorHandling) {
sink.syncErrorThrown = true;
sink.syncErrorValue = err;
}
if (canReportError(sink)) {
sink.error(err);
}
else {
console.warn(err);
}
}
};
Observable.prototype.forEach = function (next, promiseCtor) {
var _this = this;
promiseCtor = getPromiseCtor(promiseCtor);
return new promiseCtor(function (resolve, reject) {
var subscription;
subscription = _this.subscribe(function (value) {
try {
next(value);
}
catch (err) {
reject(err);
if (subscription) {
subscription.unsubscribe();
}
}
}, reject, resolve);
});
};
Observable.prototype._subscribe = function (subscriber) {
var source = this.source;
return source && source.subscribe(subscriber);
};
Observable.prototype[observable] = function () {
return this;
};
Observable.prototype.pipe = function () {
var operations = [];
for (var _i = 0; _i < arguments.length; _i++) {
operations[_i] = arguments[_i];
}
if (operations.length === 0) {
return this;
}
return pipeFromArray(operations)(this);
};
Observable.prototype.toPromise = function (promiseCtor) {
var _this = this;
promiseCtor = getPromiseCtor(promiseCtor);
return new promiseCtor(function (resolve, reject) {
var value;
_this.subscribe(function (x) { return value = x; }, function (err) { return reject(err); }, function () { return resolve(value); });
});
};
Observable.create = function (subscribe) {
return new Observable(subscribe);
};
return Observable;
}());
function getPromiseCtor(promiseCtor) {
if (!promiseCtor) {
promiseCtor = config.Promise || Promise;
}
if (!promiseCtor) {
throw new Error('no Promise impl found');
}
return promiseCtor;
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var ObjectUnsubscribedErrorImpl = /*@__PURE__*/ (function () {
function ObjectUnsubscribedErrorImpl() {
Error.call(this);
this.message = 'object unsubscribed';
this.name = 'ObjectUnsubscribedError';
return this;
}
ObjectUnsubscribedErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
return ObjectUnsubscribedErrorImpl;
})();
var ObjectUnsubscribedError = ObjectUnsubscribedErrorImpl;
/** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */
var SubjectSubscription = /*@__PURE__*/ (function (_super) {
__extends(SubjectSubscription, _super);
function SubjectSubscription(subject, subscriber) {
var _this = _super.call(this) || this;
_this.subject = subject;
_this.subscriber = subscriber;
_this.closed = false;
return _this;
}
SubjectSubscription.prototype.unsubscribe = function () {
if (this.closed) {
return;
}
this.closed = true;
var subject = this.subject;
var observers = subject.observers;
this.subject = null;
if (!observers || observers.length === 0 || subject.isStopped || subject.closed) {
return;
}
var subscriberIndex = observers.indexOf(this.subscriber);
if (subscriberIndex !== -1) {
observers.splice(subscriberIndex, 1);
}
};
return SubjectSubscription;
}(Subscription));
/** PURE_IMPORTS_START tslib,_Observable,_Subscriber,_Subscription,_util_ObjectUnsubscribedError,_SubjectSubscription,_internal_symbol_rxSubscriber PURE_IMPORTS_END */
var SubjectSubscriber = /*@__PURE__*/ (function (_super) {
__extends(SubjectSubscriber, _super);
function SubjectSubscriber(destination) {
var _this = _super.call(this, destination) || this;
_this.destination = destination;
return _this;
}
return SubjectSubscriber;
}(Subscriber));
var Subject = /*@__PURE__*/ (function (_super) {
__extends(Subject, _super);
function Subject() {
var _this = _super.call(this) || this;
_this.observers = [];
_this.closed = false;
_this.isStopped = false;
_this.hasError = false;
_this.thrownError = null;
return _this;
}
Subject.prototype[rxSubscriber] = function () {
return new SubjectSubscriber(this);
};
Subject.prototype.lift = function (operator) {
var subject = new AnonymousSubject(this, this);
subject.operator = operator;
return subject;
};
Subject.prototype.next = function (value) {
if (this.closed) {
throw new ObjectUnsubscribedError();
}
if (!this.isStopped) {
var observers = this.observers;
var len = observers.length;
var copy = observers.slice();
for (var i = 0; i < len; i++) {
copy[i].next(value);
}
}
};
Subject.prototype.error = function (err) {
if (this.closed) {
throw new ObjectUnsubscribedError();
}
this.hasError = true;
this.thrownError = err;
this.isStopped = true;
var observers = this.observers;
var len = observers.length;
var copy = observers.slice();
for (var i = 0; i < len; i++) {
copy[i].error(err);
}
this.observers.length = 0;
};
Subject.prototype.complete = function () {
if (this.closed) {
throw new ObjectUnsubscribedError();
}
this.isStopped = true;
var observers = this.observers;
var len = observers.length;
var copy = observers.slice();
for (var i = 0; i < len; i++) {
copy[i].complete();
}
this.observers.length = 0;
};
Subject.prototype.unsubscribe = function () {
this.isStopped = true;
this.closed = true;
this.observers = null;
};
Subject.prototype._trySubscribe = function (subscriber) {
if (this.closed) {
throw new ObjectUnsubscribedError();
}
else {
return _super.prototype._trySubscribe.call(this, subscriber);
}
};
Subject.prototype._subscribe = function (subscriber) {
if (this.closed) {
throw new ObjectUnsubscribedError();
}
else if (this.hasError) {
subscriber.error(this.thrownError);
return Subscription.EMPTY;
}
else if (this.isStopped) {
subscriber.complete();
return Subscription.EMPTY;
}
else {
this.observers.push(subscriber);
return new SubjectSubscription(this, subscriber);
}
};
Subject.prototype.asObservable = function () {
var observable = new Observable();
observable.source = this;
return observable;
};
Subject.create = function (destination, source) {
return new AnonymousSubject(destination, source);
};
return Subject;
}(Observable));
var AnonymousSubject = /*@__PURE__*/ (function (_super) {
__extends(AnonymousSubject, _super);
function AnonymousSubject(destination, source) {
var _this = _super.call(this) || this;
_this.destination = destination;
_this.source = source;
return _this;
}
AnonymousSubject.prototype.next = function (value) {
var destination = this.destination;
if (destination && destination.next) {
destination.next(value);
}
};
AnonymousSubject.prototype.error = function (err) {
var destination = this.destination;
if (destination && destination.error) {
this.destination.error(err);
}
};
AnonymousSubject.prototype.complete = function () {
var destination = this.destination;
if (destination && destination.complete) {
this.destination.complete();
}
};
AnonymousSubject.prototype._subscribe = function (subscriber) {
var source = this.source;
if (source) {
return this.source.subscribe(subscriber);
}
else {
return Subscription.EMPTY;
}
};
return AnonymousSubject;
}(Subject));
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function refCount() {
return function refCountOperatorFunction(source) {
return source.lift(new RefCountOperator(source));
};
}
var RefCountOperator = /*@__PURE__*/ (function () {
function RefCountOperator(connectable) {
this.connectable = connectable;
}
RefCountOperator.prototype.call = function (subscriber, source) {
var connectable = this.connectable;
connectable._refCount++;
var refCounter = new RefCountSubscriber(subscriber, connectable);
var subscription = source.subscribe(refCounter);
if (!refCounter.closed) {
refCounter.connection = connectable.connect();
}
return subscription;
};
return RefCountOperator;
}());
var RefCountSubscriber = /*@__PURE__*/ (function (_super) {
__extends(RefCountSubscriber, _super);
function RefCountSubscriber(destination, connectable) {
var _this = _super.call(this, destination) || this;
_this.connectable = connectable;
return _this;
}
RefCountSubscriber.prototype._unsubscribe = function () {
var connectable = this.connectable;
if (!connectable) {
this.connection = null;
return;
}
this.connectable = null;
var refCount = connectable._refCount;
if (refCount <= 0) {
this.connection = null;
return;
}
connectable._refCount = refCount - 1;
if (refCount > 1) {
this.connection = null;
return;
}
var connection = this.connection;
var sharedConnection = connectable._connection;
this.connection = null;
if (sharedConnection && (!connection || sharedConnection === connection)) {
sharedConnection.unsubscribe();
}
};
return RefCountSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subject,_Observable,_Subscriber,_Subscription,_operators_refCount PURE_IMPORTS_END */
var ConnectableObservable = /*@__PURE__*/ (function (_super) {
__extends(ConnectableObservable, _super);
function ConnectableObservable(source, subjectFactory) {
var _this = _super.call(this) || this;
_this.source = source;
_this.subjectFactory = subjectFactory;
_this._refCount = 0;
_this._isComplete = false;
return _this;
}
ConnectableObservable.prototype._subscribe = function (subscriber) {
return this.getSubject().subscribe(subscriber);
};
ConnectableObservable.prototype.getSubject = function () {
var subject = this._subject;
if (!subject || subject.isStopped) {
this._subject = this.subjectFactory();
}
return this._subject;
};
ConnectableObservable.prototype.connect = function () {
var connection = this._connection;
if (!connection) {
this._isComplete = false;
connection = this._connection = new Subscription();
connection.add(this.source
.subscribe(new ConnectableSubscriber(this.getSubject(), this)));
if (connection.closed) {
this._connection = null;
connection = Subscription.EMPTY;
}
}
return connection;
};
ConnectableObservable.prototype.refCount = function () {
return refCount()(this);
};
return ConnectableObservable;
}(Observable));
var connectableObservableDescriptor = /*@__PURE__*/ (function () {
var connectableProto = ConnectableObservable.prototype;
return {
operator: { value: null },
_refCount: { value: 0, writable: true },
_subject: { value: null, writable: true },
_connection: { value: null, writable: true },
_subscribe: { value: connectableProto._subscribe },
_isComplete: { value: connectableProto._isComplete, writable: true },
getSubject: { value: connectableProto.getSubject },
connect: { value: connectableProto.connect },
refCount: { value: connectableProto.refCount }
};
})();
var ConnectableSubscriber = /*@__PURE__*/ (function (_super) {
__extends(ConnectableSubscriber, _super);
function ConnectableSubscriber(destination, connectable) {
var _this = _super.call(this, destination) || this;
_this.connectable = connectable;
return _this;
}
ConnectableSubscriber.prototype._error = function (err) {
this._unsubscribe();
_super.prototype._error.call(this, err);
};
ConnectableSubscriber.prototype._complete = function () {
this.connectable._isComplete = true;
this._unsubscribe();
_super.prototype._complete.call(this);
};
ConnectableSubscriber.prototype._unsubscribe = function () {
var connectable = this.connectable;
if (connectable) {
this.connectable = null;
var connection = connectable._connection;
connectable._refCount = 0;
connectable._subject = null;
connectable._connection = null;
if (connection) {
connection.unsubscribe();
}
}
};
return ConnectableSubscriber;
}(SubjectSubscriber));
/** PURE_IMPORTS_START tslib,_Subject,_util_ObjectUnsubscribedError PURE_IMPORTS_END */
var BehaviorSubject = /*@__PURE__*/ (function (_super) {
__extends(BehaviorSubject, _super);
function BehaviorSubject(_value) {
var _this = _super.call(this) || this;
_this._value = _value;
return _this;
}
Object.defineProperty(BehaviorSubject.prototype, "value", {
get: function () {
return this.getValue();
},
enumerable: true,
configurable: true
});
BehaviorSubject.prototype._subscribe = function (subscriber) {
var subscription = _super.prototype._subscribe.call(this, subscriber);
if (subscription && !subscription.closed) {
subscriber.next(this._value);
}
return subscription;
};
BehaviorSubject.prototype.getValue = function () {
if (this.hasError) {
throw this.thrownError;
}
else if (this.closed) {
throw new ObjectUnsubscribedError();
}
else {
return this._value;
}
};
BehaviorSubject.prototype.next = function (value) {
_super.prototype.next.call(this, this._value = value);
};
return BehaviorSubject;
}(Subject));
/** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */
var Action = /*@__PURE__*/ (function (_super) {
__extends(Action, _super);
function Action(scheduler, work) {
return _super.call(this) || this;
}
Action.prototype.schedule = function (state, delay) {
return this;
};
return Action;
}(Subscription));
/** PURE_IMPORTS_START tslib,_Action PURE_IMPORTS_END */
var AsyncAction = /*@__PURE__*/ (function (_super) {
__extends(AsyncAction, _super);
function AsyncAction(scheduler, work) {
var _this = _super.call(this, scheduler, work) || this;
_this.scheduler = scheduler;
_this.work = work;
_this.pending = false;
return _this;
}
AsyncAction.prototype.schedule = function (state, delay) {
if (delay === void 0) {
delay = 0;
}
if (this.closed) {
return this;
}
this.state = state;
var id = this.id;
var scheduler = this.scheduler;
if (id != null) {
this.id = this.recycleAsyncId(scheduler, id, delay);
}
this.pending = true;
this.delay = delay;
this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);
return this;
};
AsyncAction.prototype.requestAsyncId = function (scheduler, id, delay) {
if (delay === void 0) {
delay = 0;
}
return setInterval(scheduler.flush.bind(scheduler, this), delay);
};
AsyncAction.prototype.recycleAsyncId = function (scheduler, id, delay) {
if (delay === void 0) {
delay = 0;
}
if (delay !== null && this.delay === delay && this.pending === false) {
return id;
}
clearInterval(id);
return undefined;
};
AsyncAction.prototype.execute = function (state, delay) {
if (this.closed) {
return new Error('executing a cancelled action');
}
this.pending = false;
var error = this._execute(state, delay);
if (error) {
return error;
}
else if (this.pending === false && this.id != null) {
this.id = this.recycleAsyncId(this.scheduler, this.id, null);
}
};
AsyncAction.prototype._execute = function (state, delay) {
var errored = false;
var errorValue = undefined;
try {
this.work(state);
}
catch (e) {
errored = true;
errorValue = !!e && e || new Error(e);
}
if (errored) {
this.unsubscribe();
return errorValue;
}
};
AsyncAction.prototype._unsubscribe = function () {
var id = this.id;
var scheduler = this.scheduler;
var actions = scheduler.actions;
var index = actions.indexOf(this);
this.work = null;
this.state = null;
this.pending = false;
this.scheduler = null;
if (index !== -1) {
actions.splice(index, 1);
}
if (id != null) {
this.id = this.recycleAsyncId(scheduler, id, null);
}
this.delay = null;
};
return AsyncAction;
}(Action));
/** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */
var QueueAction = /*@__PURE__*/ (function (_super) {
__extends(QueueAction, _super);
function QueueAction(scheduler, work) {
var _this = _super.call(this, scheduler, work) || this;
_this.scheduler = scheduler;
_this.work = work;
return _this;
}
QueueAction.prototype.schedule = function (state, delay) {
if (delay === void 0) {
delay = 0;
}
if (delay > 0) {
return _super.prototype.schedule.call(this, state, delay);
}
this.delay = delay;
this.state = state;
this.scheduler.flush(this);
return this;
};
QueueAction.prototype.execute = function (state, delay) {
return (delay > 0 || this.closed) ?
_super.prototype.execute.call(this, state, delay) :
this._execute(state, delay);
};
QueueAction.prototype.requestAsyncId = function (scheduler, id, delay) {
if (delay === void 0) {
delay = 0;
}
if ((delay !== null && delay > 0) || (delay === null && this.delay > 0)) {
return _super.prototype.requestAsyncId.call(this, scheduler, id, delay);
}
return scheduler.flush(this);
};
return QueueAction;
}(AsyncAction));
var Scheduler = /*@__PURE__*/ (function () {
function Scheduler(SchedulerAction, now) {
if (now === void 0) {
now = Scheduler.now;
}
this.SchedulerAction = SchedulerAction;
this.now = now;
}
Scheduler.prototype.schedule = function (work, delay, state) {
if (delay === void 0) {
delay = 0;
}
return new this.SchedulerAction(this, work).schedule(state, delay);
};
Scheduler.now = function () { return Date.now(); };
return Scheduler;
}());
/** PURE_IMPORTS_START tslib,_Scheduler PURE_IMPORTS_END */
var AsyncScheduler = /*@__PURE__*/ (function (_super) {
__extends(AsyncScheduler, _super);
function AsyncScheduler(SchedulerAction, now) {
if (now === void 0) {
now = Scheduler.now;
}
var _this = _super.call(this, SchedulerAction, function () {
if (AsyncScheduler.delegate && AsyncScheduler.delegate !== _this) {
return AsyncScheduler.delegate.now();
}
else {
return now();
}
}) || this;
_this.actions = [];
_this.active = false;
_this.scheduled = undefined;
return _this;
}
AsyncScheduler.prototype.schedule = function (work, delay, state) {
if (delay === void 0) {
delay = 0;
}
if (AsyncScheduler.delegate && AsyncScheduler.delegate !== this) {
return AsyncScheduler.delegate.schedule(work, delay, state);
}
else {
return _super.prototype.schedule.call(this, work, delay, state);
}
};
AsyncScheduler.prototype.flush = function (action) {
var actions = this.actions;
if (this.active) {
actions.push(action);
return;
}
var error;
this.active = true;
do {
if (error = action.execute(action.state, action.delay)) {
break;
}
} while (action = actions.shift());
this.active = false;
if (error) {
while (action = actions.shift()) {
action.unsubscribe();
}
throw error;
}
};
return AsyncScheduler;
}(Scheduler));
/** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */
var QueueScheduler = /*@__PURE__*/ (function (_super) {
__extends(QueueScheduler, _super);
function QueueScheduler() {
return _super !== null && _super.apply(this, arguments) || this;
}
return QueueScheduler;
}(AsyncScheduler));
/** PURE_IMPORTS_START _QueueAction,_QueueScheduler PURE_IMPORTS_END */
var queueScheduler = /*@__PURE__*/ new QueueScheduler(QueueAction);
var queue = queueScheduler;
/** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */
var EMPTY = /*@__PURE__*/ new Observable(function (subscriber) { return subscriber.complete(); });
function empty(scheduler) {
return scheduler ? emptyScheduled(scheduler) : EMPTY;
}
function emptyScheduled(scheduler) {
return new Observable(function (subscriber) { return scheduler.schedule(function () { return subscriber.complete(); }); });
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function isScheduler(value) {
return value && typeof value.schedule === 'function';
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var subscribeToArray = function (array) {
return function (subscriber) {
for (var i = 0, len = array.length; i < len && !subscriber.closed; i++) {
subscriber.next(array[i]);
}
subscriber.complete();
};
};
/** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */
function scheduleArray(input, scheduler) {
return new Observable(function (subscriber) {
var sub = new Subscription();
var i = 0;
sub.add(scheduler.schedule(function () {
if (i === input.length) {
subscriber.complete();
return;
}
subscriber.next(input[i++]);
if (!subscriber.closed) {
sub.add(this.schedule());
}
}));
return sub;
});
}
/** PURE_IMPORTS_START _Observable,_util_subscribeToArray,_scheduled_scheduleArray PURE_IMPORTS_END */
function fromArray(input, scheduler) {
if (!scheduler) {
return new Observable(subscribeToArray(input));
}
else {
return scheduleArray(input, scheduler);
}
}
/** PURE_IMPORTS_START _util_isScheduler,_fromArray,_scheduled_scheduleArray PURE_IMPORTS_END */
function of() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var scheduler = args[args.length - 1];
if (isScheduler(scheduler)) {
args.pop();
return scheduleArray(args, scheduler);
}
else {
return fromArray(args);
}
}
/** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */
function throwError(error, scheduler) {
if (!scheduler) {
return new Observable(function (subscriber) { return subscriber.error(error); });
}
else {
return new Observable(function (subscriber) { return scheduler.schedule(dispatch$1, 0, { error: error, subscriber: subscriber }); });
}
}
function dispatch$1(_a) {
var error = _a.error, subscriber = _a.subscriber;
subscriber.error(error);
}
/** PURE_IMPORTS_START _observable_empty,_observable_of,_observable_throwError PURE_IMPORTS_END */
var Notification = /*@__PURE__*/ (function () {
function Notification(kind, value, error) {
this.kind = kind;
this.value = value;
this.error = error;
this.hasValue = kind === 'N';
}
Notification.prototype.observe = function (observer) {
switch (this.kind) {
case 'N':
return observer.next && observer.next(this.value);
case 'E':
return observer.error && observer.error(this.error);
case 'C':
return observer.complete && observer.complete();
}
};
Notification.prototype.do = function (next, error, complete) {
var kind = this.kind;
switch (kind) {
case 'N':
return next && next(this.value);
case 'E':
return error && error(this.error);
case 'C':
return complete && complete();
}
};
Notification.prototype.accept = function (nextOrObserver, error, complete) {
if (nextOrObserver && typeof nextOrObserver.next === 'function') {
return this.observe(nextOrObserver);
}
else {
return this.do(nextOrObserver, error, complete);
}
};
Notification.prototype.toObservable = function () {
var kind = this.kind;
switch (kind) {
case 'N':
return of(this.value);
case 'E':
return throwError(this.error);
case 'C':
return empty();
}
throw new Error('unexpected notification kind value');
};
Notification.createNext = function (value) {
if (typeof value !== 'undefined') {
return new Notification('N', value);
}
return Notification.undefinedValueNotification;
};
Notification.createError = function (err) {
return new Notification('E', undefined, err);
};
Notification.createComplete = function () {
return Notification.completeNotification;
};
Notification.completeNotification = new Notification('C');
Notification.undefinedValueNotification = new Notification('N', undefined);
return Notification;
}());
/** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */
function observeOn(scheduler, delay) {
if (delay === void 0) {
delay = 0;
}
return function observeOnOperatorFunction(source) {
return source.lift(new ObserveOnOperator(scheduler, delay));
};
}
var ObserveOnOperator = /*@__PURE__*/ (function () {
function ObserveOnOperator(scheduler, delay) {
if (delay === void 0) {
delay = 0;
}
this.scheduler = scheduler;
this.delay = delay;
}
ObserveOnOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new ObserveOnSubscriber(subscriber, this.scheduler, this.delay));
};
return ObserveOnOperator;
}());
var ObserveOnSubscriber = /*@__PURE__*/ (function (_super) {
__extends(ObserveOnSubscriber, _super);
function ObserveOnSubscriber(destination, scheduler, delay) {
if (delay === void 0) {
delay = 0;
}
var _this = _super.call(this, destination) || this;
_this.scheduler = scheduler;
_this.delay = delay;
return _this;
}
ObserveOnSubscriber.dispatch = function (arg) {
var notification = arg.notification, destination = arg.destination;
notification.observe(destination);
this.unsubscribe();
};
ObserveOnSubscriber.prototype.scheduleMessage = function (notification) {
var destination = this.destination;
destination.add(this.scheduler.schedule(ObserveOnSubscriber.dispatch, this.delay, new ObserveOnMessage(notification, this.destination)));
};
ObserveOnSubscriber.prototype._next = function (value) {
this.scheduleMessage(Notification.createNext(value));
};
ObserveOnSubscriber.prototype._error = function (err) {
this.scheduleMessage(Notification.createError(err));
this.unsubscribe();
};
ObserveOnSubscriber.prototype._complete = function () {
this.scheduleMessage(Notification.createComplete());
this.unsubscribe();
};
return ObserveOnSubscriber;
}(Subscriber));
var ObserveOnMessage = /*@__PURE__*/ (function () {
function ObserveOnMessage(notification, destination) {
this.notification = notification;
this.destination = destination;
}
return ObserveOnMessage;
}());
/** PURE_IMPORTS_START tslib,_Subject,_scheduler_queue,_Subscription,_operators_observeOn,_util_ObjectUnsubscribedError,_SubjectSubscription PURE_IMPORTS_END */
var ReplaySubject = /*@__PURE__*/ (function (_super) {
__extends(ReplaySubject, _super);
function ReplaySubject(bufferSize, windowTime, scheduler) {
if (bufferSize === void 0) {
bufferSize = Number.POSITIVE_INFINITY;
}
if (windowTime === void 0) {
windowTime = Number.POSITIVE_INFINITY;
}
var _this = _super.call(this) || this;
_this.scheduler = scheduler;
_this._events = [];
_this._infiniteTimeWindow = false;
_this._bufferSize = bufferSize < 1 ? 1 : bufferSize;
_this._windowTime = windowTime < 1 ? 1 : windowTime;
if (windowTime === Number.POSITIVE_INFINITY) {
_this._infiniteTimeWindow = true;
_this.next = _this.nextInfiniteTimeWindow;
}
else {
_this.next = _this.nextTimeWindow;
}
return _this;
}
ReplaySubject.prototype.nextInfiniteTimeWindow = function (value) {
if (!this.isStopped) {
var _events = this._events;
_events.push(value);
if (_events.length > this._bufferSize) {
_events.shift();
}
}
_super.prototype.next.call(this, value);
};
ReplaySubject.prototype.nextTimeWindow = function (value) {
if (!this.isStopped) {
this._events.push(new ReplayEvent(this._getNow(), value));
this._trimBufferThenGetEvents();
}
_super.prototype.next.call(this, value);
};
ReplaySubject.prototype._subscribe = function (subscriber) {
var _infiniteTimeWindow = this._infiniteTimeWindow;
var _events = _infiniteTimeWindow ? this._events : this._trimBufferThenGetEvents();
var scheduler = this.scheduler;
var len = _events.length;
var subscription;
if (this.closed) {
throw new ObjectUnsubscribedError();
}
else if (this.isStopped || this.hasError) {
subscription = Subscription.EMPTY;
}
else {
this.observers.push(subscriber);
subscription = new SubjectSubscription(this, subscriber);
}
if (scheduler) {
subscriber.add(subscriber = new ObserveOnSubscriber(subscriber, scheduler));
}
if (_infiniteTimeWindow) {
for (var i = 0; i < len && !subscriber.closed; i++) {
subscriber.next(_events[i]);
}
}
else {
for (var i = 0; i < len && !subscriber.closed; i++) {
subscriber.next(_events[i].value);
}
}
if (this.hasError) {
subscriber.error(this.thrownError);
}
else if (this.isStopped) {
subscriber.complete();
}
return subscription;
};
ReplaySubject.prototype._getNow = function () {
return (this.scheduler || queue).now();
};
ReplaySubject.prototype._trimBufferThenGetEvents = function () {
var now = this._getNow();
var _bufferSize = this._bufferSize;
var _windowTime = this._windowTime;
var _events = this._events;
var eventsCount = _events.length;
var spliceCount = 0;
while (spliceCount < eventsCount) {
if ((now - _events[spliceCount].time) < _windowTime) {
break;
}
spliceCount++;
}
if (eventsCount > _bufferSize) {
spliceCount = Math.max(spliceCount, eventsCount - _bufferSize);
}
if (spliceCount > 0) {
_events.splice(0, spliceCount);
}
return _events;
};
return ReplaySubject;
}(Subject));
var ReplayEvent = /*@__PURE__*/ (function () {
function ReplayEvent(time, value) {
this.time = time;
this.value = value;
}
return ReplayEvent;
}());
/** PURE_IMPORTS_START tslib,_Subject,_Subscription PURE_IMPORTS_END */
var AsyncSubject = /*@__PURE__*/ (function (_super) {
__extends(AsyncSubject, _super);
function AsyncSubject() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.value = null;
_this.hasNext = false;
_this.hasCompleted = false;
return _this;
}
AsyncSubject.prototype._subscribe = function (subscriber) {
if (this.hasError) {
subscriber.error(this.thrownError);
return Subscription.EMPTY;
}
else if (this.hasCompleted && this.hasNext) {
subscriber.next(this.value);
subscriber.complete();
return Subscription.EMPTY;
}
return _super.prototype._subscribe.call(this, subscriber);
};
AsyncSubject.prototype.next = function (value) {
if (!this.hasCompleted) {
this.value = value;
this.hasNext = true;
}
};
AsyncSubject.prototype.error = function (error) {
if (!this.hasCompleted) {
_super.prototype.error.call(this, error);
}
};
AsyncSubject.prototype.complete = function () {
this.hasCompleted = true;
if (this.hasNext) {
_super.prototype.next.call(this, this.value);
}
_super.prototype.complete.call(this);
};
return AsyncSubject;
}(Subject));
/** PURE_IMPORTS_START _AsyncAction,_AsyncScheduler PURE_IMPORTS_END */
var asyncScheduler = /*@__PURE__*/ new AsyncScheduler(AsyncAction);
var async = asyncScheduler;
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function noop() { }
/** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */
function isObservable(obj) {
return !!obj && (obj instanceof Observable || (typeof obj.lift === 'function' && typeof obj.subscribe === 'function'));
}
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var ArgumentOutOfRangeErrorImpl = /*@__PURE__*/ (function () {
function ArgumentOutOfRangeErrorImpl() {
Error.call(this);
this.message = 'argument out of range';
this.name = 'ArgumentOutOfRangeError';
return this;
}
ArgumentOutOfRangeErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
return ArgumentOutOfRangeErrorImpl;
})();
var ArgumentOutOfRangeError = ArgumentOutOfRangeErrorImpl;
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var TimeoutErrorImpl = /*@__PURE__*/ (function () {
function TimeoutErrorImpl() {
Error.call(this);
this.message = 'Timeout has occurred';
this.name = 'TimeoutError';
return this;
}
TimeoutErrorImpl.prototype = /*@__PURE__*/ Object.create(Error.prototype);
return TimeoutErrorImpl;
})();
var TimeoutError = TimeoutErrorImpl;
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function map(project, thisArg) {
return function mapOperation(source) {
if (typeof project !== 'function') {
throw new TypeError('argument is not a function. Are you looking for `mapTo()`?');
}
return source.lift(new MapOperator(project, thisArg));
};
}
var MapOperator = /*@__PURE__*/ (function () {
function MapOperator(project, thisArg) {
this.project = project;
this.thisArg = thisArg;
}
MapOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new MapSubscriber(subscriber, this.project, this.thisArg));
};
return MapOperator;
}());
var MapSubscriber = /*@__PURE__*/ (function (_super) {
__extends(MapSubscriber, _super);
function MapSubscriber(destination, project, thisArg) {
var _this = _super.call(this, destination) || this;
_this.project = project;
_this.count = 0;
_this.thisArg = thisArg || _this;
return _this;
}
MapSubscriber.prototype._next = function (value) {
var result;
try {
result = this.project.call(this.thisArg, value, this.count++);
}
catch (err) {
this.destination.error(err);
return;
}
this.destination.next(result);
};
return MapSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
var OuterSubscriber = /*@__PURE__*/ (function (_super) {
__extends(OuterSubscriber, _super);
function OuterSubscriber() {
return _super !== null && _super.apply(this, arguments) || this;
}
OuterSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) {
this.destination.next(innerValue);
};
OuterSubscriber.prototype.notifyError = function (error, innerSub) {
this.destination.error(error);
};
OuterSubscriber.prototype.notifyComplete = function (innerSub) {
this.destination.complete();
};
return OuterSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
var InnerSubscriber = /*@__PURE__*/ (function (_super) {
__extends(InnerSubscriber, _super);
function InnerSubscriber(parent, outerValue, outerIndex) {
var _this = _super.call(this) || this;
_this.parent = parent;
_this.outerValue = outerValue;
_this.outerIndex = outerIndex;
_this.index = 0;
return _this;
}
InnerSubscriber.prototype._next = function (value) {
this.parent.notifyNext(this.outerValue, value, this.outerIndex, this.index++, this);
};
InnerSubscriber.prototype._error = function (error) {
this.parent.notifyError(error, this);
this.unsubscribe();
};
InnerSubscriber.prototype._complete = function () {
this.parent.notifyComplete(this);
this.unsubscribe();
};
return InnerSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START _hostReportError PURE_IMPORTS_END */
var subscribeToPromise = function (promise) {
return function (subscriber) {
promise.then(function (value) {
if (!subscriber.closed) {
subscriber.next(value);
subscriber.complete();
}
}, function (err) { return subscriber.error(err); })
.then(null, hostReportError);
return subscriber;
};
};
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function getSymbolIterator() {
if (typeof Symbol !== 'function' || !Symbol.iterator) {
return '@@iterator';
}
return Symbol.iterator;
}
var iterator = /*@__PURE__*/ getSymbolIterator();
/** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */
var subscribeToIterable = function (iterable) {
return function (subscriber) {
var iterator$1 = iterable[iterator]();
do {
var item = void 0;
try {
item = iterator$1.next();
}
catch (err) {
subscriber.error(err);
return subscriber;
}
if (item.done) {
subscriber.complete();
break;
}
subscriber.next(item.value);
if (subscriber.closed) {
break;
}
} while (true);
if (typeof iterator$1.return === 'function') {
subscriber.add(function () {
if (iterator$1.return) {
iterator$1.return();
}
});
}
return subscriber;
};
};
/** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */
var subscribeToObservable = function (obj) {
return function (subscriber) {
var obs = obj[observable]();
if (typeof obs.subscribe !== 'function') {
throw new TypeError('Provided object does not correctly implement Symbol.observable');
}
else {
return obs.subscribe(subscriber);
}
};
};
/** PURE_IMPORTS_START PURE_IMPORTS_END */
var isArrayLike = (function (x) { return x && typeof x.length === 'number' && typeof x !== 'function'; });
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function isPromise(value) {
return !!value && typeof value.subscribe !== 'function' && typeof value.then === 'function';
}
/** PURE_IMPORTS_START _subscribeToArray,_subscribeToPromise,_subscribeToIterable,_subscribeToObservable,_isArrayLike,_isPromise,_isObject,_symbol_iterator,_symbol_observable PURE_IMPORTS_END */
var subscribeTo = function (result) {
if (!!result && typeof result[observable] === 'function') {
return subscribeToObservable(result);
}
else if (isArrayLike(result)) {
return subscribeToArray(result);
}
else if (isPromise(result)) {
return subscribeToPromise(result);
}
else if (!!result && typeof result[iterator] === 'function') {
return subscribeToIterable(result);
}
else {
var value = isObject$1(result) ? 'an invalid object' : "'" + result + "'";
var msg = "You provided " + value + " where a stream was expected."
+ ' You can provide an Observable, Promise, Array, or Iterable.';
throw new TypeError(msg);
}
};
/** PURE_IMPORTS_START _InnerSubscriber,_subscribeTo,_Observable PURE_IMPORTS_END */
function subscribeToResult(outerSubscriber, result, outerValue, outerIndex, innerSubscriber) {
if (innerSubscriber === void 0) {
innerSubscriber = new InnerSubscriber(outerSubscriber, outerValue, outerIndex);
}
if (innerSubscriber.closed) {
return undefined;
}
if (result instanceof Observable) {
return result.subscribe(innerSubscriber);
}
return subscribeTo(result)(innerSubscriber);
}
/** PURE_IMPORTS_START tslib,_util_isScheduler,_util_isArray,_OuterSubscriber,_util_subscribeToResult,_fromArray PURE_IMPORTS_END */
var NONE = {};
function combineLatest() {
var observables = [];
for (var _i = 0; _i < arguments.length; _i++) {
observables[_i] = arguments[_i];
}
var resultSelector = undefined;
var scheduler = undefined;
if (isScheduler(observables[observables.length - 1])) {
scheduler = observables.pop();
}
if (typeof observables[observables.length - 1] === 'function') {
resultSelector = observables.pop();
}
if (observables.length === 1 && isArray$1(observables[0])) {
observables = observables[0];
}
return fromArray(observables, scheduler).lift(new CombineLatestOperator(resultSelector));
}
var CombineLatestOperator = /*@__PURE__*/ (function () {
function CombineLatestOperator(resultSelector) {
this.resultSelector = resultSelector;
}
CombineLatestOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new CombineLatestSubscriber(subscriber, this.resultSelector));
};
return CombineLatestOperator;
}());
var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) {
__extends(CombineLatestSubscriber, _super);
function CombineLatestSubscriber(destination, resultSelector) {
var _this = _super.call(this, destination) || this;
_this.resultSelector = resultSelector;
_this.active = 0;
_this.values = [];
_this.observables = [];
return _this;
}
CombineLatestSubscriber.prototype._next = function (observable) {
this.values.push(NONE);
this.observables.push(observable);
};
CombineLatestSubscriber.prototype._complete = function () {
var observables = this.observables;
var len = observables.length;
if (len === 0) {
this.destination.complete();
}
else {
this.active = len;
this.toRespond = len;
for (var i = 0; i < len; i++) {
var observable = observables[i];
this.add(subscribeToResult(this, observable, undefined, i));
}
}
};
CombineLatestSubscriber.prototype.notifyComplete = function (unused) {
if ((this.active -= 1) === 0) {
this.destination.complete();
}
};
CombineLatestSubscriber.prototype.notifyNext = function (_outerValue, innerValue, outerIndex) {
var values = this.values;
var oldVal = values[outerIndex];
var toRespond = !this.toRespond
? 0
: oldVal === NONE ? --this.toRespond : this.toRespond;
values[outerIndex] = innerValue;
if (toRespond === 0) {
if (this.resultSelector) {
this._tryResultSelector(values);
}
else {
this.destination.next(values.slice());
}
}
};
CombineLatestSubscriber.prototype._tryResultSelector = function (values) {
var result;
try {
result = this.resultSelector.apply(this, values);
}
catch (err) {
this.destination.error(err);
return;
}
this.destination.next(result);
};
return CombineLatestSubscriber;
}(OuterSubscriber));
/** PURE_IMPORTS_START _Observable,_Subscription,_symbol_observable PURE_IMPORTS_END */
function scheduleObservable(input, scheduler) {
return new Observable(function (subscriber) {
var sub = new Subscription();
sub.add(scheduler.schedule(function () {
var observable$1 = input[observable]();
sub.add(observable$1.subscribe({
next: function (value) { sub.add(scheduler.schedule(function () { return subscriber.next(value); })); },
error: function (err) { sub.add(scheduler.schedule(function () { return subscriber.error(err); })); },
complete: function () { sub.add(scheduler.schedule(function () { return subscriber.complete(); })); },
}));
}));
return sub;
});
}
/** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */
function schedulePromise(input, scheduler) {
return new Observable(function (subscriber) {
var sub = new Subscription();
sub.add(scheduler.schedule(function () {
return input.then(function (value) {
sub.add(scheduler.schedule(function () {
subscriber.next(value);
sub.add(scheduler.schedule(function () { return subscriber.complete(); }));
}));
}, function (err) {
sub.add(scheduler.schedule(function () { return subscriber.error(err); }));
});
}));
return sub;
});
}
/** PURE_IMPORTS_START _Observable,_Subscription,_symbol_iterator PURE_IMPORTS_END */
function scheduleIterable(input, scheduler) {
if (!input) {
throw new Error('Iterable cannot be null');
}
return new Observable(function (subscriber) {
var sub = new Subscription();
var iterator$1;
sub.add(function () {
if (iterator$1 && typeof iterator$1.return === 'function') {
iterator$1.return();
}
});
sub.add(scheduler.schedule(function () {
iterator$1 = input[iterator]();
sub.add(scheduler.schedule(function () {
if (subscriber.closed) {
return;
}
var value;
var done;
try {
var result = iterator$1.next();
value = result.value;
done = result.done;
}
catch (err) {
subscriber.error(err);
return;
}
if (done) {
subscriber.complete();
}
else {
subscriber.next(value);
this.schedule();
}
}));
}));
return sub;
});
}
/** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */
function isInteropObservable(input) {
return input && typeof input[observable] === 'function';
}
/** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */
function isIterable(input) {
return input && typeof input[iterator] === 'function';
}
/** PURE_IMPORTS_START _scheduleObservable,_schedulePromise,_scheduleArray,_scheduleIterable,_util_isInteropObservable,_util_isPromise,_util_isArrayLike,_util_isIterable PURE_IMPORTS_END */
function scheduled(input, scheduler) {
if (input != null) {
if (isInteropObservable(input)) {
return scheduleObservable(input, scheduler);
}
else if (isPromise(input)) {
return schedulePromise(input, scheduler);
}
else if (isArrayLike(input)) {
return scheduleArray(input, scheduler);
}
else if (isIterable(input) || typeof input === 'string') {
return scheduleIterable(input, scheduler);
}
}
throw new TypeError((input !== null && typeof input || input) + ' is not observable');
}
/** PURE_IMPORTS_START _Observable,_util_subscribeTo,_scheduled_scheduled PURE_IMPORTS_END */
function from(input, scheduler) {
if (!scheduler) {
if (input instanceof Observable) {
return input;
}
return new Observable(subscribeTo(input));
}
else {
return scheduled(input, scheduler);
}
}
/** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_util_subscribeTo PURE_IMPORTS_END */
var SimpleInnerSubscriber = /*@__PURE__*/ (function (_super) {
__extends(SimpleInnerSubscriber, _super);
function SimpleInnerSubscriber(parent) {
var _this = _super.call(this) || this;
_this.parent = parent;
return _this;
}
SimpleInnerSubscriber.prototype._next = function (value) {
this.parent.notifyNext(value);
};
SimpleInnerSubscriber.prototype._error = function (error) {
this.parent.notifyError(error);
this.unsubscribe();
};
SimpleInnerSubscriber.prototype._complete = function () {
this.parent.notifyComplete();
this.unsubscribe();
};
return SimpleInnerSubscriber;
}(Subscriber));
var SimpleOuterSubscriber = /*@__PURE__*/ (function (_super) {
__extends(SimpleOuterSubscriber, _super);
function SimpleOuterSubscriber() {
return _super !== null && _super.apply(this, arguments) || this;
}
SimpleOuterSubscriber.prototype.notifyNext = function (innerValue) {
this.destination.next(innerValue);
};
SimpleOuterSubscriber.prototype.notifyError = function (err) {
this.destination.error(err);
};
SimpleOuterSubscriber.prototype.notifyComplete = function () {
this.destination.complete();
};
return SimpleOuterSubscriber;
}(Subscriber));
function innerSubscribe(result, innerSubscriber) {
if (innerSubscriber.closed) {
return undefined;
}
if (result instanceof Observable) {
return result.subscribe(innerSubscriber);
}
return subscribeTo(result)(innerSubscriber);
}
/** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */
function mergeMap(project, resultSelector, concurrent) {
if (concurrent === void 0) {
concurrent = Number.POSITIVE_INFINITY;
}
if (typeof resultSelector === 'function') {
return function (source) { return source.pipe(mergeMap(function (a, i) { return from(project(a, i)).pipe(map(function (b, ii) { return resultSelector(a, b, i, ii); })); }, concurrent)); };
}
else if (typeof resultSelector === 'number') {
concurrent = resultSelector;
}
return function (source) { return source.lift(new MergeMapOperator(project, concurrent)); };
}
var MergeMapOperator = /*@__PURE__*/ (function () {
function MergeMapOperator(project, concurrent) {
if (concurrent === void 0) {
concurrent = Number.POSITIVE_INFINITY;
}
this.project = project;
this.concurrent = concurrent;
}
MergeMapOperator.prototype.call = function (observer, source) {
return source.subscribe(new MergeMapSubscriber(observer, this.project, this.concurrent));
};
return MergeMapOperator;
}());
var MergeMapSubscriber = /*@__PURE__*/ (function (_super) {
__extends(MergeMapSubscriber, _super);
function MergeMapSubscriber(destination, project, concurrent) {
if (concurrent === void 0) {
concurrent = Number.POSITIVE_INFINITY;
}
var _this = _super.call(this, destination) || this;
_this.project = project;
_this.concurrent = concurrent;
_this.hasCompleted = false;
_this.buffer = [];
_this.active = 0;
_this.index = 0;
return _this;
}
MergeMapSubscriber.prototype._next = function (value) {
if (this.active < this.concurrent) {
this._tryNext(value);
}
else {
this.buffer.push(value);
}
};
MergeMapSubscriber.prototype._tryNext = function (value) {
var result;
var index = this.index++;
try {
result = this.project(value, index);
}
catch (err) {
this.destination.error(err);
return;
}
this.active++;
this._innerSub(result);
};
MergeMapSubscriber.prototype._innerSub = function (ish) {
var innerSubscriber = new SimpleInnerSubscriber(this);
var destination = this.destination;
destination.add(innerSubscriber);
var innerSubscription = innerSubscribe(ish, innerSubscriber);
if (innerSubscription !== innerSubscriber) {
destination.add(innerSubscription);
}
};
MergeMapSubscriber.prototype._complete = function () {
this.hasCompleted = true;
if (this.active === 0 && this.buffer.length === 0) {
this.destination.complete();
}
this.unsubscribe();
};
MergeMapSubscriber.prototype.notifyNext = function (innerValue) {
this.destination.next(innerValue);
};
MergeMapSubscriber.prototype.notifyComplete = function () {
var buffer = this.buffer;
this.active--;
if (buffer.length > 0) {
this._next(buffer.shift());
}
else if (this.active === 0 && this.hasCompleted) {
this.destination.complete();
}
};
return MergeMapSubscriber;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START _mergeMap,_util_identity PURE_IMPORTS_END */
function mergeAll(concurrent) {
if (concurrent === void 0) {
concurrent = Number.POSITIVE_INFINITY;
}
return mergeMap(identity, concurrent);
}
/** PURE_IMPORTS_START _mergeAll PURE_IMPORTS_END */
function concatAll() {
return mergeAll(1);
}
/** PURE_IMPORTS_START _of,_operators_concatAll PURE_IMPORTS_END */
function concat() {
var observables = [];
for (var _i = 0; _i < arguments.length; _i++) {
observables[_i] = arguments[_i];
}
return concatAll()(of.apply(void 0, observables));
}
/** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */
function defer(observableFactory) {
return new Observable(function (subscriber) {
var input;
try {
input = observableFactory();
}
catch (err) {
subscriber.error(err);
return undefined;
}
var source = input ? from(input) : empty();
return source.subscribe(subscriber);
});
}
/** PURE_IMPORTS_START _Observable,_util_isArray,_operators_map,_util_isObject,_from PURE_IMPORTS_END */
function forkJoin() {
var sources = [];
for (var _i = 0; _i < arguments.length; _i++) {
sources[_i] = arguments[_i];
}
if (sources.length === 1) {
var first_1 = sources[0];
if (isArray$1(first_1)) {
return forkJoinInternal(first_1, null);
}
if (isObject$1(first_1) && Object.getPrototypeOf(first_1) === Object.prototype) {
var keys = Object.keys(first_1);
return forkJoinInternal(keys.map(function (key) { return first_1[key]; }), keys);
}
}
if (typeof sources[sources.length - 1] === 'function') {
var resultSelector_1 = sources.pop();
sources = (sources.length === 1 && isArray$1(sources[0])) ? sources[0] : sources;
return forkJoinInternal(sources, null).pipe(map(function (args) { return resultSelector_1.apply(void 0, args); }));
}
return forkJoinInternal(sources, null);
}
function forkJoinInternal(sources, keys) {
return new Observable(function (subscriber) {
var len = sources.length;
if (len === 0) {
subscriber.complete();
return;
}
var values = new Array(len);
var completed = 0;
var emitted = 0;
var _loop_1 = function (i) {
var source = from(sources[i]);
var hasValue = false;
subscriber.add(source.subscribe({
next: function (value) {
if (!hasValue) {
hasValue = true;
emitted++;
}
values[i] = value;
},
error: function (err) { return subscriber.error(err); },
complete: function () {
completed++;
if (completed === len || !hasValue) {
if (emitted === len) {
subscriber.next(keys ?
keys.reduce(function (result, key, i) { return (result[key] = values[i], result); }, {}) :
values);
}
subscriber.complete();
}
}
}));
};
for (var i = 0; i < len; i++) {
_loop_1(i);
}
});
}
/** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */
function fromEvent(target, eventName, options, resultSelector) {
if (isFunction$1(options)) {
resultSelector = options;
options = undefined;
}
if (resultSelector) {
return fromEvent(target, eventName, options).pipe(map(function (args) { return isArray$1(args) ? resultSelector.apply(void 0, args) : resultSelector(args); }));
}
return new Observable(function (subscriber) {
function handler(e) {
if (arguments.length > 1) {
subscriber.next(Array.prototype.slice.call(arguments));
}
else {
subscriber.next(e);
}
}
setupSubscription(target, eventName, handler, subscriber, options);
});
}
function setupSubscription(sourceObj, eventName, handler, subscriber, options) {
var unsubscribe;
if (isEventTarget(sourceObj)) {
var source_1 = sourceObj;
sourceObj.addEventListener(eventName, handler, options);
unsubscribe = function () { return source_1.removeEventListener(eventName, handler, options); };
}
else if (isJQueryStyleEventEmitter(sourceObj)) {
var source_2 = sourceObj;
sourceObj.on(eventName, handler);
unsubscribe = function () { return source_2.off(eventName, handler); };
}
else if (isNodeStyleEventEmitter(sourceObj)) {
var source_3 = sourceObj;
sourceObj.addListener(eventName, handler);
unsubscribe = function () { return source_3.removeListener(eventName, handler); };
}
else if (sourceObj && sourceObj.length) {
for (var i = 0, len = sourceObj.length; i < len; i++) {
setupSubscription(sourceObj[i], eventName, handler, subscriber, options);
}
}
else {
throw new TypeError('Invalid event target');
}
subscriber.add(unsubscribe);
}
function isNodeStyleEventEmitter(sourceObj) {
return sourceObj && typeof sourceObj.addListener === 'function' && typeof sourceObj.removeListener === 'function';
}
function isJQueryStyleEventEmitter(sourceObj) {
return sourceObj && typeof sourceObj.on === 'function' && typeof sourceObj.off === 'function';
}
function isEventTarget(sourceObj) {
return sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function';
}
/** PURE_IMPORTS_START _defer,_empty PURE_IMPORTS_END */
function iif(condition, trueResult, falseResult) {
if (trueResult === void 0) {
trueResult = EMPTY;
}
if (falseResult === void 0) {
falseResult = EMPTY;
}
return defer(function () { return condition() ? trueResult : falseResult; });
}
/** PURE_IMPORTS_START _isArray PURE_IMPORTS_END */
function isNumeric(val) {
return !isArray$1(val) && (val - parseFloat(val) + 1) >= 0;
}
/** PURE_IMPORTS_START _Observable,_util_isScheduler,_operators_mergeAll,_fromArray PURE_IMPORTS_END */
function merge() {
var observables = [];
for (var _i = 0; _i < arguments.length; _i++) {
observables[_i] = arguments[_i];
}
var concurrent = Number.POSITIVE_INFINITY;
var scheduler = null;
var last = observables[observables.length - 1];
if (isScheduler(last)) {
scheduler = observables.pop();
if (observables.length > 1 && typeof observables[observables.length - 1] === 'number') {
concurrent = observables.pop();
}
}
else if (typeof last === 'number') {
concurrent = observables.pop();
}
if (scheduler === null && observables.length === 1 && observables[0] instanceof Observable) {
return observables[0];
}
return mergeAll(concurrent)(fromArray(observables, scheduler));
}
/** PURE_IMPORTS_START _Observable,_util_noop PURE_IMPORTS_END */
var NEVER = /*@__PURE__*/ new Observable(noop);
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function filter(predicate, thisArg) {
return function filterOperatorFunction(source) {
return source.lift(new FilterOperator(predicate, thisArg));
};
}
var FilterOperator = /*@__PURE__*/ (function () {
function FilterOperator(predicate, thisArg) {
this.predicate = predicate;
this.thisArg = thisArg;
}
FilterOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new FilterSubscriber(subscriber, this.predicate, this.thisArg));
};
return FilterOperator;
}());
var FilterSubscriber = /*@__PURE__*/ (function (_super) {
__extends(FilterSubscriber, _super);
function FilterSubscriber(destination, predicate, thisArg) {
var _this = _super.call(this, destination) || this;
_this.predicate = predicate;
_this.thisArg = thisArg;
_this.count = 0;
return _this;
}
FilterSubscriber.prototype._next = function (value) {
var result;
try {
result = this.predicate.call(this.thisArg, value, this.count++);
}
catch (err) {
this.destination.error(err);
return;
}
if (result) {
this.destination.next(value);
}
};
return FilterSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_util_isArray,_fromArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
function race() {
var observables = [];
for (var _i = 0; _i < arguments.length; _i++) {
observables[_i] = arguments[_i];
}
if (observables.length === 1) {
if (isArray$1(observables[0])) {
observables = observables[0];
}
else {
return observables[0];
}
}
return fromArray(observables, undefined).lift(new RaceOperator());
}
var RaceOperator = /*@__PURE__*/ (function () {
function RaceOperator() {
}
RaceOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new RaceSubscriber(subscriber));
};
return RaceOperator;
}());
var RaceSubscriber = /*@__PURE__*/ (function (_super) {
__extends(RaceSubscriber, _super);
function RaceSubscriber(destination) {
var _this = _super.call(this, destination) || this;
_this.hasFirst = false;
_this.observables = [];
_this.subscriptions = [];
return _this;
}
RaceSubscriber.prototype._next = function (observable) {
this.observables.push(observable);
};
RaceSubscriber.prototype._complete = function () {
var observables = this.observables;
var len = observables.length;
if (len === 0) {
this.destination.complete();
}
else {
for (var i = 0; i < len && !this.hasFirst; i++) {
var observable = observables[i];
var subscription = subscribeToResult(this, observable, undefined, i);
if (this.subscriptions) {
this.subscriptions.push(subscription);
}
this.add(subscription);
}
this.observables = null;
}
};
RaceSubscriber.prototype.notifyNext = function (_outerValue, innerValue, outerIndex) {
if (!this.hasFirst) {
this.hasFirst = true;
for (var i = 0; i < this.subscriptions.length; i++) {
if (i !== outerIndex) {
var subscription = this.subscriptions[i];
subscription.unsubscribe();
this.remove(subscription);
}
}
this.subscriptions = null;
}
this.destination.next(innerValue);
};
return RaceSubscriber;
}(OuterSubscriber));
/** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */
function timer(dueTime, periodOrScheduler, scheduler) {
if (dueTime === void 0) {
dueTime = 0;
}
var period = -1;
if (isNumeric(periodOrScheduler)) {
period = Number(periodOrScheduler) < 1 && 1 || Number(periodOrScheduler);
}
else if (isScheduler(periodOrScheduler)) {
scheduler = periodOrScheduler;
}
if (!isScheduler(scheduler)) {
scheduler = async;
}
return new Observable(function (subscriber) {
var due = isNumeric(dueTime)
? dueTime
: (+dueTime - scheduler.now());
return scheduler.schedule(dispatch, due, {
index: 0, period: period, subscriber: subscriber
});
});
}
function dispatch(state) {
var index = state.index, period = state.period, subscriber = state.subscriber;
subscriber.next(index);
if (subscriber.closed) {
return;
}
else if (period === -1) {
return subscriber.complete();
}
state.index = index + 1;
this.schedule(state, period);
}
/** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_.._internal_symbol_iterator,_innerSubscribe PURE_IMPORTS_END */
function zip() {
var observables = [];
for (var _i = 0; _i < arguments.length; _i++) {
observables[_i] = arguments[_i];
}
var resultSelector = observables[observables.length - 1];
if (typeof resultSelector === 'function') {
observables.pop();
}
return fromArray(observables, undefined).lift(new ZipOperator(resultSelector));
}
var ZipOperator = /*@__PURE__*/ (function () {
function ZipOperator(resultSelector) {
this.resultSelector = resultSelector;
}
ZipOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new ZipSubscriber(subscriber, this.resultSelector));
};
return ZipOperator;
}());
var ZipSubscriber = /*@__PURE__*/ (function (_super) {
__extends(ZipSubscriber, _super);
function ZipSubscriber(destination, resultSelector, values) {
var _this = _super.call(this, destination) || this;
_this.resultSelector = resultSelector;
_this.iterators = [];
_this.active = 0;
_this.resultSelector = (typeof resultSelector === 'function') ? resultSelector : undefined;
return _this;
}
ZipSubscriber.prototype._next = function (value) {
var iterators = this.iterators;
if (isArray$1(value)) {
iterators.push(new StaticArrayIterator(value));
}
else if (typeof value[iterator] === 'function') {
iterators.push(new StaticIterator(value[iterator]()));
}
else {
iterators.push(new ZipBufferIterator(this.destination, this, value));
}
};
ZipSubscriber.prototype._complete = function () {
var iterators = this.iterators;
var len = iterators.length;
this.unsubscribe();
if (len === 0) {
this.destination.complete();
return;
}
this.active = len;
for (var i = 0; i < len; i++) {
var iterator = iterators[i];
if (iterator.stillUnsubscribed) {
var destination = this.destination;
destination.add(iterator.subscribe());
}
else {
this.active--;
}
}
};
ZipSubscriber.prototype.notifyInactive = function () {
this.active--;
if (this.active === 0) {
this.destination.complete();
}
};
ZipSubscriber.prototype.checkIterators = function () {
var iterators = this.iterators;
var len = iterators.length;
var destination = this.destination;
for (var i = 0; i < len; i++) {
var iterator = iterators[i];
if (typeof iterator.hasValue === 'function' && !iterator.hasValue()) {
return;
}
}
var shouldComplete = false;
var args = [];
for (var i = 0; i < len; i++) {
var iterator = iterators[i];
var result = iterator.next();
if (iterator.hasCompleted()) {
shouldComplete = true;
}
if (result.done) {
destination.complete();
return;
}
args.push(result.value);
}
if (this.resultSelector) {
this._tryresultSelector(args);
}
else {
destination.next(args);
}
if (shouldComplete) {
destination.complete();
}
};
ZipSubscriber.prototype._tryresultSelector = function (args) {
var result;
try {
result = this.resultSelector.apply(this, args);
}
catch (err) {
this.destination.error(err);
return;
}
this.destination.next(result);
};
return ZipSubscriber;
}(Subscriber));
var StaticIterator = /*@__PURE__*/ (function () {
function StaticIterator(iterator) {
this.iterator = iterator;
this.nextResult = iterator.next();
}
StaticIterator.prototype.hasValue = function () {
return true;
};
StaticIterator.prototype.next = function () {
var result = this.nextResult;
this.nextResult = this.iterator.next();
return result;
};
StaticIterator.prototype.hasCompleted = function () {
var nextResult = this.nextResult;
return Boolean(nextResult && nextResult.done);
};
return StaticIterator;
}());
var StaticArrayIterator = /*@__PURE__*/ (function () {
function StaticArrayIterator(array) {
this.array = array;
this.index = 0;
this.length = 0;
this.length = array.length;
}
StaticArrayIterator.prototype[iterator] = function () {
return this;
};
StaticArrayIterator.prototype.next = function (value) {
var i = this.index++;
var array = this.array;
return i < this.length ? { value: array[i], done: false } : { value: null, done: true };
};
StaticArrayIterator.prototype.hasValue = function () {
return this.array.length > this.index;
};
StaticArrayIterator.prototype.hasCompleted = function () {
return this.array.length === this.index;
};
return StaticArrayIterator;
}());
var ZipBufferIterator = /*@__PURE__*/ (function (_super) {
__extends(ZipBufferIterator, _super);
function ZipBufferIterator(destination, parent, observable) {
var _this = _super.call(this, destination) || this;
_this.parent = parent;
_this.observable = observable;
_this.stillUnsubscribed = true;
_this.buffer = [];
_this.isComplete = false;
return _this;
}
ZipBufferIterator.prototype[iterator] = function () {
return this;
};
ZipBufferIterator.prototype.next = function () {
var buffer = this.buffer;
if (buffer.length === 0 && this.isComplete) {
return { value: null, done: true };
}
else {
return { value: buffer.shift(), done: false };
}
};
ZipBufferIterator.prototype.hasValue = function () {
return this.buffer.length > 0;
};
ZipBufferIterator.prototype.hasCompleted = function () {
return this.buffer.length === 0 && this.isComplete;
};
ZipBufferIterator.prototype.notifyComplete = function () {
if (this.buffer.length > 0) {
this.isComplete = true;
this.parent.notifyInactive();
}
else {
this.destination.complete();
}
};
ZipBufferIterator.prototype.notifyNext = function (innerValue) {
this.buffer.push(innerValue);
this.parent.checkIterators();
};
ZipBufferIterator.prototype.subscribe = function () {
return innerSubscribe(this.observable, new SimpleInnerSubscriber(this));
};
return ZipBufferIterator;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
function audit(durationSelector) {
return function auditOperatorFunction(source) {
return source.lift(new AuditOperator(durationSelector));
};
}
var AuditOperator = /*@__PURE__*/ (function () {
function AuditOperator(durationSelector) {
this.durationSelector = durationSelector;
}
AuditOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new AuditSubscriber(subscriber, this.durationSelector));
};
return AuditOperator;
}());
var AuditSubscriber = /*@__PURE__*/ (function (_super) {
__extends(AuditSubscriber, _super);
function AuditSubscriber(destination, durationSelector) {
var _this = _super.call(this, destination) || this;
_this.durationSelector = durationSelector;
_this.hasValue = false;
return _this;
}
AuditSubscriber.prototype._next = function (value) {
this.value = value;
this.hasValue = true;
if (!this.throttled) {
var duration = void 0;
try {
var durationSelector = this.durationSelector;
duration = durationSelector(value);
}
catch (err) {
return this.destination.error(err);
}
var innerSubscription = innerSubscribe(duration, new SimpleInnerSubscriber(this));
if (!innerSubscription || innerSubscription.closed) {
this.clearThrottle();
}
else {
this.add(this.throttled = innerSubscription);
}
}
};
AuditSubscriber.prototype.clearThrottle = function () {
var _a = this, value = _a.value, hasValue = _a.hasValue, throttled = _a.throttled;
if (throttled) {
this.remove(throttled);
this.throttled = undefined;
throttled.unsubscribe();
}
if (hasValue) {
this.value = undefined;
this.hasValue = false;
this.destination.next(value);
}
};
AuditSubscriber.prototype.notifyNext = function () {
this.clearThrottle();
};
AuditSubscriber.prototype.notifyComplete = function () {
this.clearThrottle();
};
return AuditSubscriber;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */
function auditTime(duration, scheduler) {
if (scheduler === void 0) {
scheduler = async;
}
return audit(function () { return timer(duration, scheduler); });
}
/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
function catchError(selector) {
return function catchErrorOperatorFunction(source) {
var operator = new CatchOperator(selector);
var caught = source.lift(operator);
return (operator.caught = caught);
};
}
var CatchOperator = /*@__PURE__*/ (function () {
function CatchOperator(selector) {
this.selector = selector;
}
CatchOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new CatchSubscriber(subscriber, this.selector, this.caught));
};
return CatchOperator;
}());
var CatchSubscriber = /*@__PURE__*/ (function (_super) {
__extends(CatchSubscriber, _super);
function CatchSubscriber(destination, selector, caught) {
var _this = _super.call(this, destination) || this;
_this.selector = selector;
_this.caught = caught;
return _this;
}
CatchSubscriber.prototype.error = function (err) {
if (!this.isStopped) {
var result = void 0;
try {
result = this.selector(err, this.caught);
}
catch (err2) {
_super.prototype.error.call(this, err2);
return;
}
this._unsubscribeAndRecycle();
var innerSubscriber = new SimpleInnerSubscriber(this);
this.add(innerSubscriber);
var innerSubscription = innerSubscribe(result, innerSubscriber);
if (innerSubscription !== innerSubscriber) {
this.add(innerSubscription);
}
}
};
return CatchSubscriber;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */
function concatMap(project, resultSelector) {
return mergeMap(project, resultSelector, 1);
}
/** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */
function debounceTime(dueTime, scheduler) {
if (scheduler === void 0) {
scheduler = async;
}
return function (source) { return source.lift(new DebounceTimeOperator(dueTime, scheduler)); };
}
var DebounceTimeOperator = /*@__PURE__*/ (function () {
function DebounceTimeOperator(dueTime, scheduler) {
this.dueTime = dueTime;
this.scheduler = scheduler;
}
DebounceTimeOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new DebounceTimeSubscriber(subscriber, this.dueTime, this.scheduler));
};
return DebounceTimeOperator;
}());
var DebounceTimeSubscriber = /*@__PURE__*/ (function (_super) {
__extends(DebounceTimeSubscriber, _super);
function DebounceTimeSubscriber(destination, dueTime, scheduler) {
var _this = _super.call(this, destination) || this;
_this.dueTime = dueTime;
_this.scheduler = scheduler;
_this.debouncedSubscription = null;
_this.lastValue = null;
_this.hasValue = false;
return _this;
}
DebounceTimeSubscriber.prototype._next = function (value) {
this.clearDebounce();
this.lastValue = value;
this.hasValue = true;
this.add(this.debouncedSubscription = this.scheduler.schedule(dispatchNext$1, this.dueTime, this));
};
DebounceTimeSubscriber.prototype._complete = function () {
this.debouncedNext();
this.destination.complete();
};
DebounceTimeSubscriber.prototype.debouncedNext = function () {
this.clearDebounce();
if (this.hasValue) {
var lastValue = this.lastValue;
this.lastValue = null;
this.hasValue = false;
this.destination.next(lastValue);
}
};
DebounceTimeSubscriber.prototype.clearDebounce = function () {
var debouncedSubscription = this.debouncedSubscription;
if (debouncedSubscription !== null) {
this.remove(debouncedSubscription);
debouncedSubscription.unsubscribe();
this.debouncedSubscription = null;
}
};
return DebounceTimeSubscriber;
}(Subscriber));
function dispatchNext$1(subscriber) {
subscriber.debouncedNext();
}
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function defaultIfEmpty(defaultValue) {
if (defaultValue === void 0) {
defaultValue = null;
}
return function (source) { return source.lift(new DefaultIfEmptyOperator(defaultValue)); };
}
var DefaultIfEmptyOperator = /*@__PURE__*/ (function () {
function DefaultIfEmptyOperator(defaultValue) {
this.defaultValue = defaultValue;
}
DefaultIfEmptyOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new DefaultIfEmptySubscriber(subscriber, this.defaultValue));
};
return DefaultIfEmptyOperator;
}());
var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) {
__extends(DefaultIfEmptySubscriber, _super);
function DefaultIfEmptySubscriber(destination, defaultValue) {
var _this = _super.call(this, destination) || this;
_this.defaultValue = defaultValue;
_this.isEmpty = true;
return _this;
}
DefaultIfEmptySubscriber.prototype._next = function (value) {
this.isEmpty = false;
this.destination.next(value);
};
DefaultIfEmptySubscriber.prototype._complete = function () {
if (this.isEmpty) {
this.destination.next(this.defaultValue);
}
this.destination.complete();
};
return DefaultIfEmptySubscriber;
}(Subscriber));
/** PURE_IMPORTS_START PURE_IMPORTS_END */
function isDate(value) {
return value instanceof Date && !isNaN(+value);
}
/** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */
function delay(delay, scheduler) {
if (scheduler === void 0) {
scheduler = async;
}
var absoluteDelay = isDate(delay);
var delayFor = absoluteDelay ? (+delay - scheduler.now()) : Math.abs(delay);
return function (source) { return source.lift(new DelayOperator(delayFor, scheduler)); };
}
var DelayOperator = /*@__PURE__*/ (function () {
function DelayOperator(delay, scheduler) {
this.delay = delay;
this.scheduler = scheduler;
}
DelayOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new DelaySubscriber(subscriber, this.delay, this.scheduler));
};
return DelayOperator;
}());
var DelaySubscriber = /*@__PURE__*/ (function (_super) {
__extends(DelaySubscriber, _super);
function DelaySubscriber(destination, delay, scheduler) {
var _this = _super.call(this, destination) || this;
_this.delay = delay;
_this.scheduler = scheduler;
_this.queue = [];
_this.active = false;
_this.errored = false;
return _this;
}
DelaySubscriber.dispatch = function (state) {
var source = state.source;
var queue = source.queue;
var scheduler = state.scheduler;
var destination = state.destination;
while (queue.length > 0 && (queue[0].time - scheduler.now()) <= 0) {
queue.shift().notification.observe(destination);
}
if (queue.length > 0) {
var delay_1 = Math.max(0, queue[0].time - scheduler.now());
this.schedule(state, delay_1);
}
else {
this.unsubscribe();
source.active = false;
}
};
DelaySubscriber.prototype._schedule = function (scheduler) {
this.active = true;
var destination = this.destination;
destination.add(scheduler.schedule(DelaySubscriber.dispatch, this.delay, {
source: this, destination: this.destination, scheduler: scheduler
}));
};
DelaySubscriber.prototype.scheduleNotification = function (notification) {
if (this.errored === true) {
return;
}
var scheduler = this.scheduler;
var message = new DelayMessage(scheduler.now() + this.delay, notification);
this.queue.push(message);
if (this.active === false) {
this._schedule(scheduler);
}
};
DelaySubscriber.prototype._next = function (value) {
this.scheduleNotification(Notification.createNext(value));
};
DelaySubscriber.prototype._error = function (err) {
this.errored = true;
this.queue = [];
this.destination.error(err);
this.unsubscribe();
};
DelaySubscriber.prototype._complete = function () {
this.scheduleNotification(Notification.createComplete());
this.unsubscribe();
};
return DelaySubscriber;
}(Subscriber));
var DelayMessage = /*@__PURE__*/ (function () {
function DelayMessage(time, notification) {
this.time = time;
this.notification = notification;
}
return DelayMessage;
}());
/** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
function delayWhen(delayDurationSelector, subscriptionDelay) {
if (subscriptionDelay) {
return function (source) {
return new SubscriptionDelayObservable(source, subscriptionDelay)
.lift(new DelayWhenOperator(delayDurationSelector));
};
}
return function (source) { return source.lift(new DelayWhenOperator(delayDurationSelector)); };
}
var DelayWhenOperator = /*@__PURE__*/ (function () {
function DelayWhenOperator(delayDurationSelector) {
this.delayDurationSelector = delayDurationSelector;
}
DelayWhenOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new DelayWhenSubscriber(subscriber, this.delayDurationSelector));
};
return DelayWhenOperator;
}());
var DelayWhenSubscriber = /*@__PURE__*/ (function (_super) {
__extends(DelayWhenSubscriber, _super);
function DelayWhenSubscriber(destination, delayDurationSelector) {
var _this = _super.call(this, destination) || this;
_this.delayDurationSelector = delayDurationSelector;
_this.completed = false;
_this.delayNotifierSubscriptions = [];
_this.index = 0;
return _this;
}
DelayWhenSubscriber.prototype.notifyNext = function (outerValue, _innerValue, _outerIndex, _innerIndex, innerSub) {
this.destination.next(outerValue);
this.removeSubscription(innerSub);
this.tryComplete();
};
DelayWhenSubscriber.prototype.notifyError = function (error, innerSub) {
this._error(error);
};
DelayWhenSubscriber.prototype.notifyComplete = function (innerSub) {
var value = this.removeSubscription(innerSub);
if (value) {
this.destination.next(value);
}
this.tryComplete();
};
DelayWhenSubscriber.prototype._next = function (value) {
var index = this.index++;
try {
var delayNotifier = this.delayDurationSelector(value, index);
if (delayNotifier) {
this.tryDelay(delayNotifier, value);
}
}
catch (err) {
this.destination.error(err);
}
};
DelayWhenSubscriber.prototype._complete = function () {
this.completed = true;
this.tryComplete();
this.unsubscribe();
};
DelayWhenSubscriber.prototype.removeSubscription = function (subscription) {
subscription.unsubscribe();
var subscriptionIdx = this.delayNotifierSubscriptions.indexOf(subscription);
if (subscriptionIdx !== -1) {
this.delayNotifierSubscriptions.splice(subscriptionIdx, 1);
}
return subscription.outerValue;
};
DelayWhenSubscriber.prototype.tryDelay = function (delayNotifier, value) {
var notifierSubscription = subscribeToResult(this, delayNotifier, value);
if (notifierSubscription && !notifierSubscription.closed) {
var destination = this.destination;
destination.add(notifierSubscription);
this.delayNotifierSubscriptions.push(notifierSubscription);
}
};
DelayWhenSubscriber.prototype.tryComplete = function () {
if (this.completed && this.delayNotifierSubscriptions.length === 0) {
this.destination.complete();
}
};
return DelayWhenSubscriber;
}(OuterSubscriber));
var SubscriptionDelayObservable = /*@__PURE__*/ (function (_super) {
__extends(SubscriptionDelayObservable, _super);
function SubscriptionDelayObservable(source, subscriptionDelay) {
var _this = _super.call(this) || this;
_this.source = source;
_this.subscriptionDelay = subscriptionDelay;
return _this;
}
SubscriptionDelayObservable.prototype._subscribe = function (subscriber) {
this.subscriptionDelay.subscribe(new SubscriptionDelaySubscriber(subscriber, this.source));
};
return SubscriptionDelayObservable;
}(Observable));
var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) {
__extends(SubscriptionDelaySubscriber, _super);
function SubscriptionDelaySubscriber(parent, source) {
var _this = _super.call(this) || this;
_this.parent = parent;
_this.source = source;
_this.sourceSubscribed = false;
return _this;
}
SubscriptionDelaySubscriber.prototype._next = function (unused) {
this.subscribeToSource();
};
SubscriptionDelaySubscriber.prototype._error = function (err) {
this.unsubscribe();
this.parent.error(err);
};
SubscriptionDelaySubscriber.prototype._complete = function () {
this.unsubscribe();
this.subscribeToSource();
};
SubscriptionDelaySubscriber.prototype.subscribeToSource = function () {
if (!this.sourceSubscribed) {
this.sourceSubscribed = true;
this.unsubscribe();
this.source.subscribe(this.parent);
}
};
return SubscriptionDelaySubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function distinctUntilChanged(compare, keySelector) {
return function (source) { return source.lift(new DistinctUntilChangedOperator(compare, keySelector)); };
}
var DistinctUntilChangedOperator = /*@__PURE__*/ (function () {
function DistinctUntilChangedOperator(compare, keySelector) {
this.compare = compare;
this.keySelector = keySelector;
}
DistinctUntilChangedOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new DistinctUntilChangedSubscriber(subscriber, this.compare, this.keySelector));
};
return DistinctUntilChangedOperator;
}());
var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) {
__extends(DistinctUntilChangedSubscriber, _super);
function DistinctUntilChangedSubscriber(destination, compare, keySelector) {
var _this = _super.call(this, destination) || this;
_this.keySelector = keySelector;
_this.hasKey = false;
if (typeof compare === 'function') {
_this.compare = compare;
}
return _this;
}
DistinctUntilChangedSubscriber.prototype.compare = function (x, y) {
return x === y;
};
DistinctUntilChangedSubscriber.prototype._next = function (value) {
var key;
try {
var keySelector = this.keySelector;
key = keySelector ? keySelector(value) : value;
}
catch (err) {
return this.destination.error(err);
}
var result = false;
if (this.hasKey) {
try {
var compare = this.compare;
result = compare(this.key, key);
}
catch (err) {
return this.destination.error(err);
}
}
else {
this.hasKey = true;
}
if (!result) {
this.key = key;
this.destination.next(value);
}
};
return DistinctUntilChangedSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */
function take(count) {
return function (source) {
if (count === 0) {
return empty();
}
else {
return source.lift(new TakeOperator(count));
}
};
}
var TakeOperator = /*@__PURE__*/ (function () {
function TakeOperator(total) {
this.total = total;
if (this.total < 0) {
throw new ArgumentOutOfRangeError;
}
}
TakeOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new TakeSubscriber(subscriber, this.total));
};
return TakeOperator;
}());
var TakeSubscriber = /*@__PURE__*/ (function (_super) {
__extends(TakeSubscriber, _super);
function TakeSubscriber(destination, total) {
var _this = _super.call(this, destination) || this;
_this.total = total;
_this.count = 0;
return _this;
}
TakeSubscriber.prototype._next = function (value) {
var total = this.total;
var count = ++this.count;
if (count <= total) {
this.destination.next(value);
if (count === total) {
this.destination.complete();
this.unsubscribe();
}
}
};
return TakeSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */
function exhaustMap(project, resultSelector) {
if (resultSelector) {
return function (source) { return source.pipe(exhaustMap(function (a, i) { return from(project(a, i)).pipe(map(function (b, ii) { return resultSelector(a, b, i, ii); })); })); };
}
return function (source) {
return source.lift(new ExhaustMapOperator(project));
};
}
var ExhaustMapOperator = /*@__PURE__*/ (function () {
function ExhaustMapOperator(project) {
this.project = project;
}
ExhaustMapOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new ExhaustMapSubscriber(subscriber, this.project));
};
return ExhaustMapOperator;
}());
var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) {
__extends(ExhaustMapSubscriber, _super);
function ExhaustMapSubscriber(destination, project) {
var _this = _super.call(this, destination) || this;
_this.project = project;
_this.hasSubscription = false;
_this.hasCompleted = false;
_this.index = 0;
return _this;
}
ExhaustMapSubscriber.prototype._next = function (value) {
if (!this.hasSubscription) {
this.tryNext(value);
}
};
ExhaustMapSubscriber.prototype.tryNext = function (value) {
var result;
var index = this.index++;
try {
result = this.project(value, index);
}
catch (err) {
this.destination.error(err);
return;
}
this.hasSubscription = true;
this._innerSub(result);
};
ExhaustMapSubscriber.prototype._innerSub = function (result) {
var innerSubscriber = new SimpleInnerSubscriber(this);
var destination = this.destination;
destination.add(innerSubscriber);
var innerSubscription = innerSubscribe(result, innerSubscriber);
if (innerSubscription !== innerSubscriber) {
destination.add(innerSubscription);
}
};
ExhaustMapSubscriber.prototype._complete = function () {
this.hasCompleted = true;
if (!this.hasSubscription) {
this.destination.complete();
}
this.unsubscribe();
};
ExhaustMapSubscriber.prototype.notifyNext = function (innerValue) {
this.destination.next(innerValue);
};
ExhaustMapSubscriber.prototype.notifyError = function (err) {
this.destination.error(err);
};
ExhaustMapSubscriber.prototype.notifyComplete = function () {
this.hasSubscription = false;
if (this.hasCompleted) {
this.destination.complete();
}
};
return ExhaustMapSubscriber;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START tslib,_Subscriber,_Subscription PURE_IMPORTS_END */
function finalize$1(callback) {
return function (source) { return source.lift(new FinallyOperator(callback)); };
}
var FinallyOperator = /*@__PURE__*/ (function () {
function FinallyOperator(callback) {
this.callback = callback;
}
FinallyOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new FinallySubscriber(subscriber, this.callback));
};
return FinallyOperator;
}());
var FinallySubscriber = /*@__PURE__*/ (function (_super) {
__extends(FinallySubscriber, _super);
function FinallySubscriber(destination, callback) {
var _this = _super.call(this, destination) || this;
_this.add(new Subscription(callback));
return _this;
}
return FinallySubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */
function takeLast(count) {
return function takeLastOperatorFunction(source) {
if (count === 0) {
return empty();
}
else {
return source.lift(new TakeLastOperator(count));
}
};
}
var TakeLastOperator = /*@__PURE__*/ (function () {
function TakeLastOperator(total) {
this.total = total;
if (this.total < 0) {
throw new ArgumentOutOfRangeError;
}
}
TakeLastOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new TakeLastSubscriber(subscriber, this.total));
};
return TakeLastOperator;
}());
var TakeLastSubscriber = /*@__PURE__*/ (function (_super) {
__extends(TakeLastSubscriber, _super);
function TakeLastSubscriber(destination, total) {
var _this = _super.call(this, destination) || this;
_this.total = total;
_this.ring = new Array();
_this.count = 0;
return _this;
}
TakeLastSubscriber.prototype._next = function (value) {
var ring = this.ring;
var total = this.total;
var count = this.count++;
if (ring.length < total) {
ring.push(value);
}
else {
var index = count % total;
ring[index] = value;
}
};
TakeLastSubscriber.prototype._complete = function () {
var destination = this.destination;
var count = this.count;
if (count > 0) {
var total = this.count >= this.total ? this.total : this.count;
var ring = this.ring;
for (var i = 0; i < total; i++) {
var idx = (count++) % total;
destination.next(ring[idx]);
}
}
destination.complete();
};
return TakeLastSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function mapTo(value) {
return function (source) { return source.lift(new MapToOperator(value)); };
}
var MapToOperator = /*@__PURE__*/ (function () {
function MapToOperator(value) {
this.value = value;
}
MapToOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new MapToSubscriber(subscriber, this.value));
};
return MapToOperator;
}());
var MapToSubscriber = /*@__PURE__*/ (function (_super) {
__extends(MapToSubscriber, _super);
function MapToSubscriber(destination, value) {
var _this = _super.call(this, destination) || this;
_this.value = value;
return _this;
}
MapToSubscriber.prototype._next = function (x) {
this.destination.next(this.value);
};
return MapToSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function scan(accumulator, seed) {
var hasSeed = false;
if (arguments.length >= 2) {
hasSeed = true;
}
return function scanOperatorFunction(source) {
return source.lift(new ScanOperator(accumulator, seed, hasSeed));
};
}
var ScanOperator = /*@__PURE__*/ (function () {
function ScanOperator(accumulator, seed, hasSeed) {
if (hasSeed === void 0) {
hasSeed = false;
}
this.accumulator = accumulator;
this.seed = seed;
this.hasSeed = hasSeed;
}
ScanOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new ScanSubscriber(subscriber, this.accumulator, this.seed, this.hasSeed));
};
return ScanOperator;
}());
var ScanSubscriber = /*@__PURE__*/ (function (_super) {
__extends(ScanSubscriber, _super);
function ScanSubscriber(destination, accumulator, _seed, hasSeed) {
var _this = _super.call(this, destination) || this;
_this.accumulator = accumulator;
_this._seed = _seed;
_this.hasSeed = hasSeed;
_this.index = 0;
return _this;
}
Object.defineProperty(ScanSubscriber.prototype, "seed", {
get: function () {
return this._seed;
},
set: function (value) {
this.hasSeed = true;
this._seed = value;
},
enumerable: true,
configurable: true
});
ScanSubscriber.prototype._next = function (value) {
if (!this.hasSeed) {
this.seed = value;
this.destination.next(value);
}
else {
return this._tryNext(value);
}
};
ScanSubscriber.prototype._tryNext = function (value) {
var index = this.index++;
var result;
try {
result = this.accumulator(this.seed, value, index);
}
catch (err) {
this.destination.error(err);
}
this.seed = result;
this.destination.next(result);
};
return ScanSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */
function reduce(accumulator, seed) {
if (arguments.length >= 2) {
return function reduceOperatorFunctionWithSeed(source) {
return pipe(scan(accumulator, seed), takeLast(1), defaultIfEmpty(seed))(source);
};
}
return function reduceOperatorFunction(source) {
return pipe(scan(function (acc, value, index) { return accumulator(acc, value, index + 1); }), takeLast(1))(source);
};
}
/** PURE_IMPORTS_START _observable_ConnectableObservable PURE_IMPORTS_END */
function multicast(subjectOrSubjectFactory, selector) {
return function multicastOperatorFunction(source) {
var subjectFactory;
if (typeof subjectOrSubjectFactory === 'function') {
subjectFactory = subjectOrSubjectFactory;
}
else {
subjectFactory = function subjectFactory() {
return subjectOrSubjectFactory;
};
}
if (typeof selector === 'function') {
return source.lift(new MulticastOperator(subjectFactory, selector));
}
var connectable = Object.create(source, connectableObservableDescriptor);
connectable.source = source;
connectable.subjectFactory = subjectFactory;
return connectable;
};
}
var MulticastOperator = /*@__PURE__*/ (function () {
function MulticastOperator(subjectFactory, selector) {
this.subjectFactory = subjectFactory;
this.selector = selector;
}
MulticastOperator.prototype.call = function (subscriber, source) {
var selector = this.selector;
var subject = this.subjectFactory();
var subscription = selector(subject).subscribe(subscriber);
subscription.add(source.subscribe(subject));
return subscription;
};
return MulticastOperator;
}());
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function pairwise() {
return function (source) { return source.lift(new PairwiseOperator()); };
}
var PairwiseOperator = /*@__PURE__*/ (function () {
function PairwiseOperator() {
}
PairwiseOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new PairwiseSubscriber(subscriber));
};
return PairwiseOperator;
}());
var PairwiseSubscriber = /*@__PURE__*/ (function (_super) {
__extends(PairwiseSubscriber, _super);
function PairwiseSubscriber(destination) {
var _this = _super.call(this, destination) || this;
_this.hasPrev = false;
return _this;
}
PairwiseSubscriber.prototype._next = function (value) {
var pair;
if (this.hasPrev) {
pair = [this.prev, value];
}
else {
this.hasPrev = true;
}
this.prev = value;
if (pair) {
this.destination.next(pair);
}
};
return PairwiseSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subject,_innerSubscribe PURE_IMPORTS_END */
function retryWhen(notifier) {
return function (source) { return source.lift(new RetryWhenOperator(notifier, source)); };
}
var RetryWhenOperator = /*@__PURE__*/ (function () {
function RetryWhenOperator(notifier, source) {
this.notifier = notifier;
this.source = source;
}
RetryWhenOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new RetryWhenSubscriber(subscriber, this.notifier, this.source));
};
return RetryWhenOperator;
}());
var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) {
__extends(RetryWhenSubscriber, _super);
function RetryWhenSubscriber(destination, notifier, source) {
var _this = _super.call(this, destination) || this;
_this.notifier = notifier;
_this.source = source;
return _this;
}
RetryWhenSubscriber.prototype.error = function (err) {
if (!this.isStopped) {
var errors = this.errors;
var retries = this.retries;
var retriesSubscription = this.retriesSubscription;
if (!retries) {
errors = new Subject();
try {
var notifier = this.notifier;
retries = notifier(errors);
}
catch (e) {
return _super.prototype.error.call(this, e);
}
retriesSubscription = innerSubscribe(retries, new SimpleInnerSubscriber(this));
}
else {
this.errors = undefined;
this.retriesSubscription = undefined;
}
this._unsubscribeAndRecycle();
this.errors = errors;
this.retries = retries;
this.retriesSubscription = retriesSubscription;
errors.next(err);
}
};
RetryWhenSubscriber.prototype._unsubscribe = function () {
var _a = this, errors = _a.errors, retriesSubscription = _a.retriesSubscription;
if (errors) {
errors.unsubscribe();
this.errors = undefined;
}
if (retriesSubscription) {
retriesSubscription.unsubscribe();
this.retriesSubscription = undefined;
}
this.retries = undefined;
};
RetryWhenSubscriber.prototype.notifyNext = function () {
var _unsubscribe = this._unsubscribe;
this._unsubscribe = null;
this._unsubscribeAndRecycle();
this._unsubscribe = _unsubscribe;
this.source.subscribe(this);
};
return RetryWhenSubscriber;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */
function shareSubjectFactory() {
return new Subject();
}
function share() {
return function (source) { return refCount()(multicast(shareSubjectFactory)(source)); };
}
/** PURE_IMPORTS_START _ReplaySubject PURE_IMPORTS_END */
function shareReplay(configOrBufferSize, windowTime, scheduler) {
var config;
if (configOrBufferSize && typeof configOrBufferSize === 'object') {
config = configOrBufferSize;
}
else {
config = {
bufferSize: configOrBufferSize,
windowTime: windowTime,
refCount: false,
scheduler: scheduler,
};
}
return function (source) { return source.lift(shareReplayOperator(config)); };
}
function shareReplayOperator(_a) {
var _b = _a.bufferSize, bufferSize = _b === void 0 ? Number.POSITIVE_INFINITY : _b, _c = _a.windowTime, windowTime = _c === void 0 ? Number.POSITIVE_INFINITY : _c, useRefCount = _a.refCount, scheduler = _a.scheduler;
var subject;
var refCount = 0;
var subscription;
var hasError = false;
var isComplete = false;
return function shareReplayOperation(source) {
refCount++;
var innerSub;
if (!subject || hasError) {
hasError = false;
subject = new ReplaySubject(bufferSize, windowTime, scheduler);
innerSub = subject.subscribe(this);
subscription = source.subscribe({
next: function (value) {
subject.next(value);
},
error: function (err) {
hasError = true;
subject.error(err);
},
complete: function () {
isComplete = true;
subscription = undefined;
subject.complete();
},
});
if (isComplete) {
subscription = undefined;
}
}
else {
innerSub = subject.subscribe(this);
}
this.add(function () {
refCount--;
innerSub.unsubscribe();
innerSub = undefined;
if (subscription && !isComplete && useRefCount && refCount === 0) {
subscription.unsubscribe();
subscription = undefined;
subject = undefined;
}
});
};
}
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function skip(count) {
return function (source) { return source.lift(new SkipOperator(count)); };
}
var SkipOperator = /*@__PURE__*/ (function () {
function SkipOperator(total) {
this.total = total;
}
SkipOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new SkipSubscriber(subscriber, this.total));
};
return SkipOperator;
}());
var SkipSubscriber = /*@__PURE__*/ (function (_super) {
__extends(SkipSubscriber, _super);
function SkipSubscriber(destination, total) {
var _this = _super.call(this, destination) || this;
_this.total = total;
_this.count = 0;
return _this;
}
SkipSubscriber.prototype._next = function (x) {
if (++this.count > this.total) {
this.destination.next(x);
}
};
return SkipSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START _observable_concat,_util_isScheduler PURE_IMPORTS_END */
function startWith() {
var array = [];
for (var _i = 0; _i < arguments.length; _i++) {
array[_i] = arguments[_i];
}
var scheduler = array[array.length - 1];
if (isScheduler(scheduler)) {
array.pop();
return function (source) { return concat(array, source, scheduler); };
}
else {
return function (source) { return concat(array, source); };
}
}
/** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */
function switchMap(project, resultSelector) {
if (typeof resultSelector === 'function') {
return function (source) { return source.pipe(switchMap(function (a, i) { return from(project(a, i)).pipe(map(function (b, ii) { return resultSelector(a, b, i, ii); })); })); };
}
return function (source) { return source.lift(new SwitchMapOperator(project)); };
}
var SwitchMapOperator = /*@__PURE__*/ (function () {
function SwitchMapOperator(project) {
this.project = project;
}
SwitchMapOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new SwitchMapSubscriber(subscriber, this.project));
};
return SwitchMapOperator;
}());
var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) {
__extends(SwitchMapSubscriber, _super);
function SwitchMapSubscriber(destination, project) {
var _this = _super.call(this, destination) || this;
_this.project = project;
_this.index = 0;
return _this;
}
SwitchMapSubscriber.prototype._next = function (value) {
var result;
var index = this.index++;
try {
result = this.project(value, index);
}
catch (error) {
this.destination.error(error);
return;
}
this._innerSub(result);
};
SwitchMapSubscriber.prototype._innerSub = function (result) {
var innerSubscription = this.innerSubscription;
if (innerSubscription) {
innerSubscription.unsubscribe();
}
var innerSubscriber = new SimpleInnerSubscriber(this);
var destination = this.destination;
destination.add(innerSubscriber);
this.innerSubscription = innerSubscribe(result, innerSubscriber);
if (this.innerSubscription !== innerSubscriber) {
destination.add(this.innerSubscription);
}
};
SwitchMapSubscriber.prototype._complete = function () {
var innerSubscription = this.innerSubscription;
if (!innerSubscription || innerSubscription.closed) {
_super.prototype._complete.call(this);
}
this.unsubscribe();
};
SwitchMapSubscriber.prototype._unsubscribe = function () {
this.innerSubscription = undefined;
};
SwitchMapSubscriber.prototype.notifyComplete = function () {
this.innerSubscription = undefined;
if (this.isStopped) {
_super.prototype._complete.call(this);
}
};
SwitchMapSubscriber.prototype.notifyNext = function (innerValue) {
this.destination.next(innerValue);
};
return SwitchMapSubscriber;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */
function switchMapTo(innerObservable, resultSelector) {
return resultSelector ? switchMap(function () { return innerObservable; }, resultSelector) : switchMap(function () { return innerObservable; });
}
/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
function takeUntil(notifier) {
return function (source) { return source.lift(new TakeUntilOperator(notifier)); };
}
var TakeUntilOperator = /*@__PURE__*/ (function () {
function TakeUntilOperator(notifier) {
this.notifier = notifier;
}
TakeUntilOperator.prototype.call = function (subscriber, source) {
var takeUntilSubscriber = new TakeUntilSubscriber(subscriber);
var notifierSubscription = innerSubscribe(this.notifier, new SimpleInnerSubscriber(takeUntilSubscriber));
if (notifierSubscription && !takeUntilSubscriber.seenValue) {
takeUntilSubscriber.add(notifierSubscription);
return source.subscribe(takeUntilSubscriber);
}
return takeUntilSubscriber;
};
return TakeUntilOperator;
}());
var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) {
__extends(TakeUntilSubscriber, _super);
function TakeUntilSubscriber(destination) {
var _this = _super.call(this, destination) || this;
_this.seenValue = false;
return _this;
}
TakeUntilSubscriber.prototype.notifyNext = function () {
this.seenValue = true;
this.complete();
};
TakeUntilSubscriber.prototype.notifyComplete = function () {
};
return TakeUntilSubscriber;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */
function takeWhile(predicate, inclusive) {
if (inclusive === void 0) {
inclusive = false;
}
return function (source) {
return source.lift(new TakeWhileOperator(predicate, inclusive));
};
}
var TakeWhileOperator = /*@__PURE__*/ (function () {
function TakeWhileOperator(predicate, inclusive) {
this.predicate = predicate;
this.inclusive = inclusive;
}
TakeWhileOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new TakeWhileSubscriber(subscriber, this.predicate, this.inclusive));
};
return TakeWhileOperator;
}());
var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) {
__extends(TakeWhileSubscriber, _super);
function TakeWhileSubscriber(destination, predicate, inclusive) {
var _this = _super.call(this, destination) || this;
_this.predicate = predicate;
_this.inclusive = inclusive;
_this.index = 0;
return _this;
}
TakeWhileSubscriber.prototype._next = function (value) {
var destination = this.destination;
var result;
try {
result = this.predicate(value, this.index++);
}
catch (err) {
destination.error(err);
return;
}
this.nextOrComplete(value, result);
};
TakeWhileSubscriber.prototype.nextOrComplete = function (value, predicateResult) {
var destination = this.destination;
if (Boolean(predicateResult)) {
destination.next(value);
}
else {
if (this.inclusive) {
destination.next(value);
}
destination.complete();
}
};
return TakeWhileSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_Subscriber,_util_noop,_util_isFunction PURE_IMPORTS_END */
function tap(nextOrObserver, error, complete) {
return function tapOperatorFunction(source) {
return source.lift(new DoOperator(nextOrObserver, error, complete));
};
}
var DoOperator = /*@__PURE__*/ (function () {
function DoOperator(nextOrObserver, error, complete) {
this.nextOrObserver = nextOrObserver;
this.error = error;
this.complete = complete;
}
DoOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new TapSubscriber(subscriber, this.nextOrObserver, this.error, this.complete));
};
return DoOperator;
}());
var TapSubscriber = /*@__PURE__*/ (function (_super) {
__extends(TapSubscriber, _super);
function TapSubscriber(destination, observerOrNext, error, complete) {
var _this = _super.call(this, destination) || this;
_this._tapNext = noop;
_this._tapError = noop;
_this._tapComplete = noop;
_this._tapError = error || noop;
_this._tapComplete = complete || noop;
if (isFunction$1(observerOrNext)) {
_this._context = _this;
_this._tapNext = observerOrNext;
}
else if (observerOrNext) {
_this._context = observerOrNext;
_this._tapNext = observerOrNext.next || noop;
_this._tapError = observerOrNext.error || noop;
_this._tapComplete = observerOrNext.complete || noop;
}
return _this;
}
TapSubscriber.prototype._next = function (value) {
try {
this._tapNext.call(this._context, value);
}
catch (err) {
this.destination.error(err);
return;
}
this.destination.next(value);
};
TapSubscriber.prototype._error = function (err) {
try {
this._tapError.call(this._context, err);
}
catch (err) {
this.destination.error(err);
return;
}
this.destination.error(err);
};
TapSubscriber.prototype._complete = function () {
try {
this._tapComplete.call(this._context);
}
catch (err) {
this.destination.error(err);
return;
}
return this.destination.complete();
};
return TapSubscriber;
}(Subscriber));
/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */
var defaultThrottleConfig = {
leading: true,
trailing: false
};
/** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */
function throttleTime(duration, scheduler, config) {
if (scheduler === void 0) {
scheduler = async;
}
if (config === void 0) {
config = defaultThrottleConfig;
}
return function (source) { return source.lift(new ThrottleTimeOperator(duration, scheduler, config.leading, config.trailing)); };
}
var ThrottleTimeOperator = /*@__PURE__*/ (function () {
function ThrottleTimeOperator(duration, scheduler, leading, trailing) {
this.duration = duration;
this.scheduler = scheduler;
this.leading = leading;
this.trailing = trailing;
}
ThrottleTimeOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new ThrottleTimeSubscriber(subscriber, this.duration, this.scheduler, this.leading, this.trailing));
};
return ThrottleTimeOperator;
}());
var ThrottleTimeSubscriber = /*@__PURE__*/ (function (_super) {
__extends(ThrottleTimeSubscriber, _super);
function ThrottleTimeSubscriber(destination, duration, scheduler, leading, trailing) {
var _this = _super.call(this, destination) || this;
_this.duration = duration;
_this.scheduler = scheduler;
_this.leading = leading;
_this.trailing = trailing;
_this._hasTrailingValue = false;
_this._trailingValue = null;
return _this;
}
ThrottleTimeSubscriber.prototype._next = function (value) {
if (this.throttled) {
if (this.trailing) {
this._trailingValue = value;
this._hasTrailingValue = true;
}
}
else {
this.add(this.throttled = this.scheduler.schedule(dispatchNext, this.duration, { subscriber: this }));
if (this.leading) {
this.destination.next(value);
}
else if (this.trailing) {
this._trailingValue = value;
this._hasTrailingValue = true;
}
}
};
ThrottleTimeSubscriber.prototype._complete = function () {
if (this._hasTrailingValue) {
this.destination.next(this._trailingValue);
this.destination.complete();
}
else {
this.destination.complete();
}
};
ThrottleTimeSubscriber.prototype.clearThrottle = function () {
var throttled = this.throttled;
if (throttled) {
if (this.trailing && this._hasTrailingValue) {
this.destination.next(this._trailingValue);
this._trailingValue = null;
this._hasTrailingValue = false;
}
throttled.unsubscribe();
this.remove(throttled);
this.throttled = null;
}
};
return ThrottleTimeSubscriber;
}(Subscriber));
function dispatchNext(arg) {
var subscriber = arg.subscriber;
subscriber.clearThrottle();
}
/** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_innerSubscribe PURE_IMPORTS_END */
function timeoutWith(due, withObservable, scheduler) {
if (scheduler === void 0) {
scheduler = async;
}
return function (source) {
var absoluteTimeout = isDate(due);
var waitFor = absoluteTimeout ? (+due - scheduler.now()) : Math.abs(due);
return source.lift(new TimeoutWithOperator(waitFor, absoluteTimeout, withObservable, scheduler));
};
}
var TimeoutWithOperator = /*@__PURE__*/ (function () {
function TimeoutWithOperator(waitFor, absoluteTimeout, withObservable, scheduler) {
this.waitFor = waitFor;
this.absoluteTimeout = absoluteTimeout;
this.withObservable = withObservable;
this.scheduler = scheduler;
}
TimeoutWithOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new TimeoutWithSubscriber(subscriber, this.absoluteTimeout, this.waitFor, this.withObservable, this.scheduler));
};
return TimeoutWithOperator;
}());
var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) {
__extends(TimeoutWithSubscriber, _super);
function TimeoutWithSubscriber(destination, absoluteTimeout, waitFor, withObservable, scheduler) {
var _this = _super.call(this, destination) || this;
_this.absoluteTimeout = absoluteTimeout;
_this.waitFor = waitFor;
_this.withObservable = withObservable;
_this.scheduler = scheduler;
_this.scheduleTimeout();
return _this;
}
TimeoutWithSubscriber.dispatchTimeout = function (subscriber) {
var withObservable = subscriber.withObservable;
subscriber._unsubscribeAndRecycle();
subscriber.add(innerSubscribe(withObservable, new SimpleInnerSubscriber(subscriber)));
};
TimeoutWithSubscriber.prototype.scheduleTimeout = function () {
var action = this.action;
if (action) {
this.action = action.schedule(this, this.waitFor);
}
else {
this.add(this.action = this.scheduler.schedule(TimeoutWithSubscriber.dispatchTimeout, this.waitFor, this));
}
};
TimeoutWithSubscriber.prototype._next = function (value) {
if (!this.absoluteTimeout) {
this.scheduleTimeout();
}
_super.prototype._next.call(this, value);
};
TimeoutWithSubscriber.prototype._unsubscribe = function () {
this.action = undefined;
this.scheduler = null;
this.withObservable = null;
};
return TimeoutWithSubscriber;
}(SimpleOuterSubscriber));
/** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */
function timeout(due, scheduler) {
if (scheduler === void 0) {
scheduler = async;
}
return timeoutWith(due, throwError(new TimeoutError()), scheduler);
}
/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */
function withLatestFrom() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return function (source) {
var project;
if (typeof args[args.length - 1] === 'function') {
project = args.pop();
}
var observables = args;
return source.lift(new WithLatestFromOperator(observables, project));
};
}
var WithLatestFromOperator = /*@__PURE__*/ (function () {
function WithLatestFromOperator(observables, project) {
this.observables = observables;
this.project = project;
}
WithLatestFromOperator.prototype.call = function (subscriber, source) {
return source.subscribe(new WithLatestFromSubscriber(subscriber, this.observables, this.project));
};
return WithLatestFromOperator;
}());
var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) {
__extends(WithLatestFromSubscriber, _super);
function WithLatestFromSubscriber(destination, observables, project) {
var _this = _super.call(this, destination) || this;
_this.observables = observables;
_this.project = project;
_this.toRespond = [];
var len = observables.length;
_this.values = new Array(len);
for (var i = 0; i < len; i++) {
_this.toRespond.push(i);
}
for (var i = 0; i < len; i++) {
var observable = observables[i];
_this.add(subscribeToResult(_this, observable, undefined, i));
}
return _this;
}
WithLatestFromSubscriber.prototype.notifyNext = function (_outerValue, innerValue, outerIndex) {
this.values[outerIndex] = innerValue;
var toRespond = this.toRespond;
if (toRespond.length > 0) {
var found = toRespond.indexOf(outerIndex);
if (found !== -1) {
toRespond.splice(found, 1);
}
}
};
WithLatestFromSubscriber.prototype.notifyComplete = function () {
};
WithLatestFromSubscriber.prototype._next = function (value) {
if (this.toRespond.length === 0) {
var args = [value].concat(this.values);
if (this.project) {
this._tryProject(args);
}
else {
this.destination.next(args);
}
}
};
WithLatestFromSubscriber.prototype._tryProject = function (args) {
var result;
try {
result = this.project.apply(this, args);
}
catch (err) {
this.destination.error(err);
return;
}
this.destination.next(result);
};
return WithLatestFromSubscriber;
}(OuterSubscriber));
var currentAction = {
type: null,
entityIds: null,
skip: false,
};
var customActionActive = false;
function resetCustomAction() {
customActionActive = false;
}
// public API for custom actions. Custom action always wins
function logAction(type, entityIds) {
setAction(type, entityIds);
customActionActive = true;
}
function setAction(type, entityIds) {
if (customActionActive === false) {
currentAction.type = type;
currentAction.entityIds = entityIds;
}
}
function action(action, entityIds) {
return function (target, propertyKey, descriptor) {
var originalMethod = descriptor.value;
descriptor.value = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
logAction(action, entityIds);
return originalMethod.apply(this, args);
};
return descriptor;
};
}
// @internal
function hasEntity(entities, id) {
return entities.hasOwnProperty(id);
}
// @internal
function addEntities(_a) {
var state = _a.state, entities = _a.entities, idKey = _a.idKey, _b = _a.options, options = _b === void 0 ? {} : _b, preAddEntity = _a.preAddEntity;
var e_1, _c;
var newEntities = {};
var newIds = [];
var hasNewEntities = false;
try {
for (var entities_1 = __values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
var entity = entities_1_1.value;
if (hasEntity(state.entities, entity[idKey]) === false) {
// evaluate the middleware first to support dynamic ids
var current = preAddEntity(entity);
var entityId = current[idKey];
newEntities[entityId] = current;
if (options.prepend)
newIds.unshift(entityId);
else
newIds.push(entityId);
hasNewEntities = true;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (entities_1_1 && !entities_1_1.done && (_c = entities_1.return)) _c.call(entities_1);
}
finally { if (e_1) throw e_1.error; }
}
return hasNewEntities
? {
newState: __assign({}, state, { entities: __assign({}, state.entities, newEntities), ids: options.prepend ? __spread(newIds, state.ids) : __spread(state.ids, newIds) }),
newIds: newIds
}
: null;
}
// @internal
function isNil(v) {
return v === null || v === undefined;
}
// @internal
function coerceArray(value) {
if (isNil(value)) {
return [];
}
return Array.isArray(value) ? value : [value];
}
var DEFAULT_ID_KEY = 'id';
var EntityActions;
(function (EntityActions) {
EntityActions["Set"] = "Set";
EntityActions["Add"] = "Add";
EntityActions["Update"] = "Update";
EntityActions["Remove"] = "Remove";
})(EntityActions || (EntityActions = {}));
var isBrowser = typeof window !== 'undefined';
// @internal
function isObject(value) {
var type = typeof value;
return value != null && (type == 'object' || type == 'function');
}
// @internal
function isArray(value) {
return Array.isArray(value);
}
// @internal
function getActiveEntities(idOrOptions, ids, currentActive) {
var result;
if (isArray(idOrOptions)) {
result = idOrOptions;
}
else {
if (isObject(idOrOptions)) {
if (isNil(currentActive))
return;
idOrOptions = Object.assign({ wrap: true }, idOrOptions);
var currentIdIndex = ids.indexOf(currentActive);
if (idOrOptions.prev) {
var isFirst = currentIdIndex === 0;
if (isFirst && !idOrOptions.wrap)
return;
result = isFirst ? ids[ids.length - 1] : ids[currentIdIndex - 1];
}
else if (idOrOptions.next) {
var isLast = ids.length === currentIdIndex + 1;
if (isLast && !idOrOptions.wrap)
return;
result = isLast ? ids[0] : ids[currentIdIndex + 1];
}
}
else {
if (idOrOptions === currentActive)
return;
result = idOrOptions;
}
}
return result;
}
// @internal
var getInitialEntitiesState = function () {
return ({
entities: {},
ids: [],
loading: true,
error: null
});
};
// @internal
function isDefined(val) {
return isNil(val) === false;
}
// @internal
function isEmpty(arr) {
if (isArray(arr)) {
return arr.length === 0;
}
return false;
}
// @internal
function isFunction(value) {
return typeof value === 'function';
}
// @internal
function isUndefined(value) {
return value === undefined;
}
// @internal
function hasActiveState(state) {
return state.hasOwnProperty('active');
}
// @internal
function isMultiActiveState(active) {
return isArray(active);
}
// @internal
function resolveActiveEntity(_a) {
var active = _a.active, ids = _a.ids, entities = _a.entities;
if (isMultiActiveState(active)) {
return getExitingActives(active, ids);
}
if (hasEntity(entities, active) === false) {
return null;
}
return active;
}
// @internal
function getExitingActives(currentActivesIds, newIds) {
var filtered = currentActivesIds.filter(function (id) { return newIds.indexOf(id) > -1; });
/** Return the same reference if nothing has changed */
if (filtered.length === currentActivesIds.length) {
return currentActivesIds;
}
return filtered;
}
// @internal
function removeEntities(_a) {
var state = _a.state, ids = _a.ids;
var e_1, _b;
if (isNil(ids))
return removeAllEntities(state);
var entities = state.entities;
var newEntities = {};
try {
for (var _c = __values(state.ids), _d = _c.next(); !_d.done; _d = _c.next()) {
var id = _d.value;
if (ids.includes(id) === false) {
newEntities[id] = entities[id];
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
var newState = __assign({}, state, { entities: newEntities, ids: state.ids.filter(function (current) { return ids.includes(current) === false; }) });
if (hasActiveState(state)) {
newState.active = resolveActiveEntity(newState);
}
return newState;
}
// @internal
function removeAllEntities(state) {
return __assign({}, state, { entities: {}, ids: [], active: isMultiActiveState(state.active) ? [] : null });
}
// @internal
function toEntitiesObject(entities, idKey, preAddEntity) {
var e_1, _a;
var acc = {
entities: {},
ids: []
};
try {
for (var entities_1 = __values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
var entity = entities_1_1.value;
// evaluate the middleware first to support dynamic ids
var current = preAddEntity(entity);
acc.entities[current[idKey]] = current;
acc.ids.push(current[idKey]);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1);
}
finally { if (e_1) throw e_1.error; }
}
return acc;
}
// @internal
function isEntityState(state) {
return state.entities && state.ids;
}
// @internal
function applyMiddleware(entities, preAddEntity) {
var e_1, _a;
var mapped = {};
try {
for (var _b = __values(Object.keys(entities)), _c = _b.next(); !_c.done; _c = _b.next()) {
var id = _c.value;
mapped[id] = preAddEntity(entities[id]);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return mapped;
}
// @internal
function setEntities(_a) {
var state = _a.state, entities = _a.entities, idKey = _a.idKey, preAddEntity = _a.preAddEntity, isNativePreAdd = _a.isNativePreAdd;
var newEntities;
var newIds;
if (isArray(entities)) {
var resolve = toEntitiesObject(entities, idKey, preAddEntity);
newEntities = resolve.entities;
newIds = resolve.ids;
}
else if (isEntityState(entities)) {
newEntities = isNativePreAdd ? entities.entities : applyMiddleware(entities.entities, preAddEntity);
newIds = entities.ids;
}
else {
// it's an object
newEntities = isNativePreAdd ? entities : applyMiddleware(entities, preAddEntity);
newIds = Object.keys(newEntities).map(function (id) { return (isNaN(id) ? id : Number(id)); });
}
var newState = __assign({}, state, { entities: newEntities, ids: newIds, loading: false });
if (hasActiveState(state)) {
newState.active = resolveActiveEntity(newState);
}
return newState;
}
var CONFIG = {
resettable: false,
ttl: null,
producerFn: undefined
};
// @internal
function getAkitaConfig() {
return CONFIG;
}
function getGlobalProducerFn() {
return CONFIG.producerFn;
}
// @internal
function deepFreeze(o) {
Object.freeze(o);
var oIsFunction = typeof o === 'function';
var hasOwnProp = Object.prototype.hasOwnProperty;
Object.getOwnPropertyNames(o).forEach(function (prop) {
if (hasOwnProp.call(o, prop) &&
(oIsFunction ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments' : true) &&
o[prop] !== null &&
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
!Object.isFrozen(o[prop])) {
deepFreeze(o[prop]);
}
});
return o;
}
// @internal
var $$deleteStore = new Subject();
// @internal
var $$addStore = new ReplaySubject(50, 5000);
// @internal
var $$updateStore = new Subject();
// @internal
function dispatchDeleted(storeName) {
$$deleteStore.next(storeName);
}
// @internal
function dispatchAdded(storeName) {
$$addStore.next(storeName);
}
// @internal
function dispatchUpdate(storeName, action) {
$$updateStore.next({ storeName: storeName, action: action });
}
// @internal
/** @class */ ((function (_super) {
__extends(AkitaError, _super);
function AkitaError(message) {
return _super.call(this, message) || this;
}
return AkitaError;
})(Error));
// @internal
function assertStoreHasName(name, className) {
if (!name) {
console.error("@StoreConfig({ name }) is missing in " + className);
}
}
// @internal
function toBoolean(value) {
return value != null && "" + value !== 'false';
}
// @internal
function isPlainObject$1(value) {
return toBoolean(value) && value.constructor.name === 'Object';
}
var configKey = 'akitaConfig';
// @internal
var __stores__ = {};
// @internal
var __queries__ = {};
if (isBrowser) {
window.$$stores = __stores__;
window.$$queries = __queries__;
}
// @internal
var transactionFinished = new Subject();
// @internal
var transactionInProcess = new BehaviorSubject(false);
// @internal
var transactionManager = {
activeTransactions: 0,
batchTransaction: null
};
// @internal
function startBatch() {
if (!isTransactionInProcess()) {
transactionManager.batchTransaction = new Subject();
}
transactionManager.activeTransactions++;
transactionInProcess.next(true);
}
// @internal
function endBatch() {
if (--transactionManager.activeTransactions === 0) {
transactionManager.batchTransaction.next(true);
transactionManager.batchTransaction.complete();
transactionInProcess.next(false);
transactionFinished.next(true);
}
}
// @internal
function isTransactionInProcess() {
return transactionManager.activeTransactions > 0;
}
// @internal
function commit() {
return transactionManager.batchTransaction ? transactionManager.batchTransaction.asObservable() : of(true);
}
/**
* A logical transaction.
* Use this transaction to optimize the dispatch of all the stores.
* The following code will update the store, BUT emits only once
*
* @example
* applyTransaction(() => {
* this.todosStore.add(new Todo(1, title));
* this.todosStore.add(new Todo(2, title));
* });
*
*/
function applyTransaction(action, thisArg) {
if (thisArg === void 0) { thisArg = undefined; }
startBatch();
try {
return action.apply(thisArg);
}
finally {
logAction('@Transaction');
endBatch();
}
}
/**
* A logical transaction.
* Use this transaction to optimize the dispatch of all the stores.
*
* The following code will update the store, BUT emits only once.
*
* @example
* @transaction
* addTodos() {
* this.todosStore.add(new Todo(1, title));
* this.todosStore.add(new Todo(2, title));
* }
*
*
*/
function transaction() {
return function (target, propertyKey, descriptor) {
var originalMethod = descriptor.value;
descriptor.value = function () {
var _this = this;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return applyTransaction(function () {
return originalMethod.apply(_this, args);
}, this);
};
return descriptor;
};
}
/**
*
* RxJS custom operator that wraps the callback inside transaction
*
* @example
*
* return http.get().pipe(
* withTransaction(response > {
* store.setActive(1);
* store.update();
* store.updateEntity(1, {});
* })
* )
*
*/
function withTransaction(next) {
return function (source) {
return source.pipe(tap(function (value) { return applyTransaction(function () { return next(value); }); }));
};
}
/**
*
* Store for managing any type of data
*
* @example
*
* export interface SessionState {
* token: string;
* userDetails: UserDetails
* }
*
* export function createInitialState(): SessionState {
* return {
* token: '',
* userDetails: null
* };
* }
*
* @StoreConfig({ name: 'session' })
* export class SessionStore extends Store {
* constructor() {
* super(createInitialState());
* }
* }
*/
var Store = /** @class */ (function () {
function Store(initialState, options) {
if (options === void 0) { options = {}; }
this.options = options;
this.inTransaction = false;
this.cache = {
active: new BehaviorSubject(false),
ttl: null,
};
this.onInit(initialState);
}
/**
* Set the loading state
*
* @example
*
* store.setLoading(true)
*
*/
Store.prototype.setLoading = function (loading) {
if (loading === void 0) { loading = false; }
if (loading !== this._value().loading) {
setAction('Set Loading');
this._setState(function (state) { return (__assign({}, state, { loading: loading })); });
}
};
/**
*
* Set whether the data is cached
*
* @example
*
* store.setHasCache(true)
* store.setHasCache(false)
* store.setHasCache(true, { restartTTL: true })
*
*/
Store.prototype.setHasCache = function (hasCache, options) {
var _this = this;
if (options === void 0) { options = { restartTTL: false }; }
if (hasCache !== this.cache.active.value) {
this.cache.active.next(hasCache);
}
if (options.restartTTL) {
var ttlConfig = this.getCacheTTL();
if (ttlConfig) {
if (this.cache.ttl !== null) {
clearTimeout(this.cache.ttl);
}
this.cache.ttl = setTimeout(function () { return _this.setHasCache(false); }, ttlConfig);
}
}
};
/**
*
* Sometimes we need to access the store value from a store
*
* @example middleware
*
*/
Store.prototype.getValue = function () {
return this.storeValue;
};
/**
* Set the error state
*
* @example
*
* store.setError({text: 'unable to load data' })
*
*/
Store.prototype.setError = function (error) {
if (error !== this._value().error) {
setAction('Set Error');
this._setState(function (state) { return (__assign({}, state, { error: error })); });
}
};
// @internal
Store.prototype._select = function (project) {
return this.store.asObservable().pipe(map(function (snapshot) { return project(snapshot.state); }), distinctUntilChanged());
};
// @internal
Store.prototype._value = function () {
return this.storeValue;
};
// @internal
Store.prototype._cache = function () {
return this.cache.active;
};
Object.defineProperty(Store.prototype, "config", {
// @internal
get: function () {
return this.constructor[configKey] || {};
},
enumerable: true,
configurable: true
});
Object.defineProperty(Store.prototype, "storeName", {
// @internal
get: function () {
return this.config.storeName || this.options.storeName || this.options.name;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Store.prototype, "deepFreeze", {
// @internal
get: function () {
return this.config.deepFreezeFn || this.options.deepFreezeFn || deepFreeze;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Store.prototype, "cacheConfig", {
// @internal
get: function () {
return this.config.cache || this.options.cache;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Store.prototype, "_producerFn", {
get: function () {
return this.config.producerFn || this.options.producerFn || getGlobalProducerFn();
},
enumerable: true,
configurable: true
});
Object.defineProperty(Store.prototype, "resettable", {
// @internal
get: function () {
return isDefined(this.config.resettable) ? this.config.resettable : this.options.resettable;
},
enumerable: true,
configurable: true
});
// @internal
Store.prototype._setState = function (newState, _dispatchAction) {
var _this = this;
if (_dispatchAction === void 0) { _dispatchAction = true; }
if (isFunction(newState)) {
var _newState = newState(this._value());
this.storeValue = this.deepFreeze(_newState) ;
}
else {
this.storeValue = newState;
}
if (!this.store) {
this.store = new BehaviorSubject({ state: this.storeValue });
{
this.store.subscribe(function (_a) {
var action = _a.action;
if (action) {
dispatchUpdate(_this.storeName, action);
}
});
}
return;
}
if (isTransactionInProcess()) {
this.handleTransaction();
return;
}
this.dispatch(this.storeValue, _dispatchAction);
};
/**
*
* Reset the current store back to the initial value
*
* @example
*
* store.reset()
*
*/
Store.prototype.reset = function () {
var _this = this;
if (this.isResettable()) {
setAction('Reset');
this._setState(function () { return Object.assign({}, _this._initialState); });
this.setHasCache(false);
}
else {
console.warn("You need to enable the reset functionality");
}
};
Store.prototype.update = function (stateOrCallback) {
setAction('Update');
var newState;
var currentState = this._value();
if (isFunction(stateOrCallback)) {
newState = isFunction(this._producerFn) ? this._producerFn(currentState, stateOrCallback) : stateOrCallback(currentState);
}
else {
newState = stateOrCallback;
}
var withHook = this.akitaPreUpdate(currentState, __assign({}, currentState, newState));
var resolved = isPlainObject$1(currentState) ? withHook : new currentState.constructor(withHook);
this._setState(resolved);
};
Store.prototype.updateStoreConfig = function (newOptions) {
this.options = __assign({}, this.options, newOptions);
};
// @internal
Store.prototype.akitaPreUpdate = function (_, nextState) {
return nextState;
};
Store.prototype.ngOnDestroy = function () {
this.destroy();
};
/**
*
* Destroy the store
*
* @example
*
* store.destroy()
*
*/
Store.prototype.destroy = function () {
var hmrEnabled = isBrowser ? window.hmrEnabled : false;
if (!hmrEnabled && this === __stores__[this.storeName]) {
delete __stores__[this.storeName];
dispatchDeleted(this.storeName);
this.setHasCache(false);
this.cache.active.complete();
this.store.complete();
}
};
Store.prototype.onInit = function (initialState) {
__stores__[this.storeName] = this;
this._setState(function () { return initialState; });
dispatchAdded(this.storeName);
if (this.isResettable()) {
this._initialState = initialState;
}
assertStoreHasName(this.storeName, this.constructor.name);
};
Store.prototype.dispatch = function (state, _dispatchAction) {
if (_dispatchAction === void 0) { _dispatchAction = true; }
var action = undefined;
if (_dispatchAction) {
action = currentAction;
resetCustomAction();
}
this.store.next({ state: state, action: action });
};
Store.prototype.watchTransaction = function () {
var _this = this;
commit().subscribe(function () {
_this.inTransaction = false;
_this.dispatch(_this._value());
});
};
Store.prototype.isResettable = function () {
if (this.resettable === false) {
return false;
}
return this.resettable || getAkitaConfig().resettable;
};
Store.prototype.handleTransaction = function () {
if (!this.inTransaction) {
this.watchTransaction();
this.inTransaction = true;
}
};
Store.prototype.getCacheTTL = function () {
return (this.cacheConfig && this.cacheConfig.ttl) || getAkitaConfig().ttl;
};
return Store;
}());
// @internal
function updateEntities(_a) {
var state = _a.state, ids = _a.ids, idKey = _a.idKey, newStateOrFn = _a.newStateOrFn, preUpdateEntity = _a.preUpdateEntity, producerFn = _a.producerFn, onEntityIdChanges = _a.onEntityIdChanges;
var e_1, _b;
var updatedEntities = {};
var isUpdatingIdKey = false;
var idToUpdate;
try {
for (var ids_1 = __values(ids), ids_1_1 = ids_1.next(); !ids_1_1.done; ids_1_1 = ids_1.next()) {
var id = ids_1_1.value;
// if the entity doesn't exist don't do anything
if (hasEntity(state.entities, id) === false) {
continue;
}
var oldEntity = state.entities[id];
var newState = void 0;
if (isFunction(newStateOrFn)) {
newState = isFunction(producerFn) ? producerFn(oldEntity, newStateOrFn) : newStateOrFn(oldEntity);
}
else {
newState = newStateOrFn;
}
var isIdChanged = newState.hasOwnProperty(idKey) && newState[idKey] !== oldEntity[idKey];
var newEntity = void 0;
idToUpdate = id;
if (isIdChanged) {
isUpdatingIdKey = true;
idToUpdate = newState[idKey];
}
var merged = __assign({}, oldEntity, newState);
if (isPlainObject$1(oldEntity)) {
newEntity = merged;
}
else {
/**
* In case that new state is class of it's own, there's
* a possibility that it will be different than the old
* class.
* For example, Old state is an instance of animal class
* and new state is instance of person class.
* To avoid run over new person class with the old animal
* class we check if the new state is a class of it's own.
* If so, use it. Otherwise, use the old state class
*/
if (isPlainObject$1(newState)) {
newEntity = new oldEntity.constructor(merged);
}
else {
newEntity = new newState.constructor(merged);
}
}
updatedEntities[idToUpdate] = preUpdateEntity(oldEntity, newEntity);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (ids_1_1 && !ids_1_1.done && (_b = ids_1.return)) _b.call(ids_1);
}
finally { if (e_1) throw e_1.error; }
}
var updatedIds = state.ids;
var stateEntities = state.entities;
if (isUpdatingIdKey) {
var _c = __read(ids, 1), id_1 = _c[0];
var _d = state.entities, _e = id_1, rest = __rest(_d, [typeof _e === "symbol" ? _e : _e + ""]);
stateEntities = rest;
updatedIds = state.ids.map(function (current) { return (current === id_1 ? idToUpdate : current); });
onEntityIdChanges(id_1, idToUpdate);
}
return __assign({}, state, { entities: __assign({}, stateEntities, updatedEntities), ids: updatedIds });
}
/**
*
* Store for managing a collection of entities
*
* @example
*
* export interface WidgetsState extends EntityState { }
*
* @StoreConfig({ name: 'widgets' })
* export class WidgetsStore extends EntityStore {
* constructor() {
* super();
* }
* }
*
*
*/
var EntityStore = /** @class */ (function (_super) {
__extends(EntityStore, _super);
function EntityStore(initialState, options) {
if (initialState === void 0) { initialState = {}; }
if (options === void 0) { options = {}; }
var _this = _super.call(this, __assign({}, getInitialEntitiesState(), initialState), options) || this;
_this.options = options;
_this.entityActions = new Subject();
_this.entityIdChanges = new Subject();
return _this;
}
Object.defineProperty(EntityStore.prototype, "selectEntityAction$", {
// @internal
get: function () {
return this.entityActions.asObservable();
},
enumerable: true,
configurable: true
});
Object.defineProperty(EntityStore.prototype, "selectEntityIdChanges$", {
// @internal
get: function () {
return this.entityIdChanges.asObservable();
},
enumerable: true,
configurable: true
});
Object.defineProperty(EntityStore.prototype, "idKey", {
// @internal
get: function () {
return this.config.idKey || this.options.idKey || DEFAULT_ID_KEY;
},
enumerable: true,
configurable: true
});
/**
*
* Replace current collection with provided collection
*
* @example
*
* this.store.set([Entity, Entity])
* this.store.set({ids: [], entities: {}})
* this.store.set({ 1: {}, 2: {}})
*
*/
EntityStore.prototype.set = function (entities, options) {
var _this = this;
if (options === void 0) { options = {}; }
if (isNil(entities))
return;
setAction('Set Entity');
var isNativePreAdd = this.akitaPreAddEntity === EntityStore.prototype.akitaPreAddEntity;
this.setHasCache(true, { restartTTL: true });
this._setState(function (state) {
var newState = setEntities({
state: state,
entities: entities,
idKey: _this.idKey,
preAddEntity: _this.akitaPreAddEntity,
isNativePreAdd: isNativePreAdd,
});
if (isUndefined(options.activeId) === false) {
newState.active = options.activeId;
}
return newState;
});
if (this.hasInitialUIState()) {
this.handleUICreation();
}
this.entityActions.next({ type: EntityActions.Set, ids: this.ids });
};
/**
* Add entities
*
* @example
*
* this.store.add([Entity, Entity])
* this.store.add(Entity)
* this.store.add(Entity, { prepend: true })
*
* this.store.add(Entity, { loading: false })
*/
EntityStore.prototype.add = function (entities, options) {
if (options === void 0) { options = { loading: false }; }
var collection = coerceArray(entities);
if (isEmpty(collection))
return;
var data = addEntities({
state: this._value(),
preAddEntity: this.akitaPreAddEntity,
entities: collection,
idKey: this.idKey,
options: options,
});
if (data) {
setAction('Add Entity');
data.newState.loading = options.loading;
this._setState(function () { return data.newState; });
if (this.hasInitialUIState()) {
this.handleUICreation(true);
}
this.entityActions.next({ type: EntityActions.Add, ids: data.newIds });
}
};
EntityStore.prototype.update = function (idsOrFnOrState, newStateOrFn) {
var _this = this;
if (isUndefined(newStateOrFn)) {
_super.prototype.update.call(this, idsOrFnOrState);
return;
}
var ids = [];
if (isFunction(idsOrFnOrState)) {
// We need to filter according the predicate function
ids = this.ids.filter(function (id) { return idsOrFnOrState(_this.entities[id]); });
}
else {
// If it's nil we want all of them
ids = isNil(idsOrFnOrState) ? this.ids : coerceArray(idsOrFnOrState);
}
if (isEmpty(ids))
return;
setAction('Update Entity', ids);
var entityIdChanged;
this._setState(function (state) {
return updateEntities({
idKey: _this.idKey,
ids: ids,
preUpdateEntity: _this.akitaPreUpdateEntity,
state: state,
newStateOrFn: newStateOrFn,
producerFn: _this._producerFn,
onEntityIdChanges: function (oldId, newId) {
entityIdChanged = { oldId: oldId, newId: newId };
_this.entityIdChanges.next(__assign({}, entityIdChanged, { pending: true }));
},
});
});
if (entityIdChanged) {
this.entityIdChanges.next(__assign({}, entityIdChanged, { pending: false }));
}
this.entityActions.next({ type: EntityActions.Update, ids: ids });
};
EntityStore.prototype.upsert = function (ids, newState, onCreate, options) {
var _this = this;
if (options === void 0) { options = {}; }
var toArray = coerceArray(ids);
var predicate = function (isUpdate) { return function (id) { return hasEntity(_this.entities, id) === isUpdate; }; };
var baseClass = isFunction(onCreate) ? options.baseClass : onCreate ? onCreate.baseClass : undefined;
var isClassBased = isFunction(baseClass);
var updateIds = toArray.filter(predicate(true));
var newEntities = toArray.filter(predicate(false)).map(function (id) {
var _a;
var newStateObj = typeof newState === 'function' ? newState({}) : newState;
var entity = isFunction(onCreate) ? onCreate(id, newStateObj) : newStateObj;
var withId = __assign({}, entity, (_a = {}, _a[_this.idKey] = id, _a));
if (isClassBased) {
return new baseClass(withId);
}
return withId;
});
// it can be any of the three types
this.update(updateIds, newState);
this.add(newEntities);
logAction('Upsert Entity');
};
/**
*
* Upsert entity collection (idKey must be present)
*
* @example
*
* store.upsertMany([ { id: 1 }, { id: 2 }]);
*
* store.upsertMany([ { id: 1 }, { id: 2 }], { loading: true });
* store.upsertMany([ { id: 1 }, { id: 2 }], { baseClass: Todo });
*
*/
EntityStore.prototype.upsertMany = function (entities, options) {
if (options === void 0) { options = {}; }
var e_1, _a;
var addedIds = [];
var updatedIds = [];
var updatedEntities = {};
try {
// Update the state directly to optimize performance
for (var entities_1 = __values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) {
var entity = entities_1_1.value;
var withPreCheckHook = this.akitaPreCheckEntity(entity);
var id = withPreCheckHook[this.idKey];
if (hasEntity(this.entities, id)) {
var prev = this._value().entities[id];
var merged = __assign({}, this._value().entities[id], withPreCheckHook);
var next = options.baseClass ? new options.baseClass(merged) : merged;
var withHook = this.akitaPreUpdateEntity(prev, next);
var nextId = withHook[this.idKey];
updatedEntities[nextId] = withHook;
updatedIds.push(nextId);
}
else {
var newEntity = options.baseClass ? new options.baseClass(withPreCheckHook) : withPreCheckHook;
var withHook = this.akitaPreAddEntity(newEntity);
var nextId = withHook[this.idKey];
addedIds.push(nextId);
updatedEntities[nextId] = withHook;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1);
}
finally { if (e_1) throw e_1.error; }
}
logAction('Upsert Many');
this._setState(function (state) { return (__assign({}, state, { ids: addedIds.length ? __spread(state.ids, addedIds) : state.ids, entities: __assign({}, state.entities, updatedEntities), loading: !!options.loading })); });
updatedIds.length && this.entityActions.next({ type: EntityActions.Update, ids: updatedIds });
addedIds.length && this.entityActions.next({ type: EntityActions.Add, ids: addedIds });
if (addedIds.length && this.hasUIStore()) {
this.handleUICreation(true);
}
};
/**
*
* Replace one or more entities (except the id property)
*
*
* @example
*
* this.store.replace(5, newEntity)
* this.store.replace([1,2,3], newEntity)
*/
EntityStore.prototype.replace = function (ids, newState) {
var e_2, _a;
var toArray = coerceArray(ids);
if (isEmpty(toArray))
return;
var replaced = {};
try {
for (var toArray_1 = __values(toArray), toArray_1_1 = toArray_1.next(); !toArray_1_1.done; toArray_1_1 = toArray_1.next()) {
var id = toArray_1_1.value;
newState[this.idKey] = id;
replaced[id] = newState;
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (toArray_1_1 && !toArray_1_1.done && (_a = toArray_1.return)) _a.call(toArray_1);
}
finally { if (e_2) throw e_2.error; }
}
setAction('Replace Entity', ids);
this._setState(function (state) { return (__assign({}, state, { entities: __assign({}, state.entities, replaced) })); });
};
/**
*
* Move entity inside the collection
*
*
* @example
*
* this.store.move(fromIndex, toIndex)
*/
EntityStore.prototype.move = function (from, to) {
var ids = this.ids.slice();
ids.splice(to < 0 ? ids.length + to : to, 0, ids.splice(from, 1)[0]);
setAction('Move Entity');
this._setState(function (state) { return (__assign({}, state, {
// Change the entities reference so that selectAll emit
entities: __assign({}, state.entities), ids: ids })); });
};
EntityStore.prototype.remove = function (idsOrFn) {
var _this = this;
if (isEmpty(this.ids))
return;
var idPassed = isDefined(idsOrFn);
// null means remove all
var ids = [];
if (isFunction(idsOrFn)) {
ids = this.ids.filter(function (entityId) { return idsOrFn(_this.entities[entityId]); });
}
else {
ids = idPassed ? coerceArray(idsOrFn) : this.ids;
}
if (isEmpty(ids))
return;
setAction('Remove Entity', ids);
this._setState(function (state) { return removeEntities({ state: state, ids: ids }); });
if (!idPassed) {
this.setHasCache(false);
}
this.handleUIRemove(ids);
this.entityActions.next({ type: EntityActions.Remove, ids: ids });
};
/**
*
* Update the active entity
*
* @example
*
* this.store.updateActive({ completed: true })
* this.store.updateActive(active => {
* return {
* config: {
* ..active.config,
* date
* }
* }
* })
*/
EntityStore.prototype.updateActive = function (newStateOrCallback) {
var ids = coerceArray(this.active);
setAction('Update Active', ids);
this.update(ids, newStateOrCallback);
};
EntityStore.prototype.setActive = function (idOrOptions) {
var active = getActiveEntities(idOrOptions, this.ids, this.active);
if (active === undefined) {
return;
}
setAction('Set Active', active);
this._setActive(active);
};
/**
* Add active entities
*
* @example
*
* store.addActive(2);
* store.addActive([3, 4, 5]);
*/
EntityStore.prototype.addActive = function (ids) {
var _this = this;
var toArray = coerceArray(ids);
if (isEmpty(toArray))
return;
var everyExist = toArray.every(function (id) { return _this.active.indexOf(id) > -1; });
if (everyExist)
return;
setAction('Add Active', ids);
this._setState(function (state) {
/** Protect against case that one of the items in the array exist */
var uniques = Array.from(new Set(__spread(state.active, toArray)));
return __assign({}, state, { active: uniques });
});
};
/**
* Remove active entities
*
* @example
*
* store.removeActive(2)
* store.removeActive([3, 4, 5])
*/
EntityStore.prototype.removeActive = function (ids) {
var _this = this;
var toArray = coerceArray(ids);
if (isEmpty(toArray))
return;
var someExist = toArray.some(function (id) { return _this.active.indexOf(id) > -1; });
if (!someExist)
return;
setAction('Remove Active', ids);
this._setState(function (state) {
return __assign({}, state, { active: Array.isArray(state.active) ? state.active.filter(function (currentId) { return toArray.indexOf(currentId) === -1; }) : null });
});
};
/**
* Toggle active entities
*
* @example
*
* store.toggle(2)
* store.toggle([3, 4, 5])
*/
EntityStore.prototype.toggleActive = function (ids) {
var _this = this;
var toArray = coerceArray(ids);
var filterExists = function (remove) { return function (id) { return _this.active.includes(id) === remove; }; };
var remove = toArray.filter(filterExists(true));
var add = toArray.filter(filterExists(false));
this.removeActive(remove);
this.addActive(add);
logAction('Toggle Active');
};
/**
*
* Create sub UI store for managing Entity's UI state
*
* @example
*
* export type ProductUI = {
* isLoading: boolean;
* isOpen: boolean
* }
*
* interface ProductsUIState extends EntityState {}
*
* export class ProductsStore EntityStore {
* ui: EntityUIStore;
*
* constructor() {
* super();
* this.createUIStore();
* }
*
* }
*/
EntityStore.prototype.createUIStore = function (initialState, storeConfig) {
if (initialState === void 0) { initialState = {}; }
if (storeConfig === void 0) { storeConfig = {}; }
var defaults = { name: "UI/" + this.storeName, idKey: this.idKey };
this.ui = new EntityUIStore(initialState, __assign({}, defaults, storeConfig));
return this.ui;
};
// @internal
EntityStore.prototype.destroy = function () {
_super.prototype.destroy.call(this);
if (this.ui instanceof EntityStore) {
this.ui.destroy();
}
this.entityActions.complete();
};
// @internal
EntityStore.prototype.akitaPreUpdateEntity = function (_, nextEntity) {
return nextEntity;
};
// @internal
EntityStore.prototype.akitaPreAddEntity = function (newEntity) {
return newEntity;
};
// @internal
EntityStore.prototype.akitaPreCheckEntity = function (newEntity) {
return newEntity;
};
Object.defineProperty(EntityStore.prototype, "ids", {
get: function () {
return this._value().ids;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EntityStore.prototype, "entities", {
get: function () {
return this._value().entities;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EntityStore.prototype, "active", {
get: function () {
return this._value().active;
},
enumerable: true,
configurable: true
});
EntityStore.prototype._setActive = function (ids) {
this._setState(function (state) {
return __assign({}, state, { active: ids });
});
};
EntityStore.prototype.handleUICreation = function (add) {
var _this = this;
if (add === void 0) { add = false; }
var ids = this.ids;
var isFunc = isFunction(this.ui._akitaCreateEntityFn);
var uiEntities;
var createFn = function (id) {
var _a;
var current = _this.entities[id];
var ui = isFunc ? _this.ui._akitaCreateEntityFn(current) : _this.ui._akitaCreateEntityFn;
return __assign((_a = {}, _a[_this.idKey] = current[_this.idKey], _a), ui);
};
if (add) {
uiEntities = this.ids.filter(function (id) { return isUndefined(_this.ui.entities[id]); }).map(createFn);
}
else {
uiEntities = ids.map(createFn);
}
add ? this.ui.add(uiEntities) : this.ui.set(uiEntities);
};
EntityStore.prototype.hasInitialUIState = function () {
return this.hasUIStore() && isUndefined(this.ui._akitaCreateEntityFn) === false;
};
EntityStore.prototype.handleUIRemove = function (ids) {
if (this.hasUIStore()) {
this.ui.remove(ids);
}
};
EntityStore.prototype.hasUIStore = function () {
return this.ui instanceof EntityUIStore;
};
var _b;
__decorate$2([
transaction(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Object, Object, Object]),
__metadata("design:returntype", void 0)
], EntityStore.prototype, "upsert", null);
__decorate$2([
transaction(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [typeof (_b = typeof T !== "undefined" && T) === "function" ? _b : Object]),
__metadata("design:returntype", void 0)
], EntityStore.prototype, "toggleActive", null);
return EntityStore;
}(Store));
// @internal
var EntityUIStore = /** @class */ (function (_super) {
__extends(EntityUIStore, _super);
function EntityUIStore(initialState, storeConfig) {
if (initialState === void 0) { initialState = {}; }
if (storeConfig === void 0) { storeConfig = {}; }
return _super.call(this, initialState, storeConfig) || this;
}
/**
*
* Set the initial UI entity state. This function will determine the entity's
* initial state when we call `set()` or `add()`.
*
* @example
*
* constructor() {
* super();
* this.createUIStore().setInitialEntityState(entity => ({ isLoading: false, isOpen: true }));
* this.createUIStore().setInitialEntityState({ isLoading: false, isOpen: true });
* }
*
*/
EntityUIStore.prototype.setInitialEntityState = function (createFn) {
this._akitaCreateEntityFn = createFn;
};
return EntityUIStore;
}(EntityStore));
// @internal
function distinctUntilArrayItemChanged() {
return distinctUntilChanged(function (prevCollection, currentCollection) {
if (prevCollection === currentCollection) {
return true;
}
if (isArray(prevCollection) === false || isArray(currentCollection) === false) {
return false;
}
if (isEmpty(prevCollection) && isEmpty(currentCollection)) {
return true;
}
// if item is new in the current collection but not exist in the prev collection
var hasNewItem = hasChange(currentCollection, prevCollection);
if (hasNewItem) {
return false;
}
var isOneOfItemReferenceChanged = hasChange(prevCollection, currentCollection);
// return false means there is a change and we want to call next()
return isOneOfItemReferenceChanged === false;
});
}
// @internal
function hasChange(first, second) {
var hasChange = second.some(function (currentItem) {
var oldItem = first.find(function (prevItem) { return prevItem === currentItem; });
return oldItem === undefined;
});
return hasChange;
}
var Order;
(function (Order) {
Order["ASC"] = "asc";
Order["DESC"] = "desc";
})(Order || (Order = {}));
// @internal
function compareValues(key, order) {
if (order === void 0) { order = Order.ASC; }
return function (a, b) {
if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
return 0;
}
var varA = typeof a[key] === 'string' ? a[key].toUpperCase() : a[key];
var varB = typeof b[key] === 'string' ? b[key].toUpperCase() : b[key];
var comparison = 0;
if (varA > varB) {
comparison = 1;
}
else if (varA < varB) {
comparison = -1;
}
return order == Order.DESC ? comparison * -1 : comparison;
};
}
// @internal
function entitiesToArray(state, options) {
var arr = [];
var ids = state.ids, entities = state.entities;
var filterBy = options.filterBy, limitTo = options.limitTo, sortBy = options.sortBy, sortByOrder = options.sortByOrder;
var _loop_1 = function (i) {
var entity = entities[ids[i]];
if (!filterBy) {
arr.push(entity);
return "continue";
}
var toArray = coerceArray(filterBy);
var allPass = toArray.every(function (fn) { return fn(entity, i); });
if (allPass) {
arr.push(entity);
}
};
for (var i = 0; i < ids.length; i++) {
_loop_1(i);
}
if (sortBy) {
var _sortBy_1 = isFunction(sortBy) ? sortBy : compareValues(sortBy, sortByOrder);
arr = arr.sort(function (a, b) { return _sortBy_1(a, b, state); });
}
var length = Math.min(limitTo || arr.length, arr.length);
return length === arr.length ? arr : arr.slice(0, length);
}
// @internal
function entitiesToMap(state, options) {
var map = {};
var filterBy = options.filterBy, limitTo = options.limitTo;
var ids = state.ids, entities = state.entities;
if (!filterBy && !limitTo) {
return entities;
}
var hasLimit = isNil(limitTo) === false;
if (filterBy && hasLimit) {
var count = 0;
var _loop_1 = function (i, length_1) {
if (count === limitTo)
return "break";
var id = ids[i];
var entity = entities[id];
var allPass = coerceArray(filterBy).every(function (fn) { return fn(entity, i); });
if (allPass) {
map[id] = entity;
count++;
}
};
for (var i = 0, length_1 = ids.length; i < length_1; i++) {
var state_1 = _loop_1(i, length_1);
if (state_1 === "break")
break;
}
}
else {
var finalLength = Math.min(limitTo || ids.length, ids.length);
var _loop_2 = function (i) {
var id = ids[i];
var entity = entities[id];
if (!filterBy) {
map[id] = entity;
return "continue";
}
var allPass = coerceArray(filterBy).every(function (fn) { return fn(entity, i); });
if (allPass) {
map[id] = entity;
}
};
for (var i = 0; i < finalLength; i++) {
_loop_2(i);
}
}
return map;
}
// @internal
function isString(value) {
return typeof value === 'string';
}
// @internal
function findEntityByPredicate(predicate, entities) {
var e_1, _a;
try {
for (var _b = __values(Object.keys(entities)), _c = _b.next(); !_c.done; _c = _b.next()) {
var entityId = _c.value;
if (predicate(entities[entityId]) === true) {
return entityId;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return undefined;
}
// @internal
function getEntity(id, project) {
return function (entities) {
var entity = entities[id];
if (isUndefined(entity)) {
return undefined;
}
if (!project) {
return entity;
}
if (isString(project)) {
return entity[project];
}
return project(entity);
};
}
// @internal
function mapSkipUndefined(arr, callbackFn) {
return arr.reduce(function (result, value, index, array) {
var val = callbackFn(value, index, array);
if (val !== undefined) {
result.push(val);
}
return result;
}, []);
}
var queryConfigKey = 'akitaQueryConfig';
function compareKeys(keysOrFuncs) {
return function (prevState, currState) {
var isFns = isFunction(keysOrFuncs[0]);
// Return when they are NOT changed
return keysOrFuncs.some(function (keyOrFunc) {
if (isFns) {
return keyOrFunc(prevState) !== keyOrFunc(currState);
}
return prevState[keyOrFunc] !== currState[keyOrFunc];
}) === false;
};
}
var Query = /** @class */ (function () {
function Query(store) {
this.store = store;
this.__store__ = store;
{
// @internal
__queries__[store.storeName] = this;
}
}
Query.prototype.select = function (project) {
var mapFn;
if (isFunction(project)) {
mapFn = project;
}
else if (isString(project)) {
mapFn = function (state) { return state[project]; };
}
else if (Array.isArray(project)) {
return this.store
._select(function (state) { return state; })
.pipe(distinctUntilChanged(compareKeys(project)), map(function (state) {
if (isFunction(project[0])) {
return project.map(function (func) { return func(state); });
}
return project.reduce(function (acc, k) {
acc[k] = state[k];
return acc;
}, {});
}));
}
else {
mapFn = function (state) { return state; };
}
return this.store._select(mapFn);
};
/**
* Select the loading state
*
* @example
*
* this.query.selectLoading().subscribe(isLoading => {})
*/
Query.prototype.selectLoading = function () {
return this.select(function (state) { return state.loading; });
};
/**
* Select the error state
*
* @example
*
* this.query.selectError().subscribe(error => {})
*/
Query.prototype.selectError = function () {
return this.select(function (state) { return state.error; });
};
/**
* Get the store's value
*
* @example
*
* this.query.getValue()
*
*/
Query.prototype.getValue = function () {
return this.store._value();
};
/**
* Select the cache state
*
* @example
*
* this.query.selectHasCache().pipe(
* switchMap(hasCache => {
* return hasCache ? of() : http().pipe(res => store.set(res))
* })
* )
*/
Query.prototype.selectHasCache = function () {
return this.store._cache().asObservable();
};
/**
* Whether we've cached data
*
* @example
*
* this.query.getHasCache()
*
*/
Query.prototype.getHasCache = function () {
return this.store._cache().value;
};
Object.defineProperty(Query.prototype, "config", {
// @internal
get: function () {
return this.constructor[queryConfigKey];
},
enumerable: true,
configurable: true
});
return Query;
}());
// @internal
function sortByOptions(options, config) {
options.sortBy = options.sortBy || (config && config.sortBy);
options.sortByOrder = options.sortByOrder || (config && config.sortByOrder);
}
/**
*
* The Entity Query is similar to the general Query, with additional functionality tailored for EntityStores.
*
* class WidgetsQuery extends QueryEntity {
* constructor(protected store: WidgetsStore) {
* super(store);
* }
* }
*
*
*
*/
var QueryEntity = /** @class */ (function (_super) {
__extends(QueryEntity, _super);
function QueryEntity(store, options) {
if (options === void 0) { options = {}; }
var _this = _super.call(this, store) || this;
_this.options = options;
_this.__store__ = store;
return _this;
}
QueryEntity.prototype.selectAll = function (options) {
var _this = this;
if (options === void 0) { options = {
asObject: false,
}; }
return this.select(function (state) { return state.entities; }).pipe(map(function () { return _this.getAll(options); }));
};
QueryEntity.prototype.getAll = function (options) {
if (options === void 0) { options = { asObject: false, filterBy: undefined, limitTo: undefined }; }
if (options.asObject) {
return entitiesToMap(this.getValue(), options);
}
sortByOptions(options, this.config || this.options);
return entitiesToArray(this.getValue(), options);
};
QueryEntity.prototype.selectMany = function (ids, project) {
if (!ids || !ids.length)
return of([]);
return this.select(function (state) { return state.entities; }).pipe(map(function (entities) { return mapSkipUndefined(ids, function (id) { return getEntity(id, project)(entities); }); }), distinctUntilArrayItemChanged());
};
QueryEntity.prototype.selectEntity = function (idOrPredicate, project) {
var id = idOrPredicate;
if (isFunction(idOrPredicate)) {
// For performance reason we expect the entity to be in the store
id = findEntityByPredicate(idOrPredicate, this.getValue().entities);
}
return this.select(function (state) { return state.entities; }).pipe(map(getEntity(id, project)), distinctUntilChanged());
};
/**
* Get an entity by id
*
* @example
*
* this.query.getEntity(1);
*/
QueryEntity.prototype.getEntity = function (id) {
return this.getValue().entities[id];
};
/**
* Select the active entity's id
*
* @example
*
* this.query.selectActiveId()
*/
QueryEntity.prototype.selectActiveId = function () {
return this.select(function (state) { return state.active; });
};
/**
* Get the active id
*
* @example
*
* this.query.getActiveId()
*/
QueryEntity.prototype.getActiveId = function () {
return this.getValue().active;
};
QueryEntity.prototype.selectActive = function (project) {
var _this = this;
if (isArray(this.getActive())) {
return this.selectActiveId().pipe(switchMap(function (ids) { return _this.selectMany(ids, project); }));
}
return this.selectActiveId().pipe(switchMap(function (ids) { return _this.selectEntity(ids, project); }));
};
QueryEntity.prototype.getActive = function () {
var _this = this;
var activeId = this.getActiveId();
if (isArray(activeId)) {
return activeId.map(function (id) { return _this.getValue().entities[id]; });
}
return toBoolean(activeId) ? this.getEntity(activeId) : undefined;
};
/**
* Select the store's entity collection length
*
* @example
*
* this.query.selectCount()
* this.query.selectCount(entity => entity.completed)
*/
QueryEntity.prototype.selectCount = function (predicate) {
var _this = this;
return this.select(function (state) { return state.entities; }).pipe(map(function () { return _this.getCount(predicate); }));
};
/**
* Get the store's entity collection length
*
* @example
*
* this.query.getCount()
* this.query.getCount(entity => entity.completed)
*/
QueryEntity.prototype.getCount = function (predicate) {
if (isFunction(predicate)) {
return this.getAll().filter(predicate).length;
}
return this.getValue().ids.length;
};
QueryEntity.prototype.selectLast = function (project) {
return this.selectAt(function (ids) { return ids[ids.length - 1]; }, project);
};
QueryEntity.prototype.selectFirst = function (project) {
return this.selectAt(function (ids) { return ids[0]; }, project);
};
QueryEntity.prototype.selectEntityAction = function (actionOrActions) {
if (isNil(actionOrActions)) {
return this.store.selectEntityAction$;
}
var project = isArray(actionOrActions) ? function (action) { return action; } : function (_a) {
var ids = _a.ids;
return ids;
};
var actions = coerceArray(actionOrActions);
return this.store.selectEntityAction$.pipe(filter(function (_a) {
var type = _a.type;
return actions.includes(type);
}), map(function (action) { return project(action); }));
};
QueryEntity.prototype.hasEntity = function (projectOrIds) {
var _this = this;
if (isNil(projectOrIds)) {
return this.getValue().ids.length > 0;
}
if (isFunction(projectOrIds)) {
return this.getAll().some(projectOrIds);
}
if (isArray(projectOrIds)) {
return projectOrIds.every(function (id) { return id in _this.getValue().entities; });
}
return projectOrIds in this.getValue().entities;
};
/**
* Returns whether entity store has an active entity
*
* @example
*
* this.query.hasActive()
* this.query.hasActive(3)
*
*/
QueryEntity.prototype.hasActive = function (id) {
var active = this.getValue().active;
var isIdProvided = isDefined(id);
if (Array.isArray(active)) {
if (isIdProvided) {
return active.includes(id);
}
return active.length > 0;
}
return isIdProvided ? active === id : isDefined(active);
};
/**
*
* Create sub UI query for querying Entity's UI state
*
* @example
*
*
* export class ProductsQuery extends QueryEntity {
* ui: EntityUIQuery;
*
* constructor(protected store: ProductsStore) {
* super(store);
* this.createUIQuery();
* }
*
* }
*/
QueryEntity.prototype.createUIQuery = function () {
this.ui = new EntityUIQuery(this.__store__.ui);
};
QueryEntity.prototype.selectAt = function (mapFn, project) {
var _this = this;
return this.select(function (state) { return state.ids; }).pipe(map(mapFn), distinctUntilChanged(), switchMap(function (id) { return _this.selectEntity(id, project); }));
};
return QueryEntity;
}(Query));
// @internal
var EntityUIQuery = /** @class */ (function (_super) {
__extends(EntityUIQuery, _super);
function EntityUIQuery(store) {
return _super.call(this, store) || this;
}
return EntityUIQuery;
}(QueryEntity));
/**
* @example
*
* query.selectEntity(2).pipe(filterNil)
*/
var filterNil = function (source) { return source.pipe(filter(function (value) { return value !== null && typeof value !== 'undefined'; })); };
/**
* @internal
*
* @example
*
* getValue(state, 'todos.ui')
*
*/
function getValue(obj, prop) {
/** return the whole state */
if (prop.split('.').length === 1) {
return obj;
}
var removeStoreName = prop
.split('.')
.slice(1)
.join('.');
return removeStoreName.split('.').reduce(function (acc, part) { return acc && acc[part]; }, obj);
}
/**
* @internal
*
* @example
* setValue(state, 'todos.ui', { filter: {} })
*/
function setValue(obj, prop, val) {
var split = prop.split('.');
if (split.length === 1) {
return __assign({}, obj, val);
}
obj = __assign({}, obj);
var lastIndex = split.length - 2;
var removeStoreName = prop.split('.').slice(1);
removeStoreName.reduce(function (acc, part, index) {
if (index !== lastIndex) {
acc[part] = __assign({}, acc[part]);
return acc && acc[part];
}
acc[part] = Array.isArray(acc[part]) || !isObject(acc[part]) ? val : __assign({}, acc[part], val);
return acc && acc[part];
}, obj);
return obj;
}
new ReplaySubject(1);
var AkitaPlugin = /** @class */ (function () {
function AkitaPlugin(query, config) {
this.query = query;
}
/** This method is responsible for getting access to the query. */
AkitaPlugin.prototype.getQuery = function () {
return this.query;
};
/** This method is responsible for getting access to the store. */
AkitaPlugin.prototype.getStore = function () {
return this.getQuery().__store__;
};
/** This method is responsible tells whether the plugin is entityBased or not. */
AkitaPlugin.prototype.isEntityBased = function (entityId) {
return toBoolean(entityId);
};
/** This method is responsible for selecting the source; it can be the whole store or one entity. */
AkitaPlugin.prototype.selectSource = function (entityId, property) {
var _this = this;
if (this.isEntityBased(entityId)) {
return this.getQuery().selectEntity(entityId).pipe(filterNil);
}
if (property) {
return this.getQuery().select(function (state) { return getValue(state, _this.withStoreName(property)); });
}
return this.getQuery().select();
};
AkitaPlugin.prototype.getSource = function (entityId, property) {
if (this.isEntityBased(entityId)) {
return this.getQuery().getEntity(entityId);
}
var state = this.getQuery().getValue();
if (property) {
return getValue(state, this.withStoreName(property));
}
return state;
};
AkitaPlugin.prototype.withStoreName = function (prop) {
return this.storeName + "." + prop;
};
Object.defineProperty(AkitaPlugin.prototype, "storeName", {
get: function () {
return this.getStore().storeName;
},
enumerable: true,
configurable: true
});
/** This method is responsible for updating the store or one entity; it can be the whole store or one entity. */
AkitaPlugin.prototype.updateStore = function (newState, entityId, property) {
var _this = this;
if (this.isEntityBased(entityId)) {
this.getStore().update(entityId, newState);
}
else {
if (property) {
this.getStore()._setState(function (state) {
return setValue(state, _this.withStoreName(property), newState);
});
return;
}
this.getStore()._setState(function (state) { return (__assign({}, state, newState)); });
}
};
/**
* Function to invoke upon reset
*/
AkitaPlugin.prototype.onReset = function (fn) {
var _this = this;
var original = this.getStore().reset;
this.getStore().reset = function () {
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
/** It should run after the plugin destroy method */
setTimeout(function () {
original.apply(_this.getStore(), params);
fn();
});
};
};
return AkitaPlugin;
}());
var paginatorDefaults = {
pagesControls: false,
range: false,
startWith: 1,
cacheTimeout: undefined,
clearStoreWithCache: true
};
/** @class */ ((function (_super) {
__extends(PaginatorPlugin, _super);
function PaginatorPlugin(query, config) {
if (config === void 0) { config = {}; }
var _this = _super.call(this, query, {
resetFn: function () {
_this.initial = false;
_this.destroy({ clearCache: true, currentPage: 1 });
}
}) || this;
_this.query = query;
_this.config = config;
/** Save current filters, sorting, etc. in cache */
_this.metadata = new Map();
_this.pages = new Map();
_this.pagination = {
currentPage: 1,
perPage: 0,
total: 0,
lastPage: 0,
data: []
};
/**
* When the user navigates to a different page and return
* we don't want to call `clearCache` on first time.
*/
_this.initial = true;
/**
* Proxy to the query loading
*/
_this.isLoading$ = _this.query.selectLoading().pipe(delay(0));
_this.config = Object.assign(paginatorDefaults, config);
var _a = _this.config, startWith = _a.startWith, cacheTimeout = _a.cacheTimeout;
_this.page = new BehaviorSubject(startWith);
if (isObservable(cacheTimeout)) {
_this.clearCacheSubscription = cacheTimeout.subscribe(function () { return _this.clearCache(); });
}
return _this;
}
Object.defineProperty(PaginatorPlugin.prototype, "pageChanges", {
/**
* Listen to page changes
*/
get: function () {
return this.page.asObservable();
},
enumerable: true,
configurable: true
});
Object.defineProperty(PaginatorPlugin.prototype, "currentPage", {
/**
* Get the current page number
*/
get: function () {
return this.pagination.currentPage;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PaginatorPlugin.prototype, "isFirst", {
/**
* Check if current page is the first one
*/
get: function () {
return this.currentPage === 1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(PaginatorPlugin.prototype, "isLast", {
/**
* Check if current page is the last one
*/
get: function () {
return this.currentPage === this.pagination.lastPage;
},
enumerable: true,
configurable: true
});
/**
* Whether to generate an array of pages for *ngFor
* [1, 2, 3, 4]
*/
PaginatorPlugin.prototype.withControls = function () {
this.config.pagesControls = true;
return this;
};
/**
* Whether to generate the `from` and `to` keys
* [1, 2, 3, 4]
*/
PaginatorPlugin.prototype.withRange = function () {
this.config.range = true;
return this;
};
/**
* Set the loading state
*/
PaginatorPlugin.prototype.setLoading = function (value) {
if (value === void 0) { value = true; }
this.getStore().setLoading(value);
};
/**
* Update the pagination object and add the page
*/
PaginatorPlugin.prototype.update = function (response) {
this.pagination = response;
this.addPage(response.data);
};
/**
*
* Set the ids and add the page to store
*/
PaginatorPlugin.prototype.addPage = function (data) {
var _this = this;
this.pages.set(this.currentPage, { ids: data.map(function (entity) { return entity[_this.getStore().idKey]; }) });
this.getStore().upsertMany(data);
};
/**
* Clear the cache.
*/
PaginatorPlugin.prototype.clearCache = function (options) {
if (options === void 0) { options = {}; }
if (!this.initial) {
logAction('@Pagination - Clear Cache');
if (options.clearStore !== false && (this.config.clearStoreWithCache || options.clearStore)) {
this.getStore().remove();
}
this.pages = new Map();
this.metadata = new Map();
}
this.initial = false;
};
PaginatorPlugin.prototype.clearPage = function (page) {
this.pages.delete(page);
};
/**
* Clear the cache timeout and optionally the pages
*/
PaginatorPlugin.prototype.destroy = function (_a) {
var _b = _a === void 0 ? {} : _a, clearCache = _b.clearCache, currentPage = _b.currentPage;
if (this.clearCacheSubscription) {
this.clearCacheSubscription.unsubscribe();
}
if (clearCache) {
this.clearCache();
}
if (!isUndefined(currentPage)) {
this.setPage(currentPage);
}
this.initial = true;
};
/**
* Whether the provided page is active
*/
PaginatorPlugin.prototype.isPageActive = function (page) {
return this.currentPage === page;
};
/**
* Set the current page
*/
PaginatorPlugin.prototype.setPage = function (page) {
if (page !== this.currentPage || !this.hasPage(page)) {
this.page.next((this.pagination.currentPage = page));
}
};
/**
* Increment current page
*/
PaginatorPlugin.prototype.nextPage = function () {
if (this.currentPage !== this.pagination.lastPage) {
this.setPage(this.pagination.currentPage + 1);
}
};
/**
* Decrement current page
*/
PaginatorPlugin.prototype.prevPage = function () {
if (this.pagination.currentPage > 1) {
this.setPage(this.pagination.currentPage - 1);
}
};
/**
* Set current page to last
*/
PaginatorPlugin.prototype.setLastPage = function () {
this.setPage(this.pagination.lastPage);
};
/**
* Set current page to first
*/
PaginatorPlugin.prototype.setFirstPage = function () {
this.setPage(1);
};
/**
* Check if page exists in cache
*/
PaginatorPlugin.prototype.hasPage = function (page) {
return this.pages.has(page);
};
/**
* Get the current page if it's in cache, otherwise invoke the request
*/
PaginatorPlugin.prototype.getPage = function (req) {
var _this = this;
var page = this.pagination.currentPage;
if (this.hasPage(page)) {
return this.selectPage(page);
}
else {
this.setLoading(true);
return from(req()).pipe(switchMap(function (config) {
page = config.currentPage;
applyTransaction(function () {
_this.setLoading(false);
_this.update(config);
});
return _this.selectPage(page);
}));
}
};
PaginatorPlugin.prototype.getQuery = function () {
return this.query;
};
PaginatorPlugin.prototype.refreshCurrentPage = function () {
if (isNil(this.currentPage) === false) {
this.clearPage(this.currentPage);
this.setPage(this.currentPage);
}
};
PaginatorPlugin.prototype.getFrom = function () {
if (this.isFirst) {
return 1;
}
return (this.currentPage - 1) * this.pagination.perPage + 1;
};
PaginatorPlugin.prototype.getTo = function () {
if (this.isLast) {
return this.pagination.total;
}
return this.currentPage * this.pagination.perPage;
};
/**
* Select the page
*/
PaginatorPlugin.prototype.selectPage = function (page) {
var _this = this;
return this.query.selectAll({ asObject: true }).pipe(take(1), map(function (entities) {
var response = __assign({}, _this.pagination, { data: _this.pages.get(page).ids.map(function (id) { return entities[id]; }) });
var _a = _this.config, range = _a.range, pagesControls = _a.pagesControls;
/** If no total - calc it */
if (isNaN(_this.pagination.total)) {
if (response.lastPage === 1) {
response.total = response.data ? response.data.length : 0;
}
else {
response.total = response.perPage * response.lastPage;
}
_this.pagination.total = response.total;
}
if (range) {
response.from = _this.getFrom();
response.to = _this.getTo();
}
if (pagesControls) {
response.pageControls = generatePages(_this.pagination.total, _this.pagination.perPage);
}
return response;
}));
};
__decorate$2([
action('@Pagination - New Page'),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], PaginatorPlugin.prototype, "update", null);
return PaginatorPlugin;
})(AkitaPlugin));
/**
* Generate an array so we can ngFor them to navigate between pages
*/
function generatePages(total, perPage) {
var len = Math.ceil(total / perPage);
var arr = [];
for (var i = 0; i < len; i++) {
arr.push(i + 1);
}
return arr;
}
/** @class */ ((function (_super) {
__extends(PersistNgFormPlugin, _super);
function PersistNgFormPlugin(query, factoryFnOrPath, params) {
if (params === void 0) { params = {}; }
var _this = _super.call(this, query) || this;
_this.query = query;
_this.factoryFnOrPath = factoryFnOrPath;
_this.params = params;
_this.params = __assign({ debounceTime: 300, formKey: 'akitaForm', emitEvent: false, arrControlFactory: function (v) { return _this.builder.control(v); } }, params);
_this.isRootKeys = toBoolean(factoryFnOrPath) === false;
_this.isKeyBased = isString(factoryFnOrPath) || _this.isRootKeys;
return _this;
}
PersistNgFormPlugin.prototype.setForm = function (form, builder) {
this.form = form;
this.builder = builder;
this.activate();
return this;
};
PersistNgFormPlugin.prototype.reset = function (initialState) {
var _this = this;
var _a;
var value;
if (initialState) {
value = initialState;
}
else {
value = this.isKeyBased ? this.initialValue : this.factoryFnOrPath();
}
if (this.isKeyBased) {
Object.keys(this.initialValue).forEach(function (stateKey) {
var value = _this.initialValue[stateKey];
if (Array.isArray(value) && _this.builder) {
var formArray = _this.form.controls[stateKey];
_this.cleanArray(formArray);
value.forEach(function (v, i) {
_this.form.get(stateKey).insert(i, _this.params.arrControlFactory(v));
});
}
});
}
this.form.patchValue(value, { emitEvent: this.params.emitEvent });
var storeValue = this.isKeyBased ? setValue(this.getQuery().getValue(), this.getStore().storeName + "." + this.factoryFnOrPath, value) : (_a = {}, _a[this.params.formKey] = value, _a);
this.updateStore(storeValue);
};
PersistNgFormPlugin.prototype.cleanArray = function (control) {
while (control.length !== 0) {
control.removeAt(0);
}
};
PersistNgFormPlugin.prototype.resolveInitialValue = function (formValue, root) {
var _this = this;
if (!formValue)
return;
return Object.keys(formValue).reduce(function (acc, stateKey) {
var value = root[stateKey];
if (Array.isArray(value) && _this.builder) {
var factory_1 = _this.params.arrControlFactory;
_this.cleanArray(_this.form.get(stateKey));
value.forEach(function (v, i) {
_this.form.get(stateKey).insert(i, factory_1(v));
});
}
acc[stateKey] = root[stateKey];
return acc;
}, {});
};
PersistNgFormPlugin.prototype.activate = function () {
var _this = this;
var _a;
var path;
if (this.isKeyBased) {
if (this.isRootKeys) {
this.initialValue = this.resolveInitialValue(this.form.value, this.getQuery().getValue());
this.form.patchValue(this.initialValue, { emitEvent: this.params.emitEvent });
}
else {
path = this.getStore().storeName + "." + this.factoryFnOrPath;
var root = getValue(this.getQuery().getValue(), path);
this.initialValue = this.resolveInitialValue(root, root);
this.form.patchValue(this.initialValue, { emitEvent: this.params.emitEvent });
}
}
else {
if (!this.getQuery().getValue()[this.params.formKey]) {
logAction('@PersistNgFormPlugin activate');
this.updateStore((_a = {}, _a[this.params.formKey] = this.factoryFnOrPath(), _a));
}
var value = this.getQuery().getValue()[this.params.formKey];
this.form.patchValue(value);
}
this.formChanges = this.form.valueChanges.pipe(debounceTime(this.params.debounceTime)).subscribe(function (value) {
logAction('@PersistForm - Update');
var newState;
if (_this.isKeyBased) {
if (_this.isRootKeys) {
newState = function (state) { return (__assign({}, state, value)); };
}
else {
newState = function (state) { return setValue(state, path, value); };
}
}
else {
newState = function () {
var _a;
return (_a = {}, _a[_this.params.formKey] = value, _a);
};
}
_this.updateStore(newState(_this.getQuery().getValue()));
});
};
PersistNgFormPlugin.prototype.destroy = function () {
this.formChanges && this.formChanges.unsubscribe();
this.form = null;
this.builder = null;
};
return PersistNgFormPlugin;
})(AkitaPlugin));
/**
* Each plugin that wants to add support for entities should extend this interface.
*/
var EntityCollectionPlugin = /** @class */ (function () {
function EntityCollectionPlugin(query, entityIds) {
this.query = query;
this.entityIds = entityIds;
this.entities = new Map();
}
/**
* Get the entity plugin instance.
*/
EntityCollectionPlugin.prototype.getEntity = function (id) {
return this.entities.get(id);
};
/**
* Whether the entity plugin exist.
*/
EntityCollectionPlugin.prototype.hasEntity = function (id) {
return this.entities.has(id);
};
/**
* Remove the entity plugin instance.
*/
EntityCollectionPlugin.prototype.removeEntity = function (id) {
this.destroy(id);
return this.entities.delete(id);
};
/**
* Set the entity plugin instance.
*/
EntityCollectionPlugin.prototype.createEntity = function (id, plugin) {
return this.entities.set(id, plugin);
};
/**
* If the user passes `entityIds` we take them; otherwise, we take all.
*/
EntityCollectionPlugin.prototype.getIds = function () {
return isUndefined(this.entityIds) ? this.query.getValue().ids : coerceArray(this.entityIds);
};
/**
* When you call one of the plugin methods, you can pass id/ids or undefined which means all.
*/
EntityCollectionPlugin.prototype.resolvedIds = function (ids) {
return isUndefined(ids) ? this.getIds() : coerceArray(ids);
};
/**
* Call this method when you want to activate the plugin on init or when you need to listen to add/remove of entities dynamically.
*
* For example in your plugin you may do the following:
*
* this.query.select(state => state.ids).pipe(skip(1)).subscribe(ids => this.activate(ids));
*/
EntityCollectionPlugin.prototype.rebase = function (ids, actions) {
var _this = this;
if (actions === void 0) { actions = {}; }
/**
*
* If the user passes `entityIds` & we have new ids check if we need to add/remove instances.
*
* This phase will be called only upon update.
*/
if (toBoolean(ids)) {
/**
* Which means all
*/
if (isUndefined(this.entityIds)) {
for (var i = 0, len = ids.length; i < len; i++) {
var entityId = ids[i];
if (this.hasEntity(entityId) === false) {
isFunction(actions.beforeAdd) && actions.beforeAdd(entityId);
var plugin = this.instantiatePlugin(entityId);
this.entities.set(entityId, plugin);
isFunction(actions.afterAdd) && actions.afterAdd(plugin);
}
}
this.entities.forEach(function (plugin, entityId) {
if (ids.indexOf(entityId) === -1) {
isFunction(actions.beforeRemove) && actions.beforeRemove(plugin);
_this.removeEntity(entityId);
}
});
}
else {
/**
* Which means the user passes specific ids
*/
var _ids = coerceArray(this.entityIds);
for (var i = 0, len = _ids.length; i < len; i++) {
var entityId = _ids[i];
/** The Entity in current ids and doesn't exist, add it. */
if (ids.indexOf(entityId) > -1 && this.hasEntity(entityId) === false) {
isFunction(actions.beforeAdd) && actions.beforeAdd(entityId);
var plugin = this.instantiatePlugin(entityId);
this.entities.set(entityId, plugin);
isFunction(actions.afterAdd) && actions.afterAdd(plugin);
}
else {
this.entities.forEach(function (plugin, entityId) {
/** The Entity not in current ids and exists, remove it. */
if (ids.indexOf(entityId) === -1 && _this.hasEntity(entityId) === true) {
isFunction(actions.beforeRemove) && actions.beforeRemove(plugin);
_this.removeEntity(entityId);
}
});
}
}
}
}
else {
/**
* Otherwise, start with the provided ids or all.
*/
this.getIds().forEach(function (id) {
if (!_this.hasEntity(id))
_this.createEntity(id, _this.instantiatePlugin(id));
});
}
};
/**
* Listen for add/remove entities.
*/
EntityCollectionPlugin.prototype.selectIds = function () {
return this.query.select(function (state) { return state.ids; });
};
/**
* Base method for activation, you can override it if you need to.
*/
EntityCollectionPlugin.prototype.activate = function (ids) {
this.rebase(ids);
};
/**
* Loop over each id and invoke the plugin method.
*/
EntityCollectionPlugin.prototype.forEachId = function (ids, cb) {
var _ids = this.resolvedIds(ids);
for (var i = 0, len = _ids.length; i < len; i++) {
var id = _ids[i];
if (this.hasEntity(id)) {
cb(this.getEntity(id));
}
}
};
return EntityCollectionPlugin;
}());
var StateHistoryPlugin = /** @class */ (function (_super) {
__extends(StateHistoryPlugin, _super);
function StateHistoryPlugin(query, params, _entityId) {
if (params === void 0) { params = {}; }
var _this = _super.call(this, query, {
resetFn: function () { return _this.clear(); }
}) || this;
_this.query = query;
_this.params = params;
_this._entityId = _entityId;
/** Allow skipping an update from outside */
_this.skip = false;
_this.history = {
past: [],
present: null,
future: []
};
/** Skip the update when redo/undo */
_this.skipUpdate = false;
params.maxAge = !!params.maxAge ? params.maxAge : 10;
params.comparator = params.comparator || (function () { return true; });
_this.activate();
return _this;
}
Object.defineProperty(StateHistoryPlugin.prototype, "hasPast$", {
/**
* Observable stream representing whether the history plugin has an available past
*
*/
get: function () {
return this._hasPast$;
},
enumerable: true,
configurable: true
});
Object.defineProperty(StateHistoryPlugin.prototype, "hasFuture$", {
/**
* Observable stream representing whether the history plugin has an available future
*
*/
get: function () {
return this._hasFuture$;
},
enumerable: true,
configurable: true
});
Object.defineProperty(StateHistoryPlugin.prototype, "hasPast", {
get: function () {
return this.history.past.length > 0;
},
enumerable: true,
configurable: true
});
Object.defineProperty(StateHistoryPlugin.prototype, "hasFuture", {
get: function () {
return this.history.future.length > 0;
},
enumerable: true,
configurable: true
});
Object.defineProperty(StateHistoryPlugin.prototype, "property", {
get: function () {
return this.params.watchProperty;
},
enumerable: true,
configurable: true
});
/* Updates the hasPast$ hasFuture$ observables*/
StateHistoryPlugin.prototype.updateHasHistory = function () {
this.hasFutureSubject.next(this.hasFuture);
this.hasPastSubject.next(this.hasPast);
};
StateHistoryPlugin.prototype.activate = function () {
var _this = this;
this.hasPastSubject = new BehaviorSubject(false);
this._hasPast$ = this.hasPastSubject.asObservable().pipe(distinctUntilChanged());
this.hasFutureSubject = new BehaviorSubject(false);
this._hasFuture$ = this.hasFutureSubject.asObservable().pipe(distinctUntilChanged());
this.history.present = this.getSource(this._entityId, this.property);
this.subscription = this
.selectSource(this._entityId, this.property)
.pipe(pairwise())
.subscribe(function (_a) {
var _b = __read(_a, 2), past = _b[0], present = _b[1];
if (_this.skip) {
_this.skip = false;
return;
}
/**
* comparator: (prev, current) => isEqual(prev, current) === false
*/
var shouldUpdate = _this.params.comparator(past, present);
if (!_this.skipUpdate && shouldUpdate) {
if (_this.history.past.length === _this.params.maxAge) {
_this.history.past = _this.history.past.slice(1);
}
_this.history.past = __spread(_this.history.past, [past]);
_this.history.present = present;
_this.updateHasHistory();
}
});
};
StateHistoryPlugin.prototype.undo = function () {
if (this.history.past.length > 0) {
var _a = this.history, past = _a.past, present = _a.present;
var previous = past[past.length - 1];
this.history.past = past.slice(0, past.length - 1);
this.history.present = previous;
this.history.future = __spread([present], this.history.future);
this.update();
}
};
StateHistoryPlugin.prototype.redo = function () {
if (this.history.future.length > 0) {
var _a = this.history, past = _a.past, present = _a.present;
var next = this.history.future[0];
var newFuture = this.history.future.slice(1);
this.history.past = __spread(past, [present]);
this.history.present = next;
this.history.future = newFuture;
this.update('Redo');
}
};
StateHistoryPlugin.prototype.jumpToPast = function (index) {
if (index < 0 || index >= this.history.past.length)
return;
var _a = this.history, past = _a.past, future = _a.future, present = _a.present;
/**
*
* const past = [1, 2, 3, 4, 5];
* const present = 6;
* const future = [7, 8, 9];
* const index = 2;
*
* newPast = past.slice(0, index) = [1, 2];
* newPresent = past[index] = 3;
* newFuture = [...past.slice(index + 1),present, ...future] = [4, 5, 6, 7, 8, 9];
*
*/
var newPast = past.slice(0, index);
var newFuture = __spread(past.slice(index + 1), [present], future);
var newPresent = past[index];
this.history.past = newPast;
this.history.present = newPresent;
this.history.future = newFuture;
this.update();
};
StateHistoryPlugin.prototype.jumpToFuture = function (index) {
if (index < 0 || index >= this.history.future.length)
return;
var _a = this.history, past = _a.past, future = _a.future, present = _a.present;
/**
*
* const past = [1, 2, 3, 4, 5];
* const present = 6;
* const future = [7, 8, 9, 10]
* const index = 1
*
* newPast = [...past, present, ...future.slice(0, index) = [1, 2, 3, 4, 5, 6, 7];
* newPresent = future[index] = 8;
* newFuture = futrue.slice(index+1) = [9, 10];
*
*/
var newPast = __spread(past, [present], future.slice(0, index));
var newPresent = future[index];
var newFuture = future.slice(index + 1);
this.history.past = newPast;
this.history.present = newPresent;
this.history.future = newFuture;
this.update('Redo');
};
/**
*
* jump n steps in the past or forward
*
*/
StateHistoryPlugin.prototype.jump = function (n) {
if (n > 0)
return this.jumpToFuture(n - 1);
if (n < 0)
return this.jumpToPast(this.history.past.length + n);
};
/**
* Clear the history
*
* @param customUpdateFn Callback function for only clearing part of the history
*
* @example
*
* stateHistory.clear((history) => {
* return {
* past: history.past,
* present: history.present,
* future: []
* };
* });
*/
StateHistoryPlugin.prototype.clear = function (customUpdateFn) {
this.history = isFunction(customUpdateFn)
? customUpdateFn(this.history)
: {
past: [],
present: null,
future: []
};
this.updateHasHistory();
};
StateHistoryPlugin.prototype.destroy = function (clearHistory) {
if (clearHistory === void 0) { clearHistory = false; }
if (clearHistory) {
this.clear();
}
this.subscription.unsubscribe();
};
StateHistoryPlugin.prototype.ignoreNext = function () {
this.skip = true;
};
StateHistoryPlugin.prototype.update = function (action) {
if (action === void 0) { action = 'Undo'; }
this.skipUpdate = true;
logAction("@StateHistory - " + action);
this.updateStore(this.history.present, this._entityId, this.property);
this.updateHasHistory();
this.skipUpdate = false;
};
return StateHistoryPlugin;
}(AkitaPlugin));
/** @class */ ((function (_super) {
__extends(EntityStateHistoryPlugin, _super);
function EntityStateHistoryPlugin(query, params) {
if (params === void 0) { params = {}; }
var _this = _super.call(this, query, params.entityIds) || this;
_this.query = query;
_this.params = params;
params.maxAge = toBoolean(params.maxAge) ? params.maxAge : 10;
_this.activate();
_this.selectIds()
.pipe(skip(1))
.subscribe(function (ids) { return _this.activate(ids); });
return _this;
}
EntityStateHistoryPlugin.prototype.redo = function (ids) {
this.forEachId(ids, function (e) { return e.redo(); });
};
EntityStateHistoryPlugin.prototype.undo = function (ids) {
this.forEachId(ids, function (e) { return e.undo(); });
};
EntityStateHistoryPlugin.prototype.hasPast = function (id) {
if (this.hasEntity(id)) {
return this.getEntity(id).hasPast;
}
};
EntityStateHistoryPlugin.prototype.hasFuture = function (id) {
if (this.hasEntity(id)) {
return this.getEntity(id).hasFuture;
}
};
EntityStateHistoryPlugin.prototype.jumpToFuture = function (ids, index) {
this.forEachId(ids, function (e) { return e.jumpToFuture(index); });
};
EntityStateHistoryPlugin.prototype.jumpToPast = function (ids, index) {
this.forEachId(ids, function (e) { return e.jumpToPast(index); });
};
EntityStateHistoryPlugin.prototype.clear = function (ids) {
this.forEachId(ids, function (e) { return e.clear(); });
};
EntityStateHistoryPlugin.prototype.destroy = function (ids, clearHistory) {
if (clearHistory === void 0) { clearHistory = false; }
this.forEachId(ids, function (e) { return e.destroy(clearHistory); });
};
EntityStateHistoryPlugin.prototype.ignoreNext = function (ids) {
this.forEachId(ids, function (e) { return e.ignoreNext(); });
};
EntityStateHistoryPlugin.prototype.instantiatePlugin = function (id) {
return new StateHistoryPlugin(this.query, this.params, id);
};
return EntityStateHistoryPlugin;
})(EntityCollectionPlugin));
var ɵ0 = function (head, current) { return JSON.stringify(head) !== JSON.stringify(current); };
var dirtyCheckDefaultParams = {
comparator: ɵ0
};
function getNestedPath(nestedObj, path) {
var pathAsArray = path.split('.');
return pathAsArray.reduce(function (obj, key) { return (obj && obj[key] !== 'undefined' ? obj[key] : undefined); }, nestedObj);
}
var DirtyCheckPlugin = /** @class */ (function (_super) {
__extends(DirtyCheckPlugin, _super);
function DirtyCheckPlugin(query, params, _entityId) {
var _this = _super.call(this, query) || this;
_this.query = query;
_this.params = params;
_this._entityId = _entityId;
_this.dirty = new BehaviorSubject(false);
_this.active = false;
_this._reset = new Subject();
_this.isDirty$ = _this.dirty.asObservable().pipe(distinctUntilChanged());
_this.reset$ = _this._reset.asObservable();
_this.params = __assign({}, dirtyCheckDefaultParams, params);
if (_this.params.watchProperty) {
var watchProp = coerceArray(_this.params.watchProperty);
if (query instanceof QueryEntity && watchProp.includes('entities') && !watchProp.includes('ids')) {
watchProp.push('ids');
}
_this.params.watchProperty = watchProp;
}
return _this;
}
DirtyCheckPlugin.prototype.reset = function (params) {
if (params === void 0) { params = {}; }
var currentValue = this.head;
if (isFunction(params.updateFn)) {
if (this.isEntityBased(this._entityId)) {
currentValue = params.updateFn(this.head, this.getQuery().getEntity(this._entityId));
}
else {
currentValue = params.updateFn(this.head, this.getQuery().getValue());
}
}
logAction("@DirtyCheck - Revert");
this.updateStore(currentValue, this._entityId);
this._reset.next();
};
DirtyCheckPlugin.prototype.setHead = function () {
if (!this.active) {
this.activate();
this.active = true;
}
else {
this.head = this._getHead();
}
this.updateDirtiness(false);
return this;
};
DirtyCheckPlugin.prototype.isDirty = function () {
return !!this.dirty.value;
};
DirtyCheckPlugin.prototype.hasHead = function () {
return !!this.getHead();
};
DirtyCheckPlugin.prototype.destroy = function () {
this.head = null;
this.subscription && this.subscription.unsubscribe();
this._reset && this._reset.complete();
};
DirtyCheckPlugin.prototype.isPathDirty = function (path) {
var head = this.getHead();
var current = this.getQuery().getValue();
var currentPathValue = getNestedPath(current, path);
var headPathValue = getNestedPath(head, path);
return this.params.comparator(currentPathValue, headPathValue);
};
DirtyCheckPlugin.prototype.getHead = function () {
return this.head;
};
DirtyCheckPlugin.prototype.activate = function () {
var _this = this;
this.head = this._getHead();
/** if we are tracking specific properties select only the relevant ones */
var source = this.params.watchProperty
? this.params.watchProperty.map(function (prop) {
return _this.query
.select(function (state) { return state[prop]; })
.pipe(map(function (val) { return ({
val: val,
__akitaKey: prop
}); }));
})
: [this.selectSource(this._entityId)];
this.subscription = combineLatest.apply(void 0, __spread(source)).pipe(skip(1))
.subscribe(function (currentState) {
if (isUndefined(_this.head))
return;
/** __akitaKey is used to determine if we are tracking a specific property or a store change */
var isChange = currentState.some(function (state) {
var head = state.__akitaKey ? _this.head[state.__akitaKey] : _this.head;
var compareTo = state.__akitaKey ? state.val : state;
return _this.params.comparator(head, compareTo);
});
_this.updateDirtiness(isChange);
});
};
DirtyCheckPlugin.prototype.updateDirtiness = function (isDirty) {
this.dirty.next(isDirty);
};
DirtyCheckPlugin.prototype._getHead = function () {
var head = this.getSource(this._entityId);
if (this.params.watchProperty) {
head = this.getWatchedValues(head);
}
return head;
};
DirtyCheckPlugin.prototype.getWatchedValues = function (source) {
return this.params.watchProperty.reduce(function (watched, prop) {
watched[prop] = source[prop];
return watched;
}, {});
};
return DirtyCheckPlugin;
}(AkitaPlugin));
/** @class */ ((function (_super) {
__extends(EntityDirtyCheckPlugin, _super);
function EntityDirtyCheckPlugin(query, params) {
if (params === void 0) { params = {}; }
var _this = _super.call(this, query, params.entityIds) || this;
_this.query = query;
_this.params = params;
_this._someDirty = new Subject();
_this.someDirty$ = merge(_this.query.select(function (state) { return state.entities; }), _this._someDirty.asObservable()).pipe(auditTime(0), map(function () { return _this.checkSomeDirty(); }));
_this.params = __assign({}, dirtyCheckDefaultParams, params);
// TODO lazy activate?
_this.activate();
_this.selectIds()
.pipe(skip(1))
.subscribe(function (ids) {
_super.prototype.rebase.call(_this, ids, { afterAdd: function (plugin) { return plugin.setHead(); } });
});
return _this;
}
EntityDirtyCheckPlugin.prototype.setHead = function (ids) {
if (this.params.entityIds && ids) {
var toArray_1 = coerceArray(ids);
var someAreWatched = coerceArray(this.params.entityIds).some(function (id) { return toArray_1.indexOf(id) > -1; });
if (someAreWatched === false) {
return this;
}
}
this.forEachId(ids, function (e) { return e.setHead(); });
this._someDirty.next();
return this;
};
EntityDirtyCheckPlugin.prototype.hasHead = function (id) {
if (this.entities.has(id)) {
var entity = this.getEntity(id);
return entity.hasHead();
}
return false;
};
EntityDirtyCheckPlugin.prototype.reset = function (ids, params) {
if (params === void 0) { params = {}; }
this.forEachId(ids, function (e) { return e.reset(params); });
};
EntityDirtyCheckPlugin.prototype.isDirty = function (id, asObservable) {
if (asObservable === void 0) { asObservable = true; }
if (this.entities.has(id)) {
var entity = this.getEntity(id);
return asObservable ? entity.isDirty$ : entity.isDirty();
}
return false;
};
EntityDirtyCheckPlugin.prototype.someDirty = function () {
return this.checkSomeDirty();
};
EntityDirtyCheckPlugin.prototype.isPathDirty = function (id, path) {
if (this.entities.has(id)) {
var head = this.getEntity(id).getHead();
var current = this.query.getEntity(id);
var currentPathValue = getNestedPath(current, path);
var headPathValue = getNestedPath(head, path);
return this.params.comparator(currentPathValue, headPathValue);
}
return null;
};
EntityDirtyCheckPlugin.prototype.destroy = function (ids) {
this.forEachId(ids, function (e) { return e.destroy(); });
/** complete only when the plugin destroys */
if (!ids) {
this._someDirty.complete();
}
};
EntityDirtyCheckPlugin.prototype.instantiatePlugin = function (id) {
return new DirtyCheckPlugin(this.query, this.params, id);
};
EntityDirtyCheckPlugin.prototype.checkSomeDirty = function () {
var e_1, _a;
var entitiesIds = this.resolvedIds();
try {
for (var entitiesIds_1 = __values(entitiesIds), entitiesIds_1_1 = entitiesIds_1.next(); !entitiesIds_1_1.done; entitiesIds_1_1 = entitiesIds_1.next()) {
var id = entitiesIds_1_1.value;
if (this.getEntity(id).isDirty()) {
return true;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (entitiesIds_1_1 && !entitiesIds_1_1.done && (_a = entitiesIds_1.return)) _a.call(entitiesIds_1);
}
finally { if (e_1) throw e_1.error; }
}
return false;
};
return EntityDirtyCheckPlugin;
})(EntityCollectionPlugin));
/**
* Generate random guid
*
* @example
*
* {
* id: guid()
* }
*
* @remarks this isn't a GUID, but a 10 char random alpha-num
*/
function guid() {
return Math.random()
.toString(36)
.slice(2);
}
var _a, _b;
var StoreAction;
(function (StoreAction) {
StoreAction["Update"] = "UPDATE";
})(StoreAction || (StoreAction = {}));
(_a = {},
_a[StoreAction.Update] = 'update',
_a);
var EntityStoreAction;
(function (EntityStoreAction) {
EntityStoreAction["Update"] = "UPDATE";
EntityStoreAction["AddEntities"] = "ADD_ENTITIES";
EntityStoreAction["SetEntities"] = "SET_ENTITIES";
EntityStoreAction["UpdateEntities"] = "UPDATE_ENTITIES";
EntityStoreAction["RemoveEntities"] = "REMOVE_ENTITIES";
EntityStoreAction["UpsertEntities"] = "UPSERT_ENTITIES";
EntityStoreAction["UpsertManyEntities"] = "UPSERT_MANY_ENTITIES";
})(EntityStoreAction || (EntityStoreAction = {}));
(_b = {},
_b[EntityStoreAction.Update] = 'update',
_b[EntityStoreAction.AddEntities] = 'add',
_b[EntityStoreAction.SetEntities] = 'set',
_b[EntityStoreAction.UpdateEntities] = 'update',
_b[EntityStoreAction.RemoveEntities] = 'remove',
_b[EntityStoreAction.UpsertEntities] = 'upsert',
_b[EntityStoreAction.UpsertManyEntities] = 'upsertMany',
_b);
function combineQueries(observables) {
return combineLatest(observables).pipe(auditTime(0));
}
var immer_cjs_development = {};
Object.defineProperty(immer_cjs_development, '__esModule', { value: true });
var _ref;
// Should be no imports here!
// Some things that should be evaluated before all else...
// We only want to know if non-polyfilled symbols are available
var hasSymbol = typeof Symbol !== "undefined" && typeof
/*#__PURE__*/
Symbol("x") === "symbol";
var hasMap = typeof Map !== "undefined";
var hasSet = typeof Set !== "undefined";
var hasProxies = typeof Proxy !== "undefined" && typeof Proxy.revocable !== "undefined" && typeof Reflect !== "undefined";
/**
* The sentinel value returned by producers to replace the draft with undefined.
*/
var NOTHING = hasSymbol ?
/*#__PURE__*/
Symbol.for("immer-nothing") : (_ref = {}, _ref["immer-nothing"] = true, _ref);
/**
* To let Immer treat your class instances as plain immutable objects
* (albeit with a custom prototype), you must define either an instance property
* or a static property on each of your custom classes.
*
* Otherwise, your class instance will never be drafted, which means it won't be
* safe to mutate in a produce callback.
*/
var DRAFTABLE = hasSymbol ?
/*#__PURE__*/
Symbol.for("immer-draftable") : "__$immer_draftable";
var DRAFT_STATE = hasSymbol ?
/*#__PURE__*/
Symbol.for("immer-state") : "__$immer_state"; // Even a polyfilled Symbol might provide Symbol.iterator
var iteratorSymbol = typeof Symbol != "undefined" && Symbol.iterator || "@@iterator";
var errors = {
0: "Illegal state",
1: "Immer drafts cannot have computed properties",
2: "This object has been frozen and should not be mutated",
3: function _(data) {
return "Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " + data;
},
4: "An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.",
5: "Immer forbids circular references",
6: "The first or second argument to `produce` must be a function",
7: "The third argument to `produce` must be a function or undefined",
8: "First argument to `createDraft` must be a plain object, an array, or an immerable object",
9: "First argument to `finishDraft` must be a draft returned by `createDraft`",
10: "The given draft is already finalized",
11: "Object.defineProperty() cannot be used on an Immer draft",
12: "Object.setPrototypeOf() cannot be used on an Immer draft",
13: "Immer only supports deleting array indices",
14: "Immer only supports setting array indices and the 'length' property",
15: function _(path) {
return "Cannot apply patch, path doesn't resolve: " + path;
},
16: 'Sets cannot have "replace" patches.',
17: function _(op) {
return "Unsupported patch operation: " + op;
},
18: function _(plugin) {
return "The plugin for '" + plugin + "' has not been loaded into Immer. To enable the plugin, import and call `enable" + plugin + "()` when initializing your application.";
},
20: "Cannot use proxies if Proxy, Proxy.revocable or Reflect are not available",
21: function _(thing) {
return "produce can only be called on things that are draftable: plain objects, arrays, Map, Set or classes that are marked with '[immerable]: true'. Got '" + thing + "'";
},
22: function _(thing) {
return "'current' expects a draft, got: " + thing;
},
23: function _(thing) {
return "'original' expects a draft, got: " + thing;
}
};
function die(error) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
{
var e = errors[error];
var msg = !e ? "unknown error nr: " + error : typeof e === "function" ? e.apply(null, args) : e;
throw new Error("[Immer] " + msg);
}
}
var ArchtypeObject = 0;
var ArchtypeArray = 1;
var ArchtypeMap = 2;
var ArchtypeSet = 3;
var ProxyTypeProxyObject = 0;
var ProxyTypeProxyArray = 1;
var ProxyTypeES5Object = 4;
var ProxyTypeES5Array = 5;
var ProxyTypeMap = 2;
var ProxyTypeSet = 3;
/** Returns true if the given value is an Immer draft */
function isDraft(value) {
return !!value && !!value[DRAFT_STATE];
}
/** Returns true if the given value can be drafted by Immer */
function isDraftable(value) {
if (!value) return false;
return isPlainObject(value) || Array.isArray(value) || !!value[DRAFTABLE] || !!value.constructor[DRAFTABLE] || isMap(value) || isSet(value);
}
function isPlainObject(value) {
if (!value || typeof value !== "object") return false;
var proto = Object.getPrototypeOf(value);
return !proto || proto === Object.prototype;
}
function original(value) {
if (!isDraft(value)) die(23, value);
return value[DRAFT_STATE].base_;
}
var ownKeys = typeof Reflect !== "undefined" && Reflect.ownKeys ? Reflect.ownKeys : typeof Object.getOwnPropertySymbols !== "undefined" ? function (obj) {
return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj));
} :
/* istanbul ignore next */
Object.getOwnPropertyNames;
var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors || function getOwnPropertyDescriptors(target) {
// Polyfill needed for Hermes and IE, see https://github.com/facebook/hermes/issues/274
var res = {};
ownKeys(target).forEach(function (key) {
res[key] = Object.getOwnPropertyDescriptor(target, key);
});
return res;
};
function each(obj, iter, enumerableOnly) {
if (enumerableOnly === void 0) {
enumerableOnly = false;
}
if (getArchtype(obj) === ArchtypeObject) {
(enumerableOnly ? Object.keys : ownKeys)(obj).forEach(function (key) {
if (!enumerableOnly || typeof key !== "symbol") iter(key, obj[key], obj);
});
} else {
obj.forEach(function (entry, index) {
return iter(index, entry, obj);
});
}
}
function getArchtype(thing) {
/* istanbul ignore next */
var state = thing[DRAFT_STATE];
return state ? state.type_ > 3 ? state.type_ - 4 // cause Object and Array map back from 4 and 5
: state.type_ // others are the same
: Array.isArray(thing) ? ArchtypeArray : isMap(thing) ? ArchtypeMap : isSet(thing) ? ArchtypeSet : ArchtypeObject;
}
function has(thing, prop) {
return getArchtype(thing) === ArchtypeMap ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
}
function get(thing, prop) {
// @ts-ignore
return getArchtype(thing) === ArchtypeMap ? thing.get(prop) : thing[prop];
}
function set(thing, propOrOldValue, value) {
var t = getArchtype(thing);
if (t === ArchtypeMap) thing.set(propOrOldValue, value);else if (t === ArchtypeSet) {
thing.delete(propOrOldValue);
thing.add(value);
} else thing[propOrOldValue] = value;
}
function is(x, y) {
// From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js
if (x === y) {
return x !== 0 || 1 / x === 1 / y;
} else {
return x !== x && y !== y;
}
}
function isMap(target) {
return hasMap && target instanceof Map;
}
function isSet(target) {
return hasSet && target instanceof Set;
}
function latest(state) {
return state.copy_ || state.base_;
}
function shallowCopy(base) {
if (Array.isArray(base)) return Array.prototype.slice.call(base);
var descriptors = getOwnPropertyDescriptors(base);
delete descriptors[DRAFT_STATE];
var keys = ownKeys(descriptors);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var desc = descriptors[key];
if (desc.writable === false) {
desc.writable = true;
desc.configurable = true;
} // like object.assign, we will read any _own_, get/set accessors. This helps in dealing
// with libraries that trap values, like mobx or vue
// unlike object.assign, non-enumerables will be copied as well
if (desc.get || desc.set) descriptors[key] = {
configurable: true,
writable: true,
enumerable: desc.enumerable,
value: base[key]
};
}
return Object.create(Object.getPrototypeOf(base), descriptors);
}
function freeze(obj, deep) {
if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj)) return;
if (getArchtype(obj) > 1
/* Map or Set */
) {
obj.set = obj.add = obj.clear = obj.delete = dontMutateFrozenCollections;
}
Object.freeze(obj);
if (deep) each(obj, function (key, value) {
return freeze(value, true);
}, true);
}
function dontMutateFrozenCollections() {
die(2);
}
function isFrozen(obj) {
if (obj == null || typeof obj !== "object") return true; // See #600, IE dies on non-objects in Object.isFrozen
return Object.isFrozen(obj);
}
/** Plugin utilities */
var plugins = {};
function getPlugin(pluginKey) {
var plugin = plugins[pluginKey];
if (!plugin) {
die(18, pluginKey);
} // @ts-ignore
return plugin;
}
function loadPlugin(pluginKey, implementation) {
if (!plugins[pluginKey]) plugins[pluginKey] = implementation;
}
var currentScope;
function getCurrentScope() {
if ( !currentScope) die(0);
return currentScope;
}
function createScope(parent_, immer_) {
return {
drafts_: [],
parent_: parent_,
immer_: immer_,
// Whenever the modified draft contains a draft from another scope, we
// need to prevent auto-freezing so the unowned draft can be finalized.
canAutoFreeze_: true,
unfinalizedDrafts_: 0
};
}
function usePatchesInScope(scope, patchListener) {
if (patchListener) {
getPlugin("Patches"); // assert we have the plugin
scope.patches_ = [];
scope.inversePatches_ = [];
scope.patchListener_ = patchListener;
}
}
function revokeScope(scope) {
leaveScope(scope);
scope.drafts_.forEach(revokeDraft); // @ts-ignore
scope.drafts_ = null;
}
function leaveScope(scope) {
if (scope === currentScope) {
currentScope = scope.parent_;
}
}
function enterScope(immer) {
return currentScope = createScope(currentScope, immer);
}
function revokeDraft(draft) {
var state = draft[DRAFT_STATE];
if (state.type_ === ProxyTypeProxyObject || state.type_ === ProxyTypeProxyArray) state.revoke_();else state.revoked_ = true;
}
function processResult(result, scope) {
scope.unfinalizedDrafts_ = scope.drafts_.length;
var baseDraft = scope.drafts_[0];
var isReplaced = result !== undefined && result !== baseDraft;
if (!scope.immer_.useProxies_) getPlugin("ES5").willFinalizeES5_(scope, result, isReplaced);
if (isReplaced) {
if (baseDraft[DRAFT_STATE].modified_) {
revokeScope(scope);
die(4);
}
if (isDraftable(result)) {
// Finalize the result in case it contains (or is) a subset of the draft.
result = finalize(scope, result);
if (!scope.parent_) maybeFreeze(scope, result);
}
if (scope.patches_) {
getPlugin("Patches").generateReplacementPatches_(baseDraft[DRAFT_STATE], result, scope.patches_, scope.inversePatches_);
}
} else {
// Finalize the base draft.
result = finalize(scope, baseDraft, []);
}
revokeScope(scope);
if (scope.patches_) {
scope.patchListener_(scope.patches_, scope.inversePatches_);
}
return result !== NOTHING ? result : undefined;
}
function finalize(rootScope, value, path) {
// Don't recurse in tho recursive data structures
if (isFrozen(value)) return value;
var state = value[DRAFT_STATE]; // A plain object, might need freezing, might contain drafts
if (!state) {
each(value, function (key, childValue) {
return finalizeProperty(rootScope, state, value, key, childValue, path);
}, true // See #590, don't recurse into non-enumarable of non drafted objects
);
return value;
} // Never finalize drafts owned by another scope.
if (state.scope_ !== rootScope) return value; // Unmodified draft, return the (frozen) original
if (!state.modified_) {
maybeFreeze(rootScope, state.base_, true);
return state.base_;
} // Not finalized yet, let's do that now
if (!state.finalized_) {
state.finalized_ = true;
state.scope_.unfinalizedDrafts_--;
var result = // For ES5, create a good copy from the draft first, with added keys and without deleted keys.
state.type_ === ProxyTypeES5Object || state.type_ === ProxyTypeES5Array ? state.copy_ = shallowCopy(state.draft_) : state.copy_; // Finalize all children of the copy
// For sets we clone before iterating, otherwise we can get in endless loop due to modifying during iteration, see #628
// Although the original test case doesn't seem valid anyway, so if this in the way we can turn the next line
// back to each(result, ....)
each(state.type_ === ProxyTypeSet ? new Set(result) : result, function (key, childValue) {
return finalizeProperty(rootScope, state, result, key, childValue, path);
}); // everything inside is frozen, we can freeze here
maybeFreeze(rootScope, result, false); // first time finalizing, let's create those patches
if (path && rootScope.patches_) {
getPlugin("Patches").generatePatches_(state, path, rootScope.patches_, rootScope.inversePatches_);
}
}
return state.copy_;
}
function finalizeProperty(rootScope, parentState, targetObject, prop, childValue, rootPath) {
if ( childValue === targetObject) die(5);
if (isDraft(childValue)) {
var path = rootPath && parentState && parentState.type_ !== ProxyTypeSet && // Set objects are atomic since they have no keys.
!has(parentState.assigned_, prop) // Skip deep patches for assigned keys.
? rootPath.concat(prop) : undefined; // Drafts owned by `scope` are finalized here.
var res = finalize(rootScope, childValue, path);
set(targetObject, prop, res); // Drafts from another scope must prevented to be frozen
// if we got a draft back from finalize, we're in a nested produce and shouldn't freeze
if (isDraft(res)) {
rootScope.canAutoFreeze_ = false;
} else return;
} // Search new objects for unfinalized drafts. Frozen objects should never contain drafts.
if (isDraftable(childValue) && !isFrozen(childValue)) {
if (!rootScope.immer_.autoFreeze_ && rootScope.unfinalizedDrafts_ < 1) {
// optimization: if an object is not a draft, and we don't have to
// deepfreeze everything, and we are sure that no drafts are left in the remaining object
// cause we saw and finalized all drafts already; we can stop visiting the rest of the tree.
// This benefits especially adding large data tree's without further processing.
// See add-data.js perf test
return;
}
finalize(rootScope, childValue); // immer deep freezes plain objects, so if there is no parent state, we freeze as well
if (!parentState || !parentState.scope_.parent_) maybeFreeze(rootScope, childValue);
}
}
function maybeFreeze(scope, value, deep) {
if (deep === void 0) {
deep = false;
}
if (scope.immer_.autoFreeze_ && scope.canAutoFreeze_) {
freeze(value, deep);
}
}
/**
* Returns a new draft of the `base` object.
*
* The second argument is the parent draft-state (used internally).
*/
function createProxyProxy(base, parent) {
var isArray = Array.isArray(base);
var state = {
type_: isArray ? ProxyTypeProxyArray : ProxyTypeProxyObject,
// Track which produce call this is associated with.
scope_: parent ? parent.scope_ : getCurrentScope(),
// True for both shallow and deep changes.
modified_: false,
// Used during finalization.
finalized_: false,
// Track which properties have been assigned (true) or deleted (false).
assigned_: {},
// The parent draft state.
parent_: parent,
// The base state.
base_: base,
// The base proxy.
draft_: null,
// The base copy with any updated values.
copy_: null,
// Called by the `produce` function.
revoke_: null,
isManual_: false
}; // the traps must target something, a bit like the 'real' base.
// but also, we need to be able to determine from the target what the relevant state is
// (to avoid creating traps per instance to capture the state in closure,
// and to avoid creating weird hidden properties as well)
// So the trick is to use 'state' as the actual 'target'! (and make sure we intercept everything)
// Note that in the case of an array, we put the state in an array to have better Reflect defaults ootb
var target = state;
var traps = objectTraps;
if (isArray) {
target = [state];
traps = arrayTraps;
}
var _Proxy$revocable = Proxy.revocable(target, traps),
revoke = _Proxy$revocable.revoke,
proxy = _Proxy$revocable.proxy;
state.draft_ = proxy;
state.revoke_ = revoke;
return proxy;
}
/**
* Object drafts
*/
var objectTraps = {
get: function get(state, prop) {
if (prop === DRAFT_STATE) return state;
var source = latest(state);
if (!has(source, prop)) {
// non-existing or non-own property...
return readPropFromProto(state, source, prop);
}
var value = source[prop];
if (state.finalized_ || !isDraftable(value)) {
return value;
} // Check for existing draft in modified state.
// Assigned values are never drafted. This catches any drafts we created, too.
if (value === peek(state.base_, prop)) {
prepareCopy(state);
return state.copy_[prop] = createProxy(state.scope_.immer_, value, state);
}
return value;
},
has: function has(state, prop) {
return prop in latest(state);
},
ownKeys: function ownKeys(state) {
return Reflect.ownKeys(latest(state));
},
set: function set(state, prop
/* strictly not, but helps TS */
, value) {
var desc = getDescriptorFromProto(latest(state), prop);
if (desc === null || desc === void 0 ? void 0 : desc.set) {
// special case: if this write is captured by a setter, we have
// to trigger it with the correct context
desc.set.call(state.draft_, value);
return true;
}
if (!state.modified_) {
// the last check is because we need to be able to distinguish setting a non-existig to undefined (which is a change)
// from setting an existing property with value undefined to undefined (which is not a change)
var current = peek(latest(state), prop); // special case, if we assigning the original value to a draft, we can ignore the assignment
var currentState = current === null || current === void 0 ? void 0 : current[DRAFT_STATE];
if (currentState && currentState.base_ === value) {
state.copy_[prop] = value;
state.assigned_[prop] = false;
return true;
}
if (is(value, current) && (value !== undefined || has(state.base_, prop))) return true;
prepareCopy(state);
markChanged(state);
} // @ts-ignore
state.copy_[prop] = value;
state.assigned_[prop] = true;
return true;
},
deleteProperty: function deleteProperty(state, prop) {
// The `undefined` check is a fast path for pre-existing keys.
if (peek(state.base_, prop) !== undefined || prop in state.base_) {
state.assigned_[prop] = false;
prepareCopy(state);
markChanged(state);
} else {
// if an originally not assigned property was deleted
delete state.assigned_[prop];
} // @ts-ignore
if (state.copy_) delete state.copy_[prop];
return true;
},
// Note: We never coerce `desc.value` into an Immer draft, because we can't make
// the same guarantee in ES5 mode.
getOwnPropertyDescriptor: function getOwnPropertyDescriptor(state, prop) {
var owner = latest(state);
var desc = Reflect.getOwnPropertyDescriptor(owner, prop);
if (!desc) return desc;
return {
writable: true,
configurable: state.type_ !== ProxyTypeProxyArray || prop !== "length",
enumerable: desc.enumerable,
value: owner[prop]
};
},
defineProperty: function defineProperty() {
die(11);
},
getPrototypeOf: function getPrototypeOf(state) {
return Object.getPrototypeOf(state.base_);
},
setPrototypeOf: function setPrototypeOf() {
die(12);
}
};
/**
* Array drafts
*/
var arrayTraps = {};
each(objectTraps, function (key, fn) {
// @ts-ignore
arrayTraps[key] = function () {
arguments[0] = arguments[0][0];
return fn.apply(this, arguments);
};
});
arrayTraps.deleteProperty = function (state, prop) {
if ( isNaN(parseInt(prop))) die(13);
return objectTraps.deleteProperty.call(this, state[0], prop);
};
arrayTraps.set = function (state, prop, value) {
if ( prop !== "length" && isNaN(parseInt(prop))) die(14);
return objectTraps.set.call(this, state[0], prop, value, state[0]);
}; // Access a property without creating an Immer draft.
function peek(draft, prop) {
var state = draft[DRAFT_STATE];
var source = state ? latest(state) : draft;
return source[prop];
}
function readPropFromProto(state, source, prop) {
var _desc$get;
var desc = getDescriptorFromProto(source, prop);
return desc ? "value" in desc ? desc.value : // This is a very special case, if the prop is a getter defined by the
// prototype, we should invoke it with the draft as context!
(_desc$get = desc.get) === null || _desc$get === void 0 ? void 0 : _desc$get.call(state.draft_) : undefined;
}
function getDescriptorFromProto(source, prop) {
// 'in' checks proto!
if (!(prop in source)) return undefined;
var proto = Object.getPrototypeOf(source);
while (proto) {
var desc = Object.getOwnPropertyDescriptor(proto, prop);
if (desc) return desc;
proto = Object.getPrototypeOf(proto);
}
return undefined;
}
function markChanged(state) {
if (!state.modified_) {
state.modified_ = true;
if (state.parent_) {
markChanged(state.parent_);
}
}
}
function prepareCopy(state) {
if (!state.copy_) {
state.copy_ = shallowCopy(state.base_);
}
}
var Immer =
/*#__PURE__*/
function () {
function Immer(config) {
this.useProxies_ = hasProxies;
this.autoFreeze_ = true
/* istanbul ignore next */
;
if (typeof (config === null || config === void 0 ? void 0 : config.useProxies) === "boolean") this.setUseProxies(config.useProxies);
if (typeof (config === null || config === void 0 ? void 0 : config.autoFreeze) === "boolean") this.setAutoFreeze(config.autoFreeze);
this.produce = this.produce.bind(this);
this.produceWithPatches = this.produceWithPatches.bind(this);
}
/**
* The `produce` function takes a value and a "recipe function" (whose
* return value often depends on the base state). The recipe function is
* free to mutate its first argument however it wants. All mutations are
* only ever applied to a __copy__ of the base state.
*
* Pass only a function to create a "curried producer" which relieves you
* from passing the recipe function every time.
*
* Only plain objects and arrays are made mutable. All other objects are
* considered uncopyable.
*
* Note: This function is __bound__ to its `Immer` instance.
*
* @param {any} base - the initial state
* @param {Function} producer - function that receives a proxy of the base state as first argument and which can be freely modified
* @param {Function} patchListener - optional function that will be called with all the patches produced here
* @returns {any} a new state, or the initial state if nothing was modified
*/
var _proto = Immer.prototype;
_proto.produce = function produce(base, recipe, patchListener) {
// curried invocation
if (typeof base === "function" && typeof recipe !== "function") {
var defaultBase = recipe;
recipe = base;
var self = this;
return function curriedProduce(base) {
var _this = this;
if (base === void 0) {
base = defaultBase;
}
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return self.produce(base, function (draft) {
var _recipe;
return (_recipe = recipe).call.apply(_recipe, [_this, draft].concat(args));
}); // prettier-ignore
};
}
if (typeof recipe !== "function") die(6);
if (patchListener !== undefined && typeof patchListener !== "function") die(7);
var result; // Only plain objects, arrays, and "immerable classes" are drafted.
if (isDraftable(base)) {
var scope = enterScope(this);
var proxy = createProxy(this, base, undefined);
var hasError = true;
try {
result = recipe(proxy);
hasError = false;
} finally {
// finally instead of catch + rethrow better preserves original stack
if (hasError) revokeScope(scope);else leaveScope(scope);
}
if (typeof Promise !== "undefined" && result instanceof Promise) {
return result.then(function (result) {
usePatchesInScope(scope, patchListener);
return processResult(result, scope);
}, function (error) {
revokeScope(scope);
throw error;
});
}
usePatchesInScope(scope, patchListener);
return processResult(result, scope);
} else if (!base || typeof base !== "object") {
result = recipe(base);
if (result === NOTHING) return undefined;
if (result === undefined) result = base;
if (this.autoFreeze_) freeze(result, true);
return result;
} else die(21, base);
};
_proto.produceWithPatches = function produceWithPatches(arg1, arg2, arg3) {
var _this2 = this;
if (typeof arg1 === "function") {
return function (state) {
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
return _this2.produceWithPatches(state, function (draft) {
return arg1.apply(void 0, [draft].concat(args));
});
};
}
var patches, inversePatches;
var nextState = this.produce(arg1, arg2, function (p, ip) {
patches = p;
inversePatches = ip;
});
return [nextState, patches, inversePatches];
};
_proto.createDraft = function createDraft(base) {
if (!isDraftable(base)) die(8);
if (isDraft(base)) base = current(base);
var scope = enterScope(this);
var proxy = createProxy(this, base, undefined);
proxy[DRAFT_STATE].isManual_ = true;
leaveScope(scope);
return proxy;
};
_proto.finishDraft = function finishDraft(draft, patchListener) {
var state = draft && draft[DRAFT_STATE];
{
if (!state || !state.isManual_) die(9);
if (state.finalized_) die(10);
}
var scope = state.scope_;
usePatchesInScope(scope, patchListener);
return processResult(undefined, scope);
}
/**
* Pass true to automatically freeze all copies created by Immer.
*
* By default, auto-freezing is disabled in production.
*/
;
_proto.setAutoFreeze = function setAutoFreeze(value) {
this.autoFreeze_ = value;
}
/**
* Pass true to use the ES2015 `Proxy` class when creating drafts, which is
* always faster than using ES5 proxies.
*
* By default, feature detection is used, so calling this is rarely necessary.
*/
;
_proto.setUseProxies = function setUseProxies(value) {
if (value && !hasProxies) {
die(20);
}
this.useProxies_ = value;
};
_proto.applyPatches = function applyPatches(base, patches) {
// If a patch replaces the entire state, take that replacement as base
// before applying patches
var i;
for (i = patches.length - 1; i >= 0; i--) {
var patch = patches[i];
if (patch.path.length === 0 && patch.op === "replace") {
base = patch.value;
break;
}
}
var applyPatchesImpl = getPlugin("Patches").applyPatches_;
if (isDraft(base)) {
// N.B: never hits if some patch a replacement, patches are never drafts
return applyPatchesImpl(base, patches);
} // Otherwise, produce a copy of the base state.
return this.produce(base, function (draft) {
return applyPatchesImpl(draft, patches.slice(i + 1));
});
};
return Immer;
}();
function createProxy(immer, value, parent) {
// precondition: createProxy should be guarded by isDraftable, so we know we can safely draft
var draft = isMap(value) ? getPlugin("MapSet").proxyMap_(value, parent) : isSet(value) ? getPlugin("MapSet").proxySet_(value, parent) : immer.useProxies_ ? createProxyProxy(value, parent) : getPlugin("ES5").createES5Proxy_(value, parent);
var scope = parent ? parent.scope_ : getCurrentScope();
scope.drafts_.push(draft);
return draft;
}
function current(value) {
if (!isDraft(value)) die(22, value);
return currentImpl(value);
}
function currentImpl(value) {
if (!isDraftable(value)) return value;
var state = value[DRAFT_STATE];
var copy;
var archType = getArchtype(value);
if (state) {
if (!state.modified_ && (state.type_ < 4 || !getPlugin("ES5").hasChanges_(state))) return state.base_; // Optimization: avoid generating new drafts during copying
state.finalized_ = true;
copy = copyHelper(value, archType);
state.finalized_ = false;
} else {
copy = copyHelper(value, archType);
}
each(copy, function (key, childValue) {
if (state && get(state.base_, key) === childValue) return; // no need to copy or search in something that didn't change
set(copy, key, currentImpl(childValue));
}); // In the future, we might consider freezing here, based on the current settings
return archType === ArchtypeSet ? new Set(copy) : copy;
}
function copyHelper(value, archType) {
// creates a shallow copy, even if it is a map or set
switch (archType) {
case ArchtypeMap:
return new Map(value);
case ArchtypeSet:
// Set will be cloned as array temporarily, so that we can replace individual items
return Array.from(value);
}
return shallowCopy(value);
}
function enableES5() {
function willFinalizeES5_(scope, result, isReplaced) {
if (!isReplaced) {
if (scope.patches_) {
markChangesRecursively(scope.drafts_[0]);
} // This is faster when we don't care about which attributes changed.
markChangesSweep(scope.drafts_);
} // When a child draft is returned, look for changes.
else if (isDraft(result) && result[DRAFT_STATE].scope_ === scope) {
markChangesSweep(scope.drafts_);
}
}
function createES5Draft(isArray, base) {
if (isArray) {
var draft = new Array(base.length);
for (var i = 0; i < base.length; i++) {
Object.defineProperty(draft, "" + i, proxyProperty(i, true));
}
return draft;
} else {
var _descriptors = getOwnPropertyDescriptors(base);
delete _descriptors[DRAFT_STATE];
var keys = ownKeys(_descriptors);
for (var _i = 0; _i < keys.length; _i++) {
var key = keys[_i];
_descriptors[key] = proxyProperty(key, isArray || !!_descriptors[key].enumerable);
}
return Object.create(Object.getPrototypeOf(base), _descriptors);
}
}
function createES5Proxy_(base, parent) {
var isArray = Array.isArray(base);
var draft = createES5Draft(isArray, base);
var state = {
type_: isArray ? ProxyTypeES5Array : ProxyTypeES5Object,
scope_: parent ? parent.scope_ : getCurrentScope(),
modified_: false,
finalized_: false,
assigned_: {},
parent_: parent,
// base is the object we are drafting
base_: base,
// draft is the draft object itself, that traps all reads and reads from either the base (if unmodified) or copy (if modified)
draft_: draft,
copy_: null,
revoked_: false,
isManual_: false
};
Object.defineProperty(draft, DRAFT_STATE, {
value: state,
// enumerable: false <- the default
writable: true
});
return draft;
} // property descriptors are recycled to make sure we don't create a get and set closure per property,
// but share them all instead
var descriptors = {};
function proxyProperty(prop, enumerable) {
var desc = descriptors[prop];
if (desc) {
desc.enumerable = enumerable;
} else {
descriptors[prop] = desc = {
configurable: true,
enumerable: enumerable,
get: function get() {
var state = this[DRAFT_STATE];
assertUnrevoked(state); // @ts-ignore
return objectTraps.get(state, prop);
},
set: function set(value) {
var state = this[DRAFT_STATE];
assertUnrevoked(state); // @ts-ignore
objectTraps.set(state, prop, value);
}
};
}
return desc;
} // This looks expensive, but only proxies are visited, and only objects without known changes are scanned.
function markChangesSweep(drafts) {
// The natural order of drafts in the `scope` array is based on when they
// were accessed. By processing drafts in reverse natural order, we have a
// better chance of processing leaf nodes first. When a leaf node is known to
// have changed, we can avoid any traversal of its ancestor nodes.
for (var i = drafts.length - 1; i >= 0; i--) {
var state = drafts[i][DRAFT_STATE];
if (!state.modified_) {
switch (state.type_) {
case ProxyTypeES5Array:
if (hasArrayChanges(state)) markChanged(state);
break;
case ProxyTypeES5Object:
if (hasObjectChanges(state)) markChanged(state);
break;
}
}
}
}
function markChangesRecursively(object) {
if (!object || typeof object !== "object") return;
var state = object[DRAFT_STATE];
if (!state) return;
var base_ = state.base_,
draft_ = state.draft_,
assigned_ = state.assigned_,
type_ = state.type_;
if (type_ === ProxyTypeES5Object) {
// Look for added keys.
// probably there is a faster way to detect changes, as sweep + recurse seems to do some
// unnecessary work.
// also: probably we can store the information we detect here, to speed up tree finalization!
each(draft_, function (key) {
if (key === DRAFT_STATE) return; // The `undefined` check is a fast path for pre-existing keys.
if (base_[key] === undefined && !has(base_, key)) {
assigned_[key] = true;
markChanged(state);
} else if (!assigned_[key]) {
// Only untouched properties trigger recursion.
markChangesRecursively(draft_[key]);
}
}); // Look for removed keys.
each(base_, function (key) {
// The `undefined` check is a fast path for pre-existing keys.
if (draft_[key] === undefined && !has(draft_, key)) {
assigned_[key] = false;
markChanged(state);
}
});
} else if (type_ === ProxyTypeES5Array) {
if (hasArrayChanges(state)) {
markChanged(state);
assigned_.length = true;
}
if (draft_.length < base_.length) {
for (var i = draft_.length; i < base_.length; i++) {
assigned_[i] = false;
}
} else {
for (var _i2 = base_.length; _i2 < draft_.length; _i2++) {
assigned_[_i2] = true;
}
} // Minimum count is enough, the other parts has been processed.
var min = Math.min(draft_.length, base_.length);
for (var _i3 = 0; _i3 < min; _i3++) {
// Only untouched indices trigger recursion.
if (assigned_[_i3] === undefined) markChangesRecursively(draft_[_i3]);
}
}
}
function hasObjectChanges(state) {
var base_ = state.base_,
draft_ = state.draft_; // Search for added keys and changed keys. Start at the back, because
// non-numeric keys are ordered by time of definition on the object.
var keys = ownKeys(draft_);
for (var i = keys.length - 1; i >= 0; i--) {
var key = keys[i];
if (key === DRAFT_STATE) continue;
var baseValue = base_[key]; // The `undefined` check is a fast path for pre-existing keys.
if (baseValue === undefined && !has(base_, key)) {
return true;
} // Once a base key is deleted, future changes go undetected, because its
// descriptor is erased. This branch detects any missed changes.
else {
var value = draft_[key];
var _state = value && value[DRAFT_STATE];
if (_state ? _state.base_ !== baseValue : !is(value, baseValue)) {
return true;
}
}
} // At this point, no keys were added or changed.
// Compare key count to determine if keys were deleted.
var baseIsDraft = !!base_[DRAFT_STATE];
return keys.length !== ownKeys(base_).length + (baseIsDraft ? 0 : 1); // + 1 to correct for DRAFT_STATE
}
function hasArrayChanges(state) {
var draft_ = state.draft_;
if (draft_.length !== state.base_.length) return true; // See #116
// If we first shorten the length, our array interceptors will be removed.
// If after that new items are added, result in the same original length,
// those last items will have no intercepting property.
// So if there is no own descriptor on the last position, we know that items were removed and added
// N.B.: splice, unshift, etc only shift values around, but not prop descriptors, so we only have to check
// the last one
var descriptor = Object.getOwnPropertyDescriptor(draft_, draft_.length - 1); // descriptor can be null, but only for newly created sparse arrays, eg. new Array(10)
if (descriptor && !descriptor.get) return true; // For all other cases, we don't have to compare, as they would have been picked up by the index setters
return false;
}
function hasChanges_(state) {
return state.type_ === ProxyTypeES5Object ? hasObjectChanges(state) : hasArrayChanges(state);
}
function assertUnrevoked(state
/*ES5State | MapState | SetState*/
) {
if (state.revoked_) die(3, JSON.stringify(latest(state)));
}
loadPlugin("ES5", {
createES5Proxy_: createES5Proxy_,
willFinalizeES5_: willFinalizeES5_,
hasChanges_: hasChanges_
});
}
function enablePatches() {
var REPLACE = "replace";
var ADD = "add";
var REMOVE = "remove";
function generatePatches_(state, basePath, patches, inversePatches) {
switch (state.type_) {
case ProxyTypeProxyObject:
case ProxyTypeES5Object:
case ProxyTypeMap:
return generatePatchesFromAssigned(state, basePath, patches, inversePatches);
case ProxyTypeES5Array:
case ProxyTypeProxyArray:
return generateArrayPatches(state, basePath, patches, inversePatches);
case ProxyTypeSet:
return generateSetPatches(state, basePath, patches, inversePatches);
}
}
function generateArrayPatches(state, basePath, patches, inversePatches) {
var base_ = state.base_,
assigned_ = state.assigned_;
var copy_ = state.copy_; // Reduce complexity by ensuring `base` is never longer.
if (copy_.length < base_.length) {
var _ref = [copy_, base_];
base_ = _ref[0];
copy_ = _ref[1];
var _ref2 = [inversePatches, patches];
patches = _ref2[0];
inversePatches = _ref2[1];
} // Process replaced indices.
for (var i = 0; i < base_.length; i++) {
if (assigned_[i] && copy_[i] !== base_[i]) {
var path = basePath.concat([i]);
patches.push({
op: REPLACE,
path: path,
// Need to maybe clone it, as it can in fact be the original value
// due to the base/copy inversion at the start of this function
value: clonePatchValueIfNeeded(copy_[i])
});
inversePatches.push({
op: REPLACE,
path: path,
value: clonePatchValueIfNeeded(base_[i])
});
}
} // Process added indices.
for (var _i = base_.length; _i < copy_.length; _i++) {
var _path = basePath.concat([_i]);
patches.push({
op: ADD,
path: _path,
// Need to maybe clone it, as it can in fact be the original value
// due to the base/copy inversion at the start of this function
value: clonePatchValueIfNeeded(copy_[_i])
});
}
if (base_.length < copy_.length) {
inversePatches.push({
op: REPLACE,
path: basePath.concat(["length"]),
value: base_.length
});
}
} // This is used for both Map objects and normal objects.
function generatePatchesFromAssigned(state, basePath, patches, inversePatches) {
var base_ = state.base_,
copy_ = state.copy_;
each(state.assigned_, function (key, assignedValue) {
var origValue = get(base_, key);
var value = get(copy_, key);
var op = !assignedValue ? REMOVE : has(base_, key) ? REPLACE : ADD;
if (origValue === value && op === REPLACE) return;
var path = basePath.concat(key);
patches.push(op === REMOVE ? {
op: op,
path: path
} : {
op: op,
path: path,
value: value
});
inversePatches.push(op === ADD ? {
op: REMOVE,
path: path
} : op === REMOVE ? {
op: ADD,
path: path,
value: clonePatchValueIfNeeded(origValue)
} : {
op: REPLACE,
path: path,
value: clonePatchValueIfNeeded(origValue)
});
});
}
function generateSetPatches(state, basePath, patches, inversePatches) {
var base_ = state.base_,
copy_ = state.copy_;
var i = 0;
base_.forEach(function (value) {
if (!copy_.has(value)) {
var path = basePath.concat([i]);
patches.push({
op: REMOVE,
path: path,
value: value
});
inversePatches.unshift({
op: ADD,
path: path,
value: value
});
}
i++;
});
i = 0;
copy_.forEach(function (value) {
if (!base_.has(value)) {
var path = basePath.concat([i]);
patches.push({
op: ADD,
path: path,
value: value
});
inversePatches.unshift({
op: REMOVE,
path: path,
value: value
});
}
i++;
});
}
function generateReplacementPatches_(rootState, replacement, patches, inversePatches) {
patches.push({
op: REPLACE,
path: [],
value: replacement
});
inversePatches.push({
op: REPLACE,
path: [],
value: rootState.base_
});
}
function applyPatches_(draft, patches) {
patches.forEach(function (patch) {
var path = patch.path,
op = patch.op;
var base = draft;
for (var i = 0; i < path.length - 1; i++) {
base = get(base, path[i]);
if (typeof base !== "object") die(15, path.join("/"));
}
var type = getArchtype(base);
var value = deepClonePatchValue(patch.value); // used to clone patch to ensure original patch is not modified, see #411
var key = path[path.length - 1];
switch (op) {
case REPLACE:
switch (type) {
case ArchtypeMap:
return base.set(key, value);
/* istanbul ignore next */
case ArchtypeSet:
die(16);
default:
// if value is an object, then it's assigned by reference
// in the following add or remove ops, the value field inside the patch will also be modifyed
// so we use value from the cloned patch
// @ts-ignore
return base[key] = value;
}
case ADD:
switch (type) {
case ArchtypeArray:
return base.splice(key, 0, value);
case ArchtypeMap:
return base.set(key, value);
case ArchtypeSet:
return base.add(value);
default:
return base[key] = value;
}
case REMOVE:
switch (type) {
case ArchtypeArray:
return base.splice(key, 1);
case ArchtypeMap:
return base.delete(key);
case ArchtypeSet:
return base.delete(patch.value);
default:
return delete base[key];
}
default:
die(17, op);
}
});
return draft;
}
function deepClonePatchValue(obj) {
if (!isDraftable(obj)) return obj;
if (Array.isArray(obj)) return obj.map(deepClonePatchValue);
if (isMap(obj)) return new Map(Array.from(obj.entries()).map(function (_ref3) {
var k = _ref3[0],
v = _ref3[1];
return [k, deepClonePatchValue(v)];
}));
if (isSet(obj)) return new Set(Array.from(obj).map(deepClonePatchValue));
var cloned = Object.create(Object.getPrototypeOf(obj));
for (var key in obj) {
cloned[key] = deepClonePatchValue(obj[key]);
}
return cloned;
}
function clonePatchValueIfNeeded(obj) {
if (isDraft(obj)) {
return deepClonePatchValue(obj);
} else return obj;
}
loadPlugin("Patches", {
applyPatches_: applyPatches_,
generatePatches_: generatePatches_,
generateReplacementPatches_: generateReplacementPatches_
});
}
// types only!
function enableMapSet() {
/* istanbul ignore next */
var _extendStatics = function extendStatics(d, b) {
_extendStatics = Object.setPrototypeOf || {
__proto__: []
} instanceof Array && function (d, b) {
d.__proto__ = b;
} || function (d, b) {
for (var p in b) {
if (b.hasOwnProperty(p)) d[p] = b[p];
}
};
return _extendStatics(d, b);
}; // Ugly hack to resolve #502 and inherit built in Map / Set
function __extends(d, b) {
_extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = ( // @ts-ignore
__.prototype = b.prototype, new __());
}
var DraftMap = function (_super) {
__extends(DraftMap, _super); // Create class manually, cause #502
function DraftMap(target, parent) {
this[DRAFT_STATE] = {
type_: ProxyTypeMap,
parent_: parent,
scope_: parent ? parent.scope_ : getCurrentScope(),
modified_: false,
finalized_: false,
copy_: undefined,
assigned_: undefined,
base_: target,
draft_: this,
isManual_: false,
revoked_: false
};
return this;
}
var p = DraftMap.prototype;
Object.defineProperty(p, "size", {
get: function get() {
return latest(this[DRAFT_STATE]).size;
} // enumerable: false,
// configurable: true
});
p.has = function (key) {
return latest(this[DRAFT_STATE]).has(key);
};
p.set = function (key, value) {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
if (!latest(state).has(key) || latest(state).get(key) !== value) {
prepareMapCopy(state);
markChanged(state);
state.assigned_.set(key, true);
state.copy_.set(key, value);
state.assigned_.set(key, true);
}
return this;
};
p.delete = function (key) {
if (!this.has(key)) {
return false;
}
var state = this[DRAFT_STATE];
assertUnrevoked(state);
prepareMapCopy(state);
markChanged(state);
state.assigned_.set(key, false);
state.copy_.delete(key);
return true;
};
p.clear = function () {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
if (latest(state).size) {
prepareMapCopy(state);
markChanged(state);
state.assigned_ = new Map();
each(state.base_, function (key) {
state.assigned_.set(key, false);
});
state.copy_.clear();
}
};
p.forEach = function (cb, thisArg) {
var _this = this;
var state = this[DRAFT_STATE];
latest(state).forEach(function (_value, key, _map) {
cb.call(thisArg, _this.get(key), key, _this);
});
};
p.get = function (key) {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
var value = latest(state).get(key);
if (state.finalized_ || !isDraftable(value)) {
return value;
}
if (value !== state.base_.get(key)) {
return value; // either already drafted or reassigned
} // despite what it looks, this creates a draft only once, see above condition
var draft = createProxy(state.scope_.immer_, value, state);
prepareMapCopy(state);
state.copy_.set(key, draft);
return draft;
};
p.keys = function () {
return latest(this[DRAFT_STATE]).keys();
};
p.values = function () {
var _this2 = this,
_ref;
var iterator = this.keys();
return _ref = {}, _ref[iteratorSymbol] = function () {
return _this2.values();
}, _ref.next = function next() {
var r = iterator.next();
/* istanbul ignore next */
if (r.done) return r;
var value = _this2.get(r.value);
return {
done: false,
value: value
};
}, _ref;
};
p.entries = function () {
var _this3 = this,
_ref2;
var iterator = this.keys();
return _ref2 = {}, _ref2[iteratorSymbol] = function () {
return _this3.entries();
}, _ref2.next = function next() {
var r = iterator.next();
/* istanbul ignore next */
if (r.done) return r;
var value = _this3.get(r.value);
return {
done: false,
value: [r.value, value]
};
}, _ref2;
};
p[iteratorSymbol] = function () {
return this.entries();
};
return DraftMap;
}(Map);
function proxyMap_(target, parent) {
// @ts-ignore
return new DraftMap(target, parent);
}
function prepareMapCopy(state) {
if (!state.copy_) {
state.assigned_ = new Map();
state.copy_ = new Map(state.base_);
}
}
var DraftSet = function (_super) {
__extends(DraftSet, _super); // Create class manually, cause #502
function DraftSet(target, parent) {
this[DRAFT_STATE] = {
type_: ProxyTypeSet,
parent_: parent,
scope_: parent ? parent.scope_ : getCurrentScope(),
modified_: false,
finalized_: false,
copy_: undefined,
base_: target,
draft_: this,
drafts_: new Map(),
revoked_: false,
isManual_: false
};
return this;
}
var p = DraftSet.prototype;
Object.defineProperty(p, "size", {
get: function get() {
return latest(this[DRAFT_STATE]).size;
} // enumerable: true,
});
p.has = function (value) {
var state = this[DRAFT_STATE];
assertUnrevoked(state); // bit of trickery here, to be able to recognize both the value, and the draft of its value
if (!state.copy_) {
return state.base_.has(value);
}
if (state.copy_.has(value)) return true;
if (state.drafts_.has(value) && state.copy_.has(state.drafts_.get(value))) return true;
return false;
};
p.add = function (value) {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
if (!this.has(value)) {
prepareSetCopy(state);
markChanged(state);
state.copy_.add(value);
}
return this;
};
p.delete = function (value) {
if (!this.has(value)) {
return false;
}
var state = this[DRAFT_STATE];
assertUnrevoked(state);
prepareSetCopy(state);
markChanged(state);
return state.copy_.delete(value) || (state.drafts_.has(value) ? state.copy_.delete(state.drafts_.get(value)) :
/* istanbul ignore next */
false);
};
p.clear = function () {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
if (latest(state).size) {
prepareSetCopy(state);
markChanged(state);
state.copy_.clear();
}
};
p.values = function () {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
prepareSetCopy(state);
return state.copy_.values();
};
p.entries = function entries() {
var state = this[DRAFT_STATE];
assertUnrevoked(state);
prepareSetCopy(state);
return state.copy_.entries();
};
p.keys = function () {
return this.values();
};
p[iteratorSymbol] = function () {
return this.values();
};
p.forEach = function forEach(cb, thisArg) {
var iterator = this.values();
var result = iterator.next();
while (!result.done) {
cb.call(thisArg, result.value, result.value, this);
result = iterator.next();
}
};
return DraftSet;
}(Set);
function proxySet_(target, parent) {
// @ts-ignore
return new DraftSet(target, parent);
}
function prepareSetCopy(state) {
if (!state.copy_) {
// create drafts for all entries to preserve insertion order
state.copy_ = new Set();
state.base_.forEach(function (value) {
if (isDraftable(value)) {
var draft = createProxy(state.scope_.immer_, value, state);
state.drafts_.set(value, draft);
state.copy_.add(draft);
} else {
state.copy_.add(value);
}
});
}
}
function assertUnrevoked(state
/*ES5State | MapState | SetState*/
) {
if (state.revoked_) die(3, JSON.stringify(latest(state)));
}
loadPlugin("MapSet", {
proxyMap_: proxyMap_,
proxySet_: proxySet_
});
}
function enableAllPlugins() {
enableES5();
enableMapSet();
enablePatches();
}
var immer =
/*#__PURE__*/
new Immer();
/**
* The `produce` function takes a value and a "recipe function" (whose
* return value often depends on the base state). The recipe function is
* free to mutate its first argument however it wants. All mutations are
* only ever applied to a __copy__ of the base state.
*
* Pass only a function to create a "curried producer" which relieves you
* from passing the recipe function every time.
*
* Only plain objects and arrays are made mutable. All other objects are
* considered uncopyable.
*
* Note: This function is __bound__ to its `Immer` instance.
*
* @param {any} base - the initial state
* @param {Function} producer - function that receives a proxy of the base state as first argument and which can be freely modified
* @param {Function} patchListener - optional function that will be called with all the patches produced here
* @returns {any} a new state, or the initial state if nothing was modified
*/
var produce = immer.produce;
/**
* Like `produce`, but `produceWithPatches` always returns a tuple
* [nextState, patches, inversePatches] (instead of just the next state)
*/
var produceWithPatches =
/*#__PURE__*/
immer.produceWithPatches.bind(immer);
/**
* Pass true to automatically freeze all copies created by Immer.
*
* By default, auto-freezing is disabled in production.
*/
var setAutoFreeze =
/*#__PURE__*/
immer.setAutoFreeze.bind(immer);
/**
* Pass true to use the ES2015 `Proxy` class when creating drafts, which is
* always faster than using ES5 proxies.
*
* By default, feature detection is used, so calling this is rarely necessary.
*/
var setUseProxies =
/*#__PURE__*/
immer.setUseProxies.bind(immer);
/**
* Apply an array of Immer patches to the first argument.
*
* This function is a producer, which means copy-on-write is in effect.
*/
var applyPatches =
/*#__PURE__*/
immer.applyPatches.bind(immer);
/**
* Create an Immer draft from the given base state, which may be a draft itself.
* The draft can be modified until you finalize it with the `finishDraft` function.
*/
var createDraft =
/*#__PURE__*/
immer.createDraft.bind(immer);
/**
* Finalize an Immer draft from a `createDraft` call, returning the base state
* (if no changes were made) or a modified copy. The draft must *not* be
* mutated afterwards.
*
* Pass a function as the 2nd argument to generate Immer patches based on the
* changes that were made.
*/
var finishDraft =
/*#__PURE__*/
immer.finishDraft.bind(immer);
/**
* This function is actually a no-op, but can be used to cast an immutable type
* to an draft type and make TypeScript happy
*
* @param value
*/
function castDraft(value) {
return value;
}
/**
* This function is actually a no-op, but can be used to cast a mutable type
* to an immutable type and make TypeScript happy
* @param value
*/
function castImmutable(value) {
return value;
}
immer_cjs_development.Immer = Immer;
immer_cjs_development.applyPatches = applyPatches;
immer_cjs_development.castDraft = castDraft;
immer_cjs_development.castImmutable = castImmutable;
immer_cjs_development.createDraft = createDraft;
immer_cjs_development.current = current;
immer_cjs_development.default = produce;
immer_cjs_development.enableAllPlugins = enableAllPlugins;
immer_cjs_development.enableES5 = enableES5;
var enableMapSet_1 = immer_cjs_development.enableMapSet = enableMapSet;
immer_cjs_development.enablePatches = enablePatches;
immer_cjs_development.finishDraft = finishDraft;
immer_cjs_development.immerable = DRAFTABLE;
immer_cjs_development.isDraft = isDraft;
immer_cjs_development.isDraftable = isDraftable;
immer_cjs_development.nothing = NOTHING;
immer_cjs_development.original = original;
var produce_1 = immer_cjs_development.produce = produce;
immer_cjs_development.produceWithPatches = produceWithPatches;
var setAutoFreeze_1 = immer_cjs_development.setAutoFreeze = setAutoFreeze;
immer_cjs_development.setUseProxies = setUseProxies;
var rtc = {exports: {}};
/**
*
* Copyright (c) 2018 Apple (http://www.apple.com)
*
* 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.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
(function (module, exports) {
/*! Modules included in this bundle:
* name: process
* license: MIT
* version: 0.11.10
* text:
* (The MIT License)
*
* Copyright (c) 2013 Roman Shtylman
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
* name: semver
* license: ISC
* version: 5.5.0
* text:
* The ISC License
*
* Copyright (c) Isaac Z. Schlueter and Contributors
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*
* name: webpack
* license: MIT
* version: 4.41.2
* text:
* Copyright JS Foundation and other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*/
(function webpackUniversalModuleDefinition(root, factory) {
module.exports = factory();
})(commonjsGlobal, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/rtc_reporting/reporting_agent.ts");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./node_modules/process/browser.js":
/*!*****************************************!*\
!*** ./node_modules/process/browser.js ***!
\*****************************************/
/*! no static exports found */
/***/ (function(module, exports) {
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ());
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] };
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
/***/ }),
/***/ "./node_modules/semver/semver.js":
/*!***************************************!*\
!*** ./node_modules/semver/semver.js ***!
\***************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {exports = module.exports = SemVer;
// The debug function is excluded entirely from the minified version.
/* nomin */ var debug;
/* nomin */ if (typeof process === 'object' &&
/* nomin */ process.env &&
/* nomin */ process.env.NODE_DEBUG &&
/* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG))
/* nomin */ debug = function() {
/* nomin */ var args = Array.prototype.slice.call(arguments, 0);
/* nomin */ args.unshift('SEMVER');
/* nomin */ console.log.apply(console, args);
/* nomin */ };
/* nomin */ else
/* nomin */ debug = function() {};
// Note: this is the semver.org version of the spec that it implements
// Not necessarily the package version of this code.
exports.SEMVER_SPEC_VERSION = '2.0.0';
var MAX_LENGTH = 256;
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
// Max safe segment length for coercion.
var MAX_SAFE_COMPONENT_LENGTH = 16;
// The actual regexps go on exports.re
var re = exports.re = [];
var src = exports.src = [];
var R = 0;
// The following Regular Expressions can be used for tokenizing,
// validating, and parsing SemVer version strings.
// ## Numeric Identifier
// A single `0`, or a non-zero digit followed by zero or more digits.
var NUMERICIDENTIFIER = R++;
src[NUMERICIDENTIFIER] = '0|[1-9]\\d*';
var NUMERICIDENTIFIERLOOSE = R++;
src[NUMERICIDENTIFIERLOOSE] = '[0-9]+';
// ## Non-numeric Identifier
// Zero or more digits, followed by a letter or hyphen, and then zero or
// more letters, digits, or hyphens.
var NONNUMERICIDENTIFIER = R++;
src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*';
// ## Main Version
// Three dot-separated numeric identifiers.
var MAINVERSION = R++;
src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' +
'(' + src[NUMERICIDENTIFIER] + ')\\.' +
'(' + src[NUMERICIDENTIFIER] + ')';
var MAINVERSIONLOOSE = R++;
src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
'(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
'(' + src[NUMERICIDENTIFIERLOOSE] + ')';
// ## Pre-release Version Identifier
// A numeric identifier, or a non-numeric identifier.
var PRERELEASEIDENTIFIER = R++;
src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +
'|' + src[NONNUMERICIDENTIFIER] + ')';
var PRERELEASEIDENTIFIERLOOSE = R++;
src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +
'|' + src[NONNUMERICIDENTIFIER] + ')';
// ## Pre-release Version
// Hyphen, followed by one or more dot-separated pre-release version
// identifiers.
var PRERELEASE = R++;
src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +
'(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))';
var PRERELEASELOOSE = R++;
src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
'(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))';
// ## Build Metadata Identifier
// Any combination of digits, letters, or hyphens.
var BUILDIDENTIFIER = R++;
src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+';
// ## Build Metadata
// Plus sign, followed by one or more period-separated build metadata
// identifiers.
var BUILD = R++;
src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
'(?:\\.' + src[BUILDIDENTIFIER] + ')*))';
// ## Full Version String
// A main version, followed optionally by a pre-release version and
// build metadata.
// Note that the only major, minor, patch, and pre-release sections of
// the version string are capturing groups. The build metadata is not a
// capturing group, because it should not ever be used in version
// comparison.
var FULL = R++;
var FULLPLAIN = 'v?' + src[MAINVERSION] +
src[PRERELEASE] + '?' +
src[BUILD] + '?';
src[FULL] = '^' + FULLPLAIN + '$';
// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
// common in the npm registry.
var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] +
src[PRERELEASELOOSE] + '?' +
src[BUILD] + '?';
var LOOSE = R++;
src[LOOSE] = '^' + LOOSEPLAIN + '$';
var GTLT = R++;
src[GTLT] = '((?:<|>)?=?)';
// Something like "2.*" or "1.2.x".
// Note that "x.x" is a valid xRange identifer, meaning "any version"
// Only the first item is strictly required.
var XRANGEIDENTIFIERLOOSE = R++;
src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*';
var XRANGEIDENTIFIER = R++;
src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*';
var XRANGEPLAIN = R++;
src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' +
'(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
'(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
'(?:' + src[PRERELEASE] + ')?' +
src[BUILD] + '?' +
')?)?';
var XRANGEPLAINLOOSE = R++;
src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
'(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
'(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
'(?:' + src[PRERELEASELOOSE] + ')?' +
src[BUILD] + '?' +
')?)?';
var XRANGE = R++;
src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$';
var XRANGELOOSE = R++;
src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$';
// Coercion.
// Extract anything that could conceivably be a part of a valid semver
var COERCE = R++;
src[COERCE] = '(?:^|[^\\d])' +
'(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' +
'(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
'(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
'(?:$|[^\\d])';
// Tilde ranges.
// Meaning is "reasonably at or greater than"
var LONETILDE = R++;
src[LONETILDE] = '(?:~>?)';
var TILDETRIM = R++;
src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+';
re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g');
var tildeTrimReplace = '$1~';
var TILDE = R++;
src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$';
var TILDELOOSE = R++;
src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$';
// Caret ranges.
// Meaning is "at least and backwards compatible with"
var LONECARET = R++;
src[LONECARET] = '(?:\\^)';
var CARETTRIM = R++;
src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+';
re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g');
var caretTrimReplace = '$1^';
var CARET = R++;
src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$';
var CARETLOOSE = R++;
src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$';
// A simple gt/lt/eq thing, or just "" to indicate "any version"
var COMPARATORLOOSE = R++;
src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$';
var COMPARATOR = R++;
src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$';
// An expression to strip any whitespace between the gtlt and the thing
// it modifies, so that `> 1.2.3` ==> `>1.2.3`
var COMPARATORTRIM = R++;
src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
'\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')';
// this one has to use the /g flag
re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g');
var comparatorTrimReplace = '$1$2$3';
// Something like `1.2.3 - 1.2.4`
// Note that these all use the loose form, because they'll be
// checked against either the strict or loose comparator form
// later.
var HYPHENRANGE = R++;
src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' +
'\\s+-\\s+' +
'(' + src[XRANGEPLAIN] + ')' +
'\\s*$';
var HYPHENRANGELOOSE = R++;
src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' +
'\\s+-\\s+' +
'(' + src[XRANGEPLAINLOOSE] + ')' +
'\\s*$';
// Star ranges basically just allow anything at all.
var STAR = R++;
src[STAR] = '(<|>)?=?\\s*\\*';
// Compile to actual regexp objects.
// All are flag-free, unless they were created above with a flag.
for (var i = 0; i < R; i++) {
debug(i, src[i]);
if (!re[i])
re[i] = new RegExp(src[i]);
}
exports.parse = parse;
function parse(version, loose) {
if (version instanceof SemVer)
return version;
if (typeof version !== 'string')
return null;
if (version.length > MAX_LENGTH)
return null;
var r = loose ? re[LOOSE] : re[FULL];
if (!r.test(version))
return null;
try {
return new SemVer(version, loose);
} catch (er) {
return null;
}
}
exports.valid = valid;
function valid(version, loose) {
var v = parse(version, loose);
return v ? v.version : null;
}
exports.clean = clean;
function clean(version, loose) {
var s = parse(version.trim().replace(/^[=v]+/, ''), loose);
return s ? s.version : null;
}
exports.SemVer = SemVer;
function SemVer(version, loose) {
if (version instanceof SemVer) {
if (version.loose === loose)
return version;
else
version = version.version;
} else if (typeof version !== 'string') {
throw new TypeError('Invalid Version: ' + version);
}
if (version.length > MAX_LENGTH)
throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters')
if (!(this instanceof SemVer))
return new SemVer(version, loose);
debug('SemVer', version, loose);
this.loose = loose;
var m = version.trim().match(loose ? re[LOOSE] : re[FULL]);
if (!m)
throw new TypeError('Invalid Version: ' + version);
this.raw = version;
// these are actually numbers
this.major = +m[1];
this.minor = +m[2];
this.patch = +m[3];
if (this.major > MAX_SAFE_INTEGER || this.major < 0)
throw new TypeError('Invalid major version')
if (this.minor > MAX_SAFE_INTEGER || this.minor < 0)
throw new TypeError('Invalid minor version')
if (this.patch > MAX_SAFE_INTEGER || this.patch < 0)
throw new TypeError('Invalid patch version')
// numberify any prerelease numeric ids
if (!m[4])
this.prerelease = [];
else
this.prerelease = m[4].split('.').map(function(id) {
if (/^[0-9]+$/.test(id)) {
var num = +id;
if (num >= 0 && num < MAX_SAFE_INTEGER)
return num;
}
return id;
});
this.build = m[5] ? m[5].split('.') : [];
this.format();
}
SemVer.prototype.format = function() {
this.version = this.major + '.' + this.minor + '.' + this.patch;
if (this.prerelease.length)
this.version += '-' + this.prerelease.join('.');
return this.version;
};
SemVer.prototype.toString = function() {
return this.version;
};
SemVer.prototype.compare = function(other) {
debug('SemVer.compare', this.version, this.loose, other);
if (!(other instanceof SemVer))
other = new SemVer(other, this.loose);
return this.compareMain(other) || this.comparePre(other);
};
SemVer.prototype.compareMain = function(other) {
if (!(other instanceof SemVer))
other = new SemVer(other, this.loose);
return compareIdentifiers(this.major, other.major) ||
compareIdentifiers(this.minor, other.minor) ||
compareIdentifiers(this.patch, other.patch);
};
SemVer.prototype.comparePre = function(other) {
if (!(other instanceof SemVer))
other = new SemVer(other, this.loose);
// NOT having a prerelease is > having one
if (this.prerelease.length && !other.prerelease.length)
return -1;
else if (!this.prerelease.length && other.prerelease.length)
return 1;
else if (!this.prerelease.length && !other.prerelease.length)
return 0;
var i = 0;
do {
var a = this.prerelease[i];
var b = other.prerelease[i];
debug('prerelease compare', i, a, b);
if (a === undefined && b === undefined)
return 0;
else if (b === undefined)
return 1;
else if (a === undefined)
return -1;
else if (a === b)
continue;
else
return compareIdentifiers(a, b);
} while (++i);
};
// preminor will bump the version up to the next minor release, and immediately
// down to pre-release. premajor and prepatch work the same way.
SemVer.prototype.inc = function(release, identifier) {
switch (release) {
case 'premajor':
this.prerelease.length = 0;
this.patch = 0;
this.minor = 0;
this.major++;
this.inc('pre', identifier);
break;
case 'preminor':
this.prerelease.length = 0;
this.patch = 0;
this.minor++;
this.inc('pre', identifier);
break;
case 'prepatch':
// If this is already a prerelease, it will bump to the next version
// drop any prereleases that might already exist, since they are not
// relevant at this point.
this.prerelease.length = 0;
this.inc('patch', identifier);
this.inc('pre', identifier);
break;
// If the input is a non-prerelease version, this acts the same as
// prepatch.
case 'prerelease':
if (this.prerelease.length === 0)
this.inc('patch', identifier);
this.inc('pre', identifier);
break;
case 'major':
// If this is a pre-major version, bump up to the same major version.
// Otherwise increment major.
// 1.0.0-5 bumps to 1.0.0
// 1.1.0 bumps to 2.0.0
if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0)
this.major++;
this.minor = 0;
this.patch = 0;
this.prerelease = [];
break;
case 'minor':
// If this is a pre-minor version, bump up to the same minor version.
// Otherwise increment minor.
// 1.2.0-5 bumps to 1.2.0
// 1.2.1 bumps to 1.3.0
if (this.patch !== 0 || this.prerelease.length === 0)
this.minor++;
this.patch = 0;
this.prerelease = [];
break;
case 'patch':
// If this is not a pre-release version, it will increment the patch.
// If it is a pre-release it will bump up to the same patch version.
// 1.2.0-5 patches to 1.2.0
// 1.2.0 patches to 1.2.1
if (this.prerelease.length === 0)
this.patch++;
this.prerelease = [];
break;
// This probably shouldn't be used publicly.
// 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
case 'pre':
if (this.prerelease.length === 0)
this.prerelease = [0];
else {
var i = this.prerelease.length;
while (--i >= 0) {
if (typeof this.prerelease[i] === 'number') {
this.prerelease[i]++;
i = -2;
}
}
if (i === -1) // didn't increment anything
this.prerelease.push(0);
}
if (identifier) {
// 1.2.0-beta.1 bumps to 1.2.0-beta.2,
// 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
if (this.prerelease[0] === identifier) {
if (isNaN(this.prerelease[1]))
this.prerelease = [identifier, 0];
} else
this.prerelease = [identifier, 0];
}
break;
default:
throw new Error('invalid increment argument: ' + release);
}
this.format();
this.raw = this.version;
return this;
};
exports.inc = inc;
function inc(version, release, loose, identifier) {
if (typeof(loose) === 'string') {
identifier = loose;
loose = undefined;
}
try {
return new SemVer(version, loose).inc(release, identifier).version;
} catch (er) {
return null;
}
}
exports.diff = diff;
function diff(version1, version2) {
if (eq(version1, version2)) {
return null;
} else {
var v1 = parse(version1);
var v2 = parse(version2);
if (v1.prerelease.length || v2.prerelease.length) {
for (var key in v1) {
if (key === 'major' || key === 'minor' || key === 'patch') {
if (v1[key] !== v2[key]) {
return 'pre'+key;
}
}
}
return 'prerelease';
}
for (var key in v1) {
if (key === 'major' || key === 'minor' || key === 'patch') {
if (v1[key] !== v2[key]) {
return key;
}
}
}
}
}
exports.compareIdentifiers = compareIdentifiers;
var numeric = /^[0-9]+$/;
function compareIdentifiers(a, b) {
var anum = numeric.test(a);
var bnum = numeric.test(b);
if (anum && bnum) {
a = +a;
b = +b;
}
return (anum && !bnum) ? -1 :
(bnum && !anum) ? 1 :
a < b ? -1 :
a > b ? 1 :
0;
}
exports.rcompareIdentifiers = rcompareIdentifiers;
function rcompareIdentifiers(a, b) {
return compareIdentifiers(b, a);
}
exports.major = major;
function major(a, loose) {
return new SemVer(a, loose).major;
}
exports.minor = minor;
function minor(a, loose) {
return new SemVer(a, loose).minor;
}
exports.patch = patch;
function patch(a, loose) {
return new SemVer(a, loose).patch;
}
exports.compare = compare;
function compare(a, b, loose) {
return new SemVer(a, loose).compare(new SemVer(b, loose));
}
exports.compareLoose = compareLoose;
function compareLoose(a, b) {
return compare(a, b, true);
}
exports.rcompare = rcompare;
function rcompare(a, b, loose) {
return compare(b, a, loose);
}
exports.sort = sort;
function sort(list, loose) {
return list.sort(function(a, b) {
return exports.compare(a, b, loose);
});
}
exports.rsort = rsort;
function rsort(list, loose) {
return list.sort(function(a, b) {
return exports.rcompare(a, b, loose);
});
}
exports.gt = gt;
function gt(a, b, loose) {
return compare(a, b, loose) > 0;
}
exports.lt = lt;
function lt(a, b, loose) {
return compare(a, b, loose) < 0;
}
exports.eq = eq;
function eq(a, b, loose) {
return compare(a, b, loose) === 0;
}
exports.neq = neq;
function neq(a, b, loose) {
return compare(a, b, loose) !== 0;
}
exports.gte = gte;
function gte(a, b, loose) {
return compare(a, b, loose) >= 0;
}
exports.lte = lte;
function lte(a, b, loose) {
return compare(a, b, loose) <= 0;
}
exports.cmp = cmp;
function cmp(a, op, b, loose) {
var ret;
switch (op) {
case '===':
if (typeof a === 'object') a = a.version;
if (typeof b === 'object') b = b.version;
ret = a === b;
break;
case '!==':
if (typeof a === 'object') a = a.version;
if (typeof b === 'object') b = b.version;
ret = a !== b;
break;
case '': case '=': case '==': ret = eq(a, b, loose); break;
case '!=': ret = neq(a, b, loose); break;
case '>': ret = gt(a, b, loose); break;
case '>=': ret = gte(a, b, loose); break;
case '<': ret = lt(a, b, loose); break;
case '<=': ret = lte(a, b, loose); break;
default: throw new TypeError('Invalid operator: ' + op);
}
return ret;
}
exports.Comparator = Comparator;
function Comparator(comp, loose) {
if (comp instanceof Comparator) {
if (comp.loose === loose)
return comp;
else
comp = comp.value;
}
if (!(this instanceof Comparator))
return new Comparator(comp, loose);
debug('comparator', comp, loose);
this.loose = loose;
this.parse(comp);
if (this.semver === ANY)
this.value = '';
else
this.value = this.operator + this.semver.version;
debug('comp', this);
}
var ANY = {};
Comparator.prototype.parse = function(comp) {
var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
var m = comp.match(r);
if (!m)
throw new TypeError('Invalid comparator: ' + comp);
this.operator = m[1];
if (this.operator === '=')
this.operator = '';
// if it literally is just '>' or '' then allow anything.
if (!m[2])
this.semver = ANY;
else
this.semver = new SemVer(m[2], this.loose);
};
Comparator.prototype.toString = function() {
return this.value;
};
Comparator.prototype.test = function(version) {
debug('Comparator.test', version, this.loose);
if (this.semver === ANY)
return true;
if (typeof version === 'string')
version = new SemVer(version, this.loose);
return cmp(version, this.operator, this.semver, this.loose);
};
Comparator.prototype.intersects = function(comp, loose) {
if (!(comp instanceof Comparator)) {
throw new TypeError('a Comparator is required');
}
var rangeTmp;
if (this.operator === '') {
rangeTmp = new Range(comp.value, loose);
return satisfies(this.value, rangeTmp, loose);
} else if (comp.operator === '') {
rangeTmp = new Range(this.value, loose);
return satisfies(comp.semver, rangeTmp, loose);
}
var sameDirectionIncreasing =
(this.operator === '>=' || this.operator === '>') &&
(comp.operator === '>=' || comp.operator === '>');
var sameDirectionDecreasing =
(this.operator === '<=' || this.operator === '<') &&
(comp.operator === '<=' || comp.operator === '<');
var sameSemVer = this.semver.version === comp.semver.version;
var differentDirectionsInclusive =
(this.operator === '>=' || this.operator === '<=') &&
(comp.operator === '>=' || comp.operator === '<=');
var oppositeDirectionsLessThan =
cmp(this.semver, '<', comp.semver, loose) &&
((this.operator === '>=' || this.operator === '>') &&
(comp.operator === '<=' || comp.operator === '<'));
var oppositeDirectionsGreaterThan =
cmp(this.semver, '>', comp.semver, loose) &&
((this.operator === '<=' || this.operator === '<') &&
(comp.operator === '>=' || comp.operator === '>'));
return sameDirectionIncreasing || sameDirectionDecreasing ||
(sameSemVer && differentDirectionsInclusive) ||
oppositeDirectionsLessThan || oppositeDirectionsGreaterThan;
};
exports.Range = Range;
function Range(range, loose) {
if (range instanceof Range) {
if (range.loose === loose) {
return range;
} else {
return new Range(range.raw, loose);
}
}
if (range instanceof Comparator) {
return new Range(range.value, loose);
}
if (!(this instanceof Range))
return new Range(range, loose);
this.loose = loose;
// First, split based on boolean or ||
this.raw = range;
this.set = range.split(/\s*\|\|\s*/).map(function(range) {
return this.parseRange(range.trim());
}, this).filter(function(c) {
// throw out any that are not relevant for whatever reason
return c.length;
});
if (!this.set.length) {
throw new TypeError('Invalid SemVer Range: ' + range);
}
this.format();
}
Range.prototype.format = function() {
this.range = this.set.map(function(comps) {
return comps.join(' ').trim();
}).join('||').trim();
return this.range;
};
Range.prototype.toString = function() {
return this.range;
};
Range.prototype.parseRange = function(range) {
var loose = this.loose;
range = range.trim();
debug('range', range, loose);
// `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE];
range = range.replace(hr, hyphenReplace);
debug('hyphen replace', range);
// `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace);
debug('comparator trim', range, re[COMPARATORTRIM]);
// `~ 1.2.3` => `~1.2.3`
range = range.replace(re[TILDETRIM], tildeTrimReplace);
// `^ 1.2.3` => `^1.2.3`
range = range.replace(re[CARETTRIM], caretTrimReplace);
// normalize spaces
range = range.split(/\s+/).join(' ');
// At this point, the range is completely trimmed and
// ready to be split into comparators.
var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR];
var set = range.split(' ').map(function(comp) {
return parseComparator(comp, loose);
}).join(' ').split(/\s+/);
if (this.loose) {
// in loose mode, throw out any that are not valid comparators
set = set.filter(function(comp) {
return !!comp.match(compRe);
});
}
set = set.map(function(comp) {
return new Comparator(comp, loose);
});
return set;
};
Range.prototype.intersects = function(range, loose) {
if (!(range instanceof Range)) {
throw new TypeError('a Range is required');
}
return this.set.some(function(thisComparators) {
return thisComparators.every(function(thisComparator) {
return range.set.some(function(rangeComparators) {
return rangeComparators.every(function(rangeComparator) {
return thisComparator.intersects(rangeComparator, loose);
});
});
});
});
};
// Mostly just for testing and legacy API reasons
exports.toComparators = toComparators;
function toComparators(range, loose) {
return new Range(range, loose).set.map(function(comp) {
return comp.map(function(c) {
return c.value;
}).join(' ').trim().split(' ');
});
}
// comprised of xranges, tildes, stars, and gtlt's at this point.
// already replaced the hyphen ranges
// turn into a set of JUST comparators.
function parseComparator(comp, loose) {
debug('comp', comp);
comp = replaceCarets(comp, loose);
debug('caret', comp);
comp = replaceTildes(comp, loose);
debug('tildes', comp);
comp = replaceXRanges(comp, loose);
debug('xrange', comp);
comp = replaceStars(comp, loose);
debug('stars', comp);
return comp;
}
function isX(id) {
return !id || id.toLowerCase() === 'x' || id === '*';
}
// ~, ~> --> * (any, kinda silly)
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
function replaceTildes(comp, loose) {
return comp.trim().split(/\s+/).map(function(comp) {
return replaceTilde(comp, loose);
}).join(' ');
}
function replaceTilde(comp, loose) {
var r = loose ? re[TILDELOOSE] : re[TILDE];
return comp.replace(r, function(_, M, m, p, pr) {
debug('tilde', comp, _, M, m, p, pr);
var ret;
if (isX(M))
ret = '';
else if (isX(m))
ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
else if (isX(p))
// ~1.2 == >=1.2.0 <1.3.0
ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
else if (pr) {
debug('replaceTilde pr', pr);
if (pr.charAt(0) !== '-')
pr = '-' + pr;
ret = '>=' + M + '.' + m + '.' + p + pr +
' <' + M + '.' + (+m + 1) + '.0';
} else
// ~1.2.3 == >=1.2.3 <1.3.0
ret = '>=' + M + '.' + m + '.' + p +
' <' + M + '.' + (+m + 1) + '.0';
debug('tilde return', ret);
return ret;
});
}
// ^ --> * (any, kinda silly)
// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
// ^1.2.3 --> >=1.2.3 <2.0.0
// ^1.2.0 --> >=1.2.0 <2.0.0
function replaceCarets(comp, loose) {
return comp.trim().split(/\s+/).map(function(comp) {
return replaceCaret(comp, loose);
}).join(' ');
}
function replaceCaret(comp, loose) {
debug('caret', comp, loose);
var r = loose ? re[CARETLOOSE] : re[CARET];
return comp.replace(r, function(_, M, m, p, pr) {
debug('caret', comp, _, M, m, p, pr);
var ret;
if (isX(M))
ret = '';
else if (isX(m))
ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
else if (isX(p)) {
if (M === '0')
ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
else
ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0';
} else if (pr) {
debug('replaceCaret pr', pr);
if (pr.charAt(0) !== '-')
pr = '-' + pr;
if (M === '0') {
if (m === '0')
ret = '>=' + M + '.' + m + '.' + p + pr +
' <' + M + '.' + m + '.' + (+p + 1);
else
ret = '>=' + M + '.' + m + '.' + p + pr +
' <' + M + '.' + (+m + 1) + '.0';
} else
ret = '>=' + M + '.' + m + '.' + p + pr +
' <' + (+M + 1) + '.0.0';
} else {
debug('no pr');
if (M === '0') {
if (m === '0')
ret = '>=' + M + '.' + m + '.' + p +
' <' + M + '.' + m + '.' + (+p + 1);
else
ret = '>=' + M + '.' + m + '.' + p +
' <' + M + '.' + (+m + 1) + '.0';
} else
ret = '>=' + M + '.' + m + '.' + p +
' <' + (+M + 1) + '.0.0';
}
debug('caret return', ret);
return ret;
});
}
function replaceXRanges(comp, loose) {
debug('replaceXRanges', comp, loose);
return comp.split(/\s+/).map(function(comp) {
return replaceXRange(comp, loose);
}).join(' ');
}
function replaceXRange(comp, loose) {
comp = comp.trim();
var r = loose ? re[XRANGELOOSE] : re[XRANGE];
return comp.replace(r, function(ret, gtlt, M, m, p, pr) {
debug('xRange', comp, ret, gtlt, M, m, p, pr);
var xM = isX(M);
var xm = xM || isX(m);
var xp = xm || isX(p);
var anyX = xp;
if (gtlt === '=' && anyX)
gtlt = '';
if (xM) {
if (gtlt === '>' || gtlt === '<') {
// nothing is allowed
ret = '<0.0.0';
} else {
// nothing is forbidden
ret = '*';
}
} else if (gtlt && anyX) {
// replace X with 0
if (xm)
m = 0;
if (xp)
p = 0;
if (gtlt === '>') {
// >1 => >=2.0.0
// >1.2 => >=1.3.0
// >1.2.3 => >= 1.2.4
gtlt = '>=';
if (xm) {
M = +M + 1;
m = 0;
p = 0;
} else if (xp) {
m = +m + 1;
p = 0;
}
} else if (gtlt === '<=') {
// <=0.7.x is actually <0.8.0, since any 0.7.x should
// pass. Similarly, <=7.x is actually <8.0.0, etc.
gtlt = '<';
if (xm)
M = +M + 1;
else
m = +m + 1;
}
ret = gtlt + M + '.' + m + '.' + p;
} else if (xm) {
ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
} else if (xp) {
ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
}
debug('xRange return', ret);
return ret;
});
}
// Because * is AND-ed with everything else in the comparator,
// and '' means "any version", just remove the *s entirely.
function replaceStars(comp, loose) {
debug('replaceStars', comp, loose);
// Looseness is ignored here. star is always as loose as it gets!
return comp.trim().replace(re[STAR], '');
}
// This function is passed to string.replace(re[HYPHENRANGE])
// M, m, patch, prerelease, build
// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
// 1.2 - 3.4 => >=1.2.0 <3.5.0
function hyphenReplace($0,
from, fM, fm, fp, fpr, fb,
to, tM, tm, tp, tpr, tb) {
if (isX(fM))
from = '';
else if (isX(fm))
from = '>=' + fM + '.0.0';
else if (isX(fp))
from = '>=' + fM + '.' + fm + '.0';
else
from = '>=' + from;
if (isX(tM))
to = '';
else if (isX(tm))
to = '<' + (+tM + 1) + '.0.0';
else if (isX(tp))
to = '<' + tM + '.' + (+tm + 1) + '.0';
else if (tpr)
to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr;
else
to = '<=' + to;
return (from + ' ' + to).trim();
}
// if ANY of the sets match ALL of its comparators, then pass
Range.prototype.test = function(version) {
if (!version)
return false;
if (typeof version === 'string')
version = new SemVer(version, this.loose);
for (var i = 0; i < this.set.length; i++) {
if (testSet(this.set[i], version))
return true;
}
return false;
};
function testSet(set, version) {
for (var i = 0; i < set.length; i++) {
if (!set[i].test(version))
return false;
}
if (version.prerelease.length) {
// Find the set of versions that are allowed to have prereleases
// For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
// That should allow `1.2.3-pr.2` to pass.
// However, `1.2.4-alpha.notready` should NOT be allowed,
// even though it's within the range set by the comparators.
for (var i = 0; i < set.length; i++) {
debug(set[i].semver);
if (set[i].semver === ANY)
continue;
if (set[i].semver.prerelease.length > 0) {
var allowed = set[i].semver;
if (allowed.major === version.major &&
allowed.minor === version.minor &&
allowed.patch === version.patch)
return true;
}
}
// Version has a -pre, but it's not one of the ones we like.
return false;
}
return true;
}
exports.satisfies = satisfies;
function satisfies(version, range, loose) {
try {
range = new Range(range, loose);
} catch (er) {
return false;
}
return range.test(version);
}
exports.maxSatisfying = maxSatisfying;
function maxSatisfying(versions, range, loose) {
var max = null;
var maxSV = null;
try {
var rangeObj = new Range(range, loose);
} catch (er) {
return null;
}
versions.forEach(function (v) {
if (rangeObj.test(v)) { // satisfies(v, range, loose)
if (!max || maxSV.compare(v) === -1) { // compare(max, v, true)
max = v;
maxSV = new SemVer(max, loose);
}
}
});
return max;
}
exports.minSatisfying = minSatisfying;
function minSatisfying(versions, range, loose) {
var min = null;
var minSV = null;
try {
var rangeObj = new Range(range, loose);
} catch (er) {
return null;
}
versions.forEach(function (v) {
if (rangeObj.test(v)) { // satisfies(v, range, loose)
if (!min || minSV.compare(v) === 1) { // compare(min, v, true)
min = v;
minSV = new SemVer(min, loose);
}
}
});
return min;
}
exports.validRange = validRange;
function validRange(range, loose) {
try {
// Return '*' instead of '' so that truthiness works.
// This will throw if it's invalid anyway
return new Range(range, loose).range || '*';
} catch (er) {
return null;
}
}
// Determine if version is less than all the versions possible in the range
exports.ltr = ltr;
function ltr(version, range, loose) {
return outside(version, range, '<', loose);
}
// Determine if version is greater than all the versions possible in the range.
exports.gtr = gtr;
function gtr(version, range, loose) {
return outside(version, range, '>', loose);
}
exports.outside = outside;
function outside(version, range, hilo, loose) {
version = new SemVer(version, loose);
range = new Range(range, loose);
var gtfn, ltefn, ltfn, comp, ecomp;
switch (hilo) {
case '>':
gtfn = gt;
ltefn = lte;
ltfn = lt;
comp = '>';
ecomp = '>=';
break;
case '<':
gtfn = lt;
ltefn = gte;
ltfn = gt;
comp = '<';
ecomp = '<=';
break;
default:
throw new TypeError('Must provide a hilo val of "<" or ">"');
}
// If it satisifes the range it is not outside
if (satisfies(version, range, loose)) {
return false;
}
// From now on, variable terms are as if we're in "gtr" mode.
// but note that everything is flipped for the "ltr" function.
for (var i = 0; i < range.set.length; ++i) {
var comparators = range.set[i];
var high = null;
var low = null;
comparators.forEach(function(comparator) {
if (comparator.semver === ANY) {
comparator = new Comparator('>=0.0.0');
}
high = high || comparator;
low = low || comparator;
if (gtfn(comparator.semver, high.semver, loose)) {
high = comparator;
} else if (ltfn(comparator.semver, low.semver, loose)) {
low = comparator;
}
});
// If the edge version comparator has a operator then our version
// isn't outside it
if (high.operator === comp || high.operator === ecomp) {
return false;
}
// If the lowest version comparator has an operator and our version
// is less than it then it isn't higher than the range
if ((!low.operator || low.operator === comp) &&
ltefn(version, low.semver)) {
return false;
} else if (low.operator === ecomp && ltfn(version, low.semver)) {
return false;
}
}
return true;
}
exports.prerelease = prerelease;
function prerelease(version, loose) {
var parsed = parse(version, loose);
return (parsed && parsed.prerelease.length) ? parsed.prerelease : null;
}
exports.intersects = intersects;
function intersects(r1, r2, loose) {
r1 = new Range(r1, loose);
r2 = new Range(r2, loose);
return r1.intersects(r2)
}
exports.coerce = coerce;
function coerce(version) {
if (version instanceof SemVer)
return version;
if (typeof version !== 'string')
return null;
var match = version.match(re[COERCE]);
if (match == null)
return null;
return parse((match[1] || '0') + '.' + (match[2] || '0') + '.' + (match[3] || '0'));
}
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../process/browser.js */ "./node_modules/process/browser.js")));
/***/ }),
/***/ "./node_modules/webpack/buildin/harmony-module.js":
/*!*******************************************!*\
!*** (webpack)/buildin/harmony-module.js ***!
\*******************************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = function(originalModule) {
if (!originalModule.webpackPolyfill) {
var module = Object.create(originalModule);
// module.parent = undefined by default
if (!module.children) module.children = [];
Object.defineProperty(module, "loaded", {
enumerable: true,
get: function() {
return module.l;
}
});
Object.defineProperty(module, "id", {
enumerable: true,
get: function() {
return module.i;
}
});
Object.defineProperty(module, "exports", {
enumerable: true
});
module.webpackPolyfill = 1;
}
return module;
};
/***/ }),
/***/ "./src/rtc_reporting/reporting_agent.ts":
/*!**********************************************!*\
!*** ./src/rtc_reporting/reporting_agent.ts ***!
\**********************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _reporting_reporter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./reporting_reporter */ "./src/rtc_reporting/reporting_reporter.ts");
/* harmony import */ var _reporting_event__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./reporting_event */ "./src/rtc_reporting/reporting_event.ts");
/* harmony import */ var _reporting_storebag__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./reporting_storebag */ "./src/rtc_reporting/reporting_storebag.ts");
/* harmony import */ var _reporting_config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./reporting_config */ "./src/rtc_reporting/reporting_config.ts");
const { RTCReportingStoreBag } = _reporting_storebag__WEBPACK_IMPORTED_MODULE_2__;
const ReportingVersion = '1';
class RTCObjectRef {
constructor(objectNotToDestroy = null) {
this._objectNotToDestroy = objectNotToDestroy;
this._objectToDestroy = null;
}
addInstantiatedObject(objectToDestroy) {
this._objectNotToDestroy = this._objectToDestroy = objectToDestroy;
}
get instance() {
return this._objectNotToDestroy;
}
destroy() {
if (this._objectToDestroy) {
this._objectToDestroy.destroy();
}
this._objectNotToDestroy = this._objectNotToDestroy = null;
}
}
class RTCReportingAgent {
constructor(reportingConfig = {}) {
this._sessionInfo = {};
this._reportingDisabled = false;
this.storebag = new RTCObjectRef();
this.reporter = null;
this.reportingVersion = ReportingVersion;
this.fuzzFactor = 0;
this.sessionStartTime = 0;
this._initializeReportingAgent(reportingConfig);
}
destroy() {
this.endSession();
}
get ReportingAllowed() {
return !(this._reportingDisabled);
}
static get version() {
return "0.1.36";
}
issueReportingEvent(eventID, eventPayload, eventType = _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentEventTypes"].BatchEvent) {
let error = null;
if (this.ReportingAllowed && this.reporter) {
let event = new _reporting_event__WEBPACK_IMPORTED_MODULE_1__["RTCReportingEvent"](eventID, _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingSessionEventStatus"].EventStatusSessionBegin, eventPayload, this._FuzzFactor, eventType);
error = this.reporter.issueReportingEvent(event, this._sessionInfo);
}
else {
error = new _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingError"]('Reporting not allowed.');
}
return error;
}
endSession() {
if (this.ReportingAllowed && this.reporter) {
this._issueSessionEndEvent();
this.reporter.flushAllEvents();
}
this._sessionInfo = null;
this.reporter = null;
this.storebag.destroy();
this.storebag = null;
}
set SessionInfo(session_info) {
this._sessionInfo = session_info;
}
get SessionInfo() {
return this._sessionInfo;
}
get SessionID() {
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].SessionID in this._sessionInfo) {
return this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].SessionID];
}
return '';
}
get ClientName() {
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ClientName in this._sessionInfo) {
return this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ClientName];
}
return '';
}
get ServiceName() {
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ServiceName in this._sessionInfo) {
return this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ServiceName];
}
return '';
}
get _FuzzFactor() {
return this.fuzzFactor;
}
_initializeReportingAgent(reportingConfig) {
let clientName = null;
let serviceName = null;
let applicationName = '';
let sender = null;
let deviceName = null;
let osVersion = null;
let storebagURL = null;
let reportingDisabled = false;
let startTime = (new Date()).getTime();
let hlsEventEmitter = null;
let sessionID = null;
let userInfoDict = null;
let senderOSVersion = null;
let storeBag = null;
let senderServiceID = null;
let senderAltConfig = null;
let useHTTPHeaders = null;
if (!this._sessionInfo) {
this._sessionInfo = {};
}
if (reportingConfig) {
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ClientName in reportingConfig) {
clientName = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ClientName];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ServiceName in reportingConfig) {
serviceName = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ServiceName];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ApplicationName in reportingConfig) {
applicationName = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ApplicationName];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].Sender in reportingConfig) {
sender = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].Sender];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].OSVersion in reportingConfig) {
osVersion = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].OSVersion];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].StorebagURL in reportingConfig) {
storebagURL = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].StorebagURL];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].DeviceName in reportingConfig) {
deviceName = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].DeviceName];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ReportingDisabled in reportingConfig) {
reportingDisabled = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ReportingDisabled];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].HLSEventEmitter in reportingConfig) {
hlsEventEmitter = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].HLSEventEmitter];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].SessionID in reportingConfig) {
sessionID = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].SessionID];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].UserInfoDict in reportingConfig) {
userInfoDict = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].UserInfoDict];
if (userInfoDict && _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].SenderAltConfig in userInfoDict) {
senderAltConfig = userInfoDict[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].SenderAltConfig];
delete userInfoDict[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].SenderAltConfig];
if (senderAltConfig) {
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ServiceIdentifier in senderAltConfig) {
senderServiceID = senderAltConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ServiceIdentifier];
}
if (Object.keys(senderAltConfig)) {
Object.assign(userInfoDict, senderAltConfig);
}
}
}
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].SenderOSVersion in reportingConfig) {
senderOSVersion = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].SenderOSVersion];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ReportingStoreBag in reportingConfig) {
storeBag = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ReportingStoreBag];
}
if (_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].UseHTTPHeaders in reportingConfig) {
useHTTPHeaders = reportingConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].UseHTTPHeaders];
}
}
if (!sessionID) {
sessionID = RTCReportingAgent._createSessionID();
}
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ClientName] = clientName;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ServiceName] = serviceName;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ApplicationName] = applicationName;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].DeviceName] = deviceName;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].OSVersion] = osVersion;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].Sender] = sender;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].RTCSchemeVersion] = this.reportingVersion;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].RTCReportingVersion] = RTCReportingAgent.version;
this._reportingDisabled = reportingDisabled;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].SessionID] = sessionID;
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"].SenderOSVersion] = senderOSVersion;
if (applicationName && serviceName) {
serviceName = serviceName + '.' + applicationName;
}
if (senderServiceID && serviceName) {
serviceName = serviceName + '.' + senderServiceID;
}
this._sessionInfo[_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"].ServiceName] = serviceName;
this.fuzzFactor = startTime - Math.floor(startTime / 60000) * 60000;
this.sessionStartTime = startTime - this.fuzzFactor;
Object.keys(this._sessionInfo).forEach((key) => (this._sessionInfo[key] == null) && delete this._sessionInfo[key]);
if (userInfoDict && Object.keys(userInfoDict)) {
Object.assign(this._sessionInfo, userInfoDict);
}
if (this._reportingDisabled) {
return;
}
if (storeBag) {
this.storebag = new RTCObjectRef(storeBag);
}
else {
this.storebag.addInstantiatedObject(new RTCReportingStoreBag(storebagURL, clientName, serviceName, applicationName, deviceName, osVersion));
}
this.reporter = new _reporting_reporter__WEBPACK_IMPORTED_MODULE_0__["RTCReporter"](clientName, serviceName, sender, this.storebag.instance, this.reportingVersion, hlsEventEmitter, applicationName, senderServiceID, useHTTPHeaders, sessionID);
console.log(_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentDefaultConfig"].LogMsgPrefix + 'Created reporting agent using rtc.js version ' + RTCReportingAgent.version);
this._issueSessionBeginEvent();
}
_issueSessionBeginEvent() {
let event = new _reporting_event__WEBPACK_IMPORTED_MODULE_1__["RTCReportingEvent"](_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentMethods"].ReportingSessionMethod, _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingSessionEventStatus"].EventStatusSessionBegin, null, this._FuzzFactor, _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentEventTypes"].BatchEvent);
if (this.reporter && event) {
this.reporter.issueReportingEvent(event, this.SessionInfo);
}
}
_issueSessionEndEvent() {
let event = new _reporting_event__WEBPACK_IMPORTED_MODULE_1__["RTCReportingEvent"](_reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentMethods"].ReportingSessionMethod, _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingSessionEventStatus"].EventStatusSessionEnd, null, this._FuzzFactor, _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentEventTypes"].RealTimeEvent);
if (this.reporter) {
this.reporter.issueReportingEvent(event, this.SessionInfo);
}
}
static _createSessionID() {
let word0 = Math.random() * 0xffffffff | 0;
let word1 = Math.random() * 0xffffffff | 0;
let word2 = Math.random() * 0xffffffff | 0;
let word3 = Math.random() * 0xffffffff | 0;
const lastNibble = 0x0f;
const lastByte = 0xff;
const secondByteShift = 8;
const thirdByteShift = 16;
const fourthByteShift = 24;
const uuidVersion = 0x40;
const uuidVariant = 0x80;
const nByteMask = 0x3f;
let guid = [];
let radix = 16;
let guidLength = 256;
for (let i = 0; i < guidLength; ++i) {
guid[i] = (i < radix ? '0' : '') + (i).toString(radix);
}
return guid[word0 & lastByte] + guid[word0 >> secondByteShift & lastByte] + guid[word0 >> thirdByteShift & lastByte] + guid[word0 >> fourthByteShift & lastByte] + '-' +
guid[word1 & lastByte] + guid[word1 >> secondByteShift & lastByte] + '-' +
guid[word1 >> secondByteShift & lastNibble | uuidVersion] + guid[word1 >> thirdByteShift & lastByte] + '-' +
guid[word2 & nByteMask | uuidVariant] + guid[word2 >> secondByteShift & lastByte] + '-' +
guid[word2 >> secondByteShift & lastByte] + guid[word2 >> thirdByteShift & lastByte] +
guid[word3 & lastByte] + guid[word3 >> secondByteShift & lastByte] + guid[word3 >> thirdByteShift & lastByte] + guid[word3 >> fourthByteShift & lastByte];
}
}
/* harmony default export */ __webpack_exports__["default"] = ({
RTCReportingAgent,
RTCStorebag: _reporting_storebag__WEBPACK_IMPORTED_MODULE_2__,
RTCReportingAgentDefaultConfig: _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentDefaultConfig"],
RTCReportingAgentConfigKeys: _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentConfigKeys"],
RTCReportingAgentEventTypes: _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingAgentEventTypes"],
RTCReportingHTTPHeaderDefault: _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingHTTPHeaderDefault"],
RTCReportingHTTPHeaderKeys: _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingHTTPHeaderKeys"],
RTCReportingEventMetadataKeys: _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingEventMetadataKeys"],
RTC_REPORTING_EVENTS_DISPATCHED: _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTC_REPORTING_EVENTS_DISPATCHED"],
RTCObjectRef,
RTCReportingStoreBagConfig: _reporting_config__WEBPACK_IMPORTED_MODULE_3__["RTCReportingStoreBagConfig"],
});
/***/ }),
/***/ "./src/rtc_reporting/reporting_config.ts":
/*!***********************************************!*\
!*** ./src/rtc_reporting/reporting_config.ts ***!
\***********************************************/
/*! exports provided: RTCReportingAgentDefaultConfig, RTCReportingAgentConfigKeys, RTCReportingAgentEventTypes, RTCReportingHTTPHeaderKeys, RTCReportingHTTPHeaderDefault, RTCReportingEventMetadataKeys, RTCReportingStoreBagConfig, RTCReportingReporterConfig, RTCReportingAgentMethods, RTCReportingSessionEventStatus, RTCReportingStoreBagKeys, RTCReportingError, RTCReportingBuildTypes, RTC_REPORTING_EVENTS_DISPATCHED */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingAgentDefaultConfig", function() { return RTCReportingAgentDefaultConfig; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingAgentConfigKeys", function() { return RTCReportingAgentConfigKeys; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingAgentEventTypes", function() { return RTCReportingAgentEventTypes; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingHTTPHeaderKeys", function() { return RTCReportingHTTPHeaderKeys; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingHTTPHeaderDefault", function() { return RTCReportingHTTPHeaderDefault; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingEventMetadataKeys", function() { return RTCReportingEventMetadataKeys; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingStoreBagConfig", function() { return RTCReportingStoreBagConfig; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingReporterConfig", function() { return RTCReportingReporterConfig; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingAgentMethods", function() { return RTCReportingAgentMethods; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingSessionEventStatus", function() { return RTCReportingSessionEventStatus; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingStoreBagKeys", function() { return RTCReportingStoreBagKeys; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingError", function() { return RTCReportingError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingBuildTypes", function() { return RTCReportingBuildTypes; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTC_REPORTING_EVENTS_DISPATCHED", function() { return RTC_REPORTING_EVENTS_DISPATCHED; });
const RTCReportingHTTPHeaderKeys = {
ContentType: 'ContentType',
InternalBuild: 'X-RTC-Internal-Build',
ClientName: 'X-RTC-Client-Name',
ServiceName: 'X-RTC-Service-Name',
ClientVersion: 'X-RTC-Client-Version',
Sender: 'X-RTC-Sender',
UserAgent: 'User-Agent',
SessionID: 'X-RTC-Session-ID',
};
const RTCReportingHTTPHeaderDefault = {
ContentTypekey: 'application/json;charset=UTF-8',
};
const RTCReportingEventMetadataKeys = {
EventID: '_method',
EventType: '_eventType',
EventNumber: '_eventNumber',
EventTime: 'eventTime',
Sender: '_sender',
Status: '_status',
ClientTS: '_clientTS',
TimeZoneOffset: '_timezoneOffset',
PostTime: 'postTime',
Events: 'events',
SessionID: '_sessionID',
OSVersion: 'osVersion',
RTCReportingVersion: '_reportVers',
StoreBagVersion: 'StorebagVersion',
RTCSchemeVersion: '_reportScheme',
BagSchemeVersion: 'StorebagScheme',
StoreBagName: 'StorebagName',
SessionTag: 'SessionTag',
SenderOSVersion: 'SenderOSVersion',
};
const RTCReportingAgentDefaultConfig = {
RunInlineIfNoWebWorker: true,
BatchEvent: true,
LogMsgPrefix: '[RTC_RA]: ',
};
const RTCReportingAgentConfigKeys = {
ClientName: '_clientName',
ServiceName: '_serviceName',
StorebagURL: 'storebagURL',
ApplicationName: 'applicationName',
Sender: 'sender',
DeviceName: 'deviceName',
OSVersion: 'osVersion',
ReportingDisabled: 'reportingDisabled',
HLSEventEmitter: 'hlsEventEmitter',
BuildType: 'internal',
UserInfoDict: 'userInfoDict',
ReportingStoreBag: 'reportingStoreBag',
SenderAltConfig: 'senderAltConfig',
ServiceIdentifier: 'ServiceIdentifier',
UseHTTPHeaders: 'UseHTTPHeaders',
};
const RTCReportingAgentEventTypes = {
BatchEvent: 0,
RealTimeEvent: 1,
};
const RTCReportingAgentMethods = {
ReportingSessionMethod: 0,
};
const RTCReportingStoreBagConfig = {
StoreBagFetchSyncMode: 0,
StoreBagFetchAsyncMode: 1,
StoreBagVersionSupported: 1,
};
const RTCReportingReporterConfig = {
BatchThreshold: 50,
};
const RTCReportingSessionEventStatus = {
EventStatusSessionBegin: 0,
EventStatusSessionEnd: 1,
EventStatusSessionEndWithError: 2,
};
const RTCReportingStoreBagKeys = {
Version: 'Version',
Scheme: 'Scheme',
BagVersion: 'BagVersion',
Configurations: 'Configurations',
ConfigurationList: 'ConfigurationList',
PostURLs: 'PostURLs',
Filters: 'Filters',
BagList: 'BagList',
MinOSVersionDict: 'MinOSVersionDict',
ClientName: 'ClientName',
ServiceName: 'ServiceName',
ServiceNameList: 'ServiceNameList',
SenderServiceIDList: 'SenderServiceIDList',
ApplicationNameList: 'ApplicationNameList',
DeviceList: 'DeviceList',
Remove: 'Remove',
EventThreshold: 'EventThreshold',
SamplingThreshold: 'SamplingThreshold',
DeviceWhiteList: 'DeviceWhiteList',
FlushEventsInterval: 'FlushEventsInterval',
};
const RTCReportingBuildTypes = {
BuildTypePublic: 0,
BuildTypeInternal: 1,
BuildTypeSeed: 2,
BuildTypeInternalSeed: 3
};
class RTCReportingError extends Error {
constructor(...args) {
super(...args);
Error.captureStackTrace(this, RTCReportingError);
}
}
const RTC_REPORTING_EVENTS_DISPATCHED = 'rtcReportingEventsDispatched';
/***/ }),
/***/ "./src/rtc_reporting/reporting_event.ts":
/*!**********************************************!*\
!*** ./src/rtc_reporting/reporting_event.ts ***!
\**********************************************/
/*! exports provided: RTCReportingEvent */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingEvent", function() { return RTCReportingEvent; });
/* harmony import */ var _reporting_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./reporting_config */ "./src/rtc_reporting/reporting_config.ts");
class RTCReportingEvent {
constructor(eventID, status = 0, eventPayload = {}, fuzzFactor = 0, eventType = _reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingAgentEventTypes"].BatchEvent) {
this.payload = eventPayload ? eventPayload : {};
this.payload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].EventID] = eventID;
this.payload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].Status] = status;
this.payload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].EventType] = eventType;
this.fuzzFactor = fuzzFactor;
this.isEventRealTime = (eventType === _reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingAgentEventTypes"].RealTimeEvent);
this._addEventMetadata();
}
prepareEventPayload(sessionInfo, sizeTillLastBatch, sizeOfLastBatch) {
Object.keys(sessionInfo).forEach(function (sessionInfoKey) {
this.payload[sessionInfoKey] = sessionInfo[sessionInfoKey];
}.bind(this));
if (this.isEventRealTime && sizeOfLastBatch && sizeTillLastBatch) {
this.payload.sizeOfLastBatch = sizeOfLastBatch;
this.payload.sizeTillLastBatch = sizeTillLastBatch;
}
}
get EventPayload() {
return this.payload;
}
get IsEventRealTime() {
return this.isEventRealTime;
}
_addEventMetadata() {
let date = new Date();
this.payload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].EventTime] = (date.getTime()) / 1000;
this.payload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].TimeZoneOffset] = date.getTimezoneOffset() * 60;
}
}
/***/ }),
/***/ "./src/rtc_reporting/reporting_reporter.ts":
/*!*************************************************!*\
!*** ./src/rtc_reporting/reporting_reporter.ts ***!
\*************************************************/
/*! exports provided: RTCReporter */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
/* WEBPACK VAR INJECTION */(function(module) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReporter", function() { return RTCReporter; });
/* harmony import */ var _reporting_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./reporting_config */ "./src/rtc_reporting/reporting_config.ts");
const ReportingContentType = 'application/json;charset=UTF-8';
const ReportingVersion = 'RTCReportingJS/0.314';
class EventDispatcher {
constructor(eventEmitter, sessionID, useHTTPHeaders = false) {
this._eventWriter = null;
this._sessionID = sessionID;
this._eventDispatcher = eventEmitter;
if (typeof navigator !== 'undefined' && navigator && (typeof navigator.sendBeacon !== 'undefined') && navigator.sendBeacon) {
this._eventWriter = this._sendEventDataWithHTTPPost;
}
else if ( this.module !== module) {
this._eventWriter = this._sendEventDataWithHTTPHeaders;
}
else {
this._eventWriter = this._sendEventDataWithHTTPPost;
}
if (useHTTPHeaders) {
this._eventWriter = this._sendEventDataWithHTTPHeaders;
}
}
sendEventData(url, eventDataAsJSON, clientName, serviceName, clientVersion, sender) {
if (this._eventWriter) {
this._eventWriter(url, eventDataAsJSON, clientName, serviceName, clientVersion, sender);
if (this._eventDispatcher) {
this._eventDispatcher.emit(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTC_REPORTING_EVENTS_DISPATCHED"], eventDataAsJSON);
}
}
}
_sendEventDataUsingBeacon(url, eventDataAsJSON, clientName, serviceName, clientVersion, sender) {
let headerJSON = this._createEventPayloadAsJSON(clientName, serviceName, clientVersion, sender);
let formData = new FormData();
formData.append('headers', headerJSON);
formData.append('payload', eventDataAsJSON);
navigator.sendBeacon(url, formData);
}
_sendEventDataWithHTTPPost(url, eventDataAsJSON, clientName, serviceName, clientVersion, sender) {
let headerJSON = this._createEventPayloadAsJSON(clientName, serviceName, clientVersion, sender);
let formData = new FormData();
formData.append('headers', headerJSON);
formData.append('payload', eventDataAsJSON);
let request = new XMLHttpRequest();
const method = 'POST';
const async = true;
request.open(method, url, async);
request.send(formData);
}
_createEventPayloadAsJSON(clientName, serviceName, clientVersion, sender) {
let header = {};
header[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].InternalBuild] = 0;
header[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ClientName] = clientName;
header[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ServiceName] = serviceName;
header[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ClientVersion] = clientVersion;
header[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].Sender] = sender;
header[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ContentType] = 'application/json;charset=UTF-8';
let headerJSON = JSON.stringify(header);
return headerJSON;
}
_sendEventDataWithHTTPHeaders(url, eventDataAsJSON, clientName, serviceName, clientVersion, sender) {
let request = new XMLHttpRequest();
const method = 'POST';
const async = true;
request.onload = function () {
};
request.open(method, url, async);
request.setRequestHeader(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ContentType, ReportingContentType);
request.setRequestHeader(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].InternalBuild, '0');
request.setRequestHeader(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ClientName, clientName);
request.setRequestHeader(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ServiceName, serviceName);
request.setRequestHeader(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ClientVersion, clientVersion);
request.setRequestHeader(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].Sender, sender);
request.setRequestHeader(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].ClientVersion, ReportingVersion);
request.setRequestHeader(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingHTTPHeaderKeys"].SessionID, this._sessionID);
request.send(eventDataAsJSON);
}
}
class RTCReporter {
constructor(clientName, serviceName, sender, reportingStoreBag, clientVersion, hlsEventEmitter, applicationName = null, senderServiceID = null, useHTTPHeaders = false, sessionID = null) {
this.clientName = clientName;
this.serviceName = serviceName;
this.reportingStoreBag = reportingStoreBag;
this.sender = sender;
this.clientVersion = clientVersion;
this.eventList = [];
this._count = 0;
this._eventDispatcher = new EventDispatcher(hlsEventEmitter, sessionID, useHTTPHeaders);
this.sampleFactor = Math.random();
this._storebagStats = {};
this._canReport = undefined;
this._sizeTillLastBatch = this._sizeOfLastBatch = 0;
this.storeBag = null;
this.applicationName = applicationName;
this.senderServiceID = senderServiceID;
this.checkAndConfigureEventFlushTimeoutOnce = false;
}
issueReportingEvent(event, sessionInfo = {}) {
if (!event) {
return new _reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingError"]('not a valid event to report');
}
this._updateEventMetadata(event);
event.prepareEventPayload(sessionInfo, this._sizeTillLastBatch, this._sizeOfLastBatch);
this.eventList.push(event);
if (!this.checkAndConfigureEventFlushTimeoutOnce) {
if (this.canReportEvents()) {
this._configureEventFlushTimer();
}
}
if ((this.eventList.length > _reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingReporterConfig"].BatchThreshold) || event.IsEventRealTime) {
return this.flushAllEvents();
}
return null;
}
canReportEvents() {
let sampleRate;
if (this._canReport !== undefined) {
return this._canReport;
}
if (this.reportingStoreBag && !this.storeBag) {
this.storeBag = this.reportingStoreBag.createParsedStoreBag(this.applicationName, this.senderServiceID);
if (!this.storeBag) {
return false;
}
}
if (this.storeBag && this.storeBag.IsValid) {
this._canReport = true;
sampleRate = this.storeBag.getStoreBagProperty(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].SamplingThreshold);
if (sampleRate && (parseFloat(sampleRate) < this.sampleFactor)) {
this._canReport = false;
}
}
else if (this.storeBag) {
console.log(`StoreBag for client ${this.clientName}, service ${this.serviceName}, app ${this.applicationName} senderService ${this.senderServiceID} not valid ${this.storeBag.IsValid} `);
}
if (this._canReport) {
this._storebagStats[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].SamplingThreshold] = sampleRate;
this._storebagStats[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].BagSchemeVersion] = this.storeBag.StoreBagSchemeVersion;
this._storebagStats[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].StoreBagVersion] = this.storeBag.StoreBagVersion;
this._storebagStats[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].StoreBagName] = this.storeBag.StoreBagName;
let bagMinVersionDict = this.storeBag.BagMinVersionDict;
if (typeof bagMinVersionDict === 'object' && bagMinVersionDict) {
for (let key in bagMinVersionDict) {
if (bagMinVersionDict.hasOwnProperty(key)) {
this._storebagStats[key] = bagMinVersionDict[key];
}
}
}
}
console.log(`${_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingAgentDefaultConfig"].LogMsgPrefix} Event reporting is ${this._canReport} for client ${this.clientName} service ${this.serviceName}, app ${this.applicationName}, senderService ${this.senderServiceID}`);
return this._canReport;
}
flushEventTimeout() {
this.flushAllEvents();
}
flushAllEvents() {
let error = null;
if (this.canReportEvents()) {
this._sendAllEvents();
}
else {
error = new _reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingError"]('no valid storebag configured or blocked by sampling threshold, ignoring events.');
}
this.eventList = [];
return error;
}
batchedEventsCount() {
return this.eventList.length;
}
get _EventList() {
return this.eventList;
}
_updateEventMetadata(event) {
event.EventPayload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].EventNumber] = this._eventCounter();
event.EventPayload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].ClientTS] = ((new Date()).getTime()) / 1000;
event.EventPayload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].Sender] = this.sender;
event.EventPayload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingAgentConfigKeys"].ClientName] = this.clientName;
event.EventPayload[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingAgentConfigKeys"].ServiceName] = this.serviceName;
}
_sendAllEvents() {
if (this.eventList.length === 0) {
return;
}
let backEnds = this.storeBag.listOfSupportedBackEnds(this.clientName, this.serviceName);
if (!backEnds || backEnds.length <= 0) {
return;
}
let blackListKeys = this.storeBag.listOfKeysToBlock();
if (blackListKeys) {
this.eventList.forEach(function (event) {
event.prepareEventPayload(this._storebagStats, this._sizeTillLastBatch, this._sizeOfLastBatch);
blackListKeys.forEach(function (key) {
delete event.EventPayload[key];
});
}.bind(this));
}
let eventData = this._marshallAsJSONString();
this._sizeTillLastBatch += eventData.length;
this._sizeOfLastBatch = eventData.length;
backEnds.forEach(function (backEndURL) {
this._eventDispatcher.sendEventData(backEndURL, eventData, this.clientName, this.serviceName, this.clientVersion, this.sender);
}.bind(this));
console.log(`${_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingAgentDefaultConfig"].LogMsgPrefix} events reported.`);
}
_marshallAsJSONString() {
let time = ((new Date()).getTime()) / 1000;
let postData = {};
let events = [];
this.eventList.forEach(function (event) {
events.push(event.EventPayload);
});
postData[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].PostTime] = time;
postData[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingEventMetadataKeys"].Events] = events;
let postBody = JSON.stringify(postData);
return postBody;
}
_eventCounter() {
return this._count++;
}
_configureEventFlushTimer() {
let flushTimeout = null;
this.checkAndConfigureEventFlushTimeoutOnce = true;
if (this.reportingStoreBag && !this.storeBag) {
this.storeBag = this.reportingStoreBag.createParsedStoreBag(this.applicationName, this.senderServiceID);
}
if (this.storeBag && this.storeBag.IsValid) {
flushTimeout = this.storeBag.getStoreBagProperty(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].FlushEventsInterval);
}
if (flushTimeout) {
flushTimeout = parseInt(flushTimeout, 10) * 1000;
if (flushTimeout >= 10000) {
setInterval(this.flushEventTimeout.bind(this), flushTimeout);
}
}
}
}
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/harmony-module.js */ "./node_modules/webpack/buildin/harmony-module.js")(module)));
/***/ }),
/***/ "./src/rtc_reporting/reporting_storebag.ts":
/*!*************************************************!*\
!*** ./src/rtc_reporting/reporting_storebag.ts ***!
\*************************************************/
/*! exports provided: RTCReportingStoreBag */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RTCReportingStoreBag", function() { return RTCReportingStoreBag; });
/* harmony import */ var _reporting_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./reporting_config */ "./src/rtc_reporting/reporting_config.ts");
/* harmony import */ var semver__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! semver */ "./node_modules/semver/semver.js");
class RTCReportingParsedStoreBag {
constructor(storeBagConfig, selectedBagName, bagVersion, bagMinVersionDict) {
this.storeBagConfig = storeBagConfig;
this.selectedBagName = selectedBagName;
this.bagVersion = bagVersion;
this.bagMinVersionDict = bagMinVersionDict;
}
listOfSupportedBackEnds() {
return this.getStoreBagProperty(_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].PostURLs);
}
listOfKeysToBlock() {
if (!this.storeBagConfig) {
return null;
}
let filters = this.storeBagConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].Filters];
if (!filters) {
return null;
}
return filters[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].Remove];
}
get IsValid() {
return Boolean(this.storeBagConfig);
}
get StoreBagName() {
return this.IsValid ? this.selectedBagName : null;
}
get StorebagVersion() {
return this.IsValid ? this.bagVersion : null;
}
get StoreBagSchemeVersion() {
return _reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagConfig"].StoreBagVersionSupported;
}
get BagMinVersionDict() {
return this.bagMinVersionDict;
}
getStoreBagProperty(propertyKey) {
let propertyValue = null;
if (this.IsValid && propertyKey && propertyKey in this.storeBagConfig) {
propertyValue = this.storeBagConfig[propertyKey];
}
return propertyValue;
}
}
class RTCReportingStoreBag {
constructor(storebagURL, clientName = null, serviceName = null, applicationName = null, deviceName = null, bagMinVersionDict = null, mode = _reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagConfig"].StoreBagFetchAsyncMode, storebagAsJSON = null) {
this.storebagURL = storebagURL;
this.mode = mode;
this.storeBagConfig = null;
this.clientName = clientName;
this.serviceName = serviceName;
this.applicationName = applicationName;
this.deviceName = deviceName;
this.storebagLoader = null;
this.selectedBagName = null;
this.storebagAsJSON = storebagAsJSON;
this.bagVersion = null;
this.bagMinVersionDict = null;
if (typeof bagMinVersionDict === 'object') {
this.bagMinVersionDict = bagMinVersionDict;
}
this.fetchAndParseStoreBag();
}
destroy() {
if (this.storebagLoader) {
this.storebagLoader.abort();
this.storebagLoader = null;
}
}
fetchAndParseStoreBag() {
this._fetchStoreBag();
}
createParsedStoreBag(applicationName = this.applicationName, senderServiceID = null) {
if (!this.storebagAsJSON) {
console.log('no bag available!');
return null;
}
return this._parseAndReturnStoreBag(this.storebagAsJSON, applicationName, senderServiceID);
}
_checkbagMinVersion(bagMinVersionDict, currentVersionDict) {
if (bagMinVersionDict && currentVersionDict) {
for (let key in bagMinVersionDict) {
if (bagMinVersionDict.hasOwnProperty(key)) {
let bagMinVersion = bagMinVersionDict[key];
if (currentVersionDict.hasOwnProperty(key)) {
let currentVersion = currentVersionDict[key];
if (Object(semver__WEBPACK_IMPORTED_MODULE_1__["gte"])(currentVersion, bagMinVersion)) {
return true;
}
}
}
}
return false;
}
return true;
}
_parseAndReturnStoreBag(storebag, applicationName, senderServiceID) {
let selectedBag = null;
let selectedBagConfig = null;
let selectedBagConfigKey = null;
let selectedBagVersion = null;
storebag.forEach(function (bag) {
selectedBag = null;
if (bag[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].Scheme] === _reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagConfig"].StoreBagVersionSupported) {
let bagList = bag[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].BagList];
Object.keys(bagList).some(function (bagConfigKey) {
let bagConfig = bagList[bagConfigKey];
let bagMinVersionDict = bagConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].MinOSVersionDict];
if (!this._checkbagMinVersion(bagMinVersionDict, this.bagMinVersionDict)) {
console.log(`failed to match the version # `);
return false;
}
if (!this._canUseBagConfig(bagConfig, applicationName, senderServiceID)) {
return false;
}
selectedBag = bagConfig;
selectedBagConfigKey = bagConfigKey;
selectedBagVersion = bag[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].BagVersion];
return false;
}.bind(this));
}
if (selectedBag) {
selectedBagConfig = this._fillSelectedBagConfig(selectedBag, bag);
}
}.bind(this));
if (!selectedBagConfig) {
console.log(`${_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingAgentDefaultConfig"].LogMsgPrefix} Failed to select a storebag.`);
}
return new RTCReportingParsedStoreBag(selectedBagConfig, selectedBagConfigKey, selectedBagVersion, this.bagMinVersionDict);
}
_fetchStoreBag() {
if (this.storebagURL && !this.storebagAsJSON) {
this._requestStoreBagAsync();
}
}
_requestStoreBagAsync() {
this.storebagLoader = new XMLHttpRequest();
this.storebagLoader.onreadystatechange = function () {
if (this.storebagLoader && this.storebagLoader.readyState === 4 && this.storebagLoader.status === 200 && this.storebagLoader.responseText) {
this.storebagAsJSON = JSON.parse(this.storebagLoader.responseText);
}
}.bind(this);
this.storebagLoader.open('GET', this.storebagURL, true);
this.storebagLoader.send(null);
}
_canUseBagConfig(bagConfig, applicationName, senderServiceID) {
let bagClientName = bagConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].ClientName];
if (bagClientName && bagClientName !== this.clientName) {
return false;
}
let bagServiceNameList = bagConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].ServiceNameList];
let bagServiceName = bagConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].ServiceName];
if (bagServiceNameList && bagServiceNameList.length > 0 && -1 === bagServiceNameList.indexOf(this.serviceName)) {
return false;
}
if (!bagServiceNameList && bagServiceName && bagServiceName !== this.serviceName) {
return false;
}
let bagApplicationNameList = bagConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].ApplicationNameList];
if (bagApplicationNameList && bagApplicationNameList.length > 0 && -1 === bagApplicationNameList.indexOf(applicationName)) {
return false;
}
let bagDeviceList = bagConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].DeviceList];
if (bagDeviceList && bagDeviceList.length > 0 && -1 === bagDeviceList.indexOf(this.deviceName)) {
return false;
}
let bagSenderServiceIDList = bagConfig[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].SenderServiceIDList];
if (bagSenderServiceIDList && bagSenderServiceIDList.length > 0 && -1 === bagSenderServiceIDList.indexOf(senderServiceID)) {
return false;
}
return true;
}
_fillSelectedBagConfig(selectedBag, bag) {
let selectedBagConfig = null;
if (!selectedBag || !bag) {
return selectedBagConfig;
}
let configurationList = bag[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].ConfigurationList];
let listOfConfigs = selectedBag[_reporting_config__WEBPACK_IMPORTED_MODULE_0__["RTCReportingStoreBagKeys"].Configurations];
if (!listOfConfigs) {
return selectedBagConfig;
}
listOfConfigs.forEach(function (configName) {
let config = configurationList[configName];
selectedBagConfig = selectedBagConfig ? selectedBagConfig : {};
Object.assign(selectedBagConfig, config);
});
return selectedBagConfig;
}
}
/***/ })
/******/ })["default"];
});
}(rtc));
var socket_io_min = {exports: {}};
/*!
* Socket.IO v4.0.2
* (c) 2014-2021 Guillermo Rauch
* Released under the MIT License.
*/
(function (module, exports) {
!function(t,e){module.exports=e();}(self,(function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r});},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0});},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=18)}([function(t,e,n){var r=n(24),o=n(25),i=String.fromCharCode(30);t.exports={protocol:4,encodePacket:r,encodePayload:function(t,e){var n=t.length,o=new Array(n),s=0;t.forEach((function(t,c){r(t,!1,(function(t){o[c]=t,++s===n&&e(o.join(i));}));}));},decodePacket:o,decodePayload:function(t,e){for(var n=t.split(i),r=[],s=0;s0;case l.ACK:case l.BINARY_ACK:return Array.isArray(e)}}}]),n}(h);e.Decoder=b;var m=function(){function t(e){u(this,t),this.packet=e,this.buffers=[],this.reconPack=e;}return p(t,[{key:"takeBinaryData",value:function(t){if(this.buffers.push(t),this.buffers.length===this.reconPack.attachments){var e=y.reconstructPacket(this.reconPack,this.buffers);return this.finishedReconstruction(),e}return null}},{key:"finishedReconstruction",value:function(){this.reconPack=null,this.buffers=[];}}]),t}();},function(t,e){var n=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,r=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];t.exports=function(t){var e=t,o=t.indexOf("["),i=t.indexOf("]");-1!=o&&-1!=i&&(t=t.substring(0,o)+t.substring(o,i).replace(/:/g,";")+t.substring(i,t.length));for(var s,c,a=n.exec(t||""),u={},f=14;f--;)u[r[f]]=a[f]||"";return -1!=o&&-1!=i&&(u.source=e,u.host=u.host.substring(1,u.host.length-1).replace(/;/g,":"),u.authority=u.authority.replace("[","").replace("]","").replace(/;/g,":"),u.ipv6uri=!0),u.pathNames=function(t,e){var n=e.replace(/\/{2,9}/g,"/").split("/");"/"!=e.substr(0,1)&&0!==e.length||n.splice(0,1);"/"==e.substr(e.length-1,1)&&n.splice(n.length-1,1);return n}(0,u.path),u.queryKey=(s=u.query,c={},s.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,(function(t,e,n){e&&(c[e]=n);})),c),u};},function(t,e,n){function r(t){return (r="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})(t)}function o(t,e){for(var n=0;n=this._reconnectionAttempts)this.backoff.reset(),this.emitReserved("reconnect_failed"),this._reconnecting=!1;else {var n=this.backoff.duration();this._reconnecting=!0;var r=setTimeout((function(){e.skipReconnect||(t.emitReserved("reconnect_attempt",e.backoff.attempts),e.skipReconnect||e.open((function(n){n?(e._reconnecting=!1,e.reconnect(),t.emitReserved("reconnect_error",n)):e.onreconnect();})));}),n);this.opts.autoUnref&&r.unref(),this.subs.push((function(){clearTimeout(r);}));}}},{key:"onreconnect",value:function(){var t=this.backoff.attempts;this._reconnecting=!1,this.backoff.reset(),this.emitReserved("reconnect",t);}}])&&o(e.prototype,n),y}(n(17).StrictEventEmitter);e.Manager=y;},function(t,e,n){var r=n(9),o=n(23),i=n(27),s=n(28);e.polling=function(t){var e=!1,n=!1,s=!1!==t.jsonp;if("undefined"!=typeof location){var c="https:"===location.protocol,a=location.port;a||(a=c?443:80),e=t.hostname!==location.hostname||a!==t.port,n=t.secure!==c;}if(t.xdomain=e,t.xscheme=n,"open"in new r(t)&&!t.forceJSONP)return new o(t);if(!s)throw new Error("JSONP disabled");return new i(t)},e.websocket=s;},function(t,e,n){var r=n(22),o=n(2);t.exports=function(t){var e=t.xdomain,n=t.xscheme,i=t.enablesXDR;try{if("undefined"!=typeof XMLHttpRequest&&(!e||r))return new XMLHttpRequest}catch(t){}try{if("undefined"!=typeof XDomainRequest&&!n&&i)return new XDomainRequest}catch(t){}if(!e)try{return new(o[["Active"].concat("Object").join("X")])("Microsoft.XMLHTTP")}catch(t){}};},function(t,e,n){function r(t){return (r="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})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n0);return e}function u(){var t=a(+new Date);return t!==r?(s=0,r=t):t+"."+a(s++)}for(;c<64;c++)i[o[c]]=c;u.encode=a,u.decode=function(t){var e=0;for(c=0;c1?e-1:0),r=1;r=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,c=!0,a=!1;return {s:function(){n=t[Symbol.iterator]();},n:function(){var t=n.next();return c=t.done,t},e:function(t){a=!0,s=t;},f:function(){try{c||null==n.return||n.return();}finally{if(a)throw s}}}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n1?e-1:0),r=1;r1?n-1:0),o=1;o1?n-1:0),o=1;o1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2?arguments[2]:void 0,o=t;n=n||"undefined"!=typeof location&&location,null==t&&(t=n.protocol+"//"+n.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?n.protocol+t:n.host+t),/^(https?|wss?):\/\//.test(t)||(t=void 0!==n?n.protocol+"//"+t:"https://"+t),o=r(t)),o.port||(/^(http|ws)$/.test(o.protocol)?o.port="80":/^(http|ws)s$/.test(o.protocol)&&(o.port="443")),o.path=o.path||"/";var i=-1!==o.host.indexOf(":"),s=i?"["+o.host+"]":o.host;return o.id=o.protocol+"://"+s+":"+o.port+e,o.href=o.protocol+"://"+s+(n&&n.port===o.port?"":":"+o.port),o};},function(t,e,n){var r=n(21);t.exports=function(t,e){return new r(t,e)},t.exports.Socket=r,t.exports.protocol=r.protocol,t.exports.Transport=n(3),t.exports.transports=n(8),t.exports.parser=n(0);},function(t,e,n){function r(){return (r=Object.assign||function(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:{};return i(this,l),e=f.call(this),t&&"object"===o(t)&&(n=t,t=null),t?(t=y(t),n.hostname=t.host,n.secure="https"===t.protocol||"wss"===t.protocol,n.port=t.port,t.query&&(n.query=t.query)):n.host&&(n.hostname=y(n.host).host),e.secure=null!=n.secure?n.secure:"undefined"!=typeof location&&"https:"===location.protocol,n.hostname&&!n.port&&(n.port=e.secure?"443":"80"),e.hostname=n.hostname||("undefined"!=typeof location?location.hostname:"localhost"),e.port=n.port||("undefined"!=typeof location&&location.port?location.port:e.secure?443:80),e.transports=n.transports||["polling","websocket"],e.readyState="",e.writeBuffer=[],e.prevBufferLen=0,e.opts=r({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,jsonp:!0,timestampParam:"t",rememberUpgrade:!1,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{}},n),e.opts.path=e.opts.path.replace(/\/$/,"")+"/","string"==typeof e.opts.query&&(e.opts.query=d.decode(e.opts.query)),e.id=null,e.upgrades=null,e.pingInterval=null,e.pingTimeout=null,e.pingTimeoutTimer=null,"function"==typeof addEventListener&&(addEventListener("beforeunload",(function(){e.transport&&(e.transport.removeAllListeners(),e.transport.close());}),!1),"localhost"!==e.hostname&&(e.offlineEventListener=function(){e.onClose("transport close");},addEventListener("offline",e.offlineEventListener,!1))),e.open(),e}return e=l,(n=[{key:"createTransport",value:function(t){var e=function(t){var e={};for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}(this.opts.query);e.EIO=h.protocol,e.transport=t,this.id&&(e.sid=this.id);var n=r({},this.opts.transportOptions[t],this.opts,{query:e,socket:this,hostname:this.hostname,secure:this.secure,port:this.port});return new p[t](n)}},{key:"open",value:function(){var t;if(this.opts.rememberUpgrade&&l.priorWebsocketSuccess&&-1!==this.transports.indexOf("websocket"))t="websocket";else {if(0===this.transports.length){var e=this;return void setTimeout((function(){e.emit("error","No transports available");}),0)}t=this.transports[0];}this.readyState="opening";try{t=this.createTransport(t);}catch(t){return this.transports.shift(),void this.open()}t.open(),this.setTransport(t);}},{key:"setTransport",value:function(t){var e=this;this.transport&&this.transport.removeAllListeners(),this.transport=t,t.on("drain",(function(){e.onDrain();})).on("packet",(function(t){e.onPacket(t);})).on("error",(function(t){e.onError(t);})).on("close",(function(){e.onClose("transport close");}));}},{key:"probe",value:function(t){var e=this.createTransport(t,{probe:1}),n=!1,r=this;function o(){if(r.onlyBinaryUpgrades){var t=!this.supportsBinary&&r.transport.supportsBinary;n=n||t;}n||(e.send([{type:"ping",data:"probe"}]),e.once("packet",(function(t){if(!n)if("pong"===t.type&&"probe"===t.data){if(r.upgrading=!0,r.emit("upgrading",e),!e)return;l.priorWebsocketSuccess="websocket"===e.name,r.transport.pause((function(){n||"closed"!==r.readyState&&(f(),r.setTransport(e),e.send([{type:"upgrade"}]),r.emit("upgrade",e),e=null,r.upgrading=!1,r.flush());}));}else {var o=new Error("probe error");o.transport=e.name,r.emit("upgradeError",o);}})));}function i(){n||(n=!0,f(),e.close(),e=null);}function s(t){var n=new Error("probe error: "+t);n.transport=e.name,i(),r.emit("upgradeError",n);}function c(){s("transport closed");}function a(){s("socket closed");}function u(t){e&&t.name!==e.name&&i();}function f(){e.removeListener("open",o),e.removeListener("error",s),e.removeListener("close",c),r.removeListener("close",a),r.removeListener("upgrading",u);}l.priorWebsocketSuccess=!1,e.once("open",o),e.once("error",s),e.once("close",c),this.once("close",a),this.once("upgrading",u),e.open();}},{key:"onOpen",value:function(){if(this.readyState="open",l.priorWebsocketSuccess="websocket"===this.transport.name,this.emit("open"),this.flush(),"open"===this.readyState&&this.opts.upgrade&&this.transport.pause)for(var t=0,e=this.upgrades.length;t0&&void 0!==arguments[0]?arguments[0]:{};return o(t,{xd:this.xd,xs:this.xs},this.opts),new w(this.uri(),t)}},{key:"doWrite",value:function(t,e){var n=this.request({method:"POST",data:t}),r=this;n.on("success",e),n.on("error",(function(t){r.onError("xhr post error",t);}));}},{key:"doPoll",value:function(){var t=this.request(),e=this;t.on("data",(function(t){e.onData(t);})),t.on("error",(function(t){e.onError("xhr poll error",t);})),this.pollXhr=t;}}]),n}(y),w=function(t){a(n,t);var e=f(n);function n(t,r){var o;return i(this,n),(o=e.call(this)).opts=r,o.method=r.method||"GET",o.uri=t,o.async=!1!==r.async,o.data=void 0!==r.data?r.data:null,o.create(),o}return c(n,[{key:"create",value:function(){var t=v(this.opts,"agent","enablesXDR","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","autoUnref");t.xdomain=!!this.opts.xd,t.xscheme=!!this.opts.xs;var e=this.xhr=new h(t),r=this;try{e.open(this.method,this.uri,this.async);try{if(this.opts.extraHeaders)for(var o in e.setDisableHeaderCheck&&e.setDisableHeaderCheck(!0),this.opts.extraHeaders)this.opts.extraHeaders.hasOwnProperty(o)&&e.setRequestHeader(o,this.opts.extraHeaders[o]);}catch(t){}if("POST"===this.method)try{e.setRequestHeader("Content-type","text/plain;charset=UTF-8");}catch(t){}try{e.setRequestHeader("Accept","*/*");}catch(t){}"withCredentials"in e&&(e.withCredentials=this.opts.withCredentials),this.opts.requestTimeout&&(e.timeout=this.opts.requestTimeout),this.hasXDR()?(e.onload=function(){r.onLoad();},e.onerror=function(){r.onError(e.responseText);}):e.onreadystatechange=function(){4===e.readyState&&(200===e.status||1223===e.status?r.onLoad():setTimeout((function(){r.onError("number"==typeof e.status?e.status:0);}),0));},e.send(this.data);}catch(t){return void setTimeout((function(){r.onError(t);}),0)}"undefined"!=typeof document&&(this.index=n.requestsCount++,n.requests[this.index]=this);}},{key:"onSuccess",value:function(){this.emit("success"),this.cleanup();}},{key:"onData",value:function(t){this.emit("data",t),this.onSuccess();}},{key:"onError",value:function(t){this.emit("error",t),this.cleanup(!0);}},{key:"cleanup",value:function(t){if(void 0!==this.xhr&&null!==this.xhr){if(this.hasXDR()?this.xhr.onload=this.xhr.onerror=m:this.xhr.onreadystatechange=m,t)try{this.xhr.abort();}catch(t){}"undefined"!=typeof document&&delete n.requests[this.index],this.xhr=null;}}},{key:"onLoad",value:function(){var t=this.xhr.responseText;null!==t&&this.onData(t);}},{key:"hasXDR",value:function(){return "undefined"!=typeof XDomainRequest&&!this.xs&&this.enablesXDR}},{key:"abort",value:function(){this.cleanup();}}]),n}(d);if(w.requestsCount=0,w.requests={},"undefined"!=typeof document)if("function"==typeof attachEvent)attachEvent("onunload",_);else if("function"==typeof addEventListener){addEventListener("onpagehide"in b?"pagehide":"unload",_,!1);}function _(){for(var t in w.requests)w.requests.hasOwnProperty(t)&&w.requests[t].abort();}t.exports=k,t.exports.Request=w;},function(t,e,n){var r=n(11).PACKET_TYPES,o="function"==typeof Blob||"undefined"!=typeof Blob&&"[object BlobConstructor]"===Object.prototype.toString.call(Blob),i="function"==typeof ArrayBuffer,s=function(t,e){var n=new FileReader;return n.onload=function(){var t=n.result.split(",")[1];e("b"+t);},n.readAsDataURL(t)};t.exports=function(t,e,n){var c,a=t.type,u=t.data;return o&&u instanceof Blob?e?n(u):s(u,n):i&&(u instanceof ArrayBuffer||(c=u,"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(c):c&&c.buffer instanceof ArrayBuffer))?e?n(u instanceof ArrayBuffer?u:u.buffer):s(new Blob([u]),n):n(r[a]+(u||""))};},function(t,e,n){var r,o=n(11),i=o.PACKET_TYPES_REVERSE,s=o.ERROR_PACKET;"function"==typeof ArrayBuffer&&(r=n(26));var c=function(t,e){if(r){var n=r.decode(t);return a(n,e)}return {base64:!0,data:t}},a=function(t,e){switch(e){case"blob":return t instanceof ArrayBuffer?new Blob([t]):t;case"arraybuffer":default:return t}};t.exports=function(t,e){if("string"!=typeof t)return {type:"message",data:a(t,e)};var n=t.charAt(0);return "b"===n?{type:"message",data:c(t.substring(1),e)}:i[n]?t.length>1?{type:i[n],data:t.substring(1)}:{type:i[n]}:s};},function(t,e){!function(t){e.encode=function(e){var n,r=new Uint8Array(e),o=r.length,i="";for(n=0;n>2],i+=t[(3&r[n])<<4|r[n+1]>>4],i+=t[(15&r[n+1])<<2|r[n+2]>>6],i+=t[63&r[n+2]];return o%3==2?i=i.substring(0,i.length-1)+"=":o%3==1&&(i=i.substring(0,i.length-2)+"=="),i},e.decode=function(e){var n,r,o,i,s,c=.75*e.length,a=e.length,u=0;"="===e[e.length-1]&&(c--,"="===e[e.length-2]&&c--);var f=new ArrayBuffer(c),p=new Uint8Array(f);for(n=0;n>4,p[u++]=(15&o)<<4|i>>2,p[u++]=(3&i)<<6|63&s;return f};}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");},function(t,e,n){function r(t){return (r="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})(t)}function o(t,e){for(var n=0;n';n=document.createElement(t);}catch(t){(n=document.createElement("iframe")).name=r.iframeId,n.src="javascript:0";}n.id=r.iframeId,r.form.appendChild(n),r.iframe=n;}this.form.action=this.uri(),a(),t=t.replace(d,"\\\n"),this.area.value=t.replace(y,"\\n");try{this.form.submit();}catch(t){}this.iframe.attachEvent?this.iframe.onreadystatechange=function(){"complete"===r.iframe.readyState&&c();}:this.iframe.onload=c;}},{key:"supportsBinary",get:function(){return !1}}])&&o(e.prototype,n),l}(l);t.exports=v;},function(t,e,n){function r(t){return (r="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})(t)}function o(t,e){for(var n=0;n0&&t.jitter<=1?t.jitter:0,this.attempts=0;}t.exports=n,n.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),n=Math.floor(e*this.jitter*t);t=0==(1&Math.floor(10*e))?t-n:t+n;}return 0|Math.min(t,this.max)},n.prototype.reset=function(){this.attempts=0;},n.prototype.setMin=function(t){this.ms=t;},n.prototype.setMax=function(t){this.max=t;},n.prototype.setJitter=function(t){this.jitter=t;};}])}));
}(socket_io_min));
var lzString_min = {exports: {}};
(function (module) {
var LZString=function(){function o(o,r){if(!t[o]){t[o]={};for(var n=0;ne;e++){var s=r.charCodeAt(e);n[2*e]=s>>>8,n[2*e+1]=s%256;}return n},decompressFromUint8Array:function(o){if(null===o||void 0===o)return i.decompress(o);for(var n=new Array(o.length/2),e=0,t=n.length;t>e;e++)n[e]=256*o[2*e]+o[2*e+1];var s=[];return n.forEach(function(o){s.push(r(o));}),i.decompress(s.join(""))},compressToEncodedURIComponent:function(o){return null==o?"":i._compress(o,6,function(o){return e.charAt(o)})},decompressFromEncodedURIComponent:function(r){return null==r?"":""==r?null:(r=r.replace(/ /g,"+"),i._decompress(r.length,32,function(n){return o(e,r.charAt(n))}))},compress:function(o){return i._compress(o,16,function(o){return r(o)})},_compress:function(o,r,n){if(null==o)return "";var e,t,i,s={},p={},u="",c="",a="",l=2,f=3,h=2,d=[],m=0,v=0;for(i=0;ie;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;}else {for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a];}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++),s[c]=f++,a=String(u);}if(""!==a){if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;}else {for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a];}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++);}for(t=2,e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;for(;;){if(m<<=1,v==r-1){d.push(n(m));break}v++;}return d.join("")},decompress:function(o){return null==o?"":""==o?null:i._decompress(o.length,32768,function(r){return o.charCodeAt(r)})},_decompress:function(o,n,e){var i,s,p,u,c,a,l,f=[],h=4,d=4,m=3,v="",w=[],A={val:e(0),position:n,index:1};for(i=0;3>i;i+=1)f[i]=i;for(p=0,c=Math.pow(2,2),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 2:return ""}for(f[3]=l,s=l,w.push(l);;){if(A.index>o)return "";for(p=0,c=Math.pow(2,m),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(l=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 2:return w.join("")}if(0==h&&(h=Math.pow(2,m),m++),f[l])v=f[l];else {if(l!==d)return null;v=s+s.charAt(0);}w.push(v),f[d++]=s+v.charAt(0),h--,s=v,0==h&&(h=Math.pow(2,m),m++);}}};return i}();null!=module&&(module.exports=LZString);
}(lzString_min));
var lzstring = lzString_min.exports;
/**
* This file contains methods related to retrieving, storing and reading the logs
* from a remote server, it is used for QA only and all of them should not get
* included in the bundle when using production mode
*/
/**
* Logger utility methods used for debugging
*
* @param {store} store - A storage solution, either sessionStorage, localStorage, indexeddb, etc
* @constructor
*/
const LoggerExternals = (store = sessionStorage) => {
{
return {
/**
* Compress a string to take less space during transmission
*
* @param {string} string - The string to compress
* @returns {string} - The compressed string
*/
compress: (string) => {
return lzstring.compressToUTF16(string);
},
/**
* Deletes the logs stored in the store
*
* @return {void}
*/
logClear: () => {
return store.clear();
},
/**
* Read the logs that were stored in the long term storage (compressed)
*
* @param {number} chunk - The chunk to read from the log file
* @param {number} chunkSize - The size of the chunk
* @return {string}
*/
logRead: (chunk = 0, chunkSize = LoggerExternals(store).logReadLength()) => {
const startPosition = chunk * chunkSize;
const endPosition = startPosition + chunkSize;
const log = [];
// Read each stored line until we read all the lines in a chunk
for (let i = startPosition; i <= endPosition; i += 1) {
const item = lzstring.decompress(store.getItem(String(i)));
if (item)
log.push(JSON.parse(item));
}
return JSON.stringify(log);
},
/**
* Read the size of the logs stored in the sessionStorage, used by the server to calculate
* chunk transmission size
*
* @return {number}
*/
logReadLength: () => {
return parseInt(store.getItem('logLength'), 10) || 0;
},
/**
* Store logs in the storage mechanism for later retrieval
*
* @param {string} level - The console level (ex: info, warn, etc)
* @param {*} logEvent - The data
*/
logStore: (level, logEvent) => {
store.setItem('logLength', String(LoggerExternals(store).logReadLength() + 1));
store.setItem(String(store.length), lzstring.compress(JSON.stringify(logEvent)));
},
};
}
};
var LoggerExternals$1 = LoggerExternals;
/**
* see https://tools.ietf.org/html/rfc1808
*
*
* This file was modified by Apple Inc.
* Modifications Copyright (c) 2018-
*
* The initial developer is https://github.com/tjenkinson/url-toolkit. Copyright (c) 2016 Tom Jenkinson.
*
* 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.
*
*/
const URL_REGEX = /^((?:[^\/;?#]+:)?)(\/\/[^\/\;?#]*)?(.*?)??(;.*?)?(\?.*?)?(#.*?)?$/;
const FIRST_SEGMENT_REGEX = /^([^\/;?#]*)(.*)$/;
const SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g;
const SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g;
const 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 (default, not spec compliant)
// http://a.com/b/cd + /e/f/../g => http://a.com/e/g
buildAbsoluteURL: function (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;
}
const 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);
}
const 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);
}
const 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'
const pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path);
baseParts.netLoc = pathParts[1];
baseParts.path = pathParts[2];
}
if (baseParts.netLoc && !baseParts.path) {
baseParts.path = '/';
}
const 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 is non-empty, we skip to
// Step 7. Otherwise, the embedded URL inherits the
// (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 is non-empty, we skip to
// step 7; otherwise, it inherits the of the base
// URL (if any) and
if (!relativeParts.params) {
builtParts.params = baseParts.params;
// 5b) if the embedded URL's is non-empty, we skip to
// step 7; otherwise, it inherits the of the base
// URL (if any) and we skip to step 7.
if (!relativeParts.query) {
builtParts.query = baseParts.query;
}
}
}
else {
// Non-standard, allow non-empty paths to inherit the query
if (opts.inheritQuery) {
if (!relativeParts.query) {
builtParts.query = baseParts.query;
}
}
// 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.
const baseURLPath = baseParts.path;
const 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 (url) {
const 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 (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 "/../", where 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 "/..", where is a
// complete path segment not equal to "..", that
// "/.." is removed.
while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) { } // eslint-disable-line
return path.split('').reverse().join('');
},
buildURLFromParts: function (parts) {
return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment;
},
getHostName: function (url) {
let hostname;
if (!url) {
return hostname;
}
if (url.indexOf('://') > -1) {
hostname = url.split('/')[2];
}
else {
hostname = url.split('/')[0];
}
// remove port and query if present
hostname = hostname.split(':')[0];
hostname = hostname.split('?')[0];
return hostname;
},
};
var URLToolkit$1 = URLToolkit;
/**
* URL utils for hostname and other stuff
*/
function isCustomUrl(url) {
return url != null && !url.startsWith('http://') && !url.startsWith('https://');
}
function getHostName(url) {
if (url == null) {
return null;
}
if (isCustomUrl(url)) {
return null;
}
return URLToolkit.getHostName(url);
}
const hostsRequiringQueries = ['.*.itunes.apple.com'];
const URLQueries = {
deviceName: '&xapdn=',
deviceModel: '&xapdm=',
language: '&xapdl=',
dsid: '&xapdsid=',
subs: '&xapsub=',
};
function urlNeedsUpdate(url, enableQueryParamsForITunes) {
if (enableQueryParamsForITunes) {
const hostName = getHostName(url);
return (undefined !==
hostsRequiringQueries.find((regStr) => {
const regex = new RegExp(regStr);
return regex.exec(hostName);
}));
}
return false;
}
function shouldUpdateUrlWithDeviceNameAndModel(platformInfo) {
const deviceModel = platformInfo.model, deviceName = platformInfo.manufacturer;
if (!deviceModel || !deviceName) {
getLogger().warn(`Missing model/manufacturer in platformInfo model ${deviceModel} manufacturer ${deviceName}`);
}
return !!deviceModel && !!deviceName;
}
function updateUrlWithDeviceNameAndModel(url, platformInfo) {
const deviceModel = platformInfo.model, deviceName = platformInfo.manufacturer, urlHasQueryParams = url.indexOf('?') !== -1, deviceModelEnc = encodeURIComponent(deviceModel), deviceNameEnc = encodeURIComponent(deviceName);
url = urlHasQueryParams ? url : url + '?';
return url + URLQueries.deviceName + deviceNameEnc + URLQueries.deviceModel + deviceModelEnc;
}
function updateUrlWithOptionsQuery(url, queryParameters) {
const urlHasQueryParams = url.indexOf('?') !== -1;
url = urlHasQueryParams ? url : url + '?';
let query;
const logger = getLogger();
for (query in queryParameters) {
if (!queryParameters[query]) {
logger.warn(`Missing ${query} info`);
}
else {
url += URLQueries[query] + (query === 'subs' ? encodeURIComponent(queryParameters[query]) : queryParameters[query]);
}
}
return url;
}
function updateUrlWithQueryStrings(url, platformInfo, queryParameters) {
if (shouldUpdateUrlWithDeviceNameAndModel(platformInfo)) {
url = updateUrlWithDeviceNameAndModel(url, platformInfo);
}
url = updateUrlWithOptionsQuery(url, queryParameters);
return url;
}
function hasMatchingHost(hostName, url) {
return !hostName || hostName === getHostName(url);
}
function isRedirectStatusCode(status) {
return status === 300 || status === 302 || status === 303 || status === 305;
}
/**
* Return all the GET parameters passed to a page
* This function is different from parseParamsFromURL(),
* where it just extracts all the parameters
* without trying to determine the correct type
*
* @param {string} href - The url to extract
* @param {array} exclude - A list of parameters to exclude from the list
* @return {object} - Key value pair with parameter name as key and value
*/
const getURLParams = (href, exclude = []) => {
const params = {};
try {
const urlObject = new URL(href);
const urlSearch = urlObject.search;
const searchParams = new URLSearchParams(urlSearch);
for (const param of searchParams.entries()) {
if (!exclude.includes(param[0]))
params[param[0]] = param[1];
}
}
catch (e) {
getLogger().error(e);
}
return params;
};
function getTimeOffsetParameter(url) {
const paramString = URLToolkit.parseURL(url).fragment.substr(1);
if (paramString.length === 0) {
return null;
}
const searchParams = new URLSearchParams(paramString);
if (!searchParams.has('t')) {
return null;
}
const timeOffsetValue = Number(searchParams.get('t'));
if (isFiniteNumber(timeOffsetValue)) {
return timeOffsetValue;
}
return null;
}
/**
* Get specified parameters from the search query while
* trying to extract the correct type from each one.
*
* @param {array} extract - The list of parameters to extract
* @return {*}
*/
const parseParamsFromURL = (input, extract) => {
const url = new URL(input);
const params = url.searchParams;
const result = {};
const getTypedParam = (name, defaultValue = undefined, json = false, transform) => {
const param = params.get(name);
let value;
switch (param) {
case 'undefined':
value = undefined;
break;
case 'null':
value = null;
break;
case 'False':
case 'false':
value = false;
break;
case 'True':
case 'true':
value = true;
break;
default:
if (param) {
const num = Number(param);
if (isFiniteNumber(num)) {
value = num;
}
else {
value = param;
}
}
break;
}
if (typeof value === 'string' && json) {
value = safeParseJSON(value);
}
if (typeof value === 'string' && transform) {
value = transform(value);
}
return value !== null && value !== void 0 ? value : defaultValue;
};
extract.forEach((param) => {
result[param.name] = getTypedParam(param.name, param.default, param.json, param.transform);
});
return result;
};
/**
* Safely parse a json, prevent throwing an error on non-parseable input
*
* @param {string} data - Hopefully a JSON string
* @return {*}
*/
const safeParseJSON = (data) => {
let value;
if (typeof data !== 'string')
return data;
try {
value = JSON.parse(data);
}
catch (err) {
// eslint-disable-next-line no-console
console.error(`failed to parse param: ${data}`);
}
return value;
};
/*
* Get a list of the dynamic range formats the user has selected
*
* Type 0: SDR
* Type 2: HDR10
* Type 3: DV
* Type 4: HLG
*
* @returns {array}
*/
function getVideoDynamicRangeFormats(dynamicRangeFormatSDR, dynamicRangeFormatHDR10, dynamicRangeFormatDV, dynamicRangeFormatHLG, averageBitrateCap, peakBitrateCap, clearBitrateCap) {
const videoDynamicRangeFormats = [
{ type: 0, highestPlayableAverageBitRate: undefined, highestPlayablePeakBitRate: undefined },
{ type: 2, highestPlayableAverageBitRate: undefined, highestPlayablePeakBitRate: undefined },
{ type: 3, highestPlayableAverageBitRate: undefined, highestPlayablePeakBitRate: undefined },
{ type: 4, highestPlayableAverageBitRate: undefined, highestPlayablePeakBitRate: undefined },
];
const videoDynamicRangeFormatsMap = {
0: dynamicRangeFormatSDR,
2: dynamicRangeFormatHDR10,
3: dynamicRangeFormatDV,
4: dynamicRangeFormatHLG,
};
for (let formatIndex = 0; formatIndex < videoDynamicRangeFormats.length; ++formatIndex) {
videoDynamicRangeFormats[formatIndex].highestPlayableAverageBitRate = averageBitrateCap;
videoDynamicRangeFormats[formatIndex].highestPlayablePeakBitRate = peakBitrateCap;
videoDynamicRangeFormats[formatIndex].highestPlayablePeakBitRateForClearContent = clearBitrateCap;
}
return videoDynamicRangeFormats.filter(function (format) {
return !!videoDynamicRangeFormatsMap[format.type];
});
}
/*
* Get a list of the video codecs the user has selected
*
* Type 16: H264
* Type 64: HEVC
*
* @returns {array}
*/
function getVideoCodecs(videoCodecH264, videoCodecHEVC, averageBitrateCap, peakBitrateCap) {
const videoCodecs = [
{ type: 16, highestPlayableAverageBitRate: undefined, highestPlayablePeakBitRate: undefined },
{ type: 64, highestPlayableAverageBitRate: undefined, highestPlayablePeakBitRate: undefined },
];
const videoCodecsMap = { 16: videoCodecH264, 64: videoCodecHEVC };
for (let formatIndex = 0; formatIndex < videoCodecs.length; ++formatIndex) {
videoCodecs[formatIndex].highestPlayableAverageBitRate = averageBitrateCap;
videoCodecs[formatIndex].highestPlayablePeakBitRate = peakBitrateCap;
}
return videoCodecs.filter(function (format) {
return !!videoCodecsMap[format.type];
});
}
class AutomationRemote {
constructor() {
this.onStop$ = new Subject();
this._logger = console;
this._playbackData = {
audio: [],
subtitles: [],
variants: [],
};
this._timers$ = {
cpu: undefined,
memory: undefined,
system: undefined,
};
/**
* Register the current parameters or player configuration
* This is used to check if the sockets from the automation server
* are requesting the page to be reloaded
* or the server is trying to load another player url
*
* @param {object} config - The list of GET parameters passed to the URL or other configuration values
* @return {void}
*/
this.setConfig = (config = {}) => {
this._config = JSON.stringify(config);
};
/**
* Trigger a socket command back to the server to perform backend tasks
*
* @return {void}
*/
this.triggerSocketCommand = (command) => {
if (!command)
throw new Error('No command value was passed');
this.socket.emit('action', {
type: 'SOCKETS/TRIGGER_CONTROL_SSH',
command,
});
};
}
/**
* Do setup/teardown if needed on hls change
*
* @param {object} hls
* @setter
* @return {void}
*/
setHls(hls) {
if (!hls) {
this.onStop$.next();
this._hls = null;
this._playbackData = {
audio: [],
subtitles: [],
variants: [],
};
return;
}
this._hls = hls;
this._hls.altAudioOptions$
.pipe(tap((altAudioOptions) => (this._playbackData.audio = altAudioOptions)), takeUntil(this.onStop$))
.subscribe();
this._hls.subtitleOptions$
.pipe(tap((subtitleOptions) => (this._playbackData.subtitles = subtitleOptions)), takeUntil(this.onStop$))
.subscribe();
this._hls.variantOptions$
.pipe(tap((variantOptions) => (this._playbackData.variants = variantOptions)), takeUntil(this.onStop$))
.subscribe();
}
/**
* Set the logger instance
*
* @param {object} logger
* @setter
* @return {void}
*/
setLogger(logger) {
this._logger = logger;
}
/**
* Execute a function that matches the command name
*
* @param {string} command - The function name (ex: seek)
* @param {string} value - The value to pass to the function (ex: 1000)
* @return {*}
*/
applyCommand(command, value) {
if (typeof this[command] === 'function') {
try {
return this[command](value) || true; // Always return a value for the socket server to know we responded
}
catch (e) {
this._logger.error(e);
}
}
}
respondToSocketAction(data, callback) {
const loggerExternals = LoggerExternals$1();
this._logger.qe({ critical: true, name: 'interact', data });
if (!this._hls) {
return this._logger.warn(`hls object not initialized while trying to execute ${data.command}`);
}
switch (data.command) {
case 'cpu':
this._logger.qe({ critical: true, name: 'cpu', data: replaceAll('\n', ' | ', data.value) });
break;
case 'free-memory':
this._logger.qe({ critical: true, name: 'freeMemory', data: replaceAll('\n', ' | ', data.value) });
break;
case 'log-clear':
callback(loggerExternals.logClear());
break;
case 'log-end':
//callback(utils.logEnd());
break;
case 'log-read':
callback({ chunk: data.chunk, log: loggerExternals.compress(loggerExternals.logRead(data.chunk, data.chunkSize)) });
break;
case 'log-read-length':
callback({ size: loggerExternals.logReadLength(), format: 'array' });
break;
case 'log-start':
//callback(Utils.logStart());
break;
case 'memory':
this._logger.qe({ critical: true, name: 'memory', data: getJSMemory() });
break;
case 'access-log':
this._logger.qe({ critical: true, name: 'accessLog', data: { accessLogItems: this._hls.accessLog } });
break;
case 'error-log':
this._logger.qe({ critical: true, name: 'errorLog', data: { errorLogItems: this._hls.errorLog } });
break;
default:
callback(this.applyCommand(data.command, data.value));
}
}
/**
* Connect to a remote socket.io server
*
* @return {object}
*/
initializeSocketService(socketurl, socketid) {
if (!socketurl)
throw new Error('Attempted to call logConnect() without a socket URL');
if (!socketid)
throw new Error('Attempted to call logConnect() without a socket ID');
this.socket = socket_io_min.exports.io(socketurl, { query: { ip: socketid } });
this._logger.info(`Connecting socket service with server: ${socketurl} and id: ${socketid}`);
this.socket.on('connect', () => this._logger.info(`Connected to: ${socketurl}`));
this.socket.on('disconnect', () => this._logger.info(`Disonnected from: ${socketurl}`));
this.socket.on('error', (e) => this._logger.error(e));
this.socket.on('action', this.respondToSocketAction.bind(this));
}
/**
* Load a playlist
*
* @param {object} data - Server object containing data needed for playback
* @param {object} options
* @param {number} initialSeekTime
* @return {void}
*/
loadURL(data, options = {}, initialSeekTime = 0) {
var _a;
const pageUrl = data.fullURL || location.href;
const params = parseParamsFromURL(pageUrl, [
{ name: 'averageBitrateCap' },
{ name: 'dynamicRangeFormatSDR', default: true },
{ name: 'dynamicRangeFormatHDR10', default: true },
{ name: 'dynamicRangeFormatDV', default: true },
{ name: 'dynamicRangeFormatHLG', default: true },
{ name: 'maxHdcpLevel', default: 'TYPE-2', transform: decodeURIComponent },
{ name: 'maxSecurityLevel', transform: decodeURIComponent },
{ name: 'peakBitrateCap' },
{ name: 'requiresCDMAttachOnStart', default: false, json: true },
{ name: 'src' },
{ name: 'rand' },
{ name: 'videoCodecH264', default: false },
{ name: 'videoCodecHEVC', default: false },
]);
// Reload if the server requests a different player
if (this._config !== JSON.stringify(getURLParams(pageUrl, ['src', 'rand'])) && !((_a = getURLParams(location === null || location === void 0 ? void 0 : location.href)) === null || _a === void 0 ? void 0 : _a.dev)) {
location.href = pageUrl;
return;
}
const platformInfo = {
videoDynamicRangeFormats: getVideoDynamicRangeFormats(params.dynamicRangeFormatSDR, params.dynamicRangeFormatHDR10, params.dynamicRangeFormatDV, params.dynamicRangeFormatHLG, params.averageBitrateCap, params.peakBitrateCap, params.clearBitrateCap),
videoCodecs: getVideoCodecs(params.videoCodecH264, params.videoCodecHEVC, params.averageBitrateCap, params.peakBitrateCap),
requiresCDMAttachOnStart: params.requiresCDMAttachOnStart,
maxHdcpLevel: params.maxHdcpLevel,
maxSecurityLevel: params.maxSecurityLevel,
};
const storebag_url = 'https://mediaservices.cdn-apple.com/store_bags/hlsjs_qa/v1/rtc_storebag.json';
const reportingStorebag = new rtc.exports.RTCStorebag.RTCReportingStoreBag(storebag_url, 'HLSJSDemoPlayer', 'com.apple.hlsjs.demo', 'DemoPage', '', 1, 0);
const reportingAgent = new rtc.exports.RTCReportingAgent({
sender: 'HLSJS',
_clientName: 'HLSJSDemoPlayer',
_serviceName: 'com.apple.hlsjs.demo',
reportingStoreBag: reportingStorebag,
applicationName: 'DemoPage',
});
const copyOptions = Object.assign({ appData: { clientName: 'HLSJSDemoPlayer', serviceName: 'com.apple.hlsjs.demo', appName: 'DemoPage', reportingAgent: reportingAgent }, userInfo: { internalBuild: true }, platformInfo }, options);
this._hls.loadSource(data.url, copyOptions, initialSeekTime);
}
/**
* Start playback if video is not detached
*/
play() {
this._hls.desiredRate = 1;
}
/**
* Set the scrubbing speed
*
* @param {number|string} rate
*/
playbackRate(rate) {
this._hls.setRate(rate);
}
/**
* Pause playback
*/
pause() {
this._hls.desiredRate = 0;
}
/**
* Reload page
*/
reload() {
window.location.reload();
}
/**
* Seek to a time value
*
* @param {number} time - Seek position
*/
seekTo(time) {
this._hls.seekTo = time;
}
/**
* Seek to a date
*
* @param {Date} date - Seek position
*/
seekToDate(date) {
this._hls.seekToDate(date);
}
/**
* Set the current audio
*
* @param {string} lang (ex: French)
*/
setAudio(lang) {
const mediaOption = this._playbackData.audio.find((option) => {
return option.MediaSelectionOptionsExtendedLanguageTag === lang || option.MediaSelectionOptionsName === lang;
}) || {};
this._hls.audioSelectedPersistentID = mediaOption.MediaSelectionOptionsPersistentID;
}
/**
* Set the current caption given a language
*
* @param {string} lang (ex: fr)
*/
setCaption(lang) {
const mediaOption = this._playbackData.subtitles.find((option) => {
return option.MediaSelectionOptionsExtendedLanguageTag === lang || option.MediaSelectionOptionsName === lang;
}) || {};
this._hls.subtitleSelectedPersistentID = mediaOption.MediaSelectionOptionsPersistentID;
}
/**
* Start a timer tied to the lifecycle of this class
* that will request a cpu value from the server
*
* @param schedule The periodicity of the timer
* @public
*/
setTimerCpu(schedule = 2000) {
if (this._timers$.cpu)
return;
this._timers$.cpu = timer(200, schedule)
.pipe(tap(() => {
this.triggerSocketCommand('cpu');
}), takeUntil(this.onStop$))
.subscribe();
return this._timers$.cpu;
}
/**
* Start a timer tied to the lifecycle of this class
* that will request the JS memory
*
* @param schedule The periodicity of the timer
* @public
*/
setTimerJSMemory(schedule = 2000) {
if (this._timers$.memory)
return;
this._timers$.memory = timer(200, schedule)
.pipe(tap(() => {
const { jsHeapSizeLimit, totalJSHeapSize, usedJSHeapSize } = getJSMemory();
this._logger.qe({ critical: true, name: 'memory', data: { jsHeapSizeLimit, totalJSHeapSize, usedJSHeapSize } });
}), takeUntil(this.onStop$))
.subscribe();
return this._timers$.memory;
}
/**
* Start a timer tied to the lifecycle of this class
* that will request the system memory (RAM) value from the server
*
* @param schedule The periodicity of the timer
* @public
*/
setTimerSystemMemory(schedule = 2000) {
if (this._timers$.system)
return;
this._timers$.system = timer(200, schedule)
.pipe(tap(() => {
this.triggerSocketCommand('free-memory');
}), takeUntil(this.onStop$))
.subscribe();
return this._timers$.system;
}
/**
* Trigger onStop observable
*
* @return {void}
*/
stop() {
if (!this._hls)
return;
this.onStop$.next();
}
}
let remote;
/**
* Get the JS memory if supported by the browser, otherwise return defaults
*
* @return {object}
*/
const getJSMemory = () => {
const defaultMemory = {
usedJSHeapSize: 0,
jsHeapSizeLimit: 0,
};
const performance = window.performance || {};
return performance.memory || defaultMemory;
};
/**
* Create an automation instance singleton.
*
* @param socketurl The socket server URL
* @param socketid The socket identifier
*/
function initialize(socketurl, socketid) {
if (socketurl && socketid) {
if (!remote) {
remote = new AutomationRemote();
remote.initializeSocketService(socketurl, socketid);
}
return remote;
}
}
/**
* Set the hls instance on the automation remote
*/
function setHls(hls) {
remote === null || remote === void 0 ? void 0 : remote.setHls(hls);
}
/**
* Set the logger instance
*/
function setLogger(logger) {
remote === null || remote === void 0 ? void 0 : remote.setLogger(logger);
}
var VideoCodecRank;
(function (VideoCodecRank) {
VideoCodecRank[VideoCodecRank["DOVI"] = 4] = "DOVI";
VideoCodecRank[VideoCodecRank["HEVC"] = 3] = "HEVC";
VideoCodecRank[VideoCodecRank["VP09"] = 2] = "VP09";
VideoCodecRank[VideoCodecRank["AVC"] = 1] = "AVC";
VideoCodecRank[VideoCodecRank["UNKNOWN"] = 0] = "UNKNOWN";
})(VideoCodecRank || (VideoCodecRank = {}));
var VideoRangeRank;
(function (VideoRangeRank) {
VideoRangeRank[VideoRangeRank["PQ"] = 3] = "PQ";
VideoRangeRank[VideoRangeRank["HLG"] = 2] = "HLG";
VideoRangeRank[VideoRangeRank["SDR"] = 1] = "SDR";
VideoRangeRank[VideoRangeRank["UNKNOWN"] = 0] = "UNKNOWN";
})(VideoRangeRank || (VideoRangeRank = {}));
var AudioCodecRank;
(function (AudioCodecRank) {
AudioCodecRank[AudioCodecRank["ALAC"] = 7] = "ALAC";
AudioCodecRank[AudioCodecRank["FLAC"] = 6] = "FLAC";
AudioCodecRank[AudioCodecRank["EC3"] = 5] = "EC3";
AudioCodecRank[AudioCodecRank["AC3"] = 4] = "AC3";
AudioCodecRank[AudioCodecRank["XHEAAC"] = 3] = "XHEAAC";
AudioCodecRank[AudioCodecRank["AAC"] = 2] = "AAC";
AudioCodecRank[AudioCodecRank["MP3"] = 1] = "MP3";
AudioCodecRank[AudioCodecRank["UNKNOWN"] = 0] = "UNKNOWN";
})(AudioCodecRank || (AudioCodecRank = {}));
var MatchRanking;
(function (MatchRanking) {
MatchRanking[MatchRanking["VALID"] = 1] = "VALID";
MatchRanking[MatchRanking["INVALID"] = 0] = "INVALID";
})(MatchRanking || (MatchRanking = {}));
// List of privacy allowed config headers for ServerInfo
// Headers need to be approved by Privacy. Here is a sample radar on how to request approval
// rdar://78172175
const privacyAllowedLoadConfigHeaders = ['via', 'x-apple-request-uuid'];
const defaultManifestLoadPolicy = () => ({
default: {
// Overall request configs
maxTimeToFirstByteMs: 10000,
maxLoadTimeMs: 20000,
autoRetry: false,
// Retries:
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0, // Maximum delay between retries
},
errorRetry: {
maxNumRetry: 1,
retryDelayMs: 1000,
maxRetryDelayMs: 8000, // Maximum delay between retries
},
},
customURL: {
// Overall request configs
maxTimeToFirstByteMs: 10000,
maxLoadTimeMs: 10000,
autoRetry: false,
// Retries:
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0, // Maximum delay between retries
},
errorRetry: {
maxNumRetry: 1,
retryDelayMs: 1000,
maxRetryDelayMs: 8000, // Maximum delay between retries
},
},
});
const fragTimeoutRetryDefaultConfig = {
// Timeout Retries default value
maxNumRetry: 4,
retryDelayMs: 0,
maxRetryDelayMs: 0, // Maximum delay between retries
};
const fragErrorRetryDefaultConfig = {
// Error Retries default value
maxNumRetry: 6,
retryDelayMs: 1000,
maxRetryDelayMs: 8000, // Maximum delay between retries
};
const defaultSessionDataAutoLoad = {
'com.apple.hls.chapters': true,
};
const defaultCertRetry = {
maxNumRetry: 0,
retryDelayMs: 0,
maxRetryDelayMs: 0, // Maximum delay between retries
};
const defaultCertLoadPolicy = {
default: {
maxTimeToFirstByteMs: 5000,
maxLoadTimeMs: 20000,
autoRetry: false,
timeoutRetry: defaultCertRetry,
errorRetry: defaultCertRetry,
},
customURL: {
maxTimeToFirstByteMs: 10000,
maxLoadTimeMs: 20000,
autoRetry: false,
timeoutRetry: defaultCertRetry,
errorRetry: defaultCertRetry,
},
};
// max overall load time should be ~30s ish
const defaultKeyRetry = {
maxNumRetry: 8,
retryDelayMs: 1000,
maxRetryDelayMs: 20000,
backoff: 'linear',
};
const timeoutKeyRetry = Object.assign(Object.assign({}, defaultKeyRetry), { maxNumRetry: 1 });
const defaultKeyLoadPolicy = {
default: {
maxTimeToFirstByteMs: 5000,
maxLoadTimeMs: 20000,
autoRetry: false,
timeoutRetry: timeoutKeyRetry,
errorRetry: defaultKeyRetry,
},
customURL: {
maxTimeToFirstByteMs: 10000,
maxLoadTimeMs: 20000,
autoRetry: false,
timeoutRetry: timeoutKeyRetry,
errorRetry: defaultKeyRetry,
},
};
const defaultTrickPlaybackConfig = {
enabled: true,
minIframeDuration: 8,
};
const hlsDefaultConfig = {
autoStartLoad: true,
startPosition: NaN,
defaultAudioCodec: void 0,
defaultVideoCodec: void 0,
debug: false,
debugLevel: 'info',
buildType: void 0,
minFramesBeforeSwitchingLevel: 11,
minTargetDurations: 3,
maxBufferLength: 60,
maxBufferHole: 0.5,
maxSeekHole: 2,
nudgeFromEventSeek: true,
jaggedSeekTolerance: 0,
discontinuitySeekTolerance: 2,
bufferedSegmentEjectionToleranceMs: 0.5,
almostDryBufferSec: 0.5,
maxTotalDurationTolerance: 0.1,
lowBufferThreshold: 0.5,
lowBufferWatchdogPeriod: 0.5,
highBufferWatchdogPeriod: 3,
seekWatchdogPeriod: 5,
nudgeOffset: 0.1,
nudgeMaxRetry: 3,
maxFragLookUpTolerance: 0.2,
initialLiveManifestSize: 1,
liveSyncDurationCount: 3,
liveMaxLatencyDurationCount: Infinity,
liveSyncDuration: void 0,
liveMaxLatencyDuration: void 0,
liveFlushExpiredFrags: true,
liveMaxUnchangedPlaylistRefresh: 3,
liveEdgeForZeroStartPositon: false,
livePlaylistUpdateStaleness: 2,
livePlaylistDurationNudge: 0.001,
allowFastSwitchUp: false,
minMatchGroupDuration: 5,
desiredIframeFPS: 8,
initialIframeFPS: 6,
minRemainingTimeInMediaPipeline: 3,
leftMediaTimeToAutoPause: 10,
startTargetDurationFactor: 0.9,
minRequiredStartDuration: 4,
maxRequiredStartDuration: 15,
enableWorker: true,
enableWebCrypto: true,
keySystemPreference: void 0,
useMultipleKeySessions: false,
enablePlayReadyKeySystem: false,
useMediaKeySystemAccessFilter: false,
playReadyMessageFormat: 'utf16',
startLevel: void 0,
livePlaylistRefreshDelay: 2500,
liveMinPlayingBufferLen: 5,
enableIFramePreloading: true,
useMediaCapabilities: false,
enableID3Cues: true,
certLoadPolicy: defaultCertLoadPolicy,
keyLoadPolicy: defaultKeyLoadPolicy,
manifestLoadPolicy: defaultManifestLoadPolicy(),
trickPlaybackConfig: defaultTrickPlaybackConfig,
playlistLoadPolicy: {
default: {
// Overall request configs
maxTimeToFirstByteMs: 10000,
maxLoadTimeMs: 20000,
autoRetry: false,
// Retries:
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0, // Maximum delay between retries
},
errorRetry: {
maxNumRetry: 2,
retryDelayMs: 1000,
maxRetryDelayMs: 8000, // Maximum delay between retries
},
},
customURL: {
// Overall request configs
maxTimeToFirstByteMs: 10000,
maxLoadTimeMs: 10000,
autoRetry: false,
// Retries:
timeoutRetry: {
maxNumRetry: 2,
retryDelayMs: 0,
maxRetryDelayMs: 0, // Maximum delay between retries
},
errorRetry: {
maxNumRetry: 2,
retryDelayMs: 1000,
maxRetryDelayMs: 8000, // Maximum delay between retries
},
},
},
fragLoadPolicy: {
default: {
// Overall request configs
maxTimeToFirstByteMs: 5000,
maxLoadTimeMs: 20000,
autoRetry: false,
// Retries:
timeoutRetry: fragTimeoutRetryDefaultConfig,
errorRetry: fragErrorRetryDefaultConfig,
forceContentLenCheckIfNoHeader: false,
reportCDNServer: true,
},
customURL: {
// Overall request configs
maxTimeToFirstByteMs: 10000,
maxLoadTimeMs: 20000,
autoRetry: false,
// Retries:
timeoutRetry: fragTimeoutRetryDefaultConfig,
errorRetry: fragErrorRetryDefaultConfig,
reportCDNServer: true,
},
},
steeringManifestLoadPolicy: defaultManifestLoadPolicy(),
maxNumAddLevelToPenaltyBox: 4,
firstAudioMustOverlapVideoStart: false,
keyMinHoldTimeBeforeCleanup: 15000,
startFragPrefetch: false,
appendErrorMaxRetry: 3,
alwaysResetOnNewCC: false,
// loader: XhrLoader, // deprecated in favor of rxjs fetch
// loader: FetchLoader, // deprecated in favor of rxjs fetch
fLoader: void 0,
pLoader: void 0,
xhrSetup: void 0,
// fetchSetup: undefined,
// abrController: AbrController, // deprecated in favor or redux/rxjs
// bufferController: BufferController, // deprecated in favor or redux/rxjs
// #if altaudio
// audioStreamController: AudioStreamController, // deprecated in favor or redux/rxjs
// audioTrackController: AudioTrackController, // deprecated in favor or redux/rxjs
iframeMaxExitSeekDuration: 2000,
iframeStallMaxRetry: 5,
audioPrimingDelay: 0,
// #endif
// #if subtitle
// subtitleStreamController: SubtitleStreamController, // deprecated in favor or redux/rxjs
// subtitleTrackController: SubtitleTrackController, // deprecated in favor or redux/rxjs
// timelineController: TimelineController, // deprecated in favor or redux/rxjs
enableCEA708Captions: true,
customTextTrackCueRenderer: false,
enableWebVTT: true,
captionsTextTrack1Label: 'English',
captionsTextTrack1LanguageCode: 'en',
captionsTextTrack2Label: 'Spanish',
captionsTextTrack2LanguageCode: 'es',
enableDualTrackSelection: false,
condenseSubtitleTrack: false,
nativeTextTrackChangeHandling: true,
earlyFragTolerance: 7,
vttConcurrentLoadCount: 1,
trottleCheckInterval: 2000,
subtitleLeadTime: 30,
lateTolerance: 2,
// #endif
stretchShortVideoTrack: false,
forceKeyFrameOnDiscontinuity: true,
useFirstLevelAtIncompatDiscontinuity: true,
abrBandwidthEstimator: 'bandwidth-history-controller',
abrEwmaDefaultEstimate: 500000,
abrDefaultEstimate: 500000,
abrBandWidthFactor: 0.95,
abrBandWidthUpFactor: 0.9,
abrMaxWithRealBitrate: false,
maxStarvationDelay: 4,
maxLoadingDelay: 4,
minAutoBitrate: 0,
enableRtcReporting: false,
rtcIntervalTimeout: 300000,
rtcSender: 'HLSJS',
rtcSessionTag: 'none',
useHTTPPlaybackSessionId: false,
warmupCdms: false,
enablePerformanceLogging: false,
overridePlaybackRate: false,
nativeControlsEnabled: false,
useCustomMediaFunctions: true,
seekEventThrottleMs: 150,
enableAdaptiveStartup: true,
bandwidthHistoryWindowSize: 120000,
bandwidthHistoryTTL: 600000,
bandwidthHistoryAggregationMethod: 'quadratic-time-weighted',
bandwidthHistoryGetEstimateThrottleMs: 1000,
defaultTargetDuration: 10,
targetStartupMs: 4000,
adaptiveStartupMetricsOverride: {
maxValidHeight: 1080,
maxValidBitrate: Infinity,
maxPreferredBitrate: Infinity, // the purpose of `maxPreferredBitrate` is to limit startup time. In adaptive startup we use `targetStartupMs` instead.
},
bandwidthHistoryStorageKey: 'AppleHLS-bandwidth-estimation',
storageKeyPrefix: 'AppleHLS-',
storage: {
get: typeof localStorage === 'undefined' ? undefined : localStorage.getItem.bind(localStorage),
set: typeof localStorage === 'undefined' ? undefined : localStorage.setItem.bind(localStorage),
},
minFragmentCount: 10,
minPlaylistCount: 5,
enableCDNFallback: true,
enableQueryParamsForITunes: false,
gapless: false,
useViewportSizeForLevelCap: false,
statDefaults: {
playlistLoadTimeMs: 500,
playlistParseTimeMs: 50,
fragParseTimeMs: 50,
fragBufferCreationDelayMs: 200,
dataFragAppendMs: 50,
initFragAppendMs: 50,
},
disableVideoCodecList: new Set([
// codecs that will be ignored during playback
]),
disableAudioCodecList: new Set([AudioCodecRank.ALAC, AudioCodecRank.FLAC, AudioCodecRank.XHEAAC]),
useHighestVideoCodecPrivate: true,
sessionDataAutoLoad: defaultSessionDataAutoLoad, // Attributes listed here will be auto-fetched if its URI is given.
};
const NoMediaOptionKey = { itemId: 'Nah', mediaOptionId: 'Nah' };
const NoMediaOption = Object.assign(Object.assign({}, NoMediaOptionKey), { mediaOptionType: undefined });
const isEnabledMediaOption = (mediaOptionInfo) => {
const { itemId, mediaOptionId } = mediaOptionInfo;
return itemId !== 'Nah' && mediaOptionId !== 'Nah';
};
const mediaOptionKeyEquals = (firstMediaOption, secondMediaOption) => {
return firstMediaOption.itemId === secondMediaOption.itemId && firstMediaOption.mediaOptionId === secondMediaOption.mediaOptionId;
};
var MediaOptionType;
(function (MediaOptionType) {
MediaOptionType[MediaOptionType["Variant"] = 0] = "Variant";
MediaOptionType[MediaOptionType["AltAudio"] = 1] = "AltAudio";
MediaOptionType[MediaOptionType["Subtitle"] = 2] = "Subtitle";
})(MediaOptionType || (MediaOptionType = {}));
const MediaOptionNames = ['variant', 'altAudio', 'subtitle'];
const MediaOptionTypes = [MediaOptionType.Variant, MediaOptionType.AltAudio, MediaOptionType.Subtitle];
const AVMediaOptionTypes = [MediaOptionType.Variant, MediaOptionType.AltAudio];
var SourceBufferType;
(function (SourceBufferType) {
SourceBufferType[SourceBufferType["Variant"] = 0] = "Variant";
SourceBufferType[SourceBufferType["AltAudio"] = 1] = "AltAudio";
})(SourceBufferType || (SourceBufferType = {}));
const SourceBufferNames = ['variant', 'altAudio'];
function mediaOptionTypeToSourceBufferType(optionType) {
switch (optionType) {
case MediaOptionType.Variant:
return SourceBufferType.Variant;
case MediaOptionType.AltAudio:
return SourceBufferType.AltAudio;
default:
return null;
}
}
function sourceBufferTypeToMediaOptionType(sbType) {
return sbType === SourceBufferType.Variant ? MediaOptionType.Variant : MediaOptionType.AltAudio;
}
function initSegmentEquals(a, b) {
const equals = a && b && a.itemId === b.itemId && a.mediaOptionId === b.mediaOptionId && a.discoSeqNum === b.discoSeqNum && a.keyId === b.keyId;
return equals;
}
var Allowed;
(function (Allowed) {
Allowed[Allowed["NO"] = 0] = "NO";
Allowed[Allowed["YES"] = 1] = "YES";
})(Allowed || (Allowed = {}));
var MediaTypeFourCC;
(function (MediaTypeFourCC) {
MediaTypeFourCC["UNKNOWN"] = "unkn";
MediaTypeFourCC["VIDEO"] = "vide";
MediaTypeFourCC["AUDIO"] = "soun";
MediaTypeFourCC["SUBTITLE"] = "sbtl";
MediaTypeFourCC["CLOSEDCAPTION"] = "clcp";
})(MediaTypeFourCC || (MediaTypeFourCC = {}));
const BinarySearch = {
/**
* Searches for an item in an array which matches a certain condition.
* This requires the condition to only match one item in the array,
* and for the array to be ordered.
*
* @param {Array} list The array to search.
* @param {Function} comparisonFunction
* Called and provided a candidate item as the first argument.
* Should return:
* > -1 if the item should be located at a lower index than the provided item.
* > 1 if the item should be located at a higher index than the provided item.
* > 0 if the item is the item you're looking for.
*
* @return {*} The object if it is found or undefined otherwise.
*/
search: function (list, comparisonFunction) {
let minIndex = 0;
let maxIndex = (list === null || list === void 0 ? void 0 : list.length) - 1;
let currentIndex;
let currentElement;
while (minIndex <= maxIndex) {
currentIndex = ((minIndex + maxIndex) / 2) | 0;
currentElement = list[currentIndex];
const comparisonResult = comparisonFunction(currentElement);
if (comparisonResult > 0) {
minIndex = currentIndex + 1;
}
else if (comparisonResult < 0) {
maxIndex = currentIndex - 1;
}
else {
return currentElement;
}
}
return null;
},
};
var BinarySearch$1 = BinarySearch;
/**
* Fragment finder utils, providing methods for determining next fragment to fetch
*
*
*
*
*/
function fragTag(frag, level) {
return `sn/cc/level: ${frag.mediaSeqNum}/${frag.discoSeqNum}/${level}`;
}
function rangeString(frag) {
let result = 'N/A';
if (frag.start >= 0 && frag.duration >= 0) {
result = `${frag.start.toFixed(2)}-${(frag.start + frag.duration).toFixed(2)}`;
}
return result;
}
const FragmentFetchHelper = {
/**
* Finds a fragment based on the SN of the previous fragment and current buffer.
* @param fragPrevious - The last frag successfully appended
* @param fragments - The array of fragments in level
* @param bufferEnd - The end of the contiguous buffer range within which playhead is
* @param end - End time of the level
* @param maxFragLookUpTolerance - acceptable tolerance limit
*/
findFragmentBySNAndBuffer: function (fragPrevious, fragments, bufferEnd = 0, end = 0, maxFragLookUpTolerance = 0) {
let foundFrag;
const fragNext = fragPrevious ? fragments[fragPrevious.mediaSeqNum - fragments[0].mediaSeqNum + 1] : null;
if (bufferEnd < end) {
if (bufferEnd > end - maxFragLookUpTolerance) {
maxFragLookUpTolerance = 0;
}
// Prefer the next fragment if it's within tolerance
if (fragNext && !this.fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, fragNext)) {
foundFrag = fragNext;
}
else {
foundFrag = BinarySearch.search(fragments, this.fragmentWithinToleranceTest.bind(null, bufferEnd, maxFragLookUpTolerance));
}
}
else {
// reach end of playlist
foundFrag = fragments[fragments.length - 1];
}
return foundFrag;
},
fragmentWithinToleranceTest: function (bufferEnd, maxFragLookUpTolerance, candidate) {
// offset should be within fragment boundary - config.maxFragLookUpTolerance
// this is to cope with situations like
// bufferEnd = 9.991
// frag[Ø] : [0,10]
// frag[1] : [10,20]
// bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here
// frag start frag start+duration
// |-----------------------------|
// <---> <--->
// ...--------><-----------------------------><---------....
// previous frag matching fragment next frag
// return -1 return 0 return 1
// logger.info(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`);
// Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments
const candidateLookupTolerance = Math.min(maxFragLookUpTolerance, candidate.duration);
if (candidate.start + candidate.duration - candidateLookupTolerance <= bufferEnd) {
return 1;
}
else if (candidate.start - candidateLookupTolerance > bufferEnd && candidate.start) {
// if maxFragLookUpTolerance will have negative value then don't return -1 for first element
return -1;
}
return 0;
},
};
var FragmentFetchHelper$1 = FragmentFetchHelper;
const loggerName$9 = { name: 'disco' };
const DiscoHelper = {
startFragmentInCC: function (fragments, cc, candidate) {
let rank = cc - candidate.discoSeqNum;
if (rank === 0) {
const fragPrevious = fragments[candidate.mediaSeqNum - fragments[0].mediaSeqNum - 1];
rank = fragPrevious && fragPrevious.discoSeqNum === candidate.discoSeqNum ? -1 : 0;
}
return rank;
},
endFragmentInCC: function (fragments, cc, candidate) {
let rank = cc - candidate.discoSeqNum;
if (rank === 0) {
const fragNext = fragments[candidate.mediaSeqNum - fragments[0].mediaSeqNum + 1];
rank = fragNext && fragNext.discoSeqNum === candidate.discoSeqNum ? 1 : 0;
}
return rank;
},
findStartEndFragmentsInCC: function (fragments, cc, logger) {
let startFrag;
let endFrag;
if ((fragments === null || fragments === void 0 ? void 0 : fragments.length) > 0 && isFiniteNumber(cc)) {
startFrag = BinarySearch.search(fragments, DiscoHelper.startFragmentInCC.bind(null, fragments, cc));
endFrag = BinarySearch.search(fragments, DiscoHelper.endFragmentInCC.bind(null, fragments, cc));
}
if (!endFrag) {
logger.info(loggerName$9, `cc ${cc} does not appear in fragments anymore`);
}
// handle bogus results due to undefined cc
if (startFrag && !isFiniteNumber(startFrag.discoSeqNum)) {
logger.info(loggerName$9, `findStartEndFragmentsInCC startFrag ${startFrag.mediaSeqNum} has undefined cc ${cc}`);
startFrag = undefined;
}
if (endFrag && !isFiniteNumber(endFrag.discoSeqNum)) {
logger.info(loggerName$9, `findStartEndFragmentsInCC endFrag ${endFrag.mediaSeqNum} has undefined cc ${cc}`);
endFrag = undefined;
}
return { startFrag, endFrag };
},
getTimeRangeDictForCC: function (fragments, cc, logger) {
const ccFragRange = DiscoHelper.findStartEndFragmentsInCC(fragments, cc, logger);
const { startFrag, endFrag } = ccFragRange;
const start = startFrag.start;
const end = endFrag.start + endFrag.duration;
return { start, end };
},
getTimeRangeForCC: function (fragments, cc, logger) {
const ccFragRange = DiscoHelper.findStartEndFragmentsInCC(fragments, cc, logger);
const { startFrag, endFrag } = ccFragRange;
let ccTimeRange = [];
if (startFrag && endFrag) {
ccTimeRange = [startFrag.start, endFrag.start + endFrag.duration];
}
return ccTimeRange;
},
snapToCCTimeRange: function (targetTime, fragments, cc, logger) {
const ccRange = DiscoHelper.getTimeRangeForCC(fragments, cc, logger);
if (!(ccRange === null || ccRange === void 0 ? void 0 : ccRange.length)) {
return targetTime;
}
return Math.min(ccRange[1], Math.max(ccRange[0], targetTime));
},
getMinTimeForCC(mainFragments, audioFragments, cc, logger) {
if (!(mainFragments === null || mainFragments === void 0 ? void 0 : mainFragments.length)) {
return 0;
}
// const fragments = this.variantManager.getVariantInfoIfValid(this.currentVariantId)?.details?.fragments;
let startCCTime = 0;
if (isFiniteNumber(cc) && mainFragments) {
const ccRange = DiscoHelper.getTimeRangeForCC(mainFragments, cc, logger);
if (ccRange) {
const audioCCRange = DiscoHelper.getTimeRangeForCC(audioFragments, cc, logger); // this.audioStreamController?.getAudioTimeRangeForCC(cc);
if (audioCCRange === null || audioCCRange === void 0 ? void 0 : audioCCRange.length) {
startCCTime = Math.max(audioCCRange[0], ccRange[0]);
}
else {
startCCTime = ccRange[0];
}
}
}
return startCCTime;
},
discoSeqNumForTime(fragments, pos, tolerance = 0) {
const foundFrag = BinarySearch.search(fragments, FragmentFetchHelper$1.fragmentWithinToleranceTest.bind(null, pos, tolerance));
return foundFrag === null || foundFrag === void 0 ? void 0 : foundFrag.discoSeqNum;
},
};
var DiscoHelper$1 = DiscoHelper;
const VOID = of(void 0);
/**
* Wait for some condition to be true on an observable
* @param source Source observable
* @param condition Condition to apply
* @param times How many times to allow observable to fire before completing. By default, 1
*/
function waitFor(source, condition, times = 1) {
return source.pipe(filter(condition), take(times));
}
/*
* Simple clock abstraction to help transform between clocks and their timelines
*
* 2020 Apple Inc. All rights reserved.
*/
/**
* Convert a SyncTimelineValue into a different timeline
*
* @param sourceValue The value to map to a different timeline
* @param destTimeline The timeline to map into
*
* @returns A new SyncTimelineValue in destTimeline
*/
function mapValueToTimeline(sourceValue, destTimeline) {
const sourceTimeline = sourceValue.timeline;
const newValue = ((sourceValue.seconds - sourceTimeline.rootTimeSeconds) / sourceTimeline.rate) * destTimeline.rate + destTimeline.rootTimeSeconds;
return { seconds: newValue, timeline: destTimeline };
}
class IframeClock {
constructor() {
this._timeline = null;
}
get forward() {
var _a;
return ((_a = this.timeline) === null || _a === void 0 ? void 0 : _a.rate) > 0;
}
get isStarted() {
return Boolean(this.hostClock);
}
start(timeline) {
this.stopTime = null;
this._timeline = Object.assign({}, timeline);
const performanceTimeline = { rootTimeSeconds: performance.now() / 1000, rate: 1 };
this.hostClock = {
timeline: performanceTimeline,
getCurrentTime: () => {
return { seconds: performance.now() / 1000, timeline: performanceTimeline };
},
};
}
pause() {
if (this.isStarted) {
this.stopTime = this.getCurrentTime();
}
}
stop() {
this.pause();
this.hostClock = null;
this._timeline = null;
}
// ClockSyncAdapter interface
get timeline() {
return this._timeline;
}
getCurrentTime() {
if (this.stopTime) {
return this.stopTime;
}
// map the performance clock into the iframe timeline
const hostValue = this.hostClock.getCurrentTime();
const myValue = mapValueToTimeline(hostValue, this.timeline);
return myValue;
}
}
/**
* This is a view into our media element we're appending into. We don't care about any time other
* than the buffer end, so that's our time source
*/
class MediaAppendClock {
constructor(_timeline) {
this._timeline = _timeline;
// our start time is our current buffer end
this.mediaRootTime = this.lastTimeSeconds = _timeline.rootTimeSeconds;
}
// ClockSyncAdapter interface
get timeline() {
return Object.assign({}, this._timeline);
}
getCurrentTime() {
// the latest time we know about
return { seconds: this.lastTimeSeconds, timeline: Object.assign({}, this._timeline) };
}
}
/*
* Trickplay implementation
*
* 2020 Apple Inc. All rights reserved.
*/
const loggerName$8 = { name: 'ifm' };
/**
*
* A sort of 'controller' for iframes
*
* Managages two clocks:
* The iframe clock has a real time host and is untied to the media progression
* The media append clock represents the media element, where we are actually appending the iframes
*
* The responsibility of this class is to supply the iframes fragments via nextFragment so that
* the media append clock keeps pace with the iframe clock (no drift)
*
*/
class IframeMachine {
constructor(config, logger) {
this.config = config;
this.logger = logger;
// Fragments we've modified and need to cleanup
this.scaledFragments = [];
// this is the 'iframe clock', running at the iframe rate
// with a timebase anchored at the time trickplay startart
this.iframeClock = new IframeClock();
this.hasMore$ = new BehaviorSubject(true);
this.logger = logger.child(loggerName$8);
}
destroy() {
this.stop();
}
resetScaledSegments() {
this.scaledFragments = [];
}
get anchorFrag() {
return this.scaledFragments.length ? this.scaledFragments[0] : null;
}
get lastFrag() {
return this.scaledFragments.length ? this.scaledFragments.slice(-1)[0] : null;
}
get isStarted() {
return Boolean(this.iframeClock.isStarted);
}
get iframeRate() {
var _a, _b;
return (_b = (_a = this.iframeClock.timeline) === null || _a === void 0 ? void 0 : _a.rate) !== null && _b !== void 0 ? _b : 0;
}
get iframeClockTimeSeconds() {
return Math.max(0, this.iframeClock.getCurrentTime().seconds);
}
get mediaAppendClockTimeSeconds() {
var _a, _b;
return (_b = (_a = this.mediaAppendClock) === null || _a === void 0 ? void 0 : _a.getCurrentTime().seconds) !== null && _b !== void 0 ? _b : 0;
}
get mediaRootTime() {
var _a;
return (_a = this.mediaAppendClock) === null || _a === void 0 ? void 0 : _a.mediaRootTime;
}
pause() {
this.iframeClock.pause();
}
stop() {
this.logger.debug('stop');
this.hasMore$.next(true);
this.iframeClock.stop();
this.mediaAppendClock = null;
this.resetScaledSegments();
}
checkHasMore() {
this.hasMore$.next(true);
}
/**
* Re-anchor the iframe clock
* @param iframeFragments
* @param audioFragments
* @param rate
* @param pos
*/
startClocksAndGetFirstFragment(iframeFragments, audioFragments, rate, pos, disco) {
this.logger.info(`startClocksAndGetFirstFragment: rate(${rate}), pos(${pos})`);
let anchorFrag = BinarySearch.search(iframeFragments, FragmentFetchHelper$1.fragmentWithinToleranceTest.bind(null, pos, 0.0001));
if (!anchorFrag && pos >= iframeFragments[iframeFragments.length - 1].start) {
this.logger.info(`startClocksAndGetFirstFragment: pick last frag, start=${iframeFragments[iframeFragments.length - 1].start}`);
anchorFrag = iframeFragments[iframeFragments.length - 1];
}
if (!anchorFrag) {
this.logger.error(`startClocksAndGetFirstFragment => no anchorFrag for time ${pos}`);
this.hasMore$.next(false);
return null;
}
const nextDisco = isFiniteNumber(disco) ? disco : anchorFrag.discoSeqNum;
const startCCTime = DiscoHelper$1.getMinTimeForCC(iframeFragments, audioFragments, nextDisco, this.logger);
const newPosition = isFiniteNumber(disco) && rate > 1 ? startCCTime : pos;
let newMediaRootTime;
if (rate > 1) {
// fast forward should always have enough to anchor at the current point
newMediaRootTime = Math.ceil(newPosition);
}
else {
newMediaRootTime = Math.ceil(startCCTime);
}
this.iframeClock.start({ rootTimeSeconds: newPosition, rate });
this.mediaAppendClock = new MediaAppendClock({ rootTimeSeconds: newMediaRootTime, rate: 1 });
return { frag: anchorFrag, newMediaRootTime };
}
getNextFragment(fragments, bufferEnd, rate) {
const lastFrag = this.lastFrag;
const { iframeClock, mediaAppendClock } = this;
const iframeTimeline = iframeClock.timeline;
mediaAppendClock.lastTimeSeconds = bufferEnd;
this.logger.qe({
critical: true,
name: 'iframes',
data: { maxMediaTime: bufferEnd, rate, ifmat: this.mediaAppendClock.timeline.rootTimeSeconds, ifbt: this.iframeClock.timeline.rootTimeSeconds },
});
const ixStep = iframeClock.forward ? 1 : -1;
let ix = Math.max(0, Math.min(lastFrag.mediaSeqNum - fragments[0].mediaSeqNum + ixStep, fragments.length - 1));
let nextFrag;
if (lastFrag.mediaSeqNum !== fragments[ix].mediaSeqNum) {
// always allow first step to work for EOS cleanliness
do {
nextFrag = fragments[ix];
const seconds = iframeClock.forward ? nextFrag.start : nextFrag.start + nextFrag.duration;
const startAppendTime = mapValueToTimeline({ seconds, timeline: iframeTimeline }, mediaAppendClock.timeline);
if (startAppendTime.seconds >= bufferEnd && ((iframeClock.forward && seconds >= this.iframeClockTimeSeconds) || (!iframeClock.forward && seconds <= this.iframeClockTimeSeconds))) {
break;
}
ix += ixStep;
} while (ix > 0 && ix < fragments.length);
}
if (!nextFrag) {
// stream controller should have stopped and waited until we said so, and we should have found something new
this.logger.error(`getNextFragment(bufferEnd: ${bufferEnd}) => no more frags, but we should have found an end fragment, setting hasMore to false`);
this.hasMore$.next(false);
}
return { frag: nextFrag };
}
/**
* Get the next fragment to fetch
* @param iframeFragments
* @param audioFragments
* @param rate
* @param pos
* @param bufferLen
* @return anchor fragment
*/
nextFragment(iframeFragments, audioFragments, rate, pos) {
let foundFrag;
let rateSwitchPos;
if (this.isStarted && rate !== this.iframeRate) {
rateSwitchPos = this.iframeClockTimeSeconds;
this.stop();
}
if (!this.isStarted) {
foundFrag = this.startClocksAndGetFirstFragment(iframeFragments, audioFragments, rate, rateSwitchPos !== null && rateSwitchPos !== void 0 ? rateSwitchPos : pos);
if (!foundFrag) {
return;
}
}
else {
foundFrag = this.getNextFragment(iframeFragments, pos, rate);
if (!foundFrag.frag) {
return;
}
else if (foundFrag.frag.discoSeqNum !== this.anchorFrag.discoSeqNum) {
const iframeTimeSeconds = this.iframeClockTimeSeconds;
this.logger.info(`nextFragment iframeClockTime(${iframeTimeSeconds.toFixed(3)}) => found new disco, ${this.anchorFrag.discoSeqNum} to ${foundFrag.frag.discoSeqNum}`);
this.stop();
const { newMediaRootTime } = this.startClocksAndGetFirstFragment(iframeFragments, audioFragments, rate, iframeTimeSeconds, foundFrag.frag.discoSeqNum);
foundFrag.newMediaRootTime = newMediaRootTime;
}
}
const { frag, newMediaRootTime } = foundFrag;
const updatedFrag = this.handleNextFrag(iframeFragments, frag);
const appendStart = updatedFrag.iframeMediaStart, appendEnd = appendStart + updatedFrag.iframeMediaDuration;
this.logger.info(`nextFragment iframeClockTime(${this.iframeClockTimeSeconds.toFixed(3)}) => picked frag: ${fragTag(updatedFrag)}, source range: ${rangeString(updatedFrag)}, media append times: ${appendStart.toFixed(3)}-${appendEnd.toFixed(3)}${isFiniteNumber(newMediaRootTime) ? ', newMediaRootTime: ' + newMediaRootTime.toFixed(3) : ''}`);
return Object.assign(Object.assign({}, foundFrag), { frag: updatedFrag });
}
handleNextFrag(fragments, frag) {
const cpFrag = Object.assign(Object.assign({}, frag), { iframeMediaStart: NaN, iframeMediaDuration: NaN });
const { mediaAppendClock, iframeClock } = this;
// update our bounds just in case we're live
this.iframeClockBounds = DiscoHelper$1.getTimeRangeDictForCC(fragments, cpFrag.discoSeqNum, this.logger);
// the start of our iframe is the latest time of the media append clock
const bufferEnd = mediaAppendClock.getCurrentTime().seconds;
const iframeRate = iframeClock.timeline.rate;
if (!isFiniteNumber(cpFrag.iframeOriginalStart)) {
// iframe mode shouldn't have mangled frag.start
// we need the original frag.start to calculate initPTS.
// stash it in frag.iframeOriginalStart
cpFrag.iframeOriginalStart = cpFrag.start;
}
cpFrag.start = cpFrag.iframeMediaStart = bufferEnd;
cpFrag.iframeMediaDuration = Math.max(cpFrag.duration / Math.abs(iframeRate), 1 / this.config.minIframeDuration);
// track which frags we've modifed - TODO find a better way to do this
this.scaledFragments.push(cpFrag);
// check for EOS
if (this.isEndFrag(fragments, cpFrag)) {
this.logger.info(`checkEOS(frag: ${cpFrag.mediaSeqNum}) => found end frag, setting hasMore to false`);
this.hasMore$.next(false);
}
return cpFrag;
}
get hasMore() {
return this.hasMore$.value;
}
// anchor isn't necessary valid in this function, so don't reference it
/**
* Wait for there to be more fragments to be downloaded
*/
handleWaitForMore() {
this.logger.trace(`handleWaitForMore(): isStarted: ${this.isStarted}`);
if (!this.isStarted) {
return VOID;
}
const currentIframeTime = this.iframeClock.getCurrentTime();
const iframeClockTime = currentIframeTime.seconds;
const rate = currentIframeTime.timeline.rate;
const edgeTime = rate > 1 ? this.iframeClockBounds.end : this.iframeClockBounds.start;
const diff = edgeTime - currentIframeTime.seconds;
const wait = diff / rate; // the +/- work out with the rate and the diff
this.logger.info(`handleWaitForMore(): iframeClockTime: ${iframeClockTime}, edgeTime: ${edgeTime}, diff ${diff} => wait: ${wait}`);
return waitFor(this.hasMore$, (hasMore) => hasMore === true).pipe(tap(() => {
this.logger.info(`handleWaitForMore(): iframeClockTime: ${iframeClockTime} => hasMore became true while waiting`);
}));
}
isEndFrag(fragments, frag) {
const startFrag = fragments[0];
const endFrag = fragments[fragments.length - 1];
const ff = this.iframeClock.forward;
const rw = !ff;
return (rw && (startFrag === null || startFrag === void 0 ? void 0 : startFrag.mediaSeqNum) === frag.mediaSeqNum) || (ff && (endFrag === null || endFrag === void 0 ? void 0 : endFrag.mediaSeqNum) === frag.mediaSeqNum);
}
}
function createIframeMachine(config, logger) {
return new Observable((subscriber) => {
const iframeMachine = new IframeMachine(config, logger);
subscriber.next(iframeMachine);
return () => {
// cleanup
};
});
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a 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);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
/**
* Use of this source code is governed by an MIT-style license that
* can be found in the LICENSE file at https://github.com/cartant/rxjs-spy
*/
/*tslint:disable:no-use-before-declare*/
function tag(tag) {
return function tagOperation(source) {
return source.lift(new TagOperator(tag));
};
}
var TagOperator = /*#__PURE__*/function () {
// It would be better if this were a symbol. However ...
// error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol.
function TagOperator(tag) {
_classCallCheck(this, TagOperator);
_defineProperty(this, "tag", void 0);
this.tag = tag;
}
_createClass(TagOperator, [{
key: "call",
value: function call(subscriber, source) {
return source.subscribe(subscriber);
}
}]);
return TagOperator;
}();
// Key request state from a macro level (substates in KeyRequestContext)
var KeyRequestMacroState;
(function (KeyRequestMacroState) {
KeyRequestMacroState["MustRequestResponse"] = "MustRequestResponse";
KeyRequestMacroState["WaitingForKeyResponse"] = "WaitingForKeyResponse";
KeyRequestMacroState["GotKeyResponse"] = "GotKeyResponse";
})(KeyRequestMacroState || (KeyRequestMacroState = {}));
// TODO convert DecryptData types to ArrayBuffer so we don't need these anymore
function keyTagInfoToEntity(keyInfo) {
var _a, _b, _c, _d, _e;
const { method, isEncrypted, uri, format, formatversions } = keyInfo;
return {
method,
isEncrypted,
uri,
format,
formatversions,
ivBuf: (_b = (_a = keyInfo.iv) === null || _a === void 0 ? void 0 : _a.buffer) !== null && _b !== void 0 ? _b : null,
keyIdBuf: (_c = keyInfo.keyId) === null || _c === void 0 ? void 0 : _c.buffer,
keyBuf: (_d = keyInfo.key) === null || _d === void 0 ? void 0 : _d.buffer,
psshBuf: (_e = keyInfo.key) === null || _e === void 0 ? void 0 : _e.buffer,
};
}
function entityToKeyTagInfo(entity) {
const { method, isEncrypted, uri, format, formatversions } = entity;
const keyTagInfo = {
method,
isEncrypted,
uri,
format,
formatversions,
iv: entity.ivBuf ? new Uint8Array(entity.ivBuf) : null,
};
if (entity.keyIdBuf) {
keyTagInfo.keyId = new Uint8Array(entity.keyIdBuf);
}
if (entity.keyBuf) {
keyTagInfo.key = new Uint8Array(entity.keyBuf);
}
if (entity.psshBuf) {
keyTagInfo.pssh = new Uint8Array(entity.psshBuf);
}
return keyTagInfo;
}
// Generic network error
class GenericNetworkError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
class HlsNetworkError extends HlsError {
constructor(details, fatal, reason, code, response, isTimeout) {
super(ErrorTypes.NETWORK_ERROR, details, fatal, reason, response);
this.code = code;
this.isTimeout = isTimeout;
this.response = response;
}
}
class ManifestNetworkError extends HlsNetworkError {
constructor(fatal, reason, code, response, isTimeout) {
super(isTimeout ? ErrorDetails.MANIFEST_LOAD_TIMEOUT : ErrorDetails.MANIFEST_LOAD_ERROR, fatal, reason, code, response, isTimeout);
}
}
// Problem when loading playlist or manifest
class PlaylistNetworkError extends HlsNetworkError {
constructor(fatal, reason, code, response, isTimeout, mediaOptionType, mediaOptionId, url) {
super('', fatal, reason, code, response, isTimeout);
this.mediaOptionType = mediaOptionType;
this.mediaOptionId = mediaOptionId;
this.url = url;
switch (mediaOptionType) {
case MediaOptionType.Variant:
this.details = isTimeout ? ErrorDetails.LEVEL_LOAD_TIMEOUT : ErrorDetails.LEVEL_LOAD_ERROR;
break;
case MediaOptionType.AltAudio:
this.details = isTimeout ? ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT : ErrorDetails.AUDIO_TRACK_LOAD_ERROR;
break;
case MediaOptionType.Subtitle:
this.details = isTimeout ? ErrorDetails.SUBTITLE_TRACK_LOAD_TIMEOUT : ErrorDetails.SUBTITLE_TRACK_LOAD_ERROR;
break;
}
}
}
// Problem when loading SessionData
class SessionDataNetworkError extends HlsNetworkError {
constructor(fatal, reason, code, response) {
super(ErrorDetails.SESSION_DATA_LOAD_ERROR, fatal, reason, code, response, false);
}
}
// Problem when loading fragment
class FragmentNetworkError extends HlsNetworkError {
constructor(fatal, reason, code, response, isTimeout, frag, stats) {
super(isTimeout ? ErrorDetails.FRAG_LOAD_TIMEOUT : ErrorDetails.FRAG_LOAD_ERROR, fatal, reason, code, response, isTimeout);
this.mediaOptionId = frag.mediaOptionId;
this.mediaOptionType = frag.mediaOptionType;
this.stats = stats;
}
}
class GenericTimeoutError extends TimeoutError {
constructor(message, code, stats) {
super();
this.message = message;
this.code = code;
this.stats = stats;
}
}
class FragmentAbortError extends HlsNetworkError {
constructor(frag, candidateMediaOptionId, response) {
super('fragAbortError', false, 'Fragment abort', 0, response, false);
this.candidateMediaOptionId = candidateMediaOptionId;
this.mediaOptionId = frag.mediaOptionId;
this.mediaOptionType = frag.mediaOptionType;
}
}
// Errors generated by CDM / KeySystem
class KeyRequestTimeoutError extends HlsNetworkError {
constructor(message, keyuri, response, mediaOptionIds = []) {
super(ErrorDetails.KEY_LOAD_TIMEOUT, false, message, response.code, response, true);
this.keyuri = keyuri;
this.response = response;
this.mediaOptionIds = mediaOptionIds;
}
}
var KeyRequestErrorReason;
(function (KeyRequestErrorReason) {
KeyRequestErrorReason[KeyRequestErrorReason["InvalidState"] = 0] = "InvalidState";
KeyRequestErrorReason[KeyRequestErrorReason["Abort"] = 1] = "Abort";
KeyRequestErrorReason[KeyRequestErrorReason["OutputRestricted"] = 2] = "OutputRestricted";
KeyRequestErrorReason[KeyRequestErrorReason["AlreadyFailedKey"] = 3] = "AlreadyFailedKey";
KeyRequestErrorReason[KeyRequestErrorReason["HttpError"] = 4] = "HttpError";
KeyRequestErrorReason[KeyRequestErrorReason["InternalError"] = 5] = "InternalError";
KeyRequestErrorReason[KeyRequestErrorReason["LicenseServerError"] = 6] = "LicenseServerError";
KeyRequestErrorReason[KeyRequestErrorReason["InsufficientCPC"] = 7] = "InsufficientCPC";
})(KeyRequestErrorReason || (KeyRequestErrorReason = {}));
// Something that failed in the actual request to the license server
class KeyRequestError extends HlsNetworkError {
constructor(message, keyuri, code, response, isOkToRetry, keyErrorReason, fatal = false, mediaOptionIds = []) {
super(ErrorDetails.KEY_LOAD_ERROR, fatal, message, code, response, false);
this.keyuri = keyuri;
this.isOkToRetry = isOkToRetry;
this.keyErrorReason = keyErrorReason;
this.mediaOptionIds = mediaOptionIds;
}
}
// Something that failed due to key exchange or key system initialization
class KeySystemError extends HlsError {
constructor(message, keyuri, code, response, keysystemstring) {
super(ErrorTypes.OTHER_ERROR, ErrorDetails.KEY_SYSTEM_GENERIC_ERROR, true, message, response);
this.keyuri = keyuri;
this.code = code;
this.response = response;
this.keysystemstring = keysystemstring;
}
}
function copyKeyError(error, mediaOptionIds) {
if (error instanceof KeyRequestError) {
return new KeyRequestError(error.message, error.keyuri, error.code, error.response, error.isOkToRetry, error.keyErrorReason, error.fatal, mediaOptionIds);
}
else if (error instanceof KeyRequestTimeoutError) {
return new KeyRequestTimeoutError(error.message, error.keyuri, ErrorResponses.CryptResponseReceivedSlowly, mediaOptionIds);
}
else if (error) {
return new ExceptionError(error.fatal, error.reason, ErrorResponses.InternalError);
}
return null;
}
/*
* FairPlayStreaming key system constants
*
* 2018 Apple Inc. All rights reserved.
*/
const FairPlaySecurityLevels = {
AppleBaseline: 0,
AppleMain: 1,
Main: 1,
Baseline: 0,
};
const FairPlayStreamingKeySystemProperties = {
id: 'fairplaystreaming',
systemStringPrefix: 'com.apple.fps',
keyFormatString: 'com.apple.streamingkeydelivery',
securityLevels: FairPlaySecurityLevels,
};
class LoaderQuery extends QueryEntity {
constructor(store) {
super(store);
this.store = store;
}
get unresolvedUriLoading$() {
return this.selectEntityAction(EntityActions.Add).pipe(map((entityIds) => entityIds.map((id) => this.getEntity(id))));
}
}
class LoaderStore extends EntityStore {
constructor() {
super({}, { name: 'loader', producerFn: produce_1, idKey: 'uri' });
}
}
class LoaderService {
constructor(store) {
this.store = store;
}
createUnresolvedUriLoading(uri, responseType, userAgent) {
logAction('loader.create.unresolvedUriLoading');
this.store.add({ uri, responseType, userAgent });
}
removeUnresolvedUriLoading(uri) {
logAction('loader.remove.unresolvedUriLoading');
this.store.remove(uri);
}
}
const store$1 = new LoaderStore();
let service$2 = null; // To be instantiated in loaderService()
/***********************************************
* Static helper functions that specifically use the above singletons
*/
function createLoaderQuery() {
return new LoaderQuery(store$1);
}
/**
* @returns The global instance of LoaderService that operates on global LoaderStore
*/
function getLoaderService() {
if (!service$2) {
service$2 = new LoaderService(store$1);
}
return service$2;
}
/*
* HLS Event Emitter
*
*
*/
/**
* Simple adapter sub-class of Nodejs-like EventEmitter.
*/
class HlsEventEmitter extends EventEmitter {
/**
* We simply want to pass along the event-name itself
* in every call to a handler, which is the purpose of our `trigger` method
* extending the standard API.
*/
trigger(event, data) {
try {
this.emit(event, event, data);
if (event.toString() !== 'hlsFragLoadProgress') {
// do not log fragLoadProgress, too noisy
// Do NOT log data, which can be very large (for instance the data1: and data2: arguments from demuxer
// console will hold onto the arguments in here until the next event loop and can cause memory to balloon over time
let details = '';
if ((event === 'hlsInternalError' || event === 'hlsError') && data.length) {
details = JSON.stringify(data[0], ['fatal', 'details', 'reason']);
}
const eventData = { event: event.toString() };
if (details.length > 0) {
eventData.details = details;
}
getLogger().qe({ critical: true, name: 'eventTrigger', data: eventData });
}
}
catch (err) {
getLogger().warn(`error in event listener for ${event}: ${err.message}`);
}
}
}
class EventTarget {
constructor(target, _this) {
this.target = target;
this._this = _this;
}
eventWithOptions(event, options, handler, _this = this._this) {
let observable = fromEvent(this.target, event, options);
if (this.target instanceof HlsEventEmitter) {
// HLS's raw event handlers accepts two arguments:
// - event: _Event
// - data: EventData<_EventDataMap, _Event>
// We need to map it to single data argument
observable = observable.pipe(map(([_, data]) => data));
}
if (handler) {
if (_this) {
handler = handler.bind(_this);
}
observable = observable.pipe(tap(handler));
}
return observable;
}
event(event, handler, _this = this._this) {
return this.eventWithOptions(event, undefined, handler, _this);
}
listen(event, notifier, handler, _this = this._this) {
return this.event(event, handler, _this).pipe(takeUntil(notifier)).subscribe();
}
}
function fromEventTarget(target, _this) {
return new EventTarget(target, _this);
}
// Note that vuze doesn't implement some events so may not be safe to use ev directly. Use to fill
function convertEvent(currentTarget, type, ev) {
var _b, _c;
return {
currentTarget: (_b = ev === null || ev === void 0 ? void 0 : ev.currentTarget) !== null && _b !== void 0 ? _b : currentTarget,
target: (_c = ev === null || ev === void 0 ? void 0 : ev.target) !== null && _c !== void 0 ? _c : currentTarget,
type: type,
};
}
function getByteRangeLength(byteRangeHeader) {
const BYTERANGE = /([0-9]+)\-([0-9]+)\/([0-9]+)/;
const result = BYTERANGE.exec(byteRangeHeader);
return result ? parseInt(result[2]) - parseInt(result[1]) + 1 : undefined;
}
function getContentLength(xhr) {
let contentLength;
const contentEncoding = xhr.getResponseHeader('Content-Encoding');
const transferEncoding = xhr.getResponseHeader('Transfer-Encoding');
const noContentEncoding = !contentEncoding || (contentEncoding && contentEncoding.toLowerCase() === 'identity');
const noTransferEncoding = !transferEncoding || (transferEncoding && transferEncoding.toLowerCase() === 'identity');
if (noContentEncoding && noTransferEncoding) {
// Length only makes sense without encoding/compression
contentLength = getByteRangeLength(xhr.getResponseHeader('Content-Range'));
if (!isFiniteNumber(contentLength)) {
contentLength = parseInt(xhr.getResponseHeader('Content-Length'));
}
}
return contentLength;
}
function fromXMLHttpRequest(context, loadConfig) {
return new Observable((subscriber) => {
const { maxTimeToFirstByteMs, maxLoadTimeMs } = loadConfig;
const xhr = new XMLHttpRequest();
const stats = {
trequest: performance.now(),
tfirst: NaN,
tload: NaN,
loaded: 0,
total: NaN,
complete: false,
};
const xhrTarget = fromEventTarget(xhr);
// register for events
const onprogress$ = xhrTarget.event('progress').pipe(share(), throttleTime(300, queueScheduler, { leading: true, trailing: true }), map((progressEvent) => {
if (isNaN(stats.tfirst)) {
stats.tfirst = performance.now();
}
stats.loaded = progressEvent.loaded;
if (progressEvent.lengthComputable) {
stats.total = progressEvent.total;
}
return progressEvent.target;
}), filter((req) => req.readyState >= 3));
const onreadystate$ = xhrTarget.event('readystatechange').pipe(share(), map((event) => event.target), filter((req) => req.readyState >= 2), tap((req) => {
if (isNaN(stats.tfirst) && req.readyState >= 3) {
stats.tfirst = performance.now();
}
}));
let timeToFirstByteTimeout$ = EMPTY;
if (isFinite(maxTimeToFirstByteMs) && maxTimeToFirstByteMs > 0) {
timeToFirstByteTimeout$ = merge(onprogress$, onreadystate$).pipe(take(1), timeout(context.extendMaxTTFB > 0 ? context.extendMaxTTFB : maxTimeToFirstByteMs), switchMap(() => EMPTY));
}
let totalLoadTimeout$ = EMPTY;
if (isFinite(maxLoadTimeMs) && maxLoadTimeMs > 0) {
totalLoadTimeout$ = onreadystate$.pipe(filter((req) => req.readyState >= 4), take(1), timeout(maxLoadTimeMs), switchMap(() => EMPTY));
}
let onProgressCb$ = EMPTY;
if (context.onProgress) {
onProgressCb$ = merge(of(xhr), onprogress$) // Emit on subscribe and then on every 'onprogress' event
.pipe(map((xhrReq) => {
const { getData, cb } = context.onProgress;
return cb(context.url, xhrReq.status, stats, getData ? xhrReq.response : undefined);
}), takeWhile((done) => !done, true))
.pipe(switchMapTo(EMPTY));
}
const sub = merge(onprogress$.pipe(switchMap(() => EMPTY)), onreadystate$, timeToFirstByteTimeout$, totalLoadTimeout$, onProgressCb$)
.pipe(filter((req) => req.readyState >= 4), take(1), switchMap((req) => {
stats.complete = true;
if (req.status >= 200 && req.status < 300) {
stats.tload = performance.now();
stats.contentType = req.getResponseHeader('Content-Type');
if (loadConfig.reportCDNServer) {
stats.cdnServer = req.getResponseHeader('CDN-Server');
}
stats.contentLength = loadConfig.forceContentLenCheckIfNoHeader ? getContentLength(req) : null; // forceContentLenCheckIfNoHeader is true only for non-browser platforms
_relateServerInstanceInfoToRequest(req, context);
if (context.responseType === 'arraybuffer') {
stats.loaded = req.response.byteLength;
}
else {
stats.loaded = req.responseText.length;
}
stats.total = stats.loaded;
if (context.checkContentLength && // checkContentLength is true only when loading fragment
(stats.total === 0 || (isFiniteNumber(stats.contentLength) && stats.total != stats.contentLength))) {
throw new GenericNetworkError('Network error', req.status);
}
const res = [req, stats];
return scheduled(of(res), queueScheduler);
}
else {
throw new GenericNetworkError('Network error', req.status);
}
}), catchError((err) => {
if (err instanceof TimeoutError) {
throw new GenericTimeoutError(err.message, 0, stats);
}
if (!(err instanceof GenericNetworkError)) {
throw new GenericNetworkError(err.message, 0);
}
throw err;
}))
.subscribe(subscriber);
// Setup XHR request
const { url, method, byteRangeOffset, responseType, body } = context;
if (context.mimeType) {
xhr.overrideMimeType(context.mimeType);
}
try {
const xhrSetup = context.xhrSetup;
if (xhrSetup) {
try {
xhrSetup(xhr, url);
}
catch (e) {
// fix xhrSetup: (xhr, url) => {xhr.setRequestHeader("Content-Language", "test");}
// not working, as xhr.setRequestHeader expects xhr.readyState === OPEN
xhr.open(method, context.url, true);
xhrSetup(xhr, context.url);
}
}
if (!xhr.readyState) {
xhr.open(method, context.url, true);
}
}
catch (e) {
// IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS
throw new GenericNetworkError(e.message, xhr.status);
}
xhr.responseType = responseType;
// Set headers
if (byteRangeOffset && isFiniteNumber(byteRangeOffset.start) && isFiniteNumber(byteRangeOffset.end) && byteRangeOffset.start >= 0 && byteRangeOffset.end > byteRangeOffset.start) {
const { start, end } = byteRangeOffset;
xhr.setRequestHeader('Range', `bytes=${start}-${end - 1}`);
}
if (context.headers) {
for (const [name, value] of Object.entries(context.headers)) {
xhr.setRequestHeader(name, value);
}
}
// Start request
if (method === 'POST' && body) {
xhr.send(body);
}
else {
xhr.send();
}
return () => {
xhr.abort();
sub.unsubscribe();
};
});
}
function _relateServerInstanceInfoToRequest(xhr, context) {
if (context.collectServerInstanceInfo) {
context.serverInstanceInfo = {};
context.collectServerInstanceInfo.forEach((header) => {
const headerValue = xhr.getResponseHeader(header);
if (headerValue) {
context.serverInstanceInfo[header] = headerValue;
}
});
}
}
const loggerName$7 = { name: 'CustomUrlLoader' };
class CustomUrlLoader {
constructor(loaderService) {
this.loaderService = loaderService;
this.requestMap = {};
this.logger = getLogger();
}
load(context, loadConfig) {
return new Observable((observer) => {
const url = context.url;
const { maxTimeToFirstByteMs } = loadConfig;
const stats = {
trequest: performance.now(),
tfirst: NaN,
tload: NaN,
loaded: 0,
total: NaN,
complete: false,
};
const request = (this.requestMap[url] = new AsyncSubject());
const source = request.pipe(timeout(context.extendMaxTTFB > 0 ? context.extendMaxTTFB : maxTimeToFirstByteMs), switchMap((response) => {
this.logger.info(loggerName$7, `loaded originalUri=${redactUrl(url)} uri=${redactUrl(response.uri)} durationMs=${performance.now() - stats.trequest}`);
stats.tfirst = performance.now();
return this.handleExternalResponse(response, context, loadConfig, stats);
}), catchError((err) => {
if (err instanceof TimeoutError) {
throw new GenericTimeoutError(err.message, 0, stats);
}
throw err;
}), finalize$1(() => {
this.requestMap[url] = undefined;
this.loaderService.removeUnresolvedUriLoading(url);
}));
this.logger.info(loggerName$7, `loading originalUri=${redactUrl(url)}`);
if (context.onProgress) {
context.onProgress.cb(url, 0, stats, undefined);
}
const sub = source.subscribe(observer);
this.loaderService.createUnresolvedUriLoading(url, context.responseType, navigator.userAgent);
return () => {
sub.unsubscribe();
this.requestMap[url] = undefined;
};
});
}
setCustomUrlResponse(url, response) {
const source = this.requestMap[url];
if (source) {
source.next(response);
source.complete();
this.requestMap[url] = undefined;
}
}
handleExternalResponse(data, context, loadConfig, stats) {
stats.tload = performance.now();
const status = data.response.status || 200;
// http status of 200 to 299 are all successfull
if (status >= 200 && status < 300) {
if (context.responseType === 'arraybuffer' && data.response.data instanceof ArrayBuffer) {
stats.loaded = data.response.data.byteLength;
}
else {
stats.loaded = data.response.data.toString().length;
}
stats.total = stats.loaded;
stats.complete = true;
return scheduled(of({ status, data, stats }), queueScheduler);
}
else if (isRedirectStatusCode(status)) {
this.logger.info(loggerName$7, `redirect status=${status} url=${redactUrl(data.response.uri)}`);
return this.redirectRequest(data.response.uri, context, loadConfig, stats);
}
else {
this.logger.warn(loggerName$7, `unable to load custom url > uri=${redactUrl(data.response.uri)}, status=${status}`);
return throwError(new GenericNetworkError('Unable to load custom url', status));
}
}
redirectRequest(uri, context, loadConfig, stats) {
const { maxLoadTimeMs, maxTimeToFirstByteMs } = loadConfig;
const updatedMaxLoadTimeMs = maxLoadTimeMs - (performance.now() - stats.trequest); // Recalculate timeout based on request time
const updatedMaxTimeToFirstByteMs = context.extendMaxTTFB > 0 ? context.extendMaxTTFB : maxTimeToFirstByteMs - (performance.now() - stats.trequest); // Recalculate timeout based on request time
const newConfig = Object.assign(Object.assign({}, loadConfig), { maxLoadTimeMs: updatedMaxLoadTimeMs, maxTimeToFirstByteMs: updatedMaxTimeToFirstByteMs });
const newContext = Object.assign(Object.assign({}, context), { url: uri });
if (updatedMaxLoadTimeMs <= 0 || updatedMaxTimeToFirstByteMs <= 0) {
return throwError(new TimeoutError());
}
return fromXMLHttpRequest(newContext, newConfig).pipe(map(([xhr, sample]) => {
const { responseURL, status } = xhr;
const uri = responseURL || '';
const data = {
uri,
response: {
status: status,
uri,
data: xhr.response,
},
};
stats.loaded = stats.total = sample.loaded;
stats.tload = performance.now();
stats.complete = true;
return { status: xhr.status, data, stats };
}));
}
}
let loader;
function getCustomUrlLoader(loaderService) {
if (!loader) {
const service = loaderService || getLoaderService();
loader = new CustomUrlLoader(service);
}
return loader;
}
function fromUrlArrayBuffer(context, loadConfig) {
const ctx = Object.assign(Object.assign({}, context), { method: 'GET', responseType: 'arraybuffer' });
const customUrlLoader = getCustomUrlLoader();
return isCustomUrl(ctx.url)
? customUrlLoader.load(ctx, loadConfig).pipe(map((res) => [res.data.response.data, res.stats, ctx.serverInstanceInfo]))
: fromXMLHttpRequest(ctx, loadConfig).pipe(map(([xhr, bwSample]) => [xhr.response, bwSample, ctx.serverInstanceInfo]));
}
/**
* Generic load utils for retry and such
*/
function getLoadConfig(loadable, policy) {
return !loadable.url || isCustomUrl(loadable.url) ? policy.customURL : policy.default;
}
function getRetryConfig(error, config) {
if (error instanceof HlsNetworkError) {
return error.isTimeout ? config.timeoutRetry : config.errorRetry;
}
return null;
}
/**
* Operator for converting TimeoutError & GenericNetworkError into ManifestNetworkError
*/
function convertToManifestNetworkError(fatal) {
return (source) => source.pipe(catchError((err) => {
if (err instanceof GenericTimeoutError) {
throw new ManifestNetworkError(fatal, 'Timeout', 0, ErrorResponses.ManifestTimeoutError, true);
}
else if (err instanceof GenericNetworkError) {
throw new ManifestNetworkError(fatal, err.message, err.code, { code: err.code, text: 'Manifest network error' }, false);
}
throw err;
}));
}
/**
* Operator for converting TimeoutError & GenericNetworkError into PlaylistNetworkError
*/
function convertToPlaylistNetworkError(mediaOptionType, mediaOptionId, fatal, url) {
return (source) => source.pipe(catchError((err) => {
if (err instanceof GenericTimeoutError) {
throw new PlaylistNetworkError(fatal, 'Timeout', 0, ErrorResponses.PlaylistTimeoutError, true, mediaOptionType, mediaOptionId, url);
}
else if (err instanceof GenericNetworkError) {
throw new PlaylistNetworkError(fatal, err.message, err.code, { code: err.code, text: 'Playlist Network Error' }, false, mediaOptionType, mediaOptionId, url);
}
throw err;
}));
}
/**
* Operator for converting TimeoutError & GenericNetworkError into FragmentError
*/
function convertToFragmentNetworkError(frag, fatal) {
return (source) => source.pipe(catchError((err) => {
if (err instanceof GenericTimeoutError) {
throw new FragmentNetworkError(fatal, 'Timeout', 0, ErrorResponses.FragmentTimeoutError, true, frag, err.stats);
}
else if (err instanceof GenericNetworkError) {
throw new FragmentNetworkError(fatal, err.message, err.code, { code: err.code, text: 'Fragment Network Error' }, false, frag);
}
throw err;
}));
}
/**
* Helper function to update playtype of levels
*/
function updatePlaylistAttributes(levelDetails) {
const playlistTypeString = levelDetails.type;
const isLive = levelDetails.liveOrEvent;
let playlistType = 'VOD';
if (playlistTypeString === 'EVENT' && isLive) {
playlistType = 'EVENT';
}
else if ((!playlistTypeString || playlistTypeString.length === 0 || playlistTypeString === 'LIVE') && isLive) {
playlistType = 'LIVE';
}
if (levelDetails.type !== playlistType) {
getLogger().info(`Playlist type updated from ${levelDetails.type} to ${playlistType}`);
levelDetails.type = playlistType;
}
}
/**
* 2018 Apple Inc. All rights reserved.
*/
const PlayReadySecurityLevels = {
SL2000: 0,
SL3000: 1,
};
const PlayReadyKeySystemProperties = {
id: 'playready',
systemStringPrefix: 'com.microsoft.playready',
keyFormatString: 'com.microsoft.playready',
securityLevels: PlayReadySecurityLevels,
};
/**
* 2018 Apple Inc. All rights reserved.
*/
const WidevineSecurityLevels = {
WIDEVINE_SOFTWARE: 0,
WIDEVINE_HARDWARE: 1,
};
const WidevineKeySystemProperties = {
id: 'widevine',
systemStringPrefix: 'com.widevine.alpha',
keyFormatString: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed',
securityLevels: WidevineSecurityLevels,
};
/*
* Utilities for numeric encodings
*
* 2018 Apple Inc. All rights reserved.
*/
function base64ToBase64Url(base64encodedStr) {
return base64encodedStr.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');
}
class BrowserNumericEncodingUtils {
static strToBase64Encode(str) {
return btoa(str);
}
static base64DecodeToStr(str) {
return atob(str);
}
static base64Encode(input) {
return btoa(String.fromCharCode(...input));
}
static base64UrlEncode(input) {
return base64ToBase64Url(BrowserNumericEncodingUtils.base64Encode(input));
}
static base64Decode(base64encodedStr) {
return Uint8Array.from(atob(base64encodedStr), (c) => c.charCodeAt(0));
}
}
class NodeJSNumericEncodingUtils {
static strToBase64Encode(str) {
return global$1.Buffer.from(str).toString('base64');
}
static base64DecodeToStr(str) {
return global$1.Buffer.from(str, 'base64').toString();
}
static base64Encode(input) {
return global$1.Buffer.from(input).toString('base64');
}
static base64UrlEncode(input) {
return base64ToBase64Url(NodeJSNumericEncodingUtils.base64Encode(input));
}
static base64Decode(base64encodedStr) {
const buffer = global$1.Buffer.from(base64encodedStr, 'base64');
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
}
}
const NumericEncodingUtils = typeof global$1.Buffer !== 'undefined' ? NodeJSNumericEncodingUtils : BrowserNumericEncodingUtils;
var NumericEncodingUtils$1 = NumericEncodingUtils;
/*
* Utilities for key systems
*
* 2018 Apple Inc. All rights reserved.
*/
// Map of prefix to mimeType
const kVideoCodecToMimeType = {
// AVC
avc1: 'video/mp4',
avc3: 'video/mp4',
dvav: 'video/mp4',
dva1: 'video/mp4',
// HEVC
hev1: 'video/mp4',
hvc1: 'video/mp4',
dvh1: 'video/mp4',
dvhe: 'video/mp4', // Dolby vission
};
const kAudioCodecToMimeType = {
mp4a: 'audio/mp4',
'ac-3': 'audio/mp4',
'ec-3': 'audio/mp4',
};
function isMediaKeySystemConfig(config) {
return config && typeof config === 'object'; // requestMediaKeySystemAccess accepts {}
}
// Input: set of codec strings for each type
// Output:
// {
// videoCapabilities: [
// { contentType: 'video/mp4;codecs=avc.###', robustness: '' } ],
// audioCapabilities: []
// }
function getMediaKeysystemMediaCapability(videoCodecs, audioCodecs) {
const result = {
videoCapabilities: [],
audioCapabilities: [],
};
if (videoCodecs) {
videoCodecs.forEach((videoCodec) => {
const prefix = videoCodec.split('.')[0].trim();
if (prefix in kVideoCodecToMimeType) {
result.videoCapabilities.push({
contentType: kVideoCodecToMimeType[prefix] + ';codecs=' + videoCodec,
robustness: '',
});
}
});
}
if (audioCodecs) {
audioCodecs.forEach((audioCodec) => {
const prefix = audioCodec.split('.')[0].trim();
if (prefix in kAudioCodecToMimeType) {
result.audioCapabilities.push({
contentType: kAudioCodecToMimeType[prefix] + ';codecs=' + audioCodec,
robustness: '',
});
}
});
}
return result;
}
/**
* Utility to change the endianness of Key ID
* @param keyID uint8array representing the keyId
* @returns uint8array the keyId after changing the endianness
*/
function changeEndianness(keyId) {
// eslint-disable-next-line func-style
const swap = function (array, from, to) {
const cur = array[from];
array[from] = array[to];
array[to] = cur;
};
swap(keyId, 0, 3);
swap(keyId, 1, 2);
swap(keyId, 4, 5);
swap(keyId, 6, 7);
}
/**
* Generate key id from an arbitrary string
* @param str String to convert into a 16 byte key
* @returns uint8array representing the keyId
*/
function getKeyIdBytes(str) {
const keyIdbytes = BufferUtils.strToUtf8array(str).subarray(0, 16);
const paddedkeyIdbytes = new Uint8Array(16);
paddedkeyIdbytes.set(keyIdbytes, 16 - keyIdbytes.length);
return paddedkeyIdbytes;
}
/**
* @param URI string
* @returns Uint8Array of URI data
*/
function convertDataUriToArrayBytes(uri) {
// data:[
const colonsplit = uri.split(':');
let keydata = null;
if (colonsplit[0] === 'data' && colonsplit.length === 2) {
const semicolonsplit = colonsplit[1].split(';');
const commasplit = semicolonsplit[semicolonsplit.length - 1].split(',');
if (commasplit.length === 2) {
const isbase64 = commasplit[0] === 'base64';
const data = commasplit[1];
if (isbase64) {
semicolonsplit.splice(-1, 1); // remove from processing
keydata = NumericEncodingUtils$1.base64Decode(data);
}
else {
keydata = getKeyIdBytes(data);
}
}
}
return keydata;
}
/**
* Generate 'keyids' init data from an array of key ids
* @param keyIds Array of key ids represented as uint8array[16] objects
* @returns The initData string to pass to generateRequest as part of EME
*/
function makeKeyIdsInitData(keyIds) {
const initDataObj = {
kids: keyIds.map(NumericEncodingUtils$1.base64UrlEncode),
};
// Convert string to utf-8 array
return BufferUtils.strToUtf8array(JSON.stringify(initDataObj));
}
// parse pssh list and convert to dictionary:
function parsePSSHList(psshList) {
const dv = new DataView(psshList);
let whichByte = 0;
const pssh = {}; // PSSH: systemID => data
while (whichByte < dv.buffer.byteLength) {
const thisBox = whichByte;
const boxSize = dv.getUint32(whichByte);
whichByte += 4;
const nextBox = thisBox + boxSize;
if (dv.getUint32(whichByte) !== 1886614376) {
whichByte = nextBox;
continue; // next box
}
whichByte += 4;
const version = dv.getUint8(whichByte);
switch (version) {
case 0: // NO KEY IDS
case 1:
whichByte += 1;
break;
default:
whichByte = nextBox;
break;
}
whichByte += 3; // flags
// UUID: 4 bytes - 2 bytes - 2 bytes - 2 bytes - 6 bytes
let systemID = '';
// 16 bytes
for (let i = 0; i < 16; ++i, ++whichByte) {
systemID += dv.getUint8(whichByte).toString(16);
switch (i) {
case 4:
case 6:
case 8:
case 10:
systemID += '-';
break;
}
}
whichByte += 4; // Data size
pssh[systemID] = dv.buffer.slice(thisBox, nextBox);
}
return pssh;
}
const keysystemutil = {
getCapabilities: getMediaKeysystemMediaCapability,
changeEndianness,
getKeyIdBytes,
convertDataUriToArrayBytes,
makeKeyIdsInitData,
parsePSSHList,
};
/*
* Decrypt data
*
* 2018 Apple Inc. All rights reserved.
*/
// Note that this will not get copied into Worker
let keyUriToKeyIdMap = {};
// Created in playlist-loader, modified in demux / remux
class DecryptData {
/**
* @param method From METHOD attribute, mandatory
* @param uri Absolute url of the key (calculated from URI)
* @param iv 128-bit unsigned int representing Initialization Vector, used when KEYFORMAT="identity", optional
* @param format From KEYFORMAT, optional with default value of "identity"
* @param formatversions Array From KEYFORMATVERSION, an array of unsigned int, optional
*/
constructor(method, uri, iv, format, formatversions) {
this.method = method;
this.uri = uri;
this.iv = iv;
this.format = format;
this.formatversions = formatversions;
this.isEncrypted = this.method && this.method !== 'NONE';
if (!this.formatversions || this.formatversions.length === 0) {
this.formatversions = [1];
}
// Set later
this.key = undefined;
this.keyId = undefined;
if (!this.isEncrypted) {
return;
}
// Initialize keyId if possible
const keyBytes = keysystemutil.convertDataUriToArrayBytes(this.uri);
if (keyBytes) {
switch (format) {
case PlayReadyKeySystemProperties.keyFormatString: {
// Playready
this.pssh = keyBytes;
const keyBytesUtf16 = new Uint16Array(keyBytes.buffer, keyBytes.byteOffset, keyBytes.byteLength / 2);
const keyByteStr = String.fromCharCode.apply(null, Array.from(keyBytesUtf16));
// we got entire PSSH data. Incase of Playready it's WRMHEADER XML object. Parse it.
const xmlKeyBytes = keyByteStr.substring(keyByteStr.indexOf('<'), keyByteStr.length);
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlKeyBytes, 'text/xml');
const keyData = xmlDoc.getElementsByTagName('KID')[0];
if (keyData) {
let keyId = null;
if (keyData.childNodes[0]) {
keyId = keyData.childNodes[0].nodeValue;
}
else {
keyId = keyData.getAttribute('VALUE');
}
if (keyId) {
const keyIdArray = NumericEncodingUtils$1.base64Decode(keyId).subarray(0, 16);
// KID value in PRO is a base64-encoded little endian GUID interpretation of UUID
// KID value in ‘tenc’ is a big endian UUID GUID interpretation of UUID
keysystemutil.changeEndianness(keyIdArray);
this.keyId = keyIdArray;
}
}
break;
}
case WidevineKeySystemProperties.keyFormatString: {
// Widevine
this.pssh = keyBytes;
// In case of widevine keyID is embedded in PSSH box. Read Key ID.
if (keyBytes.length >= 22) {
this.keyId = keyBytes.subarray(keyBytes.length - 22, keyBytes.length - 6);
}
break;
}
default: {
// default handling
let keydata = keyBytes.subarray(0, 16);
if (keydata.length !== 16) {
const padded = new Uint8Array(16);
padded.set(keydata, 16 - keydata.length);
keydata = padded;
}
this.keyId = keydata;
break;
}
}
}
// Default behavior
if (!this.keyId || this.keyId.byteLength !== 16) {
let keyId = keyUriToKeyIdMap[this.uri];
if (!keyId) {
const val = Object.keys(keyUriToKeyIdMap).length % Number.MAX_SAFE_INTEGER;
// MAX_SAFE_INTEGER is huge (9007199254740991) so this /should/ be safe...
keyId = new Uint8Array(16);
const dv = new DataView(keyId.buffer, 12, 4); // Just set the last 4 bytes
dv.setUint32(0, val);
keyUriToKeyIdMap[this.uri] = keyId;
}
this.keyId = keyId;
}
}
get keyTagInfo() {
const { method, isEncrypted, uri, iv, keyId, key, format, formatversions } = this;
const keyTagInfo = { method, isEncrypted, uri, iv, keyId, key, format, formatversions };
return keyTagInfo;
}
static clearKeyUriToKeyIdMap() {
keyUriToKeyIdMap = {};
}
}
var KeyRequestState;
(function (KeyRequestState) {
KeyRequestState["NONE"] = "NONE";
KeyRequestState["GET_REQUEST_INFO"] = "GET_REQUEST_INFO";
KeyRequestState["GET_CHALLENGE"] = "GET_CHALLENGE";
KeyRequestState["GET_KEY_RESPONSE"] = "GET_KEY_RESPONSE";
KeyRequestState["PROCESS_LICENSE"] = "PROCESS_LICENSE";
})(KeyRequestState || (KeyRequestState = {}));
// Wrap subscription and teardown of MediaKeySession callbacks
class MediaKeySessionContext {
constructor(session, onkeystatuseschange, onkeymessage, logger) {
this.session = session;
this.onkeystatuseschange = onkeystatuseschange;
this.onkeymessage = onkeymessage;
this.logger = logger;
this.isClosing$ = new BehaviorSubject(false);
this.closed$ = new BehaviorSubject(false);
const target = fromEventTarget(this.session);
target.listen('keystatuseschange', this.isClosing$.pipe(filter((x) => x === true)), this.onkeystatuseschange);
// Message is weird because we still want the message until after close()
target.listen('message', this.closed$.pipe(filter((x) => x === true)), this.onkeymessage);
}
get isClosing() {
return this.isClosing$.value;
}
get isClosed() {
return this.closed$.value;
}
/**
* Remove and close all keys in MediaKeySession
*/
destroy() {
this.logger.info(`[Keys] : remove licenses & keys for session : ${this.session.sessionId} and close it`);
this.isClosing$.next(true);
const session = this.session;
// Unabortable section. Should execute no matter what.
return from(session
.remove()
.catch((error) => {
this.logger.info(`Could not remove session: ${error.message}`);
})
.then(() => {
return session.close();
})
.catch((error) => {
this.logger.info(`Could not close session: ${error.message}`);
})).pipe(tap(() => {
this.isClosing$.next(false);
this.closed$.next(true);
}), finalize$1(() => {
this.isClosing$.next(false);
this.closed$.next(true);
}));
}
}
/**
* @brief KeyContext keeps track of the current key request state and information about a given key.
*
* A key may exist without a key request being in progress. When a key request is in progress, there are
* multiple phases / states. Each state of a key request is asynchronous and can be completed either by
* the CDM or by the client. If we get out of sync with the current key request state, we will throw an error
* and all subscribers will be notified. We will also throw an error if aborted in the middle of the request.
* Note that subscribers will not get the abort error if they unsubscribe from the observable.
*/
class KeyContext {
constructor(decryptdata, session = null) {
this.decryptdata = decryptdata;
this._requestState$ = new BehaviorSubject(KeyRequestState.NONE); // Key request state. Note this is different from keystatus from CDM
this.destroy$ = new Subject(); // Destroy key. This should stop any renewal timers
// If in progress, the current observable
this.currentObservable = null;
this.session = null; // Current session. Could be shared by others (config.useMultipleKeySessions !== true)
this.oldSessions = [];
this.session = session;
}
get requestState() {
return this._requestState$.value;
}
get onKeyRequestState$() {
return this._requestState$;
}
destroy() {
this.destroy$.next();
// TODO actual cleanup?
}
abort() {
if (this.requestState !== KeyRequestState.NONE) {
const err = new KeyRequestError('Aborted', this.decryptdata.uri, 0, ErrorResponses.KeySystemAbort, true, KeyRequestErrorReason.Abort);
this.error(err);
}
}
/**
* Change state and return observable that gets completed when resolveState is called
*
* @param state The state to switch to
*/
setKeyRequestState(state) {
if (this.currentObservable) {
const err = new KeyRequestError(`Unexpected state transition ${this.requestState}->${state}`, this.decryptdata.uri, 0, ErrorResponses.KeySystemUnexpectedStateTransition, true, KeyRequestErrorReason.InvalidState);
this.error(err);
}
this._requestState$.next(state);
const returnVal = new AsyncSubject();
if (state === KeyRequestState.NONE) {
returnVal.complete();
this.currentObservable = null;
}
else {
//@ts-ignore
this.currentObservable = returnVal;
}
return returnVal;
}
/**
* Resolve current state observable
* @param state State to resolve
* @param value The value to resolve current observable with
*/
resolveState(state, value) {
if (!this.currentObservable) {
return;
}
if (state !== this.requestState) {
const err = new KeyRequestError(`Unexpected state ${this.requestState} != ${state}`, this.decryptdata.uri, 0, ErrorResponses.KeySystemUnexpectedState, true, KeyRequestErrorReason.InvalidState);
this.error(err);
return;
}
if (value instanceof Error) {
this.error(value);
}
else {
const obs = this.currentObservable;
this.currentObservable = null;
obs.next(value);
obs.complete();
}
}
/**
* Signal error for this key. Could be due to key request or some other internal error from CDM
* @param err The error
*/
error(err) {
if (this.currentObservable) {
const obs = this.currentObservable;
this.currentObservable = null;
obs.error(err);
}
this.setKeyRequestState(KeyRequestState.NONE);
// TODO: any other cleanup ?
}
}
/*
* Base class for key systems
*
* 2018 Apple Inc. All rights reserved.
*/
const MAX_CERT_LOAD_TIME_MS = 10000; // Maximum time for loading the certificate
function printKeyTag(tag) {
return `uri=${redactUrl(tag.uri)} keyId=${Hex$1.hexDump(tag.keyId)}`;
}
class KeySystem {
constructor(mediaKeys, systemString, config, eventEmitter, useSingleKeySession, sessionHandler, logger) {
this.mediaKeys = mediaKeys;
this.systemString = systemString;
this.config = config;
this.eventEmitter = eventEmitter;
this.useSingleKeySession = useSingleKeySession;
this.sessionHandler = sessionHandler;
this.logger = logger;
this.destroy$ = new Subject();
this.setCert = false; // Has set cert on MediaKeySession
this.certificate$ = new BehaviorSubject(null);
// This event will be signalled when a renewal request is needed or if an error occurs.
// The key system will not auto renew. Instead client is expected to call startKeyRequest
this._keyStatusChange$ = new Subject();
this.shouldDestroyMediaKeys = false;
// TJH: will playingItem raise a license challenge ?
//this.itemId = hls.loadingItem?.itemId || '';
this.itemId = '';
this.sessions = [];
this.keyIdToKeyInfo = {};
this.keyUriToKeyInfo = {};
this.sessionIdToKeyUri = {};
this.onkeystatuseschange = this.handleKeyStatusesChange.bind(this);
this.onkeymessage = this.handleKeyMessage.bind(this);
}
get keyStatusChange$() {
return this._keyStatusChange$;
}
destroy() {
this.isDestroying = true;
this.destroy$.next();
for (const info of Object.values(this.keyIdToKeyInfo)) {
this._abortKeyRequest(info);
}
// Remove sessions
const destroyPromises = this.sessions.map((ctx) => ctx.destroy());
const p = iif(() => destroyPromises.length === 0, VOID, forkJoin(destroyPromises)).pipe(mapTo(undefined), finalize$1(() => {
this.mediaKeys = undefined;
this.keyIdToKeyInfo = {};
this.keyUriToKeyInfo = {};
this.sessionIdToKeyUri = {};
}));
DecryptData.clearKeyUriToKeyIdMap();
return p;
}
/**
* @param certificate Used for generating challenge
* @returns {Promise} Fired when non-null certificate has been set on the object.
*/
setServerCertificate(certificate = null) {
this.logger.info(this.systemString + ' setServerCertificate(' + (certificate ? 'nonnull' : 'null') + ')');
if (!this.needsCert) {
return of(true);
}
if (certificate) {
this.certificate$.next(certificate);
}
const waitForCert$ = waitFor(this.certificate$, (x) => x != null).pipe(timeout(MAX_CERT_LOAD_TIME_MS));
return waitForCert$.pipe(switchMap((cert) => {
if (this.setCert) {
return of(true);
}
if (!this.setCertSubject || this.setCertSubject.isStopped) {
this.setCertSubject = new AsyncSubject();
return from(this.mediaKeys.setServerCertificate(cert)).pipe(tap((v) => {
// Sometimes the promise returned by the CDM doesn't carry boolean
// This will cause playback failure.
const certStatus = v !== undefined ? v : true;
this.setCert = certStatus;
this.setCertSubject.next(certStatus);
this.setCertSubject.complete();
}), catchError((err) => {
this.logger.info('Failed setServerCertificate');
this.setCert = false;
this.setCertSubject.error(err);
return VOID;
}), switchMap(() => {
return this.setCertSubject;
}));
}
return this.setCertSubject;
}), catchError((err) => {
this.logger.info(`setServerCertificate err=${err.message}`);
throw err;
}));
}
ensureKeyContext(decryptdata) {
const keyuri = decryptdata.uri;
if (!this.keyUriToKeyInfo[keyuri]) {
this.keyUriToKeyInfo[keyuri] = new KeyContext(decryptdata);
}
const keyInfo = this.keyUriToKeyInfo[keyuri];
if (keyInfo.session) {
return keyInfo;
}
if (this.useSingleKeySession && this.sessions.length > 0) {
keyInfo.session = this.sessions[0].session;
return keyInfo;
}
this.logger.info(`${this.systemString} createSession`);
const session = this.mediaKeys.createSession();
if (session) {
this.sessions.push(new MediaKeySessionContext(session, this.onkeystatuseschange, this.onkeymessage, this.logger));
}
else {
this.logger.info(`${this.systemString} FAIL: could not create MediaKeysSession`);
}
keyInfo.session = session;
return keyInfo;
}
/**
* Start a key request. called from key-system controller or internally on renewal.
*
* @param decryptdata DecryptData object from EXT-X-KEY
* @returns Promise (decryptdata)
*/
startKeyRequest(decryptdata) {
const keyuri = decryptdata.uri;
const keyInfo = this.ensureKeyContext(decryptdata);
const session = keyInfo === null || keyInfo === void 0 ? void 0 : keyInfo.session;
if (!session) {
return throwError(new KeySystemError('Could not create key session', decryptdata.uri, 0, ErrorResponses.KeySystemFailedToCreateSession, this.systemString));
}
const keyIdStr = BufferUtils.utf8arrayToStr(decryptdata.keyId);
this.keyIdToKeyInfo[keyIdStr] = keyInfo;
this.logger.info(`${this.systemString} startKeyRequest ${printKeyTag(decryptdata)} state=${keyInfo.requestState}`);
this.logger.qe({ critical: true, name: 'startKeyRequest', data: { uri: keyuri, keyId: keyIdStr } });
return forkJoin([this.getKeyRequestInfo(keyInfo), this.setServerCertificate()]).pipe(map((values) => values[0]), switchMap((requestInfo) => {
var _a;
(_a = this.sessionHandler) === null || _a === void 0 ? void 0 : _a.licenseChallengeSubmitted({ keyuri: keyuri, keyFormat: this.systemString });
return this.generateLicenseChallenge(keyInfo, requestInfo).pipe(catchError((error) => {
var _a;
this.logger.info(`${this.systemString} generateLicenseChallenge Failed ${error.message} ${printKeyTag(decryptdata)}`);
(_a = this.sessionHandler) === null || _a === void 0 ? void 0 : _a.licenseChallengeError({ keyuri: keyuri });
throw error;
}));
}), switchMap((licenseChallenge) => {
var _a;
this.logger.info(`${this.systemString} challenge created ${printKeyTag(decryptdata)}`);
this.logger.qe({ critical: true, name: 'challengeCreated', data: { uri: keyuri, keyId: keyIdStr } });
(_a = this.sessionHandler) === null || _a === void 0 ? void 0 : _a.licenseChallengeCreated({ keyuri: keyuri, cdmVersion: this.cdmVersion });
return this.getKeyRequestResponse(keyInfo, licenseChallenge);
}), switchMap((parsedKeyResponse) => {
var _a;
this.logger.info(`${this.systemString} onKeyResponseParsed ${printKeyTag(decryptdata)}`);
this.logger.qe({ critical: true, name: 'onKeyResponseParsed', data: { uri: keyuri, keyId: keyIdStr } });
(_a = this.sessionHandler) === null || _a === void 0 ? void 0 : _a.licenseResponseSubmitted({ keyuri: keyuri });
return this.handleParsedKeyResponse(keyInfo, parsedKeyResponse).pipe(catchError((error) => {
var _a;
this.logger.info(`${this.systemString} ParseKeyResponse Failed ${printKeyTag(decryptdata)} error=${error.message}`);
(_a = this.sessionHandler) === null || _a === void 0 ? void 0 : _a.licenseResponseError({ keyuri: keyuri });
throw error;
}));
}), map(() => {
var _a;
this.logger.info(`${this.systemString} New usable key: ${printKeyTag(decryptdata)} CDMVersion=${this.cdmVersion}`);
this.logger.qe({ critical: true, name: 'newUsableKey', data: { uri: keyuri, keyId: keyIdStr } });
(_a = this.sessionHandler) === null || _a === void 0 ? void 0 : _a.licenseResponseProcessed({ keyuri: keyuri });
keyInfo.setKeyRequestState(KeyRequestState.NONE);
this.removeSessions(keyInfo.decryptdata, false).subscribe();
return decryptdata; // Resolve
}), catchError((err) => {
this.handleKeyExchangeError(keyInfo, err);
throw err;
}),
// takeUntil(this.destroy$),
finalize$1(() => {
this._abortKeyRequest(keyInfo);
}));
}
/**
* Internal cleanup of key request
* @param keyInfo The key request to abort
*/
_abortKeyRequest(keyInfo) {
var _a;
if (keyInfo) {
const keyuri = keyInfo.decryptdata.uri;
const keyIdStr = BufferUtils.utf8arrayToStr(keyInfo.decryptdata.keyId);
if (keyInfo.requestState !== KeyRequestState.NONE) {
this.logger.info(`Aborting key ${redactUrl(keyuri)} state=${keyInfo.requestState}`);
this.logger.qe({ critical: true, name: 'keyAborted', data: { uri: keyuri, keyId: keyIdStr } });
(_a = this.sessionHandler) === null || _a === void 0 ? void 0 : _a.keyAborted({ keyuri });
}
keyInfo.abort();
}
}
// Do cleanup if needed
handleKeyExchangeError(keyInfo, err) {
keyInfo.error(err); // Mark as error so we don't erroneously report abort
const keyuri = keyInfo.decryptdata.uri;
const keyIdStr = BufferUtils.utf8arrayToStr(keyInfo.decryptdata.keyId);
this.logger.qe({ critical: true, name: 'keyExchangeError', data: { uri: keyuri, keyId: keyIdStr, errMsg: err.message } });
}
updateItemId(itemId) {
// Update the itemId to which the key belongs to. The license release message carries this info.
// When you generate challenge this itemId was being used.
this.itemId = itemId;
}
/**
* Remove a key from the keysystem
* @param decryptdata
*/
removeKey(decryptdata) {
return this.removeKeyInternal(decryptdata);
}
removeKeyInternal(decryptdata) {
this.logger.info(`removing key ${redactUrl(decryptdata.uri)}`);
const keyInfo = this.keyUriToKeyInfo[decryptdata.uri];
if (keyInfo && keyInfo.session) {
const session = keyInfo.session;
keyInfo.abort();
keyInfo.destroy();
const keyIdStr = BufferUtils.utf8arrayToStr(decryptdata.keyId);
this.keyIdToKeyInfo[keyIdStr] = undefined;
this.keyUriToKeyInfo[decryptdata.uri] = undefined;
return this.removeSession(session);
}
}
removeSessions(decryptdata, shouldRemoveCurrentSession) {
const keyInfo = this.keyUriToKeyInfo[decryptdata.uri];
if (keyInfo) {
// Remove all previous sessions
const oldRemoves = keyInfo.oldSessions.map((session) => {
return this.removeSession(session);
});
keyInfo.oldSessions = [];
return iif(() => oldRemoves.length === 0, VOID, forkJoin(oldRemoves)).pipe(switchMap(() => {
if (shouldRemoveCurrentSession) {
// Finally remove the current session
return this.removeKeyInternal(decryptdata);
}
return VOID;
}));
}
return VOID;
}
removeSession(session) {
this.logger.info(`remove session ${session.sessionId}`);
const index = this.sessions.findIndex((sessionCtx) => {
return sessionCtx.session === session;
});
const sessionCtx = this.sessions[index];
if (index > -1) {
this.sessions.splice(index, 1);
}
this.sessionIdToKeyUri[session.sessionId] = undefined;
if (sessionCtx) {
return sessionCtx.destroy();
}
return VOID;
}
getKeyRequestInfo(keyInfo) {
const decryptdata = keyInfo.decryptdata;
const keyuri = decryptdata.uri;
const obs = keyInfo.setKeyRequestState(KeyRequestState.GET_REQUEST_INFO);
this.eventEmitter.trigger(HlsEvent$1.KEY_REQUEST_STARTED, { keyuri: keyuri, decryptdata: decryptdata, timestamp: Date.now() });
return obs;
}
setKeyRequestInfo(keyuri, requestInfo) {
const keyInfo = this.keyUriToKeyInfo[keyuri];
if (!keyInfo) {
this.logger.info(`Unexpected key requested ${redactUrl(keyuri)}`);
return;
}
keyInfo.resolveState(KeyRequestState.GET_REQUEST_INFO, requestInfo);
}
sanitizeRequest(requestInfo) {
return requestInfo;
}
/**
* Generate a license challenge for the key
* @param keyInfo The key we're requesting
* @param requestInfo Additional parameters for making the key request
* @param state MediaKeyStatus for the keyId associated with keyInfo
*/
generateLicenseChallengeInternal(keyInfo, requestInfo, state) {
if (state === 'status-pending') {
this.logger.info('Request already in progress');
}
const decryptdata = keyInfo.decryptdata;
const session = keyInfo.session;
const keyuri = decryptdata.uri;
const keyId = decryptdata.keyId;
let generateRequest$;
const getKeyResponse$ = keyInfo.setKeyRequestState(KeyRequestState.GET_CHALLENGE);
if (!session.generateRequestPromise) {
const initDataResult = this.generateInitData(keyId, decryptdata, requestInfo);
this.logger.info(`challenge create start uri=${redactUrl(keyInfo.decryptdata.uri)} versions=${JSON.stringify(keyInfo.decryptdata.formatversions)}`);
session.generateRequestPromise = session.generateRequest(initDataResult.initDataType, initDataResult.initData);
// May only be called once
generateRequest$ = scheduled(session.generateRequestPromise, queueScheduler).pipe(tap(() => {
this.sessionIdToKeyUri[session.sessionId] = keyuri;
}), catchError((reason) => {
this.logger.info(`${this.systemString} FAIL: generateRequest fail keyuri=${redactUrl(keyInfo.decryptdata.uri)} message=${reason.message}`);
throw new KeySystemError(reason.message, keyInfo.decryptdata.uri, 0, ErrorResponses.KeySystemFailedToGenerateLicenseRequest, this.systemString);
}));
}
else {
// If generateRequest was already called
generateRequest$ = scheduled(session.generateRequestPromise, queueScheduler).pipe(switchMap(() => this.generateRequestInitialized(keyInfo, state === 'usable')));
}
return forkJoin([getKeyResponse$, generateRequest$]).pipe(map((result) => new Uint8Array(result[0])));
}
/**
* This is different from startKeyRequest in that it could be triggered
* from an externally generated event. (Hls.generateKeyRequest)
*
* @param keyInfo Key info object
* @param requestInfo Extra information needed to make this request
*/
generateLicenseChallenge(keyInfo, requestInfo) {
const decryptdata = keyInfo.decryptdata;
const session = keyInfo.session;
const keyuri = decryptdata.uri;
const keyId = decryptdata.keyId;
const keyIdStr = BufferUtils.utf8arrayToStr(decryptdata.keyId);
this.logger.info(`${this.systemString} generateLicenseChallenge ${printKeyTag(decryptdata)}`);
this.logger.qe({ critical: true, name: 'generateLicenseChallenge', data: { uri: keyuri, keyId: keyIdStr } });
if (keyInfo.licenseChallenge) {
// This is handling for key systems like Widevine where the license challenge for renewal is already generated and we just need to use it.
keyInfo.resolveState(KeyRequestState.GET_CHALLENGE, keyInfo.licenseChallenge);
}
requestInfo = this.sanitizeRequest(requestInfo);
keyInfo.requestInfo = requestInfo;
// In gapless mode itemId needs to be updated to the newly loading item
//this.itemId = this.hls.inGaplessMode ? this.hls.loadingItem.itemId : this.itemId;
this.sessionId = this.sessionId || (requestInfo && requestInfo.sessionId) || this.itemId; // Use first id
let state;
// If it's playready Key system we need to change the endianness of the keyid in the key status
if (this.systemString === PlayReadyKeySystemProperties.systemStringPrefix) {
// Use a different copy of KID, otherwise it will change the endianness of KID in DecryptData
// since it's a referrence
const curKid = new Uint8Array(keyId);
keysystemutil.changeEndianness(curKid);
state = session.keyStatuses.get(curKid);
}
else {
state = session.keyStatuses.get(keyId); // Keysystem state
}
let createRequestPromise;
switch (state) {
case 'status-pending': // Challenge created or key known
case 'usable': // Finished key request already, should renew
case 'expired':
case undefined: {
createRequestPromise = this.generateLicenseChallengeInternal(keyInfo, requestInfo, state);
break;
}
default:
createRequestPromise = throwError(new KeySystemError(`Bad internal state state=${state}`, keyuri, 0, ErrorResponses.KeySystemUnexpectedState, this.systemString));
break;
}
return createRequestPromise;
}
/**
* Set the parsed license response
* @param keyuri URI of key corresponding to request
* @param parsedResponse The parsed response for the key request. Specific to key system
*/
setParsedResponse(keyuri, parsedResponse) {
const keyInfo = this.keyUriToKeyInfo[keyuri];
if (keyInfo) {
keyInfo.resolveState(KeyRequestState.GET_KEY_RESPONSE, parsedResponse);
}
else {
this.logger.info(`${this.systemString} no keyInfo for keyuri: ${redactUrl(keyuri)}`);
}
}
// keystatuseschange handler
handleKeyStatusesChange(event) {
const ks = event.target;
ks.keyStatuses.forEach((status, keyid, parent) => {
const currentKeyId = new Uint8Array(keyid);
// If it's playready Key system we need to change the endianness of the keyid in the key status
if (this.systemString === PlayReadyKeySystemProperties.systemStringPrefix) {
keysystemutil.changeEndianness(currentKeyId);
}
const keyIdStr = BufferUtils.utf8arrayToStr(currentKeyId);
const keyInfo = this.keyIdToKeyInfo[keyIdStr];
if (keyInfo) {
this.handleKeyStatusForKey(status, keyInfo);
}
});
}
handleKeyStatusForKey(status, keyInfo) {
if (!keyInfo) {
return;
}
const decryptdata = keyInfo.decryptdata;
const keyuri = decryptdata.uri;
switch (status) {
case 'internal-error': {
this.logger.error(`${this.systemString} internal-error for key ${printKeyTag(decryptdata)}`);
this._signalError(keyInfo, new KeyRequestError('Got internal error from key system', keyuri, 0, ErrorResponses.KeySystemInternalError, false, KeyRequestErrorReason.InternalError));
break;
}
case 'usable': {
if (keyInfo.requestState === KeyRequestState.PROCESS_LICENSE) {
keyInfo.resolveState(KeyRequestState.PROCESS_LICENSE, undefined);
}
break;
}
case 'output-restricted': {
this.logger.warn(`${this.systemString} output-restricted for key ${printKeyTag(decryptdata)}`);
if (keyInfo.session) {
// Cleanup the session, so that we don't keep the keys and try to renew it later
this.removeSession(keyInfo.session).pipe(takeUntil(this.destroy$)).subscribe();
}
this._signalError(keyInfo, new KeyRequestError('output-restricted', keyuri, 0, ErrorResponses.KeySystemOutputRestricted, false, KeyRequestErrorReason.OutputRestricted));
break;
}
case 'expired': {
this.logger.warn(`${this.systemString} expired for key ${printKeyTag(decryptdata)}. Attempting renewal`);
this._signalRenewal(keyInfo);
break;
}
default:
this.logger.info(`key status ${printKeyTag(decryptdata)} ${status}`);
break;
}
}
_scheduleRenewal(keyInfo, renewalMs) {
this.logger.info(`${this.systemString} Scheduling renewal for ${printKeyTag(keyInfo.decryptdata)} in ${renewalMs} ms`);
timer(renewalMs)
.pipe(tap(() => this._signalRenewal(keyInfo)), takeUntil(race(keyInfo.destroy$, this.destroy$, waitFor(keyInfo.onKeyRequestState$, (state) => state === KeyRequestState.GET_REQUEST_INFO))))
.subscribe();
}
_signalRenewal(keyInfo) {
this._keyStatusChange$.next({ decryptdata: keyInfo.decryptdata, status: 'needs-renewal' });
}
_signalError(keyInfo, error) {
this._keyStatusChange$.next({ decryptdata: keyInfo.decryptdata, status: 'error', error });
keyInfo.error(error);
}
}
const kClearKeySystemString = 'org.w3.clearkey';
const ClearKeySecurityLevels = {
NONE: 0,
};
const ClearKeySystemProperties = {
id: 'clearkey',
systemStringPrefix: kClearKeySystemString,
keyFormatString: kClearKeySystemString,
securityLevels: ClearKeySecurityLevels,
};
/**
* 2018 Apple Inc. All rights reserved.
*/
const KeySystemIdValues = ['clearkey', 'fairplaystreaming', 'playready', 'widevine'];
/**
* Clear key system implementation
*
* Uses July 2016 spec:
* https://www.w3.org/TR/2016/CR-encrypted-media-20160705/
*
* 2018 Apple Inc. All rights reserved.
*/
// default configuration to pass into requestMediaKeySystemAccess
const kClearKeySystemConfig = {
initDataTypes: ['keyids', 'cenc'],
};
class ClearKeySystem extends KeySystem {
constructor(mediaKeys, keySystemString, config, eventEmitter, sessionHandler, logger) {
super(mediaKeys, keySystemString, config, eventEmitter, false, sessionHandler, logger);
}
// destroy()
static get requestAccessConfig() {
return kClearKeySystemConfig;
}
get needsCert() {
return false;
}
getKeyRequestResponse(keyInfo, licenseChallenge) {
const keyuri = keyInfo.decryptdata.uri;
const loaderConfig = {
maxLoadTimeMs: 0,
maxTimeToFirstByteMs: 0,
autoRetry: false,
timeoutRetry: null,
errorRetry: null,
};
return fromUrlArrayBuffer({ url: keyuri, xhrSetup: this.config.xhrSetup }, loaderConfig).pipe(map(([loadArrayBufferResult, _]) => {
const key = new Uint8Array(loadArrayBufferResult);
const response = {
response: this.parseResponse(licenseChallenge, key),
};
return response;
}));
}
parseResponse(licenseChallenge, key) {
const keyObj = {
kty: 'oct',
kid: NumericEncodingUtils$1.base64UrlEncode(licenseChallenge),
k: NumericEncodingUtils$1.base64UrlEncode(key),
};
return BufferUtils.strToUtf8array(JSON.stringify({ keys: [keyObj] }));
}
handleParsedKeyResponse(keyInfo, keyResponse) {
const responseBlob = keyResponse.response;
const processLicense = keyInfo.setKeyRequestState(KeyRequestState.PROCESS_LICENSE);
const updateSession = from(keyInfo.session.update(responseBlob)).pipe(tap(() => {
const keyId = keyInfo.decryptdata.keyId;
const state = keyInfo.session.keyStatuses.get(keyId);
this.handleKeyStatusForKey(state, keyInfo);
}), catchError((reason) => {
const response = { code: reason.code, text: 'Failed to update with key response' };
const err = new KeySystemError(reason.message, keyInfo.decryptdata.uri, reason.code, response, this.systemString);
throw err;
}));
return forkJoin([processLicense, updateSession]).pipe(mapTo(undefined));
}
generateInitData(keyId /* decryptdata, requestInfo*/) {
return { initData: keysystemutil.makeKeyIdsInitData([keyId]), initDataType: 'keyids' };
}
generateRequestInitialized() {
return VOID;
}
sanitizeRequest(requestInfo) {
return requestInfo;
}
// message
handleKeyMessage(event) {
if (this.isDestroying) {
this.logger.info('In the middle of destroying, ignore key message');
return;
}
if (event.messageType !== 'license-request') {
this.logger.info(`${this.systemString} Unexpected key message type ${event.messageType}`);
return;
}
const message = new Uint8Array(event.message);
const request = JSON.parse(BufferUtils.utf8arrayToStr(message).trim());
if (request.kids.length !== 1) {
this.logger.info(`${this.systemString} Unexpected number of keyIds ${request.kids.length}`);
return;
}
const keyId = NumericEncodingUtils$1.base64Decode(request.kids[0]); // just care about the first for now
const keyIdStr = BufferUtils.utf8arrayToStr(keyId);
const keyInfo = this.keyIdToKeyInfo[keyIdStr];
if (keyInfo) {
keyInfo.resolveState(KeyRequestState.GET_CHALLENGE, keyId);
}
else {
this.logger.info(`${this.systemString} no keyInfo for keyId ${JSON.stringify(keyId)}`);
}
}
}
var ClearKeySystem$1 = ClearKeySystem;
/*
* FairPlayStreaming key system constants
*
* 2018 Apple Inc. All rights reserved.
*/
const kFairPlayStreamingKeySystemConfig = {
initDataTypes: ['cenc'],
};
const kFairPlayStreamingKeySystemUUID = new Uint8Array([148, 206, 134, 251, 7, 255, 79, 67, 173, 184, 147, 210, 250, 150, 140, 162]);
var SchemeFourCC;
(function (SchemeFourCC) {
SchemeFourCC[SchemeFourCC["CENC"] = 1667591779] = "CENC";
SchemeFourCC[SchemeFourCC["CBCS"] = 1667392371] = "CBCS";
})(SchemeFourCC || (SchemeFourCC = {}));
/**
* Base class for FPS key systems
*/
class FairPlayStreamingKeySystemBase extends KeySystem {
constructor(mediaKeys, keySystemString, config, eventEmitter, useSingleKeySession, sessionHandler, logger) {
super(mediaKeys, keySystemString, config, eventEmitter, useSingleKeySession, sessionHandler, logger);
this._hasSetRenewal = false;
}
static get systemId() {
return kFairPlayStreamingKeySystemUUID;
}
static get requestAccessConfig() {
return kFairPlayStreamingKeySystemConfig;
}
get needsCert() {
return true;
}
sanitizeRequest(requestInfo) {
return {
assetId: requestInfo && requestInfo.assetId ? new Uint8Array(requestInfo.assetId) : undefined,
ssc: requestInfo && requestInfo.ssc ? new Uint8Array(requestInfo.ssc) : undefined,
sessionId: requestInfo && requestInfo.sessionId ? requestInfo.sessionId : undefined,
};
}
_scheduleRenewal(keyInfo, renewalMs) {
if (!this.useSingleKeySession) {
// Each key has its own timer
super._scheduleRenewal(keyInfo, renewalMs);
}
else if (!this._hasSetRenewal) {
this._hasSetRenewal = true;
this.logger.info(`${this.systemString} Scheduling renewal in ${renewalMs} ms`);
timer(renewalMs)
.pipe(tap(() => {
// use first available keyInfo
const keyInfo = Object.values(this.keyUriToKeyInfo)[0];
if (keyInfo) {
this._signalRenewal(keyInfo);
}
}), finalize$1(() => {
this._hasSetRenewal = false;
}), takeUntil(this.destroy$))
.subscribe();
}
}
/**
* Handle a parsed key response
* @param {Object} keyInfo Info about the key
* @param {Object} keyResponse The parsed key response object { statusCode, ckc, renewalData }
* @returns {Observable} message to pass to update() for processing license
*/
handleParsedKeyResponse(keyInfo, keyResponse) {
const keyuri = keyInfo.decryptdata.uri;
const statusCode = keyResponse.statusCode;
const licenseResponse = keyResponse.ckc && keyResponse.ckc.byteLength !== 0 ? keyResponse.ckc : keyResponse.license && keyResponse.license.byteLength !== 0 ? keyResponse.license : undefined;
// Special handling in case of HTTP Errors during key requests.
if (statusCode === 0 && !licenseResponse) {
return throwError(new KeyRequestError('License request resulted in HTTP Error', keyuri, statusCode, { code: statusCode, text: 'HTTP Error' }, true, KeyRequestErrorReason.HttpError));
}
if (statusCode !== 0) {
return throwError(new KeyRequestError('License server responded with error', keyuri, statusCode, { code: statusCode, text: 'Server Error' }, false, KeyRequestErrorReason.LicenseServerError));
}
if (!licenseResponse) {
const err = new KeyRequestError('License server responded with invalid license', keyuri, statusCode, { code: statusCode, text: 'Invalid license' }, false, KeyRequestErrorReason.LicenseServerError);
return throwError(err);
}
const renewalDate = keyResponse.renewalDate;
const now = new Date();
const renewalMs = renewalDate > now ? renewalDate.getTime() - now.getTime() : 0;
if (renewalMs > 0) {
this._scheduleRenewal(keyInfo, renewalMs);
}
const ckcArray = this.makeProcessLicenseRequestMessage(keyInfo, licenseResponse, renewalMs);
// Only resolve if we got success, either from 'usable' keystatuschange event
// or on promise completion with 'usable' key status. Otherwise reject
const session = keyInfo.session;
const updateSession = from(session.update(ckcArray)).pipe(tap(() => {
const keyId = keyInfo.decryptdata.keyId;
const status = session.keyStatuses.get(keyId);
// Slightly faster than waiting for keystatuschange
this.handleKeyStatusForKey(status, keyInfo);
}), catchError((error) => {
const err = new KeySystemError(error.message, keyInfo.decryptdata.uri, 0, ErrorResponses.KeySystemFailedToUpdateSession, this.systemString);
throw err;
}));
const getLicense = keyInfo.setKeyRequestState(KeyRequestState.PROCESS_LICENSE);
return forkJoin([getLicense, updateSession]).pipe(mapTo(undefined));
}
makeKeyRequests(requestInfoArray) {
const keyRequests = [];
for (const r of requestInfoArray) {
const decryptdata = r.decryptdata;
const requestInfo = r.requestInfo;
const keyId = decryptdata.keyId;
keyRequests.push({
keyId: keyId,
assetId: requestInfo ? requestInfo.assetId : undefined,
ssc: requestInfo ? requestInfo.ssc : undefined,
versionList: decryptdata.formatversions,
});
}
return keyRequests;
}
getSchemeAndFlags(decryptdata) {
const scheme = decryptdata.method === 'ISO-23001-7' ? SchemeFourCC.CENC : SchemeFourCC.CBCS; // TODO pass real scheme through.
const flags = 0;
// TODO
/* if (this.hls.playingItem.secureStop) {
flags |= 0x01;
} */
return { scheme, flags };
}
generateInitData(keyId, decryptdata, requestInfo) {
// Generate a PSSH
const { scheme, flags } = this.getSchemeAndFlags(decryptdata);
const keyRequests = this.makeKeyRequests([{ decryptdata, requestInfo }]);
const pssh = this.makeFpsKeySystemInitData(scheme, flags, keyRequests);
// console.log('PSSH=' + Hex.hexDump(pssh));
return { initData: pssh, initDataType: 'cenc' };
}
/**
* Generate a key renewal request on an already initialized session
* @param keyInfo Info about the key we're requesting
* @param isRenewal Is this a renewal requewst
* @returns promise for when update call is done.
**/
generateRequestInitialized(keyInfo, isRenewal) {
tag(`[Keys] challenge create start uri=${redactUrl(keyInfo.decryptdata.uri)} versions=${JSON.stringify(keyInfo.decryptdata.formatversions)}`);
const message = this.makeKeyRequestMessage(keyInfo, isRenewal);
if (!message) {
const err = new KeyRequestError('Unable to generate request using existing keySession', keyInfo.decryptdata.uri, 0, ErrorResponses.KeySystemFailedToGenerateLicenseRequest, true, KeyRequestErrorReason.InvalidState);
return throwError(err);
}
return from(keyInfo.session.update(message)).pipe(tap(() => {
keyInfo.requestInfo = undefined; // Don't need requestInfo anymore.
}), catchError((reason) => {
tag(`[Keys] ${this.systemString} FAIL: generateRequestInitialized keyuri=${redactUrl(keyInfo.decryptdata.uri)} message=${reason.message}`);
throw new KeySystemError(reason.message, keyInfo.decryptdata.uri, 0, ErrorResponses.KeySystemFailedToGenerateLicenseRenewal, this.systemString);
}));
}
/**
* @param {Object} keyInfo Info about the key we're requesting
* @param {Uint8Array} licenseChallenge Challenge bytes
* @returns {Observable
\n';
};
_proto.tablerow = function tablerow(content) {
return '
\n' + content + '
\n';
};
_proto.tablecell = function tablecell(content, flags) {
var type = flags.header ? 'th' : 'td';
var tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>';
return tag + content + '' + type + '>\n';
} // span level renderer
;
_proto.strong = function strong(text) {
return '' + text + '';
};
_proto.em = function em(text) {
return '' + text + '';
};
_proto.codespan = function codespan(text) {
return '' + text + '';
};
_proto.br = function br() {
return this.options.xhtml ? ' ' : ' ';
};
_proto.del = function del(text) {
return '' + text + '';
};
_proto.link = function link(href, title, text) {
href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
if (href === null) {
return text;
}
var out = '' + text + '';
return out;
};
_proto.image = function image(href, title, text) {
href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
if (href === null) {
return text;
}
var out = '' : '>';
return out;
};
_proto.text = function text(_text) {
return _text;
};
return Renderer;
}();
/**
* TextRenderer
* returns only the textual part of the token
*/
var TextRenderer = /*#__PURE__*/function () {
function TextRenderer() {}
var _proto = TextRenderer.prototype;
// no need for block level renderers
_proto.strong = function strong(text) {
return text;
};
_proto.em = function em(text) {
return text;
};
_proto.codespan = function codespan(text) {
return text;
};
_proto.del = function del(text) {
return text;
};
_proto.html = function html(text) {
return text;
};
_proto.text = function text(_text) {
return _text;
};
_proto.link = function link(href, title, text) {
return '' + text;
};
_proto.image = function image(href, title, text) {
return '' + text;
};
_proto.br = function br() {
return '';
};
return TextRenderer;
}();
/**
* Slugger generates header id
*/
var Slugger = /*#__PURE__*/function () {
function Slugger() {
this.seen = {};
}
var _proto = Slugger.prototype;
_proto.serialize = function serialize(value) {
return value.toLowerCase().trim() // remove html tags
.replace(/<[!\/a-z].*?>/ig, '') // remove unwanted chars
.replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '').replace(/\s/g, '-');
}
/**
* Finds the next safe (unique) slug to use
*/
;
_proto.getNextSafeSlug = function getNextSafeSlug(originalSlug, isDryRun) {
var slug = originalSlug;
var occurenceAccumulator = 0;
if (this.seen.hasOwnProperty(slug)) {
occurenceAccumulator = this.seen[originalSlug];
do {
occurenceAccumulator++;
slug = originalSlug + '-' + occurenceAccumulator;
} while (this.seen.hasOwnProperty(slug));
}
if (!isDryRun) {
this.seen[originalSlug] = occurenceAccumulator;
this.seen[slug] = 0;
}
return slug;
}
/**
* Convert string to unique id
* @param {object} options
* @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator.
*/
;
_proto.slug = function slug(value, options) {
if (options === void 0) {
options = {};
}
var slug = this.serialize(value);
return this.getNextSafeSlug(slug, options.dryrun);
};
return Slugger;
}();
/**
* Parsing & Compiling
*/
var Parser = /*#__PURE__*/function () {
function Parser(options) {
this.options = options || exports.defaults;
this.options.renderer = this.options.renderer || new Renderer();
this.renderer = this.options.renderer;
this.renderer.options = this.options;
this.textRenderer = new TextRenderer();
this.slugger = new Slugger();
}
/**
* Static Parse Method
*/
Parser.parse = function parse(tokens, options) {
var parser = new Parser(options);
return parser.parse(tokens);
}
/**
* Static Parse Inline Method
*/
;
Parser.parseInline = function parseInline(tokens, options) {
var parser = new Parser(options);
return parser.parseInline(tokens);
}
/**
* Parse Loop
*/
;
var _proto = Parser.prototype;
_proto.parse = function parse(tokens, top) {
if (top === void 0) {
top = true;
}
var out = '',
i,
j,
k,
l2,
l3,
row,
cell,
header,
body,
token,
ordered,
start,
loose,
itemBody,
item,
checked,
task,
checkbox,
ret;
var l = tokens.length;
for (i = 0; i < l; i++) {
token = tokens[i]; // Run any renderer extensions
if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
ret = this.options.extensions.renderers[token.type].call({
parser: this
}, token);
if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(token.type)) {
out += ret || '';
continue;
}
}
switch (token.type) {
case 'space':
{
continue;
}
case 'hr':
{
out += this.renderer.hr();
continue;
}
case 'heading':
{
out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape(this.parseInline(token.tokens, this.textRenderer)), this.slugger);
continue;
}
case 'code':
{
out += this.renderer.code(token.text, token.lang, token.escaped);
continue;
}
case 'table':
{
header = ''; // header
cell = '';
l2 = token.header.length;
for (j = 0; j < l2; j++) {
cell += this.renderer.tablecell(this.parseInline(token.header[j].tokens), {
header: true,
align: token.align[j]
});
}
header += this.renderer.tablerow(cell);
body = '';
l2 = token.rows.length;
for (j = 0; j < l2; j++) {
row = token.rows[j];
cell = '';
l3 = row.length;
for (k = 0; k < l3; k++) {
cell += this.renderer.tablecell(this.parseInline(row[k].tokens), {
header: false,
align: token.align[k]
});
}
body += this.renderer.tablerow(cell);
}
out += this.renderer.table(header, body);
continue;
}
case 'blockquote':
{
body = this.parse(token.tokens);
out += this.renderer.blockquote(body);
continue;
}
case 'list':
{
ordered = token.ordered;
start = token.start;
loose = token.loose;
l2 = token.items.length;
body = '';
for (j = 0; j < l2; j++) {
item = token.items[j];
checked = item.checked;
task = item.task;
itemBody = '';
if (item.task) {
checkbox = this.renderer.checkbox(checked);
if (loose) {
if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
}
} else {
item.tokens.unshift({
type: 'text',
text: checkbox
});
}
} else {
itemBody += checkbox;
}
}
itemBody += this.parse(item.tokens, loose);
body += this.renderer.listitem(itemBody, task, checked);
}
out += this.renderer.list(body, ordered, start);
continue;
}
case 'html':
{
// TODO parse inline content if parameter markdown=1
out += this.renderer.html(token.text);
continue;
}
case 'paragraph':
{
out += this.renderer.paragraph(this.parseInline(token.tokens));
continue;
}
case 'text':
{
body = token.tokens ? this.parseInline(token.tokens) : token.text;
while (i + 1 < l && tokens[i + 1].type === 'text') {
token = tokens[++i];
body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
}
out += top ? this.renderer.paragraph(body) : body;
continue;
}
default:
{
var errMsg = 'Token with "' + token.type + '" type was not found.';
if (this.options.silent) {
console.error(errMsg);
return;
} else {
throw new Error(errMsg);
}
}
}
}
return out;
}
/**
* Parse Inline Tokens
*/
;
_proto.parseInline = function parseInline(tokens, renderer) {
renderer = renderer || this.renderer;
var out = '',
i,
token,
ret;
var l = tokens.length;
for (i = 0; i < l; i++) {
token = tokens[i]; // Run any renderer extensions
if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
ret = this.options.extensions.renderers[token.type].call({
parser: this
}, token);
if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
out += ret || '';
continue;
}
}
switch (token.type) {
case 'escape':
{
out += renderer.text(token.text);
break;
}
case 'html':
{
out += renderer.html(token.text);
break;
}
case 'link':
{
out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
break;
}
case 'image':
{
out += renderer.image(token.href, token.title, token.text);
break;
}
case 'strong':
{
out += renderer.strong(this.parseInline(token.tokens, renderer));
break;
}
case 'em':
{
out += renderer.em(this.parseInline(token.tokens, renderer));
break;
}
case 'codespan':
{
out += renderer.codespan(token.text);
break;
}
case 'br':
{
out += renderer.br();
break;
}
case 'del':
{
out += renderer.del(this.parseInline(token.tokens, renderer));
break;
}
case 'text':
{
out += renderer.text(token.text);
break;
}
default:
{
var errMsg = 'Token with "' + token.type + '" type was not found.';
if (this.options.silent) {
console.error(errMsg);
return;
} else {
throw new Error(errMsg);
}
}
}
}
return out;
};
return Parser;
}();
/**
* Marked
*/
function marked(src, opt, callback) {
// throw error in case of non string input
if (typeof src === 'undefined' || src === null) {
throw new Error('marked(): input parameter is undefined or null');
}
if (typeof src !== 'string') {
throw new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');
}
if (typeof opt === 'function') {
callback = opt;
opt = null;
}
opt = merge({}, marked.defaults, opt || {});
checkSanitizeDeprecation(opt);
if (callback) {
var highlight = opt.highlight;
var tokens;
try {
tokens = Lexer.lex(src, opt);
} catch (e) {
return callback(e);
}
var done = function done(err) {
var out;
if (!err) {
try {
if (opt.walkTokens) {
marked.walkTokens(tokens, opt.walkTokens);
}
out = Parser.parse(tokens, opt);
} catch (e) {
err = e;
}
}
opt.highlight = highlight;
return err ? callback(err) : callback(null, out);
};
if (!highlight || highlight.length < 3) {
return done();
}
delete opt.highlight;
if (!tokens.length) return done();
var pending = 0;
marked.walkTokens(tokens, function (token) {
if (token.type === 'code') {
pending++;
setTimeout(function () {
highlight(token.text, token.lang, function (err, code) {
if (err) {
return done(err);
}
if (code != null && code !== token.text) {
token.text = code;
token.escaped = true;
}
pending--;
if (pending === 0) {
done();
}
});
}, 0);
}
});
if (pending === 0) {
done();
}
return;
}
try {
var _tokens = Lexer.lex(src, opt);
if (opt.walkTokens) {
marked.walkTokens(_tokens, opt.walkTokens);
}
return Parser.parse(_tokens, opt);
} catch (e) {
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
if (opt.silent) {
return '
An error occurred:
' + escape(e.message + '', true) + '
';
}
throw e;
}
}
/**
* Options
*/
marked.options = marked.setOptions = function (opt) {
merge(marked.defaults, opt);
changeDefaults(marked.defaults);
return marked;
};
marked.getDefaults = getDefaults;
marked.defaults = exports.defaults;
/**
* Use Extension
*/
marked.use = function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var opts = merge.apply(void 0, [{}].concat(args));
var extensions = marked.defaults.extensions || {
renderers: {},
childTokens: {}
};
var hasExtensions;
args.forEach(function (pack) {
// ==-- Parse "addon" extensions --== //
if (pack.extensions) {
hasExtensions = true;
pack.extensions.forEach(function (ext) {
if (!ext.name) {
throw new Error('extension name required');
}
if (ext.renderer) {
// Renderer extensions
var prevRenderer = extensions.renderers ? extensions.renderers[ext.name] : null;
if (prevRenderer) {
// Replace extension with func to run new extension but fall back if false
extensions.renderers[ext.name] = function () {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
var ret = ext.renderer.apply(this, args);
if (ret === false) {
ret = prevRenderer.apply(this, args);
}
return ret;
};
} else {
extensions.renderers[ext.name] = ext.renderer;
}
}
if (ext.tokenizer) {
// Tokenizer Extensions
if (!ext.level || ext.level !== 'block' && ext.level !== 'inline') {
throw new Error("extension level must be 'block' or 'inline'");
}
if (extensions[ext.level]) {
extensions[ext.level].unshift(ext.tokenizer);
} else {
extensions[ext.level] = [ext.tokenizer];
}
if (ext.start) {
// Function to check for start of token
if (ext.level === 'block') {
if (extensions.startBlock) {
extensions.startBlock.push(ext.start);
} else {
extensions.startBlock = [ext.start];
}
} else if (ext.level === 'inline') {
if (extensions.startInline) {
extensions.startInline.push(ext.start);
} else {
extensions.startInline = [ext.start];
}
}
}
}
if (ext.childTokens) {
// Child tokens to be visited by walkTokens
extensions.childTokens[ext.name] = ext.childTokens;
}
});
} // ==-- Parse "overwrite" extensions --== //
if (pack.renderer) {
(function () {
var renderer = marked.defaults.renderer || new Renderer();
var _loop = function _loop(prop) {
var prevRenderer = renderer[prop]; // Replace renderer with func to run extension, but fall back if false
renderer[prop] = function () {
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
var ret = pack.renderer[prop].apply(renderer, args);
if (ret === false) {
ret = prevRenderer.apply(renderer, args);
}
return ret;
};
};
for (var prop in pack.renderer) {
_loop(prop);
}
opts.renderer = renderer;
})();
}
if (pack.tokenizer) {
(function () {
var tokenizer = marked.defaults.tokenizer || new Tokenizer();
var _loop2 = function _loop2(prop) {
var prevTokenizer = tokenizer[prop]; // Replace tokenizer with func to run extension, but fall back if false
tokenizer[prop] = function () {
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
var ret = pack.tokenizer[prop].apply(tokenizer, args);
if (ret === false) {
ret = prevTokenizer.apply(tokenizer, args);
}
return ret;
};
};
for (var prop in pack.tokenizer) {
_loop2(prop);
}
opts.tokenizer = tokenizer;
})();
} // ==-- Parse WalkTokens extensions --== //
if (pack.walkTokens) {
var _walkTokens = marked.defaults.walkTokens;
opts.walkTokens = function (token) {
pack.walkTokens.call(this, token);
if (_walkTokens) {
_walkTokens.call(this, token);
}
};
}
if (hasExtensions) {
opts.extensions = extensions;
}
marked.setOptions(opts);
});
};
/**
* Run callback for every token
*/
marked.walkTokens = function (tokens, callback) {
var _loop3 = function _loop3() {
var token = _step.value;
callback.call(marked, token);
switch (token.type) {
case 'table':
{
for (var _iterator2 = _createForOfIteratorHelperLoose(token.header), _step2; !(_step2 = _iterator2()).done;) {
var cell = _step2.value;
marked.walkTokens(cell.tokens, callback);
}
for (var _iterator3 = _createForOfIteratorHelperLoose(token.rows), _step3; !(_step3 = _iterator3()).done;) {
var row = _step3.value;
for (var _iterator4 = _createForOfIteratorHelperLoose(row), _step4; !(_step4 = _iterator4()).done;) {
var _cell = _step4.value;
marked.walkTokens(_cell.tokens, callback);
}
}
break;
}
case 'list':
{
marked.walkTokens(token.items, callback);
break;
}
default:
{
if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) {
// Walk any extensions
marked.defaults.extensions.childTokens[token.type].forEach(function (childTokens) {
marked.walkTokens(token[childTokens], callback);
});
} else if (token.tokens) {
marked.walkTokens(token.tokens, callback);
}
}
}
};
for (var _iterator = _createForOfIteratorHelperLoose(tokens), _step; !(_step = _iterator()).done;) {
_loop3();
}
};
/**
* Parse Inline
*/
marked.parseInline = function (src, opt) {
// throw error in case of non string input
if (typeof src === 'undefined' || src === null) {
throw new Error('marked.parseInline(): input parameter is undefined or null');
}
if (typeof src !== 'string') {
throw new Error('marked.parseInline(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');
}
opt = merge({}, marked.defaults, opt || {});
checkSanitizeDeprecation(opt);
try {
var tokens = Lexer.lexInline(src, opt);
if (opt.walkTokens) {
marked.walkTokens(tokens, opt.walkTokens);
}
return Parser.parseInline(tokens, opt);
} catch (e) {
e.message += '\nPlease report this to https://github.com/markedjs/marked.';
if (opt.silent) {
return '
An error occurred:
' + escape(e.message + '', true) + '
';
}
throw e;
}
};
/**
* Expose
*/
marked.Parser = Parser;
marked.parser = Parser.parse;
marked.Renderer = Renderer;
marked.TextRenderer = TextRenderer;
marked.Lexer = Lexer;
marked.lexer = Lexer.lex;
marked.Tokenizer = Tokenizer;
marked.Slugger = Slugger;
marked.parse = marked;
var options = marked.options;
var setOptions = marked.setOptions;
var use = marked.use;
var walkTokens = marked.walkTokens;
var parseInline = marked.parseInline;
var parse = marked;
var parser = Parser.parse;
var lexer = Lexer.lex;
exports.Lexer = Lexer;
exports.Parser = Parser;
exports.Renderer = Renderer;
exports.Slugger = Slugger;
exports.TextRenderer = TextRenderer;
exports.Tokenizer = Tokenizer;
exports["default"] = marked;
exports.getDefaults = getDefaults;
exports.lexer = lexer;
exports.options = options;
exports.parse = parse;
exports.parseInline = parseInline;
exports.parser = parser;
exports.setOptions = setOptions;
exports.use = use;
exports.walkTokens = walkTokens;
Object.defineProperty(exports, '__esModule', { value: true });
}));
================================================
FILE: src/renderer/lib/smoothscroll.js
================================================
/* smoothscroll v0.4.4 - 2019 - Dustan Kasten, Jeremias Menichelli - MIT License */
(function () {
'use strict';
// polyfill
function polyfill() {
// aliases
var w = window;
var d = document;
// return if scroll behavior is supported and polyfill is not forced
if (
'scrollBehavior' in d.documentElement.style &&
w.__forceSmoothScrollPolyfill__ !== true
) {
return;
}
// globals
var Element = w.HTMLElement || w.Element;
var SCROLL_TIME = 468;
// object gathering original scroll methods
var original = {
scroll: w.scroll || w.scrollTo,
scrollBy: w.scrollBy,
elementScroll: Element.prototype.scroll || scrollElement,
scrollIntoView: Element.prototype.scrollIntoView
};
// define timing method
var now =
w.performance && w.performance.now
? w.performance.now.bind(w.performance)
: Date.now;
/**
* indicates if a the current browser is made by Microsoft
* @method isMicrosoftBrowser
* @param {String} userAgent
* @returns {Boolean}
*/
function isMicrosoftBrowser(userAgent) {
var userAgentPatterns = ['MSIE ', 'Trident/', 'Edge/'];
return new RegExp(userAgentPatterns.join('|')).test(userAgent);
}
/*
* IE has rounding bug rounding down clientHeight and clientWidth and
* rounding up scrollHeight and scrollWidth causing false positives
* on hasScrollableSpace
*/
var ROUNDING_TOLERANCE = isMicrosoftBrowser(w.navigator.userAgent) ? 1 : 0;
/**
* changes scroll position inside an element
* @method scrollElement
* @param {Number} x
* @param {Number} y
* @returns {undefined}
*/
function scrollElement(x, y) {
this.scrollLeft = x;
this.scrollTop = y;
}
/**
* returns result of applying ease math function to a number
* @method ease
* @param {Number} k
* @returns {Number}
*/
function ease(k) {
return 0.5 * (1 - Math.cos(Math.PI * k));
}
/**
* indicates if a smooth behavior should be applied
* @method shouldBailOut
* @param {Number|Object} firstArg
* @returns {Boolean}
*/
function shouldBailOut(firstArg) {
if (
firstArg === null ||
typeof firstArg !== 'object' ||
firstArg.behavior === undefined ||
firstArg.behavior === 'auto' ||
firstArg.behavior === 'instant'
) {
// first argument is not an object/null
// or behavior is auto, instant or undefined
return true;
}
if (typeof firstArg === 'object' && firstArg.behavior === 'smooth') {
// first argument is an object and behavior is smooth
return false;
}
// throw error when behavior is not supported
throw new TypeError(
'behavior member of ScrollOptions ' +
firstArg.behavior +
' is not a valid value for enumeration ScrollBehavior.'
);
}
/**
* indicates if an element has scrollable space in the provided axis
* @method hasScrollableSpace
* @param {Node} el
* @param {String} axis
* @returns {Boolean}
*/
function hasScrollableSpace(el, axis) {
if (axis === 'Y') {
return el.clientHeight + ROUNDING_TOLERANCE < el.scrollHeight;
}
if (axis === 'X') {
return el.clientWidth + ROUNDING_TOLERANCE < el.scrollWidth;
}
}
/**
* indicates if an element has a scrollable overflow property in the axis
* @method canOverflow
* @param {Node} el
* @param {String} axis
* @returns {Boolean}
*/
function canOverflow(el, axis) {
var overflowValue = w.getComputedStyle(el, null)['overflow' + axis];
return overflowValue === 'auto' || overflowValue === 'scroll';
}
/**
* indicates if an element can be scrolled in either axis
* @method isScrollable
* @param {Node} el
* @param {String} axis
* @returns {Boolean}
*/
function isScrollable(el) {
var isScrollableY = hasScrollableSpace(el, 'Y') && canOverflow(el, 'Y');
var isScrollableX = hasScrollableSpace(el, 'X') && canOverflow(el, 'X');
return isScrollableY || isScrollableX;
}
/**
* finds scrollable parent of an element
* @method findScrollableParent
* @param {Node} el
* @returns {Node} el
*/
function findScrollableParent(el) {
while (el !== d.body && isScrollable(el) === false) {
el = el.parentNode || el.host;
}
return el;
}
/**
* self invoked function that, given a context, steps through scrolling
* @method step
* @param {Object} context
* @returns {undefined}
*/
function step(context) {
var time = now();
var value;
var currentX;
var currentY;
var elapsed = (time - context.startTime) / SCROLL_TIME;
// avoid elapsed times higher than one
elapsed = elapsed > 1 ? 1 : elapsed;
// apply easing to elapsed time
value = ease(elapsed);
currentX = context.startX + (context.x - context.startX) * value;
currentY = context.startY + (context.y - context.startY) * value;
context.method.call(context.scrollable, currentX, currentY);
// scroll more if we have not reached our destination
if (currentX !== context.x || currentY !== context.y) {
w.requestAnimationFrame(step.bind(w, context));
}
}
/**
* scrolls window or element with a smooth behavior
* @method smoothScroll
* @param {Object|Node} el
* @param {Number} x
* @param {Number} y
* @returns {undefined}
*/
function smoothScroll(el, x, y) {
var scrollable;
var startX;
var startY;
var method;
var startTime = now();
// define scroll context
if (el === d.body) {
scrollable = w;
startX = w.scrollX || w.pageXOffset;
startY = w.scrollY || w.pageYOffset;
method = original.scroll;
} else {
scrollable = el;
startX = el.scrollLeft;
startY = el.scrollTop;
method = scrollElement;
}
// scroll looping over a frame
step({
scrollable: scrollable,
method: method,
startTime: startTime,
startX: startX,
startY: startY,
x: x,
y: y
});
}
// ORIGINAL METHODS OVERRIDES
// w.scroll and w.scrollTo
w.scroll = w.scrollTo = function() {
// avoid action when no arguments are passed
if (arguments[0] === undefined) {
return;
}
// avoid smooth behavior if not required
if (shouldBailOut(arguments[0]) === true) {
original.scroll.call(
w,
arguments[0].left !== undefined
? arguments[0].left
: typeof arguments[0] !== 'object'
? arguments[0]
: w.scrollX || w.pageXOffset,
// use top prop, second argument if present or fallback to scrollY
arguments[0].top !== undefined
? arguments[0].top
: arguments[1] !== undefined
? arguments[1]
: w.scrollY || w.pageYOffset
);
return;
}
// LET THE SMOOTHNESS BEGIN!
smoothScroll.call(
w,
d.body,
arguments[0].left !== undefined
? ~~arguments[0].left
: w.scrollX || w.pageXOffset,
arguments[0].top !== undefined
? ~~arguments[0].top
: w.scrollY || w.pageYOffset
);
};
// w.scrollBy
w.scrollBy = function() {
// avoid action when no arguments are passed
if (arguments[0] === undefined) {
return;
}
// avoid smooth behavior if not required
if (shouldBailOut(arguments[0])) {
original.scrollBy.call(
w,
arguments[0].left !== undefined
? arguments[0].left
: typeof arguments[0] !== 'object' ? arguments[0] : 0,
arguments[0].top !== undefined
? arguments[0].top
: arguments[1] !== undefined ? arguments[1] : 0
);
return;
}
// LET THE SMOOTHNESS BEGIN!
smoothScroll.call(
w,
d.body,
~~arguments[0].left + (w.scrollX || w.pageXOffset),
~~arguments[0].top + (w.scrollY || w.pageYOffset)
);
};
// Element.prototype.scroll and Element.prototype.scrollTo
Element.prototype.scroll = Element.prototype.scrollTo = function() {
// avoid action when no arguments are passed
if (arguments[0] === undefined) {
return;
}
// avoid smooth behavior if not required
if (shouldBailOut(arguments[0]) === true) {
// if one number is passed, throw error to match Firefox implementation
if (typeof arguments[0] === 'number' && arguments[1] === undefined) {
throw new SyntaxError('Value could not be converted');
}
original.elementScroll.call(
this,
// use left prop, first number argument or fallback to scrollLeft
arguments[0].left !== undefined
? ~~arguments[0].left
: typeof arguments[0] !== 'object' ? ~~arguments[0] : this.scrollLeft,
// use top prop, second argument or fallback to scrollTop
arguments[0].top !== undefined
? ~~arguments[0].top
: arguments[1] !== undefined ? ~~arguments[1] : this.scrollTop
);
return;
}
var left = arguments[0].left;
var top = arguments[0].top;
// LET THE SMOOTHNESS BEGIN!
smoothScroll.call(
this,
this,
typeof left === 'undefined' ? this.scrollLeft : ~~left,
typeof top === 'undefined' ? this.scrollTop : ~~top
);
};
// Element.prototype.scrollBy
Element.prototype.scrollBy = function() {
// avoid action when no arguments are passed
if (arguments[0] === undefined) {
return;
}
// avoid smooth behavior if not required
if (shouldBailOut(arguments[0]) === true) {
original.elementScroll.call(
this,
arguments[0].left !== undefined
? ~~arguments[0].left + this.scrollLeft
: ~~arguments[0] + this.scrollLeft,
arguments[0].top !== undefined
? ~~arguments[0].top + this.scrollTop
: ~~arguments[1] + this.scrollTop
);
return;
}
this.scroll({
left: ~~arguments[0].left + this.scrollLeft,
top: ~~arguments[0].top + this.scrollTop,
behavior: arguments[0].behavior
});
};
// Element.prototype.scrollIntoView
Element.prototype.scrollIntoView = function() {
// avoid smooth behavior if not required
if (shouldBailOut(arguments[0]) === true) {
original.scrollIntoView.call(
this,
arguments[0] === undefined ? true : arguments[0]
);
return;
}
// LET THE SMOOTHNESS BEGIN!
var scrollableParent = findScrollableParent(this);
var parentRects = scrollableParent.getBoundingClientRect();
var clientRects = this.getBoundingClientRect();
if (scrollableParent !== d.body) {
// reveal element inside parent
smoothScroll.call(
this,
scrollableParent,
scrollableParent.scrollLeft + clientRects.left - parentRects.left,
scrollableParent.scrollTop + clientRects.top - parentRects.top
);
// reveal parent in viewport unless is fixed
if (w.getComputedStyle(scrollableParent).position !== 'fixed') {
w.scrollBy({
left: parentRects.left,
top: parentRects.top,
behavior: 'smooth'
});
}
} else {
// reveal element in viewport
w.scrollBy({
left: clientRects.left,
top: clientRects.top,
behavior: 'smooth'
});
}
};
}
if (typeof exports === 'object' && typeof module !== 'undefined') {
// commonjs
module.exports = { polyfill: polyfill };
} else {
// global
polyfill();
}
}());
================================================
FILE: src/renderer/lib/vue-horizontal.js
================================================
var VueHorizontal=function(t,e){"use strict";function n(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var i=n(e).default.extend({name:"VueHorizontal",data:function(){return{left:0,width:0,scrollWidth:0,hasPrev:!1,hasNext:!1,debounceId:void 0}},props:{button:{type:Boolean,default:function(){return!0}},buttonBetween:{type:Boolean,default:function(){return!0}},scroll:{type:Boolean,default:function(){return!1}},responsive:{type:Boolean,default:function(){return!1}},displacement:{type:Number,default:function(){return 1}},snap:{type:String,default:function(){return"start"}}},mounted:function(){this.onScrollDebounce()},beforeDestroy:function(){clearTimeout(this.debounceId)},methods:{children:function(){return this.$refs.container.children},findPrevSlot:function(t){for(var e=this.children(),n=0;n2.5)return void this.scrollToLeft(t.scrollLeft+o)}var l=t.clientWidth*this.displacement;this.scrollToLeft(t.scrollLeft+l)},scrollToIndex:function(t){var e=this.children();if(e[t]){var n=this.$refs.container,i=e[t].getBoundingClientRect().left-n.getBoundingClientRect().left;this.scrollToLeft(n.scrollLeft+i)}},scrollToLeft:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"smooth",n=this.$refs.container;n.scrollTo({left:t,behavior:e})},onScroll:function(){var t=this.$refs.container;t&&(this.$emit("scroll",{left:t.scrollLeft}),clearTimeout(this.debounceId),this.debounceId=setTimeout(this.onScrollDebounce,100))},onScrollDebounce:function(){var t=this;this.refresh((function(e){t.$emit("scroll-debounce",e)}))},refresh:function(t){var e=this;this.$nextTick((function(){var n=e.calculate();e.left=n.left,e.width=n.width,e.scrollWidth=n.scrollWidth,e.hasNext=n.hasNext,e.hasPrev=n.hasPrev,null==t||t(n)}))},calculate:function(){var t=this.$refs.container,e=this.children()[0];return{left:t.scrollLeft,width:t.clientWidth,scrollWidth:t.scrollWidth,hasNext:t.scrollWidth>t.scrollLeft+t.clientWidth+2.5,hasPrev:function(){var n,i;if(0===t.scrollLeft)return!1;var o=t.getBoundingClientRect().left,l=null!==(n=null==e||null===(i=e.getBoundingClientRect())||void 0===i?void 0:i.left)&&void 0!==n?n:0;return Math.abs(o-l)>=2.5}()}}}});function o(t,e,n,i,o,l,r,a,s,c){"boolean"!=typeof r&&(s=a,a=r,r=!1);const d="function"==typeof n?n.options:n;let h;if(t&&t.render&&(d.render=t.render,d.staticRenderFns=t.staticRenderFns,d._compiled=!0,o&&(d.functional=!0)),i&&(d._scopeId=i),l?(h=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),e&&e.call(this,s(t)),t&&t._registeredComponents&&t._registeredComponents.add(l)},d._ssrRegister=h):e&&(h=r?function(t){e.call(this,c(t,this.$root.$options.shadowRoot))}:function(t){e.call(this,a(t))}),h)if(d.functional){const t=d.render;d.render=function(e,n){return h.call(n),t(e,n)}}else{const t=d.beforeCreate;d.beforeCreate=t?[].concat(t,h):[h]}return n}const l="undefined"!=typeof navigator&&/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());function r(t){return(t,e)=>function(t,e){const n=l?e.media||"default":t,i=s[n]||(s[n]={ids:new Set,styles:[]});if(!i.ids.has(t)){i.ids.add(t);let n=e.source;if(e.map&&(n+="\n/*# sourceURL="+e.map.sources[0]+" */",n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(e.map))))+" */"),i.element||(i.element=document.createElement("style"),i.element.type="text/css",e.media&&i.element.setAttribute("media",e.media),void 0===a&&(a=document.head||document.getElementsByTagName("head")[0]),a.appendChild(i.element)),"styleSheet"in i.element)i.styles.push(n),i.element.styleSheet.cssText=i.styles.filter(Boolean).join("\n");else{const t=i.ids.size-1,e=document.createTextNode(n),o=i.element.childNodes;o[t]&&i.element.removeChild(o[t]),o.length?i.element.insertBefore(e,o[t]):i.element.appendChild(e)}}}(t,e)}let a;const s={};var c=o({render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"vue-horizontal",staticStyle:{position:"relative",display:"flex"}},[t.button&&t.hasPrev?n("div",{staticClass:"v-hl-btn v-hl-btn-prev",class:{"v-hl-btn-between":t.buttonBetween},attrs:{role:"button"},on:{click:function(e){return e.stopPropagation(),t.prev(e)}}},[t._t("btn-prev",[n("svg",{staticClass:"v-hl-svg",attrs:{viewBox:"0 0 24 24","aria-label":"horizontal scroll area navigate to previous button"}},[n("path",{attrs:{d:"m9.8 12 5 5a1 1 0 1 1-1.4 1.4l-5.7-5.7a1 1 0 0 1 0-1.4l5.7-5.7a1 1 0 0 1 1.4 1.4l-5 5z"}})])])],2):t._e(),t._v(" "),t.button&&t.hasNext?n("div",{staticClass:"v-hl-btn v-hl-btn-next",class:{"v-hl-btn-between":t.buttonBetween},attrs:{role:"button"},on:{click:function(e){return e.stopPropagation(),t.next(e)}}},[t._t("btn-next",[n("svg",{staticClass:"v-hl-svg",attrs:{viewBox:"0 0 24 24","aria-label":"horizontal scroll area navigate to next button"}},[n("path",{attrs:{d:"m14.3 12.1-5-5a1 1 0 0 1 1.4-1.4l5.7 5.7a1 1 0 0 1 0 1.4l-5.7 5.7a1 1 0 0 1-1.4-1.4l5-5z"}})])])],2):t._e(),t._v(" "),n("div",{ref:"container",staticClass:"v-hl-container",class:{"v-hl-responsive":t.responsive,"v-hl-scroll":t.scroll,"v-hl-snap-start":"start"===t.snap,"v-hl-snap-center":"center"===t.snap,"v-hl-snap-end":"end"===t.snap},on:{"&scroll":function(e){return t.onScroll(e)}}},[t._t("default")],2)])},staticRenderFns:[]},(function(t){t&&t("data-v-45080727_0",{source:".v-hl-btn[data-v-45080727]{position:absolute;align-self:center;z-index:1;top:0;bottom:0;display:flex;align-items:center;cursor:pointer}.v-hl-btn-prev[data-v-45080727]{left:0}.v-hl-btn-prev.v-hl-btn-between[data-v-45080727]{transform:translateX(-50%)}.v-hl-btn-next[data-v-45080727]{right:0}.v-hl-btn-next.v-hl-btn-between[data-v-45080727]{transform:translateX(50%)}.v-hl-svg[data-v-45080727]{width:40px;height:40px;margin:6px;padding:6px;border-radius:20px;box-sizing:border-box;background:#fff;color:#000;fill:currentColor;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)}.v-hl-container[data-v-45080727]{display:flex;width:100%;margin:0;padding:0;border:none;box-sizing:content-box;overflow-x:scroll;overflow-y:hidden;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch}.v-hl-container>*[data-v-45080727]{flex-shrink:0;box-sizing:border-box;min-height:1px}.v-hl-snap-start>*[data-v-45080727]{scroll-snap-align:start}.v-hl-snap-center>*[data-v-45080727]{scroll-snap-align:center}.v-hl-snap-end>*[data-v-45080727]{scroll-snap-align:end}.v-hl-container[data-v-45080727]:not(.v-hl-scroll){scrollbar-width:none;-ms-overflow-style:none;padding-bottom:30px;margin-bottom:-30px;clip-path:inset(0 0 30px 0)}.v-hl-container[data-v-45080727]:not(.v-hl-scroll)::-webkit-scrollbar{width:0!important;height:0!important}.v-hl-responsive>*[data-v-45080727]{width:100%;margin-right:24px}.v-hl-responsive[data-v-45080727]>:last-child{margin-right:0}@media (min-width:640px){.v-hl-responsive>*[data-v-45080727]{width:calc((100% - 24px)/ 2)}}@media (min-width:768px){.v-hl-responsive>*[data-v-45080727]{width:calc((100% - 48px)/ 3)}}@media (min-width:1024px){.v-hl-responsive>*[data-v-45080727]{width:calc((100% - 72px)/ 4)}}@media (min-width:1280px){.v-hl-responsive>*[data-v-45080727]{width:calc((100% - 96px)/ 5)}}",map:void 0,media:void 0})}),i,"data-v-45080727",!1,void 0,!1,r,void 0,void 0),d=function(t){d.installed||(d.installed=!0,t.component("VueHorizontal",c))},h={install:d},u=null;return"undefined"!=typeof window?u=window.Vue:"undefined"!=typeof global&&(u=global.Vue),u&&u.use(h),c.install=d,t.default=c,Object.defineProperty(t,"__esModule",{value:!0}),t}({},Vue);
================================================
FILE: src/renderer/lib/vue.dev.js
================================================
/*!
* Vue.js v2.6.14
* (c) 2014-2021 Evan You
* Released under the MIT License.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.Vue = factory());
}(this, function () { 'use strict';
/* */
var emptyObject = Object.freeze({});
// These helpers produce better VM code in JS engines due to their
// explicitness and function inlining.
function isUndef (v) {
return v === undefined || v === null
}
function isDef (v) {
return v !== undefined && v !== null
}
function isTrue (v) {
return v === true
}
function isFalse (v) {
return v === false
}
/**
* Check if value is primitive.
*/
function isPrimitive (value) {
return (
typeof value === 'string' ||
typeof value === 'number' ||
// $flow-disable-line
typeof value === 'symbol' ||
typeof value === 'boolean'
)
}
/**
* Quick object check - this is primarily used to tell
* Objects from primitive values when we know the value
* is a JSON-compliant type.
*/
function isObject (obj) {
return obj !== null && typeof obj === 'object'
}
/**
* Get the raw type string of a value, e.g., [object Object].
*/
var _toString = Object.prototype.toString;
function toRawType (value) {
return _toString.call(value).slice(8, -1)
}
/**
* Strict object type check. Only returns true
* for plain JavaScript objects.
*/
function isPlainObject (obj) {
return _toString.call(obj) === '[object Object]'
}
function isRegExp (v) {
return _toString.call(v) === '[object RegExp]'
}
/**
* Check if val is a valid array index.
*/
function isValidArrayIndex (val) {
var n = parseFloat(String(val));
return n >= 0 && Math.floor(n) === n && isFinite(val)
}
function isPromise (val) {
return (
isDef(val) &&
typeof val.then === 'function' &&
typeof val.catch === 'function'
)
}
/**
* Convert a value to a string that is actually rendered.
*/
function toString (val) {
return val == null
? ''
: Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
? JSON.stringify(val, null, 2)
: String(val)
}
/**
* Convert an input value to a number for persistence.
* If the conversion fails, return original string.
*/
function toNumber (val) {
var n = parseFloat(val);
return isNaN(n) ? val : n
}
/**
* Make a map and return a function for checking if a key
* is in that map.
*/
function makeMap (
str,
expectsLowerCase
) {
var map = Object.create(null);
var list = str.split(',');
for (var i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return expectsLowerCase
? function (val) { return map[val.toLowerCase()]; }
: function (val) { return map[val]; }
}
/**
* Check if a tag is a built-in tag.
*/
var isBuiltInTag = makeMap('slot,component', true);
/**
* Check if an attribute is a reserved attribute.
*/
var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is');
/**
* Remove an item from an array.
*/
function remove (arr, item) {
if (arr.length) {
var index = arr.indexOf(item);
if (index > -1) {
return arr.splice(index, 1)
}
}
}
/**
* Check whether an object has the property.
*/
var hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn (obj, key) {
return hasOwnProperty.call(obj, key)
}
/**
* Create a cached version of a pure function.
*/
function cached (fn) {
var cache = Object.create(null);
return (function cachedFn (str) {
var hit = cache[str];
return hit || (cache[str] = fn(str))
})
}
/**
* Camelize a hyphen-delimited string.
*/
var camelizeRE = /-(\w)/g;
var camelize = cached(function (str) {
return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })
});
/**
* Capitalize a string.
*/
var capitalize = cached(function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
});
/**
* Hyphenate a camelCase string.
*/
var hyphenateRE = /\B([A-Z])/g;
var hyphenate = cached(function (str) {
return str.replace(hyphenateRE, '-$1').toLowerCase()
});
/**
* Simple bind polyfill for environments that do not support it,
* e.g., PhantomJS 1.x. Technically, we don't need this anymore
* since native bind is now performant enough in most browsers.
* But removing it would mean breaking code that was able to run in
* PhantomJS 1.x, so this must be kept for backward compatibility.
*/
/* istanbul ignore next */
function polyfillBind (fn, ctx) {
function boundFn (a) {
var l = arguments.length;
return l
? l > 1
? fn.apply(ctx, arguments)
: fn.call(ctx, a)
: fn.call(ctx)
}
boundFn._length = fn.length;
return boundFn
}
function nativeBind (fn, ctx) {
return fn.bind(ctx)
}
var bind = Function.prototype.bind
? nativeBind
: polyfillBind;
/**
* Convert an Array-like object to a real Array.
*/
function toArray (list, start) {
start = start || 0;
var i = list.length - start;
var ret = new Array(i);
while (i--) {
ret[i] = list[i + start];
}
return ret
}
/**
* Mix properties into target object.
*/
function extend (to, _from) {
for (var key in _from) {
to[key] = _from[key];
}
return to
}
/**
* Merge an Array of Objects into a single Object.
*/
function toObject (arr) {
var res = {};
for (var i = 0; i < arr.length; i++) {
if (arr[i]) {
extend(res, arr[i]);
}
}
return res
}
/* eslint-disable no-unused-vars */
/**
* Perform no operation.
* Stubbing args to make Flow happy without leaving useless transpiled code
* with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/).
*/
function noop (a, b, c) {}
/**
* Always return false.
*/
var no = function (a, b, c) { return false; };
/* eslint-enable no-unused-vars */
/**
* Return the same value.
*/
var identity = function (_) { return _; };
/**
* Generate a string containing static keys from compiler modules.
*/
function genStaticKeys (modules) {
return modules.reduce(function (keys, m) {
return keys.concat(m.staticKeys || [])
}, []).join(',')
}
/**
* Check if two values are loosely equal - that is,
* if they are plain objects, do they have the same shape?
*/
function looseEqual (a, b) {
if (a === b) { return true }
var isObjectA = isObject(a);
var isObjectB = isObject(b);
if (isObjectA && isObjectB) {
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
if (isArrayA && isArrayB) {
return a.length === b.length && a.every(function (e, i) {
return looseEqual(e, b[i])
})
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime()
} else if (!isArrayA && !isArrayB) {
var keysA = Object.keys(a);
var keysB = Object.keys(b);
return keysA.length === keysB.length && keysA.every(function (key) {
return looseEqual(a[key], b[key])
})
} else {
/* istanbul ignore next */
return false
}
} catch (e) {
/* istanbul ignore next */
return false
}
} else if (!isObjectA && !isObjectB) {
return String(a) === String(b)
} else {
return false
}
}
/**
* Return the first index at which a loosely equal value can be
* found in the array (if value is a plain object, the array must
* contain an object of the same shape), or -1 if it is not present.
*/
function looseIndexOf (arr, val) {
for (var i = 0; i < arr.length; i++) {
if (looseEqual(arr[i], val)) { return i }
}
return -1
}
/**
* Ensure a function is called only once.
*/
function once (fn) {
var called = false;
return function () {
if (!called) {
called = true;
fn.apply(this, arguments);
}
}
}
var SSR_ATTR = 'data-server-rendered';
var ASSET_TYPES = [
'component',
'directive',
'filter'
];
var LIFECYCLE_HOOKS = [
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'beforeDestroy',
'destroyed',
'activated',
'deactivated',
'errorCaptured',
'serverPrefetch'
];
/* */
var config = ({
/**
* Option merge strategies (used in core/util/options)
*/
// $flow-disable-line
optionMergeStrategies: Object.create(null),
/**
* Whether to suppress warnings.
*/
silent: false,
/**
* Show production mode tip message on boot?
*/
productionTip: "development" !== 'production',
/**
* Whether to enable devtools
*/
devtools: "development" !== 'production',
/**
* Whether to record perf
*/
performance: false,
/**
* Error handler for watcher errors
*/
errorHandler: null,
/**
* Warn handler for watcher warns
*/
warnHandler: null,
/**
* Ignore certain custom elements
*/
ignoredElements: [],
/**
* Custom user key aliases for v-on
*/
// $flow-disable-line
keyCodes: Object.create(null),
/**
* Check if a tag is reserved so that it cannot be registered as a
* component. This is platform-dependent and may be overwritten.
*/
isReservedTag: no,
/**
* Check if an attribute is reserved so that it cannot be used as a component
* prop. This is platform-dependent and may be overwritten.
*/
isReservedAttr: no,
/**
* Check if a tag is an unknown element.
* Platform-dependent.
*/
isUnknownElement: no,
/**
* Get the namespace of an element
*/
getTagNamespace: noop,
/**
* Parse the real tag name for the specific platform.
*/
parsePlatformTagName: identity,
/**
* Check if an attribute must be bound using property, e.g. value
* Platform-dependent.
*/
mustUseProp: no,
/**
* Perform updates asynchronously. Intended to be used by Vue Test Utils
* This will significantly reduce performance if set to false.
*/
async: true,
/**
* Exposed for legacy reasons
*/
_lifecycleHooks: LIFECYCLE_HOOKS
});
/* */
/**
* unicode letters used for parsing html tags, component names and property paths.
* using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname
* skipping \u10000-\uEFFFF due to it freezing up PhantomJS
*/
var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;
/**
* Check if a string starts with $ or _
*/
function isReserved (str) {
var c = (str + '').charCodeAt(0);
return c === 0x24 || c === 0x5F
}
/**
* Define a property.
*/
function def (obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
});
}
/**
* Parse simple path.
*/
var bailRE = new RegExp(("[^" + (unicodeRegExp.source) + ".$_\\d]"));
function parsePath (path) {
if (bailRE.test(path)) {
return
}
var segments = path.split('.');
return function (obj) {
for (var i = 0; i < segments.length; i++) {
if (!obj) { return }
obj = obj[segments[i]];
}
return obj
}
}
/* */
// can we use __proto__?
var hasProto = '__proto__' in {};
// Browser environment sniffing
var inBrowser = typeof window !== 'undefined';
var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
var UA = inBrowser && window.navigator.userAgent.toLowerCase();
var isIE = UA && /msie|trident/.test(UA);
var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
var isEdge = UA && UA.indexOf('edge/') > 0;
var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
var isPhantomJS = UA && /phantomjs/.test(UA);
var isFF = UA && UA.match(/firefox\/(\d+)/);
// Firefox has a "watch" function on Object.prototype...
var nativeWatch = ({}).watch;
var supportsPassive = false;
if (inBrowser) {
try {
var opts = {};
Object.defineProperty(opts, 'passive', ({
get: function get () {
/* istanbul ignore next */
supportsPassive = true;
}
})); // https://github.com/facebook/flow/issues/285
window.addEventListener('test-passive', null, opts);
} catch (e) {}
}
// this needs to be lazy-evaled because vue may be required before
// vue-server-renderer can set VUE_ENV
var _isServer;
var isServerRendering = function () {
if (_isServer === undefined) {
/* istanbul ignore if */
if (!inBrowser && !inWeex && typeof global !== 'undefined') {
// detect presence of vue-server-renderer and avoid
// Webpack shimming the process
_isServer = global['process'] && global['process'].env.VUE_ENV === 'server';
} else {
_isServer = false;
}
}
return _isServer
};
// detect devtools
var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
/* istanbul ignore next */
function isNative (Ctor) {
return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
var hasSymbol =
typeof Symbol !== 'undefined' && isNative(Symbol) &&
typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);
var _Set;
/* istanbul ignore if */ // $flow-disable-line
if (typeof Set !== 'undefined' && isNative(Set)) {
// use native Set when available.
_Set = Set;
} else {
// a non-standard Set polyfill that only works with primitive keys.
_Set = /*@__PURE__*/(function () {
function Set () {
this.set = Object.create(null);
}
Set.prototype.has = function has (key) {
return this.set[key] === true
};
Set.prototype.add = function add (key) {
this.set[key] = true;
};
Set.prototype.clear = function clear () {
this.set = Object.create(null);
};
return Set;
}());
}
/* */
var warn = noop;
var tip = noop;
var generateComponentTrace = (noop); // work around flow check
var formatComponentName = (noop);
{
var hasConsole = typeof console !== 'undefined';
var classifyRE = /(?:^|[-_])(\w)/g;
var classify = function (str) { return str
.replace(classifyRE, function (c) { return c.toUpperCase(); })
.replace(/[-_]/g, ''); };
warn = function (msg, vm) {
var trace = vm ? generateComponentTrace(vm) : '';
if (config.warnHandler) {
config.warnHandler.call(null, msg, vm, trace);
} else if (hasConsole && (!config.silent)) {
console.error(("[Vue warn]: " + msg + trace));
}
};
tip = function (msg, vm) {
if (hasConsole && (!config.silent)) {
console.warn("[Vue tip]: " + msg + (
vm ? generateComponentTrace(vm) : ''
));
}
};
formatComponentName = function (vm, includeFile) {
if (vm.$root === vm) {
return ''
}
var options = typeof vm === 'function' && vm.cid != null
? vm.options
: vm._isVue
? vm.$options || vm.constructor.options
: vm;
var name = options.name || options._componentTag;
var file = options.__file;
if (!name && file) {
var match = file.match(/([^/\\]+)\.vue$/);
name = match && match[1];
}
return (
(name ? ("<" + (classify(name)) + ">") : "") +
(file && includeFile !== false ? (" at " + file) : '')
)
};
var repeat = function (str, n) {
var res = '';
while (n) {
if (n % 2 === 1) { res += str; }
if (n > 1) { str += str; }
n >>= 1;
}
return res
};
generateComponentTrace = function (vm) {
if (vm._isVue && vm.$parent) {
var tree = [];
var currentRecursiveSequence = 0;
while (vm) {
if (tree.length > 0) {
var last = tree[tree.length - 1];
if (last.constructor === vm.constructor) {
currentRecursiveSequence++;
vm = vm.$parent;
continue
} else if (currentRecursiveSequence > 0) {
tree[tree.length - 1] = [last, currentRecursiveSequence];
currentRecursiveSequence = 0;
}
}
tree.push(vm);
vm = vm.$parent;
}
return '\n\nfound in\n\n' + tree
.map(function (vm, i) { return ("" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm)
? ((formatComponentName(vm[0])) + "... (" + (vm[1]) + " recursive calls)")
: formatComponentName(vm))); })
.join('\n')
} else {
return ("\n\n(found in " + (formatComponentName(vm)) + ")")
}
};
}
/* */
var uid = 0;
/**
* A dep is an observable that can have multiple
* directives subscribing to it.
*/
var Dep = function Dep () {
this.id = uid++;
this.subs = [];
};
Dep.prototype.addSub = function addSub (sub) {
this.subs.push(sub);
};
Dep.prototype.removeSub = function removeSub (sub) {
remove(this.subs, sub);
};
Dep.prototype.depend = function depend () {
if (Dep.target) {
Dep.target.addDep(this);
}
};
Dep.prototype.notify = function notify () {
// stabilize the subscriber list first
var subs = this.subs.slice();
if (!config.async) {
// subs aren't sorted in scheduler if not running async
// we need to sort them now to make sure they fire in correct
// order
subs.sort(function (a, b) { return a.id - b.id; });
}
for (var i = 0, l = subs.length; i < l; i++) {
subs[i].update();
}
};
// The current target watcher being evaluated.
// This is globally unique because only one watcher
// can be evaluated at a time.
Dep.target = null;
var targetStack = [];
function pushTarget (target) {
targetStack.push(target);
Dep.target = target;
}
function popTarget () {
targetStack.pop();
Dep.target = targetStack[targetStack.length - 1];
}
/* */
var VNode = function VNode (
tag,
data,
children,
text,
elm,
context,
componentOptions,
asyncFactory
) {
this.tag = tag;
this.data = data;
this.children = children;
this.text = text;
this.elm = elm;
this.ns = undefined;
this.context = context;
this.fnContext = undefined;
this.fnOptions = undefined;
this.fnScopeId = undefined;
this.key = data && data.key;
this.componentOptions = componentOptions;
this.componentInstance = undefined;
this.parent = undefined;
this.raw = false;
this.isStatic = false;
this.isRootInsert = true;
this.isComment = false;
this.isCloned = false;
this.isOnce = false;
this.asyncFactory = asyncFactory;
this.asyncMeta = undefined;
this.isAsyncPlaceholder = false;
};
var prototypeAccessors = { child: { configurable: true } };
// DEPRECATED: alias for componentInstance for backwards compat.
/* istanbul ignore next */
prototypeAccessors.child.get = function () {
return this.componentInstance
};
Object.defineProperties( VNode.prototype, prototypeAccessors );
var createEmptyVNode = function (text) {
if ( text === void 0 ) text = '';
var node = new VNode();
node.text = text;
node.isComment = true;
return node
};
function createTextVNode (val) {
return new VNode(undefined, undefined, undefined, String(val))
}
// optimized shallow clone
// used for static nodes and slot nodes because they may be reused across
// multiple renders, cloning them avoids errors when DOM manipulations rely
// on their elm reference.
function cloneVNode (vnode) {
var cloned = new VNode(
vnode.tag,
vnode.data,
// #7975
// clone children array to avoid mutating original in case of cloning
// a child.
vnode.children && vnode.children.slice(),
vnode.text,
vnode.elm,
vnode.context,
vnode.componentOptions,
vnode.asyncFactory
);
cloned.ns = vnode.ns;
cloned.isStatic = vnode.isStatic;
cloned.key = vnode.key;
cloned.isComment = vnode.isComment;
cloned.fnContext = vnode.fnContext;
cloned.fnOptions = vnode.fnOptions;
cloned.fnScopeId = vnode.fnScopeId;
cloned.asyncMeta = vnode.asyncMeta;
cloned.isCloned = true;
return cloned
}
/*
* not type checking this file because flow doesn't play well with
* dynamically accessing methods on Array prototype
*/
var arrayProto = Array.prototype;
var arrayMethods = Object.create(arrayProto);
var methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
];
/**
* Intercept mutating methods and emit events
*/
methodsToPatch.forEach(function (method) {
// cache original method
var original = arrayProto[method];
def(arrayMethods, method, function mutator () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
var result = original.apply(this, args);
var ob = this.__ob__;
var inserted;
switch (method) {
case 'push':
case 'unshift':
inserted = args;
break
case 'splice':
inserted = args.slice(2);
break
}
if (inserted) { ob.observeArray(inserted); }
// notify change
ob.dep.notify();
return result
});
});
/* */
var arrayKeys = Object.getOwnPropertyNames(arrayMethods);
/**
* In some cases we may want to disable observation inside a component's
* update computation.
*/
var shouldObserve = true;
function toggleObserving (value) {
shouldObserve = value;
}
/**
* Observer class that is attached to each observed
* object. Once attached, the observer converts the target
* object's property keys into getter/setters that
* collect dependencies and dispatch updates.
*/
var Observer = function Observer (value) {
this.value = value;
this.dep = new Dep();
this.vmCount = 0;
def(value, '__ob__', this);
if (Array.isArray(value)) {
if (hasProto) {
protoAugment(value, arrayMethods);
} else {
copyAugment(value, arrayMethods, arrayKeys);
}
this.observeArray(value);
} else {
this.walk(value);
}
};
/**
* Walk through all properties and convert them into
* getter/setters. This method should only be called when
* value type is Object.
*/
Observer.prototype.walk = function walk (obj) {
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
defineReactive$$1(obj, keys[i]);
}
};
/**
* Observe a list of Array items.
*/
Observer.prototype.observeArray = function observeArray (items) {
for (var i = 0, l = items.length; i < l; i++) {
observe(items[i]);
}
};
// helpers
/**
* Augment a target Object or Array by intercepting
* the prototype chain using __proto__
*/
function protoAugment (target, src) {
/* eslint-disable no-proto */
target.__proto__ = src;
/* eslint-enable no-proto */
}
/**
* Augment a target Object or Array by defining
* hidden properties.
*/
/* istanbul ignore next */
function copyAugment (target, src, keys) {
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
def(target, key, src[key]);
}
}
/**
* Attempt to create an observer instance for a value,
* returns the new observer if successfully observed,
* or the existing observer if the value already has one.
*/
function observe (value, asRootData) {
if (!isObject(value) || value instanceof VNode) {
return
}
var ob;
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__;
} else if (
shouldObserve &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
ob = new Observer(value);
}
if (asRootData && ob) {
ob.vmCount++;
}
return ob
}
/**
* Define a reactive property on an Object.
*/
function defineReactive$$1 (
obj,
key,
val,
customSetter,
shallow
) {
var dep = new Dep();
var property = Object.getOwnPropertyDescriptor(obj, key);
if (property && property.configurable === false) {
return
}
// cater for pre-defined getter/setters
var getter = property && property.get;
var setter = property && property.set;
if ((!getter || setter) && arguments.length === 2) {
val = obj[key];
}
var childOb = !shallow && observe(val);
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
var value = getter ? getter.call(obj) : val;
if (Dep.target) {
dep.depend();
if (childOb) {
childOb.dep.depend();
if (Array.isArray(value)) {
dependArray(value);
}
}
}
return value
},
set: function reactiveSetter (newVal) {
var value = getter ? getter.call(obj) : val;
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (customSetter) {
customSetter();
}
// #7981: for accessor properties without setter
if (getter && !setter) { return }
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
childOb = !shallow && observe(newVal);
dep.notify();
}
});
}
/**
* Set a property on an object. Adds the new property and
* triggers change notification if the property doesn't
* already exist.
*/
function set (target, key, val) {
if (isUndef(target) || isPrimitive(target)
) {
warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target))));
}
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val
}
if (key in target && !(key in Object.prototype)) {
target[key] = val;
return val
}
var ob = (target).__ob__;
if (target._isVue || (ob && ob.vmCount)) {
warn(
'Avoid adding reactive properties to a Vue instance or its root $data ' +
'at runtime - declare it upfront in the data option.'
);
return val
}
if (!ob) {
target[key] = val;
return val
}
defineReactive$$1(ob.value, key, val);
ob.dep.notify();
return val
}
/**
* Delete a property and trigger change if necessary.
*/
function del (target, key) {
if (isUndef(target) || isPrimitive(target)
) {
warn(("Cannot delete reactive property on undefined, null, or primitive value: " + ((target))));
}
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.splice(key, 1);
return
}
var ob = (target).__ob__;
if (target._isVue || (ob && ob.vmCount)) {
warn(
'Avoid deleting properties on a Vue instance or its root $data ' +
'- just set it to null.'
);
return
}
if (!hasOwn(target, key)) {
return
}
delete target[key];
if (!ob) {
return
}
ob.dep.notify();
}
/**
* Collect dependencies on array elements when the array is touched, since
* we cannot intercept array element access like property getters.
*/
function dependArray (value) {
for (var e = (void 0), i = 0, l = value.length; i < l; i++) {
e = value[i];
e && e.__ob__ && e.__ob__.dep.depend();
if (Array.isArray(e)) {
dependArray(e);
}
}
}
/* */
/**
* Option overwriting strategies are functions that handle
* how to merge a parent option value and a child option
* value into the final value.
*/
var strats = config.optionMergeStrategies;
/**
* Options with restrictions
*/
{
strats.el = strats.propsData = function (parent, child, vm, key) {
if (!vm) {
warn(
"option \"" + key + "\" can only be used during instance " +
'creation with the `new` keyword.'
);
}
return defaultStrat(parent, child)
};
}
/**
* Helper that recursively merges two data objects together.
*/
function mergeData (to, from) {
if (!from) { return to }
var key, toVal, fromVal;
var keys = hasSymbol
? Reflect.ownKeys(from)
: Object.keys(from);
for (var i = 0; i < keys.length; i++) {
key = keys[i];
// in case the object is already observed...
if (key === '__ob__') { continue }
toVal = to[key];
fromVal = from[key];
if (!hasOwn(to, key)) {
set(to, key, fromVal);
} else if (
toVal !== fromVal &&
isPlainObject(toVal) &&
isPlainObject(fromVal)
) {
mergeData(toVal, fromVal);
}
}
return to
}
/**
* Data
*/
function mergeDataOrFn (
parentVal,
childVal,
vm
) {
if (!vm) {
// in a Vue.extend merge, both should be functions
if (!childVal) {
return parentVal
}
if (!parentVal) {
return childVal
}
// when parentVal & childVal are both present,
// we need to return a function that returns the
// merged result of both functions... no need to
// check if parentVal is a function here because
// it has to be a function to pass previous merges.
return function mergedDataFn () {
return mergeData(
typeof childVal === 'function' ? childVal.call(this, this) : childVal,
typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal
)
}
} else {
return function mergedInstanceDataFn () {
// instance merge
var instanceData = typeof childVal === 'function'
? childVal.call(vm, vm)
: childVal;
var defaultData = typeof parentVal === 'function'
? parentVal.call(vm, vm)
: parentVal;
if (instanceData) {
return mergeData(instanceData, defaultData)
} else {
return defaultData
}
}
}
}
strats.data = function (
parentVal,
childVal,
vm
) {
if (!vm) {
if (childVal && typeof childVal !== 'function') {
warn(
'The "data" option should be a function ' +
'that returns a per-instance value in component ' +
'definitions.',
vm
);
return parentVal
}
return mergeDataOrFn(parentVal, childVal)
}
return mergeDataOrFn(parentVal, childVal, vm)
};
/**
* Hooks and props are merged as arrays.
*/
function mergeHook (
parentVal,
childVal
) {
var res = childVal
? parentVal
? parentVal.concat(childVal)
: Array.isArray(childVal)
? childVal
: [childVal]
: parentVal;
return res
? dedupeHooks(res)
: res
}
function dedupeHooks (hooks) {
var res = [];
for (var i = 0; i < hooks.length; i++) {
if (res.indexOf(hooks[i]) === -1) {
res.push(hooks[i]);
}
}
return res
}
LIFECYCLE_HOOKS.forEach(function (hook) {
strats[hook] = mergeHook;
});
/**
* Assets
*
* When a vm is present (instance creation), we need to do
* a three-way merge between constructor options, instance
* options and parent options.
*/
function mergeAssets (
parentVal,
childVal,
vm,
key
) {
var res = Object.create(parentVal || null);
if (childVal) {
assertObjectType(key, childVal, vm);
return extend(res, childVal)
} else {
return res
}
}
ASSET_TYPES.forEach(function (type) {
strats[type + 's'] = mergeAssets;
});
/**
* Watchers.
*
* Watchers hashes should not overwrite one
* another, so we merge them as arrays.
*/
strats.watch = function (
parentVal,
childVal,
vm,
key
) {
// work around Firefox's Object.prototype.watch...
if (parentVal === nativeWatch) { parentVal = undefined; }
if (childVal === nativeWatch) { childVal = undefined; }
/* istanbul ignore if */
if (!childVal) { return Object.create(parentVal || null) }
{
assertObjectType(key, childVal, vm);
}
if (!parentVal) { return childVal }
var ret = {};
extend(ret, parentVal);
for (var key$1 in childVal) {
var parent = ret[key$1];
var child = childVal[key$1];
if (parent && !Array.isArray(parent)) {
parent = [parent];
}
ret[key$1] = parent
? parent.concat(child)
: Array.isArray(child) ? child : [child];
}
return ret
};
/**
* Other object hashes.
*/
strats.props =
strats.methods =
strats.inject =
strats.computed = function (
parentVal,
childVal,
vm,
key
) {
if (childVal && "development" !== 'production') {
assertObjectType(key, childVal, vm);
}
if (!parentVal) { return childVal }
var ret = Object.create(null);
extend(ret, parentVal);
if (childVal) { extend(ret, childVal); }
return ret
};
strats.provide = mergeDataOrFn;
/**
* Default strategy.
*/
var defaultStrat = function (parentVal, childVal) {
return childVal === undefined
? parentVal
: childVal
};
/**
* Validate component names
*/
function checkComponents (options) {
for (var key in options.components) {
validateComponentName(key);
}
}
function validateComponentName (name) {
if (!new RegExp(("^[a-zA-Z][\\-\\.0-9_" + (unicodeRegExp.source) + "]*$")).test(name)) {
warn(
'Invalid component name: "' + name + '". Component names ' +
'should conform to valid custom element name in html5 specification.'
);
}
if (isBuiltInTag(name) || config.isReservedTag(name)) {
warn(
'Do not use built-in or reserved HTML elements as component ' +
'id: ' + name
);
}
}
/**
* Ensure all props option syntax are normalized into the
* Object-based format.
*/
function normalizeProps (options, vm) {
var props = options.props;
if (!props) { return }
var res = {};
var i, val, name;
if (Array.isArray(props)) {
i = props.length;
while (i--) {
val = props[i];
if (typeof val === 'string') {
name = camelize(val);
res[name] = { type: null };
} else {
warn('props must be strings when using array syntax.');
}
}
} else if (isPlainObject(props)) {
for (var key in props) {
val = props[key];
name = camelize(key);
res[name] = isPlainObject(val)
? val
: { type: val };
}
} else {
warn(
"Invalid value for option \"props\": expected an Array or an Object, " +
"but got " + (toRawType(props)) + ".",
vm
);
}
options.props = res;
}
/**
* Normalize all injections into Object-based format
*/
function normalizeInject (options, vm) {
var inject = options.inject;
if (!inject) { return }
var normalized = options.inject = {};
if (Array.isArray(inject)) {
for (var i = 0; i < inject.length; i++) {
normalized[inject[i]] = { from: inject[i] };
}
} else if (isPlainObject(inject)) {
for (var key in inject) {
var val = inject[key];
normalized[key] = isPlainObject(val)
? extend({ from: key }, val)
: { from: val };
}
} else {
warn(
"Invalid value for option \"inject\": expected an Array or an Object, " +
"but got " + (toRawType(inject)) + ".",
vm
);
}
}
/**
* Normalize raw function directives into object format.
*/
function normalizeDirectives (options) {
var dirs = options.directives;
if (dirs) {
for (var key in dirs) {
var def$$1 = dirs[key];
if (typeof def$$1 === 'function') {
dirs[key] = { bind: def$$1, update: def$$1 };
}
}
}
}
function assertObjectType (name, value, vm) {
if (!isPlainObject(value)) {
warn(
"Invalid value for option \"" + name + "\": expected an Object, " +
"but got " + (toRawType(value)) + ".",
vm
);
}
}
/**
* Merge two option objects into a new one.
* Core utility used in both instantiation and inheritance.
*/
function mergeOptions (
parent,
child,
vm
) {
{
checkComponents(child);
}
if (typeof child === 'function') {
child = child.options;
}
normalizeProps(child, vm);
normalizeInject(child, vm);
normalizeDirectives(child);
// Apply extends and mixins on the child options,
// but only if it is a raw options object that isn't
// the result of another mergeOptions call.
// Only merged options has the _base property.
if (!child._base) {
if (child.extends) {
parent = mergeOptions(parent, child.extends, vm);
}
if (child.mixins) {
for (var i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm);
}
}
}
var options = {};
var key;
for (key in parent) {
mergeField(key);
}
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key);
}
}
function mergeField (key) {
var strat = strats[key] || defaultStrat;
options[key] = strat(parent[key], child[key], vm, key);
}
return options
}
/**
* Resolve an asset.
* This function is used because child instances need access
* to assets defined in its ancestor chain.
*/
function resolveAsset (
options,
type,
id,
warnMissing
) {
/* istanbul ignore if */
if (typeof id !== 'string') {
return
}
var assets = options[type];
// check local registration variations first
if (hasOwn(assets, id)) { return assets[id] }
var camelizedId = camelize(id);
if (hasOwn(assets, camelizedId)) { return assets[camelizedId] }
var PascalCaseId = capitalize(camelizedId);
if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] }
// fallback to prototype chain
var res = assets[id] || assets[camelizedId] || assets[PascalCaseId];
if (warnMissing && !res) {
warn(
'Failed to resolve ' + type.slice(0, -1) + ': ' + id,
options
);
}
return res
}
/* */
function validateProp (
key,
propOptions,
propsData,
vm
) {
var prop = propOptions[key];
var absent = !hasOwn(propsData, key);
var value = propsData[key];
// boolean casting
var booleanIndex = getTypeIndex(Boolean, prop.type);
if (booleanIndex > -1) {
if (absent && !hasOwn(prop, 'default')) {
value = false;
} else if (value === '' || value === hyphenate(key)) {
// only cast empty string / same name to boolean if
// boolean has higher priority
var stringIndex = getTypeIndex(String, prop.type);
if (stringIndex < 0 || booleanIndex < stringIndex) {
value = true;
}
}
}
// check default value
if (value === undefined) {
value = getPropDefaultValue(vm, prop, key);
// since the default value is a fresh copy,
// make sure to observe it.
var prevShouldObserve = shouldObserve;
toggleObserving(true);
observe(value);
toggleObserving(prevShouldObserve);
}
{
assertProp(prop, key, value, vm, absent);
}
return value
}
/**
* Get the default value of a prop.
*/
function getPropDefaultValue (vm, prop, key) {
// no default, return undefined
if (!hasOwn(prop, 'default')) {
return undefined
}
var def = prop.default;
// warn against non-factory defaults for Object & Array
if (isObject(def)) {
warn(
'Invalid default value for prop "' + key + '": ' +
'Props with type Object/Array must use a factory function ' +
'to return the default value.',
vm
);
}
// the raw prop value was also undefined from previous render,
// return previous default value to avoid unnecessary watcher trigger
if (vm && vm.$options.propsData &&
vm.$options.propsData[key] === undefined &&
vm._props[key] !== undefined
) {
return vm._props[key]
}
// call factory function for non-Function types
// a value is Function if its prototype is function even across different execution context
return typeof def === 'function' && getType(prop.type) !== 'Function'
? def.call(vm)
: def
}
/**
* Assert whether a prop is valid.
*/
function assertProp (
prop,
name,
value,
vm,
absent
) {
if (prop.required && absent) {
warn(
'Missing required prop: "' + name + '"',
vm
);
return
}
if (value == null && !prop.required) {
return
}
var type = prop.type;
var valid = !type || type === true;
var expectedTypes = [];
if (type) {
if (!Array.isArray(type)) {
type = [type];
}
for (var i = 0; i < type.length && !valid; i++) {
var assertedType = assertType(value, type[i], vm);
expectedTypes.push(assertedType.expectedType || '');
valid = assertedType.valid;
}
}
var haveExpectedTypes = expectedTypes.some(function (t) { return t; });
if (!valid && haveExpectedTypes) {
warn(
getInvalidTypeMessage(name, value, expectedTypes),
vm
);
return
}
var validator = prop.validator;
if (validator) {
if (!validator(value)) {
warn(
'Invalid prop: custom validator check failed for prop "' + name + '".',
vm
);
}
}
}
var simpleCheckRE = /^(String|Number|Boolean|Function|Symbol|BigInt)$/;
function assertType (value, type, vm) {
var valid;
var expectedType = getType(type);
if (simpleCheckRE.test(expectedType)) {
var t = typeof value;
valid = t === expectedType.toLowerCase();
// for primitive wrapper objects
if (!valid && t === 'object') {
valid = value instanceof type;
}
} else if (expectedType === 'Object') {
valid = isPlainObject(value);
} else if (expectedType === 'Array') {
valid = Array.isArray(value);
} else {
try {
valid = value instanceof type;
} catch (e) {
warn('Invalid prop type: "' + String(type) + '" is not a constructor', vm);
valid = false;
}
}
return {
valid: valid,
expectedType: expectedType
}
}
var functionTypeCheckRE = /^\s*function (\w+)/;
/**
* Use function string name to check built-in types,
* because a simple equality check will fail when running
* across different vms / iframes.
*/
function getType (fn) {
var match = fn && fn.toString().match(functionTypeCheckRE);
return match ? match[1] : ''
}
function isSameType (a, b) {
return getType(a) === getType(b)
}
function getTypeIndex (type, expectedTypes) {
if (!Array.isArray(expectedTypes)) {
return isSameType(expectedTypes, type) ? 0 : -1
}
for (var i = 0, len = expectedTypes.length; i < len; i++) {
if (isSameType(expectedTypes[i], type)) {
return i
}
}
return -1
}
function getInvalidTypeMessage (name, value, expectedTypes) {
var message = "Invalid prop: type check failed for prop \"" + name + "\"." +
" Expected " + (expectedTypes.map(capitalize).join(', '));
var expectedType = expectedTypes[0];
var receivedType = toRawType(value);
// check if we need to specify expected value
if (
expectedTypes.length === 1 &&
isExplicable(expectedType) &&
isExplicable(typeof value) &&
!isBoolean(expectedType, receivedType)
) {
message += " with value " + (styleValue(value, expectedType));
}
message += ", got " + receivedType + " ";
// check if we need to specify received value
if (isExplicable(receivedType)) {
message += "with value " + (styleValue(value, receivedType)) + ".";
}
return message
}
function styleValue (value, type) {
if (type === 'String') {
return ("\"" + value + "\"")
} else if (type === 'Number') {
return ("" + (Number(value)))
} else {
return ("" + value)
}
}
var EXPLICABLE_TYPES = ['string', 'number', 'boolean'];
function isExplicable (value) {
return EXPLICABLE_TYPES.some(function (elem) { return value.toLowerCase() === elem; })
}
function isBoolean () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return args.some(function (elem) { return elem.toLowerCase() === 'boolean'; })
}
/* */
function handleError (err, vm, info) {
// Deactivate deps tracking while processing error handler to avoid possible infinite rendering.
// See: https://github.com/vuejs/vuex/issues/1505
pushTarget();
try {
if (vm) {
var cur = vm;
while ((cur = cur.$parent)) {
var hooks = cur.$options.errorCaptured;
if (hooks) {
for (var i = 0; i < hooks.length; i++) {
try {
var capture = hooks[i].call(cur, err, vm, info) === false;
if (capture) { return }
} catch (e) {
globalHandleError(e, cur, 'errorCaptured hook');
}
}
}
}
}
globalHandleError(err, vm, info);
} finally {
popTarget();
}
}
function invokeWithErrorHandling (
handler,
context,
args,
vm,
info
) {
var res;
try {
res = args ? handler.apply(context, args) : handler.call(context);
if (res && !res._isVue && isPromise(res) && !res._handled) {
res.catch(function (e) { return handleError(e, vm, info + " (Promise/async)"); });
// issue #9511
// avoid catch triggering multiple times when nested calls
res._handled = true;
}
} catch (e) {
handleError(e, vm, info);
}
return res
}
function globalHandleError (err, vm, info) {
if (config.errorHandler) {
try {
return config.errorHandler.call(null, err, vm, info)
} catch (e) {
// if the user intentionally throws the original error in the handler,
// do not log it twice
if (e !== err) {
logError(e, null, 'config.errorHandler');
}
}
}
logError(err, vm, info);
}
function logError (err, vm, info) {
{
warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
}
/* istanbul ignore else */
if ((inBrowser || inWeex) && typeof console !== 'undefined') {
console.error(err);
} else {
throw err
}
}
/* */
var isUsingMicroTask = false;
var callbacks = [];
var pending = false;
function flushCallbacks () {
pending = false;
var copies = callbacks.slice(0);
callbacks.length = 0;
for (var i = 0; i < copies.length; i++) {
copies[i]();
}
}
// Here we have async deferring wrappers using microtasks.
// In 2.5 we used (macro) tasks (in combination with microtasks).
// However, it has subtle problems when state is changed right before repaint
// (e.g. #6813, out-in transitions).
// Also, using (macro) tasks in event handler would cause some weird behaviors
// that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109).
// So we now use microtasks everywhere, again.
// A major drawback of this tradeoff is that there are some scenarios
// where microtasks have too high a priority and fire in between supposedly
// sequential events (e.g. #4521, #6690, which have workarounds)
// or even between bubbling of the same event (#6566).
var timerFunc;
// The nextTick behavior leverages the microtask queue, which can be accessed
// via either native Promise.then or MutationObserver.
// MutationObserver has wider support, however it is seriously bugged in
// UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
// completely stops working after triggering a few times... so, if native
// Promise is available, we will use it:
/* istanbul ignore next, $flow-disable-line */
if (typeof Promise !== 'undefined' && isNative(Promise)) {
var p = Promise.resolve();
timerFunc = function () {
p.then(flushCallbacks);
// In problematic UIWebViews, Promise.then doesn't completely break, but
// it can get stuck in a weird state where callbacks are pushed into the
// microtask queue but the queue isn't being flushed, until the browser
// needs to do some other work, e.g. handle a timer. Therefore we can
// "force" the microtask queue to be flushed by adding an empty timer.
if (isIOS) { setTimeout(noop); }
};
isUsingMicroTask = true;
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
isNative(MutationObserver) ||
// PhantomJS and iOS 7.x
MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
// Use MutationObserver where native Promise is not available,
// e.g. PhantomJS, iOS7, Android 4.4
// (#6466 MutationObserver is unreliable in IE11)
var counter = 1;
var observer = new MutationObserver(flushCallbacks);
var textNode = document.createTextNode(String(counter));
observer.observe(textNode, {
characterData: true
});
timerFunc = function () {
counter = (counter + 1) % 2;
textNode.data = String(counter);
};
isUsingMicroTask = true;
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
// Fallback to setImmediate.
// Technically it leverages the (macro) task queue,
// but it is still a better choice than setTimeout.
timerFunc = function () {
setImmediate(flushCallbacks);
};
} else {
// Fallback to setTimeout.
timerFunc = function () {
setTimeout(flushCallbacks, 0);
};
}
function nextTick (cb, ctx) {
var _resolve;
callbacks.push(function () {
if (cb) {
try {
cb.call(ctx);
} catch (e) {
handleError(e, ctx, 'nextTick');
}
} else if (_resolve) {
_resolve(ctx);
}
});
if (!pending) {
pending = true;
timerFunc();
}
// $flow-disable-line
if (!cb && typeof Promise !== 'undefined') {
return new Promise(function (resolve) {
_resolve = resolve;
})
}
}
/* */
var mark;
var measure;
{
var perf = inBrowser && window.performance;
/* istanbul ignore if */
if (
perf &&
perf.mark &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
) {
mark = function (tag) { return perf.mark(tag); };
measure = function (name, startTag, endTag) {
perf.measure(name, startTag, endTag);
perf.clearMarks(startTag);
perf.clearMarks(endTag);
// perf.clearMeasures(name)
};
}
}
/* not type checking this file because flow doesn't play well with Proxy */
var initProxy;
{
var allowedGlobals = makeMap(
'Infinity,undefined,NaN,isFinite,isNaN,' +
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' +
'require' // for Webpack/Browserify
);
var warnNonPresent = function (target, key) {
warn(
"Property or method \"" + key + "\" is not defined on the instance but " +
'referenced during render. Make sure that this property is reactive, ' +
'either in the data option, or for class-based components, by ' +
'initializing the property. ' +
'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',
target
);
};
var warnReservedPrefix = function (target, key) {
warn(
"Property \"" + key + "\" must be accessed with \"$data." + key + "\" because " +
'properties starting with "$" or "_" are not proxied in the Vue instance to ' +
'prevent conflicts with Vue internals. ' +
'See: https://vuejs.org/v2/api/#data',
target
);
};
var hasProxy =
typeof Proxy !== 'undefined' && isNative(Proxy);
if (hasProxy) {
var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact');
config.keyCodes = new Proxy(config.keyCodes, {
set: function set (target, key, value) {
if (isBuiltInModifier(key)) {
warn(("Avoid overwriting built-in modifier in config.keyCodes: ." + key));
return false
} else {
target[key] = value;
return true
}
}
});
}
var hasHandler = {
has: function has (target, key) {
var has = key in target;
var isAllowed = allowedGlobals(key) ||
(typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data));
if (!has && !isAllowed) {
if (key in target.$data) { warnReservedPrefix(target, key); }
else { warnNonPresent(target, key); }
}
return has || !isAllowed
}
};
var getHandler = {
get: function get (target, key) {
if (typeof key === 'string' && !(key in target)) {
if (key in target.$data) { warnReservedPrefix(target, key); }
else { warnNonPresent(target, key); }
}
return target[key]
}
};
initProxy = function initProxy (vm) {
if (hasProxy) {
// determine which proxy handler to use
var options = vm.$options;
var handlers = options.render && options.render._withStripped
? getHandler
: hasHandler;
vm._renderProxy = new Proxy(vm, handlers);
} else {
vm._renderProxy = vm;
}
};
}
/* */
var seenObjects = new _Set();
/**
* Recursively traverse an object to evoke all converted
* getters, so that every nested property inside the object
* is collected as a "deep" dependency.
*/
function traverse (val) {
_traverse(val, seenObjects);
seenObjects.clear();
}
function _traverse (val, seen) {
var i, keys;
var isA = Array.isArray(val);
if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) {
return
}
if (val.__ob__) {
var depId = val.__ob__.dep.id;
if (seen.has(depId)) {
return
}
seen.add(depId);
}
if (isA) {
i = val.length;
while (i--) { _traverse(val[i], seen); }
} else {
keys = Object.keys(val);
i = keys.length;
while (i--) { _traverse(val[keys[i]], seen); }
}
}
/* */
var normalizeEvent = cached(function (name) {
var passive = name.charAt(0) === '&';
name = passive ? name.slice(1) : name;
var once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first
name = once$$1 ? name.slice(1) : name;
var capture = name.charAt(0) === '!';
name = capture ? name.slice(1) : name;
return {
name: name,
once: once$$1,
capture: capture,
passive: passive
}
});
function createFnInvoker (fns, vm) {
function invoker () {
var arguments$1 = arguments;
var fns = invoker.fns;
if (Array.isArray(fns)) {
var cloned = fns.slice();
for (var i = 0; i < cloned.length; i++) {
invokeWithErrorHandling(cloned[i], null, arguments$1, vm, "v-on handler");
}
} else {
// return handler return value for single handlers
return invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler")
}
}
invoker.fns = fns;
return invoker
}
function updateListeners (
on,
oldOn,
add,
remove$$1,
createOnceHandler,
vm
) {
var name, def$$1, cur, old, event;
for (name in on) {
def$$1 = cur = on[name];
old = oldOn[name];
event = normalizeEvent(name);
if (isUndef(cur)) {
warn(
"Invalid handler for event \"" + (event.name) + "\": got " + String(cur),
vm
);
} else if (isUndef(old)) {
if (isUndef(cur.fns)) {
cur = on[name] = createFnInvoker(cur, vm);
}
if (isTrue(event.once)) {
cur = on[name] = createOnceHandler(event.name, cur, event.capture);
}
add(event.name, cur, event.capture, event.passive, event.params);
} else if (cur !== old) {
old.fns = cur;
on[name] = old;
}
}
for (name in oldOn) {
if (isUndef(on[name])) {
event = normalizeEvent(name);
remove$$1(event.name, oldOn[name], event.capture);
}
}
}
/* */
function mergeVNodeHook (def, hookKey, hook) {
if (def instanceof VNode) {
def = def.data.hook || (def.data.hook = {});
}
var invoker;
var oldHook = def[hookKey];
function wrappedHook () {
hook.apply(this, arguments);
// important: remove merged hook to ensure it's called only once
// and prevent memory leak
remove(invoker.fns, wrappedHook);
}
if (isUndef(oldHook)) {
// no existing hook
invoker = createFnInvoker([wrappedHook]);
} else {
/* istanbul ignore if */
if (isDef(oldHook.fns) && isTrue(oldHook.merged)) {
// already a merged invoker
invoker = oldHook;
invoker.fns.push(wrappedHook);
} else {
// existing plain hook
invoker = createFnInvoker([oldHook, wrappedHook]);
}
}
invoker.merged = true;
def[hookKey] = invoker;
}
/* */
function extractPropsFromVNodeData (
data,
Ctor,
tag
) {
// we are only extracting raw values here.
// validation and default values are handled in the child
// component itself.
var propOptions = Ctor.options.props;
if (isUndef(propOptions)) {
return
}
var res = {};
var attrs = data.attrs;
var props = data.props;
if (isDef(attrs) || isDef(props)) {
for (var key in propOptions) {
var altKey = hyphenate(key);
{
var keyInLowerCase = key.toLowerCase();
if (
key !== keyInLowerCase &&
attrs && hasOwn(attrs, keyInLowerCase)
) {
tip(
"Prop \"" + keyInLowerCase + "\" is passed to component " +
(formatComponentName(tag || Ctor)) + ", but the declared prop name is" +
" \"" + key + "\". " +
"Note that HTML attributes are case-insensitive and camelCased " +
"props need to use their kebab-case equivalents when using in-DOM " +
"templates. You should probably use \"" + altKey + "\" instead of \"" + key + "\"."
);
}
}
checkProp(res, props, key, altKey, true) ||
checkProp(res, attrs, key, altKey, false);
}
}
return res
}
function checkProp (
res,
hash,
key,
altKey,
preserve
) {
if (isDef(hash)) {
if (hasOwn(hash, key)) {
res[key] = hash[key];
if (!preserve) {
delete hash[key];
}
return true
} else if (hasOwn(hash, altKey)) {
res[key] = hash[altKey];
if (!preserve) {
delete hash[altKey];
}
return true
}
}
return false
}
/* */
// The template compiler attempts to minimize the need for normalization by
// statically analyzing the template at compile time.
//
// For plain HTML markup, normalization can be completely skipped because the
// generated render function is guaranteed to return Array. There are
// two cases where extra normalization is needed:
// 1. When the children contains components - because a functional component
// may return an Array instead of a single root. In this case, just a simple
// normalization is needed - if any child is an Array, we flatten the whole
// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep
// because functional components already normalize their own children.
function simpleNormalizeChildren (children) {
for (var i = 0; i < children.length; i++) {
if (Array.isArray(children[i])) {
return Array.prototype.concat.apply([], children)
}
}
return children
}
// 2. When the children contains constructs that always generated nested Arrays,
// e.g. , , v-for, or when the children is provided by user
// with hand-written render functions / JSX. In such cases a full normalization
// is needed to cater to all possible types of children values.
function normalizeChildren (children) {
return isPrimitive(children)
? [createTextVNode(children)]
: Array.isArray(children)
? normalizeArrayChildren(children)
: undefined
}
function isTextNode (node) {
return isDef(node) && isDef(node.text) && isFalse(node.isComment)
}
function normalizeArrayChildren (children, nestedIndex) {
var res = [];
var i, c, lastIndex, last;
for (i = 0; i < children.length; i++) {
c = children[i];
if (isUndef(c) || typeof c === 'boolean') { continue }
lastIndex = res.length - 1;
last = res[lastIndex];
// nested
if (Array.isArray(c)) {
if (c.length > 0) {
c = normalizeArrayChildren(c, ((nestedIndex || '') + "_" + i));
// merge adjacent text nodes
if (isTextNode(c[0]) && isTextNode(last)) {
res[lastIndex] = createTextVNode(last.text + (c[0]).text);
c.shift();
}
res.push.apply(res, c);
}
} else if (isPrimitive(c)) {
if (isTextNode(last)) {
// merge adjacent text nodes
// this is necessary for SSR hydration because text nodes are
// essentially merged when rendered to HTML strings
res[lastIndex] = createTextVNode(last.text + c);
} else if (c !== '') {
// convert primitive to vnode
res.push(createTextVNode(c));
}
} else {
if (isTextNode(c) && isTextNode(last)) {
// merge adjacent text nodes
res[lastIndex] = createTextVNode(last.text + c.text);
} else {
// default key for nested array children (likely generated by v-for)
if (isTrue(children._isVList) &&
isDef(c.tag) &&
isUndef(c.key) &&
isDef(nestedIndex)) {
c.key = "__vlist" + nestedIndex + "_" + i + "__";
}
res.push(c);
}
}
}
return res
}
/* */
function initProvide (vm) {
var provide = vm.$options.provide;
if (provide) {
vm._provided = typeof provide === 'function'
? provide.call(vm)
: provide;
}
}
function initInjections (vm) {
var result = resolveInject(vm.$options.inject, vm);
if (result) {
toggleObserving(false);
Object.keys(result).forEach(function (key) {
/* istanbul ignore else */
{
defineReactive$$1(vm, key, result[key], function () {
warn(
"Avoid mutating an injected value directly since the changes will be " +
"overwritten whenever the provided component re-renders. " +
"injection being mutated: \"" + key + "\"",
vm
);
});
}
});
toggleObserving(true);
}
}
function resolveInject (inject, vm) {
if (inject) {
// inject is :any because flow is not smart enough to figure out cached
var result = Object.create(null);
var keys = hasSymbol
? Reflect.ownKeys(inject)
: Object.keys(inject);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
// #6574 in case the inject object is observed...
if (key === '__ob__') { continue }
var provideKey = inject[key].from;
var source = vm;
while (source) {
if (source._provided && hasOwn(source._provided, provideKey)) {
result[key] = source._provided[provideKey];
break
}
source = source.$parent;
}
if (!source) {
if ('default' in inject[key]) {
var provideDefault = inject[key].default;
result[key] = typeof provideDefault === 'function'
? provideDefault.call(vm)
: provideDefault;
} else {
warn(("Injection \"" + key + "\" not found"), vm);
}
}
}
return result
}
}
/* */
/**
* Runtime helper for resolving raw children VNodes into a slot object.
*/
function resolveSlots (
children,
context
) {
if (!children || !children.length) {
return {}
}
var slots = {};
for (var i = 0, l = children.length; i < l; i++) {
var child = children[i];
var data = child.data;
// remove slot attribute if the node is resolved as a Vue slot node
if (data && data.attrs && data.attrs.slot) {
delete data.attrs.slot;
}
// named slots should only be respected if the vnode was rendered in the
// same context.
if ((child.context === context || child.fnContext === context) &&
data && data.slot != null
) {
var name = data.slot;
var slot = (slots[name] || (slots[name] = []));
if (child.tag === 'template') {
slot.push.apply(slot, child.children || []);
} else {
slot.push(child);
}
} else {
(slots.default || (slots.default = [])).push(child);
}
}
// ignore slots that contains only whitespace
for (var name$1 in slots) {
if (slots[name$1].every(isWhitespace)) {
delete slots[name$1];
}
}
return slots
}
function isWhitespace (node) {
return (node.isComment && !node.asyncFactory) || node.text === ' '
}
/* */
function isAsyncPlaceholder (node) {
return node.isComment && node.asyncFactory
}
/* */
function normalizeScopedSlots (
slots,
normalSlots,
prevSlots
) {
var res;
var hasNormalSlots = Object.keys(normalSlots).length > 0;
var isStable = slots ? !!slots.$stable : !hasNormalSlots;
var key = slots && slots.$key;
if (!slots) {
res = {};
} else if (slots._normalized) {
// fast path 1: child component re-render only, parent did not change
return slots._normalized
} else if (
isStable &&
prevSlots &&
prevSlots !== emptyObject &&
key === prevSlots.$key &&
!hasNormalSlots &&
!prevSlots.$hasNormal
) {
// fast path 2: stable scoped slots w/ no normal slots to proxy,
// only need to normalize once
return prevSlots
} else {
res = {};
for (var key$1 in slots) {
if (slots[key$1] && key$1[0] !== '$') {
res[key$1] = normalizeScopedSlot(normalSlots, key$1, slots[key$1]);
}
}
}
// expose normal slots on scopedSlots
for (var key$2 in normalSlots) {
if (!(key$2 in res)) {
res[key$2] = proxyNormalSlot(normalSlots, key$2);
}
}
// avoriaz seems to mock a non-extensible $scopedSlots object
// and when that is passed down this would cause an error
if (slots && Object.isExtensible(slots)) {
(slots)._normalized = res;
}
def(res, '$stable', isStable);
def(res, '$key', key);
def(res, '$hasNormal', hasNormalSlots);
return res
}
function normalizeScopedSlot(normalSlots, key, fn) {
var normalized = function () {
var res = arguments.length ? fn.apply(null, arguments) : fn({});
res = res && typeof res === 'object' && !Array.isArray(res)
? [res] // single vnode
: normalizeChildren(res);
var vnode = res && res[0];
return res && (
!vnode ||
(res.length === 1 && vnode.isComment && !isAsyncPlaceholder(vnode)) // #9658, #10391
) ? undefined
: res
};
// this is a slot using the new v-slot syntax without scope. although it is
// compiled as a scoped slot, render fn users would expect it to be present
// on this.$slots because the usage is semantically a normal slot.
if (fn.proxy) {
Object.defineProperty(normalSlots, key, {
get: normalized,
enumerable: true,
configurable: true
});
}
return normalized
}
function proxyNormalSlot(slots, key) {
return function () { return slots[key]; }
}
/* */
/**
* Runtime helper for rendering v-for lists.
*/
function renderList (
val,
render
) {
var ret, i, l, keys, key;
if (Array.isArray(val) || typeof val === 'string') {
ret = new Array(val.length);
for (i = 0, l = val.length; i < l; i++) {
ret[i] = render(val[i], i);
}
} else if (typeof val === 'number') {
ret = new Array(val);
for (i = 0; i < val; i++) {
ret[i] = render(i + 1, i);
}
} else if (isObject(val)) {
if (hasSymbol && val[Symbol.iterator]) {
ret = [];
var iterator = val[Symbol.iterator]();
var result = iterator.next();
while (!result.done) {
ret.push(render(result.value, ret.length));
result = iterator.next();
}
} else {
keys = Object.keys(val);
ret = new Array(keys.length);
for (i = 0, l = keys.length; i < l; i++) {
key = keys[i];
ret[i] = render(val[key], key, i);
}
}
}
if (!isDef(ret)) {
ret = [];
}
(ret)._isVList = true;
return ret
}
/* */
/**
* Runtime helper for rendering
*/
function renderSlot (
name,
fallbackRender,
props,
bindObject
) {
var scopedSlotFn = this.$scopedSlots[name];
var nodes;
if (scopedSlotFn) {
// scoped slot
props = props || {};
if (bindObject) {
if (!isObject(bindObject)) {
warn('slot v-bind without argument expects an Object', this);
}
props = extend(extend({}, bindObject), props);
}
nodes =
scopedSlotFn(props) ||
(typeof fallbackRender === 'function' ? fallbackRender() : fallbackRender);
} else {
nodes =
this.$slots[name] ||
(typeof fallbackRender === 'function' ? fallbackRender() : fallbackRender);
}
var target = props && props.slot;
if (target) {
return this.$createElement('template', { slot: target }, nodes)
} else {
return nodes
}
}
/* */
/**
* Runtime helper for resolving filters
*/
function resolveFilter (id) {
return resolveAsset(this.$options, 'filters', id, true) || identity
}
/* */
function isKeyNotMatch (expect, actual) {
if (Array.isArray(expect)) {
return expect.indexOf(actual) === -1
} else {
return expect !== actual
}
}
/**
* Runtime helper for checking keyCodes from config.
* exposed as Vue.prototype._k
* passing in eventKeyName as last argument separately for backwards compat
*/
function checkKeyCodes (
eventKeyCode,
key,
builtInKeyCode,
eventKeyName,
builtInKeyName
) {
var mappedKeyCode = config.keyCodes[key] || builtInKeyCode;
if (builtInKeyName && eventKeyName && !config.keyCodes[key]) {
return isKeyNotMatch(builtInKeyName, eventKeyName)
} else if (mappedKeyCode) {
return isKeyNotMatch(mappedKeyCode, eventKeyCode)
} else if (eventKeyName) {
return hyphenate(eventKeyName) !== key
}
return eventKeyCode === undefined
}
/* */
/**
* Runtime helper for merging v-bind="object" into a VNode's data.
*/
function bindObjectProps (
data,
tag,
value,
asProp,
isSync
) {
if (value) {
if (!isObject(value)) {
warn(
'v-bind without argument expects an Object or Array value',
this
);
} else {
if (Array.isArray(value)) {
value = toObject(value);
}
var hash;
var loop = function ( key ) {
if (
key === 'class' ||
key === 'style' ||
isReservedAttribute(key)
) {
hash = data;
} else {
var type = data.attrs && data.attrs.type;
hash = asProp || config.mustUseProp(tag, type, key)
? data.domProps || (data.domProps = {})
: data.attrs || (data.attrs = {});
}
var camelizedKey = camelize(key);
var hyphenatedKey = hyphenate(key);
if (!(camelizedKey in hash) && !(hyphenatedKey in hash)) {
hash[key] = value[key];
if (isSync) {
var on = data.on || (data.on = {});
on[("update:" + key)] = function ($event) {
value[key] = $event;
};
}
}
};
for (var key in value) loop( key );
}
}
return data
}
/* */
/**
* Runtime helper for rendering static trees.
*/
function renderStatic (
index,
isInFor
) {
var cached = this._staticTrees || (this._staticTrees = []);
var tree = cached[index];
// if has already-rendered static tree and not inside v-for,
// we can reuse the same tree.
if (tree && !isInFor) {
return tree
}
// otherwise, render a fresh tree.
tree = cached[index] = this.$options.staticRenderFns[index].call(
this._renderProxy,
null,
this // for render fns generated for functional component templates
);
markStatic(tree, ("__static__" + index), false);
return tree
}
/**
* Runtime helper for v-once.
* Effectively it means marking the node as static with a unique key.
*/
function markOnce (
tree,
index,
key
) {
markStatic(tree, ("__once__" + index + (key ? ("_" + key) : "")), true);
return tree
}
function markStatic (
tree,
key,
isOnce
) {
if (Array.isArray(tree)) {
for (var i = 0; i < tree.length; i++) {
if (tree[i] && typeof tree[i] !== 'string') {
markStaticNode(tree[i], (key + "_" + i), isOnce);
}
}
} else {
markStaticNode(tree, key, isOnce);
}
}
function markStaticNode (node, key, isOnce) {
node.isStatic = true;
node.key = key;
node.isOnce = isOnce;
}
/* */
function bindObjectListeners (data, value) {
if (value) {
if (!isPlainObject(value)) {
warn(
'v-on without argument expects an Object value',
this
);
} else {
var on = data.on = data.on ? extend({}, data.on) : {};
for (var key in value) {
var existing = on[key];
var ours = value[key];
on[key] = existing ? [].concat(existing, ours) : ours;
}
}
}
return data
}
/* */
function resolveScopedSlots (
fns, // see flow/vnode
res,
// the following are added in 2.6
hasDynamicKeys,
contentHashKey
) {
res = res || { $stable: !hasDynamicKeys };
for (var i = 0; i < fns.length; i++) {
var slot = fns[i];
if (Array.isArray(slot)) {
resolveScopedSlots(slot, res, hasDynamicKeys);
} else if (slot) {
// marker for reverse proxying v-slot without scope on this.$slots
if (slot.proxy) {
slot.fn.proxy = true;
}
res[slot.key] = slot.fn;
}
}
if (contentHashKey) {
(res).$key = contentHashKey;
}
return res
}
/* */
function bindDynamicKeys (baseObj, values) {
for (var i = 0; i < values.length; i += 2) {
var key = values[i];
if (typeof key === 'string' && key) {
baseObj[values[i]] = values[i + 1];
} else if (key !== '' && key !== null) {
// null is a special value for explicitly removing a binding
warn(
("Invalid value for dynamic directive argument (expected string or null): " + key),
this
);
}
}
return baseObj
}
// helper to dynamically append modifier runtime markers to event names.
// ensure only append when value is already string, otherwise it will be cast
// to string and cause the type check to miss.
function prependModifier (value, symbol) {
return typeof value === 'string' ? symbol + value : value
}
/* */
function installRenderHelpers (target) {
target._o = markOnce;
target._n = toNumber;
target._s = toString;
target._l = renderList;
target._t = renderSlot;
target._q = looseEqual;
target._i = looseIndexOf;
target._m = renderStatic;
target._f = resolveFilter;
target._k = checkKeyCodes;
target._b = bindObjectProps;
target._v = createTextVNode;
target._e = createEmptyVNode;
target._u = resolveScopedSlots;
target._g = bindObjectListeners;
target._d = bindDynamicKeys;
target._p = prependModifier;
}
/* */
function FunctionalRenderContext (
data,
props,
children,
parent,
Ctor
) {
var this$1 = this;
var options = Ctor.options;
// ensure the createElement function in functional components
// gets a unique context - this is necessary for correct named slot check
var contextVm;
if (hasOwn(parent, '_uid')) {
contextVm = Object.create(parent);
// $flow-disable-line
contextVm._original = parent;
} else {
// the context vm passed in is a functional context as well.
// in this case we want to make sure we are able to get a hold to the
// real context instance.
contextVm = parent;
// $flow-disable-line
parent = parent._original;
}
var isCompiled = isTrue(options._compiled);
var needNormalization = !isCompiled;
this.data = data;
this.props = props;
this.children = children;
this.parent = parent;
this.listeners = data.on || emptyObject;
this.injections = resolveInject(options.inject, parent);
this.slots = function () {
if (!this$1.$slots) {
normalizeScopedSlots(
data.scopedSlots,
this$1.$slots = resolveSlots(children, parent)
);
}
return this$1.$slots
};
Object.defineProperty(this, 'scopedSlots', ({
enumerable: true,
get: function get () {
return normalizeScopedSlots(data.scopedSlots, this.slots())
}
}));
// support for compiled functional template
if (isCompiled) {
// exposing $options for renderStatic()
this.$options = options;
// pre-resolve slots for renderSlot()
this.$slots = this.slots();
this.$scopedSlots = normalizeScopedSlots(data.scopedSlots, this.$slots);
}
if (options._scopeId) {
this._c = function (a, b, c, d) {
var vnode = createElement(contextVm, a, b, c, d, needNormalization);
if (vnode && !Array.isArray(vnode)) {
vnode.fnScopeId = options._scopeId;
vnode.fnContext = parent;
}
return vnode
};
} else {
this._c = function (a, b, c, d) { return createElement(contextVm, a, b, c, d, needNormalization); };
}
}
installRenderHelpers(FunctionalRenderContext.prototype);
function createFunctionalComponent (
Ctor,
propsData,
data,
contextVm,
children
) {
var options = Ctor.options;
var props = {};
var propOptions = options.props;
if (isDef(propOptions)) {
for (var key in propOptions) {
props[key] = validateProp(key, propOptions, propsData || emptyObject);
}
} else {
if (isDef(data.attrs)) { mergeProps(props, data.attrs); }
if (isDef(data.props)) { mergeProps(props, data.props); }
}
var renderContext = new FunctionalRenderContext(
data,
props,
children,
contextVm,
Ctor
);
var vnode = options.render.call(null, renderContext._c, renderContext);
if (vnode instanceof VNode) {
return cloneAndMarkFunctionalResult(vnode, data, renderContext.parent, options, renderContext)
} else if (Array.isArray(vnode)) {
var vnodes = normalizeChildren(vnode) || [];
var res = new Array(vnodes.length);
for (var i = 0; i < vnodes.length; i++) {
res[i] = cloneAndMarkFunctionalResult(vnodes[i], data, renderContext.parent, options, renderContext);
}
return res
}
}
function cloneAndMarkFunctionalResult (vnode, data, contextVm, options, renderContext) {
// #7817 clone node before setting fnContext, otherwise if the node is reused
// (e.g. it was from a cached normal slot) the fnContext causes named slots
// that should not be matched to match.
var clone = cloneVNode(vnode);
clone.fnContext = contextVm;
clone.fnOptions = options;
{
(clone.devtoolsMeta = clone.devtoolsMeta || {}).renderContext = renderContext;
}
if (data.slot) {
(clone.data || (clone.data = {})).slot = data.slot;
}
return clone
}
function mergeProps (to, from) {
for (var key in from) {
to[camelize(key)] = from[key];
}
}
/* */
/* */
/* */
/* */
// inline hooks to be invoked on component VNodes during patch
var componentVNodeHooks = {
init: function init (vnode, hydrating) {
if (
vnode.componentInstance &&
!vnode.componentInstance._isDestroyed &&
vnode.data.keepAlive
) {
// kept-alive components, treat as a patch
var mountedNode = vnode; // work around flow
componentVNodeHooks.prepatch(mountedNode, mountedNode);
} else {
var child = vnode.componentInstance = createComponentInstanceForVnode(
vnode,
activeInstance
);
child.$mount(hydrating ? vnode.elm : undefined, hydrating);
}
},
prepatch: function prepatch (oldVnode, vnode) {
var options = vnode.componentOptions;
var child = vnode.componentInstance = oldVnode.componentInstance;
updateChildComponent(
child,
options.propsData, // updated props
options.listeners, // updated listeners
vnode, // new parent vnode
options.children // new children
);
},
insert: function insert (vnode) {
var context = vnode.context;
var componentInstance = vnode.componentInstance;
if (!componentInstance._isMounted) {
componentInstance._isMounted = true;
callHook(componentInstance, 'mounted');
}
if (vnode.data.keepAlive) {
if (context._isMounted) {
// vue-router#1212
// During updates, a kept-alive component's child components may
// change, so directly walking the tree here may call activated hooks
// on incorrect children. Instead we push them into a queue which will
// be processed after the whole patch process ended.
queueActivatedComponent(componentInstance);
} else {
activateChildComponent(componentInstance, true /* direct */);
}
}
},
destroy: function destroy (vnode) {
var componentInstance = vnode.componentInstance;
if (!componentInstance._isDestroyed) {
if (!vnode.data.keepAlive) {
componentInstance.$destroy();
} else {
deactivateChildComponent(componentInstance, true /* direct */);
}
}
}
};
var hooksToMerge = Object.keys(componentVNodeHooks);
function createComponent (
Ctor,
data,
context,
children,
tag
) {
if (isUndef(Ctor)) {
return
}
var baseCtor = context.$options._base;
// plain options object: turn it into a constructor
if (isObject(Ctor)) {
Ctor = baseCtor.extend(Ctor);
}
// if at this stage it's not a constructor or an async component factory,
// reject.
if (typeof Ctor !== 'function') {
{
warn(("Invalid Component definition: " + (String(Ctor))), context);
}
return
}
// async component
var asyncFactory;
if (isUndef(Ctor.cid)) {
asyncFactory = Ctor;
Ctor = resolveAsyncComponent(asyncFactory, baseCtor);
if (Ctor === undefined) {
// return a placeholder node for async component, which is rendered
// as a comment node but preserves all the raw information for the node.
// the information will be used for async server-rendering and hydration.
return createAsyncPlaceholder(
asyncFactory,
data,
context,
children,
tag
)
}
}
data = data || {};
// resolve constructor options in case global mixins are applied after
// component constructor creation
resolveConstructorOptions(Ctor);
// transform component v-model data into props & events
if (isDef(data.model)) {
transformModel(Ctor.options, data);
}
// extract props
var propsData = extractPropsFromVNodeData(data, Ctor, tag);
// functional component
if (isTrue(Ctor.options.functional)) {
return createFunctionalComponent(Ctor, propsData, data, context, children)
}
// extract listeners, since these needs to be treated as
// child component listeners instead of DOM listeners
var listeners = data.on;
// replace with listeners with .native modifier
// so it gets processed during parent component patch.
data.on = data.nativeOn;
if (isTrue(Ctor.options.abstract)) {
// abstract components do not keep anything
// other than props & listeners & slot
// work around flow
var slot = data.slot;
data = {};
if (slot) {
data.slot = slot;
}
}
// install component management hooks onto the placeholder node
installComponentHooks(data);
// return a placeholder vnode
var name = Ctor.options.name || tag;
var vnode = new VNode(
("vue-component-" + (Ctor.cid) + (name ? ("-" + name) : '')),
data, undefined, undefined, undefined, context,
{ Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children },
asyncFactory
);
return vnode
}
function createComponentInstanceForVnode (
// we know it's MountedComponentVNode but flow doesn't
vnode,
// activeInstance in lifecycle state
parent
) {
var options = {
_isComponent: true,
_parentVnode: vnode,
parent: parent
};
// check inline-template render functions
var inlineTemplate = vnode.data.inlineTemplate;
if (isDef(inlineTemplate)) {
options.render = inlineTemplate.render;
options.staticRenderFns = inlineTemplate.staticRenderFns;
}
return new vnode.componentOptions.Ctor(options)
}
function installComponentHooks (data) {
var hooks = data.hook || (data.hook = {});
for (var i = 0; i < hooksToMerge.length; i++) {
var key = hooksToMerge[i];
var existing = hooks[key];
var toMerge = componentVNodeHooks[key];
if (existing !== toMerge && !(existing && existing._merged)) {
hooks[key] = existing ? mergeHook$1(toMerge, existing) : toMerge;
}
}
}
function mergeHook$1 (f1, f2) {
var merged = function (a, b) {
// flow complains about extra args which is why we use any
f1(a, b);
f2(a, b);
};
merged._merged = true;
return merged
}
// transform component v-model info (value and callback) into
// prop and event handler respectively.
function transformModel (options, data) {
var prop = (options.model && options.model.prop) || 'value';
var event = (options.model && options.model.event) || 'input'
;(data.attrs || (data.attrs = {}))[prop] = data.model.value;
var on = data.on || (data.on = {});
var existing = on[event];
var callback = data.model.callback;
if (isDef(existing)) {
if (
Array.isArray(existing)
? existing.indexOf(callback) === -1
: existing !== callback
) {
on[event] = [callback].concat(existing);
}
} else {
on[event] = callback;
}
}
/* */
var SIMPLE_NORMALIZE = 1;
var ALWAYS_NORMALIZE = 2;
// wrapper function for providing a more flexible interface
// without getting yelled at by flow
function createElement (
context,
tag,
data,
children,
normalizationType,
alwaysNormalize
) {
if (Array.isArray(data) || isPrimitive(data)) {
normalizationType = children;
children = data;
data = undefined;
}
if (isTrue(alwaysNormalize)) {
normalizationType = ALWAYS_NORMALIZE;
}
return _createElement(context, tag, data, children, normalizationType)
}
function _createElement (
context,
tag,
data,
children,
normalizationType
) {
if (isDef(data) && isDef((data).__ob__)) {
warn(
"Avoid using observed data object as vnode data: " + (JSON.stringify(data)) + "\n" +
'Always create fresh vnode data objects in each render!',
context
);
return createEmptyVNode()
}
// object syntax in v-bind
if (isDef(data) && isDef(data.is)) {
tag = data.is;
}
if (!tag) {
// in case of component :is set to falsy value
return createEmptyVNode()
}
// warn against non-primitive key
if (isDef(data) && isDef(data.key) && !isPrimitive(data.key)
) {
{
warn(
'Avoid using non-primitive value as key, ' +
'use string/number value instead.',
context
);
}
}
// support single function children as default scoped slot
if (Array.isArray(children) &&
typeof children[0] === 'function'
) {
data = data || {};
data.scopedSlots = { default: children[0] };
children.length = 0;
}
if (normalizationType === ALWAYS_NORMALIZE) {
children = normalizeChildren(children);
} else if (normalizationType === SIMPLE_NORMALIZE) {
children = simpleNormalizeChildren(children);
}
var vnode, ns;
if (typeof tag === 'string') {
var Ctor;
ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag);
if (config.isReservedTag(tag)) {
// platform built-in elements
if (isDef(data) && isDef(data.nativeOn) && data.tag !== 'component') {
warn(
("The .native modifier for v-on is only valid on components but it was used on <" + tag + ">."),
context
);
}
vnode = new VNode(
config.parsePlatformTagName(tag), data, children,
undefined, undefined, context
);
} else if ((!data || !data.pre) && isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
// component
vnode = createComponent(Ctor, data, context, children, tag);
} else {
// unknown or unlisted namespaced elements
// check at runtime because it may get assigned a namespace when its
// parent normalizes children
vnode = new VNode(
tag, data, children,
undefined, undefined, context
);
}
} else {
// direct component options / constructor
vnode = createComponent(tag, data, context, children);
}
if (Array.isArray(vnode)) {
return vnode
} else if (isDef(vnode)) {
if (isDef(ns)) { applyNS(vnode, ns); }
if (isDef(data)) { registerDeepBindings(data); }
return vnode
} else {
return createEmptyVNode()
}
}
function applyNS (vnode, ns, force) {
vnode.ns = ns;
if (vnode.tag === 'foreignObject') {
// use default namespace inside foreignObject
ns = undefined;
force = true;
}
if (isDef(vnode.children)) {
for (var i = 0, l = vnode.children.length; i < l; i++) {
var child = vnode.children[i];
if (isDef(child.tag) && (
isUndef(child.ns) || (isTrue(force) && child.tag !== 'svg'))) {
applyNS(child, ns, force);
}
}
}
}
// ref #5318
// necessary to ensure parent re-render when deep bindings like :style and
// :class are used on slot nodes
function registerDeepBindings (data) {
if (isObject(data.style)) {
traverse(data.style);
}
if (isObject(data.class)) {
traverse(data.class);
}
}
/* */
function initRender (vm) {
vm._vnode = null; // the root of the child tree
vm._staticTrees = null; // v-once cached trees
var options = vm.$options;
var parentVnode = vm.$vnode = options._parentVnode; // the placeholder node in parent tree
var renderContext = parentVnode && parentVnode.context;
vm.$slots = resolveSlots(options._renderChildren, renderContext);
vm.$scopedSlots = emptyObject;
// bind the createElement fn to this instance
// so that we get proper render context inside it.
// args order: tag, data, children, normalizationType, alwaysNormalize
// internal version is used by render functions compiled from templates
vm._c = function (a, b, c, d) { return createElement(vm, a, b, c, d, false); };
// normalization is always applied for the public version, used in
// user-written render functions.
vm.$createElement = function (a, b, c, d) { return createElement(vm, a, b, c, d, true); };
// $attrs & $listeners are exposed for easier HOC creation.
// they need to be reactive so that HOCs using them are always updated
var parentData = parentVnode && parentVnode.data;
/* istanbul ignore else */
{
defineReactive$$1(vm, '$attrs', parentData && parentData.attrs || emptyObject, function () {
!isUpdatingChildComponent && warn("$attrs is readonly.", vm);
}, true);
defineReactive$$1(vm, '$listeners', options._parentListeners || emptyObject, function () {
!isUpdatingChildComponent && warn("$listeners is readonly.", vm);
}, true);
}
}
var currentRenderingInstance = null;
function renderMixin (Vue) {
// install runtime convenience helpers
installRenderHelpers(Vue.prototype);
Vue.prototype.$nextTick = function (fn) {
return nextTick(fn, this)
};
Vue.prototype._render = function () {
var vm = this;
var ref = vm.$options;
var render = ref.render;
var _parentVnode = ref._parentVnode;
if (_parentVnode) {
vm.$scopedSlots = normalizeScopedSlots(
_parentVnode.data.scopedSlots,
vm.$slots,
vm.$scopedSlots
);
}
// set parent vnode. this allows render functions to have access
// to the data on the placeholder node.
vm.$vnode = _parentVnode;
// render self
var vnode;
try {
// There's no need to maintain a stack because all render fns are called
// separately from one another. Nested component's render fns are called
// when parent component is patched.
currentRenderingInstance = vm;
vnode = render.call(vm._renderProxy, vm.$createElement);
} catch (e) {
handleError(e, vm, "render");
// return error render result,
// or previous vnode to prevent render error causing blank component
/* istanbul ignore else */
if (vm.$options.renderError) {
try {
vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e);
} catch (e) {
handleError(e, vm, "renderError");
vnode = vm._vnode;
}
} else {
vnode = vm._vnode;
}
} finally {
currentRenderingInstance = null;
}
// if the returned array contains only a single node, allow it
if (Array.isArray(vnode) && vnode.length === 1) {
vnode = vnode[0];
}
// return empty vnode in case the render function errored out
if (!(vnode instanceof VNode)) {
if (Array.isArray(vnode)) {
warn(
'Multiple root nodes returned from render function. Render function ' +
'should return a single root node.',
vm
);
}
vnode = createEmptyVNode();
}
// set parent
vnode.parent = _parentVnode;
return vnode
};
}
/* */
function ensureCtor (comp, base) {
if (
comp.__esModule ||
(hasSymbol && comp[Symbol.toStringTag] === 'Module')
) {
comp = comp.default;
}
return isObject(comp)
? base.extend(comp)
: comp
}
function createAsyncPlaceholder (
factory,
data,
context,
children,
tag
) {
var node = createEmptyVNode();
node.asyncFactory = factory;
node.asyncMeta = { data: data, context: context, children: children, tag: tag };
return node
}
function resolveAsyncComponent (
factory,
baseCtor
) {
if (isTrue(factory.error) && isDef(factory.errorComp)) {
return factory.errorComp
}
if (isDef(factory.resolved)) {
return factory.resolved
}
var owner = currentRenderingInstance;
if (owner && isDef(factory.owners) && factory.owners.indexOf(owner) === -1) {
// already pending
factory.owners.push(owner);
}
if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
return factory.loadingComp
}
if (owner && !isDef(factory.owners)) {
var owners = factory.owners = [owner];
var sync = true;
var timerLoading = null;
var timerTimeout = null
;(owner).$on('hook:destroyed', function () { return remove(owners, owner); });
var forceRender = function (renderCompleted) {
for (var i = 0, l = owners.length; i < l; i++) {
(owners[i]).$forceUpdate();
}
if (renderCompleted) {
owners.length = 0;
if (timerLoading !== null) {
clearTimeout(timerLoading);
timerLoading = null;
}
if (timerTimeout !== null) {
clearTimeout(timerTimeout);
timerTimeout = null;
}
}
};
var resolve = once(function (res) {
// cache resolved
factory.resolved = ensureCtor(res, baseCtor);
// invoke callbacks only if this is not a synchronous resolve
// (async resolves are shimmed as synchronous during SSR)
if (!sync) {
forceRender(true);
} else {
owners.length = 0;
}
});
var reject = once(function (reason) {
warn(
"Failed to resolve async component: " + (String(factory)) +
(reason ? ("\nReason: " + reason) : '')
);
if (isDef(factory.errorComp)) {
factory.error = true;
forceRender(true);
}
});
var res = factory(resolve, reject);
if (isObject(res)) {
if (isPromise(res)) {
// () => Promise
if (isUndef(factory.resolved)) {
res.then(resolve, reject);
}
} else if (isPromise(res.component)) {
res.component.then(resolve, reject);
if (isDef(res.error)) {
factory.errorComp = ensureCtor(res.error, baseCtor);
}
if (isDef(res.loading)) {
factory.loadingComp = ensureCtor(res.loading, baseCtor);
if (res.delay === 0) {
factory.loading = true;
} else {
timerLoading = setTimeout(function () {
timerLoading = null;
if (isUndef(factory.resolved) && isUndef(factory.error)) {
factory.loading = true;
forceRender(false);
}
}, res.delay || 200);
}
}
if (isDef(res.timeout)) {
timerTimeout = setTimeout(function () {
timerTimeout = null;
if (isUndef(factory.resolved)) {
reject(
"timeout (" + (res.timeout) + "ms)"
);
}
}, res.timeout);
}
}
}
sync = false;
// return in case resolved synchronously
return factory.loading
? factory.loadingComp
: factory.resolved
}
}
/* */
function getFirstComponentChild (children) {
if (Array.isArray(children)) {
for (var i = 0; i < children.length; i++) {
var c = children[i];
if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
return c
}
}
}
}
/* */
/* */
function initEvents (vm) {
vm._events = Object.create(null);
vm._hasHookEvent = false;
// init parent attached events
var listeners = vm.$options._parentListeners;
if (listeners) {
updateComponentListeners(vm, listeners);
}
}
var target;
function add (event, fn) {
target.$on(event, fn);
}
function remove$1 (event, fn) {
target.$off(event, fn);
}
function createOnceHandler (event, fn) {
var _target = target;
return function onceHandler () {
var res = fn.apply(null, arguments);
if (res !== null) {
_target.$off(event, onceHandler);
}
}
}
function updateComponentListeners (
vm,
listeners,
oldListeners
) {
target = vm;
updateListeners(listeners, oldListeners || {}, add, remove$1, createOnceHandler, vm);
target = undefined;
}
function eventsMixin (Vue) {
var hookRE = /^hook:/;
Vue.prototype.$on = function (event, fn) {
var vm = this;
if (Array.isArray(event)) {
for (var i = 0, l = event.length; i < l; i++) {
vm.$on(event[i], fn);
}
} else {
(vm._events[event] || (vm._events[event] = [])).push(fn);
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
if (hookRE.test(event)) {
vm._hasHookEvent = true;
}
}
return vm
};
Vue.prototype.$once = function (event, fn) {
var vm = this;
function on () {
vm.$off(event, on);
fn.apply(vm, arguments);
}
on.fn = fn;
vm.$on(event, on);
return vm
};
Vue.prototype.$off = function (event, fn) {
var vm = this;
// all
if (!arguments.length) {
vm._events = Object.create(null);
return vm
}
// array of events
if (Array.isArray(event)) {
for (var i$1 = 0, l = event.length; i$1 < l; i$1++) {
vm.$off(event[i$1], fn);
}
return vm
}
// specific event
var cbs = vm._events[event];
if (!cbs) {
return vm
}
if (!fn) {
vm._events[event] = null;
return vm
}
// specific handler
var cb;
var i = cbs.length;
while (i--) {
cb = cbs[i];
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1);
break
}
}
return vm
};
Vue.prototype.$emit = function (event) {
var vm = this;
{
var lowerCaseEvent = event.toLowerCase();
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
"Event \"" + lowerCaseEvent + "\" is emitted in component " +
(formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
"Note that HTML attributes are case-insensitive and you cannot use " +
"v-on to listen to camelCase events when using in-DOM templates. " +
"You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
);
}
}
var cbs = vm._events[event];
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs;
var args = toArray(arguments, 1);
var info = "event handler for \"" + event + "\"";
for (var i = 0, l = cbs.length; i < l; i++) {
invokeWithErrorHandling(cbs[i], vm, args, vm, info);
}
}
return vm
};
}
/* */
var activeInstance = null;
var isUpdatingChildComponent = false;
function setActiveInstance(vm) {
var prevActiveInstance = activeInstance;
activeInstance = vm;
return function () {
activeInstance = prevActiveInstance;
}
}
function initLifecycle (vm) {
var options = vm.$options;
// locate first non-abstract parent
var parent = options.parent;
if (parent && !options.abstract) {
while (parent.$options.abstract && parent.$parent) {
parent = parent.$parent;
}
parent.$children.push(vm);
}
vm.$parent = parent;
vm.$root = parent ? parent.$root : vm;
vm.$children = [];
vm.$refs = {};
vm._watcher = null;
vm._inactive = null;
vm._directInactive = false;
vm._isMounted = false;
vm._isDestroyed = false;
vm._isBeingDestroyed = false;
}
function lifecycleMixin (Vue) {
Vue.prototype._update = function (vnode, hydrating) {
var vm = this;
var prevEl = vm.$el;
var prevVnode = vm._vnode;
var restoreActiveInstance = setActiveInstance(vm);
vm._vnode = vnode;
// Vue.prototype.__patch__ is injected in entry points
// based on the rendering backend used.
if (!prevVnode) {
// initial render
vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
} else {
// updates
vm.$el = vm.__patch__(prevVnode, vnode);
}
restoreActiveInstance();
// update __vue__ reference
if (prevEl) {
prevEl.__vue__ = null;
}
if (vm.$el) {
vm.$el.__vue__ = vm;
}
// if parent is an HOC, update its $el as well
if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
vm.$parent.$el = vm.$el;
}
// updated hook is called by the scheduler to ensure that children are
// updated in a parent's updated hook.
};
Vue.prototype.$forceUpdate = function () {
var vm = this;
if (vm._watcher) {
vm._watcher.update();
}
};
Vue.prototype.$destroy = function () {
var vm = this;
if (vm._isBeingDestroyed) {
return
}
callHook(vm, 'beforeDestroy');
vm._isBeingDestroyed = true;
// remove self from parent
var parent = vm.$parent;
if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
remove(parent.$children, vm);
}
// teardown watchers
if (vm._watcher) {
vm._watcher.teardown();
}
var i = vm._watchers.length;
while (i--) {
vm._watchers[i].teardown();
}
// remove reference from data ob
// frozen object may not have observer.
if (vm._data.__ob__) {
vm._data.__ob__.vmCount--;
}
// call the last hook...
vm._isDestroyed = true;
// invoke destroy hooks on current rendered tree
vm.__patch__(vm._vnode, null);
// fire destroyed hook
callHook(vm, 'destroyed');
// turn off all instance listeners.
vm.$off();
// remove __vue__ reference
if (vm.$el) {
vm.$el.__vue__ = null;
}
// release circular reference (#6759)
if (vm.$vnode) {
vm.$vnode.parent = null;
}
};
}
function mountComponent (
vm,
el,
hydrating
) {
vm.$el = el;
if (!vm.$options.render) {
vm.$options.render = createEmptyVNode;
{
/* istanbul ignore if */
if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
vm.$options.el || el) {
warn(
'You are using the runtime-only build of Vue where the template ' +
'compiler is not available. Either pre-compile the templates into ' +
'render functions, or use the compiler-included build.',
vm
);
} else {
warn(
'Failed to mount component: template or render function not defined.',
vm
);
}
}
}
callHook(vm, 'beforeMount');
var updateComponent;
/* istanbul ignore if */
if (config.performance && mark) {
updateComponent = function () {
var name = vm._name;
var id = vm._uid;
var startTag = "vue-perf-start:" + id;
var endTag = "vue-perf-end:" + id;
mark(startTag);
var vnode = vm._render();
mark(endTag);
measure(("vue " + name + " render"), startTag, endTag);
mark(startTag);
vm._update(vnode, hydrating);
mark(endTag);
measure(("vue " + name + " patch"), startTag, endTag);
};
} else {
updateComponent = function () {
vm._update(vm._render(), hydrating);
};
}
// we set this to vm._watcher inside the watcher's constructor
// since the watcher's initial patch may call $forceUpdate (e.g. inside child
// component's mounted hook), which relies on vm._watcher being already defined
new Watcher(vm, updateComponent, noop, {
before: function before () {
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, 'beforeUpdate');
}
}
}, true /* isRenderWatcher */);
hydrating = false;
// manually mounted instance, call mounted on self
// mounted is called for render-created child components in its inserted hook
if (vm.$vnode == null) {
vm._isMounted = true;
callHook(vm, 'mounted');
}
return vm
}
function updateChildComponent (
vm,
propsData,
listeners,
parentVnode,
renderChildren
) {
{
isUpdatingChildComponent = true;
}
// determine whether component has slot children
// we need to do this before overwriting $options._renderChildren.
// check if there are dynamic scopedSlots (hand-written or compiled but with
// dynamic slot names). Static scoped slots compiled from template has the
// "$stable" marker.
var newScopedSlots = parentVnode.data.scopedSlots;
var oldScopedSlots = vm.$scopedSlots;
var hasDynamicScopedSlot = !!(
(newScopedSlots && !newScopedSlots.$stable) ||
(oldScopedSlots !== emptyObject && !oldScopedSlots.$stable) ||
(newScopedSlots && vm.$scopedSlots.$key !== newScopedSlots.$key) ||
(!newScopedSlots && vm.$scopedSlots.$key)
);
// Any static slot children from the parent may have changed during parent's
// update. Dynamic scoped slots may also have changed. In such cases, a forced
// update is necessary to ensure correctness.
var needsForceUpdate = !!(
renderChildren || // has new static slots
vm.$options._renderChildren || // has old static slots
hasDynamicScopedSlot
);
vm.$options._parentVnode = parentVnode;
vm.$vnode = parentVnode; // update vm's placeholder node without re-render
if (vm._vnode) { // update child tree's parent
vm._vnode.parent = parentVnode;
}
vm.$options._renderChildren = renderChildren;
// update $attrs and $listeners hash
// these are also reactive so they may trigger child update if the child
// used them during render
vm.$attrs = parentVnode.data.attrs || emptyObject;
vm.$listeners = listeners || emptyObject;
// update props
if (propsData && vm.$options.props) {
toggleObserving(false);
var props = vm._props;
var propKeys = vm.$options._propKeys || [];
for (var i = 0; i < propKeys.length; i++) {
var key = propKeys[i];
var propOptions = vm.$options.props; // wtf flow?
props[key] = validateProp(key, propOptions, propsData, vm);
}
toggleObserving(true);
// keep a copy of raw propsData
vm.$options.propsData = propsData;
}
// update listeners
listeners = listeners || emptyObject;
var oldListeners = vm.$options._parentListeners;
vm.$options._parentListeners = listeners;
updateComponentListeners(vm, listeners, oldListeners);
// resolve slots + force update if has children
if (needsForceUpdate) {
vm.$slots = resolveSlots(renderChildren, parentVnode.context);
vm.$forceUpdate();
}
{
isUpdatingChildComponent = false;
}
}
function isInInactiveTree (vm) {
while (vm && (vm = vm.$parent)) {
if (vm._inactive) { return true }
}
return false
}
function activateChildComponent (vm, direct) {
if (direct) {
vm._directInactive = false;
if (isInInactiveTree(vm)) {
return
}
} else if (vm._directInactive) {
return
}
if (vm._inactive || vm._inactive === null) {
vm._inactive = false;
for (var i = 0; i < vm.$children.length; i++) {
activateChildComponent(vm.$children[i]);
}
callHook(vm, 'activated');
}
}
function deactivateChildComponent (vm, direct) {
if (direct) {
vm._directInactive = true;
if (isInInactiveTree(vm)) {
return
}
}
if (!vm._inactive) {
vm._inactive = true;
for (var i = 0; i < vm.$children.length; i++) {
deactivateChildComponent(vm.$children[i]);
}
callHook(vm, 'deactivated');
}
}
function callHook (vm, hook) {
// #7573 disable dep collection when invoking lifecycle hooks
pushTarget();
var handlers = vm.$options[hook];
var info = hook + " hook";
if (handlers) {
for (var i = 0, j = handlers.length; i < j; i++) {
invokeWithErrorHandling(handlers[i], vm, null, vm, info);
}
}
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook);
}
popTarget();
}
/* */
var MAX_UPDATE_COUNT = 100;
var queue = [];
var activatedChildren = [];
var has = {};
var circular = {};
var waiting = false;
var flushing = false;
var index = 0;
/**
* Reset the scheduler's state.
*/
function resetSchedulerState () {
index = queue.length = activatedChildren.length = 0;
has = {};
{
circular = {};
}
waiting = flushing = false;
}
// Async edge case #6566 requires saving the timestamp when event listeners are
// attached. However, calling performance.now() has a perf overhead especially
// if the page has thousands of event listeners. Instead, we take a timestamp
// every time the scheduler flushes and use that for all event listeners
// attached during that flush.
var currentFlushTimestamp = 0;
// Async edge case fix requires storing an event listener's attach timestamp.
var getNow = Date.now;
// Determine what event timestamp the browser is using. Annoyingly, the
// timestamp can either be hi-res (relative to page load) or low-res
// (relative to UNIX epoch), so in order to compare time we have to use the
// same timestamp type when saving the flush timestamp.
// All IE versions use low-res event timestamps, and have problematic clock
// implementations (#9632)
if (inBrowser && !isIE) {
var performance = window.performance;
if (
performance &&
typeof performance.now === 'function' &&
getNow() > document.createEvent('Event').timeStamp
) {
// if the event timestamp, although evaluated AFTER the Date.now(), is
// smaller than it, it means the event is using a hi-res timestamp,
// and we need to use the hi-res version for event listener timestamps as
// well.
getNow = function () { return performance.now(); };
}
}
/**
* Flush both queues and run the watchers.
*/
function flushSchedulerQueue () {
currentFlushTimestamp = getNow();
flushing = true;
var watcher, id;
// Sort queue before flush.
// This ensures that:
// 1. Components are updated from parent to child. (because parent is always
// created before the child)
// 2. A component's user watchers are run before its render watcher (because
// user watchers are created before the render watcher)
// 3. If a component is destroyed during a parent component's watcher run,
// its watchers can be skipped.
queue.sort(function (a, b) { return a.id - b.id; });
// do not cache length because more watchers might be pushed
// as we run existing watchers
for (index = 0; index < queue.length; index++) {
watcher = queue[index];
if (watcher.before) {
watcher.before();
}
id = watcher.id;
has[id] = null;
watcher.run();
// in dev build, check and stop circular updates.
if (has[id] != null) {
circular[id] = (circular[id] || 0) + 1;
if (circular[id] > MAX_UPDATE_COUNT) {
warn(
'You may have an infinite update loop ' + (
watcher.user
? ("in watcher with expression \"" + (watcher.expression) + "\"")
: "in a component render function."
),
watcher.vm
);
break
}
}
}
// keep copies of post queues before resetting state
var activatedQueue = activatedChildren.slice();
var updatedQueue = queue.slice();
resetSchedulerState();
// call component updated and activated hooks
callActivatedHooks(activatedQueue);
callUpdatedHooks(updatedQueue);
// devtool hook
/* istanbul ignore if */
if (devtools && config.devtools) {
devtools.emit('flush');
}
}
function callUpdatedHooks (queue) {
var i = queue.length;
while (i--) {
var watcher = queue[i];
var vm = watcher.vm;
if (vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) {
callHook(vm, 'updated');
}
}
}
/**
* Queue a kept-alive component that was activated during patch.
* The queue will be processed after the entire tree has been patched.
*/
function queueActivatedComponent (vm) {
// setting _inactive to false here so that a render function can
// rely on checking whether it's in an inactive tree (e.g. router-view)
vm._inactive = false;
activatedChildren.push(vm);
}
function callActivatedHooks (queue) {
for (var i = 0; i < queue.length; i++) {
queue[i]._inactive = true;
activateChildComponent(queue[i], true /* true */);
}
}
/**
* Push a watcher into the watcher queue.
* Jobs with duplicate IDs will be skipped unless it's
* pushed when the queue is being flushed.
*/
function queueWatcher (watcher) {
var id = watcher.id;
if (has[id] == null) {
has[id] = true;
if (!flushing) {
queue.push(watcher);
} else {
// if already flushing, splice the watcher based on its id
// if already past its id, it will be run next immediately.
var i = queue.length - 1;
while (i > index && queue[i].id > watcher.id) {
i--;
}
queue.splice(i + 1, 0, watcher);
}
// queue the flush
if (!waiting) {
waiting = true;
if (!config.async) {
flushSchedulerQueue();
return
}
nextTick(flushSchedulerQueue);
}
}
}
/* */
var uid$2 = 0;
/**
* A watcher parses an expression, collects dependencies,
* and fires callback when the expression value changes.
* This is used for both the $watch() api and directives.
*/
var Watcher = function Watcher (
vm,
expOrFn,
cb,
options,
isRenderWatcher
) {
this.vm = vm;
if (isRenderWatcher) {
vm._watcher = this;
}
vm._watchers.push(this);
// options
if (options) {
this.deep = !!options.deep;
this.user = !!options.user;
this.lazy = !!options.lazy;
this.sync = !!options.sync;
this.before = options.before;
} else {
this.deep = this.user = this.lazy = this.sync = false;
}
this.cb = cb;
this.id = ++uid$2; // uid for batching
this.active = true;
this.dirty = this.lazy; // for lazy watchers
this.deps = [];
this.newDeps = [];
this.depIds = new _Set();
this.newDepIds = new _Set();
this.expression = expOrFn.toString();
// parse expression for getter
if (typeof expOrFn === 'function') {
this.getter = expOrFn;
} else {
this.getter = parsePath(expOrFn);
if (!this.getter) {
this.getter = noop;
warn(
"Failed watching path: \"" + expOrFn + "\" " +
'Watcher only accepts simple dot-delimited paths. ' +
'For full control, use a function instead.',
vm
);
}
}
this.value = this.lazy
? undefined
: this.get();
};
/**
* Evaluate the getter, and re-collect dependencies.
*/
Watcher.prototype.get = function get () {
pushTarget(this);
var value;
var vm = this.vm;
try {
value = this.getter.call(vm, vm);
} catch (e) {
if (this.user) {
handleError(e, vm, ("getter for watcher \"" + (this.expression) + "\""));
} else {
throw e
}
} finally {
// "touch" every property so they are all tracked as
// dependencies for deep watching
if (this.deep) {
traverse(value);
}
popTarget();
this.cleanupDeps();
}
return value
};
/**
* Add a dependency to this directive.
*/
Watcher.prototype.addDep = function addDep (dep) {
var id = dep.id;
if (!this.newDepIds.has(id)) {
this.newDepIds.add(id);
this.newDeps.push(dep);
if (!this.depIds.has(id)) {
dep.addSub(this);
}
}
};
/**
* Clean up for dependency collection.
*/
Watcher.prototype.cleanupDeps = function cleanupDeps () {
var i = this.deps.length;
while (i--) {
var dep = this.deps[i];
if (!this.newDepIds.has(dep.id)) {
dep.removeSub(this);
}
}
var tmp = this.depIds;
this.depIds = this.newDepIds;
this.newDepIds = tmp;
this.newDepIds.clear();
tmp = this.deps;
this.deps = this.newDeps;
this.newDeps = tmp;
this.newDeps.length = 0;
};
/**
* Subscriber interface.
* Will be called when a dependency changes.
*/
Watcher.prototype.update = function update () {
/* istanbul ignore else */
if (this.lazy) {
this.dirty = true;
} else if (this.sync) {
this.run();
} else {
queueWatcher(this);
}
};
/**
* Scheduler job interface.
* Will be called by the scheduler.
*/
Watcher.prototype.run = function run () {
if (this.active) {
var value = this.get();
if (
value !== this.value ||
// Deep watchers and watchers on Object/Arrays should fire even
// when the value is the same, because the value may
// have mutated.
isObject(value) ||
this.deep
) {
// set new value
var oldValue = this.value;
this.value = value;
if (this.user) {
var info = "callback for watcher \"" + (this.expression) + "\"";
invokeWithErrorHandling(this.cb, this.vm, [value, oldValue], this.vm, info);
} else {
this.cb.call(this.vm, value, oldValue);
}
}
}
};
/**
* Evaluate the value of the watcher.
* This only gets called for lazy watchers.
*/
Watcher.prototype.evaluate = function evaluate () {
this.value = this.get();
this.dirty = false;
};
/**
* Depend on all deps collected by this watcher.
*/
Watcher.prototype.depend = function depend () {
var i = this.deps.length;
while (i--) {
this.deps[i].depend();
}
};
/**
* Remove self from all dependencies' subscriber list.
*/
Watcher.prototype.teardown = function teardown () {
if (this.active) {
// remove self from vm's watcher list
// this is a somewhat expensive operation so we skip it
// if the vm is being destroyed.
if (!this.vm._isBeingDestroyed) {
remove(this.vm._watchers, this);
}
var i = this.deps.length;
while (i--) {
this.deps[i].removeSub(this);
}
this.active = false;
}
};
/* */
var sharedPropertyDefinition = {
enumerable: true,
configurable: true,
get: noop,
set: noop
};
function proxy (target, sourceKey, key) {
sharedPropertyDefinition.get = function proxyGetter () {
return this[sourceKey][key]
};
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val;
};
Object.defineProperty(target, key, sharedPropertyDefinition);
}
function initState (vm) {
vm._watchers = [];
var opts = vm.$options;
if (opts.props) { initProps(vm, opts.props); }
if (opts.methods) { initMethods(vm, opts.methods); }
if (opts.data) {
initData(vm);
} else {
observe(vm._data = {}, true /* asRootData */);
}
if (opts.computed) { initComputed(vm, opts.computed); }
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch);
}
}
function initProps (vm, propsOptions) {
var propsData = vm.$options.propsData || {};
var props = vm._props = {};
// cache prop keys so that future props updates can iterate using Array
// instead of dynamic object key enumeration.
var keys = vm.$options._propKeys = [];
var isRoot = !vm.$parent;
// root instance props should be converted
if (!isRoot) {
toggleObserving(false);
}
var loop = function ( key ) {
keys.push(key);
var value = validateProp(key, propsOptions, propsData, vm);
/* istanbul ignore else */
{
var hyphenatedKey = hyphenate(key);
if (isReservedAttribute(hyphenatedKey) ||
config.isReservedAttr(hyphenatedKey)) {
warn(
("\"" + hyphenatedKey + "\" is a reserved attribute and cannot be used as component prop."),
vm
);
}
defineReactive$$1(props, key, value, function () {
if (!isRoot && !isUpdatingChildComponent) {
warn(
"Avoid mutating a prop directly since the value will be " +
"overwritten whenever the parent component re-renders. " +
"Instead, use a data or computed property based on the prop's " +
"value. Prop being mutated: \"" + key + "\"",
vm
);
}
});
}
// static props are already proxied on the component's prototype
// during Vue.extend(). We only need to proxy props defined at
// instantiation here.
if (!(key in vm)) {
proxy(vm, "_props", key);
}
};
for (var key in propsOptions) loop( key );
toggleObserving(true);
}
function initData (vm) {
var data = vm.$options.data;
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {};
if (!isPlainObject(data)) {
data = {};
warn(
'data functions should return an object:\n' +
'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
vm
);
}
// proxy data on instance
var keys = Object.keys(data);
var props = vm.$options.props;
var methods = vm.$options.methods;
var i = keys.length;
while (i--) {
var key = keys[i];
{
if (methods && hasOwn(methods, key)) {
warn(
("Method \"" + key + "\" has already been defined as a data property."),
vm
);
}
}
if (props && hasOwn(props, key)) {
warn(
"The data property \"" + key + "\" is already declared as a prop. " +
"Use prop default value instead.",
vm
);
} else if (!isReserved(key)) {
proxy(vm, "_data", key);
}
}
// observe data
observe(data, true /* asRootData */);
}
function getData (data, vm) {
// #7573 disable dep collection when invoking data getters
pushTarget();
try {
return data.call(vm, vm)
} catch (e) {
handleError(e, vm, "data()");
return {}
} finally {
popTarget();
}
}
var computedWatcherOptions = { lazy: true };
function initComputed (vm, computed) {
// $flow-disable-line
var watchers = vm._computedWatchers = Object.create(null);
// computed properties are just getters during SSR
var isSSR = isServerRendering();
for (var key in computed) {
var userDef = computed[key];
var getter = typeof userDef === 'function' ? userDef : userDef.get;
if (getter == null) {
warn(
("Getter is missing for computed property \"" + key + "\"."),
vm
);
}
if (!isSSR) {
// create internal watcher for the computed property.
watchers[key] = new Watcher(
vm,
getter || noop,
noop,
computedWatcherOptions
);
}
// component-defined computed properties are already defined on the
// component prototype. We only need to define computed properties defined
// at instantiation here.
if (!(key in vm)) {
defineComputed(vm, key, userDef);
} else {
if (key in vm.$data) {
warn(("The computed property \"" + key + "\" is already defined in data."), vm);
} else if (vm.$options.props && key in vm.$options.props) {
warn(("The computed property \"" + key + "\" is already defined as a prop."), vm);
} else if (vm.$options.methods && key in vm.$options.methods) {
warn(("The computed property \"" + key + "\" is already defined as a method."), vm);
}
}
}
}
function defineComputed (
target,
key,
userDef
) {
var shouldCache = !isServerRendering();
if (typeof userDef === 'function') {
sharedPropertyDefinition.get = shouldCache
? createComputedGetter(key)
: createGetterInvoker(userDef);
sharedPropertyDefinition.set = noop;
} else {
sharedPropertyDefinition.get = userDef.get
? shouldCache && userDef.cache !== false
? createComputedGetter(key)
: createGetterInvoker(userDef.get)
: noop;
sharedPropertyDefinition.set = userDef.set || noop;
}
if (sharedPropertyDefinition.set === noop) {
sharedPropertyDefinition.set = function () {
warn(
("Computed property \"" + key + "\" was assigned to but it has no setter."),
this
);
};
}
Object.defineProperty(target, key, sharedPropertyDefinition);
}
function createComputedGetter (key) {
return function computedGetter () {
var watcher = this._computedWatchers && this._computedWatchers[key];
if (watcher) {
if (watcher.dirty) {
watcher.evaluate();
}
if (Dep.target) {
watcher.depend();
}
return watcher.value
}
}
}
function createGetterInvoker(fn) {
return function computedGetter () {
return fn.call(this, this)
}
}
function initMethods (vm, methods) {
var props = vm.$options.props;
for (var key in methods) {
{
if (typeof methods[key] !== 'function') {
warn(
"Method \"" + key + "\" has type \"" + (typeof methods[key]) + "\" in the component definition. " +
"Did you reference the function correctly?",
vm
);
}
if (props && hasOwn(props, key)) {
warn(
("Method \"" + key + "\" has already been defined as a prop."),
vm
);
}
if ((key in vm) && isReserved(key)) {
warn(
"Method \"" + key + "\" conflicts with an existing Vue instance method. " +
"Avoid defining component methods that start with _ or $."
);
}
}
vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);
}
}
function initWatch (vm, watch) {
for (var key in watch) {
var handler = watch[key];
if (Array.isArray(handler)) {
for (var i = 0; i < handler.length; i++) {
createWatcher(vm, key, handler[i]);
}
} else {
createWatcher(vm, key, handler);
}
}
}
function createWatcher (
vm,
expOrFn,
handler,
options
) {
if (isPlainObject(handler)) {
options = handler;
handler = handler.handler;
}
if (typeof handler === 'string') {
handler = vm[handler];
}
return vm.$watch(expOrFn, handler, options)
}
function stateMixin (Vue) {
// flow somehow has problems with directly declared definition object
// when using Object.defineProperty, so we have to procedurally build up
// the object here.
var dataDef = {};
dataDef.get = function () { return this._data };
var propsDef = {};
propsDef.get = function () { return this._props };
{
dataDef.set = function () {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
);
};
propsDef.set = function () {
warn("$props is readonly.", this);
};
}
Object.defineProperty(Vue.prototype, '$data', dataDef);
Object.defineProperty(Vue.prototype, '$props', propsDef);
Vue.prototype.$set = set;
Vue.prototype.$delete = del;
Vue.prototype.$watch = function (
expOrFn,
cb,
options
) {
var vm = this;
if (isPlainObject(cb)) {
return createWatcher(vm, expOrFn, cb, options)
}
options = options || {};
options.user = true;
var watcher = new Watcher(vm, expOrFn, cb, options);
if (options.immediate) {
var info = "callback for immediate watcher \"" + (watcher.expression) + "\"";
pushTarget();
invokeWithErrorHandling(cb, vm, [watcher.value], vm, info);
popTarget();
}
return function unwatchFn () {
watcher.teardown();
}
};
}
/* */
var uid$3 = 0;
function initMixin (Vue) {
Vue.prototype._init = function (options) {
var vm = this;
// a uid
vm._uid = uid$3++;
var startTag, endTag;
/* istanbul ignore if */
if (config.performance && mark) {
startTag = "vue-perf-start:" + (vm._uid);
endTag = "vue-perf-end:" + (vm._uid);
mark(startTag);
}
// a flag to avoid this being observed
vm._isVue = true;
// merge options
if (options && options._isComponent) {
// optimize internal component instantiation
// since dynamic options merging is pretty slow, and none of the
// internal component options needs special treatment.
initInternalComponent(vm, options);
} else {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
}
/* istanbul ignore else */
{
initProxy(vm);
}
// expose real self
vm._self = vm;
initLifecycle(vm);
initEvents(vm);
initRender(vm);
callHook(vm, 'beforeCreate');
initInjections(vm); // resolve injections before data/props
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook(vm, 'created');
/* istanbul ignore if */
if (config.performance && mark) {
vm._name = formatComponentName(vm, false);
mark(endTag);
measure(("vue " + (vm._name) + " init"), startTag, endTag);
}
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
};
}
function initInternalComponent (vm, options) {
var opts = vm.$options = Object.create(vm.constructor.options);
// doing this because it's faster than dynamic enumeration.
var parentVnode = options._parentVnode;
opts.parent = options.parent;
opts._parentVnode = parentVnode;
var vnodeComponentOptions = parentVnode.componentOptions;
opts.propsData = vnodeComponentOptions.propsData;
opts._parentListeners = vnodeComponentOptions.listeners;
opts._renderChildren = vnodeComponentOptions.children;
opts._componentTag = vnodeComponentOptions.tag;
if (options.render) {
opts.render = options.render;
opts.staticRenderFns = options.staticRenderFns;
}
}
function resolveConstructorOptions (Ctor) {
var options = Ctor.options;
if (Ctor.super) {
var superOptions = resolveConstructorOptions(Ctor.super);
var cachedSuperOptions = Ctor.superOptions;
if (superOptions !== cachedSuperOptions) {
// super option changed,
// need to resolve new options.
Ctor.superOptions = superOptions;
// check if there are any late-modified/attached options (#4976)
var modifiedOptions = resolveModifiedOptions(Ctor);
// update base extend options
if (modifiedOptions) {
extend(Ctor.extendOptions, modifiedOptions);
}
options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions);
if (options.name) {
options.components[options.name] = Ctor;
}
}
}
return options
}
function resolveModifiedOptions (Ctor) {
var modified;
var latest = Ctor.options;
var sealed = Ctor.sealedOptions;
for (var key in latest) {
if (latest[key] !== sealed[key]) {
if (!modified) { modified = {}; }
modified[key] = latest[key];
}
}
return modified
}
function Vue (options) {
if (!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword');
}
this._init(options);
}
initMixin(Vue);
stateMixin(Vue);
eventsMixin(Vue);
lifecycleMixin(Vue);
renderMixin(Vue);
/* */
function initUse (Vue) {
Vue.use = function (plugin) {
var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
var args = toArray(arguments, 1);
args.unshift(this);
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args);
} else if (typeof plugin === 'function') {
plugin.apply(null, args);
}
installedPlugins.push(plugin);
return this
};
}
/* */
function initMixin$1 (Vue) {
Vue.mixin = function (mixin) {
this.options = mergeOptions(this.options, mixin);
return this
};
}
/* */
function initExtend (Vue) {
/**
* Each instance constructor, including Vue, has a unique
* cid. This enables us to create wrapped "child
* constructors" for prototypal inheritance and cache them.
*/
Vue.cid = 0;
var cid = 1;
/**
* Class inheritance
*/
Vue.extend = function (extendOptions) {
extendOptions = extendOptions || {};
var Super = this;
var SuperId = Super.cid;
var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {});
if (cachedCtors[SuperId]) {
return cachedCtors[SuperId]
}
var name = extendOptions.name || Super.options.name;
if (name) {
validateComponentName(name);
}
var Sub = function VueComponent (options) {
this._init(options);
};
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
Sub.cid = cid++;
Sub.options = mergeOptions(
Super.options,
extendOptions
);
Sub['super'] = Super;
// For props and computed properties, we define the proxy getters on
// the Vue instances at extension time, on the extended prototype. This
// avoids Object.defineProperty calls for each instance created.
if (Sub.options.props) {
initProps$1(Sub);
}
if (Sub.options.computed) {
initComputed$1(Sub);
}
// allow further extension/mixin/plugin usage
Sub.extend = Super.extend;
Sub.mixin = Super.mixin;
Sub.use = Super.use;
// create asset registers, so extended classes
// can have their private assets too.
ASSET_TYPES.forEach(function (type) {
Sub[type] = Super[type];
});
// enable recursive self-lookup
if (name) {
Sub.options.components[name] = Sub;
}
// keep a reference to the super options at extension time.
// later at instantiation we can check if Super's options have
// been updated.
Sub.superOptions = Super.options;
Sub.extendOptions = extendOptions;
Sub.sealedOptions = extend({}, Sub.options);
// cache constructor
cachedCtors[SuperId] = Sub;
return Sub
};
}
function initProps$1 (Comp) {
var props = Comp.options.props;
for (var key in props) {
proxy(Comp.prototype, "_props", key);
}
}
function initComputed$1 (Comp) {
var computed = Comp.options.computed;
for (var key in computed) {
defineComputed(Comp.prototype, key, computed[key]);
}
}
/* */
function initAssetRegisters (Vue) {
/**
* Create asset registration methods.
*/
ASSET_TYPES.forEach(function (type) {
Vue[type] = function (
id,
definition
) {
if (!definition) {
return this.options[type + 's'][id]
} else {
/* istanbul ignore if */
if (type === 'component') {
validateComponentName(id);
}
if (type === 'component' && isPlainObject(definition)) {
definition.name = definition.name || id;
definition = this.options._base.extend(definition);
}
if (type === 'directive' && typeof definition === 'function') {
definition = { bind: definition, update: definition };
}
this.options[type + 's'][id] = definition;
return definition
}
};
});
}
/* */
function getComponentName (opts) {
return opts && (opts.Ctor.options.name || opts.tag)
}
function matches (pattern, name) {
if (Array.isArray(pattern)) {
return pattern.indexOf(name) > -1
} else if (typeof pattern === 'string') {
return pattern.split(',').indexOf(name) > -1
} else if (isRegExp(pattern)) {
return pattern.test(name)
}
/* istanbul ignore next */
return false
}
function pruneCache (keepAliveInstance, filter) {
var cache = keepAliveInstance.cache;
var keys = keepAliveInstance.keys;
var _vnode = keepAliveInstance._vnode;
for (var key in cache) {
var entry = cache[key];
if (entry) {
var name = entry.name;
if (name && !filter(name)) {
pruneCacheEntry(cache, key, keys, _vnode);
}
}
}
}
function pruneCacheEntry (
cache,
key,
keys,
current
) {
var entry = cache[key];
if (entry && (!current || entry.tag !== current.tag)) {
entry.componentInstance.$destroy();
}
cache[key] = null;
remove(keys, key);
}
var patternTypes = [String, RegExp, Array];
var KeepAlive = {
name: 'keep-alive',
abstract: true,
props: {
include: patternTypes,
exclude: patternTypes,
max: [String, Number]
},
methods: {
cacheVNode: function cacheVNode() {
var ref = this;
var cache = ref.cache;
var keys = ref.keys;
var vnodeToCache = ref.vnodeToCache;
var keyToCache = ref.keyToCache;
if (vnodeToCache) {
var tag = vnodeToCache.tag;
var componentInstance = vnodeToCache.componentInstance;
var componentOptions = vnodeToCache.componentOptions;
cache[keyToCache] = {
name: getComponentName(componentOptions),
tag: tag,
componentInstance: componentInstance,
};
keys.push(keyToCache);
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode);
}
this.vnodeToCache = null;
}
}
},
created: function created () {
this.cache = Object.create(null);
this.keys = [];
},
destroyed: function destroyed () {
for (var key in this.cache) {
pruneCacheEntry(this.cache, key, this.keys);
}
},
mounted: function mounted () {
var this$1 = this;
this.cacheVNode();
this.$watch('include', function (val) {
pruneCache(this$1, function (name) { return matches(val, name); });
});
this.$watch('exclude', function (val) {
pruneCache(this$1, function (name) { return !matches(val, name); });
});
},
updated: function updated () {
this.cacheVNode();
},
render: function render () {
var slot = this.$slots.default;
var vnode = getFirstComponentChild(slot);
var componentOptions = vnode && vnode.componentOptions;
if (componentOptions) {
// check pattern
var name = getComponentName(componentOptions);
var ref = this;
var include = ref.include;
var exclude = ref.exclude;
if (
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))
) {
return vnode
}
var ref$1 = this;
var cache = ref$1.cache;
var keys = ref$1.keys;
var key = vnode.key == null
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid + (componentOptions.tag ? ("::" + (componentOptions.tag)) : '')
: vnode.key;
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance;
// make current key freshest
remove(keys, key);
keys.push(key);
} else {
// delay setting the cache until update
this.vnodeToCache = vnode;
this.keyToCache = key;
}
vnode.data.keepAlive = true;
}
return vnode || (slot && slot[0])
}
};
var builtInComponents = {
KeepAlive: KeepAlive
};
/* */
function initGlobalAPI (Vue) {
// config
var configDef = {};
configDef.get = function () { return config; };
{
configDef.set = function () {
warn(
'Do not replace the Vue.config object, set individual fields instead.'
);
};
}
Object.defineProperty(Vue, 'config', configDef);
// exposed util methods.
// NOTE: these are not considered part of the public API - avoid relying on
// them unless you are aware of the risk.
Vue.util = {
warn: warn,
extend: extend,
mergeOptions: mergeOptions,
defineReactive: defineReactive$$1
};
Vue.set = set;
Vue.delete = del;
Vue.nextTick = nextTick;
// 2.6 explicit observable API
Vue.observable = function (obj) {
observe(obj);
return obj
};
Vue.options = Object.create(null);
ASSET_TYPES.forEach(function (type) {
Vue.options[type + 's'] = Object.create(null);
});
// this is used to identify the "base" constructor to extend all plain-object
// components with in Weex's multi-instance scenarios.
Vue.options._base = Vue;
extend(Vue.options.components, builtInComponents);
initUse(Vue);
initMixin$1(Vue);
initExtend(Vue);
initAssetRegisters(Vue);
}
initGlobalAPI(Vue);
Object.defineProperty(Vue.prototype, '$isServer', {
get: isServerRendering
});
Object.defineProperty(Vue.prototype, '$ssrContext', {
get: function get () {
/* istanbul ignore next */
return this.$vnode && this.$vnode.ssrContext
}
});
// expose FunctionalRenderContext for ssr runtime helper installation
Object.defineProperty(Vue, 'FunctionalRenderContext', {
value: FunctionalRenderContext
});
Vue.version = '2.6.14';
/* */
// these are reserved for web because they are directly compiled away
// during template compilation
var isReservedAttr = makeMap('style,class');
// attributes that should be using props for binding
var acceptValue = makeMap('input,textarea,option,select,progress');
var mustUseProp = function (tag, type, attr) {
return (
(attr === 'value' && acceptValue(tag)) && type !== 'button' ||
(attr === 'selected' && tag === 'option') ||
(attr === 'checked' && tag === 'input') ||
(attr === 'muted' && tag === 'video')
)
};
var isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck');
var isValidContentEditableValue = makeMap('events,caret,typing,plaintext-only');
var convertEnumeratedValue = function (key, value) {
return isFalsyAttrValue(value) || value === 'false'
? 'false'
// allow arbitrary string value for contenteditable
: key === 'contenteditable' && isValidContentEditableValue(value)
? value
: 'true'
};
var isBooleanAttr = makeMap(
'allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' +
'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' +
'enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,' +
'muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,' +
'required,reversed,scoped,seamless,selected,sortable,' +
'truespeed,typemustmatch,visible'
);
var xlinkNS = 'http://www.w3.org/1999/xlink';
var isXlink = function (name) {
return name.charAt(5) === ':' && name.slice(0, 5) === 'xlink'
};
var getXlinkProp = function (name) {
return isXlink(name) ? name.slice(6, name.length) : ''
};
var isFalsyAttrValue = function (val) {
return val == null || val === false
};
/* */
function genClassForVnode (vnode) {
var data = vnode.data;
var parentNode = vnode;
var childNode = vnode;
while (isDef(childNode.componentInstance)) {
childNode = childNode.componentInstance._vnode;
if (childNode && childNode.data) {
data = mergeClassData(childNode.data, data);
}
}
while (isDef(parentNode = parentNode.parent)) {
if (parentNode && parentNode.data) {
data = mergeClassData(data, parentNode.data);
}
}
return renderClass(data.staticClass, data.class)
}
function mergeClassData (child, parent) {
return {
staticClass: concat(child.staticClass, parent.staticClass),
class: isDef(child.class)
? [child.class, parent.class]
: parent.class
}
}
function renderClass (
staticClass,
dynamicClass
) {
if (isDef(staticClass) || isDef(dynamicClass)) {
return concat(staticClass, stringifyClass(dynamicClass))
}
/* istanbul ignore next */
return ''
}
function concat (a, b) {
return a ? b ? (a + ' ' + b) : a : (b || '')
}
function stringifyClass (value) {
if (Array.isArray(value)) {
return stringifyArray(value)
}
if (isObject(value)) {
return stringifyObject(value)
}
if (typeof value === 'string') {
return value
}
/* istanbul ignore next */
return ''
}
function stringifyArray (value) {
var res = '';
var stringified;
for (var i = 0, l = value.length; i < l; i++) {
if (isDef(stringified = stringifyClass(value[i])) && stringified !== '') {
if (res) { res += ' '; }
res += stringified;
}
}
return res
}
function stringifyObject (value) {
var res = '';
for (var key in value) {
if (value[key]) {
if (res) { res += ' '; }
res += key;
}
}
return res
}
/* */
var namespaceMap = {
svg: 'http://www.w3.org/2000/svg',
math: 'http://www.w3.org/1998/Math/MathML'
};
var isHTMLTag = makeMap(
'html,body,base,head,link,meta,style,title,' +
'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' +
'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' +
'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' +
's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' +
'embed,object,param,source,canvas,script,noscript,del,ins,' +
'caption,col,colgroup,table,thead,tbody,td,th,tr,' +
'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' +
'output,progress,select,textarea,' +
'details,dialog,menu,menuitem,summary,' +
'content,element,shadow,template,blockquote,iframe,tfoot'
);
// this map is intentionally selective, only covering SVG elements that may
// contain child elements.
var isSVG = makeMap(
'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' +
'foreignobject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' +
'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view',
true
);
var isPreTag = function (tag) { return tag === 'pre'; };
var isReservedTag = function (tag) {
return isHTMLTag(tag) || isSVG(tag)
};
function getTagNamespace (tag) {
if (isSVG(tag)) {
return 'svg'
}
// basic support for MathML
// note it doesn't support other MathML elements being component roots
if (tag === 'math') {
return 'math'
}
}
var unknownElementCache = Object.create(null);
function isUnknownElement (tag) {
/* istanbul ignore if */
if (!inBrowser) {
return true
}
if (isReservedTag(tag)) {
return false
}
tag = tag.toLowerCase();
/* istanbul ignore if */
if (unknownElementCache[tag] != null) {
return unknownElementCache[tag]
}
var el = document.createElement(tag);
if (tag.indexOf('-') > -1) {
// http://stackoverflow.com/a/28210364/1070244
return (unknownElementCache[tag] = (
el.constructor === window.HTMLUnknownElement ||
el.constructor === window.HTMLElement
))
} else {
return (unknownElementCache[tag] = /HTMLUnknownElement/.test(el.toString()))
}
}
var isTextInputType = makeMap('text,number,password,search,email,tel,url');
/* */
/**
* Query an element selector if it's not an element already.
*/
function query (el) {
if (typeof el === 'string') {
var selected = document.querySelector(el);
if (!selected) {
warn(
'Cannot find element: ' + el
);
return document.createElement('div')
}
return selected
} else {
return el
}
}
/* */
function createElement$1 (tagName, vnode) {
var elm = document.createElement(tagName);
if (tagName !== 'select') {
return elm
}
// false or null will remove the attribute but undefined will not
if (vnode.data && vnode.data.attrs && vnode.data.attrs.multiple !== undefined) {
elm.setAttribute('multiple', 'multiple');
}
return elm
}
function createElementNS (namespace, tagName) {
return document.createElementNS(namespaceMap[namespace], tagName)
}
function createTextNode (text) {
return document.createTextNode(text)
}
function createComment (text) {
return document.createComment(text)
}
function insertBefore (parentNode, newNode, referenceNode) {
parentNode.insertBefore(newNode, referenceNode);
}
function removeChild (node, child) {
node.removeChild(child);
}
function appendChild (node, child) {
node.appendChild(child);
}
function parentNode (node) {
return node.parentNode
}
function nextSibling (node) {
return node.nextSibling
}
function tagName (node) {
return node.tagName
}
function setTextContent (node, text) {
node.textContent = text;
}
function setStyleScope (node, scopeId) {
node.setAttribute(scopeId, '');
}
var nodeOps = /*#__PURE__*/Object.freeze({
createElement: createElement$1,
createElementNS: createElementNS,
createTextNode: createTextNode,
createComment: createComment,
insertBefore: insertBefore,
removeChild: removeChild,
appendChild: appendChild,
parentNode: parentNode,
nextSibling: nextSibling,
tagName: tagName,
setTextContent: setTextContent,
setStyleScope: setStyleScope
});
/* */
var ref = {
create: function create (_, vnode) {
registerRef(vnode);
},
update: function update (oldVnode, vnode) {
if (oldVnode.data.ref !== vnode.data.ref) {
registerRef(oldVnode, true);
registerRef(vnode);
}
},
destroy: function destroy (vnode) {
registerRef(vnode, true);
}
};
function registerRef (vnode, isRemoval) {
var key = vnode.data.ref;
if (!isDef(key)) { return }
var vm = vnode.context;
var ref = vnode.componentInstance || vnode.elm;
var refs = vm.$refs;
if (isRemoval) {
if (Array.isArray(refs[key])) {
remove(refs[key], ref);
} else if (refs[key] === ref) {
refs[key] = undefined;
}
} else {
if (vnode.data.refInFor) {
if (!Array.isArray(refs[key])) {
refs[key] = [ref];
} else if (refs[key].indexOf(ref) < 0) {
// $flow-disable-line
refs[key].push(ref);
}
} else {
refs[key] = ref;
}
}
}
/**
* Virtual DOM patching algorithm based on Snabbdom by
* Simon Friis Vindum (@paldepind)
* Licensed under the MIT License
* https://github.com/paldepind/snabbdom/blob/master/LICENSE
*
* modified by Evan You (@yyx990803)
*
* Not type-checking this because this file is perf-critical and the cost
* of making flow understand it is not worth it.
*/
var emptyNode = new VNode('', {}, []);
var hooks = ['create', 'activate', 'update', 'remove', 'destroy'];
function sameVnode (a, b) {
return (
a.key === b.key &&
a.asyncFactory === b.asyncFactory && (
(
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
) || (
isTrue(a.isAsyncPlaceholder) &&
isUndef(b.asyncFactory.error)
)
)
)
}
function sameInputType (a, b) {
if (a.tag !== 'input') { return true }
var i;
var typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type;
var typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type;
return typeA === typeB || isTextInputType(typeA) && isTextInputType(typeB)
}
function createKeyToOldIdx (children, beginIdx, endIdx) {
var i, key;
var map = {};
for (i = beginIdx; i <= endIdx; ++i) {
key = children[i].key;
if (isDef(key)) { map[key] = i; }
}
return map
}
function createPatchFunction (backend) {
var i, j;
var cbs = {};
var modules = backend.modules;
var nodeOps = backend.nodeOps;
for (i = 0; i < hooks.length; ++i) {
cbs[hooks[i]] = [];
for (j = 0; j < modules.length; ++j) {
if (isDef(modules[j][hooks[i]])) {
cbs[hooks[i]].push(modules[j][hooks[i]]);
}
}
}
function emptyNodeAt (elm) {
return new VNode(nodeOps.tagName(elm).toLowerCase(), {}, [], undefined, elm)
}
function createRmCb (childElm, listeners) {
function remove$$1 () {
if (--remove$$1.listeners === 0) {
removeNode(childElm);
}
}
remove$$1.listeners = listeners;
return remove$$1
}
function removeNode (el) {
var parent = nodeOps.parentNode(el);
// element may have already been removed due to v-html / v-text
if (isDef(parent)) {
nodeOps.removeChild(parent, el);
}
}
function isUnknownElement$$1 (vnode, inVPre) {
return (
!inVPre &&
!vnode.ns &&
!(
config.ignoredElements.length &&
config.ignoredElements.some(function (ignore) {
return isRegExp(ignore)
? ignore.test(vnode.tag)
: ignore === vnode.tag
})
) &&
config.isUnknownElement(vnode.tag)
)
}
var creatingElmInVPre = 0;
function createElm (
vnode,
insertedVnodeQueue,
parentElm,
refElm,
nested,
ownerArray,
index
) {
if (isDef(vnode.elm) && isDef(ownerArray)) {
// This vnode was used in a previous render!
// now it's used as a new node, overwriting its elm would cause
// potential patch errors down the road when it's used as an insertion
// reference node. Instead, we clone the node on-demand before creating
// associated DOM element for it.
vnode = ownerArray[index] = cloneVNode(vnode);
}
vnode.isRootInsert = !nested; // for transition enter check
if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
return
}
var data = vnode.data;
var children = vnode.children;
var tag = vnode.tag;
if (isDef(tag)) {
{
if (data && data.pre) {
creatingElmInVPre++;
}
if (isUnknownElement$$1(vnode, creatingElmInVPre)) {
warn(
'Unknown custom element: <' + tag + '> - did you ' +
'register the component correctly? For recursive components, ' +
'make sure to provide the "name" option.',
vnode.context
);
}
}
vnode.elm = vnode.ns
? nodeOps.createElementNS(vnode.ns, tag)
: nodeOps.createElement(tag, vnode);
setScope(vnode);
/* istanbul ignore if */
{
createChildren(vnode, children, insertedVnodeQueue);
if (isDef(data)) {
invokeCreateHooks(vnode, insertedVnodeQueue);
}
insert(parentElm, vnode.elm, refElm);
}
if (data && data.pre) {
creatingElmInVPre--;
}
} else if (isTrue(vnode.isComment)) {
vnode.elm = nodeOps.createComment(vnode.text);
insert(parentElm, vnode.elm, refElm);
} else {
vnode.elm = nodeOps.createTextNode(vnode.text);
insert(parentElm, vnode.elm, refElm);
}
}
function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {
var i = vnode.data;
if (isDef(i)) {
var isReactivated = isDef(vnode.componentInstance) && i.keepAlive;
if (isDef(i = i.hook) && isDef(i = i.init)) {
i(vnode, false /* hydrating */);
}
// after calling the init hook, if the vnode is a child component
// it should've created a child instance and mounted it. the child
// component also has set the placeholder vnode's elm.
// in that case we can just return the element and be done.
if (isDef(vnode.componentInstance)) {
initComponent(vnode, insertedVnodeQueue);
insert(parentElm, vnode.elm, refElm);
if (isTrue(isReactivated)) {
reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm);
}
return true
}
}
}
function initComponent (vnode, insertedVnodeQueue) {
if (isDef(vnode.data.pendingInsert)) {
insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert);
vnode.data.pendingInsert = null;
}
vnode.elm = vnode.componentInstance.$el;
if (isPatchable(vnode)) {
invokeCreateHooks(vnode, insertedVnodeQueue);
setScope(vnode);
} else {
// empty component root.
// skip all element-related modules except for ref (#3455)
registerRef(vnode);
// make sure to invoke the insert hook
insertedVnodeQueue.push(vnode);
}
}
function reactivateComponent (vnode, insertedVnodeQueue, parentElm, refElm) {
var i;
// hack for #4339: a reactivated component with inner transition
// does not trigger because the inner node's created hooks are not called
// again. It's not ideal to involve module-specific logic in here but
// there doesn't seem to be a better way to do it.
var innerNode = vnode;
while (innerNode.componentInstance) {
innerNode = innerNode.componentInstance._vnode;
if (isDef(i = innerNode.data) && isDef(i = i.transition)) {
for (i = 0; i < cbs.activate.length; ++i) {
cbs.activate[i](emptyNode, innerNode);
}
insertedVnodeQueue.push(innerNode);
break
}
}
// unlike a newly created component,
// a reactivated keep-alive component doesn't insert itself
insert(parentElm, vnode.elm, refElm);
}
function insert (parent, elm, ref$$1) {
if (isDef(parent)) {
if (isDef(ref$$1)) {
if (nodeOps.parentNode(ref$$1) === parent) {
nodeOps.insertBefore(parent, elm, ref$$1);
}
} else {
nodeOps.appendChild(parent, elm);
}
}
}
function createChildren (vnode, children, insertedVnodeQueue) {
if (Array.isArray(children)) {
{
checkDuplicateKeys(children);
}
for (var i = 0; i < children.length; ++i) {
createElm(children[i], insertedVnodeQueue, vnode.elm, null, true, children, i);
}
} else if (isPrimitive(vnode.text)) {
nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(String(vnode.text)));
}
}
function isPatchable (vnode) {
while (vnode.componentInstance) {
vnode = vnode.componentInstance._vnode;
}
return isDef(vnode.tag)
}
function invokeCreateHooks (vnode, insertedVnodeQueue) {
for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {
cbs.create[i$1](emptyNode, vnode);
}
i = vnode.data.hook; // Reuse variable
if (isDef(i)) {
if (isDef(i.create)) { i.create(emptyNode, vnode); }
if (isDef(i.insert)) { insertedVnodeQueue.push(vnode); }
}
}
// set scope id attribute for scoped CSS.
// this is implemented as a special case to avoid the overhead
// of going through the normal attribute patching process.
function setScope (vnode) {
var i;
if (isDef(i = vnode.fnScopeId)) {
nodeOps.setStyleScope(vnode.elm, i);
} else {
var ancestor = vnode;
while (ancestor) {
if (isDef(i = ancestor.context) && isDef(i = i.$options._scopeId)) {
nodeOps.setStyleScope(vnode.elm, i);
}
ancestor = ancestor.parent;
}
}
// for slot content they should also get the scopeId from the host instance.
if (isDef(i = activeInstance) &&
i !== vnode.context &&
i !== vnode.fnContext &&
isDef(i = i.$options._scopeId)
) {
nodeOps.setStyleScope(vnode.elm, i);
}
}
function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {
for (; startIdx <= endIdx; ++startIdx) {
createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm, false, vnodes, startIdx);
}
}
function invokeDestroyHook (vnode) {
var i, j;
var data = vnode.data;
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.destroy)) { i(vnode); }
for (i = 0; i < cbs.destroy.length; ++i) { cbs.destroy[i](vnode); }
}
if (isDef(i = vnode.children)) {
for (j = 0; j < vnode.children.length; ++j) {
invokeDestroyHook(vnode.children[j]);
}
}
}
function removeVnodes (vnodes, startIdx, endIdx) {
for (; startIdx <= endIdx; ++startIdx) {
var ch = vnodes[startIdx];
if (isDef(ch)) {
if (isDef(ch.tag)) {
removeAndInvokeRemoveHook(ch);
invokeDestroyHook(ch);
} else { // Text node
removeNode(ch.elm);
}
}
}
}
function removeAndInvokeRemoveHook (vnode, rm) {
if (isDef(rm) || isDef(vnode.data)) {
var i;
var listeners = cbs.remove.length + 1;
if (isDef(rm)) {
// we have a recursively passed down rm callback
// increase the listeners count
rm.listeners += listeners;
} else {
// directly removing
rm = createRmCb(vnode.elm, listeners);
}
// recursively invoke hooks on child component root node
if (isDef(i = vnode.componentInstance) && isDef(i = i._vnode) && isDef(i.data)) {
removeAndInvokeRemoveHook(i, rm);
}
for (i = 0; i < cbs.remove.length; ++i) {
cbs.remove[i](vnode, rm);
}
if (isDef(i = vnode.data.hook) && isDef(i = i.remove)) {
i(vnode, rm);
} else {
rm();
}
} else {
removeNode(vnode.elm);
}
}
function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
var oldStartIdx = 0;
var newStartIdx = 0;
var oldEndIdx = oldCh.length - 1;
var oldStartVnode = oldCh[0];
var oldEndVnode = oldCh[oldEndIdx];
var newEndIdx = newCh.length - 1;
var newStartVnode = newCh[0];
var newEndVnode = newCh[newEndIdx];
var oldKeyToIdx, idxInOld, vnodeToMove, refElm;
// removeOnly is a special flag used only by
// to ensure removed elements stay in correct relative positions
// during leaving transitions
var canMove = !removeOnly;
{
checkDuplicateKeys(newCh);
}
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (isUndef(oldStartVnode)) {
oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
} else if (isUndef(oldEndVnode)) {
oldEndVnode = oldCh[--oldEndIdx];
} else if (sameVnode(oldStartVnode, newStartVnode)) {
patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx);
oldStartVnode = oldCh[++oldStartIdx];
newStartVnode = newCh[++newStartIdx];
} else if (sameVnode(oldEndVnode, newEndVnode)) {
patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx);
oldEndVnode = oldCh[--oldEndIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx);
canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm));
oldStartVnode = oldCh[++oldStartIdx];
newEndVnode = newCh[--newEndIdx];
} else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx);
canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);
oldEndVnode = oldCh[--oldEndIdx];
newStartVnode = newCh[++newStartIdx];
} else {
if (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); }
idxInOld = isDef(newStartVnode.key)
? oldKeyToIdx[newStartVnode.key]
: findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx);
if (isUndef(idxInOld)) { // New element
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx);
} else {
vnodeToMove = oldCh[idxInOld];
if (sameVnode(vnodeToMove, newStartVnode)) {
patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue, newCh, newStartIdx);
oldCh[idxInOld] = undefined;
canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm);
} else {
// same key but different element. treat as new element
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx);
}
}
newStartVnode = newCh[++newStartIdx];
}
}
if (oldStartIdx > oldEndIdx) {
refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
} else if (newStartIdx > newEndIdx) {
removeVnodes(oldCh, oldStartIdx, oldEndIdx);
}
}
function checkDuplicateKeys (children) {
var seenKeys = {};
for (var i = 0; i < children.length; i++) {
var vnode = children[i];
var key = vnode.key;
if (isDef(key)) {
if (seenKeys[key]) {
warn(
("Duplicate keys detected: '" + key + "'. This may cause an update error."),
vnode.context
);
} else {
seenKeys[key] = true;
}
}
}
}
function findIdxInOld (node, oldCh, start, end) {
for (var i = start; i < end; i++) {
var c = oldCh[i];
if (isDef(c) && sameVnode(node, c)) { return i }
}
}
function patchVnode (
oldVnode,
vnode,
insertedVnodeQueue,
ownerArray,
index,
removeOnly
) {
if (oldVnode === vnode) {
return
}
if (isDef(vnode.elm) && isDef(ownerArray)) {
// clone reused vnode
vnode = ownerArray[index] = cloneVNode(vnode);
}
var elm = vnode.elm = oldVnode.elm;
if (isTrue(oldVnode.isAsyncPlaceholder)) {
if (isDef(vnode.asyncFactory.resolved)) {
hydrate(oldVnode.elm, vnode, insertedVnodeQueue);
} else {
vnode.isAsyncPlaceholder = true;
}
return
}
// reuse element for static trees.
// note we only do this if the vnode is cloned -
// if the new node is not cloned it means the render functions have been
// reset by the hot-reload-api and we need to do a proper re-render.
if (isTrue(vnode.isStatic) &&
isTrue(oldVnode.isStatic) &&
vnode.key === oldVnode.key &&
(isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
) {
vnode.componentInstance = oldVnode.componentInstance;
return
}
var i;
var data = vnode.data;
if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
i(oldVnode, vnode);
}
var oldCh = oldVnode.children;
var ch = vnode.children;
if (isDef(data) && isPatchable(vnode)) {
for (i = 0; i < cbs.update.length; ++i) { cbs.update[i](oldVnode, vnode); }
if (isDef(i = data.hook) && isDef(i = i.update)) { i(oldVnode, vnode); }
}
if (isUndef(vnode.text)) {
if (isDef(oldCh) && isDef(ch)) {
if (oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly); }
} else if (isDef(ch)) {
{
checkDuplicateKeys(ch);
}
if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ''); }
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
} else if (isDef(oldCh)) {
removeVnodes(oldCh, 0, oldCh.length - 1);
} else if (isDef(oldVnode.text)) {
nodeOps.setTextContent(elm, '');
}
} else if (oldVnode.text !== vnode.text) {
nodeOps.setTextContent(elm, vnode.text);
}
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.postpatch)) { i(oldVnode, vnode); }
}
}
function invokeInsertHook (vnode, queue, initial) {
// delay insert hooks for component root nodes, invoke them after the
// element is really inserted
if (isTrue(initial) && isDef(vnode.parent)) {
vnode.parent.data.pendingInsert = queue;
} else {
for (var i = 0; i < queue.length; ++i) {
queue[i].data.hook.insert(queue[i]);
}
}
}
var hydrationBailed = false;
// list of modules that can skip create hook during hydration because they
// are already rendered on the client or has no need for initialization
// Note: style is excluded because it relies on initial clone for future
// deep updates (#7063).
var isRenderedModule = makeMap('attrs,class,staticClass,staticStyle,key');
// Note: this is a browser-only function so we can assume elms are DOM nodes.
function hydrate (elm, vnode, insertedVnodeQueue, inVPre) {
var i;
var tag = vnode.tag;
var data = vnode.data;
var children = vnode.children;
inVPre = inVPre || (data && data.pre);
vnode.elm = elm;
if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {
vnode.isAsyncPlaceholder = true;
return true
}
// assert node match
{
if (!assertNodeMatch(elm, vnode, inVPre)) {
return false
}
}
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.init)) { i(vnode, true /* hydrating */); }
if (isDef(i = vnode.componentInstance)) {
// child component. it should have hydrated its own tree.
initComponent(vnode, insertedVnodeQueue);
return true
}
}
if (isDef(tag)) {
if (isDef(children)) {
// empty element, allow client to pick up and populate children
if (!elm.hasChildNodes()) {
createChildren(vnode, children, insertedVnodeQueue);
} else {
// v-html and domProps: innerHTML
if (isDef(i = data) && isDef(i = i.domProps) && isDef(i = i.innerHTML)) {
if (i !== elm.innerHTML) {
/* istanbul ignore if */
if (typeof console !== 'undefined' &&
!hydrationBailed
) {
hydrationBailed = true;
console.warn('Parent: ', elm);
console.warn('server innerHTML: ', i);
console.warn('client innerHTML: ', elm.innerHTML);
}
return false
}
} else {
// iterate and compare children lists
var childrenMatch = true;
var childNode = elm.firstChild;
for (var i$1 = 0; i$1 < children.length; i$1++) {
if (!childNode || !hydrate(childNode, children[i$1], insertedVnodeQueue, inVPre)) {
childrenMatch = false;
break
}
childNode = childNode.nextSibling;
}
// if childNode is not null, it means the actual childNodes list is
// longer than the virtual children list.
if (!childrenMatch || childNode) {
/* istanbul ignore if */
if (typeof console !== 'undefined' &&
!hydrationBailed
) {
hydrationBailed = true;
console.warn('Parent: ', elm);
console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children);
}
return false
}
}
}
}
if (isDef(data)) {
var fullInvoke = false;
for (var key in data) {
if (!isRenderedModule(key)) {
fullInvoke = true;
invokeCreateHooks(vnode, insertedVnodeQueue);
break
}
}
if (!fullInvoke && data['class']) {
// ensure collecting deps for deep class bindings for future updates
traverse(data['class']);
}
}
} else if (elm.data !== vnode.text) {
elm.data = vnode.text;
}
return true
}
function assertNodeMatch (node, vnode, inVPre) {
if (isDef(vnode.tag)) {
return vnode.tag.indexOf('vue-component') === 0 || (
!isUnknownElement$$1(vnode, inVPre) &&
vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())
)
} else {
return node.nodeType === (vnode.isComment ? 8 : 3)
}
}
return function patch (oldVnode, vnode, hydrating, removeOnly) {
if (isUndef(vnode)) {
if (isDef(oldVnode)) { invokeDestroyHook(oldVnode); }
return
}
var isInitialPatch = false;
var insertedVnodeQueue = [];
if (isUndef(oldVnode)) {
// empty mount (likely as component), create new root element
isInitialPatch = true;
createElm(vnode, insertedVnodeQueue);
} else {
var isRealElement = isDef(oldVnode.nodeType);
if (!isRealElement && sameVnode(oldVnode, vnode)) {
// patch existing root node
patchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly);
} else {
if (isRealElement) {
// mounting to a real element
// check if this is server-rendered content and if we can perform
// a successful hydration.
if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {
oldVnode.removeAttribute(SSR_ATTR);
hydrating = true;
}
if (isTrue(hydrating)) {
if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {
invokeInsertHook(vnode, insertedVnodeQueue, true);
return oldVnode
} else {
warn(
'The client-side rendered virtual DOM tree is not matching ' +
'server-rendered content. This is likely caused by incorrect ' +
'HTML markup, for example nesting block-level elements inside ' +
'
, or missing
. Bailing hydration and performing ' +
'full client-side render.'
);
}
}
// either not server-rendered, or hydration failed.
// create an empty node and replace it
oldVnode = emptyNodeAt(oldVnode);
}
// replacing existing element
var oldElm = oldVnode.elm;
var parentElm = nodeOps.parentNode(oldElm);
// create new node
createElm(
vnode,
insertedVnodeQueue,
// extremely rare edge case: do not insert if old element is in a
// leaving transition. Only happens when combining transition +
// keep-alive + HOCs. (#4590)
oldElm._leaveCb ? null : parentElm,
nodeOps.nextSibling(oldElm)
);
// update parent placeholder node element, recursively
if (isDef(vnode.parent)) {
var ancestor = vnode.parent;
var patchable = isPatchable(vnode);
while (ancestor) {
for (var i = 0; i < cbs.destroy.length; ++i) {
cbs.destroy[i](ancestor);
}
ancestor.elm = vnode.elm;
if (patchable) {
for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {
cbs.create[i$1](emptyNode, ancestor);
}
// #6513
// invoke insert hooks that may have been merged by create hooks.
// e.g. for directives that uses the "inserted" hook.
var insert = ancestor.data.hook.insert;
if (insert.merged) {
// start at index 1 to avoid re-invoking component mounted hook
for (var i$2 = 1; i$2 < insert.fns.length; i$2++) {
insert.fns[i$2]();
}
}
} else {
registerRef(ancestor);
}
ancestor = ancestor.parent;
}
}
// destroy old node
if (isDef(parentElm)) {
removeVnodes([oldVnode], 0, 0);
} else if (isDef(oldVnode.tag)) {
invokeDestroyHook(oldVnode);
}
}
}
invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);
return vnode.elm
}
}
/* */
var directives = {
create: updateDirectives,
update: updateDirectives,
destroy: function unbindDirectives (vnode) {
updateDirectives(vnode, emptyNode);
}
};
function updateDirectives (oldVnode, vnode) {
if (oldVnode.data.directives || vnode.data.directives) {
_update(oldVnode, vnode);
}
}
function _update (oldVnode, vnode) {
var isCreate = oldVnode === emptyNode;
var isDestroy = vnode === emptyNode;
var oldDirs = normalizeDirectives$1(oldVnode.data.directives, oldVnode.context);
var newDirs = normalizeDirectives$1(vnode.data.directives, vnode.context);
var dirsWithInsert = [];
var dirsWithPostpatch = [];
var key, oldDir, dir;
for (key in newDirs) {
oldDir = oldDirs[key];
dir = newDirs[key];
if (!oldDir) {
// new directive, bind
callHook$1(dir, 'bind', vnode, oldVnode);
if (dir.def && dir.def.inserted) {
dirsWithInsert.push(dir);
}
} else {
// existing directive, update
dir.oldValue = oldDir.value;
dir.oldArg = oldDir.arg;
callHook$1(dir, 'update', vnode, oldVnode);
if (dir.def && dir.def.componentUpdated) {
dirsWithPostpatch.push(dir);
}
}
}
if (dirsWithInsert.length) {
var callInsert = function () {
for (var i = 0; i < dirsWithInsert.length; i++) {
callHook$1(dirsWithInsert[i], 'inserted', vnode, oldVnode);
}
};
if (isCreate) {
mergeVNodeHook(vnode, 'insert', callInsert);
} else {
callInsert();
}
}
if (dirsWithPostpatch.length) {
mergeVNodeHook(vnode, 'postpatch', function () {
for (var i = 0; i < dirsWithPostpatch.length; i++) {
callHook$1(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode);
}
});
}
if (!isCreate) {
for (key in oldDirs) {
if (!newDirs[key]) {
// no longer present, unbind
callHook$1(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy);
}
}
}
}
var emptyModifiers = Object.create(null);
function normalizeDirectives$1 (
dirs,
vm
) {
var res = Object.create(null);
if (!dirs) {
// $flow-disable-line
return res
}
var i, dir;
for (i = 0; i < dirs.length; i++) {
dir = dirs[i];
if (!dir.modifiers) {
// $flow-disable-line
dir.modifiers = emptyModifiers;
}
res[getRawDirName(dir)] = dir;
dir.def = resolveAsset(vm.$options, 'directives', dir.name, true);
}
// $flow-disable-line
return res
}
function getRawDirName (dir) {
return dir.rawName || ((dir.name) + "." + (Object.keys(dir.modifiers || {}).join('.')))
}
function callHook$1 (dir, hook, vnode, oldVnode, isDestroy) {
var fn = dir.def && dir.def[hook];
if (fn) {
try {
fn(vnode.elm, dir, vnode, oldVnode, isDestroy);
} catch (e) {
handleError(e, vnode.context, ("directive " + (dir.name) + " " + hook + " hook"));
}
}
}
var baseModules = [
ref,
directives
];
/* */
function updateAttrs (oldVnode, vnode) {
var opts = vnode.componentOptions;
if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) {
return
}
if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) {
return
}
var key, cur, old;
var elm = vnode.elm;
var oldAttrs = oldVnode.data.attrs || {};
var attrs = vnode.data.attrs || {};
// clone observed objects, as the user probably wants to mutate it
if (isDef(attrs.__ob__)) {
attrs = vnode.data.attrs = extend({}, attrs);
}
for (key in attrs) {
cur = attrs[key];
old = oldAttrs[key];
if (old !== cur) {
setAttr(elm, key, cur, vnode.data.pre);
}
}
// #4391: in IE9, setting type can reset value for input[type=radio]
// #6666: IE/Edge forces progress value down to 1 before setting a max
/* istanbul ignore if */
if ((isIE || isEdge) && attrs.value !== oldAttrs.value) {
setAttr(elm, 'value', attrs.value);
}
for (key in oldAttrs) {
if (isUndef(attrs[key])) {
if (isXlink(key)) {
elm.removeAttributeNS(xlinkNS, getXlinkProp(key));
} else if (!isEnumeratedAttr(key)) {
elm.removeAttribute(key);
}
}
}
}
function setAttr (el, key, value, isInPre) {
if (isInPre || el.tagName.indexOf('-') > -1) {
baseSetAttr(el, key, value);
} else if (isBooleanAttr(key)) {
// set attribute for blank value
// e.g.
if (isFalsyAttrValue(value)) {
el.removeAttribute(key);
} else {
// technically allowfullscreen is a boolean attribute for