[
  {
    "path": ".github/actions/setup-bun/action.yml",
    "content": "name: setup bun\ndescription: Setup bun and install dependencies\n\ninputs:\n  working-directory:\n    description: 'working directory for bun install'\n    default: ./\n    required: false\n\nruns:\n  using: composite\n  steps:\n    - name: Setup Bun\n      uses: oven-sh/setup-bun@v2\n      with:\n        bun-version: 1.3.1\n    \n    - name: Cache dependencies\n      id: bun-cache\n      uses: actions/cache@v4\n      with:\n        path: |\n          **/node_modules\n        key: ${{ runner.os }}-v7-bun-${{ hashFiles('**/bun.lock') }}-${{ hashFiles('**/package.json') }}\n        restore-keys: |\n          ${{ runner.os }}-v7-bun-${{ hashFiles('**/bun.lock') }}\n          ${{ runner.os }}-v7-bun-\n\n    - name: Install dependencies\n      working-directory: ${{ inputs.working-directory }}\n      run: bun install\n      shell: bash\n      "
  },
  {
    "path": ".github/workflows/deploy-docs.yml",
    "content": "name: Deploy Documentation\n\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - master\n    paths:\n      # Update on workflow change\n      - \".github/workflows/deploy-docs.yml\"\n      # Update on docs change\n      - \"docs/**\"\n      # Update on code change (Api Reference)\n      - \"packages/react-native-video/src/**\"\n\njobs:\n  build:\n    name: Build Documentation\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - uses: ./.github/actions/setup-bun\n\n      - name: Build Documentation\n        run: bun run --cwd docs build\n\n      - name: Upload Build Artifact\n        uses: actions/upload-pages-artifact@v3\n        with:\n          path: docs/build\n\n  deploy:\n    name: Deploy Documentation to GitHub Pages\n    needs: build\n\n    permissions:\n      pages: write\n      id-token: write\n\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n\n    runs-on: ubuntu-latest\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4\n"
  },
  {
    "path": ".github/workflows/test-docs-build.yml",
    "content": "name: Test Documentation Build\n\non:\n  pull_request:\n    branches:\n      - master\n    paths:\n      # Update on workflow change\n      - \".github/workflows/test-docs-build.yml\"\n      # Update on docs change\n      - \"docs/**\"\n      # Update on code change (Api Reference)\n      - \"packages/react-native-video/src/**\"\n\njobs:\n  test-docs-deploy:\n    name: Test Documentation Build\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - uses: ./.github/actions/setup-bun\n\n      - name: Test build website\n        run: bun run --cwd docs build\n"
  },
  {
    "path": ".gitignore",
    "content": "# OSX\n#\n.DS_Store\n\n**/.xcode.env.local\n\n# XDE\n.expo/\n\n# VSCode\n.vscode/\njsconfig.json\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\nproject.xcworkspace\n\n# Android/IJ\n#\n.classpath\n.cxx\n.gradle\n.idea\n.project\n.settings\nlocal.properties\nandroid.iml\n\n# Cocoapods\n#\nexample/ios/Pods\n\n# Ruby\nexample/vendor/\n\n# node.js\n#\nnode_modules/\nnpm-debug.log\nyarn-debug.log\nyarn-error.log\n\n# Bun\npackage-lock.json\n**/*.bun\n\n# BUCK\nbuck-out/\n\\.buckd/\nandroid/app/libs\nandroid/keystores/debug.keystore\n\n# Yarn\n.yarn/*\n!.yarn/patches\n!.yarn/plugins\n!.yarn/releases\n!.yarn/sdks\n!.yarn/versions\n\n# Expo\n.expo/\n\n# Turborepo\n.turbo/\n\n# generated by bob\nlib/\n\n# TypeScript\ntsconfig.tsbuildinfo"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "\n# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, caste, color, religion, or sexual\nidentity and orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the overall\n  community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or advances of\n  any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email address,\n  without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\n[INSERT CONTACT METHOD].\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series of\nactions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or permanent\nban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior, harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within the\ncommunity.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.1, available at\n[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].\n\nCommunity Impact Guidelines were inspired by\n[Mozilla's code of conduct enforcement ladder][Mozilla CoC].\n\nFor answers to common questions about this code of conduct, see the FAQ at\n[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at\n[https://www.contributor-covenant.org/translations][translations].\n\n[homepage]: https://www.contributor-covenant.org\n[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html\n[Mozilla CoC]: https://github.com/mozilla/diversity\n[FAQ]: https://www.contributor-covenant.org/faq\n[translations]: https://www.contributor-covenant.org/translations\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nContributions are always welcome, no matter how large or small!\n\nWe want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. Before contributing, please read the [code of conduct](./CODE_OF_CONDUCT.md).\n\n## Development workflow\n\nThis project is a monorepo managed using [Bun workspaces](https://bun.sh/docs/install/workspaces). It contains the following packages:\n\n- An Library package in the `packages/react-native-video` directory.\n- An example app in the `example/` directory.\n\nTo get started with the project, run `bun install` in the root directory to install the required dependencies for each package:\n\n```sh\nbun install\n```\n\n> Since the project relies on Bun workspaces, you cannot use [`npm`](https://github.com/npm/cli) or [`yarn`](https://yarnpkg.com/) for development.\n\nThe [example app](/example/) demonstrates usage of the library. You need to run it to test any changes you make.\n\nIt is configured to use the local version of the library, so any changes you make to the library's source code will be reflected in the example app. Changes to the library's JavaScript code will be reflected in the example app without a rebuild, but native code changes will require a rebuild of the example app.\n\nIf you want to use Android Studio or XCode to edit the native code, you can open the `example/android` or `example/ios` directories respectively in those editors. To edit the Objective-C or Swift files, open `example/ios/VideoExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > react-native-video`.\n\nTo edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `react-native-video` under `Android`.\n\nYou can use various commands from the root directory to work with the project.\n\nTo start the packager:\n\n```sh\nbun example start\n```\n\nTo run the example app on Android:\n\n```sh\nbun example android\n```\n\nTo run the example app on iOS:\n\n```sh\nbun example ios\n```\n\nMake sure your code passes TypeScript and ESLint. Run the following to verify:\n\n```sh\nbun typecheck\nbun lint\n```\n\nTo fix formatting errors, run the following:\n\n```sh\nbun lint --fix\n```\n\n### Commit message convention\n\nWe follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:\n\n- `fix`: bug fixes, e.g. fix crash due to deprecated method.\n- `feat`: new features, e.g. add new method to the module.\n- `refactor`: code refactor, e.g. migrate from class components to hooks.\n- `docs`: changes into documentation, e.g. add usage example for the module..\n- `test`: adding or updating tests, e.g. add integration tests using detox.\n- `chore`: tooling changes, e.g. change CI config.\n\nOur pre-commit hooks verify that your commit message matches this format when committing.\n\n### Linting and tests\n\n[ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/)\n\nWe use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing.\n\nOur pre-commit hooks verify that the linter and tests pass when committing.\n\n### Publishing to npm\n\nWe use [release-it](https://github.com/release-it/release-it) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc.\n\nTo publish new versions, run the following:\n\n```sh\nbun release\n```\n\n### Scripts\n\nThe `package.json` file contains various scripts for common tasks:\n\n- `bun install`: setup project by installing dependencies.\n- `bun typecheck`: type-check files with TypeScript.\n- `bun lint`: lint files with ESLint.\n- `bun example start`: start the Metro server for the example app.\n- `bun example android`: run the example app on Android.\n- `bun example ios`: run the example app on iOS.\n\n### Sending a pull request\n\n> **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).\n\nWhen you're sending a pull request:\n\n- Prefer small pull requests focused on one change.\n- Verify that linters and tests are passing.\n- Review the documentation to make sure it looks good.\n- Follow the pull request template when opening a pull request.\n- For pull requests that change the API or implementation, discuss with maintainers first by opening an issue.\n\n### License\n\nBy contributing to this project, you agree that your contributions will be licensed under the [MIT License](LICENSE).\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024-2025 TheWidlarzGroup\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[![React Native Video Component](./docs/static/baners/rnv-banner.png)](https://thewidlarzgroup.com/?utm_source=rnv&utm_medium=readme&utm_id=banner)\n\nThe most battle-tested open-source video player component for React Native with support for DRM, offline playback, HLS/DASH streaming, and more.\n\n> [!IMPORTANT]\n> This is a new version (v7) of `react-native-video` that is currently in active development.\n> You can expect breaking changes and missing features.\n> \n> If you have any questions, please contact us at [hi@thewidlarzgroup.com](mailto:hi@thewidlarzgroup.com).\n\n## 🔍 Features\n\n| Feature | Status |\n|---------|--------|\n| 📱 Plays all video formats natively supported by iOS/Android | ✅ Available |\n| ▶️ Local and remote playback | ✅ Available |\n| 🔁 Streaming: HLS • DASH • SmoothStreaming | ✅ Available |\n| 🧩 Expo plugin support | ✅ Available |\n| 📴 Offline playback, video download, support for side-tracks and side-captions (via [optional SDK](https://docs.thewidlarzgroup.com/offline-video-sdk?utm_source=rnv&utm_medium=readme&utm_id=features-text)) | ✅ Available |\n| 📱 Picture in Picture | ✅ Available |\n| 🎚️ Fine-grained control over tracks, buffering & events | 🏗️ In Development |\n| 🧠 Advanced control over playback and buffering | ✅ Available |\n| 🔐 DRM: Widevine & FairPlay ([See free DRM stream example](https://www.thewidlarzgroup.com/services/free-drm-token-generator-for-video?utm_source=rnv&utm_medium=readme&utm_id=free-drm)) | ✅ Available |\n| 🌐 Basic Web Support | 📝 [TODO](https://github.com/TheWidlarzGroup/react-native-video/issues/4605) |\n| 📺 TV Support | 📝 [TODO](https://github.com/TheWidlarzGroup/react-native-video/issues/4607) |\n| 🥽 VisionOS Support | 📝 [TODO](https://github.com/TheWidlarzGroup/react-native-video/issues/4608) |\n\n\n\n## ✨ Project Status\n\n| Version | State | Architecture |\n|---------|-------|--------------|\n| **v5 and lower** | ❌ End-of-life [Commercial Support Available](https://www.thewidlarzgroup.com/blog/react-native-video-upgrade-challenges-custom-maintenance-support#how-we-can-help?utm_source=rnv&utm_medium=readme&utm_id=upgradev5) | Old Architecture |\n| **v6** | 🛠 Maintained (community + TWG) | Old + New (Interop Layer) |\n| **v7** | 🚀 Active Development | Old + New (Full Support) |\n\n`react-native-video` v7 introduces full support for the new React Native architecture, unlocking better performance, improved consistency, and modern native modules.\n\n---\n\n## 📚 Documentation & Examples\n\n- 📖 [Documentation](https://docs.thewidlarzgroup.com/react-native-video/docs/v7/intro)\n- 📦 [Example: Basic Usage](https://github.com/TheWidlarzGroup/react-native-video/tree/v7/example)\n- 📦 [Example: Free DRM Stream](https://www.thewidlarzgroup.com/services/free-drm-token-generator-for-video?utm_source=rnv&utm_medium=readme&utm_id=free-drm)\n\n## 🚀 Quick Start\n\n### Requirements\n\n- React Native 0.75 or higher\n- `react-native-nitro-modules` (>=0.31.10) - Please see [nitro requirements](https://nitro.margelo.com/docs/minimum-requirements)\n\n### Install\n\n`react-native-video` requires `react-native-nitro-modules` (>=0.31.10) in your project.\n```bash\nnpm install react-native-nitro-modules\n```\n\nThen install `react-native-video`\n\n```bash\n# Install the beta version of react-native-video v7\nnpm install react-native-video@beta\n\n# Install pods\ncd ios && pod install\n```\n\n<details>\n<summary>For react-native < 0.80</summary>\n`react-native` < 0.80 have bug that prevents to properly handle errors by nitro modules on Android.\nWe highly recommend to apply bellow patch for `react-native-nitro-modules` to fix this issue.\nYou can apply it using `patch-package`.\n\nWithout this patch you won't be able \"recognize\" errors, all will be thrown as unknown errors.\n\nsee [installation guide](https://docs.thewidlarzgroup.com/react-native-video/docs/v7/installation#patch-for-react-native--080)\n</details>\n\n### Usage\n```tsx\nimport { useVideoPlayer, VideoView } from 'react-native-video';\n\nexport default () => (\n  const player = useVideoPlayer(\n    'https://www.w3schools.com/html/mov_bbb.mp4',\n    (_player) => {\n      _player.play();\n    }\n  );\n\n  <VideoView\n    player={player}\n    style={{ width: '100%', aspectRatio: 16 / 9 }}\n    controls\n  />\n);\n```\n\n---\n\n## :inbox_tray: We're building a Pro Player!\n\n<a href=\"https://sdk.thewidlarzgroup.com\">\n  <img src=\"./docs/static/baners/rnv-pro-player-banner.png\" alt=\"Offline SDK Preview\" width=\"40%\" align=\"right\" />\n</a>\n\nWe see the need for a more feature-rich video player. There is a gap between open source and commercial players, and we want to fill that gap with plugins.\n\n**Are you using a commercial player just for 1-2 features?** Maybe you are paying for a license just to get **Caching**, **Ads**, or **Analytics**? Let us know. We want to identify these missing pieces and build them, so you can switch back to open source.\n\n**This is what we have already. Check out!**\n\n* [Offline Video](https://sdk.thewidlarzgroup.com/offline-video): Logic for downloading streams (HLS/DASH) and standard video files to enable offline playback.\n* [Background Uploader](https://sdk.thewidlarzgroup.com/background-uploader): Handles uploads even if the app is minimized (not strictly a player plugin, but super useful).\n* [Chapter Markers](https://sdk.thewidlarzgroup.com/chapters): Visual markers on the timeline to navigate content.\n\n<br/>\n<br/>\n\n[-> Tell us what to build next ←](https://sdk.thewidlarzgroup.com/ask-for-plugin) or reach out to us sdk@thewidlarzgroup.com\n\n<br/>\n\n---\n\n## 💼 TWG Services & Products\n\n| Offering | Description |\n|----------|-------------|\n| [**Professional Support Packages**](https://www.thewidlarzgroup.com/issue-boost?utm_source=rnv&utm_medium=readme&utm_campaign=professional-support-packages#Contact) | Priority bug-fixes, guaranteed SLAs, [roadmap influence](https://github.com/orgs/TheWidlarzGroup/projects/6) |\n| [**Issue Booster**](https://www.thewidlarzgroup.com/issue-boost?utm_source=rnv&utm_medium=readme) | Fast-track urgent fixes with a pay‑per‑issue model |\n| [**Offline Video SDK**](https://www.thewidlarzgroup.com/offline-video-sdk/?utm_source=rnv&utm_medium=readme&utm_campaign=downloading&utm_id=offline-video-sdk-link) | Plug‑and‑play secure download solution for iOS & Android |\n| [**Integration Support**](https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=readme&utm_campaign=integration-support#Contact) | Hands‑on help integrating video, DRM & offline into your app |\n| [**Free DRM Token Generator**](https://www.thewidlarzgroup.com/services/free-drm-token-generator-for-video?utm_source=rnv&utm_medium=readme&utm_id=free-drm) | Generate Widevine / FairPlay tokens for testing |\n| [**Ready Boilerplates**](https://www.thewidlarzgroup.com/showcases?utm_source=rnv&utm_medium=readme) | Ready-to-use apps with offline HLS/DASH DRM, video frame scrubbing, TikTok-style video feed, background uploads, Skia-based frame processor (R&D phase), and more |\n| [**React Native Video Upgrade Guide**](https://www.thewidlarzgroup.com/blog/react-native-video-upgrade-challenges-custom-maintenance-support?utm_source=rnv&utm_medium=readme&utm_id=upgrade-blog&utm_campaign=v7) | Common upgrade pitfalls & how to solve them |\n\n*See how [TWG](https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=readme&utm_id=services-text) helped **Learnn** ship a world‑class player in record time -  [case study](https://gitnation.com/contents/a-4-year-retrospective-lessons-learned-from-building-a-video-player-from-scratch-with-react-native).*\n\nContact us at [hi@thewidlarzgroup.com](mailto:hi@thewidlarzgroup.com)\n\n## 🌍 Social\n\n- 🐦 **X / Twitter** - [follow product & release updates](https://x.com/TheWidlarzGroup)\n- 💬 **Discord** - [talk to the community and us](https://discord.gg/9WPq6Yx)\n- 💼 **LinkedIn** - [see TWG flexing](https://linkedin.com/company/the-widlarz-group)\n\n## 📰 Community & Media\n\n- 🗽 **React Summit US** – How TWG helped Learnn boost video performance on React Native.  \n[Watch the talk »](https://gitnation.com/contents/a-4-year-retrospective-lessons-learned-from-building-a-video-player-from-scratch-with-react-native)\n\n- 🧨 **v7 deep dive** – Why we’re building v7 with Nitro Modules\n[Watch on X »](https://x.com/krzysztof_moch/status/1854162551946478051)\n\n- 🛠️ **Well-maintained open-source library** - What does it truly mean? - Bart's talk for React Native Warsaw\n[Watch here »](https://www.youtube.com/watch?v=RAQQwGCQNqY)\n\n- 📺 **“Over the Top” Panel** - Building Streaming Apps for Mobile, Web, and Smart TVs - Bart giving his insights on the industry\n[Watch here »](https://youtu.be/j2b_bG-32JI)\n"
  },
  {
    "path": "bunfig.toml",
    "content": "[install]\nlinker = \"hoisted\""
  },
  {
    "path": "config/.editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# editorconfig.org\n\nroot = true\n\n[*]\n\nindent_style = space\nindent_size = 2\n\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\nquote_type = single\n"
  },
  {
    "path": "config/.eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  extends: ['@react-native', 'plugin:prettier/recommended'],\n  ignorePatterns: [\n    '**/node_modules',\n    '**/lib',\n    '**/build',\n    '**/.eslintrc.js',\n    '**/.prettierrc.js',\n    '**/jest.config.js',\n    '**/babel.config.js',\n    '**/metro.config.js',\n    '**/react-native.config.js',\n    '**/tsconfig.json',\n  ],\n  plugins: ['@typescript-eslint', 'prettier'],\n  parser: '@typescript-eslint/parser',\n  parserOptions: {\n    project: true,\n    tsconfigRootDir: __dirname,\n    ecmaFeatures: {\n      jsx: true,\n    },\n    ecmaVersion: 2020,\n    sourceType: 'module',\n  },\n  rules: {\n    'prettier/prettier': [\n      'error',\n      {\n        quoteProps: 'consistent',\n        singleQuote: true,\n        tabWidth: 2,\n        trailingComma: 'es5',\n        useTabs: false,\n      },\n    ],\n    quotes: [\n      'error',\n      'single',\n      { avoidEscape: true, allowTemplateLiterals: true },\n    ],\n    '@react-native/no-deep-imports': 'off',\n  },\n};\n"
  },
  {
    "path": "config/tsconfig.json",
    "content": "{\n  \"exclude\": [\n    \"**/node_modules\",\n    \"**/lib\",\n    \"**/.eslintrc.js\",\n    \"**/.prettierrc.js\",\n    \"**/jest.config.js\",\n    \"**/babel.config.js\",\n    \"**/metro.config.js\",\n    \"**/react-native.config.js\",\n    \"**/tsconfig.json\"\n  ],\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"allowUnreachableCode\": false,\n    \"allowUnusedLabels\": false,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"lib\": [\"ESNext\"],\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"noEmit\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noImplicitReturns\": true,\n    \"noImplicitUseStrict\": false,\n    \"noStrictGenericChecks\": false,\n    \"noUncheckedIndexedAccess\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"target\": \"ESNext\",\n    \"verbatimModuleSyntax\": true\n  }\n}"
  },
  {
    "path": "docs/.eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  extends: [\"../config/.eslintrc.js\"],\n  parserOptions: {\n    tsconfigRootDir: __dirname,\n    project: true,\n  },\n  plugins: ['@widlarzgroup/docusaurus'],\n  settings: {\n    '@widlarzgroup/docusaurus': {\n      extend: ['src/css/custom.css'],\n    },\n  },\n  overrides: [\n    {\n      files: ['**/*.css'],\n      processor: '@widlarzgroup/docusaurus/.css',\n    },\n  ],\n};\n"
  },
  {
    "path": "docs/.gitignore",
    "content": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# API Reference generated files\ndocs/api-reference/\n\n# Misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "docs/README.md",
    "content": "### Instalation\n\nTo install the dependencies, run at the root of the repository:\n\n```\n$ bun install\n```\n\n### Development\n\nTo start a local development server with hot-reloading, run:\n\n```\n$ bun run start\n```\n\n### Deployment\n\nDeployment is handled via GitHub Actions. Upon pushing to the `master` branch content from the `docs` directory is automatically deployed to GitHub Pages.\n\n### Custom Props\n\nCustom props are provided by the `@widlarzgroup/docusaurus-ui` package and allow you to display badges and other UI elements. Custom props can be defined in three places:\n\n#### 1. In `_category_.json` (for entire categories)\n\n```json\n{\n  \"label\": \"Analytics\",\n  \"position\": 7,\n  \"customProps\": {\n    \"badgeType\": \"new\"\n  }\n}\n```\n\n#### 2. In markdown frontmatter (for individual pages)\n\n```md\n---\nsidebar_position: 5\nsidebar_label: Chapters\ncustomProps:\n  plan: pro\n---\n```\n\n#### 3. In `sidebars.ts` (for sidebar items)\n\n```ts\n{\n  type: 'doc',\n  id: 'some-doc',\n  customProps: {\n    badgeType: 'new'\n  }\n}\n```\n\n#### Available Custom Props\n\n| Prop | Values | Description |\n|------|--------|-------------|\n| `badgeType` | `\"new\"`, `\"preview\"` | Displays a \"NEW\" or \"PREVIEW\" badge next to the item |\n| `plan` | `\"pro\"` | Displays a \"PRO\" badge indicating premium/commercial feature |\n"
  },
  {
    "path": "docs/docs/fundamentals/_category_.json",
    "content": "{\n  \"label\": \"Fundamentals\",\n  \"position\": 1,\n  \"collapsed\": false\n}\n"
  },
  {
    "path": "docs/docs/fundamentals/configuration/_category_.json",
    "content": "{\n  \"label\": \"Configuration\",\n  \"position\": 3,\n  \"collapsed\": false\n}\n"
  },
  {
    "path": "docs/docs/fundamentals/configuration/with-expo.md",
    "content": "---\nsidebar_position: 1\nsidebar_label: With Expo\ndescription: Expo plugin for react-native-video configuration\n---\n\n# Expo Plugin\n\nThe `react-native-video` library provides an Expo plugin to simplify the integration and configuration of specific features into your Expo project.\n\n## Installation\n\nTo use the Expo plugin, you need to add it to your app's configuration file (`app.json` or `app.config.js`).\n\n```json title=\"app.json\"\n{\n  \"expo\": {\n    \"plugins\": [\n      [\n        \"react-native-video\",\n        {\n          \"enableAndroidPictureInPicture\": true,\n          \"enableBackgroundAudio\": true,\n          \"androidExtensions\": {\n            \"useExoplayerDash\": true,\n            \"useExoplayerHls\": true\n          }\n        }\n      ]\n    ]\n  }\n}\n```\n\n```javascript title=\"app.config.js\"\nexport default {\n  plugins: [\n    [\n      'react-native-video',\n      {\n        enableAndroidPictureInPicture: true,\n        enableBackgroundAudio: true,\n        androidExtensions: {\n          useExoplayerDash: true,\n          useExoplayerHls: true,\n        },\n      },\n    ],\n  ],\n};\n```\n\n## Configuration Options\n\nThe plugin accepts an optional configuration object with the following properties:\n\n### `enableAndroidPictureInPicture` (optional)\n\n-   **Type:** `boolean`\n-   **Default:** `false`\n-   **Description:** Enables Picture-in-Picture (PiP) mode on Android. This will apply the necessary configurations to your Android project.\n\n### `enableBackgroundAudio` (optional)\n\n-   **Type:** `boolean`\n-   **Default:** `false`\n-   **Description:** Enables audio playback to continue when the app is in the background on Android. Ensure you have also configured the necessary background modes capabilities in your app if required by the operating system.\n\n### `androidExtensions` (optional)\n\n-   **Type:** `object`\n-   **Default:** `{ useExoplayerDash: true, useExoplayerHls: true }`\n-   **Description:** Allows you to specify which Android ExoPlayer extensions to include. This can help reduce the size of your app by only including the extensions you need.\n    -   `useExoplayerDash` (boolean, default: `true`): Whether to include ExoPlayer's Dash extension.\n    -   `useExoplayerHls` (boolean, default: `true`): Whether to include ExoPlayer's HLS extension.\n\n### `reactNativeTestApp` (optional)\n\n-   **Type:** `boolean`\n-   **Default:** `false`\n-   **Description:** Whether to use `react-native-test-app` compatible mode.\n\n## Usage\n\nOnce configured in your `app.json` or `app.config.js`, the plugin will automatically apply the necessary native project changes during the prebuild process (e.g., when running `npx expo prebuild`). No further manual setup is typically required for these features. "
  },
  {
    "path": "docs/docs/fundamentals/configuration/without-expo.md",
    "content": "---\nsidebar_position: 2\nsidebar_label: Without Expo\ndescription: Manual configuration of react-native-video\n---\n\n# Manual Configuration\n\nIf you prefer not to use the Expo plugin you can configure **react-native-video** manually by editing the native project files directly.  The steps below show the exact changes performed by the plugin so you can reproduce them in a plain React Native or bare Expo project.\n\n---\n\n## iOS\n\n### Enable Background Audio\nTo allow video sound to continue when the app goes to the background add the `audio` mode to `Info.plist`:\n\n```xml title=\"ios/YourApp/Info.plist\"\n<key>UIBackgroundModes</key>\n<array>\n  <string>audio</string>\n</array>\n```\n\n## Android\n\n### Configure ExoPlayer extensions\nBy default the library enables DASH & HLS extensions.  You can fine-tune this by adding properties to **gradle.properties**:\n\n```properties title=\"android/gradle.properties\"\n# Enable / disable ExoPlayer extensions used by react-native-video\nRNVideo_useExoplayerDash=true   # DASH playback support\nRNVideo_useExoplayerHls=true    # HLS  playback support\n```\nSet a value to `false` to exclude the corresponding extension and reduce APK size.\n\n### Enable Picture-in-Picture (PiP)\nAdd the `android:supportsPictureInPicture` flag to your *main* activity in **AndroidManifest.xml**:\n\n```xml title=\"android/app/src/main/AndroidManifest.xml\"\n<application>\n  <activity\n    android:name=\".MainActivity\"\n    android:supportsPictureInPicture=\"true\"\n    ...>\n    <!-- other attributes -->\n  </activity>\n</application>\n```\n\nPiP requires **API 26+** (Android 8.0). Make sure `minSdkVersion` is at least `26` when enabling this feature.\n\n## Verification\nAfter the modifications:\n\n1. **iOS** – run `cd ios && pod install` then build the app from Xcode or via `npx react-native run-ios` / `npx expo run:ios`.\n2. **Android** – clean & rebuild the project: `./gradlew clean && ./gradlew :app:assembleDebug` or simply run `npx react-native run-android` / `npx expo run:android`.\n\nIf the build succeeds your manual configuration is complete.\n\n---\n\n### Need an easier way?\nUse the [Expo plugin](./with-expo.md) to apply exactly the same changes automatically during `expo prebuild`."
  },
  {
    "path": "docs/docs/fundamentals/installation.md",
    "content": "---\ntitle: Installation\nsidebar_position: 2\ndescription: React Native Video Installation Guide and Requirements\n---\n# Installation\n\nReact Native Video is a library that allows you to play various kinds of video in a React Native application. It is built on top of the [`react-native-nitro-modules`](https://nitro.margelo.com/docs/what-is-nitro) framework, giving it type-safety and blazing fast communication across Native and JavaScript threads. React Native Video supports both the New Architecture and the Old Architecture.\n\n## Requirements\n\n### System Requirements\n- iOS `15.0` or higher\n- Android `6.0` or higher\n\n### Minimal Package Requirements\n- `react-native` `0.75.0` or higher\n- `react-native-nitro-modules` `0.35.0` or higher\n\n## Installation\n\n1. Install dependencies:\n```bash\nnpm install react-native-video@next react-native-nitro-modules\n```\n\n2. Configure Library:\nYou can configure the library in two ways:\n- [With Expo](./configuration/with-expo.md)\n- [Without Expo](./configuration/without-expo.md)\n\n3. Run the project:\nIf you are using Expo, you will need to generate native files:\n```bash\nnpx expo prebuild\n```\n\nAnd then run the project:\n```bash\nnpx expo run:ios # run on iOS\nnpx expo run:android # run on Android\n```\n\nIf you are using React Native CLI, you will need to install Pods for iOS:\n```bash\ncd ios && pod install && cd ..\n```\n\nAnd then run the project:\n```bash\nnpx react-native run-ios # run on iOS\nnpx react-native run-android # run on Android\n```\n\n## Patch for react-native < 0.80\n\nVersions of `react-native` < 0.80 have a bug that prevents them from properly handling errors thrown by nitro modules on Android.\nIf working with these versions of `react-native`, we highly recommend you apply the `react-native-nitro-modules` patch below, to fix this issue.\nYou can apply it using `patch-package`.\n\n:::warning\nWithout this patch you won't be able \"recognize\" errors, all will be thrown as unknown errors.\n:::\n\n<details>\n  <summary>Patch for `react-native-nitro-modules`</summary>\n\n  ```diff\n  diff --git a/node_modules/react-native-nitro-modules/cpp/core/HybridFunction.hpp b/node_modules/react-native-nitro-modules/cpp/core/HybridFunction.hpp\n  index efcea05..ffad3f2 100644\n  --- a/node_modules/react-native-nitro-modules/cpp/core/HybridFunction.hpp\n  +++ b/node_modules/react-native-nitro-modules/cpp/core/HybridFunction.hpp\n  @@ -23,6 +23,10 @@ struct JSIConverter;\n  #include <string>\n  #include <type_traits>\n\n  +#ifdef ANDROID\n  +#include <fbjni/fbjni.h>\n  +#endif\n  +\n  namespace margelo::nitro {\n\n  using namespace facebook;\n  @@ -109,6 +113,15 @@ public:\n          std::string funcName = getHybridFuncFullName<THybrid>(kind, name, hybridInstance.get());\n          std::string message = exception.what();\n          throw jsi::JSError(runtime, funcName + \": \" + message);\n  +#ifdef ANDROID\n  +#pragma clang diagnostic push\n  +#pragma clang diagnostic ignored \"-Wexceptions\"\n  +      } catch (const jni::JniException& exception) {\n  +        std::string funcName = getHybridFuncFullName<THybrid>(kind, name, hybridInstance.get());\n  +        std::string message = exception.what();\n  +        throw jsi::JSError(runtime, funcName + \": \" + message);\n  +#pragma clang diagnostic pop\n  +#endif\n        } catch (...) {\n          // Some unknown exception was thrown - add method name information and re-throw as `JSError`.\n          std::string funcName = getHybridFuncFullName<THybrid>(kind, name, hybridInstance.get());\n  ```\n\n  see [raw](https://github.com/TheWidlarzGroup/react-native-video/blob/v7/example/patches/react-native-nitro-modules%2B0.27.2.patch)\n</details>\n\n\n## Usage\n\n```tsx title=\"App.tsx\"\nimport { VideoView, useVideoPlayer } from 'react-native-video';\n\nexport default function App() {\n  const player = useVideoPlayer({\n    source: {\n      uri: 'https://www.w3schools.com/html/mov_bbb.mp4',\n    },\n  });\n\n  return <VideoView player={player} />;\n}\n```"
  },
  {
    "path": "docs/docs/fundamentals/intro.mdx",
    "content": "---\ntitle: Intro\nsidebar_position: 1\ndescription: Introduction to React Native Video v7\ncustomProps:\n  badgeType: new\n---\n\nimport {\n  V7Lead,\n  V7FeatureCards,\n  V7ApiModel,\n  V7NitroSection,\n  V7StatusTimeline,\n  V7OpenSource,\n  V7ProPlugins,\n} from '@site/src/components/Intro';\n\n<V7Lead />\n\n## What changed in v7 vs v6\n\n<V7FeatureCards />\n\n## New API model in practice\n\n### New model: you control the player, the view is optional\n\n<V7ApiModel />\n\n## Why Nitro Modules?\n\n### Nitro Modules as the foundation of v7\n\n<V7NitroSection />\n\n## Status v7\n\n<V7StatusTimeline />\n\n## Open-source + optional Pro features and services\n\n<V7OpenSource />\n\n## Pro plugins\n\n<V7ProPlugins />\n"
  },
  {
    "path": "docs/docs/offer.mdx",
    "content": "---\ntitle: Offer\ndescription: Introduction to React Native Video library\nsidebar_class_name: hidden\n---\n\nimport {\n  IntroHero,\n  OfferCards,\n  HowItWorks,\n  Services,\n  Extensions,\n  DecisionTable,\n  Contact,\n} from \"@site/src/components/Offer\";\n\n<IntroHero />\n\n## What you can use\n\nThree ways to work with react-native-video, depending on your needs and timeline:\n\n<OfferCards />\n\n## How it works\n\n<HowItWorks />\n\n## Services\n\nWhen you need guaranteed response times and direct maintainer involvement:\n\n<Services />\n\n## Extensions\n\nReady-to-use modules and templates for advanced use cases:\n\n<Extensions />\n\n## Which option should I choose?\n\nQuick reference guide based on your situation:\n\n<DecisionTable />\n\n## Contact\n\nReady to discuss your project? Here's what to include:\n\n<Contact />\n"
  },
  {
    "path": "docs/docs/player/_category_.json",
    "content": "{\n  \"label\": \"Player\",\n  \"position\": 2,\n  \"collapsed\": false\n}\n"
  },
  {
    "path": "docs/docs/player/analytics/_category_.json",
    "content": "{\n  \"label\": \"Analytics\",\n  \"position\": 7,\n  \"collapsed\": false,\n  \"customProps\": {\n    \"badgeType\": \"new\"\n  }\n}\n"
  },
  {
    "path": "docs/docs/player/analytics/manual.md",
    "content": "---\nsidebar_position: 2\nsidebar_label: Manual (Native)\ndescription: Manual analytics integration guide using native plugins\n---\n\n# Manual Analytics\n\nIntegrate your own analytics system using native plugins.\n\n## Overview\n\nMost analytics systems that track player data (e.g., bitrate, errors) can be integrated directly with ExoPlayer or AVPlayer. The [plugin system](../../plugins/plugins.mdx) allows for non-intrusive analytics integration with react-native-video. It should be implemented in native languages (Kotlin/Swift) to ensure efficiency.\n\n## Architecture\n\n```\n┌─────────────────────────────────────┐\n│     React Native App                │\n│  ┌───────────────────────────────┐  │\n│  │   react-native-video          │  │\n│  │  ┌─────────────────────────┐  │  │\n│  │  │   Plugin System         │  │  │\n│  │  └─────────────────────────┘  │  │\n│  └───────────────────────────────┘  │\n└─────────────────────────────────────┘\n         │                    │\n         │ onPlayerCreated    │ onPlayerCreated\n         ▼                    ▼\n┌─────────────────┐  ┌─────────────────┐\n│ Android Plugin  │  │  iOS Plugin     │\n│   (Kotlin)      │  │   (Swift)       │\n│                 │  │                 │\n│ ExoPlayer       │  │ AVPlayer        │\n│ Analytics       │  │ KVO Observers   │\n│ Listener        │  │                 │\n└─────────────────┘  └─────────────────┘\n```\n\n## Implementation\n\n### Android (Kotlin)\n\n```kotlin\nimport androidx.annotation.OptIn\nimport androidx.media3.common.Format\nimport androidx.media3.common.PlaybackException\nimport androidx.media3.common.Player\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.exoplayer.analytics.AnalyticsListener\nimport com.twg.video.core.plugins.NativeVideoPlayer\nimport com.twg.video.core.plugins.ReactNativeVideoPlugin\nimport java.lang.ref.WeakReference\n\n@OptIn(UnstableApi::class)\nclass AnalyticsPlugin : ReactNativeVideoPlugin(\"MyAnalytics\") {\n    \n    override fun onPlayerCreated(player: WeakReference<NativeVideoPlayer>) {\n        val nativePlayer = player.get() ?: return\n        val exoPlayer = nativePlayer.player\n        \n        exoPlayer.addAnalyticsListener(object : AnalyticsListener {\n            override fun onBandwidthEstimate(\n                eventTime: AnalyticsListener.EventTime,\n                totalLoadTimeMs: Int,\n                totalBytesLoaded: Long,\n                bitrateEstimate: Long\n            ) {\n                trackMetric(\"bitrate\", bitrateEstimate)\n            }\n            \n            override fun onDroppedVideoFrames(\n                eventTime: AnalyticsListener.EventTime,\n                droppedFrames: Int,\n                elapsedMs: Long\n            ) {\n                trackMetric(\"dropped_frames\", droppedFrames)\n            }\n            \n            override fun onVideoInputFormatChanged(\n                eventTime: AnalyticsListener.EventTime,\n                format: Format,\n                decoderReuseDecision: Int?\n            ) {\n                trackEvent(\"quality_change\", mapOf(\n                    \"width\" to format.width,\n                    \"height\" to format.height,\n                    \"bitrate\" to format.bitrate\n                ))\n            }\n            \n            override fun onPlaybackStateChanged(\n                eventTime: AnalyticsListener.EventTime,\n                state: Int\n            ) {\n                when (state) {\n                    Player.STATE_BUFFERING -> trackEvent(\"buffering_start\")\n                    Player.STATE_READY -> trackEvent(\"buffering_end\")\n                    Player.STATE_ENDED -> trackEvent(\"playback_complete\")\n                }\n            }\n            \n            override fun onPlayerError(\n                eventTime: AnalyticsListener.EventTime,\n                error: PlaybackException\n            ) {\n                trackEvent(\"error\", mapOf(\n                    \"code\" to error.errorCode,\n                    \"message\" to error.message\n                ))\n            }\n        })\n    }\n    \n    override fun onPlayerDestroyed(player: WeakReference<NativeVideoPlayer>) {\n        flushAnalytics()\n    }\n    \n    private fun trackEvent(name: String, params: Map<String, Any?> = emptyMap()) {\n        // Send to your analytics backend\n    }\n    \n    private fun trackMetric(name: String, value: Number) {\n        // Send to your analytics backend\n    }\n    \n    private fun flushAnalytics() {\n        // Flush pending analytics\n    }\n}\n```\n\n### iOS (Swift)\n\n```swift\nimport AVFoundation\n\nclass AnalyticsPlugin: ReactNativeVideoPlugin {\n    \n    // MARK: - Properties\n    \n    private weak var currentPlayer: AVPlayer?\n    private var rateObserver: NSKeyValueObservation?\n    private var statusObserver: NSKeyValueObservation?\n    private var timeObserver: Any?\n    \n    // MARK: - Init\n    \n    init() {\n        super.init(name: \"MyAnalytics\")\n    }\n    \n    // MARK: - Plugin Lifecycle\n    \n    override func onPlayerCreated(player: Weak<NativeVideoPlayer>) {\n        guard let nativePlayer = player.value else { return }\n        currentPlayer = nativePlayer.player\n        \n        setupPlaybackObservers(for: nativePlayer.player)\n        setupQualityTracking(for: nativePlayer.playerItem)\n    }\n    \n    override func onPlayerDestroyed(player: Weak<NativeVideoPlayer>) {\n        removeAllObservers()\n        flushAnalytics()\n    }\n    \n    // MARK: - Setup\n    \n    private func setupPlaybackObservers(for player: AVPlayer) {\n        rateObserver = player.observe(\\.rate) { [weak self] p, _ in\n            self?.trackEvent(p.rate > 0 ? \"play\" : \"pause\")\n        }\n        \n        statusObserver = player.observe(\\.status) { [weak self] p, _ in\n            if p.status == .readyToPlay {\n                self?.trackEvent(\"ready\")\n            } else if p.status == .failed {\n                self?.trackEvent(\"error\", params: [\"message\": p.error?.localizedDescription ?? \"\"])\n            }\n        }\n        \n        timeObserver = player.addPeriodicTimeObserver(\n            forInterval: CMTime(seconds: 10, preferredTimescale: 1),\n            queue: .main\n        ) { [weak self] time in\n            self?.trackMetric(\"position\", value: time.seconds)\n        }\n    }\n    \n    private func setupQualityTracking(for playerItem: AVPlayerItem?) {\n        NotificationCenter.default.addObserver(\n            self,\n            selector: #selector(handleAccessLog),\n            name: .AVPlayerItemNewAccessLogEntry,\n            object: playerItem\n        )\n    }\n    \n    @objc private func handleAccessLog(_ notification: Notification) {\n        guard let item = notification.object as? AVPlayerItem,\n              let event = item.accessLog()?.events.last else { return }\n        \n        trackMetric(\"bitrate\", value: event.indicatedBitrate)\n        trackMetric(\"stalls\", value: Double(event.numberOfStalls))\n        trackMetric(\"dropped_frames\", value: Double(event.numberOfDroppedVideoFrames))\n    }\n    \n    private func removeAllObservers() {\n        if let observer = timeObserver {\n            currentPlayer?.removeTimeObserver(observer)\n        }\n        rateObserver?.invalidate()\n        statusObserver?.invalidate()\n        NotificationCenter.default.removeObserver(self)\n        \n        currentPlayer = nil\n        timeObserver = nil\n    }\n    \n    // MARK: - Analytics\n    \n    private func trackEvent(_ name: String, params: [String: Any] = [:]) {\n        // Send to your analytics backend\n    }\n    \n    private func trackMetric(_ name: String, value: Double) {\n        // Send to your analytics backend\n    }\n    \n    private func flushAnalytics() {\n        // Flush pending analytics\n    }\n}\n```\n\n## Available Metrics\n\n### Android (ExoPlayer AnalyticsListener)\n\n| Event | Method | Data |\n|-------|--------|------|\n| Bitrate | `onBandwidthEstimate` | `bitrateEstimate` |\n| Dropped frames | `onDroppedVideoFrames` | `droppedFrames`, `elapsedMs` |\n| Quality change | `onVideoInputFormatChanged` | `format.width`, `format.height` |\n| Buffering | `onPlaybackStateChanged` | `Player.STATE_BUFFERING` |\n| Stall | `onStallStart` / `onStallEnd` | duration |\n| Seek | `onSeekStarted` / `onSeekProcessed` | position |\n| Error | `onPlayerError` | `errorCode`, `message` |\n\n### iOS (AVPlayer)\n\n| Metric | Source | Property |\n|--------|--------|----------|\n| Bitrate | `accessLog` | `indicatedBitrate` |\n| Stalls | `accessLog` | `numberOfStalls` |\n| Dropped frames | `accessLog` | `numberOfDroppedVideoFrames` |\n| Bytes | `accessLog` | `numberOfBytesTransferred` |\n| Playback status | KVO | `player.status` |\n| Play/Pause | KVO | `player.rate` |\n| Buffer | `playerItem` | `isPlaybackLikelyToKeepUp` |\n\n## Registration\n\nPlugins auto-register when instantiated. Create your plugin early in app lifecycle:\n\n**Android** - `MainApplication.kt`:\n\n```kotlin\nclass MainApplication : Application() {\n    override fun onCreate() {\n        super.onCreate()\n        AnalyticsPlugin() // Auto-registers via init block\n    }\n}\n```\n\n**iOS** - `AppDelegate.swift`:\n\n```swift\n@main\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n    private var analyticsPlugin: AnalyticsPlugin?\n    \n    func application(\n        _ application: UIApplication,\n        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n    ) -> Bool {\n        analyticsPlugin = AnalyticsPlugin() // Auto-registers via init\n        return true\n    }\n}\n```\n\n## See Also\n\n- [Plugins](../../plugins/plugins.mdx) - Full plugin system documentation\n- [Plugin Interface](../../plugins/interface.md) - Complete API reference\n"
  },
  {
    "path": "docs/docs/player/analytics/simple.md",
    "content": "---\nsidebar_position: 0\nsidebar_label: Simple (JS Events)\ndescription: Simple analytics using JavaScript events\n---\n\n# Simple Analytics\n\nThe easiest way to track video analytics is by using the JavaScript events provided by `react-native-video`. This approach requires no native code and works across all platforms.\n\n## Overview\n\nUse the `useEvent` hook to subscribe to player events. For a complete list of available events and their data, see the [Events documentation](../events.md).\n\n## Example\n\n```tsx\nimport { useVideoPlayer, useEvent, VideoView } from 'react-native-video';\n\nfunction VideoPlayer() {\n  const player = useVideoPlayer('https://example.com/video.mp4');\n\n  useEvent(player, 'onLoad', (data) => {\n    analytics.track('video_loaded', { duration: data.duration });\n  });\n\n  useEvent(player, 'onProgress', (data) => {\n    analytics.track('video_progress', { currentTime: data.currentTime });\n  });\n\n  useEvent(player, 'onError', (error) => {\n    analytics.track('video_error', { error: error.error });\n  });\n\n  useEvent(player, 'onEnd', () => {\n    analytics.track('video_completed');\n  });\n\n  return <VideoView player={player} style={{ flex: 1 }} />;\n}\n```\n\n## When to Use\n\n**Use JS Events when:**\n- You need basic playback tracking (play, pause, progress, errors)\n- You want a quick integration without native code\n- Your analytics needs are straightforward\n\n**Consider [Manual Analytics](./manual.md) when:**\n- You need low-level metrics (bitrate, dropped frames, buffer health)\n- You want to integrate with native analytics SDKs\n- You need the most accurate and detailed data\n\n## Tips\n\n1. **Throttle progress events** - `onProgress` fires frequently. Consider throttling before sending to your analytics backend.\n\n2. **Track session data** - Store a session ID to group events from the same viewing session.\n\n3. **Include video metadata** - Add video ID, title, or other metadata to your events for better reporting.\n\n```tsx\nconst sessionId = useRef(uuid()).current;\n\nconst handleProgress = (data) => {\n  // Throttle to every 10 seconds\n  if (Math.floor(data.currentTime) % 10 === 0) {\n    analytics.track('video_progress', {\n      sessionId,\n      videoId: 'video-123',\n      currentTime: data.currentTime,\n    });\n  }\n};\n```\n"
  },
  {
    "path": "docs/docs/player/downloading/_category_.json",
    "content": "{\n  \"label\": \"Downloading\",\n  \"position\": 6,\n  \"link\": null,\n  \"collapsed\": false,\n  \"customProps\": {\n    \"plan\": \"pro\"\n  }\n}\n"
  },
  {
    "path": "docs/docs/player/downloading/downloading.md",
    "content": "---\nsidebar_position: 2\nsidebar_label: Downloading\ndescription: Complete API reference for Offline Video SDK\n---\n\n# Downloading\n\n## Authorization\n\n### `registerPlugin(apiKey: string): Promise<boolean>`\n\nRegisters and authorizes the plugin with the provided API key. Must be called before using any other functions.\n\n**Parameters:**\n- `apiKey`: Your API key obtained from [sdk.thewidlarzgroup.com](https://sdk.thewidlarzgroup.com?utm_source=rnv&utm_medium=docs&utm_campaign=downloading&utm_id=downloading_api-key-param)\n\n**Returns:** `Promise<boolean>` - `true` if registration was successful, `false` otherwise\n\n```tsx\nimport { registerPlugin } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst success = await registerPlugin(\"YOUR_API_KEY\");\n```\n\n### `disablePlugin(): void`\n\nDisables the plugin. After calling this, you'll need to call `registerPlugin` again to use the SDK.\n\n```tsx\nimport { disablePlugin } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\ndisablePlugin();\n```\n\n### `isRegistered(): boolean`\n\nChecks if the plugin is currently registered and authorized.\n\n**Returns:** `boolean` - `true` if registered, `false` otherwise\n\n```tsx\nimport { isRegistered } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nif (isRegistered()) {\n  // Plugin is ready to use\n}\n```\n\n## Configuration\n\n### `setConfig(config: DownloadConfig): void`\n\nSets global configuration for downloads.\n\n**Parameters:**\n- `config`: Configuration with the following properties:\n  - `updateFrequencyMS?: number` - How often to update download progress (in milliseconds)\n  - `maxParallelDownloads?: number` - Maximum number of simultaneous downloads\n\n```tsx\nimport { setConfig } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nsetConfig({\n  updateFrequencyMS: 1000,\n  maxParallelDownloads: 3,\n});\n```\n\n### `getConfig(): DownloadConfig`\n\nGets the current global configuration.\n\n**Returns:** `DownloadConfig` with properties:\n- `updateFrequencyMS?: number`\n- `maxParallelDownloads?: number`\n\n```tsx\nimport { getConfig } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst config = getConfig();\n```\n\n## Download Management\n\n### `downloadStream(url: string, options?: DownloadOptions): Promise<DownloadStatus>` {#downloadstream}\n\nDownloads a video stream for offline playback.\n\n**Parameters:**\n- `url`: The URL of the video stream to download\n- `options`: Optional download configuration with the following properties:\n  - `includeAllTracks?: boolean` - Whether to download all available tracks (default: `false`)\n  - `tracks?: Track[]` - Array of specific tracks to download. Each track has:\n    - `id: string` - Track identifier\n    - `type: 'video' | 'audio' | 'text'` - Track type\n    - `language?: string` - Language code (for audio/text tracks)\n  - `expiresAt?: number` - Unix timestamp when the download should expire\n  - `drm?: DRMConfig` - DRM configuration (see [DRM Downloading](./drm-downloading.md) for details)\n  - `metadata?: Record<string, string>` - Custom metadata to store with the download\n\n**Returns:** `Promise<DownloadStatus>` - Status immediately after adding to queue (not after completion)\n\n**DownloadStatus properties:**\n- `id: string` - Unique download identifier\n- `url: string` - Source URL\n- `status: 'queued' | 'downloading' | 'paused' | 'completed' | 'failed' | 'cancelled'` - Current status\n- `progress: number` - Download progress (0-1)\n- `bytesDownloaded: number` - Number of bytes downloaded\n- `totalBytes: number` - Total bytes to download (may be `undefined` until known)\n\n```tsx\nimport { downloadStream } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst status = await downloadStream(\"https://example.com/video.m3u8\", {\n  tracks: [\n    { id: \"video-1\", type: \"video\" },\n    { id: \"audio-en\", type: \"audio\", language: \"en\" },\n  ],\n});\n```\n\n### `pauseDownload(id: string): Promise<void>`\n\nPauses an active download.\n\n**Parameters:**\n- `id`: The download identifier returned from `downloadStream`\n\n```tsx\nimport { pauseDownload } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nawait pauseDownload(downloadId);\n```\n\n### `resumeDownload(id: string): Promise<void>`\n\nResumes a paused download.\n\n**Parameters:**\n- `id`: The download identifier returned from `downloadStream`\n\n```tsx\nimport { resumeDownload } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nawait resumeDownload(downloadId);\n```\n\n### `cancelDownload(id: string): Promise<void>`\n\nCancels a download and removes it from the queue. Also deletes any partially downloaded files.\n\n**Parameters:**\n- `id`: The download identifier returned from `downloadStream`\n\n```tsx\nimport { cancelDownload } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nawait cancelDownload(downloadId);\n```\n\n### `cancelAllDownloads(): Promise<void>`\n\nCancels all active and queued downloads.\n\n```tsx\nimport { cancelAllDownloads } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nawait cancelAllDownloads();\n```\n\n### `getDownloadStatus(id: string): Promise<DownloadStatus | null>`\n\nGets the current status of a specific download.\n\n**Parameters:**\n- `id`: The download identifier\n\n**Returns:** `Promise<DownloadStatus | null>` - Current download status or `null` if not found\n\n```tsx\nimport { getDownloadStatus } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst status = await getDownloadStatus(downloadId);\n```\n\n### `getDownloadsStatus(): Promise<DownloadStatus[]>`\n\nGets the status of all downloads (active, queued, completed, etc.).\n\n**Returns:** `Promise<DownloadStatus[]>` - Array of all download statuses\n\n```tsx\nimport { getDownloadsStatus } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst allStatuses = await getDownloadsStatus();\n```\n\n## Track Inspection\n\n### `getAvailableTracks(url: string): Promise<AvailableTracks>` {#getavailabletracks}\n\nRetrieves information about available audio, video, and subtitle tracks in a stream.\n\n**Parameters:**\n- `url`: The URL of the video stream to inspect\n\n**Returns:** `Promise<AvailableTracks>` with the following structure:\n- `video: VideoTrack[]` - Available video tracks, each with:\n  - `id: string` - Track identifier\n  - `width: number` - Video width in pixels\n  - `height: number` - Video height in pixels\n  - `bitrate: number` - Bitrate in bits per second\n- `audio: AudioTrack[]` - Available audio tracks, each with:\n  - `id: string` - Track identifier\n  - `language: string` - Language code (e.g., \"en\", \"es\")\n  - `bitrate: number` - Bitrate in bits per second\n- `text: TextTrack[]` - Available subtitle tracks, each with:\n  - `id: string` - Track identifier\n  - `language: string` - Language code\n  - `type: string` - Subtitle format (e.g., \"text/vtt\")\n\n```tsx\nimport { getAvailableTracks } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst tracks = await getAvailableTracks(\"https://example.com/video.m3u8\");\n\n// Use tracks.video, tracks.audio, tracks.text to let user select\n// Then pass selected tracks to downloadStream\n```\n\nFor more details on track selection, see [Track Selection](./track-selection.md).\n\n## Types\n\n### `DownloadStatus` {#downloadstatus}\n\nStatus information for a download.\n\n**Properties:**\n- `id: string` - Unique download identifier\n- `url: string` - Source URL\n- `status: 'queued' | 'downloading' | 'paused' | 'completed' | 'failed' | 'cancelled'` - Current status\n- `progress: number` - Download progress (0-1)\n- `bytesDownloaded: number` - Number of bytes downloaded\n- `totalBytes: number | undefined` - Total bytes to download (may be `undefined` until known)\n\n### `DownloadOptions`\n\nConfiguration options for `downloadStream`.\n\n**Properties:**\n- `includeAllTracks?: boolean` - Whether to download all available tracks (default: `false`)\n- `tracks?: Track[]` - Array of specific tracks to download\n- `expiresAt?: number` - Unix timestamp when the download should expire\n- `drm?: DRMConfig` - DRM configuration (see [DRM Downloading](./drm-downloading.md))\n- `metadata?: Record<string, string>` - Custom metadata to store with the download\n\n### `Track`\n\nA track selection for download.\n\n**Properties:**\n- `id: string` - Track identifier\n- `type: 'video' | 'audio' | 'text'` - Track type\n- `language?: string` - Language code (for audio/text tracks)\n\n### `AvailableTracks`\n\nResult from `getAvailableTracks` containing available tracks.\n\n**Properties:**\n- `video: VideoTrack[]` - Available video tracks\n- `audio: AudioTrack[]` - Available audio tracks\n- `text: TextTrack[]` - Available subtitle tracks\n\n### `VideoTrack`\n\nInformation about a video track.\n\n**Properties:**\n- `id: string` - Track identifier\n- `width: number` - Video width in pixels\n- `height: number` - Video height in pixels\n- `bitrate: number` - Bitrate in bits per second\n\n### `AudioTrack`\n\nInformation about an audio track.\n\n**Properties:**\n- `id: string` - Track identifier\n- `language: string` - Language code (e.g., \"en\", \"es\")\n- `bitrate: number` - Bitrate in bits per second\n\n### `TextTrack`\n\nInformation about a subtitle track.\n\n**Properties:**\n- `id: string` - Track identifier\n- `language: string` - Language code\n- `type: string` - Subtitle format (e.g., \"text/vtt\")\n\n### `DownloadConfig`\n\nGlobal configuration for downloads.\n\n**Properties:**\n- `updateFrequencyMS?: number` - How often to update download progress (in milliseconds)\n- `maxParallelDownloads?: number` - Maximum number of simultaneous downloads\n\n### `DRMConfig`\n\nDRM configuration for downloading protected content.\n\n**Properties:**\n- `licenseServer: string` - URL of the license server\n- `certificateUrl?: string` - Certificate URL (required for FairPlay on iOS)\n- `headers?: Record<string, string>` - HTTP headers for license requests\n- `getLicense?: (spcData: ArrayBuffer) => Promise<ArrayBuffer>` - Custom license acquisition function (iOS only, FairPlay)\n"
  },
  {
    "path": "docs/docs/player/downloading/drm-downloading.md",
    "content": "---\nsidebar_position: 5\nsidebar_label: DRM Downloading\ndescription: Downloading and playing DRM-protected content offline\n---\n\n# DRM Downloading\n\nThe Offline Video SDK supports downloading and playing DRM-protected content offline, including support for persistent licenses.\n\n## Prerequisites\n\n:::warning Critical Requirement\nYour DRM provider **must support persistent/offline licenses**. Not all DRM providers support this feature. Contact your DRM provider to confirm offline license support before implementing.\n:::\n\nTo download DRM-protected content, you need:\n\n- **Encrypted media**: Video content encrypted with DRM (Widevine, FairPlay, PlayReady)\n- **License server**: A license server that supports **persistent/offline licenses**\n- **Short-lived token**: Authentication token for license acquisition (if required)\n\n## High-level Flow\n\n1. **Content Preparation**: Media is encrypted and packaged with DRM\n2. **License Server Configuration**: License server is configured to issue persistent licenses\n3. **Download with DRM Config**: Call `downloadStream` with DRM configuration\n4. **License Acquisition**: SDK automatically acquires and stores persistent license\n5. **Offline Playback**: Downloaded content can be played offline using the stored license\n\n## Configuration\n\nThe `drm` property in `downloadStream` accepts a `DRMConfig` with the following properties:\n- `licenseServer: string` - URL of the license server\n- `certificateUrl?: string` - Certificate URL (required for FairPlay on iOS)\n- `headers?: Record<string, string>` - HTTP headers for license requests\n- `getLicense?: (spcData: ArrayBuffer) => Promise<ArrayBuffer>` - Custom license acquisition function (iOS only, FairPlay)\n\nSee [DRMConfig](./downloading.md#drmconfig) in API Reference for complete type definition.\n\n### Basic DRM Configuration\n\n```tsx\nimport { downloadStream } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nawait downloadStream(videoUrl, {\n  drm: {\n    licenseServer: \"https://license.example.com/acquire\",\n    headers: {\n      \"Authorization\": \"Bearer YOUR_TOKEN\",\n    },\n  },\n});\n```\n\n### FairPlay (iOS)\n\nFor FairPlay on iOS, you also need to provide the certificate URL:\n\n```tsx\nawait downloadStream(videoUrl, {\n  drm: {\n    licenseServer: \"https://license.example.com/acquire\",\n    certificateUrl: \"https://license.example.com/certificate.cer\",\n    headers: {\n      \"Authorization\": \"Bearer YOUR_TOKEN\",\n    },\n  },\n});\n```\n\n### Custom License Acquisition (iOS only)\n\nOn iOS, you can provide a custom license acquisition function:\n\n```tsx\nawait downloadStream(videoUrl, {\n  drm: {\n    licenseServer: \"https://license.example.com/acquire\",\n    certificateUrl: \"https://license.example.com/certificate.cer\",\n    getLicense: async (spcData: ArrayBuffer) => {\n      // Custom license acquisition logic\n      const response = await fetch(\"https://license.example.com/acquire\", {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/octet-stream\",\n          \"Authorization\": \"Bearer YOUR_TOKEN\",\n        },\n        body: spcData,\n      });\n      return await response.arrayBuffer();\n    },\n  },\n});\n```\n\n## Platform-Specific Notes\n\n### Android\n\n- Supports Widevine and PlayReady\n- License acquisition is handled automatically by the SDK\n- Ensure your license server supports persistent licenses\n\n### iOS\n\n- Supports FairPlay\n- Requires `certificateUrl` for FairPlay\n- Custom license acquisition via `getLicense` is optional but available\n- FairPlay configuration should match your `react-native-video` DRM setup\n\n## Testing\n\n:::tip\nAlways test DRM downloading on a **real device**. Simulators/emulators may not properly handle DRM operations.\n:::\n\nWhen testing:\n1. Ensure your test content is properly encrypted\n2. Verify your license server supports persistent licenses\n3. Test on both iOS and Android devices\n4. Verify offline playback works after download completes\n5. Test license expiration scenarios\n\n## FairPlay Notes\n\nThe FairPlay configuration for offline downloading should match your `react-native-video` DRM configuration exactly. Use the same:\n- `licenseServer` URL\n- `certificateUrl`\n- `headers` (if applicable)\n- `getLicense` function (if using custom acquisition)\n\nThis ensures consistency between online and offline playback.\n"
  },
  {
    "path": "docs/docs/player/downloading/events-downloading.md",
    "content": "---\nsidebar_position: 3\nsidebar_label: Events (downloading)\ndescription: Event system for tracking download progress and status\n---\n\n# Downloading Events\n\nThe Offline Video SDK emits events that allow you to monitor and react to changes in download status and progress. You can subscribe to these events using the `useEvent` hook.\n\n## Available Events\n\n### `onError`\n\nFired when an error occurs during download.\n\n**Callback signature:**\n```tsx\n(error: string) => void\n```\n\n**Parameters:**\n- `error`: Error message describing what went wrong\n\n```tsx\nimport { useEvent } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nuseEvent(\"onError\", (error: string) => {\n  console.error(\"Download error:\", error);\n});\n```\n\n### `onDownloadProgress`\n\nFired periodically during downloads with current progress information.\n\n**Callback signature:**\n```tsx\n(downloads: DownloadStatus[]) => void\n```\n\n**Parameters:**\n- `downloads`: Array of `DownloadStatus` - See [DownloadStatus structure](./downloading.md#downloadstatus) in API Reference for complete properties\n\n```tsx\nimport { useEvent } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nuseEvent(\"onDownloadProgress\", (downloads: DownloadStatus[]) => {\n  downloads.forEach((download) => {\n    console.log(`Download ${download.id}: ${(download.progress * 100).toFixed(1)}%`);\n  });\n});\n```\n\n### `onDownloadEnd`\n\nFired when a download completes (successfully or with failure).\n\n**Callback signature:**\n```tsx\n(download: DownloadStatus) => void\n```\n\n**Parameters:**\n- `download`: Final `DownloadStatus` - See [DownloadStatus structure](./downloading.md#downloadstatus) in API Reference for complete properties. When this event fires, `status` will be either `'completed'` or `'failed'`.\n\n```tsx\nimport { useEvent } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nuseEvent(\"onDownloadEnd\", (download: DownloadStatus) => {\n  if (download.status === \"completed\") {\n    console.log(`Download ${download.id} completed successfully`);\n  } else {\n    console.log(`Download ${download.id} failed`);\n  }\n});\n```\n\n## Using Events\n\nEvents are automatically typed and can be used with the `useEvent` hook:\n\n```tsx\nimport { useEvent } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nfunction DownloadManager() {\n  useEvent(\"onDownloadProgress\", (downloads) => {\n    // Update UI with progress\n  });\n\n  useEvent(\"onDownloadEnd\", (download) => {\n    // Handle completion\n  });\n\n  useEvent(\"onError\", (error) => {\n    // Handle errors\n  });\n\n  // ... rest of component\n}\n```\n\nThe `useEvent` hook automatically manages cleanup when the component unmounts, preventing memory leaks.\n"
  },
  {
    "path": "docs/docs/player/downloading/getting-started.md",
    "content": "---\nsidebar_position: 1\nsidebar_label: Getting Started\ndescription: Installation and setup guide for Offline Video SDK\n---\n\n# Getting Started\n\nThis section covers the **Offline Video SDK** - a commercial extension for `react-native-video` that enables downloading and offline playback.\n\nThe Offline Video SDK is a commercial add-on for `react-native-video` (versions 6 and 7) that enables secure offline playback of HLS/DASH streams or static videos like MP4, including support for DRM, multiple audio tracks, and subtitles.\n\n## Requirements\n\n- **React Native Video**: version 6.15.0 or higher (versions 6 and 7 are supported)\n- **iOS**: 15.0 or higher\n- **Android**: 6.0 or higher\n- **Api key**: A valid api key for the Offline Video SDK is required. You can obtain this through the [SDK platform](https://sdk.thewidlarzgroup.com?utm_source=rnv&utm_medium=docs&utm_campaign=downloading&utm_id=getting-started_api-key-requirement).\n\n## Features\n\n- **HLS/DASH/MP4 Downloading**: Download and store video streams for offline playback\n- **Asset Management**: Full control over downloaded assets\n- **Offline DRM**: Supports offline playback of DRM-protected content with proper rights enforcement and license handling\n- **Offline Playback**: Play downloaded content without internet connection\n- **Cross-platform**: Works on both iOS and Android\n\n## Installation\n\n### 1. Configure npm for Private Package\n\nSince this is a private package, configure npm to access GitHub Packages by adding the following to your `~/.npmrc` file:\n\n```\n@TheWidlarzGroup:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=<NPM_GITHUB_AUTH_TOKEN>\n```\n\nReplace `<NPM_GITHUB_AUTH_TOKEN>` with your GitHub token. To obtain this token, please [contact us](https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=downloading&utm_id=getting-started_github-token#Contact).\n\n:::note\nThis token is different from the API key used for plugin authorization.\n:::\n\n### 2. Install the Package\n\nInstall the package using npm:\n\n```bash\nnpm install @TheWidlarzGroup/react-native-video-stream-downloader\n```\n\n### 3. Android Configuration\n\nAdd the following line to your `./android/app/build.gradle` file in the `dependencies` block:\n\n```groovy\nimplementation fileTree(dir: \"../../node_modules/@TheWidlarzGroup/react-native-video-stream-downloader/native-libs\", include: [\"*.aar\"])\n```\n\nEnsure the path matches your project's `node_modules` location.\n\n### 4. iOS Configuration\n\nNo additional configuration is required for iOS; the plugin will be automatically linked.\n\n### 5. Plugin Authorization\n\nAfter installation, authorize the plugin with an API key:\n\n```tsx\nimport { registerPlugin } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst success = await registerPlugin(\"YOUR_API_KEY\");\n```\n\nReplace `\"YOUR_API_KEY\"` with your actual API key obtained from [sdk.thewidlarzgroup.com](https://sdk.thewidlarzgroup.com?utm_source=rnv&utm_medium=docs&utm_campaign=downloading&utm_id=getting-started_api-key-link).\n\n## Supported Formats\n\n| Format | iOS | Android |\n|--------|-----|---------|\n| HLS | ✅ | ✅ |\n| MP4 | ✅ | ✅ |\n| MPEG-DASH | ❌ | ✅ |\n\n## Licensing & Pricing\n\nThe Offline Video SDK is distributed under a commercial license. You can evaluate it for free for 14 days without a credit card. For questions or assistance, contact [hi@thewidlarzgroup.com](mailto:hi@thewidlarzgroup.com).\n"
  },
  {
    "path": "docs/docs/player/downloading/track-selection.md",
    "content": "---\nsidebar_position: 4\nsidebar_label: Track Selection\ndescription: How to select specific tracks for download\n---\n\n# Track Selection\n\nTrack selection allows you to download only the specific audio, video, and subtitle tracks you need, optimizing storage usage and download time.\n\n## Why Select Tracks?\n\n- **Storage Optimization**: Download only the tracks you need (e.g., specific language, resolution)\n- **Language Support**: Choose audio tracks in different languages\n- **Subtitle Selection**: Download only the subtitle languages your users need\n- **Bitrate Control**: Select video tracks with appropriate bitrates for your use case\n\n## How It Works\n\nThe track selection process follows a 2-step flow:\n\n1. **Inspect Available Tracks**: Use `getAvailableTracks(url)` to retrieve all available tracks\n2. **Select Tracks for Download**: Pass the selected track IDs to `downloadStream` in the `tracks` property\n\n### Step 1: Get Available Tracks\n\nUse `getAvailableTracks` to retrieve all available tracks. See [getAvailableTracks](./downloading.md#getavailabletracks) in API Reference for complete details.\n\n```tsx\nimport { getAvailableTracks } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst tracks = await getAvailableTracks(\"https://example.com/video.m3u8\");\n// tracks.video, tracks.audio, tracks.text contain available tracks\n```\n\n### Step 2: Download Selected Tracks\n\n```tsx\nimport { downloadStream } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\n// Select specific tracks\nconst selectedTracks = [\n  tracks.video[0].id, // First video track (usually highest quality)\n  tracks.audio.find(t => t.language === \"en\")?.id, // English audio\n  tracks.text.find(t => t.language === \"en\")?.id, // English subtitles\n].filter(Boolean); // Remove undefined values\n\nawait downloadStream(\"https://example.com/video.m3u8\", {\n  tracks: selectedTracks.map(id => ({ id, type: \"video\" })), // You need to specify type\n});\n```\n\n## Example: Multi-Language Selection\n\n```tsx\nimport { getAvailableTracks, downloadStream } from \"@TheWidlarzGroup/react-native-video-stream-downloader\";\n\nconst tracks = await getAvailableTracks(videoUrl);\n\n// Select video track (highest quality)\nconst videoTrack = tracks.video[0];\n\n// Select multiple audio tracks (English and Spanish)\nconst audioTracks = tracks.audio.filter(t => \n  t.language === \"en\" || t.language === \"es\"\n);\n\n// Select subtitles for both languages\nconst subtitleTracks = tracks.text.filter(t => \n  t.language === \"en\" || t.language === \"es\"\n);\n\n// Build track selection array\nconst selectedTracks = [\n  { id: videoTrack.id, type: \"video\" as const },\n  ...audioTracks.map(t => ({ id: t.id, type: \"audio\" as const })),\n  ...subtitleTracks.map(t => ({ id: t.id, type: \"text\" as const })),\n];\n\nawait downloadStream(videoUrl, {\n  tracks: selectedTracks,\n});\n```\n\n## Default Behavior\n\nIf you don't specify `tracks` in `downloadStream`, or if `includeAllTracks` is `false`, only the default tracks are downloaded (typically the first video track and the first audio track).\n\nTo download all available tracks, set `includeAllTracks: true`:\n\n```tsx\nawait downloadStream(videoUrl, {\n  includeAllTracks: true,\n});\n```\n"
  },
  {
    "path": "docs/docs/player/drm.md",
    "content": "---\nsidebar_position: 4\nsidebar_label: DRM\n---\n\n# DRM\n\n## What is DRM (Digital Rights Management)?\nDRM is a set of access control technologies that are used to protect copyrighted content from unauthorized use and distribution. It allows content owners to control how their digital media is used and distributed.\n\n### When do you need it?\nIf you are working with copyrighted content and want to prevent unauthorized access or distribution, you will need DRM. It is especially important for streaming services, e-learning platforms, and any application that delivers premium content that you want to protect from piracy.\n\n### What next?\nThis page explains how to play DRM‑protected content with React Native Video using the official DRM plugin. It covers installing and enabling the plugin, configuring sources with DRM, and platform‑specific notes for Android (Widevine) and iOS/visionOS (FairPlay).\n\n## Install and enable the DRM plugin\n\n:::tip Pluginable Architecture\nReact Native Video uses a plugin architecture. DRM support is provided by the `@react-native-video/drm` plugin and is not built into the core package.\n:::\n\n1) Install dependencies in your app:\n\n```sh\nnpm install @react-native-video/drm\n```\n\n2) Enable the plugin at app startup (before creating any players):\n\n```ts\n// App.tsx (or any place you want to initialize the plugin)\nimport { enable } from '@react-native-video/drm';\n\nenable();\n```\n\nThe plugin autolinks on both Android and iOS. Nitro Modules are required because the plugin uses Nitro under the hood.\n\n## Quick start\n\nYou pass DRM configuration via `VideoConfig.drm` when creating a player or using the `useVideoPlayer` hook. If `drm.type` is omitted, the default is inferred per platform (`widevine` on Android, `fairplay` on iOS/visionOS).\n\n```tsx\nimport { VideoView, useVideoPlayer } from 'react-native-video';\n\nexport function Player() {\n  const player = useVideoPlayer({\n    source: {\n    uri: 'https://example.com/manifest.mpd', // or HLS .m3u8 for FairPlay\n    // On iOS these headers are also used for the default license request\n    headers: { Authorization: 'Bearer <token>' },\n    drm: {\n      // type: 'widevine' | 'fairplay'  // optional; inferred by platform\n      licenseUrl: 'https://license.example.com/widevine',\n    },\n  },\n  });\n\n  return <VideoView player={player} />;\n}\n```\n\n:::warning\nYou shouldn't include your authorization token directly in the code. Instead, use a backend method to retrieve it at runtime.\n:::\n\n## DRM config reference\n\nAll properties are optional unless marked otherwise for a platform. The table below describes each property, the expected type, platforms where it applies, whether it's required, and important notes.\n\n| Property | Type | Platform | Required | Notes |\n|---|---:|---|:---:|---|\n| `type` | `'widevine' \\| 'fairplay'` | Android, iOS, visionOS | No (defaulted) | Default inferred per platform when `drm` is present and `type` omitted (Android → `widevine`, iOS/visionOS → `fairplay`). |\n| `licenseUrl` | `string` | Android, iOS, visionOS | Android: Yes; iOS/visionOS: Yes for default/custom flows | URL of the license (CKC) service. Required for license acquisition. |\n| `licenseHeaders` | ``Record<string, string>`` | Android | No | Extra headers sent with the Widevine license request. (On iOS, use `source.headers` for license requests.) |\n| `multiSession` | `boolean` | Android | No | Whether to allow multiple Widevine sessions. |\n| `certificateUrl` | `string` | iOS, visionOS | Yes (for FairPlay) | URL to fetch the FairPlay application certificate (used to create the SPC). |\n| `contentId` | `string` | iOS, visionOS | No | If omitted, derived from the `skd://` key URL. Used when creating the SPC. |\n| `getLicense` | ``(payload) => Promise<string>`` | iOS, visionOS | No | Optional hook for custom FairPlay license logic; must resolve to a base64‑encoded CKC string. |\n\nPayload shape passed to `getLicense` (iOS/visionOS):\n\n| Field | Type | Description |\n|---|---:|---|\n| `contentId` | `string` | Content identifier for the asset. If not provided the player will try to derive it from the `skd://` key URL. |\n| `licenseUrl` | `string` | The license server URL that should be used for license acquisition. |\n| `keyUrl` | `string` | The key URL/identifier received from the stream (typically an `skd://` URL). |\n| `spc` | `string` | The SPC (secure playback context) as a base64‑encoded string. Send raw SPC bytes to your license server (server side may expect raw bytes rather than base64). |\n\n## Android: Widevine\n\n- Set `drm.type` to `'widevine'` or omit it (the library will default to Widevine on Android if `drm` is present).\n- `licenseUrl` is required; `licenseHeaders` and `multiSession` are optional.\n- Implementation details:\n\t- The plugin uses ExoPlayer’s `DefaultDrmSessionManager` and `HttpMediaDrmCallback` with your `licenseUrl` and `licenseHeaders`.\n\t- If a first attempt fails due to device security level issues, the plugin retries with `L3` security level.\n\nExample:\n\n```tsx\nuseVideoPlayer({\n  source: {\n    uri: 'https://example.com/manifest.mpd',\n    drm: {\n      // type: 'widevine', // optional\n      licenseUrl: 'https://license.example.com/widevine',\n      licenseHeaders: { 'X-Custom-Header': 'value' },\n      multiSession: false,\n    },\n  },\n});\n```\n\n## iOS and visionOS: FairPlay\n\nTwo ways to get the CKC (license):\n\n1) Default flow (no `getLicense`):\n\t - Required: `certificateUrl`, `licenseUrl`.\n\t - The plugin requests the application certificate, generates the SPC, then POSTs the SPC to `licenseUrl`.\n\t - It uses `source.headers` (not `drm.licenseHeaders`) for the license request.\n\n2) Custom flow (provide `getLicense`):\n\t - Required: `certificateUrl`, `licenseUrl`, and a `getLicense` implementation.\n\t - You receive `{ contentId, licenseUrl, keyUrl, spc }` and must return a base64‑encoded CKC string.\n\nNotes:\n- DRM isn’t supported in the iOS Simulator; the plugin returns `null` for DRM in Simulator builds.\n- If `contentId` isn’t provided, it is derived from the `skd://` key URL.\n\nDefault flow example:\n\n```tsx\nuseVideoPlayer({\n  source: {\n    uri: 'https://example.com/fairplay.m3u8',\n    headers: { Authorization: 'Bearer <token>' }, // used for the license request\n    drm: {\n      // type: 'fairplay', // optional\n      certificateUrl: 'https://license.example.com/fps-cert',\n      licenseUrl: 'https://license.example.com/fps',\n      // contentId: 'my-content-id', // optional\n    },\n  },\n});\n```\n\nCustom `getLicense` example:\n\n:::tip\nThis is example code for a custom `getLicense` implementation. it may differ from your actual implementation provided by your DRM provider\n:::\n\n```tsx\nuseVideoPlayer({\n  source: {\n  uri: 'https://example.com/fairplay.m3u8',\n  drm: {\n    certificateUrl: 'https://license.example.com/fps-cert',\n    licenseUrl: 'https://license.example.com/fps',\n    getLicense: async ({ contentId, licenseUrl, keyUrl, spc }) => {\n      // Example: POST SPC to your license server and return base64 CKC\n        const res = await fetch(licenseUrl, {\n          method: 'POST',\n          body: Buffer.from(spc, 'base64'), // server expects raw SPC bytes\n          headers: {\n            'Content-Type': 'application/octet-stream',\n            'X-Content-ID': contentId,\n            'X-Asset-Id': keyUrl,\n          },\n        });\n        if (!res.ok) throw new Error(`License request failed: ${res.status}`);\n        const ckc = await res.arrayBuffer();\n        // return base64 CKC string\n        return Buffer.from(ckc).toString('base64');\n      },\n    },\n  },\n});\n```\n\n## Offline\nIf you are looking for implementing offline playback with DRM, make sure to checkout our [Offline Video SDK](https://www.thewidlarzgroup.com/offline-video-sdk?utm_source=rnv&utm_medium=docs&utm_campaign=drm&utm_id=offline-sdk-link). It provides a comprehensive solution for downloading and playing Streams and DRM-protected content.\n\n## Troubleshooting\n\n- DRMPluginNotFound: Ensure you installed `@react-native-video/drm`, imported it, and called `enable()` before creating any players.\n- iOS headers: The default FairPlay flow uses `source.headers` for license requests; `drm.licenseHeaders` are not used on iOS.\n- Invalid CKC: `getLicense` must return a base64 string. Returning raw bytes or JSON will fail.\n- 403/415 from license server: Verify required auth headers, content type, and whether the server expects raw SPC bytes vs base64.\n- Android security level issues: The plugin retries with Widevine L3 if the first attempt fails.\n- iOS Simulator: DRM isn’t supported in Simulator. Test on a real device.\n\n## Notes and defaults\n\n- If `drm` is provided without `type`, the library sets a platform default: Android → Widevine, iOS/visionOS → FairPlay.\n- For custom DRM systems or advanced pipelines, you can implement your own plugin. See the Plugin Interface docs.\n\n"
  },
  {
    "path": "docs/docs/player/events.md",
    "content": "---\nsidebar_label: Events\nsidebar_position: 5\n---\n\n# Handling Player Events\n\nThe `VideoPlayer` emits a variety of events that allow you to monitor and react to changes in its state and playback.\n\n## Using the `useEvent` Hook\n\nFor React functional components, the `useEvent` hook provides a convenient way to subscribe to player events and automatically manage cleanup.\n\n```typescript\nimport { useVideoPlayer, useEvent } from 'react-native-video';\nimport { useEffect } from 'react';\n\nconst MyVideoComponent = () => {\n  const player = useVideoPlayer('https://example.com/video.mp4', (_player) => {\n    _player.play();\n  });\n\n  useEvent(player, 'onLoad', (data) => {\n    console.log('Video loaded via useEvent! Duration:', data.duration);\n  });\n\n  useEvent(player, 'onProgress', (data) => {\n    console.log('Progress via useEvent:', data.currentTime);\n  });\n\n  // For onError, which is a direct property on VideoPlayer, not from VideoPlayerEvents\n  useEvent(player, 'onError', (error) => {\n    console.error('Player Error via useEvent:', error.code, error.message);\n  });\n\n  return <VideoView player={player} />;\n};\n```\n\n## Available Events\n\nThe `VideoPlayer` class, through `VideoPlayerEvents`, supports the following events. You can subscribe to these by assigning a callback function to the corresponding property on the `VideoPlayer` instance.\n\n| Event                      | Callback Signature                                      | Description                                                                                 |\n|----------------------------|--------------------------------------------------------|---------------------------------------------------------------------------------------------|\n| `onAudioBecomingNoisy`     | () => void                                           | Fired when audio is about to become noisy (e.g., headphones unplugged).                     |\n| `onAudioFocusChange`       | (hasAudioFocus: boolean) => void                     | Fired when the audio focus changes (e.g., another app starts playing audio).                |\n| `onBandwidthUpdate`        | (data: [BandwidthData](../api-reference/interfaces/BandwidthData.md)) => void                        | Fired with an estimate of the available bandwidth.                                          |\n| `onBuffer`                 | (buffering: boolean) => void                         | Fired when the player starts or stops buffering data.                                       |\n| `onControlsVisibleChange`  | (visible: boolean) => void                           | Fired when the visibility of native controls changes.                                       |\n| `onEnd`                    | () => void                                           | Fired when the video playback reaches the end.                                              |\n| `onExternalPlaybackChange` | (externalPlaybackActive: boolean) => void            | Fired when the external playback status changes (e.g., AirPlay).                            |\n| `onLoad`                   | (data: [onLoadData](../api-reference/interfaces/onLoadData.md)) => void                           | Fired when the video has loaded and is ready to play.                                       |\n| `onLoadStart`              | (data: [onLoadStartData](../api-reference/interfaces/onLoadStartData.md)) => void                      | Fired when the video starts loading.                                                        |\n| `onPlaybackRateChange`     | (rate: number) => void                               | Fired when the playback rate changes.                                                       |\n| `onPlaybackStateChange`    | (data: [onPlaybackStateChangeData](../api-reference/interfaces/onPlaybackStateChangeData.md)) => void            | Fired when the playback state changes (e.g., playing, paused, stopped).                     |\n| `onProgress`               | (data: [onProgressData](../api-reference/interfaces/onProgressData.md)) => void                       | Fired periodically during playback with the current time.                                   |\n| `onReadyToDisplay`         | () => void                                           | Fired when the player is ready to display the first frame of the video.                     |\n| `onSeek`                   | (seekTime: number) => void                           | Fired when a seek operation has completed.                                                  |\n| `onStatusChange`           | (status: [VideoPlayerStatus](../api-reference/type-aliases/VideoPlayerStatus.md)) => void                  | Fired when the player status changes (detailed status updates).                             |\n| `onTextTrackDataChanged`   | (texts: string[]) => void                            | Fired when text track data (e.g., subtitles) changes.                                       |\n| `onTimedMetadata`          | (metadata: [TimedMetadata](../api-reference/interfaces/TimedMetadata.md)) => void                    | Fired when timed metadata is encountered in the video stream.                               |\n| `onTrackChange`            | (track: [TextTrack](../api-reference/interfaces/TextTrack.md) \\| null) => void                    | Fired when the selected text track changes.                                                 |\n| `onVolumeChange`           | (data: [onVolumeChangeData](../api-reference/interfaces/onVolumeChangeData.md)) => void     | Fired when the volume changes.                                                              |\n\nAdditionally, the `VideoPlayer` instance itself has an `onError` property:\n\n-   `onError: (error: ` [VideoRuntimeError](../api-reference/interfaces/VideoRuntimeError.md) `) => void` - Fired when an error occurs. The callback receives the `VideoRuntimeError` object.\n\n**Benefits of `useEvent`**:\n\n-   **Automatic Cleanup**: The event listener is automatically removed when the component unmounts or when the `player`, `event`, or `callback` dependencies change, preventing memory leaks.\n-   **Type Safety**: Provides better type inference for event callback parameters.\n\nThis hook is recommended for managing event subscriptions in a declarative React style. \n\n### Initialization Timing and Events\n\n`onLoadStart` / `onLoad` will fire automatically after construction when `initializeOnCreation` (default `true`) is enabled. If you set `initializeOnCreation: false`, these events will not fire until you call `initialize()` or `preload()`. Attach your event handlers before invoking those methods to avoid missing early events.\n\n## Subscribing to Events\n\nYou can subscribe to an event by assigning a function to the player instance's corresponding property:\n\n```typescript\nimport { VideoPlayer } from 'react-native-video';\n\nconst player = new VideoPlayer('https://example.com/video.mp4');\n\nplayer.addEventListener('onLoad', (data) => {\n  console.log('Video loaded! Duration:', data.duration);\n});\n\nplayer.addEventListener('onProgress', (data) => {\n  console.log('Current time:', data.currentTime);\n});\n\nplayer.addEventListener('onError', (error) => {\n  console.error('Player Error:', error.code, error.message);\n});\n\nplayer.play();\n```\n\n## Clearing Events\n\n-   The `player.clearEvent(eventName)` method can be used to clear a specific native event handler.\n-   When a player instance is no longer needed and `player.release()` is called, all event listeners are automatically cleared\n"
  },
  {
    "path": "docs/docs/player/player.md",
    "content": "---\nsidebar_position: 1\nsidebar_label: Player\n---\n\n# Player\n\nThe `VideoPlayer` class is the primary way to control video playback. It provides methods and properties to manage the video source, playback state, volume, and other aspects of the video.\n\n## Initialization\n\nTo use the `VideoPlayer`, you first need to create an instance of it with a video source. There are two ways to do this. By default the native media item is initialized asynchronously right after creation (unless you opt out with `initializeOnCreation: false`).\n\n### Using `useVideoPlayer` hook\n\n```tsx\nimport { useVideoPlayer } from 'react-native-video';\n\nconst player = useVideoPlayer({\n  source: {\n    uri: 'https://www.w3schools.com/html/mov_bbb.mp4',\n  },\n});\n```\n\n:::info\n`useVideoPlayer` hook is recommended for most use cases. It automatically manages the player lifecycle between the component mount and unmount.\n:::\n\nFor detailed information about using the hook, see [useVideoPlayer](./use-video-player.md).\n\n### Using `VideoPlayer` class constructor directly\n\n```typescript\nimport { VideoPlayer } from 'react-native-video';\n\n// Using a URL string\nconst player = new VideoPlayer('https://example.com/video.mp4');\n\n// Using a VideoSource object\nconst playerWithSource = new VideoPlayer({ uri: 'https://example.com/video.mp4' });\n\n// Using a VideoConfig object\nconst playerWithConfig = new VideoPlayer({\n  source: { uri: 'https://example.com/video.mp4' },\n  // other configurations\n});\n```\n\n:::warning\nWhen using `VideoPlayer` class directly, you need to manually manage the player lifecycle. Once you no longer need the player, you need to call `release()` method to release the player's native resources. See [Player Lifecycle](./video-player.md#player-lifecycle) for more details.\n:::\n\nFor detailed information about using the class, see [VideoPlayer](./video-player.md).\n"
  },
  {
    "path": "docs/docs/player/use-video-player.md",
    "content": "---\nsidebar_position: 2\nsidebar_label: useVideoPlayer\n---\n\n# useVideoPlayer\n\nThe `useVideoPlayer` hook is the recommended way to create and manage a `VideoPlayer` instance in React components. It automatically handles the player lifecycle, ensuring resources are properly released when the component unmounts.\n\n## Quick Start\n\nThe simplest way to use the hook is to pass a video source:\n\n```tsx\nimport { useVideoPlayer } from 'react-native-video';\n\nconst player = useVideoPlayer('https://www.w3schools.com/html/mov_bbb.mp4');\n```\n\nYou can also pass a configuration object for more control:\n\n```tsx\nconst player = useVideoPlayer({\n  source: {\n    uri: 'https://www.w3schools.com/html/mov_bbb.mp4',\n  },\n});\n```\n\n## Why useVideoPlayer?\n\nThe `useVideoPlayer` hook provides several advantages over creating a `VideoPlayer` instance directly:\n\n- **Automatic lifecycle management**: The player is automatically released when the component unmounts\n- **React-friendly**: Works seamlessly with React's component lifecycle\n\n:::info\nFor most React components, `useVideoPlayer` is the recommended approach. If you need more control over the player lifecycle, see [VideoPlayer class](./video-player.md) for direct instantiation.\n:::\n\n## Using the Player Instance\n\nThe `useVideoPlayer` hook returns a `VideoPlayer` instance that you can use to control playback:\n\n```tsx\nimport { useVideoPlayer } from 'react-native-video';\n\nconst player = useVideoPlayer('https://example.com/video.mp4');\n\n// Control playback\nplayer.play();\nplayer.pause();\nplayer.muted = true;\n```\n\n### Playback Control\n\n| Method | Description |\n|--------|-------------|\n| `play()` | Starts or resumes video playback. |\n| `pause()` | Pauses video playback. |\n| `seekBy(time: number)` | Seeks the video forward or backward by the specified number of seconds. |\n| `seekTo(time: number)` | Seeks the video to a specific time in seconds. |\n| `replaceSourceAsync(source: VideoSource \\| VideoConfig \\| null)` | Replaces the current video source with a new one. Pass `null` to release the current source without replacing it. |\n| `initialize()` | Manually initialize the underlying native player item when `initializeOnCreation` was set to `false`. No-op if already initialized. |\n| `preload()` | Ensures the media source is set and prepared (buffering started) without starting playback. If not yet initialized it will initialize first. |\n| `release()` | Releases the player's native resources. The player is no longer usable after calling this method. **Note:** If you intend to reuse the player instance with a different source, use `replaceSourceAsync(null)` to clear resources instead of `release()`. |\n\n### Properties\n\n| Property | Access | Type | Description |\n|----------|--------|------|-------------|\n| `source` | Read-only | `VideoPlayerSource` | Gets the current `VideoPlayerSource` object. |\n| `status` | Read-only | `VideoPlayerStatus` | Gets the current status (e.g., `playing`, `paused`, `buffering`). |\n| `duration` | Read-only | `number` | Gets the total duration of the video in seconds. Returns `NaN` until metadata is loaded. |\n| `volume` | Read/Write | `number` | Gets or sets the player volume (0.0 to 1.0). |\n| `currentTime` | Read/Write | `number` | Gets or sets the current playback time in seconds. |\n| `muted` | Read/Write | `boolean` | Gets or sets whether the video is muted. |\n| `loop` | Read/Write | `boolean` | Gets or sets whether the video should loop. |\n| `rate` | Read/Write | `number` | Gets or sets the playback rate (e.g., 1.0 for normal speed, 0.5 for half speed, 2.0 for double speed). |\n| `mixAudioMode` | Read/Write | `MixAudioMode` | Controls how this player's audio mixes with other audio sources (see [MixAudioMode](../api-reference/type-aliases/MixAudioMode.md)). |\n| `ignoreSilentSwitchMode` | Read/Write | `IgnoreSilentSwitchMode` | iOS-only. Determines how audio should behave when the hardware mute (silent) switch is on. |\n| `playInBackground` | Read/Write | `boolean` | Whether playback should continue when the app goes to the background. |\n| `playWhenInactive` | Read/Write | `boolean` | Whether playback should continue when the app is inactive (e.g., during a phone call). |\n| `isPlaying` | Read-only | `boolean` | Returns `true` if the video is currently playing. |\n| `selectedTrack` | Read-only | `TextTrack \\| undefined` | Currently selected text track, or `undefined` when no track is selected. |\n\n### Error Handling\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `onError?` | `(error: VideoRuntimeError) => void` | A callback function that is invoked when a runtime error occurs in the player. You can use this to catch and handle errors gracefully. |\n\n### Buffer Config\n\nYou can fine‑tune buffering via `bufferConfig` on the `VideoConfig` you pass to `useVideoPlayer`/`VideoPlayer`. This controls how much data is buffered, live latency targets, and iOS network constraints.\n\nExample\n\n```ts\nconst player = useVideoPlayer({\n  source: {\n    uri: 'https://example.com/stream.m3u8',\n    bufferConfig: {\n      // Android\n      minBufferMs: 5000,\n      maxBufferMs: 10000,\n      // iOS\n      preferredForwardBufferDurationMs: 3000,\n      // Live (cross‑platform target)\n      livePlayback: { targetOffsetMs: 500 },\n    },\n  },\n});\n```\n\n#### Android\nProperties below are Android‑only\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `minBufferMs` | `number` | Minimum media duration the player attempts to keep buffered (ms). Default: 5000. |\n| `maxBufferMs` | `number` | Maximum media duration the player attempts to buffer (ms). Default: 10000. |\n| `bufferForPlaybackMs` | `number` | Media that must be buffered before playback can start or resume after user action (ms). Default: 1000. |\n| `bufferForPlaybackAfterRebufferMs` | `number` | Media that must be buffered to resume after a rebuffer (ms). Default: 2000. |\n| `backBufferDurationMs` | `number` | Duration kept behind the current position to allow instant rewind without rebuffer (ms). |\n| `livePlayback.minPlaybackSpeed` | `number` | Minimum playback speed used to maintain target live offset. |\n| `livePlayback.maxPlaybackSpeed` | `number` | Maximum playback speed used to catch up to target live offset. |\n| `livePlayback.minOffsetMs` | `number` | Minimum allowed live offset (ms). |\n| `livePlayback.maxOffsetMs` | `number` | Maximum allowed live offset (ms). |\n| `livePlayback.targetOffsetMs` | `number` | Target live offset the player tries to maintain (ms). |\n\n#### iOS, visionOS, tvOS\nProperties below are Apple platforms‑only\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `preferredForwardBufferDurationMs` | `number` | Preferred duration the player attempts to retain ahead of the playhead (ms). |\n| `preferredPeakBitRate` | `number` | Desired limit of network bandwidth for loading the current item (bits per second). |\n| `preferredMaximumResolution` | `{ width: number; height: number }` | Preferred maximum video resolution. |\n| `preferredPeakBitRateForExpensiveNetworks` | `number` | Bandwidth limit for expensive networks (e.g., cellular), in bits per second. |\n| `preferredMaximumResolutionForExpensiveNetworks` | `{ width: number; height: number }` | Preferred maximum resolution on expensive networks. |\n| `livePlayback.targetOffsetMs` | `number` | Target live offset (ms) the player will try to maintain. |\n\n## DRM\n\nProtected content is supported via a plugin. See the full DRM guide: [DRM](./drm.md).\n\nQuick notes:\n- Install and enable the official plugin `@react-native-video/drm` and call `enable()` at app startup before creating players.\n- Pass DRM configuration on the source using the `drm` property of `VideoConfig` (see the DRM guide for platform specifics and `getLicense` examples).\n- If you defer initialization (`initializeOnCreation: false`), be sure to call `await player.initialize()` (or `preload()`) before expecting DRM license acquisition events."
  },
  {
    "path": "docs/docs/player/video-player.md",
    "content": "---\nsidebar_position: 3\nsidebar_label: VideoPlayer\n---\n\n# VideoPlayer\n\n:::tip When to Use What\n- **[`useVideoPlayer`](./use-video-player.md) hook** - Recommended for most cases. Automatically manages player lifecycle (creation, cleanup on unmount, source changes).\n- **`VideoPlayer` class** - Use when you need manual lifecycle control, e.g., preloading videos before displaying them, managing multiple players with custom logic, or deferred initialization scenarios.\n:::\n\nThe `VideoPlayer` class is the primary way to control video playback. It provides methods and properties to manage the video source, playback state, volume, and other aspects of the video.\n\n## Initialization\n\nTo use the `VideoPlayer`, you first need to create an instance of it with a video source. By default the native media item is initialized asynchronously right after creation (unless you opt out with `initializeOnCreation: false`).\n\n```typescript\nimport { VideoPlayer } from 'react-native-video';\n\n// Using a URL string\nconst player = new VideoPlayer('https://example.com/video.mp4');\n\n// Using a VideoSource object\nconst playerWithSource = new VideoPlayer({ uri: 'https://example.com/video.mp4' });\n\n// Using a VideoConfig object\nconst playerWithConfig = new VideoPlayer({\n  source: { uri: 'https://example.com/video.mp4' },\n  // other configurations\n});\n```\n\n:::warning\nWhen using `VideoPlayer` class directly, you need to manually manage the player lifecycle. Once you no longer need the player, you need to call `release()` method to release the player's native resources. See the [Player Lifecycle](#player-lifecycle) section below for more details.\n:::\n\n## Core Functionality\n\nThe `VideoPlayer` class offers a comprehensive set of methods and properties to control video playback:\n\n### Playback Control\n\n| Method | Description |\n|--------|-------------|\n| `play()` | Starts or resumes video playback. |\n| `pause()` | Pauses video playback. |\n| `seekBy(time: number)` | Seeks the video forward or backward by the specified number of seconds. |\n| `seekTo(time: number)` | Seeks the video to a specific time in seconds. |\n| `replaceSourceAsync(source: VideoSource \\| VideoConfig \\| null)` | Replaces the current video source with a new one. Pass `null` to release the current source without replacing it. |\n| `initialize()` | Manually initialize the underlying native player item when `initializeOnCreation` was set to `false`. No-op if already initialized. |\n| `preload()` | Ensures the media source is set and prepared (buffering started) without starting playback. If not yet initialized it will initialize first. |\n| `release()` | Releases the player's native resources. The player is no longer usable after calling this method. **Note:** If you intend to reuse the player instance with a different source, use `replaceSourceAsync(null)` to clear resources instead of `release()`. |\n\n### Properties\n\n| Property | Access | Type | Description |\n|----------|--------|------|-------------|\n| `source` | Read-only | `VideoPlayerSource` | Gets the current `VideoPlayerSource` object. |\n| `status` | Read-only | `VideoPlayerStatus` | Gets the current status (e.g., `playing`, `paused`, `buffering`). |\n| `duration` | Read-only | `number` | Gets the total duration of the video in seconds. Returns `NaN` until metadata is loaded. |\n| `volume` | Read/Write | `number` | Gets or sets the player volume (0.0 to 1.0). |\n| `currentTime` | Read/Write | `number` | Gets or sets the current playback time in seconds. |\n| `muted` | Read/Write | `boolean` | Gets or sets whether the video is muted. |\n| `loop` | Read/Write | `boolean` | Gets or sets whether the video should loop. |\n| `rate` | Read/Write | `number` | Gets or sets the playback rate (e.g., 1.0 for normal speed, 0.5 for half speed, 2.0 for double speed). |\n| `mixAudioMode` | Read/Write | `MixAudioMode` | Controls how this player's audio mixes with other audio sources (see [MixAudioMode](../api-reference/type-aliases/MixAudioMode.md)). |\n| `ignoreSilentSwitchMode` | Read/Write | `IgnoreSilentSwitchMode` | iOS-only. Determines how audio should behave when the hardware mute (silent) switch is on. |\n| `playInBackground` | Read/Write | `boolean` | Whether playback should continue when the app goes to the background. |\n| `playWhenInactive` | Read/Write | `boolean` | Whether playback should continue when the app is inactive (e.g., during a phone call). |\n| `isPlaying` | Read-only | `boolean` | Returns `true` if the video is currently playing. |\n| `selectedTrack` | Read-only | `TextTrack \\| undefined` | Currently selected text track, or `undefined` when no track is selected. |\n\n### Error Handling\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `onError?` | `(error: VideoRuntimeError) => void` | A callback function that is invoked when a runtime error occurs in the player. You can use this to catch and handle errors gracefully. |\n\n### Buffer Config\n\nYou can fine‑tune buffering via `bufferConfig` on the `VideoConfig` you pass to `useVideoPlayer`/`VideoPlayer`. This controls how much data is buffered, live latency targets, and iOS network constraints.\n\nExample\n\n```ts\nconst player = new VideoPlayer({\n  source: {\n    uri: 'https://example.com/stream.m3u8',\n    bufferConfig: {\n      // Android\n      minBufferMs: 5000,\n      maxBufferMs: 10000,\n      // iOS\n      preferredForwardBufferDurationMs: 3000,\n      // Live (cross‑platform target)\n      livePlayback: { targetOffsetMs: 500 },\n    },\n  },\n});\n```\n\n#### Android\nProperties below are Android‑only\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `minBufferMs` | `number` | Minimum media duration the player attempts to keep buffered (ms). Default: 5000. |\n| `maxBufferMs` | `number` | Maximum media duration the player attempts to buffer (ms). Default: 10000. |\n| `bufferForPlaybackMs` | `number` | Media that must be buffered before playback can start or resume after user action (ms). Default: 1000. |\n| `bufferForPlaybackAfterRebufferMs` | `number` | Media that must be buffered to resume after a rebuffer (ms). Default: 2000. |\n| `backBufferDurationMs` | `number` | Duration kept behind the current position to allow instant rewind without rebuffer (ms). |\n| `livePlayback.minPlaybackSpeed` | `number` | Minimum playback speed used to maintain target live offset. |\n| `livePlayback.maxPlaybackSpeed` | `number` | Maximum playback speed used to catch up to target live offset. |\n| `livePlayback.minOffsetMs` | `number` | Minimum allowed live offset (ms). |\n| `livePlayback.maxOffsetMs` | `number` | Maximum allowed live offset (ms). |\n| `livePlayback.targetOffsetMs` | `number` | Target live offset the player tries to maintain (ms). |\n\n#### iOS, visionOS, tvOS\nProperties below are Apple platforms‑only\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `preferredForwardBufferDurationMs` | `number` | Preferred duration the player attempts to retain ahead of the playhead (ms). |\n| `preferredPeakBitRate` | `number` | Desired limit of network bandwidth for loading the current item (bits per second). |\n| `preferredMaximumResolution` | `{ width: number; height: number }` | Preferred maximum video resolution. |\n| `preferredPeakBitRateForExpensiveNetworks` | `number` | Bandwidth limit for expensive networks (e.g., cellular), in bits per second. |\n| `preferredMaximumResolutionForExpensiveNetworks` | `{ width: number; height: number }` | Preferred maximum resolution on expensive networks. |\n| `livePlayback.targetOffsetMs` | `number` | Target live offset (ms) the player will try to maintain. |\n\n## DRM\n\nProtected content is supported via a plugin. See the full DRM guide: [DRM](./drm.md).\n\nQuick notes:\n- Install and enable the official plugin `@react-native-video/drm` and call `enable()` at app startup before creating players.\n- Pass DRM configuration on the source using the `drm` property of `VideoConfig` (see the DRM guide for platform specifics and `getLicense` examples).\n- If you defer initialization (`initializeOnCreation: false`), be sure to call `await player.initialize()` (or `preload()`) before expecting DRM license acquisition events.\n\n## Player Lifecycle\n\nUnderstanding the lifecycle of the `VideoPlayer` is crucial for managing resources effectively and ensuring a smooth user experience.\n\n### Creation and Initialization\n\n1. **Instantiation**: A `VideoPlayer` instance is created by calling its constructor with a video source (URL, `VideoSource`, or `VideoConfig`).\n    ```typescript\n    const player = new VideoPlayer('https://example.com/video.mp4');\n    ```\n2. **Native Player Allocation**: A lightweight native player object is allocated immediately.\n3. **Asset Initialization**: By default (unless you opt out) the underlying media item is prepared **asynchronously right after creation**. You can control this with `initializeOnCreation` inside `VideoConfig`.\n\n#### Deferred Initialization (Advanced)\n\nIf you pass a `VideoConfig` with `{ initializeOnCreation: false }`, the player will skip preparing the media item automatically. This is useful when:\n\n- You need to batch‑create many players without incurring immediate decoding / network cost\n- You want to attach event handlers before any network requests happen\n- You want explicit control over when buffering begins (e.g. on user interaction)\n\nTo initialize later, call:\n```ts\nawait player.initialize();\n// or preload if you also want it prepared & ready\nawait player.preload();\n```\n\n#### Initialization Methods Comparison\n\n| Method | When to use | What it does |\n|--------|-------------|--------------|\n| `initialize()` | You deferred initialization and now want to create the native player item / media source | Creates & attaches the underlying player item / media source without starting playback |\n| `preload()` | You want the player item prepared (buffering kicked off) ahead of an upcoming `play()` call | Ensures the media source is set and prepared; resolves once preparation started (may already be initialized) |\n| Implicit (default) | `initializeOnCreation` not set or `true` | Automatically schedules initialization after JS construction |\n\n:::info\nBy default, the player initializes automatically after construction. If you need to defer initialization, set `initializeOnCreation: false` in the config. You can then call `player.initialize()` or `player.preload()` later to start the player.\n:::\n\n### Playing a Video\n\n1.  **Loading**: When the player (auto) initializes, `preload()` is called, or after `replaceSourceAsync()`, the player starts loading the video metadata and buffering content.\n    -   `onLoadStart`: Fired when the video starts loading.\n    -   `onLoad`: Fired when the video metadata is loaded and the player is ready to play (duration, dimensions, etc., are available).\n    -   `onBuffer`: Fired when buffering starts or ends.\n2.  **Playback**: Once enough data is buffered, playback begins.\n    -   `onPlaybackStateChange`: Fired when the playback state changes (e.g., from `buffering` to `playing`).\n    -   `onProgress`: Fired periodically with the current playback time.\n    -   `onReadyToDisplay`: Fired when the first frame is ready to be displayed.\n\n### Controlling Playback\n\n-   `pause()`: Pauses playback. `status` changes to `paused`.\n-   `seekTo(time)`, `seekBy(time)`: Changes the current playback position. `onSeek` is fired when the seek operation completes.\n-   `set volume(value)`, `set muted(value)`, `set loop(value)`, `set rate(value)`: Modify player properties. Corresponding events like `onVolumeChange` or `onPlaybackRateChange` might be fired.\n\n### Changing Source\n\n-   `replaceSourceAsync(newSource)`: This method allows you to change the video source dynamically.\n    1.  The current native player resources associated with the old source are released (similar to `release()` but specifically for the source).\n    2.  A new native player instance (or reconfigured existing one) is prepared for the `newSource`.\n    3.  The loading lifecycle events (`onLoadStart`, `onLoad`, etc.) will fire for the new source.\n-   `replaceSourceAsync(null)`: This effectively unloads the current video and releases its associated resources without loading a new one. This is useful for freeing up memory if the player is temporarily not needed but might be used again later.\n\n### Releasing Resources\n\nThere are two main ways to release resources:\n\n1.  **`replaceSourceAsync(null)`**: This is a less destructive way to free resources related *only* to the current video source.\n    -   The `VideoPlayer` instance itself remains usable.\n    -   You can later call `replaceSourceAsync(newSource)` to load and play a new video.\n\n2.  **`release()`**: This is a destructive operation.\n   \n:::danger\nAfter calling `release()`, the player instance becomes unusable. Any subsequent calls to its methods or property access will result in errors.\n:::\n\n:::tip\nIt is recommended to use `replaceSourceAsync(null)` when you want to free resources related to the current video source. You should call `release()` only when you are 100% sure that you don't need the player instance anymore. Anyway garbage collector will release the player instance when it is no longer needed.\n:::\n\n### Error Handling\n\n-   The `onError` callback, if provided, will be called when a `VideoRuntimeError` occurs. This allows you to handle issues like network errors, invalid source, or platform-specific playback problems.\n-   If `onError` is not provided, errors might be thrown as exceptions.\n\n### Using with Hooks (`useVideoPlayer`)\n\nThe `useVideoPlayer` hook simplifies managing the `VideoPlayer` lifecycle within React components.\n\n```typescript\nimport { useVideoPlayer } from 'react-native-video';\n\nconst MyComponent = () => {\n  const player = useVideoPlayer('https://example.com/video.mp4', (playerInstance) => {\n    // Optional setup function: configure the player instance after creation\n    playerInstance.loop = true;\n  });\n\n  // ... use player ...\n\n  return <VideoView player={player} />;\n};\n```\n\n-   **Automatic Creation**: `useVideoPlayer` creates a `VideoPlayer` instance when the component mounts or when the source dependency changes.\n-   **Automatic Cleanup**: It automatically cleanup resources when the component unmounts or before recreating the player due to a source change. This prevents resource leaks.\n-   **Dependency Management**: If the `source` prop passed to `useVideoPlayer` changes, the hook will clean up the old player instance and create a new one with the new source.\n\n:::tip\nUsing `useVideoPlayer` is the recommended way to manage `VideoPlayer` instances in functional components to ensure proper lifecycle management and resource cleanup. It will also respect `initializeOnCreation` (defaults to `true`). If you need deferred initialization with the hook:\n\n```tsx\nconst player = useVideoPlayer({\n    source: { uri: 'https://example.com/video.mp4' },\n    initializeOnCreation: false,\n}, (instance) => {\n    // Attach listeners first\n    instance.onLoad = () => console.log('Loaded');\n});\n\n// Later (e.g. on user tap)\nawait player.initialize(); // or player.preload()\nplayer.play();\n```\n:::\n"
  },
  {
    "path": "docs/docs/plugins/_category_.json",
    "content": "{\n  \"label\": \"Plugins\",\n  \"position\": 4,\n  \"collapsed\": false\n}\n"
  },
  {
    "path": "docs/docs/plugins/ask-for-plugin.md",
    "content": "---\ntitle: Ask for Plugin\ndescription: Request a custom plugin for your React Native Video application\nsidebar_position: 7\n---\n\n# Ask for Plugin\n\nNeed a custom plugin for your React Native Video application? We can build it for you.\n\n## What We Build\n\nOur team specializes in creating production-ready plugins for `react-native-video`. Whatever video functionality you need - we can build it.\n\n**Examples of plugins we can build:**\n\n- **Analytics integrations** - Connect with any analytics provider (Mux, Conviva, custom solutions)\n- **Live streaming features** - Real-time chat overlays, live reactions, viewer counts\n- **Interactive video** - Clickable hotspots, branching narratives, shoppable videos\n- **Accessibility enhancements** - Audio descriptions, sign language overlays, custom captions styling\n- **AI-powered features** - Auto-generated thumbnails, content moderation, speech-to-text\n- **Social features** - Watch parties, synchronized playback, clip sharing\n- **Custom UI components** - Branded controls, gesture handlers, thumbnail previews on seek\n\n## Why Choose Us?\n\n- **Deep expertise** - We maintain `react-native-video` and know the codebase inside out\n- **Production-ready** - Battle-tested code with proper error handling and edge cases covered\n- **Native performance** - Plugins implemented in Kotlin/Swift for optimal performance\n- **Ongoing support** - We maintain and update plugins as the library evolves\n\n## Our Existing Plugins\n\nWe've already built several production-ready plugins:\n\n| Plugin | Description |\n|--------|-------------|\n| [Offline Video SDK](https://www.thewidlarzgroup.com/offline-video-sdk?utm_source=rnv&utm_medium=docs&utm_campaign=ask-for-plugin&utm_id=offline-video-sdk) | Download and play HLS, MPEG-DASH, MP4 streams offline with DRM support |\n| [Background Uploader](https://sdk.thewidlarzgroup.com/background-uploader?utm_source=rnv&utm_medium=docs&utm_campaign=ask-for-plugin&utm_id=background-uploader) | Upload files in the background with retry support and progress tracking |\n| [Chapters Plugin](https://sdk.thewidlarzgroup.com/chapters?utm_source=rnv&utm_medium=docs&utm_campaign=ask-for-plugin&utm_id=chapters-plugin) | Chapter markers and navigation on the seekbar |\n\n## Get Started\n\nReady to discuss your plugin needs?\n\n➡️ [**Request a Plugin**](https://sdk.thewidlarzgroup.com/ask-for-plugin?utm_source=rnv&utm_medium=docs&utm_campaign=ask-for-plugin&utm_id=request-plugin-button)\n\nWe'll review your requirements and get back to you with a proposal.\n"
  },
  {
    "path": "docs/docs/plugins/examples.md",
    "content": "---\ntitle: Plugin Usage Examples\ndescription: Simple examples of implementing common plugin scenarios for React Native Video\nsidebar_position: 3\n---\n\n# Plugin Usage Examples\n\nThis document provides practical examples of implementing common plugin scenarios for React Native Video.\n\n## Basic Plugin Template\n\n```kotlin title=\"Android\"\nclass MyPlugin : ReactNativeVideoPlugin(\"MyPlugin\") {\n    override fun onPlayerCreated(player: WeakReference<NativeVideoPlayer>) {\n        Log.d(\"MyPlugin\", \"Player created with uri ${player.get()?.source.uri}\")\n    }\n    \n    override fun onPlayerDestroyed(player: WeakReference<NativeVideoPlayer>) {\n        Log.d(\"MyPlugin\", \"Player destroyed\")\n    }\n    \n    override fun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource {\n        Log.d(\"MyPlugin\", \"Overriding source with uri ${source.uri}\")\n        return source\n    }\n}\n\n// Usage\nval plugin = MyPlugin() // Automatically registered\n```\n\n```swift title=\"iOS\"\nclass MyPlugin: ReactNativeVideoPlugin {\n    init() {\n        super.init(name: \"MyPlugin\")\n    }\n    \n    override func onPlayerCreated(player: Weak<NativeVideoPlayer>) {\n        // Custom logic when player is created\n    }\n    \n    override func onPlayerDestroyed(player: Weak<NativeVideoPlayer>) {\n        // Custom cleanup when player is destroyed\n    }\n    \n    override func overrideSource(source: NativeVideoPlayerSource) async -> NativeVideoPlayerSource {\n        // Modify source if needed\n        return source\n    }\n}\n\n// Usage\nlet plugin = MyPlugin() // Automatically registered\n```\n\n## DRM Plugin\n\nImplement custom DRM handling for protected content.\n\n:::warning\n\nDRM plugins are not supported yet in React Native Video. `getDRMManager` is not implemented yet and will have no effect.\n\n:::\n\n```kotlin title=\"Android\"\nclass CustomDRMPlugin : ReactNativeVideoPlugin(\"CustomDRM\") {\n    override fun getDRMManager(source: NativeVideoPlayerSource): Any? {\n        if (source.isDRMProtected() && source.drmType == \"custom\") {\n            return CustomDRMManager(\n                licenseUrl = source.drmLicenseUrl,\n                certificateUrl = source.drmCertificateUrl,\n                keyId = source.drmKeyId\n            )\n        }\n        return null\n    }\n}\n```\n\n```swift title=\"iOS\"\nclass CustomDRMPlugin: ReactNativeVideoPlugin {\n    init() {\n        super.init(name: \"CustomDRM\")\n    }\n    \n    override func getDRMManager(source: NativeVideoPlayerSource) async -> Any? {\n        guard source.isDRMProtected() && source.drmType == \"custom\" else {\n            return nil\n        }\n        \n        return CustomDRMManager(\n            licenseUrl: source.drmLicenseUrl,\n            certificateUrl: source.drmCertificateUrl,\n            keyId: source.drmKeyId\n        )\n    }\n}\n```"
  },
  {
    "path": "docs/docs/plugins/interface.md",
    "content": "---\ntitle: Plugin Interface\ndescription: Reference for the React Native Video plugin interface\nsidebar_position: 2\n---\n\n# Plugin Interface Reference\n\nThis document provides a complete reference for the `ReactNativeVideoPluginSpec` interface and the base `ReactNativeVideoPlugin` implementation.\n\n## ReactNativeVideoPluginSpec Interface\n\n### Required Properties\n\n#### id: String\nUnique identifier for the plugin. Must be unique across all registered plugins.\n\n```kotlin\n// Android\noverride val id: String = \"my_unique_plugin_id\"\n```\n\n```swift\n// iOS\nvar id: String { \"my_unique_plugin_id\" }\n```\n\n#### name: String\nHuman-readable name for the plugin, used in debug logging.\n\n```kotlin\n// Android\noverride val name: String = \"My Custom Plugin\"\n```\n\n```swift\n// iOS\nvar name: String { \"My Custom Plugin\" }\n```\n\n## Lifecycle Methods\n\n### Player Lifecycle\n\n#### onPlayerCreated\nCalled when a new player instance is created.\n\n```kotlin\n// Android\n@UnstableApi\nfun onPlayerCreated(player: WeakReference<NativeVideoPlayer>)\n```\n\n```swift\n// iOS\nfunc onPlayerCreated(player: Weak<NativeVideoPlayer>)\n```\n\n**Parameters:**\n- `player`: Weak reference to the newly created player instance\n\n**Use Cases:**\n- Initialize player-specific resources\n- Set up player event listeners\n- Configure player settings\n\n#### onPlayerDestroyed\nCalled when a player instance is being destroyed.\n\n```kotlin\n// Android\n@UnstableApi\nfun onPlayerDestroyed(player: WeakReference<NativeVideoPlayer>)\n```\n\n```swift\n// iOS\nfunc onPlayerDestroyed(player: Weak<NativeVideoPlayer>)\n```\n\n**Parameters:**\n- `player`: Weak reference to the player instance being destroyed\n\n**Use Cases:**\n- Clean up player-specific resources\n- Remove event listeners\n- Save state or analytics data\n\n### Video View Lifecycle\n\n#### onVideoViewCreated\nCalled when a new video view is created.\n\n```kotlin\n// Android\n@UnstableApi\nfun onVideoViewCreated(view: WeakReference<VideoView>)\n```\n\n```swift\n// iOS\nfunc onVideoViewCreated(view: Weak<VideoComponentView>)\n```\n\n**Parameters:**\n- `view`: Weak reference to the newly created video view\n\n**Use Cases:**\n- Configure view-specific settings\n- Set up UI event handlers\n- Initialize view overlays\n\n#### onVideoViewDestroyed\nCalled when a video view is being destroyed.\n\n```kotlin\n// Android\n@UnstableApi\nfun onVideoViewDestroyed(view: WeakReference<VideoView>)\n```\n\n```swift\n// iOS\nfunc onVideoViewDestroyed(view: Weak<VideoComponentView>)\n```\n\n**Parameters:**\n- `view`: Weak reference to the video view being destroyed\n\n**Use Cases:**\n- Clean up view-specific resources\n- Remove UI event handlers\n- Save view state\n\n## Content Modification Methods\n\n### overrideSource\nModify the video source before it's processed by the player.\n\n```kotlin\n// Android\nfun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource\n```\n\n```swift\n// iOS\nfunc overrideSource(source: NativeVideoPlayerSource) async -> NativeVideoPlayerSource\n```\n\n**Parameters:**\n- `source`: The original video source\n\n**Returns:**\n- Modified video source (can be the same instance if no changes needed)\n\n**Use Cases:**\n- Add authentication headers\n- Modify URLs (e.g., CDN switching)\n- Add tracking parameters\n- Transform source format\n\n### getDRMManager\nProvide a custom DRM manager for protected content.\n\n```kotlin\n// Android\nfun getDRMManager(source: NativeVideoPlayerSource): Any?\n```\n\n```swift\n// iOS\nfunc getDRMManager(source: NativeVideoPlayerSource) async -> Any?\n```\n\n**Parameters:**\n- `source`: The video source that may require DRM\n\n**Returns:**\n- DRM manager instance, or `null` if this plugin doesn't handle DRM for this source\n\n**Use Cases:**\n- Widevine DRM implementation\n- FairPlay DRM implementation\n- Custom DRM solutions\n- License acquisition logic\n\n## Android-Specific Methods\n\n### getMediaDataSourceFactory\nOverride the data source factory used by ExoPlayer.\n\n```kotlin\nfun getMediaDataSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaDataSourceFactory: DataSource.Factory\n): DataSource.Factory?\n```\n\n**Parameters:**\n- `source`: The video source\n- `mediaDataSourceFactory`: The default data source factory\n\n**Returns:**\n- Custom data source factory, or `null` to use the default\n\n**Use Cases:**\n- Custom caching strategies\n- Network optimization\n- Custom authentication\n- Analytics data collection\n\n### getMediaSourceFactory\nOverride the media source factory used by ExoPlayer.\n\n```kotlin\nfun getMediaSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaSourceFactory: MediaSource.Factory,\n    mediaDataSourceFactory: DataSource.Factory\n): MediaSource.Factory?\n```\n\n**Parameters:**\n- `source`: The video source\n- `mediaSourceFactory`: The default media source factory\n- `mediaDataSourceFactory`: The data source factory\n\n**Returns:**\n- Custom media source factory, or `null` to use the default\n\n**Use Cases:**\n- Custom media format support\n- Advanced ExoPlayer configuration\n- Source-specific optimizations\n\n### getMediaItemBuilder\nOverride the media item builder used by ExoPlayer.\n\n```kotlin\nfun getMediaItemBuilder(\n    source: NativeVideoPlayerSource,\n    mediaItemBuilder: MediaItem.Builder\n): MediaItem.Builder?\n```\n\n**Parameters:**\n- `source`: The video source\n- `mediaItemBuilder`: The default media item builder\n\n**Returns:**\n- Modified media item builder, or `null` to use the default\n\n**Use Cases:**\n- Add custom metadata\n- Configure subtitles\n- Set playback preferences\n- Configure DRM settings\n\n### shouldDisableCache\nControl whether caching should be disabled for a source.\n\n```kotlin\nfun shouldDisableCache(source: NativeVideoPlayerSource): Boolean\n```\n\n**Parameters:**\n- `source`: The video source\n\n**Returns:**\n- `true` to disable caching, `false` to allow caching\n\n**Use Cases:**\n- Disable caching for live streams\n- Disable caching for DRM content\n- Custom caching policies\n\n## Base Implementation: ReactNativeVideoPlugin\n\nThe base class provides default implementations for all methods:\n\n### Automatic Registration\n```kotlin\n// Android\ninit {\n    PluginsRegistry.shared.register(this)\n}\n```\n\n```swift\n// iOS\npublic init(name: String) {\n    self.name = name\n    self.id = \"RNV_Plugin_\\(name)\"\n    PluginsRegistry.shared.register(plugin: self)\n}\n```\n\n### Automatic Cleanup (iOS only)\n```swift\ndeinit {\n    PluginsRegistry.shared.unregister(plugin: self)\n}\n```\n\n### Default Implementations\n\nAll methods have sensible defaults:\n- Lifecycle methods: No-op implementations\n- `overrideSource`: Returns the original source unchanged\n- `getDRMManager`: Returns `null`\n- Factory methods (Android): Return `null` (use defaults)\n- `shouldDisableCache`: Returns `false`\n\n## Method Calling Order\n\n### Source Processing Flow\n1. `overrideSource` - Called for each registered plugin in order\n2. `getDRMManager` - Called for each plugin until one returns non-null\n3. Factory methods (Android) - Called for each plugin until one returns non-null\n\n### Lifecycle Flow\n1. View/Player creation methods called for all plugins\n2. Source processing happens during playback\n3. View/Player destruction methods called for all plugins\n\n## Error Handling\n\n### DRM Plugin Not Found\nIf no plugin provides a DRM manager when required:\n\n```kotlin\n// Android\nthrow LibraryError.DRMPluginNotFound\n```\n\n```swift\n// iOS\nthrow LibraryError.DRMPluginNotFound.error()\n```\n\n### Best Practices\n- Return `null` from optional methods when not providing custom behavior\n- Handle weak reference nullability properly\n- Use appropriate error handling in async methods (iOS)\n- Log meaningful debug information\n\n## Platform Differences Summary\n\n| Feature | Android | iOS |\n|---------|---------|-----|\n| Async Support | No | Yes (async/await) |\n| Media Factories | Full ExoPlayer support | Limited AVFoundation |\n| Cache Control | Yes | No |\n| Auto Cleanup | Manual | Automatic (deinit) |\n| Weak References | `WeakReference<T>` | `Weak<T>` |"
  },
  {
    "path": "docs/docs/plugins/plugins.mdx",
    "content": "---\ntitle: Plugins  \ndescription: Overview of the React Native Video plugin system\nsidebar_position: 6\n---\n\n# Plugins Overview\n\nThe **React Native Video** library offers a robust plugin system to extend and customize video functionality on Android and iOS. With plugins, you can override source handling, implement custom DRM, modify media factories, and respond to player lifecycle events.\n\n:::tip Use in Third Party Library Guide\nIf you are looking how to import React Native Video in your native code to use plugins, you can checkout [Use in Third Party Library](./use-in-third-party-library) page.\n:::\n\n## What Are Plugins?\n\nPlugins are modular extensions that hook into the video player's lifecycle and processing pipeline. They allow you to:\n\n-  **Customize video sources** before playback\n-  **Implement custom DRM** for protected content\n-  **Override media factories** (Android only)\n-  **React to player lifecycle events** for analytics, logging, or cleanup\n-  **Control caching behavior** for performance\n\n## Architecture\n\nThe plugin system consists of three main components:\n\n| Component                    | Description                                                                                 |\n|:-----------------------------|:-------------------------------------------------------------------------------------------|\n| `PluginsRegistry`            | Singleton that manages plugin registration and coordinates plugin interactions              |\n| `ReactNativeVideoPluginSpec` | Interface/protocol defining the contract all plugins must implement                        |\n| `ReactNativeVideoPlugin`     | Base implementation with convenient defaults; override only the methods you care about     |\n\n:::tip\nPlugins are automatically registered when you instantiate a class that extends `ReactNativeVideoPlugin`.  \n:::\n\n## Core Concepts\n\n### Plugin Lifecycle\n\nPlugins receive notifications for key events:\n\n-  **Player creation/destruction** - react to player instance lifecycle\n-  **Video view creation/destruction** - handle UI component lifecycle\n-  **Source processing** - modify video sources before playback\n-  **DRM requests** - provide custom DRM handling\n-  **Media factory overrides** - customize ExoPlayer components (Android)\n\n:::caution\nAll player and view references passed to plugins are **weak references** to prevent memory leaks.\n:::\n\n## Platform Differences\n\n| Feature                        | Android (Kotlin / ExoPlayer)                   | iOS (Swift / AVFoundation)         |\n|:-------------------------------|:-----------------------------------------------|:-----------------------------------|\n| Underlying player              | ExoPlayer                                      | AVFoundation                       |\n| Media factory customization    | Extensive                                      | Limited                            |\n| Cache control                  | Supported                                      | Limited                            |\n| Plugin method style            | Synchronous                                    | Async/await                        |\n| Memory management              | Manual cleanup                                 | Manual cleanup                     |\n\n## Getting Started\n\n### Example: Android Plugin\n\n```kotlin\n// Android\nclass MyPlugin : ReactNativeVideoPlugin(\"MyPluginName\") {\n    override fun onPlayerCreated(player: WeakReference<NativeVideoPlayer>) {\n        // Custom logic here\n    }\n}\n```\n\n### Example: iOS Plugin\n\n```swift\n// iOS\nclass MyPlugin: ReactNativeVideoPlugin {\n    init() {\n        super.init(name: \"MyPluginName\")\n    }\n\n    override func onPlayerCreated(player: Weak<NativeVideoPlayer>) {\n        // Custom logic here\n    }\n}\n```\n\n\n\n## Next Steps\n\n-  [**Plugin Registry**](./registry) - Learn about plugin management and registration\n-  [**Plugin Interface**](./interface) - Complete API reference for plugin methods\n-  [**Usage Examples**](./examples) - Practical implementations and common patterns\n-  [**Ask for Plugin**](./ask-for-plugin) - Request a custom plugin built by our team\n\n\n\n"
  },
  {
    "path": "docs/docs/plugins/registry.md",
    "content": "---\ntitle: Plugin Registry  \ndescription: Overview of the React Native Video plugin registry and how to use it\nsidebar_position: 1\n---\n\n# Plugin Registry\n\nThe `PluginsRegistry` is a singleton that manages all plugin instances and coordinates their interactions with the video player system. It handles registration, unregistration, and notification distribution to all active plugins.\n\n## Singleton Pattern\n\nBoth Android and iOS use a shared singleton:\n\n```kotlin title=\"Android\"\n// Register\nPluginsRegistry.shared.register(plugin)\n// Unregister\nPluginsRegistry.shared.unregister(plugin)\n```\n\n```swift title=\"iOS\"\n// Register\nPluginsRegistry.shared.register(plugin: plugin)\n// Unregister\nPluginsRegistry.shared.unregister(plugin: plugin)\n```\n\n:::tip Plugin Ordering\nPlugins are processed in registration order. Later plugins can override earlier ones.\n:::\n\n## Registration Methods\n\n### Automatic Registration\n\nYou can use the base class `ReactNativeVideoPlugin` to automatically register your plugin. This will also mock all the methods that are not implemented in your plugin. \n\n:::danger\nYou still need to unregister your plugin manually when you are done with it. Otherwise, you will have a memory leak.\n:::\n\n```kotlin title=\"Android\"\nclass MyPlugin : ReactNativeVideoPlugin(\"MyPlugin\") {\n    // ...\n}\nval plugin = MyPlugin() // Auto-registered\n```\n\n```swift title=\"iOS\"\nclass MyPlugin: ReactNativeVideoPlugin {\n    init() {\n        super.init(name: \"MyPlugin\")\n    }\n    // Auto-unregistered in deinit\n}\nlet plugin = MyPlugin() // Auto-registered\n```\n\n### Manual Registration\n\nYou can also manually register your plugin. This is useful if you want to implement a plugin that is not a subclass of `ReactNativeVideoPlugin`.\nYou will need to implement the `ReactNativeVideoPluginSpec` interface. This is a protocol that defines the methods and properties that a plugin must implement.\n\n```kotlin title=\"Android\"\nclass MyCustomPlugin : ReactNativeVideoPluginSpec {\n    override val id = \"my_custom_id\"\n    override val name = \"MyCustomPlugin\"\n    // ...\n}\nval plugin = MyCustomPlugin()\nPluginsRegistry.shared.register(plugin)\n```\n\n```swift title=\"iOS\"\nclass MyCustomPlugin: ReactNativeVideoPluginSpec {\n    let id = \"my_custom_id\"\n    let name = \"MyCustomPlugin\"\n    // ...\n}\nlet plugin = MyCustomPlugin()\nPluginsRegistry.shared.register(plugin: plugin)\n```\n\n## Plugin ID Generation\n\nWhen using the base class, IDs are auto-generated:\n\n```kotlin title=\"Android\"\nID Format: \"RNV_Plugin_{name}\"\nExample: \"RNV_Plugin_MyCustomDRM\"\n```\n\n```swift title=\"iOS\"\nID Format: \"RNV_Plugin_{name}\"\nExample: \"RNV_Plugin_MyCustomDRM\"\n```\n\n## Plugin Internals\n\nBellow are the internals of the plugin registry, that shows logic for certain methods.\n\n### Source Processing\n\nThe registry coordinates source modifications:\n\n```kotlin title=\"Android\"\ninternal fun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource {\n    var overriddenSource = source\n    for (plugin in plugins.values) {\n        overriddenSource = plugin.overrideSource(overriddenSource)\n    }\n    return overriddenSource\n}\n```\n\n```swift title=\"iOS\"\ninternal func overrideSource(source: NativeVideoPlayerSource) async -> NativeVideoPlayerSource {\n    var overriddenSource = source\n    for plugin in plugins.values {\n        overriddenSource = await plugin.overrideSource(source: source)\n    }\n    return overriddenSource\n}\n```\n\n### DRM Manager Resolution\n\nFinds the first plugin that can provide a DRM manager:\n\n```kotlin title=\"Android\"\ninternal fun getDRMManager(source: NativeVideoPlayerSource): Any {\n    for (plugin in plugins.values) {\n        val manager = plugin.getDRMManager(source)\n        if (manager != null) return manager\n    }\n    throw LibraryError.DRMPluginNotFound\n}\n```\n\n```swift title=\"iOS\"\ninternal func getDrmManager(source: NativeVideoPlayerSource) async throws -> Any? {\n    for plugin in plugins.values {\n        if let drmManager = await plugin.getDRMManager(source: source) {\n            return drmManager\n        }\n    }\n    throw LibraryError.DRMPluginNotFound.error()\n}\n```\n\n## Android-Specific Registry Methods\n\n| Method Name                       | Purpose                                                   |\n|:----------------------------------|:----------------------------------------------------------|\n| `overrideMediaDataSourceFactory`  | Override data source factory for custom ExoPlayer sources  |\n| `overrideMediaSourceFactory`      | Override media source factory                             |\n| `overrideMediaItemBuilder`        | Customize the media item builder                          |\n| `shouldDisableCache`              | Control caching behavior                                  |\n\nExample signatures:\n\n```kotlin\ninternal fun overrideMediaDataSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaDataSourceFactory: DataSource.Factory\n): DataSource.Factory\n\ninternal fun overrideMediaSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaSourceFactory: MediaSource.Factory,\n    mediaDataSourceFactory: DataSource.Factory\n): MediaSource.Factory\n\ninternal fun overrideMediaItemBuilder(\n    source: NativeVideoPlayerSource,\n    mediaItemBuilder: MediaItem.Builder\n): MediaItem.Builder\n\ninternal fun shouldDisableCache(source: NativeVideoPlayerSource): Boolean\n```\n\n## Best Practices\n\n-  **Memory management**: Registry holds strong references to plugins; plugins get weak references to players/views.\n-  **Unregister plugins**: Use unregistration to prevent memory leaks.\n-  **Performance**: Minimize work in notification handlers. Cache expensive operations. Be mindful of plugin order.\n\n:::tip Need a Custom Plugin?\nIf you need functionality that the library doesn't currently offer, we can build it for you. Check out [Ask for Plugin](./ask-for-plugin.md) to request a custom plugin built by our team.\n:::\n\n"
  },
  {
    "path": "docs/docs/plugins/use-in-third-party-library.md",
    "content": "---\ntitle: Use in Third Party Library\ndescription: How to use React Native Video in a third party library\nsidebar_position: 4\n---\n\n# Use in Third Party Library\n\nYou can use React Native Video in your third party library either as a dependency if you want to have specific version of the library or as a peer dependency if you want to version selection to be handled by the consumer of the library.\n\n## In JS\n\nAdd `react-native-video` as a dependency or peer dependency.\n\n```json title=\"package.json\"\n{\n  \"dependencies\": {\n    \"react-native-video\": \"latest\"\n  }\n  // OR\n  \"peerDependencies\": {\n    \"react-native-video\": \"*\"\n  }\n}\n```\n\nAnd then you can import it in your code.\n\n```ts\nimport { VideoPlayer } from 'react-native-video';\n\nconst player = new VideoPlayer({ uri: 'https://www.example.com/video.mp4' });\n\nplayer.play();\n```\n\n## In Native\n\n### iOS\nAdd `ReactNativeVideo` as a dependency in your `*.podspec` file.\n\n```ruby title=\"*.podspec\"\nPod::Spec.new do |s|\n  // ...\n\n  s.dependency 'ReactNativeVideo'\nend\n```\n\n### Android\n\nAdd `:react-native-video` and `:react-native-nitro-modules` as a dependency in your `build.gradle` file. Also you will need to add `androidx.media3` dependencies. to use player and source in your library.\n\n```groovy title=\"build.gradle\"\n// ...\n\ndependencies {\n  // ...\n\n  implementation project(':react-native-video')\n  implementation project(':react-native-nitro-modules')\n\n  implementation \"androidx.media3:media3-common:1.4.1\"\n  implementation \"androidx.media3:media3-exoplayer:1.4.1\"\n}\n```\n\n"
  },
  {
    "path": "docs/docs/projects.md",
    "content": "---\ntitle: Useful Projects\ndescription: React Native Video Useful Projects\nsidebar_class_name: hidden\n---\n# Useful Projects\n\nThis page lists open-source projects that can be helpful for your player implementation. <br/>\nIf you have a project that could benefit other users, feel free to open a PR to add it here.\n\n## Our (TheWidlarzGroup) Libraries\n- [react-native-video-player](https://github.com/TheWidlarzGroup/react-native-video-player): Our video player UI library.\n- [Offline Video SDK](https://www.thewidlarzgroup.com/offline-video-sdk?utm_source=rnv&utm_medium=docs&utm_campaign=projects&utm_id=offline-video-sdk): If you're building an app that needs **offline playback** (e.g., downloading HLS videos, subtitles, audio tracks, or DRM-protected content), check out our commercial Offline Video SDK. It integrates with `react-native-video` and is available with a [free trial](https://sdk.thewidlarzgroup.com/signup?utm_source=rnv&utm_medium=docs&utm_campaign=projects&utm_id=start-trial-offline-video-sdk). To get started quickly, you can clone our [Offline Video Starter Project](https://github.com/TheWidlarzGroup/react-native-offline-video-starter?utm_source=rnv&utm_medium=docs&utm_campaign=projects&utm_id=offline-video-starter), which includes a ready-to-run example app demonstrating offline playback, multi-audio, subtitles, and DRM setup.\n\n## Community Libraries\n- [react-native-corner-video](https://github.com/Lg0gs/react-native-corner-video): A floating video player.\n- [react-native-track-player](https://github.com/doublesymmetry/react-native-track-player): A toolbox for audio playback.\n- [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls): A video player UI.\n- [react-native-media-console](https://github.com/criszz77/react-native-media-console): An updated version of react-native-video-controls, rewritten in TypeScript.\n"
  },
  {
    "path": "docs/docs/updating.md",
    "content": "---\ntitle: Updating\ndescription: React Native Video Updating Guide\nsidebar_class_name: hidden\n---\n\n## Upgrading from react-native-video v6 to v7\n\nVersion 7 of `react-native-video` introduces a significant architectural shift, separating the video player logic from the UI rendering. This change unlocks new capabilities like video preloading and a more intuitive, hook-based API. This guide will walk you through the necessary steps to migrate your application from v6 to v7.\n\n### Key Changes in v7\n\nThe most substantial change in v7 is the move from a monolithic `<Video>` component to a more modular approach with two distinct components:\n\n*   **`VideoPlayer`**: A new class that manages the player's state and playback logic. It is not a UI component.\n*   **`VideoView`**: A UI component responsible for rendering the video on the screen. It takes a `VideoPlayer` instance as a prop.\n*   **`useVideoPlayer` hook**: The recommended way to create and manage the lifecycle of a `VideoPlayer` instance within a functional component. It automatically handles the creation and cleanup of the player.\n\n### New Dependency\n`react-native-video` v7 is now built on top of [`react-native-nitro-modules`](https://nitro.margelo.com/docs/what-is-nitro) framework. This means that you need to install the Nitro framework to use `react-native-video` v7.\n\n### Step-by-Step Migration Guide\n\n#### 1. Installation\n\nFirst, update the `react-native-video` package to the latest v7 release:\n\n```bash\nnpm install react-native-video@next --save\n```\n\nThen, install the pods for iOS:\n\n```bash\ncd ios && pod install\n```\n\n#### 2. Updating Your Component\n\nThe core of the migration involves replacing the `<Video>` component with the new `useVideoPlayer` hook and `<VideoView>` component.\n\n**v6 Implementation:**\n\n```jsx\nimport React, { useRef } from 'react';\nimport Video from 'react-native-video';\n\nconst VideoPlayerV6 = () => {\n  const videoRef = useRef(null);\n\n  return (\n    <Video\n      source={{ uri: 'https://www.w3schools.com/html/mov_bbb.mp4' }}\n      ref={videoRef}\n      style={{ width: 300, height: 200 }}\n      controls={true}\n      onLoad={() => console.log('Video loaded')}\n      onProgress={(data) => console.log('Progress:', data.currentTime)}\n    />\n  );\n};\n```\n\n**v7 Implementation:**\n\n```jsx\nimport React from 'react';\nimport { useVideoPlayer, VideoView, useEvent } from 'react-native-video';\n\nconst VideoPlayerV7 = () => {\n  const player = useVideoPlayer({\n    source: {\n      uri: 'https://www.w3schools.com/html/mov_bbb.mp4',\n    },\n  });\n\n  useEvent(player, 'onLoad', () => {\n    console.log('Video loaded');\n  });\n\n  useEvent(player, 'onProgress', (data) => {\n    console.log('Progress:', data.currentTime);\n  });\n\n  return (\n    <VideoView\n      player={player}\n      style={{ width: 300, height: 200 }}\n      controls={true}\n    />\n  );\n};\n```\n\n### Prop and Method Migration\n\nMany props and methods from the v6 `<Video>` component have been moved to the `VideoPlayer` instance in v7.\n\n#### Common Props\n\n| v6 Prop (`<Video>`) | v7 Equivalent (`VideoPlayer` properties) | Notes |\n| :--- | :--- | :--- |\n| `source` | `source` property in `useVideoPlayer` config | The structure of the source object remains largely the same. |\n| `paused` | `paused` property on the `VideoPlayer` instance | Can be controlled via `player.pause()` and `player.play()`. |\n| `muted` | `muted` property on the `VideoPlayer` instance | `player.muted = true/false;` |\n| `volume` | `volume` property on the `VideoPlayer` instance | `player.volume = 0.5;` |\n| `rate` | `rate` property on the `VideoPlayer` instance | `player.rate = 1.5;` |\n| `loop` | `loop` property on the `VideoPlayer` instance | `player.loop = true;` |\n| `resizeMode` | `resizeMode` prop on `<VideoView>` | This remains a prop on the UI component. |\n| `controls` | `controls` prop on `<VideoView>` | This also remains on the UI component. |\n\nsee [VideoPlayer](./player/player.md) for more details.\n\n#### Methods\n\nImperative methods previously called on the `<Video>` component's ref are now methods on the `VideoPlayer` instance.\n\n| v6 Method (`videoRef.current`) | v7 Equivalent (`player`) |\n| :--- | :--- |\n| `seek(time)` | `player.seekTo(time)` |\n| `presentFullscreenPlayer()` | `videoViewRef.current.enterFullscreen()` | Fullscreen is now managed by the `VideoView` ref. |\n| `dismissFullscreenPlayer()` | `videoViewRef.current.exitFullscreen()` | |\n| `pause()` | `player.pause()` | |\n| `resume()` | `player.play()` | |\n\nsee [VideoPlayer](./player/player.md) for more details.\n\n### Event Handling\n\nIn v7, event handling is standardized through the `useEvent` hook or by directly assigning callbacks to the `VideoPlayer` instance. The `useEvent` hook is recommended as it automatically handles listener cleanup.\n\n**v6 Event Handling:**\n\n```jsx\n<Video\n  onLoad={(data) => console.log(data)}\n  onProgress={(data) => console.log(data.currentTime)}\n  onError={(error) => console.error(error)}\n/>\n```\n\n**v7 Event Handling with `useEvent`:**\n\n```jsx\nimport { useVideoPlayer, VideoView, useEvent } from 'react-native-video';\n\nconst MyPlayer = () => {\n  const player = useVideoPlayer({ source: { uri: '...' } });\n\n  useEvent(player, 'onLoad', (data) => console.log(data));\n  useEvent(player, 'onProgress', (data) => console.log(data.currentTime));\n  useEvent(player, 'onError', (error) => console.error(error.code, error.message));\n\n  return <VideoView player={player} />;\n}\n```\n\n**Directly assigning callbacks in v7:**\n\n```jsx\nconst player = useVideoPlayer('https://example.com/video.mp4', (_player) => {\n  _player.onLoad = (data) => {\n    console.log('Video loaded! Duration:', data.duration);\n  };\n  _player.onError = (error) => {\n    console.error('Player Error:', error.code, error.message);\n  };\n});\n```\n\n### Benefits of the New Architecture\n\n*   **Preloading**: You can create a `VideoPlayer` instance and begin loading a video before it's visible in the UI. When you're ready to display it, simply pass the player instance to a `<VideoView>`.\n*   **Improved Performance**: Separating the player logic from the UI rendering can lead to better performance and a more responsive application.\n*   **Cleaner API**: The hook-based API simplifies player management and reduces boilerplate code, especially for handling the player's lifecycle.\n*   **Full New Architecture Support**: Version 7 fully embraces React Native's New Architecture, ensuring better performance and consistency."
  },
  {
    "path": "docs/docs/video-view/_category_.json",
    "content": "{\n  \"label\": \"video-view\",\n  \"position\": 3,\n  \"collapsed\": false\n}\n"
  },
  {
    "path": "docs/docs/video-view/chapters.md",
    "content": "---\nsidebar_position: 5\nsidebar_label: Chapters\ndescription: VideoView chapters support\ncustomProps:\n  plan: pro\n---\n\n# Chapters\n\nThe `VideoView` component supports video chapters, allowing users to navigate through different segments of a video. Chapters appear as visual markers on the seekbar and can be used to jump to specific points in the video.\n\n<video controls width=\"50%\">\n  <source src=\"/react-native-video/videos/chapters.mp4\" type=\"video/mp4\" />\n  Your browser does not support the video tag.\n</video>\n\n## Installation\n\nTo use chapters functionality, you need to install the `@react-native-video/chapters` package:\n\n```bash\nnpm install @react-native-video/chapters\n```\n\n## Getting Started\n\nFirst, enable the chapters functionality by calling `enable()`:\n\n```tsx\nimport { enable } from '@react-native-video/chapters';\n\nenable();\n```\n\n## API\n\n### `enable()`\n\nEnables the chapters functionality. Must be called before using other chapter methods.\n\n### `setChapters(chapters, options?)`\n\nSets the chapters for the video player.\n\n**Parameters:**\n- `chapters`: Array of chapter objects with the following structure:\n  ```tsx\n  {\n    title: string;  // Chapter title\n    timeMs: number; // Chapter time in milliseconds\n  }[]\n  ```\n- `options` (optional): Configuration object\n  - `markersColor?: string` - Color of the chapter markers (default: platform default)\n  - `showTooltip?: boolean` - Whether to show tooltip when hovering over markers (default: `true`)\n  - `showTimer?: boolean` - Whether to show timer on markers (default: `true`)\n\n**Example:**\n```tsx\nimport { setChapters } from '@react-native-video/chapters';\n\nconst chapters = [\n  { title: \"Introduction\", timeMs: 0 },\n  { title: \"Main Content\", timeMs: 30000 }, // 30 seconds\n  { title: \"Conclusion\", timeMs: 120000 },  // 2 minutes\n];\n\nsetChapters(chapters, {\n  markersColor: \"#FF6B35\",\n  showTooltip: true,\n  showTimer: true,\n});\n```\n\n### `clearChapters()`\n\nRemoves all chapters from the video player.\n\n```tsx\nimport { clearChapters } from '@react-native-video/chapters';\n\nclearChapters();\n```\n\n### `goToChapter(title)`\n\nProgrammatically navigates to a specific chapter by its title.\n\n**Parameters:**\n- `title`: The title of the chapter to navigate to\n\n```tsx\nimport { goToChapter } from '@react-native-video/chapters';\n\ngoToChapter(\"Main Content\");\n```\n\n## Platform Differences\n\n- **iOS**: Custom seekbar with visual markers and tooltip\n- **Android**: Visual markers on seekbar with tooltip\n"
  },
  {
    "path": "docs/docs/video-view/events.md",
    "content": "---\nsidebar_position: 3\nsidebar_label: Events\ndescription: VideoView event callbacks\n---\n\n# Events\n\n`VideoView` also accepts several event callback props related to UI state changes:\n\n| Event | Type | Description |\n|-------|------|-------------|\n| `onPictureInPictureChange?` | `(event: { isActive: boolean }) => void` | Fired when the picture-in-picture mode starts or stops. |\n| `onFullscreenChange?` | `(event: { isFullscreen: boolean }) => void` | Fired when the fullscreen mode starts or stops. |\n| `willEnterFullscreen?` | `() => void` | Fired just before the view enters fullscreen mode. |\n| `willExitFullscreen?` | `() => void` | Fired just before the view exits fullscreen mode. |\n| `willEnterPictureInPicture?` | `() => void` | Fired just before the view enters picture-in-picture mode. |\n| `willExitPictureInPicture?` | `() => void` | Fired just before the view exits picture-in-picture mode. |\n\nThese can be used to update your component's state or UI in response to these changes.\n\n```tsx\n<VideoView\n  player={player}\n  onFullscreenChange={({ isFullscreen }) => {\n    console.log(isFullscreen ? 'Entered fullscreen' : 'Exited fullscreen');\n  }}\n  onPictureInPictureChange={({ isActive }) => {\n    console.log(isActive ? 'PiP active' : 'PiP inactive');\n  }}\n/>\n```\n"
  },
  {
    "path": "docs/docs/video-view/methods.md",
    "content": "---\nsidebar_position: 4\nsidebar_label: Methods\ndescription: VideoView imperative methods\n---\n\n# Refs and Imperative Methods\n\nYou can obtain a ref to the `VideoView` component to call imperative methods:\n\n```tsx\nconst videoViewRef = React.useRef<VideoViewRef>(null);\n\n// ...\n\n<VideoView ref={videoViewRef} player={player} />\n\n// Later, you can call methods like:\nvideoViewRef.current?.enterFullscreen();\n```\n\nAvailable methods on the `VideoViewRef`:\n\n| Method | Type | Description |\n|--------|------|-------------|\n| `enterFullscreen()` | `() => void` | Programmatically requests the video view to enter fullscreen mode. |\n| `exitFullscreen()` | `() => void` | Programmatically requests the video view to exit fullscreen mode. |\n| `enterPictureInPicture()` | `() => void` | Programmatically requests the video view to enter picture-in-picture mode. |\n| `exitPictureInPicture()` | `() => void` | Programmatically requests the video view to exit picture-in-picture mode. |\n| `canEnterPictureInPicture()` | `() => boolean` | Checks if picture-in-picture mode is currently available and supported. Returns `true` if PiP can be entered, `false` otherwise. |\n"
  },
  {
    "path": "docs/docs/video-view/props.md",
    "content": "---\nsidebar_position: 2\nsidebar_label: Props\ndescription: VideoView component properties\n---\n\n# Props\n\n| Prop | Type | Required | Default | Description |\n|------|------|----------|---------|-------------|\n| `player` | `VideoPlayer` | Yes | - | The `VideoPlayer` instance that manages the video to be displayed. |\n| `style` | `ViewStyle` | No | - | Standard React Native styles to control the layout and appearance of the `VideoView`. |\n| `controls` | `boolean` | No | `false` | Whether to show the native video playback controls (play/pause, seek bar, volume, etc.). |\n| `pictureInPicture` | `boolean` | No | `false` | Whether to enable and show the picture-in-picture (PiP) button in the native controls (if supported by the platform and controls are visible). |\n| `autoEnterPictureInPicture` | `boolean` | No | `false` | Whether the video should automatically enter PiP mode when it starts playing and the app is backgrounded (behavior might vary by platform). |\n| `resizeMode` | `'contain' \\| 'cover' \\| 'stretch' \\| 'none'` | No | `'none'` | How the video should be resized to fit the view. |\n| `keepScreenAwake` | `boolean` | No | `true` | Whether to keep the device screen awake while the video view is mounted. |\n| `surfaceType` | `'surface' \\| 'texture'` | No (Android only) | `'surface'` | (Android) Underlying native view type. `'surface'` uses a SurfaceView (better performance, no transforms/overlap), `'texture'` uses a TextureView (supports animations, transforms, overlapping UI) at a small performance cost. Ignored on iOS. |\n\n## Android: Choosing a surface type\n\n:::info Android Only\nThis section applies only to Android. The `surfaceType` prop is ignored on iOS.\n:::\n\nOn Android the default rendering path uses a `SurfaceView` (set via `surfaceType=\"surface\"`) for optimal decoding performance and lower latency. However `SurfaceView` lives in a separate window and can't be:\n\n- Animated with transforms (scale, rotate, opacity fade)\n- Clipped by parent views (rounded corners, masks)\n- Overlapped reliably with sibling views (z-order issues)\n\nIf you need those UI effects, switch to `TextureView`:\n\n```tsx\n<VideoView\n  player={player}\n  surfaceType=\"texture\"\n  style={{ width: 300, height: 170, borderRadius: 16, overflow: 'hidden' }}\n  resizeMode=\"cover\"\n  controls\n/>\n```\n\nUse `TextureView` only when required, as it can be slightly less performant and may increase power consumption on some devices.\n"
  },
  {
    "path": "docs/docs/video-view/video-view.md",
    "content": "---\nsidebar_position: 1\nsidebar_label: Introduction\ndescription: Introduction to VideoView component\n---\n\n# VideoView Component\n\nThe `VideoView` component is responsible for rendering the video content managed by a `VideoPlayer` instance onto the screen. It also provides UI functionalities like native controls, fullscreen, and picture-in-picture mode.\n\n## Basic Usage\n\nTo use `VideoView`, you need to pass a `VideoPlayer` instance to its `player` prop.\n\n```tsx\nimport React from 'react';\nimport { VideoPlayer, VideoView } from 'react-native-video';\nimport { StyleSheet } from 'react-native';\n\nconst App = () => {\n  const player = useVideoPlayer('https://example.com/video.mp4', (_player) => {\n    // This is optional setup function that will be called when the player is created.\n    _player.play();\n  });\n\n  return (\n    <VideoView\n      style={styles.video}\n      player={player}\n      controls={true}\n    />\n  );\n};\n\nconst styles = StyleSheet.create({\n  video: {\n    width: '100%',\n    height: 200,\n  },\n});\n\nexport default App;\n```\n"
  },
  {
    "path": "docs/docusaurus.config.ts",
    "content": "import type * as Preset from '@docusaurus/preset-classic';\nimport type { Config } from '@docusaurus/types';\nimport { createSidebarWithCustomProps } from '@widlarzgroup/docusaurus-ui';\nimport { themes as prismThemes } from 'prism-react-renderer';\n\n// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)\n\nconst config: Config = {\n  title: 'React Native Video',\n  tagline: 'React Native Video - Video player for React Native',\n  favicon: 'img/favicon.ico',\n\n  url: 'https://docs.thewidlarzgroup.com',\n  baseUrl: '/react-native-video',\n\n  organizationName: 'TheWidlarzGroup',\n  projectName: 'react-native-video',\n\n  onBrokenLinks: 'throw',\n  onBrokenMarkdownLinks: 'warn',\n\n  future: {\n    experimental_faster: true,\n    v4: true,\n  },\n\n  i18n: {\n    defaultLocale: 'en',\n    locales: ['en'],\n  },\n\n  presets: [\n    [\n      'classic',\n      {\n        docs: {\n          sidebarPath: './sidebars.ts',\n          lastVersion: '6.x',\n          includeCurrentVersion: true,\n          versions: {\n            'current': {\n              label: 'v7 Beta',\n              path: 'v7',\n              banner: 'none',\n            },\n            '6.x': {\n              label: 'v6',\n              path: 'v6',\n            },\n          },\n          sidebarItemsGenerator: createSidebarWithCustomProps,\n        },\n        theme: {\n          customCss: './src/css/custom.css',\n        },\n      } satisfies Preset.Options,\n    ],\n  ],\n\n  headTags: [\n    {\n      tagName: 'link',\n      attributes: {\n        rel: 'preconnect',\n        href: 'https://fonts.googleapis.com',\n      },\n    },\n    {\n      tagName: 'link',\n      attributes: {\n        rel: 'preconnect',\n        href: 'https://fonts.gstatic.com',\n      },\n    },\n    {\n      tagName: 'link',\n      attributes: {\n        rel: 'stylesheet',\n        href: 'https://fonts.googleapis.com/css2?family=Orbitron:wght@400..900&display=swap',\n      },\n    },\n  ],\n\n  themes: ['@widlarzgroup/docusaurus-ui'],\n\n  themeConfig: {\n    image: 'img/twg-social-card.png',\n    navbar: {\n      title: 'React Native Video',\n      logo: {\n        alt: 'TheWidlarzGroup Logo',\n        style: {\n          width: '60px',\n          height: '40px',\n          marginRight: '10px',\n          transform: 'translateY(-4px)',\n        },\n        src: 'img/twg-logo.png',\n      },\n      items: [\n        {\n          type: 'docSidebar',\n          sidebarId: 'docsSidebar',\n          position: 'left',\n          label: 'Documentation',\n        },\n        {\n          type: 'docsVersionDropdown',\n          versions: {\n            'current': { label: 'v7 Beta' },\n            '6.x': { label: 'v6' },\n          },\n          position: 'right',\n        },\n        {\n          href: 'https://github.com/TheWidlarzGroup/react-native-video',\n          label: 'GitHub',\n          position: 'right',\n        },\n        {\n          href: 'https://www.thewidlarzgroup.com/react-native-video?utm_source=rnv&utm_medium=docs&utm_campaign=navbar&utm_id=offer-button',\n          label: 'Offer',\n          position: 'right',\n        },\n        {\n          type: 'search',\n          position: 'right',\n        },\n      ],\n    },\n    docs: {\n      sidebar: {\n        hideable: false,\n      },\n      versionPersistence: 'localStorage',\n    },\n    footer: {\n      style: 'light',\n      copyright: `Built With ❤️ By TheWidlarzGroup & React Native Video Community`,\n    },\n    colorMode: {\n      defaultMode: 'dark',\n      disableSwitch: true,\n      respectPrefersColorScheme: false,\n    },\n    prism: {\n      theme: prismThemes.oneLight,\n      darkTheme: prismThemes.oneDark,\n    },\n  } satisfies Preset.ThemeConfig,\n\n  plugins: [\n    require.resolve('docusaurus-lunr-search'),\n    [\n      'docusaurus-plugin-typedoc',\n      {\n        name: 'API Reference',\n        entryPoints: ['../packages/react-native-video/src'],\n        exclude: '../packages/react-native-video/src/index.ts',\n        tsconfig: '../packages/react-native-video/tsconfig.json',\n        out: './docs/api-reference',\n        watch: process.env.TYPEDOC_WATCH,\n        excludePrivate: true,\n        excludeProtected: true,\n        excludeExternals: true,\n        excludeInternal: true,\n        readme: 'none',\n        sidebar: {\n          autoConfiguration: false,\n        },\n        parametersFormat: 'table',\n        enumMembersFormat: 'table',\n        useCodeBlocks: true,\n      },\n    ],\n    // LLMs txt generation for v6\n    [\n      'docusaurus-plugin-llms',\n      {\n        id: 'llms-v6',\n        generateLLMsTxt: false,\n        generateLLMsFullTxt: false,\n        docsDir: 'versioned_docs/version-6.x',\n        pathTransformation: {\n          ignorePaths: ['docs'],\n          addPaths: ['react-native-video/docs/v6'],\n        },\n        version: '6.x.x',\n        customLLMFiles: [\n          {\n            filename: 'llms-v6.txt',\n            title: 'React Native Video v6 Documentation',\n            description: 'Complete documentation for React Native Video v6',\n            includePatterns: ['**/*.md', '**/*.mdx'],\n            fullContent: false,\n          },\n          {\n            filename: 'llms-v6-full.txt',\n            title: 'React Native Video v6 Documentation',\n            description: 'Complete documentation for React Native Video v6',\n            includePatterns: ['**/*.md', '**/*.mdx'],\n            fullContent: true,\n          },\n        ],\n      },\n    ],\n    // LLMs txt generation for v7\n    [\n      'docusaurus-plugin-llms',\n      {\n        id: 'llms-v7',\n        generateLLMsTxt: false,\n        generateLLMsFullTxt: false,\n        docsDir: 'docs',\n        pathTransformation: {\n          ignorePaths: ['docs'],\n          addPaths: ['react-native-video/docs/v7'],\n        },\n        version: '7.x.x',\n        customLLMFiles: [\n          {\n            filename: 'llms-v7.txt',\n            title: 'React Native Video v7 Documentation',\n            description: 'Complete documentation for React Native Video v7',\n            includePatterns: ['docs/**/*.md'],\n            fullContent: false,\n          },\n          {\n            filename: 'llms-v7-full.txt',\n            title: 'React Native Video v7 Documentation',\n            description: 'Complete documentation for React Native Video v7',\n            includePatterns: ['docs/**/*.md'],\n            fullContent: true,\n          },\n        ],\n      },\n    ],\n  ],\n};\n\nexport default config;\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"name\": \"@react-native-video/docs\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"docusaurus\": \"docusaurus\",\n    \"start\": \"TYPEDOC_WATCH=true docusaurus start\",\n    \"build\": \"docusaurus build\",\n    \"swizzle\": \"docusaurus swizzle\",\n    \"deploy\": \"docusaurus deploy\",\n    \"clear\": \"docusaurus clear\",\n    \"serve\": \"docusaurus serve\",\n    \"write-translations\": \"docusaurus write-translations\",\n    \"write-heading-ids\": \"docusaurus write-heading-ids\",\n    \"typecheck\": \"tsc\",\n    \"lint\": \"eslint .\"\n  },\n  \"dependencies\": {\n    \"@docusaurus/core\": \"^3.8.1\",\n    \"@docusaurus/faster\": \"^3.8.1\",\n    \"@docusaurus/preset-classic\": \"^3.8.1\",\n    \"@mdx-js/react\": \"^3.0.0\",\n    \"@widlarzgroup/docusaurus-ui\": \"^0.1.3\",\n    \"clsx\": \"^2.0.0\",\n    \"docusaurus-lunr-search\": \"^3.6.0\",\n    \"motion\": \"^12.23.26\",\n    \"prism-react-renderer\": \"^2.3.0\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@docusaurus/module-type-aliases\": \"^3.8.1\",\n    \"@docusaurus/tsconfig\": \"^3.8.1\",\n    \"@docusaurus/types\": \"^3.8.1\",\n    \"@widlarzgroup/eslint-plugin-docusaurus\": \"^0.0.1\",\n    \"docusaurus-plugin-llms\": \"^0.1.5\",\n    \"docusaurus-plugin-typedoc\": \"^1.4.0\",\n    \"eslint\": \"^8.51.0\",\n    \"typescript\": \"^5.2.2\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.5%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 3 chrome version\",\n      \"last 3 firefox version\",\n      \"last 5 safari version\"\n    ]\n  },\n  \"engines\": {\n    \"node\": \">=18.0\"\n  }\n}\n"
  },
  {
    "path": "docs/sidebars.ts",
    "content": "import { TypedSidebarsConfig } from '@widlarzgroup/docusaurus-ui';\n\nconst sidebars: TypedSidebarsConfig = {\n  docsSidebar: [\n    {\n      type: 'autogenerated',\n      dirName: '.',\n    },\n    {\n      type: 'html',\n      value:\n        '<hr style=\"margin: 1rem 0; border: none; border-top: 1px solid var(--ifm-color-emphasis-300);\" />',\n    },\n    {\n      type: 'link',\n      label: 'Example Apps',\n      href: 'https://github.com/TheWidlarzGroup/react-native-video/tree/master/example',\n    },\n    {\n      type: 'doc',\n      label: 'Useful Projects',\n      id: 'projects',\n    },\n    {\n      type: 'html',\n      value:\n        '<hr style=\"margin: 1rem 0; border: none; border-top: 1px solid var(--ifm-color-emphasis-300);\" />',\n    },\n    {\n      type: 'link',\n      label: 'Offer',\n      href: '/react-native-video/docs/v7/offer',\n    },\n    {\n      type: 'link',\n      label: 'Boost Your Issue',\n      href: 'https://www.thewidlarzgroup.com/issue-boost/?utm_source=rnv&utm_medium=docs&utm_campaign=sidebar&utm_id=issue-boost-button',\n    },\n    {\n      type: 'html',\n      value:\n        '<hr style=\"margin: 1rem 0; border: none; border-top: 1px solid var(--ifm-color-emphasis-300);\" />',\n    },\n    {\n      type: 'doc',\n      label: 'Updating',\n      id: 'updating',\n    },\n    {\n      type: 'link',\n      label: 'Releases',\n      href: 'https://github.com/TheWidlarzGroup/react-native-video/releases',\n    },\n  ],\n};\n\nexport default sidebars;\n"
  },
  {
    "path": "docs/src/components/Homepage/Enterprise/Enterprise.module.css",
    "content": ".enterprise {\n  padding: 6rem 2rem;\n}\n\n.container {\n  max-width: 1200px;\n  margin: 0 auto;\n}\n\n.content {\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  gap: 4rem;\n  align-items: center;\n}\n\n.textContent {\n  display: flex;\n  flex-direction: column;\n  gap: 1.5rem;\n}\n\n.label {\n  display: inline-block;\n  padding: 0.5rem 1rem;\n  font-size: 0.75rem;\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n  color: var(--color-accent);\n  background: var(--color-accent-subtle);\n  border-radius: 100px;\n  width: fit-content;\n}\n\n.title {\n  margin: 0;\n  font-size: 2.5rem;\n  font-weight: 700;\n  line-height: 1.2;\n  color: var(--color-text-primary);\n}\n\n.description {\n  margin: 0;\n  font-size: 1.125rem;\n  line-height: 1.6;\n  color: var(--color-text-secondary);\n}\n\n.ctaButton {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.875rem 1.5rem;\n  font-size: 1rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n  background: var(--color-accent-bright);\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.2s ease;\n  width: fit-content;\n}\n\n[data-theme='dark'] .ctaButton {\n  color: var(--color-bg-primary);\n}\n\n.ctaButton:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\n.arrowIcon {\n  width: 20px;\n  height: 20px;\n  transition: transform 0.2s ease;\n}\n\n.ctaButton:hover .arrowIcon {\n  transform: translateX(4px);\n}\n\n.featuresList {\n  display: flex;\n  flex-direction: column;\n  gap: 1rem;\n}\n\n@media (max-width: 968px) {\n  .content {\n    grid-template-columns: 1fr;\n    gap: 3rem;\n  }\n\n  .title {\n    font-size: 2rem;\n  }\n}\n\n@media (max-width: 640px) {\n  .enterprise {\n    padding: 4rem 1.5rem;\n  }\n\n  .title {\n    font-size: 1.75rem;\n  }\n\n  .description {\n    font-size: 1rem;\n  }\n}\n\n"
  },
  {
    "path": "docs/src/components/Homepage/Enterprise/Enterprise.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport { FeatureCard, type FeatureCardItem } from './FeatureCard/FeatureCard';\nimport styles from './Enterprise.module.css';\n\nconst ArrowIcon = require('@site/static/img/arrow-icon.svg').default;\nconst LayersIcon =\n  require('@site/static/img/homepage/enterprise/layers-icon.svg').default;\nconst ShieldIcon =\n  require('@site/static/img/homepage/enterprise/shield-icon.svg').default;\nconst LightningIcon =\n  require('@site/static/img/homepage/enterprise/lightning-icon.svg').default;\n\nconst CONTACT_URL =\n  'https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=landing-enterprise-solutions&utm_id=enterprise#Contact';\n\nconst FEATURE_LIST: FeatureCardItem[] = [\n  {\n    title: 'Custom Integration',\n    description: 'Custom solutions for your specific requirements',\n    Icon: LayersIcon,\n  },\n  {\n    title: 'Dedicated Support',\n    description: 'Priority support with direct access to our team',\n    Icon: ShieldIcon,\n  },\n  {\n    title: 'Expert Consultation',\n    description: 'Architecture guidance and best practices',\n    Icon: LightningIcon,\n  },\n];\n\nexport function Enterprise() {\n  return (\n    <section className={styles.enterprise}>\n      <div className={styles.container}>\n        <div className={styles.content}>\n          <div className={styles.textContent}>\n            <span className={styles.label}>Enterprise Solutions</span>\n            <h2 className={styles.title}>\n              Need custom integration or support?\n            </h2>\n            <p className={styles.description}>\n              Our team provides enterprise-grade integration services, custom\n              development, and dedicated support to help you build the perfect\n              video solution for your business.\n            </p>\n            <Link to={CONTACT_URL} className={styles.ctaButton}>\n              Get in touch\n              <ArrowIcon className={styles.arrowIcon} />\n            </Link>\n          </div>\n          <div className={styles.featuresList}>\n            {FEATURE_LIST.map((feature) => (\n              <FeatureCard key={feature.title} {...feature} />\n            ))}\n          </div>\n        </div>\n      </div>\n    </section>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Enterprise/FeatureCard/FeatureCard.module.css",
    "content": ".card {\n  display: flex;\n  gap: 1rem;\n  padding: 1.25rem;\n  background: var(--color-bg-secondary);\n  border: 1px solid var(--color-border);\n  border-radius: 12px;\n  transition: all 0.2s ease;\n}\n\n.card:hover {\n  border-color: var(--color-border-hover);\n}\n\n.iconWrapper {\n  flex-shrink: 0;\n  width: 48px;\n  height: 48px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n  border-radius: 10px;\n}\n\n.icon {\n  width: 24px;\n  height: 24px;\n  stroke: var(--color-accent);\n}\n\n.content {\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n\n.title {\n  margin: 0;\n  font-size: 1rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n}\n\n.description {\n  margin: 0;\n  font-size: 0.875rem;\n  color: var(--color-text-secondary);\n  line-height: 1.5;\n}\n\n"
  },
  {
    "path": "docs/src/components/Homepage/Enterprise/FeatureCard/FeatureCard.tsx",
    "content": "import React from 'react';\nimport styles from './FeatureCard.module.css';\n\nexport interface FeatureCardItem {\n  title: string;\n  description: string;\n  Icon: React.ComponentType<React.ComponentProps<'svg'>>;\n}\n\nexport function FeatureCard({ title, description, Icon }: FeatureCardItem) {\n  return (\n    <div className={styles.card}>\n      <div className={styles.iconWrapper}>\n        <Icon role=\"img\" className={styles.icon} />\n      </div>\n      <div className={styles.content}>\n        <h3 className={styles.title}>{title}</h3>\n        <p className={styles.description}>{description}</p>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Features/Feature/Feature.module.css",
    "content": ".card {\n  position: relative;\n  padding: 2rem;\n  border-radius: 16px;\n  background: var(--glass-bg);\n  border: 1px solid var(--color-border);\n  transition: all 0.3s ease;\n  backdrop-filter: blur(10px);\n  display: flex;\n  flex-direction: column;\n}\n\n.card:hover {\n  border-color: rgba(150, 201, 235, 0.4);\n  background: var(--color-bg-elevated);\n  box-shadow: 0 4px 20px rgba(150, 201, 235, 0.15);\n  transform: translateY(-2px);\n}\n\n[data-theme='dark'] .card:hover {\n  box-shadow: none;\n}\n\n.iconWrapper {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 48px;\n  height: 48px;\n  margin-bottom: 1.5rem;\n  border-radius: 12px;\n  background: var(--color-accent-subtle);\n  border: 1px solid rgba(150, 201, 235, 0.2);\n}\n\n[data-theme='dark'] .iconWrapper {\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.icon {\n  width: 24px;\n  height: 24px;\n  stroke: var(--color-accent);\n}\n\n.title {\n  font-size: 1.15rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n  margin-bottom: 0.75rem;\n  letter-spacing: -0.01em;\n}\n\n.description {\n  font-size: 0.95rem;\n  color: var(--color-text-secondary);\n  line-height: 1.7;\n  margin: 0;\n}\n\n.card:hover .iconWrapper {\n  background: rgba(150, 201, 235, 0.15);\n  border-color: rgba(150, 201, 235, 0.3);\n}\n\n[data-theme='dark'] .card:hover .iconWrapper {\n  background: rgba(150, 201, 235, 0.1);\n  border-color: rgba(150, 201, 235, 0.2);\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Features/Feature/Feature.tsx",
    "content": "import React from 'react';\nimport styles from './Feature.module.css';\n\nexport interface FeatureItem {\n  title: string;\n  Icon: React.ComponentType<React.ComponentProps<'svg'>>;\n  description: string;\n}\n\nexport function Feature({ title, Icon, description }: FeatureItem) {\n  return (\n    <div className={styles.card}>\n      <div className={styles.iconWrapper}>\n        <Icon role=\"img\" className={styles.icon} />\n      </div>\n      <h3 className={styles.title}>{title}</h3>\n      <p className={styles.description}>{description}</p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Features/Features.module.css",
    "content": ".features {\n  padding: 6rem 2rem 8rem;\n  position: relative;\n  background: linear-gradient(180deg, transparent 0%, var(--color-bg-primary) 15%, var(--color-bg-primary) 100%);\n  margin-top: -1px;\n}\n\n.container {\n  max-width: 1200px;\n  margin: 0 auto;\n}\n\n.header {\n  text-align: center;\n  margin-bottom: 4rem;\n}\n\n.label {\n  display: inline-block;\n  padding: 0.4rem 1rem;\n  background: var(--color-accent-subtle);\n  border: 1px solid rgba(150, 201, 235, 0.2);\n  border-radius: 100px;\n  font-size: 0.8rem;\n  font-weight: 600;\n  color: var(--color-accent);\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n  margin-bottom: 1.5rem;\n}\n\n.title {\n  font-size: clamp(1.75rem, 4vw, 2.5rem);\n  font-weight: 700;\n  color: var(--color-text-primary);\n  letter-spacing: -0.03em;\n  margin-bottom: 1rem;\n  line-height: 1.2;\n}\n\n.subtitle {\n  font-size: 1.1rem;\n  color: var(--color-text-muted);\n  max-width: 500px;\n  margin: 0 auto;\n  line-height: 1.7;\n}\n\n.grid {\n  display: grid;\n  grid-template-columns: repeat(3, 1fr);\n  gap: 1.5rem;\n}\n\n@media (max-width: 1024px) {\n  .grid {\n    grid-template-columns: repeat(2, 1fr);\n  }\n}\n\n@media (max-width: 640px) {\n  .grid {\n    grid-template-columns: 1fr;\n  }\n  \n  .features {\n    padding: 4rem 1.5rem 6rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Features/Features.tsx",
    "content": "import React from 'react';\nimport { Feature, type FeatureItem } from './Feature/Feature';\nimport styles from './Features.module.css';\n\nconst FEATURE_LIST: FeatureItem[] = [\n  {\n    title: 'React Native First',\n    Icon: require('@site/static/img/homepage/features/reactjs-icon.svg')\n      .default,\n    description:\n      'Built specifically for React Native with a native-first approach. Seamless integration with your existing React Native projects.',\n  },\n  {\n    title: 'Multi-Platform',\n    Icon: require('@site/static/img/homepage/features/platforms-icon.svg')\n      .default,\n    description:\n      'iOS, Android, tvOS, visionOS, Vega OS, Web, and Windows. One API across all platforms with platform-specific optimizations.',\n  },\n  {\n    title: 'Subtitles & Audio',\n    Icon: require('@site/static/img/homepage/features/subtitles-icon.svg')\n      .default,\n    description:\n      'Full support for multiple subtitle formats and audio tracks. Switch between languages on the fly.',\n  },\n  {\n    title: 'DRM Protected',\n    Icon: require('@site/static/img/homepage/features/shield-icon.svg').default,\n    description:\n      'Industry-standard DRM support including Widevine, FairPlay, and PlayReady for secure content delivery.',\n  },\n  {\n    title: 'High Performance',\n    Icon: require('@site/static/img/homepage/features/performance-icon.svg')\n      .default,\n    description:\n      'Optimized native players under the hood. Smooth playback with minimal memory footprint.',\n  },\n  {\n    title: 'Plugin System',\n    Icon: require('@site/static/img/homepage/features/plugins-icon.svg')\n      .default,\n    description:\n      'Extensible architecture with a powerful plugin system. Add custom functionality without forking.',\n  },\n];\n\nexport function Features() {\n  return (\n    <section className={styles.features}>\n      <div className={styles.container}>\n        <div className={styles.header}>\n          <span className={styles.label}>Features</span>\n          <h2 className={styles.title}>\n            Everything you need for video playback\n          </h2>\n          <p className={styles.subtitle}>\n            A comprehensive video solution trusted by thousands of developers\n            worldwide\n          </p>\n        </div>\n\n        <div className={styles.grid}>\n          {FEATURE_LIST.map((props, idx) => (\n            <Feature key={idx} {...props} />\n          ))}\n        </div>\n      </div>\n    </section>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/Badge/Badge.module.css",
    "content": ".badge {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.5rem 1rem;\n  margin-bottom: 1.5rem;\n  background: var(--color-secondary-subtle);\n  border: 1px solid rgba(250, 216, 91, 0.25);\n  border-radius: 100px;\n  font-size: 0.85rem;\n  font-weight: 500;\n  color: var(--color-secondary);\n}\n\n.dot {\n  width: 8px;\n  height: 8px;\n  background: var(--color-secondary-dim);\n  border-radius: 50%;\n}\n\n@media screen and (max-width: 480px) {\n  .badge {\n    font-size: 0.75rem;\n    padding: 0.4rem 0.8rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/Badge/Badge.tsx",
    "content": "import React, { type ReactNode } from 'react';\nimport { motion } from 'motion/react';\nimport { itemVariants } from '../Hero';\nimport styles from './Badge.module.css';\n\ninterface BadgeProps {\n  children: ReactNode;\n}\n\nexport function Badge({ children }: BadgeProps) {\n  return (\n    <motion.div className={styles.badge} variants={itemVariants}>\n      <motion.span\n        className={styles.dot}\n        animate={{ opacity: [0.5, 0.3, 0.5] }}\n        transition={{ duration: 2, ease: 'easeInOut', repeat: Infinity }}\n      />\n      {children}\n    </motion.div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/Buttons/Buttons.module.css",
    "content": ".buttons {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 1rem;\n  justify-content: center;\n}\n\n.primary,\n.secondary {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 1rem 2rem;\n  font-size: 1rem;\n  font-weight: 600;\n  border-radius: 12px;\n  text-decoration: none;\n  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.primary:hover,\n.secondary:hover {\n  transform: translateY(-2px);\n}\n\n.primary {\n  background: var(--color-accent-bright);\n  color: var(--color-dark);\n  box-shadow: 0 0 0 0 rgba(150, 201, 235, 0);\n}\n\n.primary:hover {\n  background: var(--color-accent-bright-dim);\n}\n\n.secondary {\n  background: transparent;\n  color: var(--color-text-primary);\n  border: 1px solid var(--color-border);\n}\n\n.secondary:hover {\n  background: var(--color-accent-subtle);\n  border-color: var(--color-border-hover);\n}\n\n.icon {\n  width: 20px;\n  height: 20px;\n  transition: transform 0.3s ease;\n}\n\n.primary:hover .icon {\n  transform: translateX(4px);\n}\n\n@media screen and (max-width: 768px) {\n  .buttons {\n    flex-direction: column;\n    width: 100%;\n  }\n  \n  .primary,\n  .secondary {\n    width: 100%;\n    justify-content: center;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/Buttons/Buttons.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport { motion } from 'motion/react';\nimport { itemVariants } from '../Hero';\nimport styles from './Buttons.module.css';\n\nconst ArrowIcon = require('@site/static/img/arrow-icon.svg').default;\nconst GitHubIcon = require('@site/static/img/github-icon.svg').default;\n\ninterface ButtonsProps {\n  docsLink: string;\n  githubLink: string;\n}\n\nexport function Buttons({ docsLink, githubLink }: ButtonsProps) {\n  return (\n    <motion.div className={styles.buttons} variants={itemVariants}>\n      <Link to={docsLink} className={styles.primary}>\n        Get Started\n        <ArrowIcon role=\"img\" className={styles.icon} />\n      </Link>\n      <Link to={githubLink} className={styles.secondary}>\n        <GitHubIcon role=\"img\" className={styles.icon} />\n        View on GitHub\n      </Link>\n    </motion.div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/Hero.module.css",
    "content": ".hero {\n  position: relative;\n  min-height: calc(100vh - var(--ifm-navbar-height));\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  padding: 4rem 2rem 8rem;\n  overflow: visible;\n  background: var(--color-bg-primary);\n}\n\n.hero::before {\n  content: '';\n  position: absolute;\n  top: -50%;\n  right: -20%;\n  width: 80vw;\n  height: 80vw;\n  max-width: 1200px;\n  max-height: 1200px;\n  background: rgba(250, 216, 91, 0.05);\n  border-radius: 50%;\n  z-index: 0;\n  pointer-events: none;\n  display: none;\n}\n\n.hero::after {\n  content: '';\n  position: absolute;\n  bottom: -40%;\n  left: -20%;\n  width: 70vw;\n  height: 70vw;\n  max-width: 1000px;\n  max-height: 1000px;\n  background: rgba(150, 201, 235, 0.05);\n  border-radius: 50%;\n  z-index: 0;\n  pointer-events: none;\n  display: none;\n}\n\n[data-theme='dark'] .hero::before {\n  background: rgba(250, 216, 91, 0.008);\n}\n\n[data-theme='dark'] .hero::after {\n  background: rgba(150, 201, 235, 0.004);\n}\n\n.content {\n  position: relative;\n  z-index: 1;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  text-align: center;\n  max-width: 900px;\n}\n\n.logo {\n  width: 120px;\n  height: 80px;\n  margin-bottom: 2rem;\n}\n\n.title {\n  font-size: clamp(2.5rem, 8vw, 5rem);\n  font-weight: 800;\n  letter-spacing: -0.04em;\n  line-height: 1.1;\n  margin-bottom: 1.5rem;\n  color: var(--color-text-primary);\n}\n\n.titleAccent {\n  background: linear-gradient(135deg, var(--color-accent-bright) 0%, var(--color-accent-bright-dim) 100%);\n  -webkit-background-clip: text;\n  -webkit-text-fill-color: transparent;\n  background-clip: text;\n  padding-right: 0.05em;\n}\n\n.subtitle {\n  font-size: clamp(1.1rem, 2.5vw, 1.4rem);\n  font-weight: 400;\n  color: var(--color-text-secondary);\n  max-width: 600px;\n  line-height: 1.7;\n  margin-bottom: 3rem;\n}\n\n@media screen and (min-width: 769px) {\n  .hero::before,\n  .hero::after {\n    display: block;\n  }\n}\n\n@media screen and (max-width: 768px) {\n  .hero {\n    padding: 3rem 1.5rem;\n    min-height: auto;\n  }\n  \n  .logo {\n    width: 100px;\n    height: 66px;\n  }\n}\n\n@media screen and (max-width: 480px) {\n  .hero {\n    padding: 2rem 1rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/Hero.tsx",
    "content": "import React, { useMemo } from 'react';\nimport { useDocsPreferredVersion } from '@docusaurus/theme-common';\nimport { motion, type Variants } from 'motion/react';\nimport { Badge } from './Badge/Badge';\nimport { Buttons } from './Buttons/Buttons';\nimport { Stats } from './Stats/Stats';\nimport { ScrollIndicator } from './ScrollIndicator/ScrollIndicator';\nimport styles from './Hero.module.css';\n\nconst GITHUB_URL = 'https://github.com/TheWidlarzGroup/react-native-video';\nconst DEFAULT_DOCS_PATH = '/docs/v6/intro';\n\nconst STATS = [\n  { value: '7k+', label: 'GitHub Stars' },\n  { value: '350k+', label: 'Weekly Downloads' },\n  { value: 'TWG', label: 'Company Backed' },\n];\n\nexport const itemVariants: Variants = {\n  hidden: { opacity: 0, y: 20 },\n  visible: {\n    opacity: 1,\n    y: 0,\n  },\n};\n\nconst logoVariants: Variants = {\n  hidden: { opacity: 0, scale: 0.8 },\n  visible: {\n    opacity: 1,\n    scale: 1,\n  },\n};\n\ninterface PreferredVersion {\n  preferredVersion: { label: string; mainDocId: string; path: string } | null;\n}\n\nfunction useDocsLink() {\n  const version = useDocsPreferredVersion() as PreferredVersion;\n\n  return useMemo(() => {\n    if (!version.preferredVersion) {\n      return DEFAULT_DOCS_PATH;\n    }\n    return `${version.preferredVersion.path}/${version.preferredVersion.mainDocId}`;\n  }, [version]);\n}\n\nexport function Hero() {\n  const docsLink = useDocsLink();\n\n  return (\n    <header className={styles.hero}>\n      <motion.div\n        className={styles.content}\n        initial=\"hidden\"\n        animate=\"visible\"\n        transition={{\n          staggerChildren: 0.1,\n          delayChildren: 0.1,\n        }}\n      >\n        <Badge>v7 Beta Available</Badge>\n\n        <motion.img\n          src=\"./img/twg-logo.png\"\n          alt=\"TheWidlarzGroup logo\"\n          className={styles.logo}\n          variants={logoVariants}\n          transition={{ duration: 0.5, ease: 'easeOut' }}\n        />\n\n        <motion.h1\n          className={styles.title}\n          variants={itemVariants}\n          transition={{ duration: 0.5, ease: 'easeOut' }}\n        >\n          <span className={styles.titleAccent}>Video</span> for React Native\n        </motion.h1>\n\n        <motion.p\n          className={styles.subtitle}\n          variants={itemVariants}\n          transition={{ duration: 0.5, ease: 'easeOut' }}\n        >\n          The most feature-rich video player for React Native. Multi-platform\n          support with DRM, subtitles, and audio tracks.\n        </motion.p>\n\n        <Buttons docsLink={docsLink} githubLink={GITHUB_URL} />\n        <Stats stats={STATS} />\n      </motion.div>\n\n      <ScrollIndicator />\n    </header>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/ScrollIndicator/ScrollIndicator.module.css",
    "content": ".indicator {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  gap: 0.5rem;\n  color: var(--color-text-muted);\n  font-size: 0.75rem;\n  text-transform: uppercase;\n  letter-spacing: 0.1em;\n}\n\n.line {\n  width: 1px;\n  height: 40px;\n  background: linear-gradient(to bottom, var(--color-text-muted), transparent);\n}\n\n@media screen and (max-width: 768px) {\n  .indicator {\n    display: none;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/ScrollIndicator/ScrollIndicator.tsx",
    "content": "import React from 'react';\nimport { motion } from 'motion/react';\nimport styles from './ScrollIndicator.module.css';\n\ninterface ScrollIndicatorProps {\n  label?: string;\n}\n\nexport function ScrollIndicator({ label = 'Explore' }: ScrollIndicatorProps) {\n  return (\n    <motion.div\n      className={styles.indicator}\n      initial={{ opacity: 0, y: 20 }}\n      animate={{\n        opacity: [0.5, 1, 0.5],\n        y: [0, 10, 0],\n      }}\n      transition={{\n        duration: 2,\n        repeat: Infinity,\n        ease: 'easeInOut',\n        delay: 0.6,\n      }}\n    >\n      <span>{label}</span>\n      <div className={styles.line} />\n    </motion.div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/Stats/Stats.module.css",
    "content": ".stats {\n  display: flex;\n  gap: 4rem;\n  margin-top: 5rem;\n  padding-top: 3rem;\n  border-top: 1px solid var(--color-border);\n}\n\n.stat {\n  text-align: center;\n}\n\n.value {\n  display: block;\n  font-size: 2.5rem;\n  font-weight: 700;\n  color: var(--color-accent-bright);\n  letter-spacing: -0.02em;\n}\n\n.label {\n  font-size: 0.9rem;\n  color: var(--color-text-muted);\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n}\n\n@media screen and (max-width: 768px) {\n  .stats {\n    flex-direction: column;\n    gap: 2rem;\n    margin-top: 3rem;\n    padding-top: 2rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Homepage/Hero/Stats/Stats.tsx",
    "content": "import React from 'react';\nimport { motion } from 'motion/react';\nimport { itemVariants } from '../Hero';\nimport styles from './Stats.module.css';\n\ninterface StatItem {\n  value: string;\n  label: string;\n}\n\ninterface StatsProps {\n  stats: StatItem[];\n}\n\nexport function Stats({ stats }: StatsProps) {\n  return (\n    <motion.div className={styles.stats} variants={itemVariants}>\n      {stats.map((stat) => (\n        <div key={stat.label} className={styles.stat}>\n          <span className={styles.value}>{stat.value}</span>\n          <span className={styles.label}>{stat.label}</span>\n        </div>\n      ))}\n    </motion.div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7ApiModel/V7ApiModel.module.css",
    "content": ".container {\n  display: flex;\n  flex-direction: column;\n  gap: 1.5rem;\n  margin-bottom: 1rem;\n}\n\n.text {\n  font-size: 1rem;\n  line-height: 1.7;\n  color: var(--color-text-secondary);\n  margin: 0;\n  max-width: 700px;\n}\n\n.useCases {\n  display: grid;\n  grid-template-columns: repeat(2, 1fr);\n  gap: 1rem;\n}\n\n.useCase {\n  padding: 1rem 1.25rem;\n  border-left: 3px solid var(--color-accent);\n  background: var(--color-accent-subtle);\n  border-radius: 0 8px 8px 0;\n}\n\n.useCaseTitle {\n  font-size: 0.95rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n  margin: 0 0 0.5rem;\n}\n\n.useCaseDescription {\n  font-size: 0.875rem;\n  color: var(--color-text-secondary);\n  line-height: 1.6;\n  margin: 0;\n}\n\n@media (max-width: 640px) {\n  .useCases {\n    grid-template-columns: 1fr;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7ApiModel/V7ApiModel.tsx",
    "content": "import React from 'react';\nimport styles from './V7ApiModel.module.css';\n\nconst USE_CASES = [\n  {\n    title: 'Video feeds / lists',\n    description:\n      'Prepare upcoming players in advance for smoother scrolling and fewer glitches.',\n  },\n  {\n    title: 'Faster playback start',\n    description:\n      'Preload before the user clicks \"play\" / before the screen appears.',\n  },\n];\n\nexport function V7ApiModel() {\n  return (\n    <div className={styles.container}>\n      <p className={styles.text}>\n        In v6, \"player = view\". In v7, the player is a separate entity: you can\n        pass it as a prop to a view or prepare it in advance before rendering\n        anything.\n      </p>\n      <div className={styles.useCases}>\n        {USE_CASES.map((useCase) => (\n          <div key={useCase.title} className={styles.useCase}>\n            <h4 className={styles.useCaseTitle}>{useCase.title}</h4>\n            <p className={styles.useCaseDescription}>{useCase.description}</p>\n          </div>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7FeatureCards/V7FeatureCards.module.css",
    "content": ".grid {\n  display: grid;\n  grid-template-columns: repeat(3, 1fr);\n  gap: 1rem;\n  margin: 1.5rem 0 2rem;\n}\n\n.card {\n  padding: 1.25rem;\n  border-radius: 12px;\n  background: var(--glass-bg);\n  border: 1px solid var(--color-border);\n  transition: all 0.3s ease;\n}\n\n.card:hover {\n  border-color: var(--color-border-hover);\n  background: var(--color-bg-elevated);\n}\n\n.card.wide {\n  grid-column: span 2;\n}\n\n.title {\n  font-size: 1rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n  margin: 0 0 0.5rem;\n}\n\n.description {\n  font-size: 0.9rem;\n  color: var(--color-text-secondary);\n  line-height: 1.6;\n  margin: 0;\n}\n\n.badge {\n  display: inline-block;\n  margin-top: 0.75rem;\n  padding: 0.25rem 0.6rem;\n  font-size: 0.7rem;\n  font-weight: 600;\n  color: var(--color-accent);\n  background: var(--color-accent-subtle);\n  border: 1px solid rgba(150, 201, 235, 0.2);\n  border-radius: 100px;\n}\n\n@media (max-width: 968px) {\n  .grid {\n    grid-template-columns: repeat(2, 1fr);\n  }\n\n  .card.wide {\n    grid-column: span 2;\n  }\n}\n\n@media (max-width: 640px) {\n  .grid {\n    grid-template-columns: 1fr;\n  }\n\n  .card.wide {\n    grid-column: span 1;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7FeatureCards/V7FeatureCards.tsx",
    "content": "import React from 'react';\nimport styles from './V7FeatureCards.module.css';\n\ninterface FeatureCard {\n  title: string;\n  description: string;\n  badge?: string;\n  wide?: boolean;\n}\n\nconst FEATURES: FeatureCard[] = [\n  {\n    title: 'Player ≠ View',\n    description:\n      'Playback logic is separated from the UI component - the player can exist independently from the view.',\n  },\n  {\n    title: 'Preloading',\n    description:\n      'Prepare the player in advance before showing video to the user.',\n    badge: 'In our tests: 6x faster loading',\n  },\n  {\n    title: 'Better resource management',\n    description:\n      'The new separation unlocks better resource management and enables feed/video list scenarios.',\n  },\n  {\n    title: 'Performance',\n    description:\n      'Fewer FPS drops during player creation - we focused on one of the biggest pain points.',\n  },\n  {\n    title: 'Nitro Modules + New Architecture',\n    description:\n      'Nitro is the foundation of v7: more performance and stability plus easier support for both New and Old Architecture.',\n    wide: true,\n  },\n];\n\nfunction FeatureCard({ title, description, badge, wide }: FeatureCard) {\n  return (\n    <div className={`${styles.card} ${wide ? styles.wide : ''}`}>\n      <h3 className={styles.title}>{title}</h3>\n      <p className={styles.description}>{description}</p>\n      {badge && <span className={styles.badge}>{badge}</span>}\n    </div>\n  );\n}\n\nexport function V7FeatureCards() {\n  return (\n    <div className={styles.grid}>\n      {FEATURES.map((feature) => (\n        <FeatureCard key={feature.title} {...feature} />\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7Lead/V7Lead.module.css",
    "content": ".lead {\n  display: flex;\n  flex-direction: column;\n  gap: 1rem;\n  max-width: 800px;\n  margin-bottom: 1rem;\n}\n\n.text {\n  font-size: 1.25rem;\n  line-height: 1.7;\n  color: var(--color-text-primary);\n  margin: 0;\n}\n\n.textSecondary {\n  font-size: 1.1rem;\n  line-height: 1.7;\n  color: var(--color-text-secondary);\n  margin: 0;\n}\n\n.code {\n  background: var(--color-bg-tertiary);\n  padding: 0.2rem 0.5rem;\n  border-radius: 6px;\n  font-size: 1.1rem;\n  color: var(--color-accent);\n  border: 1px solid var(--color-border);\n}\n\n@media (max-width: 640px) {\n  .text {\n    font-size: 1.1rem;\n  }\n\n  .textSecondary {\n    font-size: 1rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7Lead/V7Lead.tsx",
    "content": "import React from 'react';\nimport styles from './V7Lead.module.css';\n\nexport function V7Lead() {\n  return (\n    <div className={styles.lead}>\n      <p className={styles.text}>\n        <code className={styles.code}>react-native-video</code> v7 is the\n        biggest change in the library's history: we rebuilt it from the ground\n        up to be modern, stable, and ready for React Native's future.\n      </p>\n      <p className={styles.textSecondary}>\n        The most important foundation of v7 is the separation of player logic\n        from the view component and support for Nitro Modules - unlocking\n        preloading, real performance improvements, and full compatibility with\n        React Native's new architecture.\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7NitroSection/V7NitroSection.module.css",
    "content": ".container {\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n  margin-bottom: 1rem;\n}\n\n.text {\n  font-size: 1rem;\n  line-height: 1.7;\n  color: var(--color-text-secondary);\n  margin: 0;\n  max-width: 700px;\n}\n\n.quote {\n  margin: 1rem 0 0;\n  padding: 1rem 1.25rem;\n  border-left: 3px solid var(--color-secondary);\n  background: var(--color-secondary-subtle);\n  border-radius: 0 8px 8px 0;\n  font-style: italic;\n  font-size: 0.95rem;\n  color: var(--color-text-primary);\n  max-width: 600px;\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7NitroSection/V7NitroSection.tsx",
    "content": "import React from 'react';\nimport styles from './V7NitroSection.module.css';\n\nexport function V7NitroSection() {\n  return (\n    <div className={styles.container}>\n      <p className={styles.text}>\n        v7 was built on Nitro Modules, which delivers a strong boost in\n        performance and stability.\n      </p>\n      <p className={styles.text}>\n        Thanks to Nitro, it's easier to support both New and Old Architecture\n        simultaneously - and faster to deliver new features.\n      </p>\n      <blockquote className={styles.quote}>\n        Nitro enables us to support both the New and Old Architecture with\n        minimal effort\n      </blockquote>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7OpenSource/V7OpenSource.module.css",
    "content": ".container {\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n}\n\n.text {\n  font-size: 1rem;\n  line-height: 1.7;\n  color: var(--color-text-secondary);\n  margin: 0;\n  max-width: 700px;\n}\n\n.text strong {\n  color: var(--color-text-primary);\n}\n\n.note {\n  display: flex;\n  align-items: flex-start;\n  gap: 0.75rem;\n  margin-top: 0.75rem;\n  padding: 1rem 1.25rem;\n  background: var(--color-accent-subtle);\n  border: 1px solid rgba(150, 201, 235, 0.2);\n  border-radius: 8px;\n  max-width: 700px;\n}\n\n.noteIcon {\n  font-size: 1.1rem;\n  flex-shrink: 0;\n}\n\n.noteText {\n  font-size: 0.9rem;\n  line-height: 1.6;\n  color: var(--color-text-secondary);\n  margin: 0;\n}\n\n.noteText strong {\n  color: var(--color-text-primary);\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7OpenSource/V7OpenSource.tsx",
    "content": "import React from 'react';\nimport styles from './V7OpenSource.module.css';\n\nexport function V7OpenSource() {\n  return (\n    <div className={styles.container}>\n      <p className={styles.text}>\n        The library remains <strong>community-first</strong> - the core\n        functionality will stay free and open source, just like today.\n      </p>\n      <p className={styles.text}>\n        There is a set of paid plugins and services that enhance the\n        functionality.\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7ProPlugins/V7ProPlugins.module.css",
    "content": ".container {\n  display: flex;\n  flex-direction: column;\n  gap: 1.5rem;\n  margin-top: 1rem;\n}\n\n.plugin {\n  padding: 1.5rem;\n  border-radius: 12px;\n  background: var(--glass-bg);\n  border-left: 4px solid;\n}\n\n.plugin.pro {\n  border-left-color: var(--color-pro);\n}\n\n.plugin.accent {\n  border-left-color: var(--color-accent);\n}\n\n.plugin.secondary {\n  border-left-color: var(--color-secondary);\n}\n\n.title {\n  margin: 0 0 0.75rem 0;\n  font-size: 1.25rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n}\n\n.description {\n  margin: 0 0 1rem 0;\n  font-size: 0.95rem;\n  line-height: 1.6;\n  color: var(--color-text-secondary);\n}\n\n.features {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n  margin-bottom: 1rem;\n}\n\n.featureItem {\n  font-size: 0.9rem;\n  line-height: 1.5;\n  color: var(--color-text-secondary);\n  padding-left: 1rem;\n  position: relative;\n}\n\n.featureItem::before {\n  content: '•';\n  position: absolute;\n  left: 0;\n  color: var(--color-text-muted);\n}\n\n.featureItem strong {\n  color: var(--color-text-primary);\n}\n\n.footer {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding-top: 1rem;\n  border-top: 1px solid var(--color-border);\n}\n\n.platforms {\n  font-size: 0.85rem;\n  color: var(--color-text-muted);\n}\n\n.link {\n  font-size: 0.9rem;\n  font-weight: 500;\n  color: var(--color-accent) !important;\n  text-decoration: none !important;\n}\n\n.link:hover {\n  text-decoration: underline !important;\n}\n\n/* Custom CTA */\n.customCta {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 2rem;\n  padding: 1.5rem;\n  background: linear-gradient(135deg, rgba(150, 201, 235, 0.1), rgba(184, 151, 255, 0.1));\n  border-radius: 12px;\n  border: 1px solid var(--color-border);\n}\n\n@media (max-width: 640px) {\n  .customCta {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n.customContent {\n  flex: 1;\n}\n\n.customTitle {\n  margin: 0 0 0.5rem 0;\n  font-size: 1.1rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n}\n\n.customText {\n  margin: 0;\n  font-size: 0.9rem;\n  line-height: 1.5;\n  color: var(--color-text-secondary);\n}\n\n.customText code {\n  padding: 0.15rem 0.4rem;\n  font-size: 0.85rem;\n  background: var(--color-bg-secondary);\n  border-radius: 4px;\n}\n\n.customButton {\n  padding: 0.75rem 1.5rem;\n  font-size: 0.9rem;\n  font-weight: 500;\n  color: #0f0f0f !important;\n  background: var(--color-accent);\n  border-radius: 8px;\n  text-decoration: none !important;\n  white-space: nowrap;\n  transition: opacity 0.2s ease;\n}\n\n.customButton:hover {\n  opacity: 0.9;\n  text-decoration: none !important;\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7ProPlugins/V7ProPlugins.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport styles from './V7ProPlugins.module.css';\n\nexport function V7ProPlugins() {\n  return (\n    <div className={styles.container}>\n      {/* Offline Video SDK */}\n      <div className={`${styles.plugin} ${styles.pro}`}>\n        <h3 className={styles.title}>Offline Video SDK</h3>\n        <p className={styles.description}>\n          Download and play video content offline with full DRM support. Perfect\n          for apps that need content available without an internet connection -\n          streaming platforms, educational apps, or any app where users want to\n          watch videos on the go.\n        </p>\n        <div className={styles.features}>\n          <div className={styles.featureItem}>\n            <strong>HLS/DASH/MP4 downloading</strong> - download and store\n            streams for offline playback\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Offline DRM</strong> - play DRM-protected content offline\n            with proper license handling\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Multiple audio tracks & subtitles</strong> - download\n            specific language tracks to optimize storage\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Background download management</strong> - queuing, progress\n            tracking, retries, pause/resume\n          </div>\n        </div>\n        <div className={styles.footer}>\n          <span className={styles.platforms}>iOS, Android</span>\n          <Link\n            to=\"https://www.thewidlarzgroup.com/offline-video-sdk?utm_source=rnv&utm_medium=docs&utm_campaign=intro&utm_id=offline-video-sdk\"\n            className={styles.link}\n          >\n            Learn more →\n          </Link>\n        </div>\n      </div>\n\n      {/* Background Uploader */}\n      <div className={`${styles.plugin} ${styles.accent}`}>\n        <h3 className={styles.title}>Background Uploader</h3>\n        <p className={styles.description}>\n          Upload files in the background with enterprise-grade reliability.\n          Ideal for apps that handle user-generated content - social media,\n          video sharing platforms, or any app where users upload large files.\n        </p>\n        <div className={styles.features}>\n          <div className={styles.featureItem}>\n            <strong>Background uploading</strong> - continue uploads even when\n            the app is in the background\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Retry support</strong> - automatic retries with exponential\n            backoff\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Progress tracking</strong> - real-time upload progress\n            monitoring\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Queue management</strong> - handle multiple uploads with\n            priority control\n          </div>\n        </div>\n        <div className={styles.footer}>\n          <span className={styles.platforms}>iOS, Android</span>\n          <Link\n            to=\"https://sdk.thewidlarzgroup.com/background-uploader?utm_source=rnv&utm_medium=docs&utm_campaign=intro&utm_id=background-uploader\"\n            className={styles.link}\n          >\n            Learn more →\n          </Link>\n        </div>\n      </div>\n\n      {/* Chapters */}\n      <div className={`${styles.plugin} ${styles.secondary}`}>\n        <h3 className={styles.title}>Chapters</h3>\n        <p className={styles.description}>\n          Add chapter markers to your video player for easy navigation between\n          segments. Great for educational content, tutorials, podcasts, or any\n          long-form video where users need to jump to specific sections.\n        </p>\n        <div className={styles.features}>\n          <div className={styles.featureItem}>\n            <strong>Visual markers</strong> - chapter points displayed on the\n            seekbar\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Tooltip support</strong> - show chapter titles when\n            hovering/tapping markers\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Programmatic navigation</strong> - jump to chapters via API\n          </div>\n          <div className={styles.featureItem}>\n            <strong>Customizable styling</strong> - control marker colors and\n            appearance\n          </div>\n        </div>\n        <div className={styles.footer}>\n          <span className={styles.platforms}>iOS, Android</span>\n          <Link\n            to=\"https://sdk.thewidlarzgroup.com/chapters?utm_source=rnv&utm_medium=docs&utm_campaign=intro&utm_id=chapters\"\n            className={styles.link}\n          >\n            Learn more →\n          </Link>\n        </div>\n      </div>\n\n      {/* Custom CTA */}\n      <div className={styles.customCta}>\n        <div className={styles.customContent}>\n          <h4 className={styles.customTitle}>Need something specific?</h4>\n          <p className={styles.customText}>\n            We can build any video-related plugin for your requirements. Our\n            team maintains\n            <code>react-native-video</code> and knows the codebase inside out.\n          </p>\n        </div>\n        <Link\n          to=\"https://sdk.thewidlarzgroup.com/ask-for-plugin?utm_source=rnv&utm_medium=docs&utm_campaign=intro&utm_id=ask-for-plugin\"\n          className={styles.customButton}\n        >\n          Request a custom plugin\n        </Link>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7StatusTimeline/V7StatusTimeline.module.css",
    "content": ".container {\n  display: flex;\n  flex-direction: column;\n  gap: 1.5rem;\n  margin-bottom: 1rem;\n}\n\n.list {\n  margin: 0;\n  padding-left: 1.25rem;\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.item {\n  font-size: 0.95rem;\n  line-height: 1.6;\n  color: var(--color-text-secondary);\n}\n\n.item strong {\n  color: var(--color-text-primary);\n}\n\n.timeline {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 0.75rem;\n  padding: 1.5rem 2rem;\n  background: var(--glass-bg);\n  border: 1px solid var(--color-border);\n  border-radius: 12px;\n}\n\n.step {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n}\n\n.step.upcoming {\n  opacity: 0.5;\n}\n\n.dot {\n  width: 12px;\n  height: 12px;\n  border-radius: 50%;\n  background: var(--color-text-muted);\n}\n\n.dot.completed {\n  background: var(--color-accent);\n}\n\n.dot.active {\n  background: var(--color-secondary);\n  box-shadow: 0 0 0 4px var(--color-secondary-subtle);\n}\n\n.label {\n  font-size: 0.9rem;\n  font-weight: 500;\n  color: var(--color-text-primary);\n}\n\n.line {\n  width: 40px;\n  height: 2px;\n  background: var(--color-border);\n}\n\n@media (max-width: 480px) {\n  .timeline {\n    padding: 1rem;\n    gap: 0.5rem;\n  }\n\n  .line {\n    width: 24px;\n  }\n\n  .label {\n    font-size: 0.8rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Intro/V7StatusTimeline/V7StatusTimeline.tsx",
    "content": "import React from 'react';\nimport styles from './V7StatusTimeline.module.css';\n\nconst STATUS_POINTS = [\n  {\n    label: 'v7 was rewritten from scratch',\n    description: 'to deliver a stable, modern API.',\n  },\n  {\n    label: 'Public version (alpha → beta)',\n    description:\n      'is available for testing - your feedback really impacts the final release.',\n  },\n  {\n    label: 'Public roadmap includes new features',\n    description: 'and improvements planned for upcoming releases.',\n  },\n];\n\nexport function V7StatusTimeline() {\n  return (\n    <div className={styles.container}>\n      <ul className={styles.list}>\n        {STATUS_POINTS.map((point) => (\n          <li key={point.label} className={styles.item}>\n            <strong>{point.label}</strong> {point.description}\n          </li>\n        ))}\n      </ul>\n\n      <div className={styles.timeline}>\n        <div className={styles.step}>\n          <span className={`${styles.dot} ${styles.completed}`} />\n          <span className={styles.label}>Alpha</span>\n        </div>\n        <div className={styles.line} />\n        <div className={styles.step}>\n          <span className={`${styles.dot} ${styles.active}`} />\n          <span className={styles.label}>Beta</span>\n        </div>\n        <div className={styles.line} />\n        <div className={`${styles.step} ${styles.upcoming}`}>\n          <span className={styles.dot} />\n          <span className={styles.label}>Stable</span>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Intro/index.ts",
    "content": "export { V7Lead } from './V7Lead/V7Lead';\nexport { V7FeatureCards } from './V7FeatureCards/V7FeatureCards';\nexport { V7ApiModel } from './V7ApiModel/V7ApiModel';\nexport { V7NitroSection } from './V7NitroSection/V7NitroSection';\nexport { V7StatusTimeline } from './V7StatusTimeline/V7StatusTimeline';\nexport { V7OpenSource } from './V7OpenSource/V7OpenSource';\nexport { V7ProPlugins } from './V7ProPlugins/V7ProPlugins';\n"
  },
  {
    "path": "docs/src/components/Offer/Contact/Contact.module.css",
    "content": ".section {\n  padding: 3rem 0 4rem;\n}\n\n.sectionTitle {\n  font-size: 1.5rem;\n  font-weight: 700;\n  color: var(--color-text-primary);\n  margin: 0 0 2rem;\n}\n\n.content {\n  display: grid;\n  grid-template-columns: 1fr 300px;\n  gap: 2rem;\n  align-items: start;\n}\n\n.checklist {\n  padding: 1.5rem;\n  border-radius: 16px;\n  background: var(--glass-bg);\n  border: 1px solid var(--color-border);\n}\n\n.intro {\n  margin: 0 0 1rem;\n  font-size: 0.95rem;\n  color: var(--color-text-secondary);\n}\n\n.list {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n}\n\n.item {\n  display: flex;\n  align-items: flex-start;\n  gap: 0.75rem;\n  font-size: 0.9rem;\n  line-height: 1.5;\n}\n\n.checkIcon {\n  width: 18px;\n  height: 18px;\n  color: var(--color-accent);\n  stroke: var(--color-accent);\n  flex-shrink: 0;\n  margin-top: 2px;\n}\n\n.itemLabel {\n  font-weight: 600;\n  color: var(--color-text-primary);\n  white-space: nowrap;\n}\n\n.itemValue {\n  color: var(--color-text-secondary);\n}\n\n.cta {\n  padding: 1.5rem;\n  border-radius: 16px;\n  background: var(--color-accent-subtle);\n  border: 1px solid rgba(150, 201, 235, 0.2);\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  text-align: center;\n}\n\n.ctaIcon {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 56px;\n  height: 56px;\n  margin-bottom: 1rem;\n  border-radius: 50%;\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.mailIcon {\n  width: 28px;\n  height: 28px;\n  color: var(--color-accent);\n  stroke: var(--color-accent);\n}\n\n.ctaText {\n  margin: 0 0 1.25rem;\n  font-size: 0.95rem;\n  color: var(--color-text-secondary);\n  line-height: 1.5;\n}\n\n.ctaButton {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 100%;\n  padding: 0.875rem 1.5rem;\n  font-size: 1rem;\n  font-weight: 600;\n  color: #0f0f0f !important;\n  background: var(--color-accent-bright);\n  border: none !important;\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.2s ease;\n}\n\n.ctaButton:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 4px 12px var(--color-accent-glow);\n  color: #0f0f0f !important;\n  text-decoration: none;\n  border: none !important;\n}\n\n@media (max-width: 868px) {\n  .content {\n    grid-template-columns: 1fr;\n  }\n\n  .cta {\n    order: -1;\n  }\n}\n\n@media (max-width: 480px) {\n  .item {\n    flex-wrap: wrap;\n  }\n\n  .itemValue {\n    width: 100%;\n    padding-left: calc(18px + 0.75rem);\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Contact/Contact.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport styles from './Contact.module.css';\n\nconst MailIcon = require('@site/static/img/intro/mail-icon.svg').default;\nconst CheckIcon = require('@site/static/img/intro/check-icon.svg').default;\n\nconst CONTACT_URL =\n  'https://sdk.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=intro-contact-form&utm_id=intro&contact=true';\n\nconst CHECKLIST = [\n  { label: 'Platform', value: 'iOS / Android' },\n  { label: 'Video', value: 'HLS / DASH / MP4 (+ DRM if any)' },\n  {\n    label: 'Need',\n    value: 'Issue Booster / Support / Offline / Custom UI / Boilerplate',\n  },\n  { label: 'Timeline', value: 'ASAP / planned' },\n  { label: 'Repro/design link', value: '(optional)' },\n];\n\nexport function Contact() {\n  return (\n    <div className={styles.content}>\n      <div className={styles.checklist}>\n        <p className={styles.intro}>When you reach out, please include:</p>\n        <ul className={styles.list}>\n          {CHECKLIST.map((item) => (\n            <li key={item.label} className={styles.item}>\n              <CheckIcon className={styles.checkIcon} />\n              <span className={styles.itemLabel}>{item.label}:</span>\n              <span className={styles.itemValue}>{item.value}</span>\n            </li>\n          ))}\n        </ul>\n      </div>\n      <div className={styles.cta}>\n        <div className={styles.ctaIcon}>\n          <MailIcon className={styles.mailIcon} />\n        </div>\n        <p className={styles.ctaText}>\n          Ready to talk? We'll respond within 24 hours.\n        </p>\n        <Link to={CONTACT_URL} className={styles.ctaButton}>\n          Contact us\n        </Link>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Offer/DecisionTable/DecisionTable.module.css",
    "content": ".section {\n  padding: 3rem 0;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.sectionTitle {\n  font-size: 1.5rem;\n  font-weight: 700;\n  color: var(--color-text-primary);\n  margin: 0 0 2rem;\n}\n\n.tableWrapper {\n  overflow-x: auto;\n  border-radius: 12px;\n  border: 1px solid var(--color-border);\n  background: var(--glass-bg);\n}\n\n.table {\n  width: 100%;\n  border-collapse: collapse;\n  font-size: 0.95rem;\n}\n\n.th {\n  padding: 1rem 1.25rem;\n  text-align: left;\n  font-weight: 600;\n  font-size: 0.8rem;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  color: var(--color-text-muted);\n  background: var(--color-bg-tertiary);\n  border-bottom: 1px solid var(--color-border);\n}\n\n.th:first-child {\n  border-top-left-radius: 11px;\n}\n\n.th:last-child {\n  border-top-right-radius: 11px;\n}\n\n.row {\n  transition: background 0.2s ease;\n}\n\n.row:hover {\n  background: var(--color-bg-elevated);\n}\n\n.row:not(:last-child) .td {\n  border-bottom: 1px solid var(--color-border);\n}\n\n.td {\n  padding: 1rem 1.25rem;\n  vertical-align: middle;\n}\n\n.situation {\n  color: var(--color-text-secondary);\n  font-style: italic;\n}\n\n.choose {\n  display: inline-block;\n  padding: 0.3rem 0.7rem;\n  font-size: 0.85rem;\n  font-weight: 600;\n  border-radius: 6px;\n}\n\n.community {\n  color: var(--color-text-secondary);\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.booster {\n  color: var(--color-secondary);\n  background: var(--color-secondary-subtle);\n  border: 1px solid rgba(250, 216, 91, 0.2);\n}\n\n.support {\n  color: var(--color-accent);\n  background: var(--color-accent-subtle);\n  border: 1px solid rgba(150, 201, 235, 0.2);\n}\n\n.extensions {\n  color: var(--color-pro);\n  background: var(--color-pro-subtle);\n  border: 1px solid var(--color-pro-border);\n}\n\n.migration {\n  color: var(--color-accent);\n  background: linear-gradient(\n    135deg,\n    var(--color-accent-subtle) 0%,\n    var(--color-secondary-subtle) 100%\n  );\n  border: 1px solid rgba(150, 201, 235, 0.2);\n}\n\n.result {\n  color: var(--color-text-primary);\n}\n\n@media (max-width: 640px) {\n  .th,\n  .td {\n    padding: 0.75rem 1rem;\n  }\n\n  .th:first-child,\n  .td:first-child {\n    min-width: 160px;\n  }\n\n  .table {\n    font-size: 0.875rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Offer/DecisionTable/DecisionTable.tsx",
    "content": "import React from 'react';\nimport styles from './DecisionTable.module.css';\n\ninterface DecisionRow {\n  situation: string;\n  choose: string;\n  result: string;\n  chooseVariant?:\n    | 'community'\n    | 'booster'\n    | 'support'\n    | 'extensions'\n    | 'migration';\n}\n\nconst DECISIONS: DecisionRow[] = [\n  {\n    situation: \"I'm just integrating video\",\n    choose: 'Community',\n    result: 'Best-effort help + docs',\n    chooseVariant: 'community',\n  },\n  {\n    situation: 'A crash/bug blocks release',\n    choose: 'Issue Booster',\n    result: 'ASAP fix (PR/patch/release)',\n    chooseVariant: 'booster',\n  },\n  {\n    situation: 'We need ongoing maintainer help',\n    choose: 'Support plan',\n    result: 'Stability + guidance over time',\n    chooseVariant: 'support',\n  },\n  {\n    situation: 'We want to switch from another player',\n    choose: 'Migration',\n    result: 'Lower costs + full control',\n    chooseVariant: 'migration',\n  },\n  {\n    situation: 'We need offline / chapters / custom UI',\n    choose: 'Extensions',\n    result: 'Advanced capabilities',\n    chooseVariant: 'extensions',\n  },\n];\n\nexport function DecisionTable() {\n  return (\n    <div className={styles.tableWrapper}>\n      <table className={styles.table}>\n        <thead>\n          <tr>\n            <th className={styles.th}>Situation</th>\n            <th className={styles.th}>Choose</th>\n            <th className={styles.th}>Result</th>\n          </tr>\n        </thead>\n        <tbody>\n          {DECISIONS.map((row) => (\n            <tr key={row.situation} className={styles.row}>\n              <td className={styles.td}>\n                <span className={styles.situation}>\"{row.situation}\"</span>\n              </td>\n              <td className={styles.td}>\n                <span\n                  className={`${styles.choose} ${styles[row.chooseVariant || 'community']}`}\n                >\n                  {row.choose}\n                </span>\n              </td>\n              <td className={styles.td}>\n                <span className={styles.result}>{row.result}</span>\n              </td>\n            </tr>\n          ))}\n        </tbody>\n      </table>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Extensions/Extensions.module.css",
    "content": ".container {\n  display: flex;\n  flex-direction: column;\n}\n\n.grid {\n  display: grid;\n  grid-template-columns: repeat(2, 1fr);\n  gap: 1.5rem;\n}\n\n.card {\n  padding: 1.5rem;\n  border-radius: 16px;\n  background: var(--glass-bg);\n  border: 1px solid var(--color-border);\n  display: flex;\n  flex-direction: column;\n  transition: all 0.3s ease;\n}\n\n.card:hover {\n  border-color: var(--color-border-hover);\n  background: var(--color-bg-elevated);\n}\n\n.proCard {\n  border-color: rgba(184, 151, 255, 0.6);\n  background: var(--glass-bg);\n}\n\n.proCard:hover {\n  border-color: rgba(184, 151, 255, 0.8);\n  box-shadow: 0 4px 20px rgba(184, 151, 255, 0.15);\n}\n\n.iconWrapper {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 48px;\n  height: 48px;\n  margin-bottom: 1rem;\n  border-radius: 12px;\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.proCard .iconWrapper {\n  background: var(--color-bg-tertiary);\n  border-color: rgba(184, 151, 255, 0.5);\n}\n\n.icon {\n  width: 24px;\n  height: 24px;\n  color: var(--color-accent);\n  stroke: var(--color-accent);\n}\n\n.proCard .icon {\n  color: #b897ff;\n  stroke: #b897ff;\n}\n\n.title {\n  font-size: 1.15rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n  margin: 0 0 0.75rem;\n}\n\n.list {\n  margin: 0 0 1.25rem;\n  padding-left: 1.25rem;\n  list-style: disc;\n  flex-grow: 1;\n}\n\n.list li {\n  font-size: 0.95rem;\n  color: var(--color-text-secondary);\n  line-height: 1.6;\n  margin-bottom: 0.25rem;\n}\n\n.ctaButton {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  padding: 0.75rem 1.25rem;\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: #b897ff !important;\n  background: transparent;\n  border: 1px solid #b897ff !important;\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.2s ease;\n  margin-top: auto;\n}\n\n.ctaButton:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 4px 12px rgba(184, 151, 255, 0.4);\n  color: #0f0f0f !important;\n  text-decoration: none;\n  border: 1px solid #c9adff !important;\n  background: #c9adff;\n}\n\n.ctaButtonSecondary {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  padding: 0.75rem 1.25rem;\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: var(--color-text-primary) !important;\n  background: transparent;\n  border: 1px solid var(--color-accent) !important;\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.2s ease;\n  margin-top: auto;\n}\n\n.ctaButtonSecondary:hover {\n  transform: translateY(-2px);\n  background: var(--color-accent-subtle);\n  border: 1px solid var(--color-accent) !important;\n  color: var(--color-text-primary) !important;\n  text-decoration: none;\n}\n\n.callout {\n  display: flex;\n  align-items: flex-start;\n  gap: 1rem;\n  margin-top: 1.5rem;\n  padding: 1.25rem;\n  border-radius: 12px;\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.calloutIcon {\n  width: 24px;\n  height: 24px;\n  stroke: var(--color-text-muted);\n  flex-shrink: 0;\n  margin-top: 2px;\n}\n\n.calloutContent {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.calloutText {\n  margin: 0;\n  font-size: 0.95rem;\n  color: var(--color-text-secondary);\n  line-height: 1.5;\n}\n\n.calloutText strong {\n  color: var(--color-text-primary);\n}\n\n.calloutLink {\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: var(--color-accent) !important;\n  text-decoration: none;\n  border-bottom: none !important;\n  transition: color 0.2s ease;\n}\n\n.calloutLink:hover {\n  color: var(--color-accent-bright) !important;\n  text-decoration: none;\n  border-bottom: none !important;\n}\n\n@media (max-width: 768px) {\n  .grid {\n    grid-template-columns: 1fr;\n  }\n\n  .callout {\n    flex-direction: column;\n    gap: 0.75rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Extensions/Extensions.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport styles from './Extensions.module.css';\n\nconst DownloadIcon =\n  require('@site/static/img/intro/download-icon.svg').default;\nconst TemplateIcon =\n  require('@site/static/img/intro/template-icon.svg').default;\nconst CustomIcon = require('@site/static/img/intro/custom-icon.svg').default;\n\nconst PRO_ADDONS_URL =\n  'https://sdk.thewidlarzgroup.com/showcases?utm_source=rnv&utm_medium=docs&utm_campaign=pro-addons&utm_id=intro';\nconst BOILERPLATES_URL =\n  'https://sdk.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=boilerplates&utm_id=intro&contact=true';\nconst CUSTOM_URL =\n  'https://sdk.thewidlarzgroup.com/ask-for-plugin?utm_source=rnv&utm_medium=docs&utm_campaign=custom-extension&utm_id=intro';\n\nexport function Extensions() {\n  return (\n    <div className={styles.container}>\n      <div className={styles.grid}>\n        <div className={`${styles.card} ${styles.proCard}`}>\n          <div className={styles.iconWrapper}>\n            <DownloadIcon className={styles.icon} />\n          </div>\n          <h3 className={styles.title}>Pro add-ons for RNV</h3>\n          <ul className={styles.list}>\n            <li>Offline Video SDK</li>\n            <li>Chapters / Custom UI</li>\n          </ul>\n          <Link to={PRO_ADDONS_URL} className={styles.ctaButton}>\n            Explore add-ons\n          </Link>\n        </div>\n\n        <div className={styles.card}>\n          <div className={styles.iconWrapper}>\n            <TemplateIcon className={styles.icon} />\n          </div>\n          <h3 className={styles.title}>Boilerplates</h3>\n          <ul className={styles.list}>\n            <li>Video Feed starter (free baseline)</li>\n            <li>Netflix-style downloads UI starter</li>\n          </ul>\n          <Link to={BOILERPLATES_URL} className={styles.ctaButtonSecondary}>\n            View boilerplates\n          </Link>\n        </div>\n      </div>\n\n      <div className={styles.callout}>\n        <CustomIcon className={styles.calloutIcon} />\n        <div className={styles.calloutContent}>\n          <p className={styles.calloutText}>\n            <strong>Need something specific?</strong> We can extend boilerplates\n            and add-ons to match your product.\n          </p>\n          <Link to={CUSTOM_URL} className={styles.calloutLink}>\n            Request an extension →\n          </Link>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Hero/IntroHero.module.css",
    "content": ".hero {\n  padding: 3rem 0 4rem;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.content {\n  max-width: 700px;\n  display: flex;\n  flex-direction: column;\n  gap: 1rem;\n}\n\n.text {\n  font-size: 1.35rem;\n  line-height: 1.6;\n  color: var(--color-text-primary);\n  margin: 0;\n}\n\n.textSecondary {\n  font-size: 1.1rem;\n  line-height: 1.6;\n  color: var(--color-text-secondary);\n  margin: 0;\n}\n\n.code {\n  background: var(--color-bg-tertiary);\n  padding: 0.2rem 0.5rem;\n  border-radius: 6px;\n  font-size: 1.1rem;\n  color: var(--color-accent);\n  border: 1px solid var(--color-border);\n}\n\n.highlight {\n  color: var(--color-secondary);\n  font-weight: 600;\n}\n\n.buttons {\n  display: flex;\n  gap: 1rem;\n  margin-top: 1.5rem;\n  flex-wrap: wrap;\n}\n\n.primaryButton {\n  display: inline-flex;\n  align-items: center;\n  padding: 0.75rem 1.5rem;\n  font-size: 0.95rem;\n  font-weight: 600;\n  color: #0f0f0f !important;\n  background: var(--color-accent-bright);\n  border: none;\n  border-bottom: none !important;\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.3s ease;\n}\n\n.primaryButton:hover {\n  transform: translateY(-2px) scale(1.01);\n  color: #0f0f0f !important;\n  text-decoration: none;\n  border-bottom: none !important;\n}\n\n.secondaryButton {\n  display: inline-flex;\n  align-items: center;\n  padding: 0.75rem 1.5rem;\n  font-size: 0.95rem;\n  font-weight: 600;\n  color: var(--color-text-primary) !important;\n  background: transparent;\n  border: 1px solid var(--color-secondary) !important;\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.3s ease;\n}\n\n.secondaryButton:hover {\n  transform: translateY(-2px) scale(1.01);\n  background: var(--color-secondary-subtle);\n  color: var(--color-text-primary) !important;\n  text-decoration: none;\n  border: 1px solid var(--color-secondary) !important;\n}\n\n@media (max-width: 640px) {\n  .hero {\n    padding: 2rem 0 3rem;\n  }\n\n  .text {\n    font-size: 1.15rem;\n  }\n\n  .textSecondary {\n    font-size: 1rem;\n  }\n\n  .buttons {\n    flex-direction: column;\n  }\n\n  .primaryButton,\n  .secondaryButton {\n    width: 100%;\n    justify-content: center;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Hero/IntroHero.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport styles from './IntroHero.module.css';\n\nconst CONTACT_URL =\n  'https://sdk.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=intro-contact&utm_id=intro&contact=true';\nconst URGENT_URL =\n  'https://sdk.thewidlarzgroup.com/issue-booster?utm_source=rnv&utm_medium=docs&utm_campaign=intro-urgent&utm_id=intro';\n\nexport function IntroHero() {\n  return (\n    <section className={styles.hero}>\n      <div className={styles.content}>\n        <p className={styles.text}>\n          <code className={styles.code}>react-native-video</code> is{' '}\n          <span className={styles.highlight}>community-first</span> and stays\n          free to use.\n        </p>\n        <p className={styles.textSecondary}>\n          Pro Player is an optional set of add-ons and maintainer services for\n          teams that need advanced features or faster support.\n        </p>\n        <div className={styles.buttons}>\n          <Link to={CONTACT_URL} className={styles.primaryButton}>\n            Contact us\n          </Link>\n          <Link to={URGENT_URL} className={styles.secondaryButton}>\n            I have an urgent issue\n          </Link>\n        </div>\n      </div>\n    </section>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Offer/HowItWorks/HowItWorks.module.css",
    "content": ".container {\n  display: flex;\n  flex-direction: column;\n}\n\n.flows {\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n}\n\n.flowLine {\n  display: flex;\n  align-items: center;\n  gap: 0.75rem;\n  padding: 1rem 1.25rem;\n  border-radius: 12px;\n  background: var(--glass-bg);\n  border: 1px solid var(--color-border);\n  flex-wrap: wrap;\n}\n\n.flowLine.highlight {\n  border-color: rgba(250, 216, 91, 0.3);\n  background: rgba(250, 216, 91, 0.05);\n}\n\n.flowLabel {\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n  min-width: 160px;\n}\n\n.community .flowLabel {\n  color: var(--color-text-secondary);\n}\n\n.booster .flowLabel {\n  color: var(--color-secondary);\n}\n\n.support .flowLabel {\n  color: var(--color-accent);\n}\n\n.arrow {\n  color: var(--color-text-muted);\n  font-size: 0.85rem;\n}\n\n.step {\n  font-size: 0.85rem;\n  color: var(--color-text-secondary);\n  padding: 0.25rem 0.6rem;\n  background: var(--color-bg-tertiary);\n  border-radius: 6px;\n}\n\n.stepHighlight {\n  background: var(--color-secondary-subtle);\n  color: var(--color-secondary);\n  font-weight: 600;\n  border: 1px solid rgba(250, 216, 91, 0.2);\n}\n\n.note {\n  margin: 1.5rem 0 0;\n  font-size: 0.9rem;\n  color: var(--color-text-muted);\n  font-style: italic;\n}\n\n@media (max-width: 768px) {\n  .flowLine {\n    padding: 0.875rem 1rem;\n  }\n\n  .flowLabel {\n    min-width: auto;\n    width: 100%;\n    margin-bottom: 0.25rem;\n  }\n}\n\n@media (max-width: 480px) {\n  .step {\n    font-size: 0.8rem;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Offer/HowItWorks/HowItWorks.tsx",
    "content": "import React from 'react';\nimport styles from './HowItWorks.module.css';\n\ninterface FlowLine {\n  label: string;\n  steps: string[];\n  variant: 'community' | 'booster' | 'support';\n  highlight?: boolean;\n}\n\nconst FLOWS: FlowLine[] = [\n  {\n    label: 'Community Support',\n    steps: [\n      'Search docs & examples',\n      'Post issue / discussion',\n      'Wait for community response',\n    ],\n    variant: 'community',\n  },\n  {\n    label: 'Issue Booster',\n    steps: [\n      'Submit bug report with repro',\n      'Maintainer prioritizes & fixes',\n      'Receive patch/PR/release',\n    ],\n    variant: 'booster',\n    highlight: true,\n  },\n  {\n    label: 'Support Plan',\n    steps: [\n      'Define your needs & scope',\n      'Get ongoing maintainer access',\n      'Ship with confidence',\n    ],\n    variant: 'support',\n  },\n];\n\nfunction FlowLine({ label, steps, variant, highlight }: FlowLine) {\n  return (\n    <div\n      className={`${styles.flowLine} ${styles[variant]} ${highlight ? styles.highlight : ''}`}\n    >\n      <span className={styles.flowLabel}>{label}</span>\n      <span className={styles.arrow}>→</span>\n      {steps.map((step, index) => (\n        <React.Fragment key={step}>\n          <span\n            className={`${styles.step} ${index === steps.length - 1 && highlight ? styles.stepHighlight : ''}`}\n          >\n            {step}\n          </span>\n          {index < steps.length - 1 && <span className={styles.arrow}>→</span>}\n        </React.Fragment>\n      ))}\n    </div>\n  );\n}\n\nexport function HowItWorks() {\n  return (\n    <div className={styles.container}>\n      <div className={styles.flows}>\n        {FLOWS.map((flow) => (\n          <FlowLine key={flow.label} {...flow} />\n        ))}\n      </div>\n      <p className={styles.note}>\n        Most users only need the community path - the other options exist for\n        teams with tighter deadlines or advanced requirements.\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Migration/Migration.module.css",
    "content": ".section {\n  padding: 3rem 0;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.container {\n  display: flex;\n  gap: 1.5rem;\n  padding: 1.5rem;\n  border-radius: 16px;\n  background: linear-gradient(\n    135deg,\n    var(--color-accent-subtle) 0%,\n    var(--color-secondary-subtle) 100%\n  );\n  border: 1px solid rgba(150, 201, 235, 0.2);\n}\n\n.iconWrapper {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 56px;\n  height: 56px;\n  flex-shrink: 0;\n  border-radius: 14px;\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.icon {\n  width: 28px;\n  height: 28px;\n  color: var(--color-accent);\n  stroke: var(--color-accent);\n}\n\n.content {\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n}\n\n.title {\n  font-size: 1.25rem;\n  font-weight: 700;\n  color: var(--color-text-primary);\n  margin: 0;\n}\n\n.description {\n  font-size: 0.95rem;\n  line-height: 1.6;\n  color: var(--color-text-secondary);\n  margin: 0;\n  max-width: 600px;\n}\n\n.highlight {\n  color: var(--color-accent);\n  font-weight: 500;\n}\n\n.highlightSecondary {\n  color: var(--color-secondary);\n  font-weight: 500;\n}\n\n.badges {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.5rem;\n  margin-top: 0.25rem;\n}\n\n.badgeOss,\n.badgeCommercial,\n.badgeVersion {\n  display: inline-block;\n  padding: 0.25rem 0.6rem;\n  font-size: 0.7rem;\n  font-weight: 600;\n  border-radius: 100px;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n}\n\n.badgeOss {\n  color: var(--color-text-secondary);\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.badgeCommercial {\n  color: var(--color-secondary);\n  background: var(--color-secondary-subtle);\n  border: 1px solid rgba(250, 216, 91, 0.2);\n}\n\n.badgeVersion {\n  color: var(--color-accent);\n  background: var(--color-accent-subtle);\n  border: 1px solid rgba(150, 201, 235, 0.2);\n}\n\n.ctaButton {\n  display: inline-flex;\n  align-items: center;\n  width: fit-content;\n  padding: 0.75rem 1.25rem;\n  margin-top: 0.5rem;\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: #0f0f0f !important;\n  background: var(--color-accent-bright);\n  border: none !important;\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.2s ease;\n}\n\n.ctaButton:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 4px 12px var(--color-accent-glow);\n  color: #0f0f0f !important;\n  text-decoration: none;\n  border: none !important;\n}\n\n@media (max-width: 640px) {\n  .container {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n\n  .ctaButton {\n    width: 100%;\n    justify-content: center;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Migration/Migration.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport styles from './Migration.module.css';\n\nconst MigrationIcon =\n  require('@site/static/img/intro/migration-icon.svg').default;\n\nconst MIGRATION_URL =\n  'https://sdk.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=migration&utm_id=intro&contact=true';\n\nexport function Migration() {\n  return (\n    <div className={styles.container}>\n      <div className={styles.iconWrapper}>\n        <MigrationIcon className={styles.icon} />\n      </div>\n      <div className={styles.content}>\n        <p className={styles.description}>\n          We help teams migrate from other video player alternatives - both{' '}\n          <span className={styles.highlight}>open-source</span> (including RNV\n          v6 to v7) and{' '}\n          <span className={styles.highlightSecondary}>commercial</span>{' '}\n          solutions - to reduce licensing costs and gain full control over your\n          video stack.\n        </p>\n        <div className={styles.badges}>\n          <span className={styles.badgeOss}>From OSS players</span>\n          <span className={styles.badgeCommercial}>\n            From commercial players\n          </span>\n          <span className={styles.badgeVersion}>v6 → v7</span>\n        </div>\n        <Link to={MIGRATION_URL} className={styles.ctaButton}>\n          Discuss migration\n        </Link>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Offer/OfferCards/OfferCards.module.css",
    "content": ".section {\n  padding: 3rem 0;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.sectionTitle {\n  font-size: 1.5rem;\n  font-weight: 700;\n  color: var(--color-text-primary);\n  margin: 0 0 2rem;\n}\n\n.grid {\n  display: grid;\n  grid-template-columns: repeat(3, 1fr);\n  gap: 1.5rem;\n}\n\n.card {\n  position: relative;\n  padding: 1.5rem;\n  border-radius: 16px;\n  background: var(--glass-bg);\n  border: 1px solid var(--color-border);\n  transition: all 0.3s ease;\n  backdrop-filter: blur(10px);\n  display: flex;\n  flex-direction: column;\n  min-height: 260px;\n}\n\n.card:hover {\n  border-color: var(--color-border-hover);\n  background: var(--color-bg-elevated);\n  transform: translateY(-2px);\n}\n\n.card.highlight {\n  border-color: rgba(150, 201, 235, 0.3);\n  background: rgba(150, 201, 235, 0.05);\n}\n\n.card.highlight:hover {\n  border-color: rgba(150, 201, 235, 0.5);\n  box-shadow: 0 4px 20px var(--color-accent-glow);\n}\n\n.iconWrapper {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 48px;\n  height: 48px;\n  margin-bottom: 1rem;\n  border-radius: 12px;\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.card:hover .iconWrapper {\n  background: rgba(150, 201, 235, 0.1);\n  border-color: rgba(150, 201, 235, 0.2);\n}\n\n.icon {\n  width: 24px;\n  height: 24px;\n  color: var(--color-accent);\n  stroke: var(--color-accent);\n}\n\n.title {\n  font-size: 1.15rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n  margin: 0 0 0.5rem;\n}\n\n.description {\n  font-size: 0.95rem;\n  color: var(--color-text-secondary);\n  line-height: 1.6;\n  margin: 0 0 1rem;\n  flex-grow: 1;\n}\n\n.badges {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.5rem;\n  margin-bottom: 1rem;\n}\n\n.badge {\n  display: inline-block;\n  padding: 0.25rem 0.6rem;\n  font-size: 0.7rem;\n  font-weight: 600;\n  border-radius: 100px;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n}\n\n.badgeAccent {\n  color: var(--color-accent);\n  background: var(--color-accent-subtle);\n  border: 1px solid rgba(150, 201, 235, 0.2);\n}\n\n.badgeSecondary {\n  color: var(--color-secondary);\n  background: var(--color-secondary-subtle);\n  border: 1px solid rgba(250, 216, 91, 0.2);\n}\n\n.badgePro {\n  color: var(--color-pro);\n  background: var(--color-pro-subtle);\n  border: 1px solid var(--color-pro-border);\n}\n\n.link {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: var(--color-accent) !important;\n  text-decoration: none;\n  border-bottom: none !important;\n  margin-top: auto;\n  transition: gap 0.2s ease;\n}\n\n.link:hover {\n  text-decoration: none;\n  gap: 0.75rem;\n  color: var(--color-accent) !important;\n  border-bottom: none !important;\n}\n\n.arrow {\n  transition: transform 0.2s ease;\n}\n\n.link:hover .arrow {\n  transform: translateX(4px);\n}\n\n@media (max-width: 968px) {\n  .grid {\n    grid-template-columns: 1fr;\n    gap: 1rem;\n  }\n\n  .card {\n    min-height: auto;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Offer/OfferCards/OfferCards.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport styles from './OfferCards.module.css';\n\nconst CommunityIcon =\n  require('@site/static/img/intro/community-icon.svg').default;\nconst SupportIcon = require('@site/static/img/intro/support-icon.svg').default;\nconst ExtensionsIcon =\n  require('@site/static/img/intro/extensions-icon.svg').default;\n\ninterface Badge {\n  label: string;\n  variant?: 'accent' | 'secondary' | 'pro';\n}\n\ninterface OfferCard {\n  title: string;\n  description: string;\n  Icon: React.ComponentType<React.ComponentProps<'svg'>>;\n  badges?: Badge[];\n  linkText: string;\n  linkHref: string;\n  variant?: 'default' | 'highlight';\n}\n\nconst CARDS: OfferCard[] = [\n  {\n    title: 'Community',\n    description:\n      'Access comprehensive documentation, browse code examples, and get help through GitHub issues and community discussions. Support is best-effort based on maintainer availability and community engagement.',\n    Icon: CommunityIcon,\n    linkText: 'Get started',\n    linkHref: 'https://github.com/react-native-video/react-native-video',\n    variant: 'default',\n  },\n  {\n    title: 'Maintainer support',\n    description:\n      'Get priority assistance directly from the core maintainers when you need faster response times than community support can provide. Available as one-time fixes or ongoing partnerships.',\n    Icon: SupportIcon,\n    badges: [\n      { label: 'Issue Booster', variant: 'secondary' },\n      { label: 'Support plan', variant: 'accent' },\n    ],\n    linkText: 'See services',\n    linkHref: '#services',\n    variant: 'highlight',\n  },\n  {\n    title: 'Extensions',\n    description:\n      'Enhance your video implementation with optional building blocks: offline playback capabilities, chapters navigation, custom UI components, and production-ready starter templates.',\n    Icon: ExtensionsIcon,\n    badges: [\n      { label: 'Offline Video', variant: 'pro' },\n      { label: 'Chapters / Custom UI', variant: 'pro' },\n      { label: 'Boilerplates', variant: 'accent' },\n    ],\n    linkText: 'See extensions',\n    linkHref: '#extensions',\n    variant: 'default',\n  },\n];\n\nfunction OfferCard({\n  title,\n  description,\n  Icon,\n  badges,\n  linkText,\n  linkHref,\n  variant = 'default',\n}: OfferCard) {\n  return (\n    <div className={`${styles.card} ${styles[variant]}`}>\n      <div className={styles.iconWrapper}>\n        <Icon className={styles.icon} />\n      </div>\n      <h3 className={styles.title}>{title}</h3>\n      <p className={styles.description}>{description}</p>\n      {badges && badges.length > 0 && (\n        <div className={styles.badges}>\n          {badges.map((badge) => (\n            <span\n              key={badge.label}\n              className={`${styles.badge} ${styles[`badge${badge.variant?.charAt(0).toUpperCase()}${badge.variant?.slice(1)}`]}`}\n            >\n              {badge.label}\n            </span>\n          ))}\n        </div>\n      )}\n      <Link to={linkHref} className={styles.link}>\n        {linkText}\n        <span className={styles.arrow}>→</span>\n      </Link>\n    </div>\n  );\n}\n\nexport function OfferCards() {\n  return (\n    <div className={styles.grid}>\n      {CARDS.map((card) => (\n        <OfferCard key={card.title} {...card} />\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Services/Services.module.css",
    "content": ".section {\n  padding: 3rem 0;\n  border-bottom: 1px solid var(--color-border);\n}\n\n.sectionTitle {\n  font-size: 1.5rem;\n  font-weight: 700;\n  color: var(--color-text-primary);\n  margin: 0 0 2rem;\n}\n\n.grid {\n  display: grid;\n  grid-template-columns: repeat(2, 1fr);\n  gap: 1.5rem;\n}\n\n.card {\n  padding: 1.5rem;\n  border-radius: 16px;\n  background: var(--glass-bg);\n  border: 1px solid var(--color-border);\n  display: flex;\n  flex-direction: column;\n  transition: all 0.3s ease;\n}\n\n.card:hover {\n  border-color: var(--color-border-hover);\n  background: var(--color-bg-elevated);\n}\n\n.boosterCard {\n  border-color: rgba(250, 216, 91, 0.3);\n  background: rgba(250, 216, 91, 0.03);\n}\n\n.boosterCard:hover {\n  border-color: rgba(250, 216, 91, 0.5);\n  box-shadow: 0 4px 20px var(--color-secondary-glow);\n}\n\n.iconWrapper {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 48px;\n  height: 48px;\n  margin-bottom: 1rem;\n  border-radius: 12px;\n  background: var(--color-bg-tertiary);\n  border: 1px solid var(--color-border);\n}\n\n.boosterCard .iconWrapper {\n  background: var(--color-secondary-subtle);\n  border-color: rgba(250, 216, 91, 0.2);\n}\n\n.icon {\n  width: 24px;\n  height: 24px;\n  color: var(--color-accent);\n  stroke: var(--color-accent);\n}\n\n.boosterCard .icon {\n  color: var(--color-secondary);\n  stroke: var(--color-secondary);\n}\n\n.title {\n  font-size: 1.25rem;\n  font-weight: 600;\n  color: var(--color-text-primary);\n  margin: 0 0 0.25rem;\n}\n\n.subtitle {\n  font-size: 0.85rem;\n  color: var(--color-text-muted);\n  margin: 0 0 0.75rem;\n}\n\n.list {\n  margin: 0.5rem 0 1rem;\n  padding-left: 1.25rem;\n  list-style: disc;\n}\n\n.list li {\n  font-size: 0.95rem;\n  color: var(--color-text-secondary);\n  line-height: 1.6;\n  margin-bottom: 0.25rem;\n}\n\n.miniNote {\n  margin-bottom: 1.25rem;\n  padding: 0.5rem 0.75rem;\n  background: var(--color-bg-tertiary);\n  border-radius: 8px;\n  border: 1px solid var(--color-border);\n}\n\n.miniNote code {\n  font-size: 0.75rem;\n  color: var(--color-text-muted);\n  background: none;\n  padding: 0;\n}\n\n.ctaButton {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  padding: 0.75rem 1.25rem;\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: #0f0f0f !important;\n  background: var(--color-secondary);\n  border: none !important;\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.2s ease;\n  margin-top: auto;\n}\n\n.ctaButton:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 4px 12px var(--color-secondary-glow);\n  color: #0f0f0f !important;\n  text-decoration: none;\n  border: none !important;\n}\n\n.ctaButtonSecondary {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  padding: 0.75rem 1.25rem;\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: var(--color-text-primary) !important;\n  background: transparent;\n  border: 1px solid var(--color-accent) !important;\n  border-radius: 8px;\n  text-decoration: none;\n  transition: all 0.2s ease;\n  margin-top: auto;\n}\n\n.ctaButtonSecondary:hover {\n  transform: translateY(-2px);\n  background: var(--color-accent-subtle);\n  border: 1px solid var(--color-accent) !important;\n  color: var(--color-text-primary) !important;\n  text-decoration: none;\n}\n\n@media (max-width: 768px) {\n  .grid {\n    grid-template-columns: 1fr;\n  }\n}\n"
  },
  {
    "path": "docs/src/components/Offer/Services/Services.tsx",
    "content": "import React from 'react';\nimport Link from '@docusaurus/Link';\nimport styles from './Services.module.css';\n\nconst RocketIcon = require('@site/static/img/intro/rocket-icon.svg').default;\nconst ClockIcon = require('@site/static/img/intro/clock-icon.svg').default;\n\nconst ISSUE_BOOSTER_URL =\n  'https://sdk.thewidlarzgroup.com/issue-booster?contact=true&utm_source=rnv&utm_medium=docs&utm_campaign=issue-booster&utm_id=intro';\nconst SUPPORT_PLAN_URL =\n  'https://sdk.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=support-plan&utm_id=intro&contact=true';\n\nexport function Services() {\n  return (\n    <div className={styles.grid}>\n      <div className={`${styles.card} ${styles.boosterCard}`}>\n        <div className={styles.iconWrapper}>\n          <RocketIcon className={styles.icon} />\n        </div>\n        <h3 className={styles.title}>Issue Booster</h3>\n        <ul className={styles.list}>\n          <li>A bug/crash blocks your release.</li>\n          <li>We prioritize it and deliver a fix ASAP (PR/patch/release).</li>\n        </ul>\n        <div className={styles.miniNote}>\n          <code>Include: RNV version • platform • minimal repro • logs</code>\n        </div>\n        <Link to={ISSUE_BOOSTER_URL} className={styles.ctaButton}>\n          Start Issue Booster\n        </Link>\n      </div>\n\n      <div className={styles.card}>\n        <div className={styles.iconWrapper}>\n          <ClockIcon className={styles.icon} />\n        </div>\n        <h3 className={styles.title}>Support plan</h3>\n        <p className={styles.subtitle}>Hours / subscription</p>\n        <ul className={styles.list}>\n          <li>Buy hours or a monthly subscription.</li>\n          <li>Use it for triage, upgrades, production issues and guidance.</li>\n        </ul>\n        <Link to={SUPPORT_PLAN_URL} className={styles.ctaButtonSecondary}>\n          Ask about Support\n        </Link>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/src/components/Offer/index.ts",
    "content": "export { IntroHero } from './Hero/IntroHero';\nexport { OfferCards } from './OfferCards/OfferCards';\nexport { HowItWorks } from './HowItWorks/HowItWorks';\nexport { Services } from './Services/Services';\nexport { Migration } from './Migration/Migration';\nexport { Extensions } from './Extensions/Extensions';\nexport { DecisionTable } from './DecisionTable/DecisionTable';\nexport { Contact } from './Contact/Contact';\n"
  },
  {
    "path": "docs/src/components/PlatformsList/PlatformsList.module.css",
    "content": ".paragraphStyle {\n  margin-top: 10;\n}\n\n.spanStyle {\n  font-family: \"Orbitron\", sans-serif;\n  font-optical-sizing: auto;\n  font-weight: 800;\n  font-style: normal;\n}\n"
  },
  {
    "path": "docs/src/components/PlatformsList/PlatformsList.tsx",
    "content": "import React from 'react';\nimport styles from './PlatformsList.module.css';\n\ntype Platform =\n  | 'Android'\n  | 'iOS'\n  | 'visionOS'\n  | 'tvOS'\n  | 'Windows UWP'\n  | 'Web'\n  | 'All';\n\ninterface Platforms {\n  types: Platform[];\n}\n\nfunction PlatformsList({ types }: Platforms) {\n  return (\n    <p className={styles.paragraphStyle}>\n      {types.length === 1 && !types.includes('All')\n        ? 'Platform:'\n        : 'Platforms:'}\n      <span className={styles.spanStyle}>{' ' + types.join(' | ')}</span>\n    </p>\n  );\n}\n\nexport default PlatformsList;\n"
  },
  {
    "path": "docs/src/css/custom.css",
    "content": "/**\n * Custom CSS for this project.\n * \n * We import base styles from @widlarzgroup/docusaurus-ui which:\n * - Overrides default Infima variables with our custom design system\n * - Provides new CSS variables for colors (--color-accent-*, --color-secondary-*, etc.)\n * - Adds custom component styles and utilities\n * \n * You can further customize any CSS variables here - they will take\n * precedence over both Infima defaults and the imported package styles.\n */\n@import '@widlarzgroup/docusaurus-ui/css/custom.css';\n\n/* Add your custom overrides below */\n\n:root {\n    --color-dark: #0f0f0f;\n}"
  },
  {
    "path": "docs/src/pages/index.module.css",
    "content": "/**\n * CSS files with the .module.css suffix will be treated as CSS modules\n * and scoped locally.\n */\n\n.heroBanner {\n  padding: 4rem 0;\n  text-align: center;\n  position: relative;\n  overflow: hidden;\n}\n\n@media screen and (max-width: 996px) {\n  .heroBanner {\n    padding: 2rem;\n  }\n}\n\n.buttons {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.logo {\n  width: 240px;\n  height: 160px;\n  margin-bottom: 20px;\n}\n"
  },
  {
    "path": "docs/src/pages/index.tsx",
    "content": "import React from 'react';\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\nimport { Enterprise } from '@site/src/components/Homepage/Enterprise/Enterprise';\nimport { Features } from '@site/src/components/Homepage/Features/Features';\nimport Layout from '@theme/Layout';\nimport { Hero } from '../components/Homepage/Hero/Hero';\n\nexport default function Home() {\n  const { siteConfig } = useDocusaurusContext();\n  return (\n    <Layout\n      title={`${siteConfig.title}`}\n      description=\"Video player for React Native.\"\n    >\n      <Hero />\n      <main>\n        <Features />\n        <Enterprise />\n      </main>\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "docs/static/.nojekyll",
    "content": ""
  },
  {
    "path": "docs/tsconfig.json",
    "content": "{\n  // This file is not used in compilation. It is here just for a nice editor experience.\n  \"extends\": [\n    \"@docusaurus/tsconfig\",\n    \"../config/tsconfig.json\"\n  ],\n  \"compilerOptions\": {\n    \"baseUrl\": \".\"\n  },\n  \"exclude\": [\".docusaurus\", \"build\"]\n}\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/component/_category_.json",
    "content": "{\n  \"label\": \"Component\",\n  \"position\": 3,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Description of React Native Video Component\"\n  },\n  \"collapsed\": false\n}\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/component/ads.md",
    "content": "---\nsidebar_position: 5\ntitle: Ads\ndescription: React Native Video Ads Integration\n---\n# Ads\n\n## IMA SDK\n\n`react-native-video` includes built-in support for Google IMA SDK on Android and iOS. To enable it, refer to the [installation section](../installation.md).\n\n### Usage\n\nTo use AVOD (Ad-Supported Video on Demand), pass the `adTagUrl` prop to the `Video` component. The `adTagUrl` should be a VAST-compliant URI.\n\n#### Example:\n\n```jsx\nadTagUrl=\"https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostoptimizedpodbumper&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=\"\n```\n\n> **Note:** Video ads cannot start when Picture-in-Picture (PiP) mode is active on iOS. More details are available in the [Google IMA SDK Docs](https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/picture_in_picture?hl=en#starting_ads). If you are using custom controls, hide the PiP button when receiving the `STARTED` event from `onReceiveAdEvent` and show it again when receiving the `ALL_ADS_COMPLETED` event.\n\n### Events\n\nTo receive events from the IMA SDK, pass the `onReceiveAdEvent` prop to the `Video` component. The full list of supported events is available [here](https://github.com/TheWidlarzGroup/react-native-video/blob/master/src/types/Ads.ts).\n\n#### Example:\n\n```jsx\n...\nonReceiveAdEvent={event => console.log(event)}\n...\n```\n\n### Localization\n\nTo change the language of the IMA SDK, pass the `adLanguage` prop to the `Video` component. The list of supported languages is available [here](https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/localization#locale-codes).\n\n- By default, **iOS** uses the system language, and **Android** defaults to `en` (English).\n\n#### Example:\n\n```jsx\n...\nadLanguage=\"fr\"\n...\n```\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/component/drm.mdx",
    "content": "---\nsidebar_position: 4\ntitle: DRM\ndescription: React Native Video DRM Integration\n---\nimport PlatformsList from \"@site/src/components/PlatformsList/PlatformsList.tsx\";\n\n# DRM\n\n## DRM Example\n\nWe provide a sample implementation in the [example app](https://github.com/TheWidlarzGroup/react-native-video/blob/master/examples/common/DRMExample.tsx) demonstrating how to use DRM with `react-native-video`. You’ll need a valid token—visit [our site](https://www.thewidlarzgroup.com/services/free-drm-token-generator-for-video?utm_source=rnv&utm_medium=docs&utm_campaign=drm&utm_id=text) to obtain a **free 24-hour token**.\n\n## DRM Offline\n\nIf you need DRM-protected content available offline, our [Offline Video SDK](https://www.thewidlarzgroup.com/offline-video-sdk/?utm_source=rnv&utm_medium=docs&utm_campaign=drm&utm_id=offline-video-sdk-link) enables downloading, storing, and managing streams with and without DRM. It also handles many edge cases you may encounter over time.\n\n### Prerequisites:\n\n- Use `react-native-video` v6 or v7. If you're still on v5 or lower, [contact us](https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=drm&utm_id=upgrade-contact#Contact) for assistance.\n\n> Supporting our software kits helps maintain this open-source project. Thank you!\n\n## Providing DRM Data (Tested with HTTP/HTTPS Assets)\n\nYou can configure DRM playback by providing a DRM object with the following properties. This feature disables the use of `TextureView` on Android.\n\n### DRM Properties\n\n### `base64Certificate`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\n**Type:** boolean\n**Default:** `false`\n\nIndicates whether the certificate URL returns data in Base64 format.\n\n### `certificateUrl`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\n**Type:** string\n**Default:** `undefined`\n\nThe URL used to fetch a valid certificate for FairPlay.\n\n### `getLicense`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\n**Type:** function\n**Default:** `undefined`\n\nInstead of setting `licenseServer`, you can manually acquire the license in JavaScript and send the result to the native module for FairPlay DRM configuration.\n\nThe following parameters are available in `getLicense`:\n\n- `contentId`: The content ID from the DRM object or `loadingRequest.request.url?.host`\n- `loadedLicenseUrl`: The URL retrieved from `loadingRequest.request.URL.absoluteString`, starting with `skd://` or `clearkey://`\n- `licenseServer`: The URL passed in the DRM object\n- `spcString`: The SPC used for DRM validation\n\nYou should return a Base64-encoded CKC response, either directly or as a `Promise`.\n\n#### Example:\n\n```js\ngetLicense: (spcString, contentId, licenseUrl, loadedLicenseUrl) => {\n  const base64spc = Base64.encode(spcString);\n  const formData = new FormData();\n  formData.append(\"spc\", base64spc);\n  return fetch(`https://license.pallycon.com/ri/licenseManager.do`, {\n    method: \"POST\",\n    headers: {\n      \"pallycon-customdata-v2\": \"your-custom-header\",\n      \"Content-Type\": \"application/x-www-form-urlencoded\",\n    },\n    body: formData,\n  })\n    .then((response) => response.text())\n    .then((response) => response)\n    .catch((error) => console.error(\"Error\", error));\n};\n```\n\n### `contentId`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\n**Type:** string\n**Default:** `undefined`\n\nSets the content ID for the stream. If not specified, the system uses the host value from `loadingRequest.request.URL.host`.\n\n### `headers`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\n**Type:** Object\n**Default:** `undefined`\n\nCustom headers for the license server request.\n\n#### Example:\n\n```js\ndrm: {\n  type: DRMType.WIDEVINE,\n  licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense',\n  headers: {\n    'X-AxDRM-Message': 'your-drm-header',\n  },\n}\n```\n\n### `licenseServer`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\n**Type:** string\n**Default:** `undefined`\n\nThe license server URL that authorizes protected content playback.\n\n### `multiDrm`\n\n<PlatformsList types={[\"Android\"]} />\n\n**Type:** boolean\n**Default:** `false`\n\nIndicates whether the DRM system should support key rotation. See [Android Developer Docs](https://developer.android.google.cn/media/media3/exoplayer/drm?hl=en#key-rotation) for more details.\n\n### `type`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\n**Type:** DRMType\n**Default:** `undefined`\n\nDefines the DRM type:\n\n- **Android:** `DRMType.WIDEVINE`, `DRMType.PLAYREADY`, `DRMType.CLEARKEY`\n- **iOS:** `DRMType.FAIRPLAY`\n\n### `localSourceEncryptionKeyScheme`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\n**Type:** string\n\nSets the URL scheme for stream encryption keys used in local assets.\n\n#### Example:\n\n```js\nlocalSourceEncryptionKeyScheme = \"my-offline-key\";\n```\n\n## Common Usage Scenarios\n\n### Sending Cookies to the License Server\n\nYou can send cookies using the `headers` prop.\n\n#### Example:\n\n```js\ndrm: {\n  type: DRMType.WIDEVINE,\n  licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense',\n  headers: {\n    'Cookie': 'PHPSESSID=your-session-id; csrftoken=mytoken; _gat=1; foo=bar'\n  },\n}\n```\n\n### Custom License Acquisition (iOS Only)\n\n#### Example:\n\n```js\ndrm: {\n  type: DRMType.FAIRPLAY,\n  getLicense: (spcString) => {\n    const base64spc = Base64.encode(spcString);\n    return fetch('YOUR_LICENSE_SERVER_URL', {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        Accept: 'application/json',\n      },\n      body: JSON.stringify({\n        getFairplayLicense: {\n          foo: 'bar',\n          spcMessage: base64spc,\n        }\n      })\n    })\n      .then(response => response.json())\n      .then((response) => {\n        if (response?.getFairplayLicenseResponse?.ckcResponse) {\n          return response.getFairplayLicenseResponse.ckcResponse;\n        }\n        throw new Error('No valid response');\n      })\n      .catch((error) => console.error('CKC error', error));\n  }\n}\n```\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/component/events.mdx",
    "content": "---\nsidebar_position: 2\ntitle: Events\ndescription: React Native Video Component Events\n---\n\nimport PlatformsList from \"@site/src/components/PlatformsList/PlatformsList.tsx\";\n\n# Events\n\nThis page lists all available callbacks for handling player notifications.\n\n## Details\n\n### `onAudioBecomingNoisy`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nTriggered when audio output changes (e.g., switching from headphones to speakers). It's recommended to pause the media when this event occurs.\n\n**Payload:** _none_\n\n---\n\n### `onAudioFocusChanged`\n\n<PlatformsList types={[\"Android\"]} />\n\nCalled when audio focus is gained or lost.\n\n**Payload:**\n| Property | Type | Description |\n|---------------|--------|----------------------------------------------|\n| hasAudioFocus | boolean | `true` if media has audio focus, `false` otherwise |\n\n**Example:**\n\n```javascript\n{\n  hasAudioFocus: true;\n}\n```\n\n---\n\n### `onAudioTracks`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nTriggered when available audio tracks change.\n\n**Payload:** _Array of objects with track details_\n\n| Property | Type    | Description                                                                      |\n| -------- | ------- | -------------------------------------------------------------------------------- |\n| index    | number  | Internal track ID                                                                |\n| title    | string  | Descriptive track name                                                           |\n| language | string  | [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code |\n| bitrate  | number  | Track bitrate                                                                    |\n| type     | string  | Track MIME type                                                                  |\n| selected | boolean | `true` if track is currently playing                                             |\n\n**Example:**\n\n```javascript\n{\n  audioTracks: [\n    {\n      language: \"es\",\n      title: \"Spanish\",\n      type: \"audio/mpeg\",\n      index: 0,\n      selected: true,\n    },\n    { language: \"en\", title: \"English\", type: \"audio/mpeg\", index: 1 },\n  ];\n}\n```\n\n---\n\n### `onBandwidthUpdate`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nCalled when available bandwidth changes.\n\n**Payload:**\n| Property | Type | Description |\n|----------|--------|-----------------------------------------------|\n| bitrate | number | Estimated bitrate in bits/sec |\n| width | number | Video width (Android only) |\n| height | number | Video height (Android only) |\n| trackId | string | Video track ID (Android only) |\n\n**Example (iOS):**\n\n```javascript\n{\n  bitrate: 1000000;\n}\n```\n\n**Example (Android):**\n\n```javascript\n{\n  bitrate: 1000000,\n  width: 1920,\n  height: 1080,\n  trackId: 'some-track-id'\n}\n```\n\n> **Note:** On Android, set the [`reportBandwidth`](#reportbandwidth) prop to enable this event.\n\n---\n\n### `onBuffer`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\nTriggered when buffering starts or stops.\n\n**Payload:**\n| Property | Type | Description |\n|------------|--------|---------------------------------|\n| isBuffering | boolean | `true` if buffering is active |\n\n**Example:**\n\n```javascript\n{\n  isBuffering: true;\n}\n```\n\n---\n\n### `onControlsVisibilityChange`\n\n<PlatformsList types={[\"Android\"]} />\n\nTriggered when the video player controls become visible or hidden.\n\n**Payload:**\n| Property | Type | Description |\n|----------|--------|-------------------------------------|\n| isVisible | boolean | `true` if controls are visible |\n\n**Example:**\n\n```javascript\n{\n  isVisible: true;\n}\n```\n\n---\n\n### `onEnd`\n\n<PlatformsList types={[\"All\"]} />\n\nTriggered when the media reaches the end.\n\n**Payload:** _none_\n\n---\n\n### `onError`\n\n<PlatformsList types={[\"All\"]} />\n\nCalled when a playback error occurs.\n\n**Payload:**\n| Property | Type | Description |\n|---------|--------|---------------------------|\n| error | object | Error details |\n\n---\n\n### `onExternalPlaybackChange`\n\n<PlatformsList types={[\"iOS\"]} />\n\nCalled when external playback mode changes (e.g., Apple TV connection/disconnection).\n\n**Payload:**\n| Property | Type | Description |\n|-------------------------|--------|--------------------------------------------|\n| isExternalPlaybackActive | boolean | `true` if external playback is active |\n\n**Example:**\n\n```javascript\n{\n  isExternalPlaybackActive: true;\n}\n```\n\n---\n\n### `onFullscreenPlayerWillPresent`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nCalled before entering fullscreen mode.\n\n**Payload:** _none_\n\n---\n\n### `onFullscreenPlayerDidPresent`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nCalled when fullscreen mode is active.\n\n**Payload:** _none_\n\n---\n\n### `onFullscreenPlayerWillDismiss`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nCalled before exiting fullscreen mode.\n\n**Payload:** _none_\n\n---\n\n### `onFullscreenPlayerDidDismiss`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nCalled when fullscreen mode is exited.\n\n**Payload:** _none_\n\n---\n\n### `onLoad`\n\n<PlatformsList types={[\"All\"]} />\n\nTriggered when the media is loaded and ready to play.\n\n### Payload:\n\n| Property    | Type   | Description                                                                                                                                                                                                                                                                                                                                                                            |\n| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| currentTime | number | Time in seconds where the media will start                                                                                                                                                                                                                                                                                                                                             |\n| duration    | number | Length of the media in seconds                                                                                                                                                                                                                                                                                                                                                         |\n| naturalSize | object | Properties:<br/> &ensp; width - Width in pixels that the video was encoded at<br/> &ensp; height - Height in pixels that the video was encoded at<br/> &ensp; orientation - \"portrait\", \"landscape\" or \"square\"                                                                                                                                                                        |\n| audioTracks | array  | An array of audio track info objects with the following properties:<br/> &ensp; index - Index number<br/> &ensp; title - Description of the track<br/> &ensp; language - 2 letter [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) or 3 letter [ISO639-2](https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes) language code<br/> &ensp; type - Mime type of track |\n| textTracks  | array  | An array of text track info objects with the following properties:<br/> &ensp; index - Index number<br/> &ensp; title - Description of the track<br/> &ensp; language - 2 letter [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) or 3 letter [ISO 639-2](https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes) language code<br/> &ensp; type - Mime type of track |\n| videoTracks | array  | An array of video track info objects with the following properties:<br/> &ensp; trackId - ID for the track<br/> &ensp; bitrate - Bit rate in bits per second<br/> &ensp; codecs - Comma separated list of codecs<br/> &ensp; height - Height of the video<br/> &ensp; width - Width of the video                                                                                       |\n| trackId     | string | Provide key information about the video track, typically including: `Resolution`, `Bitrate`.                                                                                                                                                                                                                                                                                           |\n\n**Example:**\n\n```js\n{\n  canPlaySlowForward: true,\n  canPlayReverse: false,\n  canPlaySlowReverse: false,\n  canPlayFastForward: false,\n  canStepForward: false,\n  canStepBackward: false,\n  currentTime: 0,\n  duration: 5910.208984375,\n  naturalSize: {\n     height: 1080\n     orientation: 'landscape'\n     width: '1920'\n  },\n  audioTracks: [\n    { language: 'es', title: 'Spanish', type: 'audio/mpeg', index: 0 },\n    { language: 'en', title: 'English', type: 'audio/mpeg', index: 1 }\n  ],\n  textTracks: [\n    { title: '#1 French', language: 'fr', index: 0, type: 'text/vtt' },\n    { title: '#2 English CC', language: 'en', index: 1, type: 'text/vtt' },\n    { title: '#3 English Director Commentary', language: 'en', index: 2, type: 'text/vtt' }\n  ],\n  videoTracks: [\n    { index: 0, bitrate: 3987904, codecs: \"avc1.640028\", height: 720, trackId: \"f1-v1-x3\", width: 1280 },\n    { index: 1, bitrate: 7981888, codecs: \"avc1.640028\", height: 1080, trackId: \"f2-v1-x3\", width: 1920 },\n    { index: 2, bitrate: 1994979, codecs: \"avc1.4d401f\", height: 480, trackId: \"f3-v1-x3\", width: 848 }\n  ],\n  trackId: \"720p 2400kbps\",\n}\n```\n\n> **Note:** `audioTracks`, `textTracks`, and `videoTracks` are not available on the web.\n\n---\n\n### `onLoadStart`\n\n<PlatformsList types={[\"All\"]} />\n\nTriggered when media starts loading.\n\n**Payload:**\n| Property | Type | Description |\n|----------|--------|-------------------------------------|\n| isNetwork | boolean | `true` if media is loaded from a network |\n| type | string | Media type (not available on Windows) |\n| uri | string | Media source URI (not available on Windows) |\n\n**Example:**\n\n```javascript\n{\n  isNetwork: true,\n  type: '',\n  uri: 'https://example.com/video.mp4'\n}\n```\n\n---\n\n### `onPlaybackStateChanged`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\", \"web\"]} />\n\nTriggered when playback state changes.\n\n**Payload:**\n| Property | Type | Description |\n|----------|--------|-------------------------------------|\n| isPlaying | boolean | `true` if media is playing |\n| isSeeking | boolean | `true` if seeking is in progress |\n\n**Example:**\n\n```javascript\n{\n  isPlaying: true,\n  isSeeking: false\n}\n```\n\n---\n\n### `onPictureInPictureStatusChanged`\n\n<PlatformsList types={[\"iOS\", \"Android\", \"web\"]} />\n\nTriggered when Picture-in-Picture (PiP) mode is activated or deactivated.\n\n**Payload:**\n| Property | Type | Description |\n|----------|--------|----------------------------------|\n| isActive | boolean | `true` if PiP mode is active |\n\n**Example:**\n\n```javascript\n{\n  isActive: true;\n}\n```\n\n---\n\n### `onPlaybackRateChange`\n\n<PlatformsList types={[\"All\"]} />\n\nTriggered when playback speed changes.\n\n**Payload:**\n| Property | Type | Description |\n|-------------|--------|---------------------------------|\n| playbackRate | number | `0` (paused), `1` (normal speed), other values indicate speed changes |\n\n**Example:**\n\n```javascript\n{\n  playbackRate: 0; // indicates paused\n}\n```\n\n---\n\n### `onProgress`\n\n<PlatformsList types={[\"All\"]} />\n\nTriggered every `progressUpdateInterval` milliseconds, providing information about the current playback position.\n\n**Payload:**\n| Property | Type | Description |\n|----------------|--------|-------------------------------------------------------------------------|\n| currentTime | number | Current playback position (seconds) |\n| playableDuration | number | Duration that can be played using only the buffer (seconds) |\n| seekableDuration | number | Duration that can be seeked to (usually the total length of the media) |\n\n**Example:**\n\n```javascript\n{\n  currentTime: 5.2,\n  playableDuration: 34.6,\n  seekableDuration: 888\n}\n```\n\n---\n\n### `onReadyForDisplay`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"Web\"]} />\n\nTriggered when the first video frame is ready to be displayed. This is when the poster is removed.\n\n**Payload:** _none_\n\n- iOS: [`readyForDisplay`](https://developer.apple.com/documentation/avkit/avplayerviewcontroller/1615830-readyfordisplay?language=objc)\n- Android: [`STATE_READY`](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html#STATE_READY)\n\n---\n\n### `onReceiveAdEvent`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nTriggered when an AdEvent is received from the IMA SDK.\n\nEnum `AdEvent` possible values for [Android](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.AdEvent) and [iOS](https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/reference/Enums/IMAAdEventType):\n\n<details>\n  <summary>AdEvent</summary>\n\n| Event                      | Platform     | Description                                                                                                                                                                                                 |\n| -------------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `AD_BREAK_ENDED`           | iOS          | Fired the first time each ad break ends. Applications must reenable seeking when this occurs (only used for dynamic ad insertion).                                                                          |\n| `AD_BREAK_READY`           | Android, iOS | Fires when an ad rule or a VMAP ad break would have played if autoPlayAdBreaks is false.                                                                                                                    |\n| `AD_BREAK_STARTED`         | iOS          | Fired first time each ad break begins playback. If an ad break is watched subsequent times this will not be fired. Applications must disable seeking when this occurs (only used for dynamic ad insertion). |\n| `AD_BUFFERING`             | Android      | Fires when the ad has stalled playback to buffer.                                                                                                                                                           |\n| `AD_CAN_PLAY`              | Android      | Fires when the ad is ready to play without buffering, either at the beginning of the ad or after buffering completes.                                                                                       |\n| `AD_METADATA`              | Android      | Fires when an ads list is loaded.                                                                                                                                                                           |\n| `AD_PERIOD_ENDED`          | iOS          | Fired every time the stream switches from advertising or slate to content. This will be fired even when an ad is played a second time or when seeking into an ad (only used for dynamic ad insertion).      |\n| `AD_PERIOD_STARTED`        | iOS          | Fired every time the stream switches from content to advertising or slate. This will be fired even when an ad is played a second time or when seeking into an ad (only used for dynamic ad insertion).      |\n| `AD_PROGRESS`              | Android      | Fires when the ad's current time value changes. The event `data` will be populated with an AdProgressData object.                                                                                           |\n| `ALL_ADS_COMPLETED`        | Android, iOS | Fires when the ads manager is done playing all the valid ads in the ads response, or when the response doesn't return any valid ads.                                                                        |\n| `CLICK`                    | Android, iOS | Fires when the ad is clicked.                                                                                                                                                                               |\n| `COMPLETED`                | Android, iOS | Fires when the ad completes playing.                                                                                                                                                                        |\n| `CONTENT_PAUSE_REQUESTED`  | Android      | Fires when content should be paused. This usually happens right before an ad is about to cover the content.                                                                                                 |\n| `CONTENT_RESUME_REQUESTED` | Android      | Fires when content should be resumed. This usually happens when an ad finishes or collapses.                                                                                                                |\n| `CUEPOINTS_CHANGED`        | iOS          | Cuepoints changed for VOD stream (only used for dynamic ad insertion).                                                                                                                                      |\n| `DURATION_CHANGE`          | Android      | Fires when the ad's duration changes.                                                                                                                                                                       |\n| `ERROR`                    | Android, iOS | Fires when an error occurred while loading the ad and prevent it from playing.                                                                                                                              |\n| `FIRST_QUARTILE`           | Android, iOS | Fires when the ad playhead crosses first quartile.                                                                                                                                                          |\n| `IMPRESSION`               | Android      | Fires when the impression URL has been pinged.                                                                                                                                                              |\n| `INTERACTION`              | Android      | Fires when an ad triggers the interaction callback. Ad interactions contain an interaction ID string in the ad data.                                                                                        |\n| `LINEAR_CHANGED`           | Android      | Fires when the displayed ad changes from linear to nonlinear, or the reverse.                                                                                                                               |\n| `LOADED`                   | Android, iOS | Fires when ad data is available.                                                                                                                                                                            |\n| `LOG`                      | Android, iOS | Fires when a non-fatal error is encountered. The user need not take any action since the SDK will continue with the same or next ad playback depending on the error situation.                              |\n| `MIDPOINT`                 | Android, iOS | Fires when the ad playhead crosses midpoint.                                                                                                                                                                |\n| `PAUSED`                   | Android, iOS | Fires when the ad is paused.                                                                                                                                                                                |\n| `RESUMED`                  | Android, iOS | Fires when the ad is resumed.                                                                                                                                                                               |\n| `SKIPPABLE_STATE_CHANGED`  | Android      | Fires when the displayed ads skippable state is changed.                                                                                                                                                    |\n| `SKIPPED`                  | Android, iOS | Fires when the ad is skipped by the user.                                                                                                                                                                   |\n| `STARTED`                  | Android, iOS | Fires when the ad starts playing.                                                                                                                                                                           |\n| `STREAM_LOADED`            | iOS          | Stream request has loaded (only used for dynamic ad insertion).                                                                                                                                             |\n| `TAPPED`                   | iOS          | Fires when the ad is tapped.                                                                                                                                                                                |\n| `THIRD_QUARTILE`           | Android, iOS | Fires when the ad playhead crosses third quartile.                                                                                                                                                          |\n| `UNKNOWN`                  | iOS          | An unknown event has fired                                                                                                                                                                                  |\n| `USER_CLOSE`               | Android      | Fires when the ad is closed by the user.                                                                                                                                                                    |\n| `VIDEO_CLICKED`            | Android      | Fires when the non-clickthrough portion of a video ad is clicked.                                                                                                                                           |\n| `VIDEO_ICON_CLICKED`       | Android      | Fires when a user clicks a video icon.                                                                                                                                                                      |\n| `VOLUME_CHANGED`           | Android      | Fires when the ad volume has changed.                                                                                                                                                                       |\n| `VOLUME_MUTED`             | Android      | Fires when the ad volume has been muted.                                                                                                                                                                    |\n\n</details>\n\n**Payload:**\n| Property | Type | Description |\n|----------|-----------------------------------------|---------------------|\n| event | AdEvent | The ad event received |\n| data | Record&lt;string, string&gt; \\| undefined | Additional ad event data |\n\n**Example:**\n\n```json\n{\n  \"data\": {\n    \"key\": \"value\"\n  },\n  \"event\": \"LOG\"\n}\n```\n\n---\n\n### `onRestoreUserInterfaceForPictureInPictureStop`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nCorresponds to Apple's [`restoreUserInterfaceForPictureInPictureStopWithCompletionHandler`](https://developer.apple.com/documentation/avkit/avpictureinpicturecontrollerdelegate/1614703-pictureinpicturecontroller?language=objc).\nCall `restoreUserInterfaceForPictureInPictureStopCompleted` inside this function when the UI is restored.\n\n**Payload:** _none_\n\n---\n\n### `onSeek`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"Windows UWP\", \"web\"]} />\n\nTriggered when a seek operation completes.\n\n**Payload:**\n| Property | Type | Description |\n|------------|--------|---------------------------------|\n| currentTime | number | Current time after seeking |\n| seekTime | number | Requested seek time |\n\n**Example:**\n\n```javascript\n{\n  currentTime: 100.5,\n  seekTime: 100\n}\n```\n\n> **Note:** On iOS, this callback is not reported when native controls are enabled.\n\n---\n\n### `onTimedMetadata`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nTriggered when timed metadata is available.\n\n**Payload:**\n| Property | Type | Description |\n|----------|------|--------------------------|\n| metadata | array | Array of metadata objects |\n\n**Example:**\n\n```javascript\n{\n  metadata: [\n    { value: \"Streaming Encoder\", identifier: \"TRSN\" },\n    { value: \"Internet Stream\", identifier: \"TRSO\" },\n    { value: \"Any Time You Like\", identifier: \"TIT2\" },\n  ];\n}\n```\n\n---\n\n### `onTextTrackDataChanged`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nTriggered when new subtitle data becomes available.\n\n**Payload:**\n| Property | Type | Description |\n|----------------|--------|--------------------------------------------------|\n| subtitleTracks | string | The subtitle text content in a compatible format |\n\n**Example:**\n\n```javascript\n{\n  subtitleTracks: \"This blade has a dark past.\";\n}\n```\n\n---\n\n### `onTextTracks`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nTriggered when available text (subtitle) tracks change.\n\n**Payload:**\n| Property | Type | Description |\n|----------|--------|--------------------------------------------------------------------------------------------------------------|\n| index | number | Internal track ID |\n| title | string | Track name |\n| language | string | 2 letter [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code |\n| type | string | Track MIME type (_VTT_, _SRT_, _TTML_) |\n| selected | boolean | `true` if the track is currently playing |\n\n**Example:**\n\n```javascript\n{\n  textTracks: [\n    {\n      index: 0,\n      title: \"English Subtitles\",\n      type: \"vtt\",\n      selected: true,\n    },\n  ];\n}\n```\n\n---\n\n### `onVideoTracks`\n\n<PlatformsList types={[\"Android\"]} />\n\nTriggered when video tracks change.\n\n**Payload:**\n| Property | Type | Description |\n|----------|---------|-----------------------------------|\n| index | number | Track index |\n| trackId | string | Internal track ID |\n| codecs | string | Codec type |\n| width | number | Video width |\n| height | number | Video height |\n| bitrate | number | Track bitrate (bps) |\n| selected | boolean | `true` if the track is playing |\n| rotation | number | Rotation angle (0, 90, 180, 270) |\n\n**Example:**\n\n```javascript\n{\n  videoTracks: [\n    {\n      index: 0,\n      trackId: \"1\",\n      codecs: \"video/mp4\",\n      width: 1920,\n      height: 1080,\n      bitrate: 5000000,\n      selected: true,\n      rotation: 0,\n    },\n  ];\n}\n```\n\n---\n\n### `onVolumeChange`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\", \"web\"]} />\n\nTriggered when the player volume changes.\n\n> **Note:** This event applies to the player's volume, not the device's system volume.\n\n**Payload:**\n| Property | Type | Description |\n|----------|--------|---------------------------------|\n| volume | number | Volume level (0 to 1) |\n| muted | boolean | Whether the player is muted |\n\n**Example:**\n\n```javascript\n{\n  volume: 0.5;\n}\n```\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/component/methods.mdx",
    "content": "---\nsidebar_position: 3\ntitle: Methods\ndescription: React Native Video Component Methods\n---\n\nimport PlatformsList from \"@site/src/components/PlatformsList/PlatformsList.tsx\";\n\n# Methods\n\nThis page shows the list of available methods.\n\n## Details\n\n### `dismissFullscreenPlayer`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\ndismissFullscreenPlayer(): Promise<void>\n```\n\nExits fullscreen mode.\n\n> **Deprecated:** Use `setFullScreen(false)` instead.\n\n---\n\n### `pause`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\npause(): Promise<void>\n```\n\nPauses the video.\n\n---\n\n### `presentFullscreenPlayer`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\npresentFullscreenPlayer(): Promise<void>\n```\n\nEnters fullscreen mode.\n\n- On **iOS**, this opens a fullscreen view controller with controls.\n- On **Android**, this makes the player fullscreen but requires styling to match screen dimensions.\n\n> **Deprecated:** Use `setFullScreen(true)` instead.\n\n---\n\n### `resume`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\nresume(): Promise<void>\n```\n\nResumes video playback.\n\n---\n\n### `restoreUserInterfaceForPictureInPictureStopCompleted`\n\n<PlatformsList types={[\"iOS\"]} />\n\n```tsx\nrestoreUserInterfaceForPictureInPictureStopCompleted(restored);\n```\n\nMust be called after `onRestoreUserInterfaceForPictureInPictureStop`.\nCorresponds to Apple's [`restoreUserInterfaceForPictureInPictureStop`](https://developer.apple.com/documentation/avkit/avpictureinpicturecontrollerdelegate/1614703-pictureinpicturecontroller?language=objc).\n\n---\n\n### `save`\n\n<PlatformsList types={[\"iOS\"]} />\n\n```tsx\nsave(): Promise<{ uri: string }>\n```\n\nSaves the video to the user's **Photos app** with the current filter.\n\n#### Notes:\n\n- Supports **MP4** export only.\n- Exports to the **cache directory** with a generated UUID filename.\n- Requires **internet connection** if the video is not already buffered.\n- Video remains in the **Photos app** until manually deleted.\n- Works with **cached videos**.\n\n#### Future improvements:\n\n- Support for **multiple quality options**.\n- Support for **more formats**.\n- Support for **custom directory and filename**.\n\n---\n\n### `enterPictureInPicture`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\nenterPictureInPicture();\n```\n\nActivates Picture-in-Picture (PiP) mode.\n\n#### Android setup:\n\nFor **Expo**, enable PiP in `app.json`:\n\n```json\n\"plugins\": [\n  [\n    \"react-native-video\",\n    {\n      \"enableAndroidPictureInPicture\": true\n    }\n  ]\n]\n```\n\nFor **Bare React Native**, update `AndroidManifest.xml`:\n\n```xml\n<activity\n  android:name=\".MainActivity\"\n  android:supportsPictureInPicture=\"true\">\n</activity>\n```\n\n> **Note:**\n>\n> - On **Android**, entering PiP moves the app to the **background**.\n> - On **iOS**, **video ads cannot start** in PiP mode ([Google IMA SDK](https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/picture_in_picture?hl=en#starting_ads)).\n\n---\n\n### `exitPictureInPicture`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\nexitPictureInPicture();\n```\n\nExits Picture-in-Picture (PiP) mode.\n\n---\n\n### `seek`\n\n<PlatformsList types={[\"All\"]} />\n\n```tsx\nseek(seconds: number)\n```\n\nSeeks to the specified position (**in seconds**).\n\n#### Notes:\n\n- **Must be called after** `onLoad`.\n- Triggers the [`onSeek`](./events#onseek) event.\n\n#### **iOS Exact Seek:**\n\n```tsx\nseek(seconds, tolerance: number)\n```\n\n- Default **tolerance**: ±100ms.\n- Set `tolerance = 0` for **precise seeking**.\n\n---\n\n### `setVolume`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\nsetVolume(value: number): Promise<void>\n```\n\nChanges the **volume** level. Same behavior as the [`volume`](./props#volume) prop.\n\n---\n\n### `getCurrentPosition`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\ngetCurrentPosition(): Promise<number>\n```\n\nReturns the **current playback position** in seconds.\n\n> **Throws an error** if the player is not initialized.\n\n---\n\n### `setSource`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\n```tsx\nsetSource(source: ReactVideoSource): Promise<void>\n```\n\nUpdates the media source **dynamically**.\n\n> **Note:** This **overrides** the `source` prop.\n\n---\n\n### `setFullScreen`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\n```tsx\nsetFullScreen(fullscreen: boolean): Promise<void>\n```\n\nToggles fullscreen mode.\n\n- `true` → Enters fullscreen.\n- `false` → Exits fullscreen.\n\n---\n\n### `nativeHtmlVideoRef`\n\n<PlatformsList types={[\"web\"]} />\n\nA **reference to the native HTML `<video>` element**.\nUseful for integrating **third-party** video libraries like **hls.js, shaka, video.js, etc.**.\n\n---\n\n### **Example Usage**\n\n```tsx\nconst videoRef = useRef<VideoRef>(null);\n\nconst handleVideoControls = async () => {\n  if (!videoRef.current) return;\n\n  // Fullscreen controls\n  videoRef.current.presentFullscreenPlayer();\n  videoRef.current.dismissFullscreenPlayer();\n\n  // Playback controls\n  videoRef.current.pause();\n  videoRef.current.resume();\n\n  // Save video\n  const response = await videoRef.current.save();\n  console.log(\"Saved video path:\", response.uri);\n\n  // Seek to 200s (or with tolerance on iOS)\n  videoRef.current.seek(200);\n  videoRef.current.seek(200, 10);\n};\n\nreturn (\n  <Video\n    ref={videoRef}\n    source={{ uri: \"https://www.w3schools.com/html/mov_bbb.mp4\" }}\n  />\n);\n```\n\n## Static Methods\n\n### `getWidevineLevel`\n\n<PlatformsList types={[\"Android\"]} />\n\n```tsx\ngetWidevineLevel(): Promise<number>\n```\n\nReturns the **Widevine DRM level**:\n\n- **0** → Unknown / Not supported.\n- **1, 2, 3** → Supported Widevine levels.\n\n---\n\n### `isCodecSupported`\n\n<PlatformsList types={[\"Android\", \"web\"]} />\n\n```tsx\nisCodecSupported(mimetype: string, width: number, height: number): Promise<'hardware' | 'software' | 'unsupported'>\n```\n\nChecks if the given **video codec** is supported.\n\n| Result        | Meaning                          |\n| ------------- | -------------------------------- |\n| `hardware`    | Hardware decoding supported      |\n| `software`    | Only software decoding available |\n| `unsupported` | Codec **not supported**          |\n\n---\n\n### `isHEVCSupported`\n\n<PlatformsList types={[\"Android\"]} />\n\n```tsx\nisHEVCSupported(): Promise<boolean>\n```\n\nChecks if **HEVC (H.265)** is supported at **1920×1080 resolution**.\n\n> Uses `isCodecSupported` internally.\n\n---\n\n### Static Methods Example Usage\n\n```tsx\nimport { VideoDecoderProperties } from \"react-native-video\";\n\nVideoDecoderProperties.getWidevineLevel().then((level) => {\n  console.log(\"Widevine Level:\", level);\n});\n\nVideoDecoderProperties.isCodecSupported(\"video/hevc\", 1920, 1080).then(\n  (support) => {\n    console.log(\"HEVC Support:\", support);\n  }\n);\n\nVideoDecoderProperties.isHEVCSupported().then((support) => {\n  console.log(\"HEVC 1080p Support:\", support);\n});\n```\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/component/props.mdx",
    "content": "---\nsidebar_position: 1\ntitle: Props\ndescription: React Native Video Component Props\n---\n\nimport PlatformsList from \"@site/src/components/PlatformsList/PlatformsList.tsx\";\n\n# Configurable Props\n\nThis page shows the list of available properties to configure the player.\n\n## Details\n\n### `adTagUrl`\n\n:::warning\nDeprecated, use `source.ad.adTagUrl` instead.\n:::\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nSets the VAST URI to play AVOD ads.\n\n**Example:**\n\n```javascript\nadTagUrl =\n  \"https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostoptimizedpodbumper&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=\";\n```\n\n> **Note:** You need to enable IMA SDK in the Gradle or Podfile – see [Enable Client-Side Ads Insertion](../installation.md).\n\n---\n\n### `allowsExternalPlayback`\n\n<PlatformsList types={[\"iOS\"]} />\n\nIndicates whether the player allows switching to external playback mode such as AirPlay or HDMI.\n\n- **true (default)** – Allows switching to external playback mode.\n- **false** – Prevents switching to external playback mode.\n\n---\n\n### `audioOutput`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nChanges the audio output.\n\n- **speaker (default)** – Plays through the speaker.\n- **earpiece** – Plays through the earpiece.\n\n---\n\n### `automaticallyWaitsToMinimizeStalling`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nIndicates whether the player should automatically delay playback to minimize stalling. Available for clients linked against iOS 10.0 and later.\n\n- **false** – Immediately starts playback.\n- **true (default)** – Delays playback to minimize stalling.\n\n---\n\n### `bufferConfig`\n\n:::warning\nDeprecated, use `source.bufferConfig` instead.\n:::\n\n<PlatformsList types={[\"Android\"]} />\n\nAdjusts the buffer settings. This prop takes an object with one or more of the following properties:\n\n| Property                          | Type   | Description                                                                       |\n| --------------------------------- | ------ | --------------------------------------------------------------------------------- |\n| minBufferMs                       | number | Minimum duration (ms) the player will attempt to keep buffered.                   |\n| maxBufferMs                       | number | Maximum duration (ms) the player will attempt to buffer.                          |\n| bufferForPlaybackMs               | number | Duration (ms) that must be buffered before playback starts or resumes.            |\n| bufferForPlaybackAfterRebufferMs  | number | Duration (ms) that must be buffered after a rebuffer before playback resumes.     |\n| backBufferDurationMs              | number | Duration (ms) of buffer to keep before the current position (allows rewinding).   |\n| maxHeapAllocationPercent          | number | Percentage of available heap the video can use to buffer (0 to 1).                |\n| minBackBufferMemoryReservePercent | number | Percentage of available app memory before the back buffer is disabled (0 to 1).   |\n| minBufferMemoryReservePercent     | number | Percentage of available app memory reserved for preventing buffer usage (0 to 1). |\n| cacheSizeMB                       | number | Cache size in MB. Set to `0` to disable caching (Android only).                   |\n| live                              | object | Object containing configuration for live playback. See below.                     |\n\n#### Live Buffer Configurations\n\n| Property         | Type   | Description                                                        |\n| ---------------- | ------ | ------------------------------------------------------------------ |\n| maxPlaybackSpeed | number | Maximum playback speed for catching up to target live offset.      |\n| minPlaybackSpeed | number | Minimum playback speed for falling back to target live offset.     |\n| maxOffsetMs      | number | Maximum allowed live offset. The player won’t exceed this limit.   |\n| minOffsetMs      | number | Minimum allowed live offset. The player won’t go below this limit. |\n| targetOffsetMs   | number | The target live offset the player will aim to maintain.            |\n\nFor more details on Android live streaming, see [ExoPlayer Live Streaming](https://developer.android.com/media/media3/exoplayer/live-streaming?hl=en).\n\n#### Example with Default Values\n\n```javascript\nbufferConfig={{\n  minBufferMs: 15000,\n  maxBufferMs: 50000,\n  bufferForPlaybackMs: 2500,\n  bufferForPlaybackAfterRebufferMs: 5000,\n  backBufferDurationMs: 120000,\n  cacheSizeMB: 0,\n  live: {\n      targetOffsetMs: 500,\n  },\n}}\n```\n\n> **Note:** The Android cache is global and shared among all components. The first `cacheSizeMB` value set persists throughout the app lifecycle.\n\n---\n\n### `bufferingStrategy`\n\n<PlatformsList types={[\"Android\"]} />\n\nConfigures the buffering and data loading strategy.\n\n- **Default (default)** – Uses ExoPlayer's default loading strategy.\n- **DisableBuffering** – Prevents buffering beyond the immediate need. **Use with caution, as this may stop playback.**\n- **DependingOnMemory** – Uses ExoPlayer’s default strategy but stops buffering and triggers garbage collection when memory is low.\n\n---\n\n### `chapters`\n\n<PlatformsList types={[\"tvOS\"]} />\n\nProvides a custom chapter source for tvOS. This prop takes an array of objects with the following properties:\n\n| Property  | Type    | Description                                                                    |\n| --------- | ------- | ------------------------------------------------------------------------------ |\n| title     | string  | The title of the chapter.                                                      |\n| startTime | number  | The start time of the chapter (seconds).                                       |\n| endTime   | number  | The end time of the chapter (seconds).                                         |\n| uri       | string? | Optional image override URL (HTTP or Base64). Some media auto-generate images. |\n\n---\n\n### `currentPlaybackTime`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nWhen playing an HLS live stream with an `EXT-X-PROGRAM-DATE-TIME` tag, this property contains the epoch value in milliseconds.\n\n---\n\n### `controls`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\", \"web\"]} />\n\nDetermines whether player controls are shown.\n\n- **false (default)** – Hides player controls.\n- **true** – Displays player controls.\n\nControls are always visible in fullscreen mode, even if `controls={false}`. To add custom controls, use packages like:\n\n- [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls)\n- [react-native-media-console](https://github.com/criszz77/react-native-media-console)\n\nSee [Useful Side Projects](../projects.md).\n\n---\n\n### `controlsStyles`\n\n<PlatformsList types={[\"Android\"]} />\n\nAdjust the control styles. This prop is needed only if `controls={true}` and is an object. See the supported properties below.\n\n| Property                            | Type    | Description                                                         |\n| ----------------------------------- | ------- | ------------------------------------------------------------------- |\n| hidePosition                        | boolean | Hides the position indicator. Default is `false`.                   |\n| hidePlayPause                       | boolean | Hides the play/pause button. Default is `false`.                    |\n| hideForward                         | boolean | Hides the forward button. Default is `false`.                       |\n| hideRewind                          | boolean | Hides the rewind button. Default is `false`.                        |\n| hideNext                            | boolean | Hides the next button. Default is `false`.                          |\n| hidePrevious                        | boolean | Hides the previous button. Default is `false`.                      |\n| hideFullscreen                      | boolean | Hides the fullscreen button. Default is `false`.                    |\n| hideSeekBar                         | boolean | Hides the seek bar, useful for live broadcasts. Default is `false`. |\n| hideDuration                        | boolean | Hides the duration display. Default is `false`.                     |\n| hideNavigationBarOnFullScreenMode   | boolean | Hides the navigation bar in fullscreen mode. Default is `true`.     |\n| hideNotificationBarOnFullScreenMode | boolean | Hides the notification bar in fullscreen mode. Default is `true`.   |\n| hideSettingButton                   | boolean | Hides the settings button. Default is `true`.                       |\n| seekIncrementMS                     | number  | Defines the seek increment in milliseconds. Default is `10000`.     |\n| liveLabel                           | string  | Sets a label for live video.                                        |\n\n**Example with default values:**\n\n```javascript\ncontrolsStyles={{\n  hidePosition: false,\n  hidePlayPause: false,\n  hideForward: false,\n  hideRewind: false,\n  hideNext: false,\n  hidePrevious: false,\n  hideFullscreen: false,\n  hideSeekBar: false,\n  hideDuration: false,\n  hideNavigationBarOnFullScreenMode: true,\n  hideNotificationBarOnFullScreenMode: true,\n  hideSettingButton: true,\n  seekIncrementMS: 10000,\n  liveLabel: \"LIVE\"\n}}\n```\n\n---\n\n### `contentStartTime`\n\n:::warning\nDeprecated, use `source.contentStartTime` instead.\n:::\n\n<PlatformsList types={[\"Android\"]} />\n\nDefines the start time in milliseconds for SSAI content. This ensures that video resolutions are loaded at the correct time. **Note:** This feature only works with DASH streams.\n\n---\n\n### `debug`\n\n<PlatformsList types={[\"Android\"]} />\n\nEnables detailed logging.\n\n:::warning\nDo not use this in production builds.\n:::\n\n| Property | Type    | Description                               |\n| -------- | ------- | ----------------------------------------- |\n| `enable` | boolean | Enables verbose logs. Default is `false`. |\n| `thread` | boolean | Displays logs with thread information.    |\n\n**Example:**\n\n```javascript\ndebug={{\n  enable: true,\n  thread: true,\n}}\n```\n\n---\n\n### `disableFocus`\n\n<PlatformsList types={[\"Android\"]} />\n\nDetermines whether video audio should override background music/audio on Android.\n\n- **false (default)** – Overrides background audio/music.\n- **true** – Allows background audio/music from other apps to continue playing.\n\n> **Note:** If `true`, multiple videos can play simultaneously. If `false`, starting another video will pause the first one.\n\n---\n\n### `disableDisconnectError`\n\n<PlatformsList types={[\"Android\"]} />\n\nDetermines if the player should throw an error when the network connection is lost.\n\n- **false (default)** – Throws an error when the connection is lost.\n- **true** – The player will keep trying to buffer when the connection is lost.\n\n---\n\n### `disableAudioSessionManagement`\n\n<PlatformsList types={[\"iOS\"]} />\n\nDisable audio session management in library (for all views).\n\n- **true** - Disable audio session management in the library.\n- **false (default)** - Enable audio session management in the library.\n\n:::danger\nThis prop disables audio session management in the library. You only should use this prop if you are managing the audio session yourself.\nYou can encounter issues with other features, like background audio, if you don't properly manage the audio session.\n:::\n\n---\n\n### `drm`\n\n:::warning\nDeprecated, use `source.drm` instead.\n:::\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nTo set up DRM, follow [this guide](./drm.mdx).\n\n---\n\n### `enterPictureInPictureOnLeave`\n\n<PlatformsList types={[\"iOS\", \"Android\"]} />\n\nDetermines whether to enter Picture-in-Picture (PiP) mode when the user leaves the app.\n\n- **false (default)** – Does not enable PiP mode.\n- **true** – Plays media in PiP mode when the user switches apps.\n\n**Using this on Android:**\n\n- **With Expo:** Add `enableAndroidPictureInPicture` to `app.json`:\n\n```json\n  \"plugins\": [\n    [\n      \"react-native-video\",\n      {\n        \"enableAndroidPictureInPicture\": true\n      }\n    ]\n  ]\n```\n\n- **With Bare React Native:** Add PiP support in `AndroidManifest.xml`:\n\n```xml\n<activity\n  android:name=\".MainActivity\"\n  android:supportsPictureInPicture=\"true\">\n```\n\n> **Note:** Video ads cannot start when using PiP on iOS. More details are available in the [Google IMA SDK Docs](https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side/picture_in_picture?hl=en#starting_ads).\n\n---\n\n### `filter`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nApplies a video filter.\n\n| FilterType         | Description           |\n| ------------------ | --------------------- |\n| `NONE (default)`   | No filter             |\n| `INVERT`           | CIColorInvert         |\n| `MONOCHROME`       | CIColorMonochrome     |\n| `POSTERIZE`        | CIColorPosterize      |\n| `FALSE`            | CIFalseColor          |\n| `MAXIMUMCOMPONENT` | CIMaximumComponent    |\n| `MINIMUMCOMPONENT` | CIMinimumComponent    |\n| `CHROME`           | CIPhotoEffectChrome   |\n| `FADE`             | CIPhotoEffectFade     |\n| `INSTANT`          | CIPhotoEffectInstant  |\n| `MONO`             | CIPhotoEffectMono     |\n| `NOIR`             | CIPhotoEffectNoir     |\n| `PROCESS`          | CIPhotoEffectProcess  |\n| `TONAL`            | CIPhotoEffectTonal    |\n| `TRANSFER`         | CIPhotoEffectTransfer |\n| `SEPIA`            | CISepiaTone           |\n\n> **Notes:**\n>\n> 1. Using a filter may increase CPU usage.\n> 2. Saving a filtered video and reloading it is a workaround for performance issues.\n> 3. Filters are not supported on HLS playlists.\n> 4. `filterEnabled` must be set to `true` for filters to work.\n\n---\n\n### `filterEnabled`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nEnables video filter.\n\n- **false (default)** – Don't enable filter.\n- **true** – Enable filter.\n\n---\n\n### `focusable`\n\n<PlatformsList types={[\"Android\"]} />\n\nDetermines whether this video view should be focusable with a non-touch input device, such as a hardware keyboard.\n\n- **false** – Makes view unfocusable.\n- **true (default)** – Makes view focusable.\n\n---\n\n### `fullscreen`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\", \"web\"]} />\n\nControls whether the player enters fullscreen on play.\n\n- **false (default)** – Don’t display the video in fullscreen.\n- **true** – Display the video in fullscreen.\n\nSee [presentFullscreenPlayer](#presentfullscreenplayer) for details.\n\n---\n\n### `fullscreenAutorotate`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nIf a preferred [fullscreenOrientation](#fullscreenorientation) is set, this causes the video to rotate to that orientation but permits rotation of the screen to match the user's holding position. Defaults to `true`.\n\n---\n\n### `fullscreenOrientation`\n\n<PlatformsList types={[\"iOS\", \"visionOS\", \"web\"]} />\n\n- **all (default)** – Allows rotation in all orientations.\n- **landscape** – Locks fullscreen to landscape mode.\n- **portrait** – Locks fullscreen to portrait mode.\n\n---\n\n### `headers`\n\n<PlatformsList types={[\"iOS\", \"Android\"]} />\n\nPasses headers to the HTTP client, which can be used for authorization. Headers must be part of the source object.\n\n**Example:**\n\n```javascript\nsource={{\n  uri: \"https://www.example.com/video.mp4\",\n  headers: {\n    Authorization: 'Bearer some-token-value',\n    'X-Custom-Header': 'some value'\n  }\n}}\n```\n\n---\n\n### `hideShutterView`\n\n<PlatformsList types={[\"Android\"]} />\n\nControls whether the ExoPlayer shutter view (black screen while loading) is enabled.\n\n- **false (default)** – Show shutter view.\n- **true** – Hide shutter view.\n\n---\n\n### `ignoreSilentSwitch`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nControls the iOS silent switch behavior.\n\n- **\"inherit\" (default)** – Uses the default AVPlayer behavior.\n- **\"ignore\"** – Plays audio even if the silent switch is set.\n- **\"obey\"** – Doesn’t play audio if the silent switch is set.\n\n---\n\n### `maxBitRate`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nSets the desired limit, in bits per second, of network bandwidth consumption when multiple video streams are available for a playlist.\n\n**Default:** `0` (no limit on maxBitRate).\n\n**Example:**\n\n```javascript\nmaxBitRate={2000000} // 2 megabits\n```\n\n---\n\n### `mixWithOthers`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nControls how audio mixes with other apps.\n\n- **\"inherit\" (default)** – Uses the default AVPlayer behavior.\n- **\"mix\"** – Allows this video’s audio to mix with other apps.\n- **\"duck\"** – Lowers the volume of other apps while playing this video.\n\n---\n\n### `muted`\n\n<PlatformsList types={[\"All\"]} />\n\nControls whether the audio is muted.\n\n- **false (default)** – Don’t mute audio.\n- **true** – Mute audio.\n\n---\n\n### `paused`\n\n<PlatformsList types={[\"All\"]} />\n\nControls whether the media is paused.\n\n- **false (default)** – Don’t pause the media.\n- **true** – Pause the media.\n\n---\n\n### `playInBackground`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nDetermines whether the media should continue playing while the app is in the background.\n\n- **false (default)** – Don’t continue playing the media.\n- **true** – Continue playing the media.\n\nTo use this feature on iOS, you must:\n\n- [Enable Background Audio](https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionBasics/AudioSessionBasics.html#//apple_ref/doc/uid/TP40007875-CH3-SW3) in your Xcode project.\n- Set the `ignoreSilentSwitch` prop to \"ignore\".\n\n---\n\n### `playWhenInactive`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nDetermines whether the media should continue playing when notifications or the Control Center are in front of the video.\n\n- **false (default)** – Don’t continue playing the media.\n- **true** – Continue playing the media.\n\n---\n\n### `poster`\n\n<PlatformsList types={[\"All\"]} />\n\n:::warning\nValue: string with a URL for the poster is deprecated, use `poster` as an object instead.\n:::\n\nAn image to display while the video is loading.\n\n**Example:**\n\n```javascript\n<Video>\n  poster=\n  {{\n    source: { uri: \"https://baconmockup.com/300/200/\" },\n    resizeMode: \"cover\",\n  }}\n</Video>\n```\n\n---\n\n### `posterResizeMode`\n\n:::warning\nDeprecated, use `poster` with `resizeMode` key instead.\n:::\n\n<PlatformsList types={[\"All\"]} />\n\nDetermines how to resize the poster image when the frame doesn’t match the raw video dimensions.\n\n- **\"contain\" (default)** – Scales the image uniformly to fit within the view.\n- **\"center\"** – Centers the image in the view without scaling beyond its original size.\n- **\"cover\"** – Scales the image uniformly, ensuring it fills the view while maintaining aspect ratio.\n- **\"none\"** – No resizing applied.\n- **\"repeat\"** – Repeats the image to fill the view (iOS only).\n- **\"stretch\"** – Stretches width and height independently, potentially distorting the aspect ratio.\n\n---\n\n### `preferredForwardBufferDuration`\n\n<PlatformsList types={[\"iOS\", \"visionOS\"]} />\n\nDefines how long the player should buffer media ahead of the playhead to prevent playback interruptions.\n\n**Default:** `0`.\n\n[Apple Documentation](https://developer.apple.com/documentation/avfoundation/avplayeritem/1643630-preferredforwardbufferduration)\n\n---\n\n### `preventsDisplaySleepDuringVideoPlayback`\n\n<PlatformsList types={[\"iOS\", \"Android\"]} />\n\nDetermines whether the device screen should remain active while playing a video.\n\n**Default:** `true` (prevents the display from sleeping).\n\n---\n\n### `progressUpdateInterval`\n\n<PlatformsList types={[\"All\"]} />\n\nSets the delay (in milliseconds) between `onProgress` events.\n\n**Default:** `250.0` ms.\n\n---\n\n### `rate`\n\n<PlatformsList types={[\"All\"]} />\n\nControls the speed at which the media should play.\n\n- **0.0** – Pauses the video (iOS only).\n- **1.0 (default)** – Plays at normal speed.\n- **Other values** – Adjusts playback speed (faster/slower).\n\n---\n\n### `renderLoader`\n\n<PlatformsList types={[\"All\"]} />\n\nAllows you to provide a custom component to display while the video is loading.\n\nIf `renderLoader` is provided, `poster` and `posterResizeMode` will be ignored.\n\n`renderLoader` can be either a component or a function returning a component.\n\n#### Function Signature\n\n```typescript\ninterface ReactVideoRenderLoaderProps {\n  source?: ReactVideoSource;\n  style?: StyleProp<ImageStyle>;\n  resizeMode?: EnumValues<VideoResizeMode>;\n}\n```\n\n#### Example\n\n```javascript\n<Video>\n  renderLoader=\n  {() => (\n    <View>\n      <Text>Custom Loader</Text>\n    </View>\n  )}\n</Video>\n```\n\n---\n\n### `repeat`\n\n<PlatformsList types={[\"All\"]} />\n\nDetermines whether to repeat the video when playback reaches the end.\n\n- **false (default)** – Don’t repeat the video.\n- **true** – Repeat the video.\n\n---\n\n### `reportBandwidth`\n\n<PlatformsList types={[\"Android\"]} />\n\nDetermines whether to generate `onBandwidthUpdate` events. This is necessary due to the high frequency of these events on ExoPlayer.\n\n- **false (default)** – Don’t generate `onBandwidthUpdate` events.\n- **true** – Generate `onBandwidthUpdate` events.\n\n---\n\n### `resizeMode`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"Windows UWP\"]} />\n\nDetermines how to resize the video when the frame doesn’t match the raw video dimensions.\n\n- **\"none\" (default)** – No resizing applied.\n- **\"contain\"** – Scales the video uniformly to fit within the view.\n- **\"cover\"** – Scales the video uniformly to fill the view while maintaining aspect ratio.\n- **\"stretch\"** – Stretches width and height independently, which may alter the aspect ratio.\n\n---\n\n### `selectedAudioTrack`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nConfigures which audio track, if any, is played.\n\n```javascript\nselectedAudioTrack={{\n  type: \"title\",\n  value: \"Dubbing\"\n}}\n```\n\n| Type               | Value  | Description                                                                                 |\n| ------------------ | ------ | ------------------------------------------------------------------------------------------- |\n| \"system\" (default) | N/A    | Play the audio track that matches the system language. If none match, play the first track. |\n| \"disabled\"         | N/A    | Turn off audio.                                                                             |\n| \"title\"            | string | Play the audio track with the specified title, e.g., \"French\".                              |\n| \"language\"         | string | Play the audio track with the specified language, e.g., \"fr\".                               |\n| \"index\"            | number | Play the audio track with the specified index, e.g., 0.                                     |\n\nIf no matching track is found, the first available track will be played. If multiple tracks match, the first match will be used.\n\n---\n\n### `selectedTextTrack`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nConfigures which text track (captions or subtitles), if any, is shown.\n\n```javascript\nselectedTextTrack={{\n  type: \"title\",\n  value: \"English Subtitles\"\n}}\n```\n\n| Type               | Value  | Description                                                             |\n| ------------------ | ------ | ----------------------------------------------------------------------- |\n| \"system\" (default) | N/A    | Display captions only if the system preference for captions is enabled. |\n| \"disabled\"         | N/A    | Don’t display a text track.                                             |\n| \"title\"            | string | Display the text track with the specified title, e.g., \"French 1\".      |\n| \"language\"         | string | Display the text track with the specified language, e.g., \"fr\".         |\n| \"index\"            | number | Display the text track with the specified index, e.g., 0.               |\n\nIf no matching track is found, no subtitles will be displayed. If multiple tracks match, the first match will be used.\n\n---\n\n### `selectedVideoTrack`\n\n<PlatformsList types={[\"Android\"]} />\n\nConfigures which video track should be played. By default, the player uses Adaptive Bitrate Streaming (ABR) to automatically select the best stream based on available bandwidth.\n\n```javascript\nselectedVideoTrack={{\n  type: \"resolution\",\n  value: 480\n}}\n```\n\n| Type             | Value  | Description                                                                    |\n| ---------------- | ------ | ------------------------------------------------------------------------------ |\n| \"auto\" (default) | N/A    | Let the player determine the best track using ABR.                             |\n| \"disabled\"       | N/A    | Turn off video.                                                                |\n| \"resolution\"     | number | Play the video track with the specified height, e.g., 480 for the 480p stream. |\n| \"index\"          | number | Play the video track with the specified index, e.g., 0.                        |\n\nIf no matching track is found, ABR will be used.\n\n---\n\n### `shutterColor`\n\n<PlatformsList types={[\"Android\"]} />\n\nApplies color to the shutter view. If black flashes appear before the video starts, set:\n\n```javascript\nshutterColor = \"transparent\";\n```\n\n**Default:** `black`.\n\n---\n\n### `source`\n\nSets the media source. You can pass an asset loaded via `require` or an object with a `uri`.\n\nSetting the source will trigger the player to attempt to load the provided media with all other given props. Ensure all props are provided before or at the same time as setting the source.\n\nRendering the player component with a `null` source initializes the player and starts playing once a source value is provided.\n\nProviding a `null` source value after loading a previous source stops playback and clears out the previous content.\n\nThe documentation for this prop is incomplete and will be updated as each option is investigated and tested.\n\n#### Asset Loaded via `require`\n\n:::danger\nOn iOS, file names must not contain spaces. For example, `my video.mp4` will not work—use `my-video.mp4` instead.\n:::\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\", \"Windows UWP\"]} />\n\nExample:\n\nPass the asset directly (deprecated):\n\n```javascript\nconst sintel = require(\"./sintel.mp4\");\nsource = { sintel };\n```\n\nOr by using a URI (starting from `6.0.0-beta.6`):\n\n```javascript\nconst sintel = require('./sintel.mp4');\nsource={{ uri: sintel }}\n```\n\n#### URI String\n\nA number of URI schemes are supported by passing an object with a `uri` attribute.\n\nAll URI strings must be URL encoded.\nFor example, `'www.myurl.com/blabla?q=test uri'` is invalid, whereas `'www.myurl.com/blabla?q=test%20uri'` is valid.\n\n##### Web Address (`http://`, `https://`)\n\n<PlatformsList types={[\"All\"]} />\n\nExample:\n\n```javascript\nsource={{ uri: 'https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_10mb.mp4' }}\n```\n\n##### File Path (`file://`)\n\n<PlatformsList types={[\"Android\"]} />\n\nExample:\n\n```javascript\nsource={{ uri: 'file:///sdcard/Movies/sintel.mp4' }}\n```\n\nNote: Your app will need permission to read external storage if accessing a file outside your app.\n\n##### File from Asset Folder (`asset://`)\n\n<PlatformsList types={[\"Android\"]} />\n\nAllows playing a video file from the app's asset folder.\n\nExample:\n\n```javascript\nsource={{ uri: 'asset:///sintel.mp4' }}\n```\n\n##### iPod Library (`ipod-library://`)\n\n<PlatformsList types={[\"iOS\"]} />\n\nPath to a sound file in your iTunes library, typically shared from iTunes to your app.\n\nExample:\n\n```javascript\nsource={{ uri: 'ipod-library:///path/to/music.mp3' }}\n```\n\nNote: Using this feature requires adding an entry for `NSAppleMusicUsageDescription` to your `Info.plist` file, as described [here](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html).\n\n##### Explicit MIME Type for Streams\n\nProvide a `type` property (`mpd`/`m3u8`/`ism`) inside the source object.\nThis is needed when the URL extension does not match the expected MIME type.\n\nExample (URL extension is `.ism` for Smooth Streaming, but the file is actually MPEG-DASH (`mpd`)):\n\n```javascript\nsource={{ uri: 'http://host-serving-a-type-different-than-the-extension.ism/manifest(format=mpd-time-csf)',\ntype: 'mpd' }}\n```\n\n##### Other Protocols\n\nThe following protocols are supported on some platforms but not fully documented yet:\n`content://, ms-appx://, ms-appdata://, assets-library://`\n\n#### Using DRM Content\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\", \"tvOS\"]} />\n\nTo set up DRM, follow [this guide](./drm.mdx).\n\nExample:\n\n```javascript\n{\n  description: 'WV: Secure SD & HD (cbcs, MP4, H264)',\n  uri: 'https://storage.googleapis.com/wvmedia/cbcs/h264/tears/tears_aes_cbcs.mpd',\n  drm: {\n    type: DRMType.WIDEVINE,\n    licenseServer:\n      'https://proxy.uat.widevine.com/proxy?provider=widevine_test',\n  },\n},\n```\n\n#### Start Playback at a Specific Point in Time\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\nProvide an optional `startPosition` for video playback. The value is in milliseconds. If the `cropStart` prop is applied, it will be applied from that point forward.\n(If it is negative, undefined, or `null`, it is ignored.)\n\n#### Playing Only a Portion of the Video (Start & End Time)\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nProvide an optional `cropStart` and/or `cropEnd` for the video. Values are in milliseconds. This is useful when you want to play only a portion of a large video.\n\n**Example:**\n\n```javascript\nsource={{ uri: 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8', cropStart: 36012, cropEnd: 48500 }}\n\nsource={{ uri: 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8', cropStart: 36012 }}\n\nsource={{ uri: 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8', cropEnd: 48500 }}\n```\n\n#### Overriding the Metadata of a Source\n\n<PlatformsList types={[\"Android\", \"iOS\", \"tvOS\"]} />\n\nProvide optional `title`, `subtitle`, `artist`, `imageUri`, and/or `description` properties for the video.\nThis is useful when using notification controls on Android or iOS or adapting the tvOS playback experience.\n\n**Example:**\n\n```javascript\nsource={{\n    uri: 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8',\n    metadata: {\n      title: 'Custom Title',\n      subtitle: 'Custom Subtitle',\n      artist: 'Custom Artist',\n      description: 'Custom Description',\n      imageUri: 'https://pbs.twimg.com/profile_images/1498641868397191170/6qW2XkuI_400x400.png'\n    }\n  }}\n```\n\n#### `ad`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\nSets the ad configuration.\n\n**Example:**\n\n```javascript\nad: {\n  adTagUrl =\n    \"https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostoptimizedpodbumper&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=\";\n  adLanguage = \"fr\";\n}\n```\n\nSee: [ads](./ads.md) for more information.\n\nNote: You need to enable IMA SDK in the Gradle or Pod file - [enable client-side ads insertion](../installation.md).\n\n#### `contentStartTime`\n\n<PlatformsList types={[\"Android\"]} />\n\nThe start time in ms for SSAI content. This determines at what time to load the video info like resolutions. Use this only when you have an SSAI stream where the ad resolution is not the same as the content resolution.\n\nNote: This feature only works on DASH streams.\n\n#### `textTracksAllowChunklessPreparation`\n\n<PlatformsList types={[\"Android\"]} />\n\nAllow Chunkless Preparation for HLS media sources.\nSee: [disabling-chunkless](https://developer.android.com/media/media3/exoplayer/hls?#disabling-chunkless) in the Android documentation.\n\nDefault value: `true`.\n\n```javascript\nsource={{\n    uri: 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8',\n    textTracksAllowChunklessPreparation: false,\n  }}\n```\n\n#### `bufferConfig`\n\n<PlatformsList types={[\"Android\"]} />\n\nAdjust the buffer settings. This prop takes an object with one or more of the properties listed below.\n\n| Property                          | Type   | Description                                                                                                                                     |\n| --------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| minBufferMs                       | number | Minimum duration of media that the player will attempt to buffer at all times, in milliseconds.                                                 |\n| maxBufferMs                       | number | Maximum duration of media that the player will attempt to buffer, in milliseconds.                                                              |\n| bufferForPlaybackMs               | number | Duration of media that must be buffered for playback to start or resume following a user action, in milliseconds.                               |\n| bufferForPlaybackAfterRebufferMs  | number | Duration of media that must be buffered for playback to resume after a rebuffer, in milliseconds.                                               |\n| backBufferDurationMs              | number | Duration of buffer to keep before the current position, allowing rewinding without rebuffering.                                                 |\n| maxHeapAllocationPercent          | number | Percentage of available heap that the video can use to buffer, between 0 and 1.                                                                 |\n| minBackBufferMemoryReservePercent | number | Percentage of available app memory at which during startup the back buffer will be disabled, between 0 and 1.                                   |\n| minBufferMemoryReservePercent     | number | Percentage of available app memory to keep in reserve, preventing buffer usage, between 0 and 1.                                                |\n| initialBitrate                    | number | Initial bitrate in bits per second (Android only). Defaults to 1_000_000. Used only at start, then ABR (Adaptive Bitrate Streaming) takes over. |\n| cacheSizeMB                       | number | Cache size in MB, preventing new src requests and saving bandwidth while repeating videos, or 0 to disable. Android only.                       |\n| live                              | object | Object containing another config set for live playback configuration.                                                                           |\n\n#### `minLoadRetryCount`\n\n<PlatformsList types={[\"Android\"]} />\n\nSets the minimum number of times to retry loading data before failing and reporting an error to the application. Useful for recovering from transient internet failures.\n\nDefault: `3`. Retries `3` times.\n\n**Example:**\n\n```javascript\nsource={{\n  uri: 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8',\n  minLoadRetryCount: 5 // Retry 5 times.\n}}\n```\n\n#### `textTracks`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nLoad one or more \"sidecar\" text tracks. This takes an array of objects representing each track. Each object should have the format:\n\n:::warning  \nThis feature does not work with HLS playlists (e.g., m3u8) on iOS.\n:::\n\n| Property | Description                                                                                                 |\n| -------- | ----------------------------------------------------------------------------------------------------------- |\n| title    | Descriptive name for the track.                                                                             |\n| language | 2-letter [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) representing the language. |\n| type     | Mime type of the track. Supports `TextTrackType.SUBRIP`, `TextTrackType.TTML`, `TextTrackType.VTT`.         |\n| uri      | URL for the text track. Only tracks hosted on a web server are supported.                                   |\n\nNote: Due to iOS limitations, sidecar text tracks are not compatible with AirPlay. If `textTracks` are specified, AirPlay support will be automatically disabled.\n\n**Example:**\n\n```javascript\nimport { TextTrackType } from \"react-native-video\";\n\ntextTracks = [\n  {\n    title: \"English CC\",\n    language: \"en\",\n    type: TextTrackType.VTT, // \"text/vtt\"\n    uri: \"https://bitdash-a.akamaihd.net/content/sintel/subtitles/subtitles_en.vtt\",\n  },\n  {\n    title: \"Spanish Subtitles\",\n    language: \"es\",\n    type: TextTrackType.SUBRIP, // \"application/x-subrip\"\n    uri: \"https://durian.blender.org/wp-content/content/subtitles/sintel_es.srt\",\n  },\n];\n```\n\n---\n\n### `subtitleStyle`\n\n<PlatformsList types={[\"Android\", \"iOS\"]} />\n\n| Property             | Platform     | Description                                                                                                                                                                                        | Platforms    |\n| -------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| fontSize             | Android      | Adjust the font size of the subtitles. Default: font size of the device                                                                                                                            | Android      |\n| paddingTop           | Android      | Adjust the top padding of the subtitles. Default: 0                                                                                                                                                | Android      |\n| paddingBottom        | Android      | Adjust the bottom padding of the subtitles. Default: 0                                                                                                                                             | Android      |\n| paddingLeft          | Android      | Adjust the left padding of the subtitles. Default: 0                                                                                                                                               | Android      |\n| paddingRight         | Android      | Adjust the right padding of the subtitles. Default: 0                                                                                                                                              | Android      |\n| opacity              | Android, iOS | Adjust the visibility of subtitles with 0 hiding and 1 fully showing them. Android supports float values between 0 and 1 for varying opacity levels, whereas iOS supports only 0 or 1. Default: 1. | Android, iOS |\n| subtitlesFollowVideo | Android      | Boolean to adjust position of subtitles. Default: true                                                                                                                                             |\n\n**Example:**\n\n```javascript\nsubtitleStyle={{ paddingBottom: 50, fontSize: 20, opacity: 0 }}\n```\n\nNote for `subtitlesFollowVideo`\n\n`subtitlesFollowVideo` helps to determine how the subtitles are positioned.\nTo understand this prop, you need to understand how view management works.\nThe main View style passed to react-native-video is the space reserved to display the video component.\nIt may not match exactly the real video size.\nFor example, you can pass a 4:3 video view and render a 16:9 video inside.\nSo there is a second view, the video view.\n\nSubtitles are managed in a third view.\n\n- When `subtitlesFollowVideo` is set to true, the subtitle view will adapt to the video view.\n  If the video is displayed out of screen, the subtitles may also be displayed out of screen.\n- When `subtitlesFollowVideo` is set to false, the subtitle view will adapt to the main view.\n  If the video is displayed out of screen, the subtitles may still remain visible within the main view.\n\nThis prop can be changed at runtime.\n\n---\n\n### `textTracks`\n\n:::warning\nDeprecated, use `source.textTracks` instead. Changing text tracks will restart playback.\n:::\n\n<PlatformsList types={[\"Android\", \"iOS\", \"visionOS\"]} />\n\nLoad one or more \"sidecar\" text tracks. This takes an array of objects representing each track. Each object should have the format:\n\n:::warning\nThis feature does not work with HLS playlists (e.g., m3u8) on iOS.\n:::\n\n| Property | Description                                                                                                                                                                         |\n| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| title    | Descriptive name for the track                                                                                                                                                      |\n| language | 2-letter [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) representing the language                                                                          |\n| type     | Mime type of the track (TextTrackType.SUBRIP - SubRip (.srt), TextTrackType.TTML - TTML (.ttml), TextTrackType.VTT - WebVTT (.vtt)). iOS only supports VTT, Android supports all 3. |\n| uri      | URL for the text track. Currently, only tracks hosted on a web server are supported.                                                                                                |\n\nOn iOS, sidecar text tracks are only supported for individual files, not HLS playlists. For HLS, you should include the text tracks as part of the playlist.\n\nNote: Due to iOS limitations, sidecar text tracks are not compatible with AirPlay. If `textTracks` are specified, AirPlay support will be automatically disabled.\n\n**Example:**\n\n```javascript\nimport { TextTrackType }, Video from 'react-native-video';\n\ntextTracks=[\n  {\n    title: \"English CC\",\n    language: \"en\",\n    type: TextTrackType.VTT, // \"text/vtt\"\n    uri: \"https://bitdash-a.akamaihd.net/content/sintel/subtitles/subtitles_en.vtt\"\n  },\n  {\n    title: \"Spanish Subtitles\",\n    language: \"es\",\n    type: TextTrackType.SUBRIP, // \"application/x-subrip\"\n    uri: \"https://durian.blender.org/wp-content/content/subtitles/sintel_es.srt\"\n  }\n]\n```\n\n---\n\n### `showNotificationControls`\n\n<PlatformsList types={[\"Android\", \"iOS\", \"web\"]} />\n\nControls whether to show media controls in the notification area.\nFor Android, each Video component will have its own notification controls, whereas on iOS only one notification control will be shown for the last active Video component.\n\nOn Android, this will also allow for external controls, Google Assistant session, and other benefits of `MediaSession`.\n\nYou probably also want to set `playInBackground` to `true` to keep the video playing when the app is in the background, or `playWhenInactive` to `true` to keep the video playing when notifications or the Control Center are in front of the video.\n\nTo customize the notification controls, you can use the `metadata` property in the `source` prop.\n\n- **false (default)** - Don't show media controls in the notification area.\n- **true** - Show media controls in the notification area.\n\n**To test notification controls on iOS, you need to run the app on a real device, as the simulator does not support it.**\n\n**For Android, you have to add the following code in your `AndroidManifest.xml` file:**\n\n```xml\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    ...\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK\" />\n    ...\n\n    <application>\n      ...\n      <service\n        android:name=\"com.brentvatne.exoplayer.VideoPlaybackService\"\n        android:exported=\"false\"\n        android:foregroundServiceType=\"mediaPlayback\">\n          <intent-filter>\n            <action android:name=\"androidx.media3.session.MediaSessionService\" />\n          </intent-filter>\n      </service>\n    </application>\n</manifest>\n```\n\n---\n\n### `useSecureView`\n\n:::warning\ndeprecated, use viewType instead\n:::\n\n<PlatformsList types={[\"Android\"]} />\n\nForce the output to a SurfaceView and enables the secure surface.\n\nThis will override useTextureView flag.\n\nSurfaceView is the only one that can be labeled as secure.\n\n- **true** - Use security\n- **false (default)** - Do not use security\n\n### `useTextureView`\n\n:::warning\ndeprecated, use viewType instead\n:::\n\n<PlatformsList types={[\"Android\"]} />\n\nControls whether to output to a TextureView or SurfaceView.\n\nSurfaceView is more efficient and provides better performance but has two limitations:\n\n- It can't be animated, transformed or scaled\n- You can't overlay multiple SurfaceViews\n\nuseTextureView can only be set at the same time you're setting the source.\n\n- **true (default)** - Use a TextureView\n- **false** - Use a SurfaceView\n\n### `viewType`\n\n<PlatformsList types={[\"Android\"]} />\n\nAllows explicitly specifying the view type.\nThis flag replaces `useSecureView` and `useTextureView` fields.\nThere are 3 available values:\n\n- 'textureView': The video is rendered in a texture view. It allows mapping the view on a texture (useful for 3D).\n  DRM playback is not supported on textureView. If the DRM prop is provided, the surface will be transformed into a SurfaceView.\n- 'surfaceView' (default): The video is rendered in a surface, taking fewer resources to render.\n- 'secureView': The video is rendered in a surface that prevents screenshots from being taken.\n\n### `volume`\n\n<PlatformsList types={[\"All\"]} />\n\nAdjust the volume.\n\n- **1.0 (default)** - Play at full volume\n- **0.0** - Mute the audio\n- **Other values** - Reduce volume\n\n### `cmcd`\n\n<PlatformsList types={[\"Android\"]} />\n\nConfigure CMCD (Common Media Client Data) parameters. CMCD is a standard for conveying client-side metrics and capabilities to servers, which can help improve streaming quality and performance.\n\nFor detailed information about CMCD, please refer to the [CTA-5004 Final Specification](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf).\n\n- **false (default)** - Don't use CMCD\n- **true** - Use default CMCD configuration\n- **object** - Use custom CMCD configuration\n\nWhen providing an object, you can configure the following properties:\n\n| Property  | Type       | Description                                       |\n| --------- | ---------- | ------------------------------------------------- |\n| `mode`    | `CmcdMode` | The mode for sending CMCD data                    |\n| `request` | `CmcdData` | Custom key-value pairs for the request object     |\n| `session` | `CmcdData` | Custom key-value pairs for the session object     |\n| `object`  | `CmcdData` | Custom key-value pairs for the object metadata    |\n| `status`  | `CmcdData` | Custom key-value pairs for the status information |\n\nNote: The `mode` property defaults to `CmcdMode.MODE_QUERY_PARAMETER` if not specified.\n\n#### `CmcdMode`\n\nCmcdMode is an enum that defines how CMCD data should be sent:\n\n- `CmcdMode.MODE_REQUEST_HEADER` (0) - Send CMCD data in the HTTP request headers.\n- `CmcdMode.MODE_QUERY_PARAMETER` (1) - Send CMCD data as query parameters in the URL.\n\n#### `CmcdData`\n\nCmcdData is a type representing custom key-value pairs for CMCD data. It's defined as:\n\n```typescript\ntype CmcdData = Record<`${string}-${string}`, string | number>;\n```\n\nCustom key names MUST include a hyphenated prefix to prevent namespace collisions. It's recommended to use a reverse-DNS syntax for custom prefixes.\n\n**Example:**\n\n```javascript\n<Video\n  source={{\n    uri: \"https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8\",\n    cmcd: {\n      mode: CmcdMode.MODE_QUERY_PARAMETER,\n      request: {\n        \"com-custom-key\": \"custom-value\",\n      },\n      session: {\n        sid: \"session-id\",\n      },\n      object: {\n        br: \"3000\",\n        d: \"4000\",\n      },\n      status: {\n        rtp: \"1200\",\n      },\n    },\n  }}\n  // or other video props\n/>\n```\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/installation.md",
    "content": "---\nsidebar_position: 2\n---\n\n# Installation\n\nUsing npm:\n\n```shell\nnpm install --save react-native-video\n```\n\nor using yarn:\n\n```shell\nyarn add react-native-video\n```\n\nThen follow the instructions for your platform to link `react-native-video` into your project.\n\n# Specific Platform Installation\n\n<details>\n<summary>iOS</summary>\n\n## iOS\n\n### Standard Method\nRun `pod install` in the `ios` directory of your project.\n\n:::warning\nFrom version `6.0.0`, the minimum iOS version required is `13.0`. For more information, see the [updating section](updating.md).\n:::\n\n### Enable Custom Features in the Podfile\n\nSample configurations are available in the sample app. See the [sample pod file](https://github.com/TheWidlarzGroup/react-native-video/blob/9c669a2d8a53df36773fd82ff0917280d0659bc7/examples/basic/ios/Podfile#L34).\n\n#### Video Caching\n\nTo enable video caching, add the following line to your Podfile: ([more info here](other/caching.md))\n\n```podfile\n# Enable Video Caching\n$RNVideoUseVideoCaching=true\n```\n\n#### Google IMA\n\nGoogle IMA is the SDK for client-side ads integration. See the [Google documentation](https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side) for more details.\n\nTo enable Google IMA, add the following line to your Podfile:\n\n```podfile\n$RNVideoUseGoogleIMA=true\n```\n\n**If you are using Expo, you can use the [Expo plugin](other/expo.md).**\n\n> **Note:** If you are enabling video caching (using `$RNVideoUseVideoCaching`), you must add the following to your `Gemfile`:\n>\n> ```ruby\n> gem \"cocoapods-swift-modular-headers\"\n> ```\n>\n> Then, install dependencies using:\n>\n> ```sh\n> bundle install\n> bundle exec pod install\n> ```\n>\n> This enables Swift modular headers for Swift dependencies.\n\n</details>\n\n<details>\n<summary>Android</summary>\n\n## Android\n\nFrom version `>= 6.0.0`, your application must use Kotlin version `>= 1.8.0`.\n\n```gradle\nbuildscript {\n    ...\n    ext.kotlinVersion = '1.8.0'\n    ext.compileSdkVersion = 34\n    ext.targetSdkVersion = 34\n    ...\n}\n```\n\n### Enable Custom Features in the Gradle File\n\n**If you are using Expo, you can use the [Expo plugin](other/expo.md).**\n\nYou can enable or disable the following features by setting the corresponding variables in your `android/build.gradle` file:\n\n- `useExoplayerIMA` - Enable Google IMA SDK (ads support)\n- `useExoplayerRtsp` - Enable RTSP support\n- `useExoplayerSmoothStreaming` - Enable SmoothStreaming support\n- `useExoplayerDash` - Enable Dash support\n- `useExoplayerHls` - Enable HLS support\n\nEach enabled feature increases the APK size, so only enable what you need.\n\nBy default, the enabled features are:\n- `useExoplayerSmoothStreaming`\n- `useExoplayerDash`\n- `useExoplayerHls`\n\nExample:\n\n```gradle\nbuildscript {\n  ext {\n    ...\n    useExoplayerIMA = true\n    useExoplayerRtsp = true\n    useExoplayerSmoothStreaming = true\n    useExoplayerDash = true\n    useExoplayerHls = true\n    ...\n  }\n}\n```\n\nSee the [sample app](https://github.com/TheWidlarzGroup/react-native-video/blob/9c669a2d8a53df36773fd82ff0917280d0659bc7/examples/basic/android/build.gradle#L14C5-L14C5).\n\n</details>\n\n<details>\n<summary>Windows</summary>\n\n## Windows\n\n### Autolinking\n\n**React Native Windows 0.63 and above**\n\nAutolinking should automatically add `react-native-video` to your app.\n\n### Manual Linking\n\n**React Native Windows 0.62**\n\nMake the following manual additions:\n\n#### `windows\\myapp.sln`\n\nAdd the _ReactNativeVideoCPP_ project to your solution:\n\n1. Open your solution in Visual Studio 2019.\n2. Right-click the Solution icon in Solution Explorer > Add > Existing Project...\n3. Select `node_modules\\react-native-video\\windows\\ReactNativeVideoCPP\\ReactNativeVideoCPP.vcxproj`.\n\n#### `windows\\myapp\\myapp.vcxproj`\n\nAdd a reference to _ReactNativeVideoCPP_ to your main application project:\n\n1. Open your solution in Visual Studio 2019.\n2. Right-click the main application project > Add > Reference...\n3. Check _ReactNativeVideoCPP_ from Solution Projects.\n\n#### `pch.h`\n\nAdd:\n\n```cpp\n#include \"winrt/ReactNativeVideoCPP.h\"\n```\n\n#### `app.cpp`\n\nAdd:\n\n```cpp\nPackageProviders().Append(winrt::ReactNativeVideoCPP::ReactPackageProvider());\n```\n\nbefore `InitializeComponent();`.\n\n**React Native Windows 0.61 and below**\n\nFollow the manual linking steps for React Native Windows 0.62, but use _ReactNativeVideoCPP61_ instead of _ReactNativeVideoCPP_.\n\n</details>\n\n<details>\n<summary>tvOS</summary>\n\n## tvOS\n\n`react-native link react-native-video` does not work properly with the tvOS target, so the library must be added manually.\n\n### Steps:\n\n1. Select your project in Xcode.\n\n   ![tvOS step 1](./assets/tvOS-step-1.jpg)\n\n2. Select the tvOS target of your application and open the \"General\" tab.\n\n   ![tvOS step 2](./assets/tvOS-step-2.jpg)\n\n3. Scroll to \"Linked Frameworks and Libraries\" and click the `+` button.\n\n   ![tvOS step 3](./assets/tvOS-step-3.jpg)\n\n4. Select `RCTVideo-tvOS`.\n\n   ![tvOS step 4](./assets/tvOS-step-4.jpg)\n\n</details>\n\n<details>\n<summary>visionOS</summary>\n\n## visionOS\n\nRun `pod install` in the `visionos` directory of your project.\n\n</details>\n\n<details>\n<summary>Web</summary>\n\n## Web\n\nNo additional setup is required. Everything should work out of the box.\n\nHowever, only basic video support is available. HLS, Dash, ads, and DRM are not currently supported.\n\n</details>\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/intro.md",
    "content": "---\nsidebar_position: 1\ntitle: Intro\n---\n# A `<Video>` Component for React Native\n\n## About\n`react-native-video` is a React Native library that provides a Video component to render media content like videos and streams.\n\nIt allows you to stream video files (m3u, mpd, mp4, etc.) inside your React Native application.\n\n- ExoPlayer for Android\n- AVPlayer for iOS, tvOS, and visionOS\n- Windows UWP for Windows\n- HTML5 for Web\n- Trick mode support\n- Subtitles (embedded or side-loaded)\n- DRM support\n- Client-side ad insertion (via Google IMA)\n- PiP (Picture-in-Picture)\n- Embedded playback controls\n- And more\n\nThe goal of this package is to provide lightweight but full control over the player.\n\n## V6.0.0 Information\n:::warning\n**Version 6**: This documentation covers features available only in v6.0.0 and later.\nIf you're unsure or need an older version, you can still use [version 5.2.x](https://github.com/TheWidlarzGroup/react-native-video/blob/v5.2.0/README.md).\n:::\n\nVersion 6.x requires **react-native >= 0.68.2**\n:::warning\nFrom **6.0.0-beta.8**, it also requires **iOS >= 13.0** (default in React Native 0.73).\n:::\n\nFor older versions of React Native, [please use version 5.x](https://github.com/TheWidlarzGroup/react-native-video/tree/v5.2.0).\n\n## Usage\n\n```javascript\n// Load the module\nimport Video, { VideoRef } from 'react-native-video';\n\n// Inside your render function, assuming you have a file called\n// \"background.mp4\" in your project. You can include multiple videos\n// on a single screen if needed.\n\nconst VideoPlayer = () => {\n  const videoRef = useRef<VideoRef>(null);\n  const background = require('./background.mp4');\n\n  return (\n    <Video\n      // Can be a URL or a local file.\n      source={background}\n      // Store reference  \n      ref={videoRef}\n      // Callback when remote video is buffering                                      \n      onBuffer={onBuffer}\n      // Callback when the video cannot be loaded              \n      onError={onError}               \n      style={styles.backgroundVideo}\n    />\n  );\n};\n\n// Later in your styles...\nvar styles = StyleSheet.create({\n  backgroundVideo: {\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    bottom: 0,\n    right: 0,\n  },\n});\n```"
  },
  {
    "path": "docs/versioned_docs/version-6.x/other/_category_.json",
    "content": "{\n  \"label\": \"Other\",\n  \"position\": 4,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Other topics of React Native Video\"\n  },\n  \"collapsed\": true\n}\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/other/caching.md",
    "content": "---\nsidebar_position: 3\ntitle: Caching\ndescription: React Native Video Caching Integration\n---\n# Caching\n\nCaching is supported on `iOS` platforms with a CocoaPods setup and on `Android` using `SimpleCache`.\n\n## Android\n\nAndroid uses an LRU `SimpleCache` with a variable cache size, which can be specified by `bufferConfig - cacheSizeMB`. This creates a folder named `RNVCache` inside the app's `cache` directory.\n\nNote that `react-native-video` does not currently offer a native method to flush the cache, but it can be cleared by manually clearing the app's cache.\n\nAdditionally, this resolves the issue in RNV6 where the source URI was repeatedly called when looping a video on Android.\n\n## iOS\n\n### Technology\n\nThe cache is backed by [SPTPersistentCache](https://github.com/spotify/SPTPersistentCache) and [DVAssetLoaderDelegate](https://github.com/vdugnist/DVAssetLoaderDelegate).\n\n### How It Works\n\nCaching is based on the asset's URL. `SPTPersistentCache` uses an LRU ([Least Recently Used](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU))) caching policy.\n\n### Restrictions\n\nCurrently, caching is only supported for URLs ending in `.mp4`, `.m4v`, or `.mov`. In future versions, URLs with query strings (e.g., `test.mp4?resolution=480p`) will be supported once dependencies allow access to the `Content-Type` header.\n\nAt this time, HLS playlists (`.m3u8`) and videos with sideloaded text tracks are not supported and will bypass the cache.\n\nYou will see warnings in the Xcode logs when using `debug` mode. If you're unsure whether your video is cached, check your Xcode logs.\n\nBy default, files expire after 30 days, and the maximum cache size is 100MB.\n\nFuture updates may include more configurable caching options.\n\n> **Note:** If you are enabling video caching (using `$RNVideoUseVideoCaching`), you must add the following to your `Gemfile`:\n>\n> ```ruby\n> gem \"cocoapods-swift-modular-headers\"\n> ```\n>\n> Then, install dependencies using:\n>\n> ```sh\n> bundle install\n> bundle exec pod install\n> ```\n>\n> This enables Swift modular headers for Swift dependencies.\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/other/debug.md",
    "content": "---\nsidebar_position: 2\ntitle: Debugging\ndescription: React Native Video Debugging Tips\n---\n# Debugging\n\nThis page provides useful tips for debugging and troubleshooting issues in the package or your application.\n\n## Using the Sample App\n\nThis repository contains multiple sample implementations in the `example` folder. It is always preferable to test behavior in a sample app rather than in a full application. The basic sample allows testing of many features.\n\nTo use the sample app, follow these steps:\n\n- Clone this repository:\n  ```shell\n  git clone git@github.com:TheWidlarzGroup/react-native-video.git\n  ```\n- Navigate to the root folder and build the package. This generates a transpiled version in the `lib` folder:\n  ```shell\n  cd react-native-video && yarn && yarn build\n  ```\n- Navigate to the sample app and install dependencies:\n  ```shell\n  cd example/basic && yarn install\n  ```\n- Build and run the app:\n    - For Android:\n      ```shell\n      yarn android\n      ```\n    - For iOS:\n      ```shell\n      cd ios && pod install && cd .. && yarn ios\n      ```\n\n## HTTP Playback Doesn't Work or Black Screen on Release Build (Android)\n\nIf your video works in Debug mode but shows only a black screen in Release mode, check the URL of your video. If you are using the `http` protocol, you need to add the following line to your `AndroidManifest.xml` file. [More details here](https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic):\n\n```xml\n<application\n ...\n android:usesCleartextTraffic=\"true\"\n>\n```\n\n## Decoder Issue (Android)\n\nSome devices have a maximum number of simultaneous video playbacks. If this limit is reached, ExoPlayer returns an error: `Unable to instantiate decoder`.\n\n**Known issue:** This happens frequently in Debug mode.\n\n## Unable to Play Clear Content (All OS)\n\nBefore opening a ticket, follow these steps:\n\n### Check Remote File Access\n\nEnsure you can download the manifest/content file using a browser.\n\n### Check If Another Player Can Play the Content\n\nClear playback should work with any video player. Test the content with another player, such as [VLC](https://www.videolan.org/vlc/), to confirm it plays without issues.\n\n## Unable to Play Protected Content (All OS)\n\n### Protected Content Gives an Error (Token Error / Access Forbidden)\n\nIf the content requires an access token or HTTP headers, ensure you can access the data using `wget` or a REST client. Provide all necessary authentication parameters.\n\n## Debugging Network Calls Not Visible in React Native Debugging Tools\n\nThis is a React Native limitation—React Native debugging tools only capture network calls made in JavaScript.\n\nTo debug network calls, use tools like:\n- [Charles Proxy](https://www.charlesproxy.com/)\n- [Fiddler](https://www.telerik.com/fiddler)\n\nThese tools allow you to sniff all HTTP/HTTPS calls, including access to content, DRM, and audio/video chunks. Compare the request/response patterns with previous tests to diagnose issues.\n\n## Debugging Media3: Build from Media3 Source\n\nIf you need to use a specific ExoPlayer version or modify default behavior, you may need to build from the Media3 source code.\n\n### Configure Player Path\n\nAdd the following lines to `settings.gradle` to configure your Media3 source path:\n\n```gradle\ngradle.ext.androidxMediaModulePrefix = 'media-'\napply from: file(\"../../../../media3/core_settings.gradle\")\n```\n\nReplace this with the actual Media3 source path. Ensure that you use the same version (or a compatible API version) supported by the package.\n\n### Enable Building from Source\n\nIn your `build.gradle` file, add the following setting:\n\n```gradle\nbuildscript {\n    ext {\n        ...\n        buildFromMedia3Source = true\n        ...\n    }\n}\n```\n\n## Still Not Working?\n\nYou can open a ticket or contact us for [premium support](https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=debugging&utm_id=enterprise#Contact).\n\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/other/downloading.md",
    "content": "---\nsidebar_position: 4\ntitle: Downloading\ndescription: React Native Video Integration with Offline Video SDK\n---\n# Offline Video SDK\n\n## Add Offline Playback to Your React Native App — Fast\n\nThe [Offline Video SDK](https://www.thewidlarzgroup.com/offline-video-sdk/?utm_source=rnv&utm_medium=docs&utm_campaign=downloading&utm_id=offline-video-sdk-link) is a commercial add-on for `react-native-video` (v6 and v7) that enables secure **offline playback** of HLS streams — including support for **DRM**, **multi-audio**, and **subtitles**.\n\nIt’s built for teams who need a production-ready solution without spending months on in-house development.  \nTry it free today and ship faster.\n\n➡️ [Start Free Trial](https://sdk.thewidlarzgroup.com/signup?utm_source=rnv&utm_medium=docs&utm_id=downloading_start-trial-offline-video-sdk-1)\n\n---\n\n## 🚀 Key Features\n\n- **Stream Downloading**  \n  Download and store HLS content for offline playback, including full control over asset management.\n\n- **Offline DRM**  \n  Seamlessly supports offline playback of DRM-protected content, with proper rights enforcement and license handling.\n\n- **Multiple Audio Tracks & Subtitles**  \n  Choose which tracks to download (e.g. language, subtitles) — ideal for localized content.\n\n- **Selective Downloads**  \n  Only selected tracks are downloaded by default to optimize storage.\n\n- **DRM License Optimization**  \n  Works efficiently with persistent licenses — no need to re-fetch unless expired.\n\n- **Background Download Management**  \n  Handles queuing, progress tracking, retries, pausing/resuming – all out of the box.\n\n- **Pluggable Architecture**  \n  Compatible with your existing player setup — doesn’t interfere with other plugins or custom features.\n\n---\n\n## ⚙️ Compatibility & Requirements\n\n- Supports `react-native-video` **v6** and **v7**\n\n---\n\n## 🤝 Integration & Support\n\nYou can integrate the SDK yourself using our documentation and [Offline Video Starter Project](https://github.com/TheWidlarzGroup/react-native-offline-video-starter?utm_source=rnv&utm_medium=docs&utm_id=downloading_offline-video-sdk-starter), which includes a ready-to-run example app demonstrating offline playback, multi-audio, subtitles, and DRM setup.  \nAlternatively, work with our team to accelerate your roadmap.\n\n- 💬 [Contact us for support](mailto:sdk@thewidlarzgroup.com)  \n- 🧪 [Try the SDK – Free Trial](https://sdk.thewidlarzgroup.com/signup?utm_source=rnv&utm_medium=docs&utm_id=downloading_start-trial-offline-video-sdk-2)  \n- 🔗 [Learn more about features](https://www.thewidlarzgroup.com/offline-video-sdk?utm_source=rnv&utm_medium=docs&utm_id=downloading_learn-more-offline-video-sdk)\n\n---\n\n## 📄 Licensing & Trials\n\nThe Offline Video SDK is distributed under a commercial license.  \nYou can evaluate it for free for 14 days — no credit card required.\n\nHave questions or need help?  \n📬 [sdk@thewidlarzgroup.com](mailto:sdk@thewidlarzgroup.com)"
  },
  {
    "path": "docs/versioned_docs/version-6.x/other/expo.md",
    "content": "---\nsidebar_position: 1\ntitle: Expo\ndescription: React Native Video Expo Plugin\n---\n# Expo\n\n## Expo Plugin\n\nStarting from version `6.3.1`, `react-native-video` supports an Expo plugin. You can configure `react-native-video` properties in the `app.json`, `app.config.json`, or `app.config.js` file.\n\nThis is particularly useful when using the `Expo` managed workflow (`expo prebuild`), as it automatically sets up `react-native-video` properties in the native part of the Expo project.\n\n### Example Configuration\n\n```json\n// app.json\n{\n  \"name\": \"my app\",\n  \"plugins\": [\n    [\n      \"react-native-video\",\n      {\n        \"enableNotificationControls\": true,\n        \"androidExtensions\": {\n          \"useExoplayerRtsp\": false,\n          \"useExoplayerSmoothStreaming\": false,\n          \"useExoplayerHls\": false,\n          \"useExoplayerDash\": false\n        }\n      }\n    ]\n  ]\n}\n```\n\n## Expo Plugin Properties\n\n| Property | Type | Default | Description |\n| --- | --- | --- | --- |\n| enableNotificationControls | boolean | false | Add required changes on android to use notification controls for video player |\n| enableBackgroundAudio | boolean | false | Add required changes to play video in background on iOS |\n| enableADSExtension | boolean | false | Add required changes to use ads extension for video player |\n| enableCacheExtension | boolean | false | Add required changes to use cache extension for video player on iOS |\n| androidExtensions | object | {} | You can enable/disable extensions as per your requirement - this allow to reduce library size on android |\n| enableAndroidPictureInPicture | boolean | false | Apply configs to be able to use Picture-in-picture on android |\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/other/misc.md",
    "content": "---\nsidebar_position: 5\ntitle: Miscellaneous\ndescription: React Native Video Miscellaneous & Tips\n---\n# Miscellaneous\n\n## iOS App Transport Security\n\nBy default, iOS only allows loading encrypted (`https`) URLs. If you need to load content from an unencrypted (`http`) source, you must modify your `Info.plist` file and add the following entry:\n\n![App Transport Security](../assets/AppTransportSecuritySetting.png)\n\nFor more details, check this [article](https://cocoacasts.com/how-to-add-app-transport-security-exception-domains).\n\n## Audio Mixing\n\nIn future versions, `react-native-video` will include an Audio Manager for configuring how videos mix with other audio-playing apps.\n\nOn iOS, if you want to allow background music from other apps to continue playing over your video component, update your `AppDelegate.m` file:\n\n### **AppDelegate.m**\n\n```objective-c\n#import <AVFoundation/AVFoundation.h>  // Import the AVFoundation framework\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions\n{\n  ...\n  [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];  // Allow background audio\n  ...\n}\n```\n\nYou can also use the [`ignoreSilentSwitch`](#ignoresilentswitch) prop.\n\n## Android Expansion File Usage\n\nExpansion files allow you to include assets exceeding the 100MB APK size limit without requiring an update every time you push a new version.\n\n- Only supports `.mp4` files, and they **must not be compressed**.\n- Example command to prevent compression:\n\n```bash\nzip -r -n .mp4 *.mp4 player.video.example.com\n```\n\n### Example Usage in Code:\n\n```javascript\n// Assuming \"background.mp4\" is included in your expansion file.\n<Video \n  source={{uri: \"background\", mainVer: 1, patchVer: 0}} // Looks for \"background.mp4\" in the specified expansion version.\n  resizeMode=\"cover\"           // Fill the whole screen while maintaining aspect ratio.\n  style={styles.backgroundVideo} \n/>\n```\n\n## Load Files with the React Native Asset System\n\nThe asset system introduced in RN `0.14` allows loading shared image resources across iOS and Android without modifying native code. As of RN `0.31`, the same applies to `.mp4` video assets on Android. From RN `0.33`, iOS support was added. Requires `react-native-video@0.9.0` or later.\n\n### Example:\n\n```javascript\n<Video\n  source={require('../assets/video/turntable.mp4')}\n/>\n```\n\n## Play in Background on iOS\n\nTo allow audio playback in the background on iOS, set the audio session to `AVAudioSessionCategoryPlayback`. See the [Apple documentation](https://developer.apple.com/documentation/avfoundation/avaudiosession) for more details.\n\n_(Note: There is an open ticket to [expose this as a prop](https://github.com/react-native-community/react-native-video/issues/310).)_\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/other/new-arch.md",
    "content": "---\nsidebar_position: 6\ntitle: New Architecture\ndescription: React Native Video New Architecture Support\n---\n# New Architecture\n\n## Fabric\n\nThe library currently does not support Fabric. We are working on adding support. In the meantime, you can use the Interop Layer.\n\n## Interop Layer\n\nYou can use this library with the New Architecture by enabling the Interop Layer.\n\n### Requirements:\n- `react-native` **>= 0.72.0**\n- `react-native-video` **>= 6.0.0-beta.5**\n\nFor `react-native` versions **< 0.74**, you need to add the following configuration in the `react-native.config.js` file:\n\n```javascript\nmodule.exports = {\n  project: {\n    android: {\n      unstable_reactLegacyComponentNames: ['Video'],\n    },\n    ios: {\n      unstable_reactLegacyComponentNames: ['Video'],\n    },\n  },\n};\n```\n\n## Bridgeless Mode\n\nThe library currently does not support Bridgeless Mode. We are working on adding support.\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/other/plugin.md",
    "content": "---\nsidebar_position: 4\ntitle: Plugins\ndescription: React Native Video Plugins Integration\n---\n# Plugins\n\nSince version `6.4.0`, it is possible to create plugins for analytics management and potentially more.\nA sample plugin is available in the repository: [example/react-native-video-plugin-sample](https://github.com/TheWidlarzGroup/react-native-video/tree/master/examples/react-native-video-plugin-sample).\n\n## Commercial Plugins\n\nWe at The Widlarz Group have created a set of plugins for comprehensive offline video support. If you are interested, check out our [Offline Video SDK](https://www.thewidlarzgroup.com/offline-video-sdk/?utm_source=rnv&utm_medium=docs&utm_campaign=plugins&utm_id=text). If you need additional plugins (analytics, processing, etc.), let us know.\n\n> Using or recommending our commercial software helps support the maintenance of this open-source project. Thank you!\n\n## Plugins for Analytics\n\nMost analytics systems that track player data (e.g., bitrate, errors) can be integrated directly with ExoPlayer or AVPlayer.\nThis plugin system allows for non-intrusive analytics integration with `react-native-video`. It should be implemented in native languages (Kotlin/Swift) to ensure efficiency.\n\nThe goal is to enable easy analytics integration without modifying `react-native-video` itself.\n\n## Warnings & Considerations\n\nThis is an **experimental API** and may change over time. The API is simple yet flexible enough to implement analytics systems.\nIf additional metadata is needed, you should implement a setter in your custom package.\n\nSince the API is flexible, misuse is possible. The player handle should be treated as **read-only**. Modifying player behavior may cause unexpected issues in `react-native-video`.\n\n## General Setup\n\nFirst, create a new React Native package:\n\n```shell\nnpx create-react-native-library@latest react-native-video-custom-analytics\n```\n\nBoth Android and iOS implementations expose an `RNVPlugin` interface.\nYour `react-native-video-custom-analytics` package should implement this interface and register itself as a plugin for `react-native-video`.\n\n## Plugin Types\n\nThere are two types of plugins you can implement:\n\n1. **Base Plugin (`RNVPlugin`)**: For general-purpose plugins that don't need specific player implementation details.\n2. **Player-Specific Plugins**:\n   - `RNVAVPlayerPlugin` for iOS: Provides type-safe access to AVPlayer instances\n   - `RNVExoplayerPlugin` for Android: Provides type-safe access to ExoPlayer instances\n\nChoose the appropriate plugin type based on your needs. If you need direct access to player-specific APIs, use the player-specific plugin classes.\n\n## Android Implementation\n\n### 1. Create the Plugin\n\nYou can implement either the base `RNVPlugin` interface or the player-specific `RNVExoplayerPlugin` interface.\n\n#### Base Plugin\n\n```kotlin\nclass MyAnalyticsPlugin : RNVPlugin {\n    override fun onInstanceCreated(id: String, player: Any) {\n        // Handle player creation\n    }\n\n    override fun onInstanceRemoved(id: String, player: Any) {\n        // Handle player removal\n    }\n}\n```\n\n#### ExoPlayer-Specific Plugin\n\n```kotlin\nclass MyExoPlayerAnalyticsPlugin : RNVExoplayerPlugin {\n    override fun onInstanceCreated(id: String, player: ExoPlayer) {\n        // Handle ExoPlayer creation with type-safe access\n    }\n\n    override fun onInstanceRemoved(id: String, player: ExoPlayer) {\n        // Handle ExoPlayer removal with type-safe access\n    }\n}\n```\n\nThe `RNVPlugin` interface defines two functions:\n\n```kotlin\n/**\n * Function called when a new player is created\n * @param id: a random string identifying the player\n * @param player: the instantiated player reference\n */\nfun onInstanceCreated(id: String, player: Any)\n\n/**\n * Function called when a player should be destroyed\n * when this callback is called, the plugin shall free all\n * resources and release all reference to Player object\n * @param id: a random string identifying the player\n * @param player: the player to release\n */\nfun onInstanceRemoved(id: String, player: Any)\n```\n\n### 2. Register the Plugin\n\nTo register the plugin within the main `react-native-video` package, call:\n\n```kotlin\nReactNativeVideoManager.getInstance().registerPlugin(plugin)\n```\n\nIn the sample implementation, the plugin is registered in the `createNativeModules` entry point.\n\nOnce registered, your module can track player updates and report analytics data.\n\n### Extending Core Functionality via Plugins\n\nIn addition to analytics, plugins can also be used to modify or override core behavior of `react-native-video`.\n\nThis allows native modules to deeply integrate with the playback system - for example:\n- replacing the media source factory,\n- modifying the media item before playback starts (e.g., injecting stream keys),\n- disabling caching dynamically per source.\n\nThese capabilities are available through the advanced Android plugin interface: `RNVExoplayerPlugin`.\n\n:::warning\nThese extension points are optional — if no plugin provides them, the player behaves exactly as it did before.\n:::\n\n---\n\n#### Plugin Extension Points (Android)\n\nIf your plugin implements `RNVExoplayerPlugin`, you can override the following methods:\n\n##### 1. `overrideMediaItemBuilder`\n\nAllows you to modify the `MediaItem.Builder` before it’s used. You can inject stream keys, cache keys, or override URIs.\n\n```kotlin\noverride fun overrideMediaItemBuilder(\n    source: Source,\n    mediaItemBuilder: MediaItem.Builder\n): MediaItem.Builder? {\n    // Return modified builder or null to use default\n}\n```\n\n##### 2. `overrideMediaDataSourceFactory`\n\nLets you replace the data source used by ExoPlayer. Useful for implementing read-only cache or request interception.\n\n```kotlin\noverride fun overrideMediaDataSourceFactory(\n    source: Source,\n    mediaDataSourceFactory: DataSource.Factory\n): DataSource.Factory? {\n    // Return your custom factory or null to use default\n}\n```\n\n##### 3. `overrideMediaSourceFactory`\n\nAllows you to override the default MediaSource.Factory used by ExoPlayer for creating media sources.\nUse this if you need to inject a custom media source implementation. If you return null, the default media source factory will be used.\n\n```kotlin\noverride fun overrideMediaSourceFactory(\n    source: Source,\n    mediaSourceFactory: MediaSource.Factory,\n    mediaDataSourceFactory: DataSource.Factory\n  ): MediaSource.Factory? {\n    // Return your custom factory or null to use default\n  }\n```\n\n##### 4. `shouldDisableCache`\n\nEnables dynamic disabling of the caching system per source.\n\n```kotlin\noverride fun shouldDisableCache(source: Source): Boolean {\n    return true // your own logic\n}\n```\n\n---\n\nOnce implemented, `react-native-video` will automatically invoke these methods for each `<Video />` instance.\n\n## iOS Implementation\n\n### 1. Podspec Integration\n\nYour new module must have access to `react-native-video`. Add it as a dependency in your Podspec file:\n\n```podfile\ns.dependency \"react-native-video\"\n```\n\n### 2. Create the Plugin\n\nYou can implement either the base `RNVPlugin` class or the player-specific `RNVAVPlayerPlugin` class.\n\n#### Base Plugin\n\n```swift\nclass MyAnalyticsPlugin: RNVPlugin {\n    override func onInstanceCreated(id: String, player: Any) {\n        // Handle player creation\n    }\n\n    override func onInstanceRemoved(id: String, player: Any) {\n        // Handle player removal\n    }\n}\n```\n\n#### AVPlayer-Specific Plugin\n\n```swift\nclass MyAVPlayerAnalyticsPlugin: RNVAVPlayerPlugin {\n    override func onInstanceCreated(id: String, player: AVPlayer) {\n        // Handle AVPlayer creation with type-safe access\n    }\n\n    override func onInstanceRemoved(id: String, player: AVPlayer) {\n        // Handle AVPlayer removal with type-safe access\n    }\n\n    /// Optionally override the asset used by the player before playback starts\n    override func overridePlayerAsset(source: VideoSource, asset: AVAsset) async -> OverridePlayerAssetResult? {\n        // Return a modified asset or nil to use the default\n        return nil\n    }\n}\n```\n\nThe `RNVAVPlayerPlugin` class defines several extension points:\n\n```swift\n/**\n * Function called when a new AVPlayer instance is created\n * @param id: a random string identifying the player\n * @param player: the instantiated AVPlayer\n */\nopen func onInstanceCreated(id: String, player: AVPlayer) { /* no-op */ }\n\n/**\n * Function called when an AVPlayer instance is being removed\n * @param id: a random string identifying the player\n * @param player: the AVPlayer to release\n */\nopen func onInstanceRemoved(id: String, player: AVPlayer) { /* no-op */ }\n\n/**\n * Optionally override the asset used by the player before playback starts.\n * Allows you to modify or replace the AVAsset before it is used to create the AVPlayerItem.\n * Return nil to use the default asset.\n *\n * @param source: The VideoSource describing the video (uri, type, headers, etc.)\n * @param asset: The AVAsset prepared by the player\n * @return: OverridePlayerAssetResult if you want to override, or nil to use the default\n */\nopen func overridePlayerAsset(source: VideoSource, asset: AVAsset) async -> OverridePlayerAssetResult? { nil }\n```\n\n##### `OverridePlayerAssetResult` and `OverridePlayerAssetType`\n\nTo override the asset, return an `OverridePlayerAssetResult`:\n\n```swift\npublic struct OverridePlayerAssetResult {\n  public let type: OverridePlayerAssetType\n  public let asset: AVAsset\n\n  public init(type: OverridePlayerAssetType, asset: AVAsset) {\n    self.type = type\n    self.asset = asset\n  }\n}\n\npublic enum OverridePlayerAssetType {\n  case partial // Return a partially modified asset; will go through the default prepare process\n  case full    // Return a fully modified asset; will skip the default prepare process\n}\n```\n\n- Use `.partial` if you want the asset to continue through the player's normal preparation (e.g., for text tracks or metadata injection).\n- Use `.full` if you want to provide a fully prepared asset that will be used as-is for playback.\n\n**Example:**\n\n```swift\noverride func overridePlayerAsset(source: VideoSource, asset: AVAsset) async -> OverridePlayerAssetResult? {\n    // Example: Replace the asset URL\n    let newAsset = AVAsset(url: URL(string: \"https://example.com/override.mp4\")!)\n    return Result(type: .full, asset: newAsset)\n}\n```\n\n> Only one plugin can override the player asset at a time. If multiple plugins implement this, only the first will be used.\n\n### 3. Register the Plugin\n\nTo register the plugin in `react-native-video`, call:\n\n```swift\nReactNativeVideoManager.shared.registerPlugin(plugin: plugin)\n```\n\nIn the sample implementation, the plugin is registered inside the `VideoPluginSample` file within the `init` function:\n\n```swift\nimport react_native_video\n\n...\n\noverride init() {\n    super.init()\n    ReactNativeVideoManager.shared.registerPlugin(plugin: self)\n}\n```\n\nOnce registered, your module can track player updates and report analytics data to your backend.\n\n## Custom DRM Manager\n\nYou can provide a custom DRM manager through your plugin to handle DRM in a custom way. This is useful when you need to integrate with a specific DRM provider or implement custom DRM logic.\n\n### Android Implementation\n\n#### 1/ Create custom DRM manager\n\nCreate a class that implements the `DRMManagerSpec` interface:\n\n```kotlin\nclass CustomDRMManager : DRMManagerSpec {\n    @Throws(UnsupportedDrmException::class)\n    override fun buildDrmSessionManager(uuid: UUID, drmProps: DRMProps): DrmSessionManager? {\n        // Your custom implementation for building DRM session manager\n        // Return null if the DRM scheme is not supported\n        // Throw UnsupportedDrmException if the DRM scheme is invalid\n    }\n}\n```\n\n#### 2/ Register DRM manager in your plugin\n\nImplement `getDRMManager()` in your ExoPlayer plugin to provide the custom DRM manager:\n\n```kotlin\nclass CustomVideoPlugin : RNVExoplayerPlugin {\n    private val drmManager = CustomDRMManager()\n    \n    override fun getDRMManager(): DRMManagerSpec? {\n        return drmManager\n    }\n    \n    override fun onInstanceCreated(id: String, player: ExoPlayer) {\n        // Handle player creation\n    }\n    \n    override fun onInstanceRemoved(id: String, player: ExoPlayer) {\n        // Handle player removal\n    }\n}\n```\n\n### iOS Implementation\n\n#### 1/ Create custom DRM manager\n\nCreate a class that implements the `DRMManagerSpec` protocol:\n\n```swift\nclass CustomDRMManager: NSObject, DRMManagerSpec {\n    func createContentKeyRequest(\n        asset: AVContentKeyRecipient,\n        drmProps: DRMParams?,\n        reactTag: NSNumber?,\n        onVideoError: RCTDirectEventBlock?,\n        onGetLicense: RCTDirectEventBlock?\n    ) {\n        // Initialize content key session and handle key request\n    }\n    \n    func handleContentKeyRequest(keyRequest: AVContentKeyRequest) {\n        // Process the content key request\n    }\n    \n    func finishProcessingContentKeyRequest(keyRequest: AVContentKeyRequest, license: Data) throws {\n        // Finish processing the key request with the obtained license\n    }\n    \n    func handleError(_ error: Error, for keyRequest: AVContentKeyRequest) {\n        // Handle any errors during the DRM process\n    }\n    \n    func setJSLicenseResult(license: String, licenseUrl: String) {\n        // Handle successful license acquisition from JS side\n    }\n    \n    func setJSLicenseError(error: String, licenseUrl: String) {\n        // Handle license acquisition errors from JS side\n    }\n}\n```\n\n#### 2/ Register DRM manager in your plugin\n\nImplement `getDRMManager()` in your AVPlayer plugin to provide the custom DRM manager:\n\n```swift\nclass CustomVideoPlugin: RNVAVPlayerPlugin {\n    override func getDRMManager() -> DRMManagerSpec? {\n        return CustomDRMManager()\n    }\n    \n    override func onInstanceCreated(id: String, player: AVPlayer) {\n        // Handle player creation\n    }\n    \n    override func onInstanceRemoved(id: String, player: AVPlayer) {\n        // Handle player removal\n    }\n}\n```\n\n### Important notes about DRM managers:\n\n1. Only one plugin can provide a DRM manager at a time. If multiple plugins try to provide DRM managers, only the first one will be used.\n2. The custom DRM manager will be used for all video instances in the app.\n3. If no custom DRM manager is provided:\n   - On iOS, the default FairPlay-based implementation will be used\n   - On Android, the default ExoPlayer DRM implementation will be used\n4. The DRM manager must handle all DRM-related functionality:\n   - On iOS: key requests, license acquisition, and error handling through AVContentKeySession\n   - On Android: DRM session management and license acquisition through ExoPlayer's DrmSessionManager\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/projects.md",
    "content": "---\ntitle: Useful Projects\ndescription: React Native Video Useful Projects\nsidebar_class_name: hidden\n---\n# Useful Projects\n\nThis page lists open-source projects that can be helpful for your player implementation. <br/>\nIf you have a project that could benefit other users, feel free to open a PR to add it here.\n\n## Our (TheWidlarzGroup) Libraries\n- [react-native-video-player](https://github.com/TheWidlarzGroup/react-native-video-player): Our video player UI library.\n- [Offline Video SDK](https://www.thewidlarzgroup.com/offline-video-sdk?utm_source=rnv&utm_medium=docs&utm_id=projects_offline-video-sdk): If you're building an app that needs **offline playback** (e.g., downloading HLS videos, subtitles, audio tracks, or DRM-protected content), check out our commercial Offline Video SDK. It integrates with `react-native-video` and is available with a [free trial](https://sdk.thewidlarzgroup.com/signup?utm_source=rnv&utm_medium=docs&utm_id=projects_start-trial-offline-video-sdk). To get started quickly, you can clone our [Offline Video Starter Project](https://github.com/TheWidlarzGroup/react-native-offline-video-starter?utm_source=rnv&utm_medium=docs&utm_id=projects_offline-video-starter), which includes a ready-to-run example app demonstrating offline playback, multi-audio, subtitles, and DRM setup.\n\n## Community Libraries\n- [react-native-corner-video](https://github.com/Lg0gs/react-native-corner-video): A floating video player.\n- [react-native-track-player](https://github.com/doublesymmetry/react-native-track-player): A toolbox for audio playback.\n- [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls): A video player UI.\n- [react-native-media-console](https://github.com/criszz77/react-native-media-console): An updated version of react-native-video-controls, rewritten in TypeScript.\n"
  },
  {
    "path": "docs/versioned_docs/version-6.x/updating.md",
    "content": "---\ntitle: Updating\ndescription: React Native Video Updating Guide\nsidebar_class_name: hidden\n---\n# Updating\n\n## Version 6.0.0\n\n### iOS\n\n#### Minimum iOS Version\nStarting from version 6.0.0, the minimum supported iOS version is 13.0. Projects using `react-native < 0.73` must set the minimum iOS version to 13.0 in the Podfile.\n\nYou can do this by adding the following code to your Podfile:\n\n```diff\n- platform :ios, min_ios_version_supported\n\n+ MIN_IOS_OVERRIDE = '13.0'\n+ if Gem::Version.new(MIN_IOS_OVERRIDE) > Gem::Version.new(min_ios_version_supported)\n+   min_ios_version_supported = MIN_IOS_OVERRIDE\n+ end\n```\n\n#### Linking\nIn your project's Podfile, add support for static dependency linking. This is required to support the new Promises subdependency in the iOS Swift conversion.\n\nAdd `use_frameworks! :linkage => :static` right below `platform :ios` in your iOS project Podfile.\n\n[See the example iOS project for reference](https://github.com/TheWidlarzGroup/react-native-video/blob/master/examples/basic/ios/Podfile#L5).\n\n#### Podspec\n\nYou can remove the following lines from your Podfile as they are no longer needed:\n\n```diff\n-  `pod 'react-native-video', :path => '../node_modules/react-native-video/react-native-video.podspec'`\n\n-  `pod 'react-native-video/VideoCaching', :path => '../node_modules/react-native-video/react-native-video.podspec'`\n```\n\nIf you were previously using VideoCaching, you should set the `$RNVideoUseVideoCaching` flag in your Podspec. See the [installation section](https://docs.thewidlarzgroup.com/react-native-video/installation#video-caching) for details.\n\n> **Note:** If you are enabling video caching (using `$RNVideoUseVideoCaching`), you must add the following to your `Gemfile`:\n>\n> ```ruby\n> gem \"cocoapods-swift-modular-headers\"\n> ```\n>\n> Then, install dependencies using:\n>\n> ```sh\n> bundle install\n> bundle exec pod install\n> ```\n>\n> This enables Swift modular headers for Swift dependencies.\n\n### Android\n\nIf you were using ExoPlayer on V5, remove the patch from **android/settings.gradle**:\n\n```diff\n- include ':react-native-video'\n- project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android-exoplayer')\n```\n\n#### Using App Build Settings\nYou need to create a `project.ext` section in the top-level `build.gradle` file (not `app/build.gradle`). Fill in the values from the example below using the ones found in your `app/build.gradle` file.\n\n```groovy\n// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    ... // Various other settings go here\n}\n\nallprojects {\n    ... // Various other settings go here\n\n    project.ext {\n        compileSdkVersion = 31\n        buildToolsVersion = \"30.0.2\"\n\n        minSdkVersion = 21\n        targetSdkVersion = 22\n    }\n}\n```\n\nIf you encounter the error `Could not find com.android.support:support-annotations:27.0.0.`, reinstall your Android Support Repository.\n"
  },
  {
    "path": "docs/versioned_sidebars/version-6.x-sidebars.json",
    "content": "{\n  \"docsSidebar\": [\n    {\n      \"type\": \"autogenerated\",\n      \"dirName\": \".\"\n    },\n    {\n      \"type\": \"html\",\n      \"value\": \"<hr style=\\\"margin: 1rem 0; border: none; border-top: 1px solid var(--ifm-color-emphasis-300);\\\" />\"\n    },\n    {\n      \"type\": \"link\",\n      \"label\": \"Example Apps\",\n      \"href\": \"https://github.com/TheWidlarzGroup/react-native-video/tree/support/6.x.x/examples\"\n    },\n    {\n      \"type\": \"doc\",\n      \"label\": \"Useful Projects\",\n      \"id\": \"projects\"\n    },\n    {\n      \"type\": \"html\",\n      \"value\": \"<hr style=\\\"margin: 1rem 0; border: none; border-top: 1px solid var(--ifm-color-emphasis-300);\\\" />\"\n    },\n    {\n      \"type\": \"link\",\n      \"label\": \"Offline Video SDK\",\n      \"href\": \"https://www.thewidlarzgroup.com/offline-video-sdk/?utm_source=rnv&utm_medium=docs&utm_campaign=sidebar&utm_id=offline-video-sdk-button\"\n    },\n    {\n      \"type\": \"link\",\n      \"label\": \"Enterprise Support\",\n      \"href\": \"https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=navbar&utm_id=enterprise#Contact\"\n    },\n    {\n      \"type\": \"link\",\n      \"label\": \"Boost Your Issue\",\n      \"href\": \"https://www.thewidlarzgroup.com/issue-boost/?utm_source=rnv&utm_medium=docs&utm_campaign=sidebar&utm_id=issue-boost-button\"\n    },\n    {\n      \"type\": \"html\",\n      \"value\": \"<hr style=\\\"margin: 1rem 0; border: none; border-top: 1px solid var(--ifm-color-emphasis-300);\\\" />\"\n    },\n    {\n      \"type\": \"doc\",\n      \"label\": \"Updating\",\n      \"id\": \"updating\"\n    },\n    {\n      \"type\": \"link\",\n      \"label\": \"Changelog\",\n      \"href\": \"https://github.com/TheWidlarzGroup/react-native-video/blob/support/6.x.x/CHANGELOG.md\"\n    }\n  ]\n}\n"
  },
  {
    "path": "docs/versions.json",
    "content": "[\n  \"6.x\"\n]\n"
  },
  {
    "path": "example/.bundle/config",
    "content": "BUNDLE_PATH: \"vendor/bundle\"\nBUNDLE_FORCE_RUBY_PLATFORM: 1\n"
  },
  {
    "path": "example/.eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  extends: [\"../config/.eslintrc.js\"],\n  parserOptions: {\n    tsconfigRootDir: __dirname,\n    project: true,\n  },\n};\n"
  },
  {
    "path": "example/.gitignore",
    "content": "# OSX\n#\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\n**/.xcode.env.local\n\n# Android/IntelliJ\n#\nbuild/\n.idea\n.gradle\nlocal.properties\n*.iml\n*.hprof\n.cxx/\n*.keystore\n!debug.keystore\n\n# node.js\n#\nnode_modules/\nnpm-debug.log\nyarn-error.log\n\n# fastlane\n#\n# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the\n# screenshots whenever they are needed.\n# For more information about the recommended setup visit:\n# https://docs.fastlane.tools/best-practices/source-control/\n\n**/fastlane/report.xml\n**/fastlane/Preview.html\n**/fastlane/screenshots\n**/fastlane/test_output\n\n# Bundle artifact\n*.jsbundle\n\n# Ruby / CocoaPods\n**/Pods/\n/vendor/bundle/\n\n# Temporary files created by Metro to check the health of the file watcher\n.metro-health-check*\n\n# testing\n/coverage\n\n# Yarn\n.yarn/*\n!.yarn/patches\n!.yarn/plugins\n!.yarn/releases\n!.yarn/sdks\n!.yarn/versions\n\n# TypeScript\ntsconfig.tsbuildinfo\n"
  },
  {
    "path": "example/.watchmanconfig",
    "content": "{}\n"
  },
  {
    "path": "example/Gemfile",
    "content": "source 'https://rubygems.org'\n\n# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version\nruby \">= 2.6.10\"\n\n# Exclude problematic versions of cocoapods and activesupport that causes build failures.\ngem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'\ngem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'\ngem 'xcodeproj', '< 1.26.0'\n"
  },
  {
    "path": "example/android/app/build.gradle",
    "content": "apply plugin: \"com.android.application\"\napply plugin: \"org.jetbrains.kotlin.android\"\napply plugin: \"com.facebook.react\"\n\n/**\n * This is the configuration block to customize your React Native Android app.\n * By default you don't need to apply any configuration, just uncomment the lines you need.\n */\nreact {\n    /* Folders */\n    //   The root of your project, i.e. where \"package.json\" lives. Default is '../..'\n    // root = file(\"../../\")\n    //   The folder where the react-native NPM package is. Default is ../../node_modules/react-native\n    reactNativeDir = file(\"../../../node_modules/react-native\")\n    //   The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen\n    codegenDir = file(\"../../../node_modules/@react-native/codegen\")\n    //   The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js\n    cliFile = file(\"../../../node_modules/react-native/cli.js\")\n\n    /* Variants */\n    //   The list of variants to that are debuggable. For those we're going to\n    //   skip the bundling of the JS bundle and the assets. By default is just 'debug'.\n    //   If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.\n    // debuggableVariants = [\"liteDebug\", \"prodDebug\"]\n\n    /* Bundling */\n    //   A list containing the node command and its flags. Default is just 'node'.\n    // nodeExecutableAndArgs = [\"node\"]\n    //\n    //   The command to run when bundling. By default is 'bundle'\n    // bundleCommand = \"ram-bundle\"\n    //\n    //   The path to the CLI configuration file. Default is empty.\n    // bundleConfig = file(../rn-cli.config.js)\n    //\n    //   The name of the generated asset file containing your JS bundle\n    // bundleAssetName = \"MyApplication.android.bundle\"\n    //\n    //   The entry file for bundle generation. Default is 'index.android.js' or 'index.js'\n    // entryFile = file(\"../js/MyApplication.android.js\")\n    //\n    //   A list of extra flags to pass to the 'bundle' commands.\n    //   See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle\n    // extraPackagerArgs = []\n\n    /* Hermes Commands */\n    //   The hermes compiler command to run. By default it is 'hermesc'\n    hermesCommand = \"$rootDir/../../node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc\"\n    //\n    //   The list of flags to pass to the Hermes compiler. By default is \"-O\", \"-output-source-map\"\n    // hermesFlags = [\"-O\", \"-output-source-map\"]\n\n    /* Autolinking */\n    autolinkLibrariesWithApp()\n}\n\n/**\n * Set this to true to Run Proguard on Release builds to minify the Java bytecode.\n */\ndef enableProguardInReleaseBuilds = false\n\n/**\n * The preferred build flavor of JavaScriptCore (JSC)\n *\n * For example, to use the international variant, you can use:\n * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`\n *\n * The international variant includes ICU i18n library and necessary data\n * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that\n * give correct results when using with locales other than en-US. Note that\n * this variant is about 6MiB larger per architecture than default.\n */\ndef jscFlavor = 'org.webkit:android-jsc:+'\n\nandroid {\n    ndkVersion rootProject.ext.ndkVersion\n    buildToolsVersion rootProject.ext.buildToolsVersion\n    compileSdk rootProject.ext.compileSdkVersion\n\n    namespace \"com.twg.videoexample\"\n    defaultConfig {\n        applicationId \"com.twg.videoexample\"\n        minSdkVersion rootProject.ext.minSdkVersion\n        targetSdkVersion rootProject.ext.targetSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    signingConfigs {\n        debug {\n            storeFile file('debug.keystore')\n            storePassword 'android'\n            keyAlias 'androiddebugkey'\n            keyPassword 'android'\n        }\n    }\n    buildTypes {\n        debug {\n            signingConfig signingConfigs.debug\n        }\n        release {\n            // Caution! In production, you need to generate your own keystore file.\n            // see https://reactnative.dev/docs/signed-apk-android.\n            signingConfig signingConfigs.debug\n            minifyEnabled enableProguardInReleaseBuilds\n            proguardFiles getDefaultProguardFile(\"proguard-android.txt\"), \"proguard-rules.pro\"\n        }\n    }\n}\n\ndependencies {\n    // The version of react-native is set by the React Native Gradle Plugin\n    implementation(\"com.facebook.react:react-android\")\n\n    if (hermesEnabled.toBoolean()) {\n        implementation(\"com.facebook.react:hermes-android\")\n    } else {\n        implementation jscFlavor\n    }\n}\n"
  },
  {
    "path": "example/android/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n"
  },
  {
    "path": "example/android/app/src/debug/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <application\n        android:usesCleartextTraffic=\"true\"\n        tools:targetApi=\"28\"\n        tools:ignore=\"GoogleAppIndexingWarning\"/>\n</manifest>\n"
  },
  {
    "path": "example/android/app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <!-- Background Audio -->\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />\n    <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK\" />\n\n    <application\n      android:name=\".MainApplication\"\n      android:label=\"@string/app_name\"\n      android:icon=\"@mipmap/ic_launcher\"\n      android:roundIcon=\"@mipmap/ic_launcher_round\"\n      android:allowBackup=\"false\"\n      android:theme=\"@style/AppTheme\"\n      android:supportsPictureInPicture=\"true\"\n      android:supportsRtl=\"true\">\n      <activity\n        android:supportsPictureInPicture=\"true\"\n        android:name=\".MainActivity\"\n        android:label=\"@string/app_name\"\n        android:configChanges=\"keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode\"\n        android:launchMode=\"singleTask\"\n        android:windowSoftInputMode=\"adjustResize\"\n        android:exported=\"true\">\n        <intent-filter>\n            <action android:name=\"android.intent.action.MAIN\" />\n            <category android:name=\"android.intent.category.LAUNCHER\" />\n        </intent-filter>\n      </activity>\n      <service\n      android:name=\"com.twg.video.core.services.playback.VideoPlaybackService\"\n      android:exported=\"false\"\n      android:foregroundServiceType=\"mediaPlayback\">\n      <intent-filter>\n        <action android:name=\"androidx.media3.session.MediaSessionService\" />\n      </intent-filter>\n    </service>\n    </application>\n</manifest>\n"
  },
  {
    "path": "example/android/app/src/main/java/com/videoexample/MainActivity.kt",
    "content": "package com.twg.videoexample\n\nimport com.facebook.react.ReactActivity\nimport com.facebook.react.ReactActivityDelegate\nimport com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled\nimport com.facebook.react.defaults.DefaultReactActivityDelegate\n\nclass MainActivity : ReactActivity() {\n\n  /**\n   * Returns the name of the main component registered from JavaScript. This is used to schedule\n   * rendering of the component.\n   */\n  override fun getMainComponentName(): String = \"VideoExample\"\n\n  /**\n   * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]\n   * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]\n   */\n  override fun createReactActivityDelegate(): ReactActivityDelegate =\n      DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)\n}\n"
  },
  {
    "path": "example/android/app/src/main/java/com/videoexample/MainApplication.kt",
    "content": "package com.twg.videoexample\n\nimport android.app.Application\nimport com.facebook.react.PackageList\nimport com.facebook.react.ReactApplication\nimport com.facebook.react.ReactHost\nimport com.facebook.react.ReactNativeHost\nimport com.facebook.react.ReactPackage\nimport com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load\nimport com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost\nimport com.facebook.react.defaults.DefaultReactNativeHost\nimport com.facebook.react.soloader.OpenSourceMergedSoMapping\nimport com.facebook.soloader.SoLoader\n\nclass MainApplication : Application(), ReactApplication {\n\n  override val reactNativeHost: ReactNativeHost =\n      object : DefaultReactNativeHost(this) {\n        override fun getPackages(): List<ReactPackage> =\n            PackageList(this).packages.apply {\n              // Packages that cannot be autolinked yet can be added manually here, for example:\n              // add(MyReactNativePackage())\n            }\n\n        override fun getJSMainModuleName(): String = \"index\"\n\n        override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG\n\n        override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED\n        override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED\n      }\n\n  override val reactHost: ReactHost\n    get() = getDefaultReactHost(applicationContext, reactNativeHost)\n\n  override fun onCreate() {\n    super.onCreate()\n    SoLoader.init(this, OpenSourceMergedSoMapping)\n    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {\n      // If you opted-in for the New Architecture, we load the native entry point for this app.\n      load()\n    }\n  }\n}\n"
  },
  {
    "path": "example/android/app/src/main/res/drawable/rn_edit_text_material.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2014 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n<inset xmlns:android=\"http://schemas.android.com/apk/res/android\"\n       android:insetLeft=\"@dimen/abc_edit_text_inset_horizontal_material\"\n       android:insetRight=\"@dimen/abc_edit_text_inset_horizontal_material\"\n       android:insetTop=\"@dimen/abc_edit_text_inset_top_material\"\n       android:insetBottom=\"@dimen/abc_edit_text_inset_bottom_material\"\n       >\n\n    <selector>\n        <!--\n          This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).\n          The item below with state_pressed=\"false\" and state_focused=\"false\" causes a NullPointerException.\n          NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'\n\n          <item android:state_pressed=\"false\" android:state_focused=\"false\" android:drawable=\"@drawable/abc_textfield_default_mtrl_alpha\"/>\n\n          For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.\n        -->\n        <item android:state_enabled=\"false\" android:drawable=\"@drawable/abc_textfield_default_mtrl_alpha\"/>\n        <item android:drawable=\"@drawable/abc_textfield_activated_mtrl_alpha\"/>\n    </selector>\n\n</inset>\n"
  },
  {
    "path": "example/android/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">VideoExample</string>\n</resources>\n"
  },
  {
    "path": "example/android/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.DayNight.NoActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"android:editTextBackground\">@drawable/rn_edit_text_material</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "example/android/build.gradle",
    "content": "buildscript {\n    ext {\n        buildToolsVersion = \"35.0.0\"\n        minSdkVersion = 24\n        compileSdkVersion = 35\n        targetSdkVersion = 34\n        ndkVersion = \"26.1.10909125\"\n        kotlinVersion = \"1.9.24\"\n    }\n    repositories {\n        google()\n        mavenCentral()\n    }\n    dependencies {\n        classpath(\"com.android.tools.build:gradle\")\n        classpath(\"com.facebook.react:react-native-gradle-plugin\")\n        classpath(\"org.jetbrains.kotlin:kotlin-gradle-plugin\")\n    }\n}\n\napply plugin: \"com.facebook.react.rootproject\"\n"
  },
  {
    "path": "example/android/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.10.2-all.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "example/android/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m\norg.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n\n# AndroidX package structure to make it clearer which packages are bundled with the\n# Android operating system, and which are packaged with your app's APK\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\nandroid.useAndroidX=true\n\n# Use this property to specify which architecture you want to build.\n# You can also override it from the CLI using\n# ./gradlew <task> -PreactNativeArchitectures=x86_64\nreactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64\n\n# Use this property to enable support to the new architecture.\n# This will allow you to use TurboModules and the Fabric render in\n# your application. You should enable this flag either if you want\n# to write custom TurboModules/Fabric components OR use libraries that\n# are providing them.\nnewArchEnabled=true\n\n#useExoplayerHls=false\n#useExoplayerDash=false\n\n# Use this property to enable or disable the Hermes JS engine.\n# If set to false, you will be using JSC instead.\nhermesEnabled=true\n"
  },
  {
    "path": "example/android/gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "example/android/gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n@rem SPDX-License-Identifier: Apache-2.0\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "example/android/settings.gradle",
    "content": "pluginManagement { includeBuild(\"../../node_modules/@react-native/gradle-plugin\") }\nplugins { id(\"com.facebook.react.settings\") }\nextensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }\nrootProject.name = 'VideoExample'\ninclude ':app'\nincludeBuild('../../node_modules/@react-native/gradle-plugin')\n"
  },
  {
    "path": "example/app.json",
    "content": "{\n  \"name\": \"VideoExample\",\n  \"displayName\": \"VideoExample\"\n}\n"
  },
  {
    "path": "example/babel.config.js",
    "content": "module.exports = {\n  presets: ['module:@react-native/babel-preset'],\n};\n"
  },
  {
    "path": "example/index.js",
    "content": "/**\n * @format\n */\n\nimport { AppRegistry } from 'react-native';\nimport { name as appName } from './app.json';\nimport App from './src/App';\n\nAppRegistry.registerComponent(appName, () => App);\n"
  },
  {
    "path": "example/ios/.xcode.env",
    "content": "# This `.xcode.env` file is versioned and is used to source the environment\n# used when running script phases inside Xcode.\n# To customize your local environment, you can create an `.xcode.env.local`\n# file that is not versioned.\n\n# NODE_BINARY variable contains the PATH to the node executable.\n#\n# Customize the NODE_BINARY variable here.\n# For example, to use nvm with brew, add the following line\n# . \"$(brew --prefix nvm)/nvm.sh\" --no-use\nexport NODE_BINARY=$(command -v node)\n"
  },
  {
    "path": "example/ios/Podfile",
    "content": "# Resolve react_native_pods.rb with node to allow for hoisting\nrequire Pod::Executable.execute_command('node', ['-p',\n  'require.resolve(\n    \"react-native/scripts/react_native_pods.rb\",\n    {paths: [process.argv[1]]},\n  )', __dir__]).strip\n\nplatform :ios, min_ios_version_supported\nprepare_react_native_project!\n\n\nENV['RCT_NEW_ARCH_ENABLED'] = '1'\nif ENV['RCT_NEW_ARCH_ENABLED'] == '1'\n  Pod::UI.puts \"New Architecture is ENABLED\".green\nelse\n  Pod::UI.puts \"New Architecture is DISABLED\".red\nend\n\nlinkage = ENV['USE_FRAMEWORKS']\nif linkage != nil\n  Pod::UI.puts \"Configuring Pod with #{linkage}ally linked Frameworks\".green\n  use_frameworks! :linkage => linkage.to_sym\nend\n\ntarget 'VideoExample' do\n  config = use_native_modules!\n\n  use_react_native!(\n    :path => config[:reactNativePath],\n    # An absolute path to your application root.\n    :app_path => \"#{Pod::Config.instance.installation_root}/..\"\n  )\n\n  post_install do |installer|\n    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202\n    react_native_post_install(\n      installer,\n      config[:reactNativePath],\n      :mac_catalyst_enabled => false,\n      # :ccache_enabled => true\n    )\n  end\nend\n"
  },
  {
    "path": "example/ios/VideoExample/AppDelegate.swift",
    "content": "//\n//  AppDelegate.swift\n//  VideoExample\n//\n//  Created by Krzysztof Moch on 31/01/2025.\n//\n\n\nimport UIKit\nimport React\nimport React_RCTAppDelegate\nimport ReactAppDependencyProvider\n\n@main\nclass AppDelegate: RCTAppDelegate {\n  override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {\n    self.moduleName = \"VideoExample\"\n    self.dependencyProvider = RCTAppDependencyProvider()\n\n    // You can add your custom initial props in the dictionary below.\n    // They will be passed down to the ViewController used by React Native.\n    self.initialProps = [:]\n\n    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n  }\n\n  override func sourceURL(for bridge: RCTBridge) -> URL? {\n    self.bundleURL()\n  }\n\n  override func bundleURL() -> URL? {\n#if DEBUG\n    RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: \"index\")\n#else\n    Bundle.main.url(forResource: \"main\", withExtension: \"jsbundle\")\n#endif\n  }\n}\n"
  },
  {
    "path": "example/ios/VideoExample/Images.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"60x60\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"60x60\"\n    },\n    {\n      \"idiom\" : \"ios-marketing\",\n      \"scale\" : \"1x\",\n      \"size\" : \"1024x1024\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "example/ios/VideoExample/Images.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "example/ios/VideoExample/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleDisplayName</key>\n\t<string>VideoExample</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<false/>\n\t\t<key>NSAllowsLocalNetworking</key>\n\t\t<true/>\n\t</dict>\n\t<key>NSLocationWhenInUseUsageDescription</key>\n\t<string></string>\n\t<key>UIBackgroundModes</key>\n\t<array>\n\t\t<string>audio</string>\n\t</array>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>arm64</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "example/ios/VideoExample/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"15702\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" useSafeAreas=\"YES\" colorMatched=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <device id=\"retina4_7\" orientation=\"portrait\" appearance=\"light\"/>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"15704\"/>\n        <capability name=\"Safe area layout guides\" minToolsVersion=\"9.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"667\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"VideoExample\" textAlignment=\"center\" lineBreakMode=\"middleTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"GJd-Yh-RWb\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"202\" width=\"375\" height=\"43\"/>\n                                <fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"36\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Powered by React Native\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"9\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"MN2-I3-ftu\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"626\" width=\"375\" height=\"21\"/>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\" cocoaTouchSystemColor=\"whiteColor\"/>\n                        <constraints>\n                            <constraint firstItem=\"Bcu-3y-fUS\" firstAttribute=\"bottom\" secondItem=\"MN2-I3-ftu\" secondAttribute=\"bottom\" constant=\"20\" id=\"OZV-Vh-mqD\"/>\n                            <constraint firstItem=\"Bcu-3y-fUS\" firstAttribute=\"centerX\" secondItem=\"GJd-Yh-RWb\" secondAttribute=\"centerX\" id=\"Q3B-4B-g5h\"/>\n                            <constraint firstItem=\"MN2-I3-ftu\" firstAttribute=\"centerX\" secondItem=\"Bcu-3y-fUS\" secondAttribute=\"centerX\" id=\"akx-eg-2ui\"/>\n                            <constraint firstItem=\"MN2-I3-ftu\" firstAttribute=\"leading\" secondItem=\"Bcu-3y-fUS\" secondAttribute=\"leading\" id=\"i1E-0Y-4RG\"/>\n                            <constraint firstItem=\"GJd-Yh-RWb\" firstAttribute=\"centerY\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"bottom\" multiplier=\"1/3\" constant=\"1\" id=\"moa-c2-u7t\"/>\n                            <constraint firstItem=\"GJd-Yh-RWb\" firstAttribute=\"leading\" secondItem=\"Bcu-3y-fUS\" secondAttribute=\"leading\" symbolic=\"YES\" id=\"x7j-FC-K8j\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"Bcu-3y-fUS\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"52.173913043478265\" y=\"375\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "example/ios/VideoExample/PrivacyInfo.xcprivacy",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>NSPrivacyAccessedAPITypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>C617.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategoryUserDefaults</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>CA92.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>NSPrivacyAccessedAPIType</key>\n\t\t\t<string>NSPrivacyAccessedAPICategorySystemBootTime</string>\n\t\t\t<key>NSPrivacyAccessedAPITypeReasons</key>\n\t\t\t<array>\n\t\t\t\t<string>35F9.1</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n\t<key>NSPrivacyCollectedDataTypes</key>\n\t<array/>\n\t<key>NSPrivacyTracking</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "example/ios/VideoExample-Bridging-Header.h",
    "content": "//\n//  Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n"
  },
  {
    "path": "example/ios/VideoExample.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t00E356F31AD99517003FC87E /* VideoExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* VideoExampleTests.m */; };\n\t\t13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };\n\t\t816A0BB965C7D616166E4A50 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };\n\t\t81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };\n\t\t9B33EFC63F107D31293DC837 /* libPods-VideoExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EC879E2D9A5E3666772BB43B /* libPods-VideoExample.a */; };\n\t\tE24C673A2DA45E9200FB6B41 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E24C67392DA45E9200FB6B41 /* AppDelegate.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 13B07F861A680F5B00A75B9A;\n\t\t\tremoteInfo = VideoExample;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t00E356EE1AD99517003FC87E /* VideoExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VideoExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t00E356F21AD99517003FC87E /* VideoExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VideoExampleTests.m; sourceTree = \"<group>\"; };\n\t\t1296B1F9CB9A72FBF202C0EA /* Pods-VideoExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-VideoExample.debug.xcconfig\"; path = \"Target Support Files/Pods-VideoExample/Pods-VideoExample.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t13B07F961A680F5B00A75B9A /* VideoExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VideoExample.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = VideoExample/Images.xcassets; sourceTree = \"<group>\"; };\n\t\t13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = VideoExample/Info.plist; sourceTree = \"<group>\"; };\n\t\t13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = VideoExample/PrivacyInfo.xcprivacy; sourceTree = \"<group>\"; };\n\t\t81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = VideoExample/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\tAAFF36D6DEC049CEB9D865D8 /* Pods-VideoExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-VideoExample.release.xcconfig\"; path = \"Target Support Files/Pods-VideoExample/Pods-VideoExample.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tE24C67342DA4538300FB6B41 /* VideoExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"VideoExample-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\tE24C67392DA45E9200FB6B41 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = VideoExample/AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\tEC879E2D9A5E3666772BB43B /* libPods-VideoExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = \"libPods-VideoExample.a\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t00E356EB1AD99517003FC87E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F8C1A680F5B00A75B9A /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t9B33EFC63F107D31293DC837 /* libPods-VideoExample.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t00E356EF1AD99517003FC87E /* VideoExampleTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00E356F21AD99517003FC87E /* VideoExampleTests.m */,\n\t\t\t\t00E356F01AD99517003FC87E /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = VideoExampleTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00E356F01AD99517003FC87E /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00E356F11AD99517003FC87E /* Info.plist */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t13B07FAE1A68108700A75B9A /* VideoExample */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tE24C67392DA45E9200FB6B41 /* AppDelegate.swift */,\n\t\t\t\t13B07FB51A68108700A75B9A /* Images.xcassets */,\n\t\t\t\t13B07FB61A68108700A75B9A /* Info.plist */,\n\t\t\t\t81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,\n\t\t\t\t13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,\n\t\t\t\tE24C67342DA4538300FB6B41 /* VideoExample-Bridging-Header.h */,\n\t\t\t);\n\t\t\tname = VideoExample;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t2D16E6871FA4F8E400B85C8A /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tED297162215061F000B7C4FE /* JavaScriptCore.framework */,\n\t\t\t\tEC879E2D9A5E3666772BB43B /* libPods-VideoExample.a */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t832341AE1AAA6A7D00B99B32 /* Libraries */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tname = Libraries;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t83CBB9F61A601CBA00E9B192 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t13B07FAE1A68108700A75B9A /* VideoExample */,\n\t\t\t\t832341AE1AAA6A7D00B99B32 /* Libraries */,\n\t\t\t\t00E356EF1AD99517003FC87E /* VideoExampleTests */,\n\t\t\t\t83CBBA001A601CBA00E9B192 /* Products */,\n\t\t\t\t2D16E6871FA4F8E400B85C8A /* Frameworks */,\n\t\t\t\tBBD78D7AC51CEA395F1C20DB /* Pods */,\n\t\t\t);\n\t\t\tindentWidth = 2;\n\t\t\tsourceTree = \"<group>\";\n\t\t\ttabWidth = 2;\n\t\t\tusesTabs = 0;\n\t\t};\n\t\t83CBBA001A601CBA00E9B192 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t13B07F961A680F5B00A75B9A /* VideoExample.app */,\n\t\t\t\t00E356EE1AD99517003FC87E /* VideoExampleTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBD78D7AC51CEA395F1C20DB /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1296B1F9CB9A72FBF202C0EA /* Pods-VideoExample.debug.xcconfig */,\n\t\t\t\tAAFF36D6DEC049CEB9D865D8 /* Pods-VideoExample.release.xcconfig */,\n\t\t\t);\n\t\t\tpath = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t00E356ED1AD99517003FC87E /* VideoExampleTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget \"VideoExampleTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t00E356EA1AD99517003FC87E /* Sources */,\n\t\t\t\t00E356EB1AD99517003FC87E /* Frameworks */,\n\t\t\t\t00E356EC1AD99517003FC87E /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t00E356F51AD99517003FC87E /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = VideoExampleTests;\n\t\t\tproductName = VideoExampleTests;\n\t\t\tproductReference = 00E356EE1AD99517003FC87E /* VideoExampleTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t13B07F861A680F5B00A75B9A /* VideoExample */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget \"VideoExample\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tFD3671B4534E587DE7FC3AE1 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t13B07F871A680F5B00A75B9A /* Sources */,\n\t\t\t\t13B07F8C1A680F5B00A75B9A /* Frameworks */,\n\t\t\t\t13B07F8E1A680F5B00A75B9A /* Resources */,\n\t\t\t\t00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,\n\t\t\t\t6075DF6F545CCB0D1B44F807 /* [CP] Embed Pods Frameworks */,\n\t\t\t\t5C23AE340DBC4431B262FF5D /* [CP] Copy Pods Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = VideoExample;\n\t\t\tproductName = VideoExample;\n\t\t\tproductReference = 13B07F961A680F5B00A75B9A /* VideoExample.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t83CBB9F71A601CBA00E9B192 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 1210;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t00E356ED1AD99517003FC87E = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.2;\n\t\t\t\t\t\tTestTargetID = 13B07F861A680F5B00A75B9A;\n\t\t\t\t\t};\n\t\t\t\t\t13B07F861A680F5B00A75B9A = {\n\t\t\t\t\t\tLastSwiftMigration = 1630;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject \"VideoExample\" */;\n\t\t\tcompatibilityVersion = \"Xcode 12.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 83CBB9F61A601CBA00E9B192;\n\t\t\tproductRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t13B07F861A680F5B00A75B9A /* VideoExample */,\n\t\t\t\t00E356ED1AD99517003FC87E /* VideoExampleTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t00E356EC1AD99517003FC87E /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F8E1A680F5B00A75B9A /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,\n\t\t\t\t816A0BB965C7D616166E4A50 /* PrivacyInfo.xcprivacy in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"$(SRCROOT)/.xcode.env.local\",\n\t\t\t\t\"$(SRCROOT)/.xcode.env\",\n\t\t\t);\n\t\t\tname = \"Bundle React Native code and images\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"set -e\\n\\nWITH_ENVIRONMENT=\\\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\\\"\\nREACT_NATIVE_XCODE=\\\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\\\"\\n\\n/bin/sh -c \\\"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\\\"\\n\";\n\t\t};\n\t\t5C23AE340DBC4431B262FF5D /* [CP] Copy Pods Resources */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-resources-${CONFIGURATION}-input-files.xcfilelist\",\n\t\t\t);\n\t\t\tname = \"[CP] Copy Pods Resources\";\n\t\t\toutputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-resources-${CONFIGURATION}-output-files.xcfilelist\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-resources.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t6075DF6F545CCB0D1B44F807 /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-frameworks-${CONFIGURATION}-input-files.xcfilelist\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputFileListPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-frameworks-${CONFIGURATION}-output-files.xcfilelist\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tFD3671B4534E587DE7FC3AE1 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-VideoExample-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\\necho \\\"SUCCESS\\\" > \\\"${SCRIPT_OUTPUT_FILE_0}\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t00E356EA1AD99517003FC87E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t00E356F31AD99517003FC87E /* VideoExampleTests.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F871A680F5B00A75B9A /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tE24C673A2DA45E9200FB6B41 /* AppDelegate.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t00E356F51AD99517003FC87E /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 13B07F861A680F5B00A75B9A /* VideoExample */;\n\t\t\ttargetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\t00E356F61AD99517003FC87E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = VideoExampleTests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.1;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@loader_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/VideoExample.app/VideoExample\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t00E356F71AD99517003FC87E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tINFOPLIST_FILE = VideoExampleTests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.1;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t\t\"@loader_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/VideoExample.app/VideoExample\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t13B07F941A680F5B00A75B9A /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 1296B1F9CB9A72FBF202C0EA /* Pods-VideoExample.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = QQRD9CKGZW;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tINFOPLIST_FILE = VideoExample/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.1;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)\";\n\t\t\t\t\"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]\" = org.reactjs.native.example.VideoExample.pip;\n\t\t\t\tPRODUCT_NAME = VideoExample;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"VideoExample-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t13B07F951A680F5B00A75B9A /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = AAFF36D6DEC049CEB9D865D8 /* Pods-VideoExample.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = QQRD9CKGZW;\n\t\t\t\tINFOPLIST_FILE = VideoExample/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.1;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)\";\n\t\t\t\t\"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]\" = org.reactjs.native.example.VideoExample.pip;\n\t\t\t\tPRODUCT_NAME = VideoExample;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"VideoExample-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t83CBBA201A601CBA00E9B192 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++20\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\t\"EXCLUDED_ARCHS[sdk=iphonesimulator*]\" = \"\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.1;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t/usr/lib/swift,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"\\\"$(SDKROOT)/usr/lib/swift\\\"\",\n\t\t\t\t\t\"\\\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\\\"\",\n\t\t\t\t\t\"\\\"$(inherited)\\\"\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-DFOLLY_NO_CONFIG\",\n\t\t\t\t\t\"-DFOLLY_MOBILE=1\",\n\t\t\t\t\t\"-DFOLLY_USE_LIBCPP=1\",\n\t\t\t\t\t\"-DFOLLY_CFG_NO_COROUTINES=1\",\n\t\t\t\t\t\"-DFOLLY_HAVE_CLOCK_GETTIME=1\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\" \",\n\t\t\t\t);\n\t\t\t\tREACT_NATIVE_PATH = \"${PODS_ROOT}/../../../node_modules/react-native\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = \"$(inherited) DEBUG\";\n\t\t\t\tUSE_HERMES = true;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t83CBBA211A601CBA00E9B192 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++20\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\t\"EXCLUDED_ARCHS[sdk=iphonesimulator*]\" = \"\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.1;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t/usr/lib/swift,\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"\\\"$(SDKROOT)/usr/lib/swift\\\"\",\n\t\t\t\t\t\"\\\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\\\"\",\n\t\t\t\t\t\"\\\"$(inherited)\\\"\",\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tOTHER_CPLUSPLUSFLAGS = (\n\t\t\t\t\t\"$(OTHER_CFLAGS)\",\n\t\t\t\t\t\"-DFOLLY_NO_CONFIG\",\n\t\t\t\t\t\"-DFOLLY_MOBILE=1\",\n\t\t\t\t\t\"-DFOLLY_USE_LIBCPP=1\",\n\t\t\t\t\t\"-DFOLLY_CFG_NO_COROUTINES=1\",\n\t\t\t\t\t\"-DFOLLY_HAVE_CLOCK_GETTIME=1\",\n\t\t\t\t);\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\" \",\n\t\t\t\t);\n\t\t\t\tREACT_NATIVE_PATH = \"${PODS_ROOT}/../../../node_modules/react-native\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tUSE_HERMES = true;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget \"VideoExampleTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t00E356F61AD99517003FC87E /* Debug */,\n\t\t\t\t00E356F71AD99517003FC87E /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget \"VideoExample\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t13B07F941A680F5B00A75B9A /* Debug */,\n\t\t\t\t13B07F951A680F5B00A75B9A /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject \"VideoExample\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t83CBBA201A601CBA00E9B192 /* Debug */,\n\t\t\t\t83CBBA211A601CBA00E9B192 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;\n}\n"
  },
  {
    "path": "example/ios/VideoExample.xcodeproj/xcshareddata/xcschemes/VideoExample.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1210\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n               BuildableName = \"VideoExample.app\"\n               BlueprintName = \"VideoExample\"\n               ReferencedContainer = \"container:VideoExample.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"00E356ED1AD99517003FC87E\"\n               BuildableName = \"VideoExampleTests.xctest\"\n               BlueprintName = \"VideoExampleTests\"\n               ReferencedContainer = \"container:VideoExample.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n            BuildableName = \"VideoExample.app\"\n            BlueprintName = \"VideoExample\"\n            ReferencedContainer = \"container:VideoExample.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n            BuildableName = \"VideoExample.app\"\n            BlueprintName = \"VideoExample\"\n            ReferencedContainer = \"container:VideoExample.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "example/ios/VideoExample.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:VideoExample.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Pods/Pods.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "example/ios/VideoExampleTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "example/ios/VideoExampleTests/VideoExampleTests.m",
    "content": "#import <UIKit/UIKit.h>\n#import <XCTest/XCTest.h>\n\n#import <React/RCTLog.h>\n#import <React/RCTRootView.h>\n\n#define TIMEOUT_SECONDS 600\n#define TEXT_TO_LOOK_FOR @\"Welcome to React\"\n\n@interface VideoExampleTests : XCTestCase\n\n@end\n\n@implementation VideoExampleTests\n\n- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test\n{\n  if (test(view)) {\n    return YES;\n  }\n  for (UIView *subview in [view subviews]) {\n    if ([self findSubviewInView:subview matching:test]) {\n      return YES;\n    }\n  }\n  return NO;\n}\n\n- (void)testRendersWelcomeScreen\n{\n  UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];\n  NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];\n  BOOL foundElement = NO;\n\n  __block NSString *redboxError = nil;\n#ifdef DEBUG\n  RCTSetLogFunction(\n      ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {\n        if (level >= RCTLogLevelError) {\n          redboxError = message;\n        }\n      });\n#endif\n\n  while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {\n    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];\n    [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];\n\n    foundElement = [self findSubviewInView:vc.view\n                                  matching:^BOOL(UIView *view) {\n                                    if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {\n                                      return YES;\n                                    }\n                                    return NO;\n                                  }];\n  }\n\n#ifdef DEBUG\n  RCTSetLogFunction(RCTDefaultLogFunction);\n#endif\n\n  XCTAssertNil(redboxError, @\"RedBox error: %@\", redboxError);\n  XCTAssertTrue(foundElement, @\"Couldn't find element with text '%@' in %d seconds\", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);\n}\n\n@end\n"
  },
  {
    "path": "example/metro.config.js",
    "content": "const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\nconst path = require('path');\nconst escape = require('escape-string-regexp');\nconst exclusionList = require('metro-config/src/defaults/exclusionList');\nconst pak = require('../package.json');\n\nconst root = path.resolve(__dirname, '..');\nconst modules = Object.keys({\n  ...pak.peerDependencies,\n});\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {\n  watchFolders: [root],\n  resolver: {\n    blacklistRE: exclusionList(\n      modules.map(\n        (m) =>\n          new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\\\/.*$`)\n      )\n    ),\n    extraNodeModules: modules.reduce((acc, name) => {\n      acc[name] = path.join(__dirname, 'node_modules', name);\n      return acc;\n    }, {}),\n  },\n  transformer: {\n    getTransformOptions: async () => ({\n      transform: {\n        experimentalImportSupport: false,\n        inlineRequires: true,\n      },\n    }),\n  },\n};\n\nmodule.exports = mergeConfig(getDefaultConfig(__dirname), config);\n"
  },
  {
    "path": "example/package.json",
    "content": "{\n  \"name\": \"react-native-video-example\",\n  \"version\": \"7.0.0-beta.7\",\n  \"private\": true,\n  \"scripts\": {\n    \"android\": \"react-native run-android\",\n    \"ios\": \"react-native run-ios\",\n    \"lint\": \"eslint .\",\n    \"typecheck\": \"tsc\",\n    \"start\": \"react-native start --client-logs\",\n    \"bundle-install\": \"bundle install\",\n    \"pods\": \"cd ios && pod install && cd ..\"\n  },\n  \"dependencies\": {\n    \"@react-native-community/slider\": \"^4.5.6\",\n    \"react\": \"18.3.1\",\n    \"react-native\": \"^0.77.0\",\n    \"react-native-nitro-modules\": \"0.35.0\",\n    \"react-native-video\": \"*\",\n    \"@react-native-video/drm\": \"*\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.25.2\",\n    \"@babel/preset-env\": \"^7.25.3\",\n    \"@babel/runtime\": \"^7.25.0\",\n    \"@react-native-community/cli\": \"15.0.1\",\n    \"@react-native-community/cli-platform-android\": \"15.0.1\",\n    \"@react-native-community/cli-platform-ios\": \"15.0.1\",\n    \"@react-native/babel-preset\": \"^0.77.0\",\n    \"@react-native/eslint-config\": \"^0.77.0\",\n    \"@react-native/metro-config\": \"^0.77.0\",\n    \"@react-native/typescript-config\": \"^0.77.0\",\n    \"@types/react\": \"^18.2.44\",\n    \"eslint\": \"^8.51.0\",\n    \"prettier\": \"^3.0.3\",\n    \"typescript\": \"^5.2.2\"\n  },\n  \"engines\": {\n    \"node\": \">=18\"\n  }\n}\n"
  },
  {
    "path": "example/src/App.tsx",
    "content": "import Slider from '@react-native-community/slider';\nimport React from 'react';\nimport { Alert, SafeAreaView, ScrollView, Text, View } from 'react-native';\nimport {\n  type VideoConfig,\n  type VideoPlayerStatus,\n  VideoView,\n  type VideoViewRef,\n  type onLoadData,\n  type onProgressData,\n  type onVolumeChangeData,\n  useEvent,\n  useVideoPlayer,\n} from 'react-native-video';\nimport {\n  ActionButton,\n  ControlButton,\n  SwitchControl,\n  ToggleButton,\n} from './components/Controls';\nimport TextTrackManager from './components/TextTrackManager';\nimport { styles } from './styles';\nimport { type VideoSettings, defaultSettings } from './types/videoSettings';\nimport { formatTime } from './utils/time';\nimport { getVideoSource } from './utils/videoSource';\n\nconst VideoDemo = () => {\n  const videoViewRef = React.useRef<VideoViewRef>(null);\n  const [settings, setSettings] =\n    React.useState<VideoSettings>(defaultSettings);\n  const [progress, setProgress] = React.useState(0);\n  const [events, setEvents] = React.useState<\n    Array<{ id: string; message: string; timestamp: string }>\n  >([]);\n\n  const updateSetting = <K extends keyof VideoSettings>(\n    key: K,\n    value: VideoSettings[K]\n  ) => {\n    setSettings((prev) => ({ ...prev, [key]: value }));\n  };\n\n  const addEvent = React.useCallback((message: string) => {\n    const newEvent = {\n      id: `${Date.now()}-${Math.random()}`,\n      message,\n      timestamp: new Date().toLocaleTimeString(),\n    };\n    setEvents((prev) => [newEvent, ...prev.slice(0, 49)]);\n  }, []);\n\n  const handleFullscreenChange = React.useCallback(\n    (fullscreen: boolean) => {\n      addEvent(\n        'View: onFullscreenChange ' + (fullscreen ? 'entered' : 'exited')\n      );\n    },\n    [addEvent]\n  );\n\n  const handlePictureInPictureChange = React.useCallback(\n    (pipEnabled: boolean) => {\n      addEvent(\n        'View: onPictureInPictureChange ' + (pipEnabled ? 'entered' : 'exited')\n      );\n    },\n    [addEvent]\n  );\n\n  const handlePlayerEnd = React.useCallback(() => {\n    addEvent('Player: onEnd');\n  }, [addEvent]);\n\n  const handlePlayerLoad = React.useCallback(\n    (_data: onLoadData) => {\n      addEvent('Player: onLoad');\n    },\n    [addEvent]\n  );\n\n  const handlePlayerBuffer = React.useCallback(\n    (buffering: boolean) => {\n      addEvent('Player: onBuffer ' + buffering);\n    },\n    [addEvent]\n  );\n\n  const handlePlayerProgress = React.useCallback((data: onProgressData) => {\n    setProgress(data.currentTime);\n  }, []);\n\n  const handlePlayerStatusChange = React.useCallback(\n    (status: VideoPlayerStatus) => {\n      addEvent('Player: onStatusChange ' + status);\n    },\n    [addEvent]\n  );\n\n  const handlePlayerSeek = React.useCallback(\n    (time: number) => {\n      addEvent(`Player: onSeek ${time.toFixed(2)}s`);\n    },\n    [addEvent]\n  );\n\n  const handlePlayerStateChange = React.useCallback(\n    (state: { isPlaying: boolean; isBuffering: boolean }) => {\n      addEvent(\n        `Player: onPlaybackStateChange isPlaying=${state.isPlaying}, isBuffering=${state.isBuffering}`\n      );\n    },\n    [addEvent]\n  );\n\n  const handleVolumeChange = React.useCallback(\n    ({ muted, volume }: onVolumeChangeData) => {\n      addEvent(`Player: onVolumeChange ${volume.toFixed(2)} isMuted=${muted}`);\n    },\n    [addEvent]\n  );\n\n  const player = useVideoPlayer(\n    getVideoSource(defaultSettings.videoType),\n    (_player) => {\n      player.seekTo(1);\n    }\n  );\n\n  useEvent(player, 'onEnd', handlePlayerEnd);\n  useEvent(player, 'onLoad', handlePlayerLoad);\n  useEvent(player, 'onBuffer', handlePlayerBuffer);\n  useEvent(player, 'onProgress', handlePlayerProgress);\n  useEvent(player, 'onStatusChange', handlePlayerStatusChange);\n  useEvent(player, 'onSeek', handlePlayerSeek);\n  useEvent(player, 'onPlaybackStateChange', handlePlayerStateChange);\n  useEvent(player, 'onVolumeChange', handleVolumeChange);\n\n  React.useEffect(() => {\n    player.volume = settings.volume;\n    player.muted = settings.muted;\n\n    if (player.isPlaying) {\n      player.rate = settings.rate;\n    }\n\n    player.loop = settings.loop;\n    player.playInBackground = settings.playInBackground;\n    player.playWhenInactive = settings.playWhenInactive;\n    player.mixAudioMode = settings.mixAudioMode;\n    player.ignoreSilentSwitchMode = settings.ignoreSilentSwitchMode;\n    player.showNotificationControls = settings.showNotificationControls;\n  }, [settings, player]);\n\n  const handleSeek = (val: number) => {\n    player.seekTo(val);\n    setProgress(val);\n  };\n\n  return (\n    <ScrollView style={styles.container}>\n      <View style={styles.videoContainer}>\n        {settings.show ? (\n          <VideoView\n            player={player}\n            style={styles.video}\n            ref={videoViewRef}\n            controls={settings.showNativeControls}\n            pictureInPicture={true}\n            autoEnterPictureInPicture={true}\n            onFullscreenChange={handleFullscreenChange}\n            onPictureInPictureChange={handlePictureInPictureChange}\n            resizeMode={settings.resizeMode}\n          />\n        ) : (\n          <View style={styles.hiddenVideo}>\n            <Text style={styles.hiddenVideoText}>Video Hidden</Text>\n          </View>\n        )}\n      </View>\n\n      <View style={styles.section}>\n        <View style={styles.progressRow}>\n          <Text style={styles.timeText}>{formatTime(progress)}</Text>\n          <Slider\n            style={styles.progressSlider}\n            minimumValue={0}\n            maximumValue={isNaN(player.duration) ? 1 : player.duration}\n            value={progress}\n            onSlidingComplete={handleSeek}\n            minimumTrackTintColor=\"#007aff\"\n            maximumTrackTintColor=\"#e1e1e1\"\n            thumbTintColor=\"#007aff\"\n          />\n          <Text style={styles.timeText}>{formatTime(player.duration)}</Text>\n        </View>\n      </View>\n\n      <View style={styles.section}>\n        <View style={styles.transportRow}>\n          <ControlButton icon=\"⏮\" onPress={() => player.seekTo(0)} />\n          <ControlButton icon=\"⏪\" onPress={() => player.seekBy(-10)} />\n          <ControlButton\n            icon=\"⏯\"\n            onPress={() => (player.isPlaying ? player.pause() : player.play())}\n            size=\"large\"\n          />\n          <ControlButton icon=\"⏩\" onPress={() => player.seekBy(10)} />\n        </View>\n        <Text style={styles.subSectionTitle}>Video Type</Text>\n        <View style={styles.buttonGroup}>\n          {(['hls', 'mp4', 'drm'] as const).map((mode) => (\n            <ToggleButton\n              key={mode}\n              label={mode}\n              active={settings.videoType === mode}\n              onPress={async () => {\n                updateSetting('videoType', mode);\n                try {\n                  await player.replaceSourceAsync(getVideoSource(mode));\n                } catch (error) {\n                  console.error('Error replacing source:', error);\n                }\n              }}\n            />\n          ))}\n        </View>\n      </View>\n\n      <View style={styles.section}>\n        <Text style={styles.sectionTitle}>Display Settings</Text>\n\n        <View style={styles.switchRow}>\n          <SwitchControl\n            label=\"Show Video\"\n            value={settings.show}\n            onValueChange={(value) => updateSetting('show', value)}\n          />\n          <SwitchControl\n            label=\"Native Controls\"\n            value={settings.showNativeControls}\n            onValueChange={(value) =>\n              updateSetting('showNativeControls', value)\n            }\n          />\n        </View>\n\n        <Text style={styles.subSectionTitle}>Resize Mode</Text>\n        <View style={styles.buttonGroup}>\n          {(['contain', 'cover', 'stretch', 'none'] as const).map((mode) => (\n            <ToggleButton\n              key={mode}\n              label={mode}\n              active={settings.resizeMode === mode}\n              onPress={() => updateSetting('resizeMode', mode)}\n            />\n          ))}\n        </View>\n      </View>\n\n      <View style={styles.section}>\n        <Text style={styles.sectionTitle}>Audio Controls</Text>\n        <View style={styles.audioControls}>\n          <View style={styles.sliderControl}>\n            <Text style={styles.controlLabel}>Volume</Text>\n            <Slider\n              style={styles.slider}\n              minimumValue={0}\n              maximumValue={1}\n              value={settings.volume}\n              step={0.01}\n              onValueChange={(value) => updateSetting('volume', value)}\n              minimumTrackTintColor=\"#007aff\"\n              maximumTrackTintColor=\"#e1e1e1\"\n              thumbTintColor=\"#007aff\"\n            />\n            <Text style={styles.valueText}>\n              {Math.round(settings.volume * 100)}%\n            </Text>\n          </View>\n\n          <View style={styles.sliderControl}>\n            <Text style={styles.controlLabel}>Speed</Text>\n            <Slider\n              style={styles.slider}\n              minimumValue={0.25}\n              maximumValue={2}\n              value={settings.rate}\n              step={0.25}\n              onValueChange={(value) => updateSetting('rate', value)}\n              minimumTrackTintColor=\"#007aff\"\n              maximumTrackTintColor=\"#e1e1e1\"\n              thumbTintColor=\"#007aff\"\n            />\n            <Text style={styles.valueText}>{settings.rate}x</Text>\n          </View>\n        </View>\n\n        <View style={styles.switchRow}>\n          <SwitchControl\n            label=\"Muted\"\n            value={settings.muted}\n            onValueChange={(value) => updateSetting('muted', value)}\n          />\n          <SwitchControl\n            label=\"Loop\"\n            value={settings.loop}\n            onValueChange={(value) => updateSetting('loop', value)}\n          />\n        </View>\n      </View>\n\n      <View style={styles.section}>\n        <Text style={styles.sectionTitle}>Background Playback</Text>\n        <View style={styles.switchColumn}>\n          <SwitchControl\n            label=\"Play in Background\"\n            value={settings.playInBackground}\n            onValueChange={(value) => updateSetting('playInBackground', value)}\n          />\n          <SwitchControl\n            label=\"Play When Inactive\"\n            value={settings.playWhenInactive}\n            onValueChange={(value) => updateSetting('playWhenInactive', value)}\n          />\n          <SwitchControl\n            label=\"Notification Controls\"\n            value={settings.showNotificationControls}\n            onValueChange={(value) =>\n              updateSetting('showNotificationControls', value)\n            }\n          />\n        </View>\n      </View>\n\n      <View style={styles.section}>\n        <Text style={styles.sectionTitle}>Audio Settings</Text>\n\n        <Text style={styles.subSectionTitle}>Mix Audio Mode</Text>\n        <View style={styles.buttonGroup}>\n          {(['mixWithOthers', 'doNotMix', 'duckOthers', 'auto'] as const).map(\n            (mode) => (\n              <ToggleButton\n                key={mode}\n                label={mode}\n                active={settings.mixAudioMode === mode}\n                onPress={() => updateSetting('mixAudioMode', mode)}\n              />\n            )\n          )}\n        </View>\n\n        <Text style={styles.subSectionTitle}>Silent Switch Mode</Text>\n        <View style={styles.buttonGroup}>\n          {(['auto', 'ignore', 'obey'] as const).map((mode) => (\n            <ToggleButton\n              key={mode}\n              label={mode}\n              active={settings.ignoreSilentSwitchMode === mode}\n              onPress={() => updateSetting('ignoreSilentSwitchMode', mode)}\n            />\n          ))}\n        </View>\n      </View>\n\n      <View style={styles.section}>\n        <Text style={styles.sectionTitle}>Text Tracks</Text>\n        <TextTrackManager player={player} />\n      </View>\n\n      <View style={styles.section}>\n        <Text style={styles.sectionTitle}>Advanced Controls</Text>\n\n        <View style={styles.actionGrid}>\n          <ActionButton\n            label=\"Preload\"\n            onPress={() => player.preload().catch(console.error)}\n          />\n          <ActionButton\n            label=\"Replace Source\"\n            onPress={() => {\n              const newSource = {\n                uri: 'https://playertest.longtailvideo.com/adaptive/elephants_dream_v4/index.m3u8',\n                externalSubtitles: [\n                  {\n                    uri: 'https://bitdash-a.akamaihd.net/content/sintel/subtitles/subtitles_en.vtt',\n                    label: 'External English',\n                    language: 'en',\n                    type: 'vtt',\n                  },\n                  {\n                    uri: 'https://bitdash-a.akamaihd.net/content/sintel/subtitles/subtitles_fr.vtt',\n                    label: 'External French',\n                    language: 'External French',\n                    type: 'vtt',\n                  },\n                ],\n              } satisfies VideoConfig;\n              player.replaceSourceAsync(newSource);\n            }}\n          />\n          <ActionButton\n            label=\"Get Source Asset Info\"\n            onPress={() => {\n              player.source\n                .getAssetInformationAsync()\n                .then((info) => {\n                  console.log('Asset info:', info);\n                })\n                .catch((error) => {\n                  console.error('Error getting asset info:', error);\n                });\n            }}\n          />\n          <ActionButton\n            label=\"Enter Fullscreen\"\n            onPress={() => {\n              if (videoViewRef.current) {\n                videoViewRef.current.enterFullscreen();\n              } else {\n                Alert.alert('No video view found');\n              }\n            }}\n          />\n          <ActionButton\n            label=\"Enter PiP\"\n            onPress={() => {\n              if (videoViewRef.current) {\n                videoViewRef.current.enterPictureInPicture();\n              } else {\n                Alert.alert('No video view found');\n              }\n            }}\n          />\n        </View>\n      </View>\n\n      <View style={styles.section}>\n        <Text style={styles.sectionTitle}>Event Log</Text>\n        <View style={styles.eventLog}>\n          <ScrollView\n            style={styles.eventLogScroll}\n            showsVerticalScrollIndicator={true}\n          >\n            {events.length === 0 ? (\n              <Text style={styles.eventText}>No events yet</Text>\n            ) : (\n              events.map((event) => (\n                <View key={event.id} style={styles.eventItem}>\n                  <Text style={styles.eventTime}>{event.timestamp}</Text>\n                  <Text style={styles.eventText}>{event.message}</Text>\n                </View>\n              ))\n            )}\n          </ScrollView>\n        </View>\n      </View>\n    </ScrollView>\n  );\n};\n\nexport default function App() {\n  const [mounted, setMounted] = React.useState(true);\n\n  return (\n    <SafeAreaView style={styles.app}>\n      {mounted && <VideoDemo />}\n      <View style={styles.mountControl}>\n        <ActionButton\n          label={mounted ? 'Unmount Demo' : 'Mount Demo'}\n          onPress={() => setMounted((prev) => !prev)}\n        />\n      </View>\n    </SafeAreaView>\n  );\n}\n"
  },
  {
    "path": "example/src/components/Controls.tsx",
    "content": "import React from 'react';\nimport { Switch, Text, TouchableOpacity, View } from 'react-native';\nimport { styles } from '../styles';\n\nexport const ControlButton = ({\n  icon,\n  onPress,\n  size = 'normal',\n}: {\n  icon: string;\n  onPress: () => void;\n  size?: 'normal' | 'large';\n}) => (\n  <TouchableOpacity\n    style={[\n      styles.controlButton,\n      size === 'large' && styles.controlButtonLarge,\n    ]}\n    onPress={onPress}\n  >\n    <Text\n      style={[styles.controlIcon, size === 'large' && styles.controlIconLarge]}\n    >\n      {icon}\n    </Text>\n  </TouchableOpacity>\n);\n\nexport const SwitchControl = ({\n  label,\n  value,\n  onValueChange,\n}: {\n  label: string;\n  value: boolean;\n  onValueChange: (value: boolean) => void;\n}) => (\n  <View style={styles.switchControl}>\n    <Text style={styles.switchLabel}>{label}</Text>\n    <Switch\n      value={value}\n      onValueChange={onValueChange}\n      trackColor={{ false: '#e1e1e1', true: '#007aff' }}\n      thumbColor={value ? '#ffffff' : '#f4f3f4'}\n    />\n  </View>\n);\n\nexport const ToggleButton = ({\n  label,\n  active,\n  onPress,\n}: {\n  label: string;\n  active: boolean;\n  onPress: () => void;\n}) => (\n  <TouchableOpacity\n    style={[styles.toggleButton, active && styles.toggleButtonActive]}\n    onPress={onPress}\n  >\n    <Text\n      style={[styles.toggleButtonText, active && styles.toggleButtonTextActive]}\n    >\n      {label}\n    </Text>\n  </TouchableOpacity>\n);\n\nexport const ActionButton = ({\n  label,\n  onPress,\n}: {\n  label: string;\n  onPress: () => void;\n}) => (\n  <TouchableOpacity style={styles.actionButton} onPress={onPress}>\n    <Text style={styles.actionButtonText}>{label}</Text>\n  </TouchableOpacity>\n);\n"
  },
  {
    "path": "example/src/components/TextTrackManager.tsx",
    "content": "import React from 'react';\nimport { Text, TouchableOpacity, View } from 'react-native';\nimport { useEvent, type TextTrack, type VideoPlayer } from 'react-native-video';\nimport { styles } from '../styles';\nimport { ActionButton } from './Controls';\n\nexport const TextTrackManager = ({ player }: { player: VideoPlayer }) => {\n  const [textTracks, setTextTracks] = React.useState<TextTrack[]>([]);\n  const [selectedTrackId, setSelectedTrackId] = React.useState<string | null>(\n    null\n  );\n  const [currentSelectedTrack, setCurrentSelectedTrack] =\n    React.useState<TextTrack | null>(null);\n  const [trackChangeEvents, setTrackChangeEvents] = React.useState<string[]>(\n    []\n  );\n\n  const loadTextTracks = React.useCallback(() => {\n    try {\n      const tracks = player.getAvailableTextTracks();\n      setTextTracks(tracks);\n\n      const selectedTrack = player.selectedTrack;\n      setSelectedTrackId(selectedTrack?.id || null);\n      setCurrentSelectedTrack(selectedTrack || null);\n    } catch (error) {\n      console.error('Error loading text tracks:', error);\n    }\n  }, [player]);\n\n  const selectTrack = React.useCallback(\n    (track: TextTrack) => {\n      try {\n        player.selectTextTrack(track);\n      } catch (error) {\n        console.error('Error selecting text track:', error);\n      }\n    },\n    [player]\n  );\n\n  const disableTextTracks = React.useCallback(() => {\n    try {\n      player.selectTextTrack(null);\n    } catch (error) {\n      console.error('Error disabling text tracks:', error);\n    }\n  }, [player]);\n\n  useEvent(player, 'onReadyToDisplay', () => {\n    loadTextTracks();\n  });\n\n  useEvent(player, 'onTrackChange', (track) => {\n    setCurrentSelectedTrack(track);\n    setSelectedTrackId(track?.id || null);\n\n    const timestamp = new Date().toLocaleTimeString();\n    const eventMessage = track\n      ? `${timestamp}: Track changed to \"${track.label}\" (${track.id})${track.id.startsWith('external-') ? ' [External]' : ''}`\n      : `${timestamp}: All tracks disabled`;\n\n    setTrackChangeEvents((prev) => [eventMessage, ...prev.slice(0, 4)]);\n  });\n\n  return (\n    <View>\n      <View style={styles.buttonGroup}>\n        <ActionButton label=\"Refresh Tracks\" onPress={loadTextTracks} />\n        <ActionButton label=\"Disable Tracks\" onPress={disableTextTracks} />\n        <ActionButton\n          label=\"Sync Selection\"\n          onPress={() => {\n            try {\n              const selectedTrack = player.selectedTrack;\n              setCurrentSelectedTrack(selectedTrack || null);\n              setSelectedTrackId(selectedTrack?.id || null);\n            } catch (error) {\n              console.error('Error syncing selection:', error);\n            }\n          }}\n        />\n      </View>\n\n      {currentSelectedTrack && (\n        <View style={styles.selectedTrackInfo}>\n          <Text style={styles.selectedTrackLabel}>Currently Selected:</Text>\n          <Text style={styles.selectedTrackText}>\n            {currentSelectedTrack.label}\n            {currentSelectedTrack.language &&\n              ` (${currentSelectedTrack.language})`}\n            {currentSelectedTrack.id.startsWith('external-') && ' [External]'}\n          </Text>\n        </View>\n      )}\n\n      {trackChangeEvents.length > 0 && (\n        <View style={styles.eventLogContainer}>\n          <Text style={styles.eventLogTitle}>Track Change Events:</Text>\n          {trackChangeEvents.map((event, index) => (\n            <Text key={index} style={styles.eventLogText}>\n              {event}\n            </Text>\n          ))}\n        </View>\n      )}\n\n      {textTracks.length > 0 ? (\n        <View style={styles.trackList}>\n          <Text style={styles.subSectionTitle}>\n            Available Tracks ({textTracks.length})\n          </Text>\n          {textTracks.map((track) => (\n            <TouchableOpacity\n              key={track.id}\n              style={[\n                styles.trackButton,\n                selectedTrackId === track.id && styles.trackButtonSelected,\n              ]}\n              onPress={() => selectTrack(track)}\n            >\n              <Text\n                style={[\n                  styles.trackButtonText,\n                  selectedTrackId === track.id &&\n                    styles.trackButtonTextSelected,\n                ]}\n              >\n                {track.label} {track.language && `(${track.language})`}\n                {track.selected && ' ✓'}\n                {track.id.startsWith('external-') && ' [External]'}\n              </Text>\n            </TouchableOpacity>\n          ))}\n        </View>\n      ) : (\n        <View>\n          <Text style={styles.noTracksText}>No text tracks available</Text>\n          <Text style={styles.noTracksSubText}>\n            Make sure the video is loaded. External subtitles are loaded but not\n            automatically enabled - you need to select them manually.\n          </Text>\n        </View>\n      )}\n    </View>\n  );\n};\n\nexport default TextTrackManager;\n"
  },
  {
    "path": "example/src/styles.ts",
    "content": "import { StyleSheet } from 'react-native';\n\nexport const styles = StyleSheet.create({\n  app: {\n    flex: 1,\n    backgroundColor: '#f8f9fa',\n  },\n  container: {\n    flex: 1,\n    padding: 16,\n  },\n  videoContainer: {\n    width: '100%',\n    aspectRatio: 16 / 9,\n    backgroundColor: '#000',\n    borderRadius: 12,\n    overflow: 'hidden',\n    marginBottom: 16,\n    elevation: 3,\n    shadowColor: '#000',\n    shadowOffset: { width: 0, height: 2 },\n    shadowOpacity: 0.1,\n    shadowRadius: 4,\n  },\n  video: {\n    width: '100%',\n    height: '100%',\n  },\n  hiddenVideo: {\n    width: '100%',\n    height: '100%',\n    backgroundColor: '#333',\n    alignItems: 'center',\n    justifyContent: 'center',\n  },\n  hiddenVideoText: {\n    color: '#fff',\n    fontSize: 18,\n    fontWeight: '600',\n  },\n  section: {\n    backgroundColor: '#fff',\n    borderRadius: 12,\n    padding: 16,\n    marginBottom: 12,\n    elevation: 1,\n    shadowColor: '#000',\n    shadowOffset: { width: 0, height: 1 },\n    shadowOpacity: 0.05,\n    shadowRadius: 2,\n  },\n  sectionTitle: {\n    fontSize: 18,\n    fontWeight: '700',\n    color: '#1a1a1a',\n    marginBottom: 12,\n  },\n  subSectionTitle: {\n    fontSize: 14,\n    fontWeight: '600',\n    color: '#666',\n    marginTop: 12,\n    marginBottom: 8,\n  },\n  progressRow: {\n    flexDirection: 'row',\n    alignItems: 'center',\n  },\n  progressSlider: {\n    flex: 1,\n    marginHorizontal: 12,\n  },\n  timeText: {\n    fontSize: 14,\n    fontWeight: '600',\n    color: '#666',\n    width: 50,\n    textAlign: 'center',\n    fontVariant: ['tabular-nums'],\n  },\n  transportRow: {\n    flexDirection: 'row',\n    justifyContent: 'center',\n    alignItems: 'center',\n    gap: 12,\n  },\n  controlButton: {\n    width: 48,\n    height: 48,\n    borderRadius: 24,\n    backgroundColor: '#f0f0f0',\n    alignItems: 'center',\n    justifyContent: 'center',\n    elevation: 2,\n    shadowColor: '#000',\n    shadowOffset: { width: 0, height: 1 },\n    shadowOpacity: 0.1,\n    shadowRadius: 2,\n  },\n  controlButtonLarge: {\n    width: 64,\n    height: 64,\n    borderRadius: 32,\n    backgroundColor: '#007aff',\n  },\n  controlIcon: {\n    fontSize: 20,\n    color: '#333',\n  },\n  controlIconLarge: {\n    fontSize: 28,\n    color: '#fff',\n  },\n  audioControls: {\n    gap: 16,\n  },\n  sliderControl: {\n    flexDirection: 'row',\n    alignItems: 'center',\n    gap: 12,\n  },\n  controlLabel: {\n    fontSize: 14,\n    fontWeight: '600',\n    color: '#333',\n    width: 60,\n  },\n  slider: {\n    flex: 1,\n  },\n  valueText: {\n    fontSize: 14,\n    fontWeight: '600',\n    color: '#666',\n    width: 40,\n    textAlign: 'right',\n  },\n  switchRow: {\n    flexDirection: 'row',\n    gap: 20,\n    flexWrap: 'wrap',\n  },\n  switchColumn: {\n    flexDirection: 'column',\n    gap: 8,\n  },\n  switchControl: {\n    flexDirection: 'row',\n    alignItems: 'center',\n    gap: 8,\n    flex: 1,\n    minWidth: 120,\n  },\n  switchLabel: {\n    fontSize: 14,\n    fontWeight: '500',\n    color: '#333',\n  },\n  buttonGroup: {\n    flexDirection: 'row',\n    flexWrap: 'wrap',\n    gap: 8,\n  },\n  toggleButton: {\n    paddingHorizontal: 16,\n    paddingVertical: 8,\n    borderRadius: 20,\n    backgroundColor: '#f0f0f0',\n    borderWidth: 1,\n    borderColor: '#e0e0e0',\n  },\n  toggleButtonActive: {\n    backgroundColor: '#007aff',\n    borderColor: '#007aff',\n  },\n  toggleButtonText: {\n    fontSize: 14,\n    fontWeight: '500',\n    color: '#666',\n    textTransform: 'capitalize',\n  },\n  toggleButtonTextActive: {\n    color: '#fff',\n    fontWeight: '600',\n  },\n  actionGrid: {\n    flexDirection: 'row',\n    flexWrap: 'wrap',\n    gap: 8,\n  },\n  actionButton: {\n    backgroundColor: '#007aff',\n    paddingHorizontal: 16,\n    paddingVertical: 10,\n    borderRadius: 8,\n    elevation: 2,\n    shadowColor: '#000',\n    shadowOffset: { width: 0, height: 1 },\n    shadowOpacity: 0.1,\n    shadowRadius: 2,\n  },\n  actionButtonText: {\n    color: '#fff',\n    fontWeight: '600',\n    fontSize: 14,\n  },\n  eventLog: {\n    backgroundColor: '#f8f9fa',\n    borderRadius: 8,\n    borderLeftWidth: 3,\n    borderLeftColor: '#007aff',\n    height: 200,\n  },\n  eventLogScroll: {\n    flex: 1,\n    padding: 12,\n  },\n  eventItem: {\n    paddingVertical: 4,\n    borderBottomWidth: 1,\n    borderBottomColor: '#e1e1e1',\n  },\n  eventTime: {\n    fontSize: 10,\n    color: '#999',\n    fontFamily: 'monospace',\n    marginBottom: 2,\n  },\n  eventText: {\n    fontSize: 12,\n    color: '#666',\n    fontFamily: 'monospace',\n  },\n  mountControl: {\n    padding: 16,\n    alignItems: 'center',\n  },\n  trackList: {\n    marginTop: 12,\n  },\n  trackButton: {\n    padding: 12,\n    borderWidth: 1,\n    borderColor: '#e0e0e0',\n    borderRadius: 8,\n    marginBottom: 8,\n  },\n  trackButtonSelected: {\n    backgroundColor: '#007aff',\n    borderColor: '#007aff',\n  },\n  trackButtonText: {\n    fontSize: 14,\n    fontWeight: '600',\n    color: '#333',\n  },\n  trackButtonTextSelected: {\n    color: '#fff',\n    fontWeight: '600',\n  },\n  noTracksText: {\n    fontSize: 14,\n    color: '#666',\n    fontWeight: '600',\n    textAlign: 'center',\n  },\n  noTracksSubText: {\n    fontSize: 12,\n    color: '#999',\n    textAlign: 'center',\n  },\n  selectedTrackInfo: {\n    backgroundColor: '#e7f4ff',\n    padding: 12,\n    borderRadius: 8,\n    borderLeftWidth: 3,\n    borderLeftColor: '#007aff',\n    marginBottom: 12,\n  },\n  selectedTrackLabel: {\n    fontSize: 12,\n    fontWeight: '600',\n    color: '#666',\n    marginBottom: 4,\n  },\n  selectedTrackText: {\n    fontSize: 14,\n    fontWeight: '600',\n    color: '#007aff',\n  },\n  eventLogContainer: {\n    backgroundColor: '#f8f9fa',\n    padding: 12,\n    borderRadius: 8,\n    borderLeftWidth: 3,\n    borderLeftColor: '#28a745',\n    marginBottom: 12,\n  },\n  eventLogTitle: {\n    fontSize: 12,\n    fontWeight: '600',\n    color: '#666',\n    marginBottom: 8,\n  },\n  eventLogText: {\n    fontSize: 11,\n    color: '#333',\n    fontFamily: 'monospace',\n    marginBottom: 2,\n  },\n});\n"
  },
  {
    "path": "example/src/types/videoSettings.ts",
    "content": "import type {\n  IgnoreSilentSwitchMode,\n  MixAudioMode,\n  ResizeMode,\n} from 'react-native-video';\n\nexport interface VideoSettings {\n  show: boolean;\n  videoType: 'hls' | 'mp4' | 'drm';\n  volume: number;\n  muted: boolean;\n  rate: number;\n  loop: boolean;\n  showNativeControls: boolean;\n  resizeMode: ResizeMode;\n  mixAudioMode: MixAudioMode;\n  ignoreSilentSwitchMode: IgnoreSilentSwitchMode;\n  playInBackground: boolean;\n  playWhenInactive: boolean;\n  showNotificationControls: boolean;\n}\n\nexport const defaultSettings: VideoSettings = {\n  show: false,\n  videoType: 'hls',\n  volume: 1,\n  muted: false,\n  rate: 1,\n  loop: false,\n  showNativeControls: false,\n  resizeMode: 'contain',\n  mixAudioMode: 'auto',\n  ignoreSilentSwitchMode: 'auto',\n  playInBackground: true,\n  playWhenInactive: false,\n  showNotificationControls: true,\n};\n"
  },
  {
    "path": "example/src/utils/time.ts",
    "content": "export const formatTime = (seconds: number) => {\n  if (isNaN(seconds)) return '--:--';\n  const m = Math.floor(seconds / 60);\n  const s = Math.floor(seconds % 60);\n  return `${m}:${s < 10 ? '0' : ''}${s}`;\n};\n"
  },
  {
    "path": "example/src/utils/videoSource.ts",
    "content": "import { Platform } from 'react-native';\nimport type { VideoConfig } from 'react-native-video';\nimport {\n  enable as enableDRMPlugin,\n  disable as disableDRMPlugin,\n  isEnabled as isDRMPluginEnabled,\n} from '@react-native-video/drm';\n\nconst getDRMSource = (): VideoConfig => {\n  const HLS =\n    'https://d2e67eijd6imrw.cloudfront.net/559c7a7e-960d-4cd8-9dba-bc4e59890177/assets/47cfca69-91b5-4311-bf6c-b9b1f297ed9b/videokit-720p-dash-hls-drm/hls/index.m3u8';\n  const DASH =\n    'https://d2e67eijd6imrw.cloudfront.net/559c7a7e-960d-4cd8-9dba-bc4e59890177/assets/47cfca69-91b5-4311-bf6c-b9b1f297ed9b/videokit-720p-dash-hls-drm/dash/index.mpd';\n  const CERT =\n    'https://thewidlarzgroup.la.drm.cloud/certificate/fairplay?brandGuid=559c7a7e-960d-4cd8-9dba-bc4e59890177';\n  const FAIRPLAY_LICENSE =\n    'https://thewidlarzgroup.la.drm.cloud/acquire-license/fairplay?brandGuid=559c7a7e-960d-4cd8-9dba-bc4e59890177';\n  const WIDEVINE_LICENSE =\n    'https://thewidlarzgroup.la.drm.cloud/acquire-license/widevine?brandGuid=559c7a7e-960d-4cd8-9dba-bc4e59890177';\n  const USER_TOKEN =\n    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NTU3NzQzMTQsImtpZCI6WyIqIl0sImR1cmF0aW9uIjo4NjQwMCwicGVyc2lzdGVudCI6dHJ1ZSwid2lkZXZpbmUiOnsibGljZW5zZV9kdXJhdGlvbiI6OTk5OTk5OSwicGxheWJhY2tfZHVyYXRpb24iOjk5OTk5OTksInJlbnRpYWxfZHVyYXRpb24iOjk5OTk5OTl9LCJmYWlycGxheSI6eyJzdG9yYWdlX2R1cmF0aW9uIjo5OTk5OTk5LCJwbGF5YmFja19kdXJhdGlvbiI6OTk5OTk5OX19.Gm5caVyq_pSTJIy8mZ-vrCeATKueRATmubirh-ajqVg';\n\n  if (Platform.OS === 'ios') {\n    return {\n      uri: HLS,\n      drm: {\n        type: 'fairplay',\n        licenseUrl: FAIRPLAY_LICENSE,\n        certificateUrl: CERT,\n        getLicense: async ({ spc, keyUrl }) => {\n          const formData = new FormData();\n          formData.append('spc', spc);\n\n          const fixedLicenseUrl = keyUrl.replace('skd://', 'https://');\n\n          try {\n            const response = await fetch(\n              `${fixedLicenseUrl}&userToken=${USER_TOKEN}`,\n              {\n                method: 'POST',\n                headers: {\n                  'Content-Type': 'multipart/form-data',\n                  'Accept': 'application/json',\n                },\n                body: formData,\n              }\n            );\n\n            const responseData = await response.json();\n            return responseData.ckc;\n          } catch (error) {\n            console.error('Error fetching license:', error);\n            throw error;\n          }\n        },\n      },\n    } as VideoConfig;\n  }\n\n  if (Platform.OS === 'android') {\n    return {\n      uri: DASH,\n      headers: {\n        'x-drm-userToken': USER_TOKEN,\n      },\n      drm: {\n        type: 'widevine',\n        licenseUrl: WIDEVINE_LICENSE,\n      },\n    } as VideoConfig;\n  }\n\n  throw new Error(\n    'DRM is not Supported or Configured on Platform not supported'\n  );\n};\n\nexport type VideoType = 'hls' | 'mp4' | 'drm';\n\nexport const getVideoSource = (type: VideoType): VideoConfig => {\n  if (type === 'drm') {\n    if (!isDRMPluginEnabled) {\n      enableDRMPlugin();\n    }\n    return getDRMSource();\n  }\n\n  if (isDRMPluginEnabled) {\n    disableDRMPlugin();\n  }\n\n  const HLS = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8';\n  const MP4 =\n    'https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_30MB.mp4';\n\n  return {\n    uri: type === 'hls' ? HLS : MP4,\n    externalSubtitles: [\n      {\n        label: 'External',\n        uri: 'https://gist.githubusercontent.com/samdutton/ca37f3adaf4e23679957b8083e061177/raw/e19399fbccbc069a2af4266e5120ae6bad62699a/sample.vtt',\n        language: 'en',\n        type: 'vtt',\n      },\n    ],\n    metadata: {\n      title: 'Big Buck Bunny',\n      artist: 'Blender Foundation',\n      imageUri:\n        'https://peach.blender.org/wp-content/uploads/title_anouncement.jpg',\n      subtitle: 'By the Blender Institute',\n      description:\n        'Big Buck Bunny is a short computer-animated comedy film by the Blender Institute, part of the Blender Foundation. It was made using Blender, a free and open-source 3D creation suite.',\n    },\n  } as VideoConfig;\n};\n"
  },
  {
    "path": "example/tsconfig.json",
    "content": "{\n  \"extends\": [\n    \"@react-native/typescript-config/tsconfig.json\",\n    \"../config/tsconfig.json\"\n  ],\n  \"include\": [\"src\", \"index.js\", \"app.json\"],\n  \"compilerOptions\": {\n    \"jsx\": \"react\",\n    \"types\": [\"react-native\"]\n  }\n}\n"
  },
  {
    "path": "lefthook.yml",
    "content": "pre-commit:\n  parallel: true\n  commands:\n    lint:\n      glob: \"*.{js,ts,jsx,tsx}\"\n      exclude: \"docs/**/*\"\n      run: bun lint\n    lint-docs:\n      # using @widlarzgroup/eslint-plugin-docusaurus for CSS variable validation\n      root: \"docs/\"\n      glob: \"**/*.{js,ts,jsx,tsx,css}\"\n      run: bun run lint\n    types:\n      glob: \"*.{js,ts,jsx,tsx}\"\n      run: bun typecheck\ncommit-msg:\n  parallel: true\n  commands:\n    commitlint:\n      run: bunx commitlint --edit\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-native-video-monorepo\",\n  \"packageManager\": \"bun@1.1.42\",\n  \"version\": \"7.0.0-beta.8\",\n  \"private\": true,\n  \"repository\": \"https://github.com/TheWidlarzGroup/react-native-video\",\n  \"author\": \"TheWidlarzGroup <hi@thewidlarzgroup.com> (https://github.com/TheWidlarzGroup)\",\n  \"workspaces\": [\n    \"packages/react-native-video\",\n    \"packages/drm-plugin\",\n    \"example\",\n    \"docs\"\n  ],\n  \"scripts\": {\n    \"build\": \"bun --filter=\\\"./packages/**\\\" run build\",\n    \"specs\": \"bun --filter=\\\"./packages/**\\\" specs\",\n    \"lint\": \"bun --filter=\\\"**\\\" lint\",\n    \"typecheck\": \"bun --filter=\\\"**\\\" typecheck\",\n    \"clean\": \"git clean -xdf\",\n    \"react-native-video\": \"bun run --cwd packages/react-native-video\",\n    \"drm-plugin\": \"bun run --cwd packages/drm-plugin\",\n    \"example\": \"bun run --cwd example\",\n    \"docs\": \"bun run --cwd docs\",\n    \"postinstall\": \"patch-package --patch-dir example/patches\",\n    \"release:github\": \"release-it --preRelease beta\",\n    \"release\": \"./scripts/release.sh\"\n  },\n  \"devDependencies\": {\n    \"@commitlint/config-conventional\": \"^17.0.2\",\n    \"@eslint/js\": \"^9.10.0\",\n    \"@evilmartians/lefthook\": \"^1.5.0\",\n    \"@react-native/eslint-config\": \"^0.77.0\",\n    \"@release-it-plugins/workspaces\": \"^4.2.0\",\n    \"@release-it/bumper\": \"^6.0.1\",\n    \"@release-it/conventional-changelog\": \"^8.0.2\",\n    \"@tsconfig/react-native\": \"^2.0.2\",\n    \"@types/eslint__js\": \"^8.42.3\",\n    \"@types/react\": \"^18.2.44\",\n    \"commitlint\": \"^17.0.2\",\n    \"eslint\": \"^8.51.0\",\n    \"eslint-plugin-prettier\": \"^5.0.1\",\n    \"patch-package\": \"^8.0.0\",\n    \"prettier\": \"^3.0.3\",\n    \"react\": \"18.3.1\",\n    \"react-native\": \"^0.77.0\",\n    \"release-it\": \"^17.10.0\",\n    \"typescript\": \"^5.2.2\",\n    \"typescript-eslint\": \"^8.13.0\"\n  },\n  \"commitlint\": {\n    \"extends\": [\n      \"@commitlint/config-conventional\"\n    ]\n  },\n  \"release-it\": {\n    \"npm\": {\n      \"publish\": false\n    },\n    \"git\": {\n      \"commitMessage\": \"chore: release ${version}\",\n      \"tagName\": \"v${version}\",\n      \"requireCleanWorkingDir\": false\n    },\n    \"github\": {\n      \"release\": true\n    },\n    \"hooks\": {\n      \"before:release\": \"bun run --cwd packages/react-native-video build && bun run --cwd packages/drm-plugin build\",\n      \"before:git\": \"bun install && bun example bundle-install && bun example pods && git add bun.lock && git add example/ios/Podfile.lock\"\n    },\n    \"plugins\": {\n      \"@release-it/bumper\": {\n        \"out\": [\n          {\n            \"file\": \"packages/react-native-video/package.json\",\n            \"path\": \"version\"\n          },\n          {\n            \"file\": \"packages/drm-plugin/package.json\",\n            \"path\": \"version\"\n          },\n          {\n            \"file\": \"example/package.json\",\n            \"path\": \"version\"\n          }\n        ]\n      },\n      \"@release-it/conventional-changelog\": {\n        \"preset\": {\n          \"name\": \"conventionalcommits\",\n          \"types\": [\n            {\n              \"type\": \"feat\",\n              \"section\": \"Features ✨\"\n            },\n            {\n              \"type\": \"fix\",\n              \"section\": \"Bug Fixes 🐛\"\n            },\n            {\n              \"type\": \"refactor\",\n              \"section\": \"Code Refactoring 🛠\"\n            },\n            {\n              \"type\": \"chore(deps)\",\n              \"section\": \"Dependency Upgrades 📦\"\n            },\n            {\n              \"type\": \"docs\",\n              \"section\": \"Documentation 📚\"\n            }\n          ]\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/.eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  extends: ['../../config/.eslintrc.js'],\n  parserOptions: {\n    tsconfigRootDir: __dirname,\n    project: true,\n  },\n};\n"
  },
  {
    "path": "packages/drm-plugin/.gitattributes",
    "content": "*.pbxproj -text\n# specific for windows script files\n*.bat text eol=crlf\n"
  },
  {
    "path": "packages/drm-plugin/.gitignore",
    "content": "# OSX\n#\n.DS_Store\n\n# XDE\n.expo/\n\n# VSCode\n.vscode/\njsconfig.json\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\nproject.xcworkspace\n**/.xcode.env.local\n\n# Android/IJ\n#\n.classpath\n.cxx\n.gradle\n.idea\n.project\n.settings\nlocal.properties\nandroid.iml\n\n# Cocoapods\n#\nexample/ios/Pods\n\n# Ruby\nexample/vendor/\n\n# node.js\n#\nnode_modules/\nnpm-debug.log\nyarn-debug.log\nyarn-error.log\n\n# BUCK\nbuck-out/\n\\.buckd/\nandroid/app/libs\nandroid/keystores/debug.keystore\n\n# Yarn\n.yarn/*\n!.yarn/patches\n!.yarn/plugins\n!.yarn/releases\n!.yarn/sdks\n!.yarn/versions\n\n# Expo\n.expo/\n\n# Turborepo\n.turbo/\n\n# generated by bob\nlib/\n\n# React Native Codegen\nios/generated\nandroid/generated\n"
  },
  {
    "path": "packages/drm-plugin/.watchmanconfig",
    "content": "{}"
  },
  {
    "path": "packages/drm-plugin/README.md",
    "content": "# @react-native-video/drm\n\nDRM plugin for react-native-video. It adds Widevine (Android) and FairPlay (iOS, visionOS) playback support via the react-native-video plugin system.\n\n## Requirements\n\n- react-native-video >= 7.0.0-alpha.3\n- react-native-nitro-modules >= 0.35.0\n\n## Installation\n\n```sh\nnpm install @react-native-video/drm react-native-video react-native-nitro-modules\n# then for iOS\nnpx pod-install\n```\n\nNotes\n- This library uses Nitro Modules; autolinking is supported. No manual native changes are needed besides running CocoaPods on iOS.\n- On Expo, use a prebuild workflow (npx expo prebuild) — pure managed apps aren’t supported.\n\n## Quick start\n\nEnable the plugin once at app start, then pass DRM params on your video source.\n\n```tsx\nimport React from 'react';\nimport { Platform } from 'react-native';\nimport { VideoView, useVideoPlayer } from 'react-native-video';\nimport { enable, isEnabled } from '@react-native-video/drm';\n\n// Enable at startup (required on Android; safe on iOS)\nenable();\n\nexport default function Player() {\n\tconst player = useVideoPlayer({\n\t\turi: 'https://example.com/stream.m3u8',\n\t\t// Request headers used by the media request and (on iOS default flow) the license request\n\t\theaders: { Authorization: 'Bearer <token>' },\n\t\tdrm: {\n\t\t\t// Optional: defaults to platform (fairplay on Apple, widevine on Android)\n\t\t\ttype: Platform.select({ ios: 'fairplay', default: 'widevine' }),\n\n\t\t\t// Android (Widevine)\n\t\t\tlicenseUrl: 'https://license.example.com/widevine',\n\t\t\tlicenseHeaders: { 'x-custom': 'value' },\n\t\t\tmultiSession: true,\n\n\t\t\t// iOS (FairPlay)\n\t\t\t// For FairPlay provide certificateUrl and (optionally) contentId.\n\t\t\t// When contentId is not provided, the plugin tries to infer it from the skd:// key URL.\n\t\t\tcertificateUrl: Platform.OS === 'ios' ? 'https://license.example.com/fps.cer' : undefined,\n\t\t},\n\t});\n\n\treturn <VideoView player={player} style={{ flex: 1 }} />;\n}\n```\n\n## API\n\nFrom `@react-native-video/drm`:\n\n- `enable(): void` — registers the plugin. Call once during app startup (Android requires it; iOS tries to auto-enable, but calling is safe).\n- `disable(): void` — unregisters the plugin.\n- `isEnabled: boolean` — plugin registration status.\n\nDRM params (provided via `useVideoPlayer({ drm: ... })` or equivalent config in react-native-video):\n\n- `type?: 'widevine' | 'fairplay' | string` — DRM system. Defaults: Android → widevine, Apple → fairplay.\n- `licenseUrl?: string` — license server URL. Required for both Widevine and FairPlay default flows.\n- `licenseHeaders?: Record<string, string>` — headers for license requests (Android only).\n- `multiSession?: boolean` — allow multiple sessions (Android only).\n- `certificateUrl?: string` — FairPlay application certificate URL (iOS/visionOS).\n- `contentId?: string` — FairPlay content ID (iOS/visionOS). If omitted, inferred from `skd://` key URL when possible.\n- `getLicense?: (payload) => Promise<string>` — iOS custom license fetch. Receives `{ contentId, licenseUrl, keyUrl, spc }` and must resolve to a base64-encoded CKC.\n\n## Platform notes\n\n- iOS/visionOS\n\t- FairPlay is not supported on the simulator — test on a real device.\n\t- Default license flow posts SPC bytes to `licenseUrl` and uses `source.headers` (not `licenseHeaders`). Use `getLicense` for full control.\n\t- Provide `certificateUrl`; set `contentId` if your server needs it.\n- Android\n\t- Widevine is handled via ExoPlayer (Media3). Use `licenseHeaders` for request headers and `multiSession` if needed.\n\n## Troubleshooting\n\n- “Failed to fetch certificate/license” — verify URLs are reachable and correct, and that headers/tokens are included. On iOS default flow, set headers in `source.headers`.\n- “Unsupported DRM type” — set `drm.type` appropriately or omit it to use platform defaults.\n- “DRM not working on simulator” — FairPlay does not work on the iOS simulator.\n\n## License\n\nMIT\n"
  },
  {
    "path": "packages/drm-plugin/ReactNativeVideoDrm.podspec",
    "content": "require \"json\"\n\npackage = JSON.parse(File.read(File.join(__dir__, \"package.json\")))\n\nPod::Spec.new do |s|\n  s.name         = \"ReactNativeVideoDrm\"\n  s.version      = package[\"version\"]\n  s.summary      = package[\"description\"]\n  s.homepage     = package[\"homepage\"]\n  s.license      = package[\"license\"]\n  s.authors      = package[\"author\"]\n\n  s.platforms    = { :ios => min_ios_version_supported }\n  s.source       = { :git => \"https://github.com/TheWidlarzGroup/react-native-video-drm.git\", :tag => \"#{s.version}\" }\n\n\n  s.source_files = [\n    \"ios/**/*.{swift}\",\n    \"ios/**/*.{m,mm}\",\n    \"cpp/**/*.{hpp,cpp}\",\n  ]\n\n  s.dependency 'React-jsi'\n  s.dependency 'React-callinvoker'\n  s.dependency 'ReactNativeVideo'\n\n  load 'nitrogen/generated/ios/ReactNativeVideoDrm+autolinking.rb'\n  add_nitrogen_files(s)\n\n  install_modules_dependencies(s)\nend\n"
  },
  {
    "path": "packages/drm-plugin/android/CMakeLists.txt",
    "content": "project(ReactNativeVideoDrm)\ncmake_minimum_required(VERSION 3.9.0)\n\nset(PACKAGE_NAME ReactNativeVideoDrm)\nset(CMAKE_VERBOSE_MAKEFILE ON)\nset(CMAKE_CXX_STANDARD 20)\n\n# Define C++ library and add all sources\nadd_library(${PACKAGE_NAME} SHARED src/main/cpp/cpp-adapter.cpp)\n\n# Add Nitrogen specs :)\ninclude(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeVideoDrm+autolinking.cmake)\n\n# Set up local includes\ninclude_directories(\"src/main/cpp\" \"../cpp\")\n\nfind_library(LOG_LIB log)\n\n# Link all libraries together\ntarget_link_libraries(\n        ${PACKAGE_NAME}\n        ${LOG_LIB}\n        android # <-- Android core\n)\n"
  },
  {
    "path": "packages/drm-plugin/android/build.gradle",
    "content": "buildscript {\n  ext.getExtOrDefault = {name ->\n    return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['VideoDrm_' + name]\n  }\n\n  repositories {\n    google()\n    mavenCentral()\n  }\n\n  dependencies {\n    classpath \"com.android.tools.build:gradle:8.7.2\"\n    // noinspection DifferentKotlinGradleVersion\n    classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}\"\n  }\n}\n\ndef reactNativeArchitectures() {\n  def value = rootProject.getProperties().get(\"reactNativeArchitectures\")\n  return value ? value.split(\",\") : [\"armeabi-v7a\", \"x86\", \"x86_64\", \"arm64-v8a\"]\n}\n\napply plugin: \"com.android.library\"\napply plugin: \"kotlin-android\"\napply from: '../nitrogen/generated/android/ReactNativeVideoDrm+autolinking.gradle'\n\napply plugin: \"com.facebook.react\"\n\ndef getExtOrIntegerDefault(name) {\n  return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties[\"VideoDrm_\" + name]).toInteger()\n}\n\nandroid {\n  namespace \"com.twg.videodrm\"\n\n  compileSdkVersion getExtOrIntegerDefault(\"compileSdkVersion\")\n\n  defaultConfig {\n    minSdkVersion getExtOrIntegerDefault(\"minSdkVersion\")\n    targetSdkVersion getExtOrIntegerDefault(\"targetSdkVersion\")\n\n    externalNativeBuild {\n      cmake {\n        cppFlags \"-frtti -fexceptions -Wall -fstack-protector-all\"\n        arguments \"-DANDROID_STL=c++_shared\", \"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON\"\n        abiFilters (*reactNativeArchitectures())\n\n        buildTypes {\n          debug {\n            cppFlags \"-O1 -g\"\n          }\n          release {\n            cppFlags \"-O2\"\n          }\n        }\n      }\n    }\n  }\n\n  externalNativeBuild {\n    cmake {\n      path \"CMakeLists.txt\"\n    }\n  }\n\n  packagingOptions {\n    excludes = [\n            \"META-INF\",\n            \"META-INF/**\",\n            \"**/libc++_shared.so\",\n            \"**/libfbjni.so\",\n            \"**/libjsi.so\",\n            \"**/libfolly_json.so\",\n            \"**/libfolly_runtime.so\",\n            \"**/libglog.so\",\n            \"**/libhermes.so\",\n            \"**/libhermes-executor-debug.so\",\n            \"**/libhermes_executor.so\",\n            \"**/libreactnative.so\",\n            \"**/libreactnativejni.so\",\n            \"**/libturbomodulejsijni.so\",\n            \"**/libreact_nativemodule_core.so\",\n            \"**/libjscexecutor.so\"\n    ]\n  }\n\n  buildFeatures {\n    buildConfig true\n    prefab true\n  }\n\n  buildTypes {\n    release {\n      minifyEnabled false\n    }\n  }\n\n  lintOptions {\n    disable \"GradleCompatible\"\n  }\n\n  compileOptions {\n    sourceCompatibility JavaVersion.VERSION_1_8\n    targetCompatibility JavaVersion.VERSION_1_8\n  }\n\n  sourceSets {\n    main {\n      java.srcDirs += [\n        \"generated/java\",\n        \"generated/jni\"\n      ]\n    }\n  }\n}\n\nrepositories {\n  mavenCentral()\n  google()\n}\n\ndef kotlin_version = getExtOrDefault(\"kotlinVersion\")\n\ndependencies {\n  implementation \"com.facebook.react:react-android\"\n  implementation \"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version\"\n\n  implementation \"androidx.media3:media3-common:1.4.1\"\n  implementation \"androidx.media3:media3-exoplayer:1.4.1\"\n  implementation \"androidx.media3:media3-datasource-okhttp:1.4.1\"\n\n  implementation project(\":react-native-nitro-modules\")\n  implementation project(\":react-native-video\")\n}\n\n"
  },
  {
    "path": "packages/drm-plugin/android/gradle.properties",
    "content": "VideoDrm_kotlinVersion=2.0.21\nVideoDrm_minSdkVersion=24\nVideoDrm_targetSdkVersion=34\nVideoDrm_compileSdkVersion=35\nVideoDrm_ndkVersion=27.1.12297006\n"
  },
  {
    "path": "packages/drm-plugin/android/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n</manifest>\n"
  },
  {
    "path": "packages/drm-plugin/android/src/main/cpp/cpp-adapter.cpp",
    "content": "#include <jni.h>\n#include \"ReactNativeVideoDrmOnLoad.hpp\"\n\nJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {\n  return margelo::nitro::videodrm::initialize(vm);\n}\n"
  },
  {
    "path": "packages/drm-plugin/android/src/main/java/com/twg/videodrm/DRMManager/DRMManager.kt",
    "content": "package com.twg.videodrm.DRMManager\n\nimport android.content.Context\nimport androidx.annotation.OptIn\nimport androidx.media3.common.MediaItem.DrmConfiguration\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.common.util.Util\nimport androidx.media3.datasource.okhttp.OkHttpDataSource\nimport androidx.media3.exoplayer.drm.DefaultDrmSessionManager\nimport androidx.media3.exoplayer.drm.DrmSessionManager\nimport androidx.media3.exoplayer.drm.FrameworkMediaDrm\nimport androidx.media3.exoplayer.drm.HttpMediaDrmCallback\nimport androidx.media3.exoplayer.drm.MediaDrmCallback\nimport com.twg.video.core.player.DRMManagerSpec\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.video.NativeDrmParams\nimport com.twg.video.core.player.buildHttpDataSourceFactory\nimport com.twg.video.core.plugins.NativeVideoPlayerSource\nimport java.util.UUID\n\nclass DRMManager(val source: NativeVideoPlayerSource) : DRMManagerSpec {\n  private var hasDrmFailed = false\n  private val context: Context\n    get() {\n      return NitroModules.applicationContext ?: throw Error(\"Context is not found\")\n    }\n\n  private var headersHash = -1\n  private var httpDataSourceFactory: OkHttpDataSource.Factory? = null\n\n  private fun shouldRebuildHttpDataSource(): Boolean {\n    val header = source.config.headers\n    if (header == null) {\n      return false\n    }\n\n    val hash = header.hashCode()\n    if (hash == headersHash) {\n      return false\n    }\n\n    headersHash = hash\n    return true\n  }\n\n  private fun getHttpDataSourceFactory(): OkHttpDataSource.Factory {\n    if (shouldRebuildHttpDataSource() || httpDataSourceFactory == null) {\n      httpDataSourceFactory = buildHttpDataSourceFactory(context, source)\n    }\n\n    return httpDataSourceFactory ?: throw Error(\"Couldn't build HttpDataSourceFactory\")\n  }\n\n  @OptIn(UnstableApi::class)\n  override fun buildDrmSessionManager(\n    drmParams: NativeDrmParams,\n    drmUuid: UUID?,\n    retryCount: Int\n  ): DrmSessionManager {\n    try {\n      val uuid = drmUuid ?: throw Error(\"DRM UUID is not set\")\n      val mediaDrm = FrameworkMediaDrm.newInstance(uuid)\n      val mediaDrmCallback = HttpMediaDrmCallback(\n        drmParams.licenseUrl,\n        getHttpDataSourceFactory(),\n      )\n\n      if (drmParams.licenseHeaders != null) {\n        for ((key, value) in drmParams.licenseHeaders) {\n          mediaDrmCallback.setKeyRequestProperty(key, value)\n        }\n      }\n\n      if (hasDrmFailed) {\n        mediaDrm.setPropertyString(\"securityLevel\", \"L3\")\n      }\n\n      return DefaultDrmSessionManager.Builder()\n        .setUuidAndExoMediaDrmProvider(uuid) { mediaDrm }\n        .setKeyRequestParameters(null)\n        .setMultiSession(drmParams.multiSession == true)\n        .build(mediaDrmCallback)\n    } catch (err: Exception) {\n      if (retryCount < 3) {\n        hasDrmFailed = true\n        return buildDrmSessionManager(drmParams, drmUuid, retryCount + 1)\n      }\n\n      throw err\n    }\n  }\n\n  @OptIn(UnstableApi::class)\n  override fun getDRMConfiguration(drmParams: NativeDrmParams): DrmConfiguration {\n    val uuid = Util.getDrmUuid(drmParams.type ?: \"widevine\") ?: throw Error(\"DRM UUID is not set\")\n\n    val configurationBuilder =  DrmConfiguration.Builder(uuid)\n      .setMultiSession(drmParams.multiSession == true)\n      .setLicenseUri(drmParams.licenseUrl)\n\n    drmParams.licenseHeaders?.let {\n      configurationBuilder.setLicenseRequestHeaders(it)\n    }\n\n    return configurationBuilder.build()\n  }\n}"
  },
  {
    "path": "packages/drm-plugin/android/src/main/java/com/twg/videodrm/DRMPlugin.kt",
    "content": "package com.twg.videodrm\n\nimport com.twg.videodrm.DRMManager.DRMManager\nimport com.twg.video.core.player.DRMManagerSpec\nimport com.twg.video.core.plugins.NativeVideoPlayerSource\nimport com.twg.video.core.plugins.ReactNativeVideoPlugin\n\nclass DRMPlugin(name: String) : ReactNativeVideoPlugin(name) {\n  override fun getDRMManager(source: NativeVideoPlayerSource): DRMManagerSpec? {\n    return DRMManager(source)\n  }\n}"
  },
  {
    "path": "packages/drm-plugin/android/src/main/java/com/twg/videodrm/PluginManager.kt",
    "content": "package com.margelo.nitro.videodrm\n  \nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.twg.videodrm.DRMPlugin\nimport com.twg.video.core.plugins.PluginsRegistry\n\n@DoNotStrip\nclass PluginManager : HybridPluginManagerSpec() {\n  private var plugin: DRMPlugin? = null\n\n  override val isEnabled: Boolean\n    get() = plugin != null\n\n  override fun enable() {\n    if (isEnabled) {\n      return\n    }\n\n    initializePlugin()\n  }\n\n  override fun disable() {\n    if (!isEnabled) {\n      return\n    }\n\n    destroyPlugin()\n  }\n\n  private fun initializePlugin() {\n    plugin = DRMPlugin(\"ReactNativeVideoDRM\")\n\n    plugin?.let {\n      PluginsRegistry.shared.register(it)\n    } ?: throw Error(\"Failed to initialize DRM plugin.\")\n  }\n\n  private fun destroyPlugin() {\n    plugin?.let {\n      PluginsRegistry.shared.unregister(it)\n    } ?: throw Error(\"Plugin is not initialized!\")\n\n    plugin = null\n  }\n\n  override fun dispose() {\n    if (isEnabled) {\n      try {\n        destroyPlugin()\n      } catch (_: Exception) { }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/android/src/main/java/com/twg/videodrm/VideoDrmPackage.kt",
    "content": "package com.twg.videodrm\n\nimport com.facebook.react.TurboReactPackage\nimport com.facebook.react.bridge.NativeModule\nimport com.facebook.react.bridge.ReactApplicationContext\nimport com.facebook.react.module.model.ReactModuleInfoProvider\n\nclass VideoDrmPackage : TurboReactPackage() {\n    override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {\n        return null\n    }\n\n    override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {\n        return ReactModuleInfoProvider { HashMap() }\n    }\n\n    companion object {\n        init {\n            System.loadLibrary(\"ReactNativeVideoDrm\")\n        }\n    }\n}\n"
  },
  {
    "path": "packages/drm-plugin/babel.config.js",
    "content": "module.exports = {\n  overrides: [\n    {\n      exclude: /\\/node_modules\\//,\n      presets: ['module:react-native-builder-bob/babel-preset'],\n    },\n    {\n      include: /\\/node_modules\\//,\n      presets: ['module:@react-native/babel-preset'],\n    },\n  ],\n};\n"
  },
  {
    "path": "packages/drm-plugin/ios/DRMManager/DRMManager+AVContentKeySessionDelegate.swift",
    "content": "//\n//  DRMManager+AVContentKeySessionDelegate.swift\n//  ReactNativeVideoDrm\n//\n//  Created by Krzysztof Moch on 07/08/2025.\n//\n\nimport AVFoundation\nimport Foundation\nimport NitroModules\n\nextension DRMManager: AVContentKeySessionDelegate {\n  func contentKeySession(\n    _: AVContentKeySession,\n    didProvide keyRequest: AVContentKeyRequest\n  ) {\n    handleContentKeyRequest(keyRequest: keyRequest)\n  }\n\n  func contentKeySession(\n    _: AVContentKeySession,\n    didProvideRenewingContentKeyRequest keyRequest: AVContentKeyRequest\n  ) {\n    handleContentKeyRequest(keyRequest: keyRequest)\n  }\n\n  func contentKeySession(\n    _: AVContentKeySession,\n    shouldRetry _: AVContentKeyRequest,\n    reason retryReason: AVContentKeyRequest.RetryReason\n  ) -> Bool {\n    let retryReasons: [AVContentKeyRequest.RetryReason] = [\n      .timedOut,\n      .receivedResponseWithExpiredLease,\n      .receivedObsoleteContentKey,\n    ]\n    return retryReasons.contains(retryReason)\n  }\n\n  func contentKeySession(\n    _: AVContentKeySession,\n    didProvide keyRequest: AVPersistableContentKeyRequest\n  ) {\n    handleError(\n      error: RuntimeError.error(\n        withMessage:\n          \"Persistable content key requests are not supported in This Plugin. Please see Offline Video SDK if you need this functionality.\"\n      ),\n      for: keyRequest\n    )\n  }\n\n  func contentKeySession(\n    _: AVContentKeySession,\n    contentKeyRequest _: AVContentKeyRequest,\n    didFailWithError error: Error\n  ) {\n    // TODO: Handle error appropriately\n    print(\n      \"[ReactNativeVideo] DRMManager: Content key request failed with error: \\(error.localizedDescription)\"\n    )\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/ios/DRMManager/DRMManager.swift",
    "content": "//\n//  DRMManager.swift\n//  ReactNativeVideoDrm\n//\n//  Created by Krzysztof Moch on 07/08/2025.\n//\n\nimport AVFoundation\nimport Foundation\nimport NitroModules\nimport ReactNativeVideo\n\nclass DRMManager: NSObject, DRMManagerSpec {\n  static let queue = DispatchQueue(\n    label: \"ReactNativeVideoDrmContentKeyDelegateQueue\"\n  )\n\n  let contentKeySession: AVContentKeySession\n  weak var source: NativeVideoPlayerSource?\n  \n  var drmParams: NativeDrmParams? {\n    return source?.config.drm\n  }\n\n  init(source: NativeVideoPlayerSource) {\n    contentKeySession = AVContentKeySession(keySystem: .fairPlayStreaming)\n    self.source = source\n\n    super.init()\n    contentKeySession.setDelegate(self, queue: DRMManager.queue)\n  }\n\n  func createContentKeyRequest(\n    for asset: AVURLAsset,\n    drmParams: NativeDrmParams\n  ) throws {\n    if drmParams.type != \"fairplay\" {\n      throw RuntimeError.error(\n        withMessage:\n          \"Unsupported DRM type: \\(String(describing: drmParams.type))\"\n      )\n    }\n\n    contentKeySession.addContentKeyRecipient(asset)\n  }\n\n  // MARK: - Internal Methods\n  internal func handleError(error: Error, for keyRequest: AVContentKeyRequest) {\n    print(\n      \"[ReactNativeVideo] DRM Error: \\(error.localizedDescription) for source \\(source?.uri ?? \"unknown source\")\"\n      )\n    \n    keyRequest.processContentKeyResponseError(error)\n  }\n  \n  internal func handleContentKeyRequest(keyRequest: AVContentKeyRequest) {\n    Task {\n      do {\n        try await processContentKeyRequest(keyRequest: keyRequest)\n      } catch {\n        handleError(error: error, for: keyRequest)\n      }\n    }\n  }\n\n  internal func finishProcessingContentKeyRequest(\n    keyRequest: AVContentKeyRequest,\n    license: Data\n  ) throws {\n    let keyResponse = AVContentKeyResponse(\n      fairPlayStreamingKeyResponseData: license\n    )\n    keyRequest.processContentKeyResponse(keyResponse)\n  }\n\n  // MARK: - Private Methods\n\n  private func processContentKeyRequest(keyRequest: AVContentKeyRequest)\n    async throws\n  {\n    guard let assetId = getAssetId(keyRequest: keyRequest),\n      let assetIdData = assetId.data(using: .utf8)\n    else {\n      throw RuntimeError.error(\n        withMessage:\n          \"No asset ID found for content key request (For \\(source?.uri ?? \"unknown source\"))\"\n      )\n    }\n\n    let appCertificate = try await requestApplicationCertificate()\n    let spcData = try await keyRequest.makeStreamingContentKeyRequestData(\n      forApp: appCertificate,\n      contentIdentifier: assetIdData\n    )\n\n    if let getLicense = drmParams?.getLicense {\n      \n      guard let licenseUrl = drmParams?.licenseUrl,\n        let keyUrl = keyRequest.identifier as? String\n      else {\n        throw RuntimeError.error(\n          withMessage:\n            \"Missing required parameters for getLicense (For \\(source?.uri ?? \"unknown source\"))\"\n        )\n      }\n\n      let payload = OnGetLicensePayload(\n        contentId: assetId,\n        licenseUrl: licenseUrl,\n        keyUrl: keyUrl,\n        spc: spcData.base64EncodedString()\n      )\n      \n      // Get Promise from JavaScript\n      let getLicenseJS = try await getLicense(payload).await()\n      \n      // Resolve Promise from JavaScript\n      let license = try await getLicenseJS.await()\n      \n      guard let licenseData = Data(base64Encoded: license) else {\n        throw RuntimeError.error(\n          withMessage:\n            \"Invalid license data received from getLicense (For \\(source?.uri ?? \"unknown source\"))\"\n        )\n      }\n      \n      try finishProcessingContentKeyRequest(\n        keyRequest: keyRequest,\n        license: licenseData\n      )\n    } else {\n      \n      // Try \"Default\" License Request\n      let license = try await requestLicense(spcData: spcData)\n      try finishProcessingContentKeyRequest(\n        keyRequest: keyRequest,\n        license: license\n      )\n    }\n  }\n\n  private func requestApplicationCertificate() async throws -> Data {\n    guard let urlString = drmParams?.certificateUrl,\n      let url = URL(string: urlString)\n    else {\n      throw RuntimeError.error(\n        withMessage:\n          \"No certificate URL provided (For \\(source?.uri ?? \"unknown source\"))\"\n      )\n    }\n\n    let (data, response) = try await URLSession.shared.data(from: url)\n\n    guard let httpResponse = response as? HTTPURLResponse,\n      httpResponse.statusCode == 200\n    else {\n      throw RuntimeError.error(\n        withMessage: \"Failed to fetch certificate from \\(urlString)\"\n      )\n    }\n\n    if let base64EncodedData = String(data: data, encoding: .utf8),\n      let certData = Data(base64Encoded: base64EncodedData)\n    {\n      return certData\n    }\n\n    return data\n  }\n\n  private func requestLicense(spcData: Data) async throws -> Data {\n    guard let licenseServerUrlString = drmParams?.licenseUrl,\n      let licenseServerUrl = URL(string: licenseServerUrlString)\n    else {\n      throw RuntimeError.error(\n        withMessage:\n          \"No license URL provided (For \\(source?.uri ?? \"unknown source\"))\"\n      )\n    }\n\n    var request = URLRequest(url: licenseServerUrl)\n    request.httpMethod = \"POST\"\n    request.httpBody = spcData\n\n    // Use source headers for now, there was some issues with headers in the DRM params\n    if let headers = source?.config.headers {\n      for (key, value) in headers {\n        request.setValue(value, forHTTPHeaderField: key)\n      }\n    }\n\n    let (data, response) = try await URLSession.shared.data(for: request)\n\n    guard let httpResponse = response as? HTTPURLResponse else {\n      throw RuntimeError.error(\n        withMessage:\n          \"Invalid response from license server (For \\(source?.uri ?? \"unknown source\")) - \\(String(describing: response))\"\n      )\n    }\n\n    guard httpResponse.statusCode == 200 else {\n      throw RuntimeError.error(\n        withMessage:\n          \"License request failed with status code \\(httpResponse.statusCode) (For \\(source?.uri ?? \"unknown source\"))\"\n      )\n    }\n\n    guard !data.isEmpty else {\n      throw RuntimeError.error(\n        withMessage:\n          \"License response is empty (For \\(source?.uri ?? \"unknown source\"))\"\n      )\n    }\n\n    return data\n  }\n\n  private func getAssetId(keyRequest: AVContentKeyRequest) -> String? {\n    if let assetId = drmParams?.contentId {\n      return assetId\n    }\n\n    if let url = keyRequest.identifier as? String {\n      return url.replacingOccurrences(of: \"skd://\", with: \"\")\n    }\n\n    return nil\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/ios/DRMPlugin.swift",
    "content": "//\n//  DRMPlugin.swift\n//  ReactNativeVideoDrm\n//\n//  Created by Krzysztof Moch on 07/08/2025.\n//\n\nimport Foundation\nimport ReactNativeVideo\n\nclass DRMPlugin: ReactNativeVideoPlugin {\n  override func getDRMManager(source: any NativeVideoPlayerSource) -> (any DRMManagerSpec)? {\n    #if targetEnvironment(simulator)\n      // DRM is not supported on the simulator.\n      print(\"[ReactNativeVideoDRM] DRM is not supported on the simulator. Returning nil.\")\n      return nil\n    #else\n      return DRMManager(source: source)\n    #endif\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/ios/PluginManager.swift",
    "content": "//\n//  PluginManager.swift\n//  ReactNativeVideoDrm\n//\n//  Created by Krzysztof Moch on 07/08/2025.\n//\n\nimport NitroModules\nimport ReactNativeVideo\n\nclass PluginManager: HybridPluginManagerSpec {\n  var plugin: DRMPlugin? = nil\n\n  override init() {\n    super.init()\n    do {\n      try enable()\n    } catch {\n      // Handle error if needed, for example log it\n      print(\"Failed to enable DRM plugin: \\(error)\")\n    }\n  }\n\n  var isEnabled: Bool {\n    return plugin != nil\n  }\n\n  func enable() throws {\n    if isEnabled {\n      return\n    }\n\n    try initializePlugin()\n  }\n\n  func disable() throws {\n    if !isEnabled {\n      return\n    }\n\n    try destroyPlugin()\n  }\n\n  private func initializePlugin() throws {\n    plugin = DRMPlugin(name: \"ReactNativeVideoDRM\")\n\n    guard let plugin else {\n      throw RuntimeError.error(withMessage: \"Failed to initialize DRM plugin.\")\n    }\n\n    PluginsRegistry.shared.register(plugin: plugin)\n  }\n\n  private func destroyPlugin() throws {\n    guard let plugin else {\n      throw RuntimeError.error(withMessage: \"Plugin is not initialized.\")\n    }\n\n    PluginsRegistry.shared.unregister(plugin: plugin)\n    self.plugin = nil\n  }\n\n  func dispose() {\n    if isEnabled {\n      do {\n        try destroyPlugin()\n      } catch {\n        // ignore errors during disposal\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/nitro.json",
    "content": "{\n  \"cxxNamespace\": [\"videodrm\"],\n  \"ios\": {\n    \"iosModuleName\": \"ReactNativeVideoDrm\"\n  },\n  \"android\": {\n    \"androidNamespace\": [\"videodrm\"],\n    \"androidCxxLibName\": \"ReactNativeVideoDrm\"\n  },\n  \"autolinking\": {\n    \"PluginManager\": {\n      \"swift\": \"PluginManager\",\n      \"kotlin\": \"PluginManager\"\n    }\n  },\n  \"ignorePaths\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/.gitattributes",
    "content": "** linguist-generated=true\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/android/ReactNativeVideoDrm+autolinking.cmake",
    "content": "#\n# ReactNativeVideoDrm+autolinking.cmake\n# This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n# https://github.com/mrousavy/nitro\n# Copyright © Marc Rousavy @ Margelo\n#\n\n# This is a CMake file that adds all files generated by Nitrogen\n# to the current CMake project.\n#\n# To use it, add this to your CMakeLists.txt:\n# ```cmake\n# include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeVideoDrm+autolinking.cmake)\n# ```\n\n# Define a flag to check if we are building properly\nadd_definitions(-DBUILDING_REACTNATIVEVIDEODRM_WITH_GENERATED_CMAKE_PROJECT)\n\n# Enable Raw Props parsing in react-native (for Nitro Views)\nadd_definitions(-DRN_SERIALIZABLE_STATE)\n\n# Add all headers that were generated by Nitrogen\ninclude_directories(\n  \"../nitrogen/generated/shared/c++\"\n  \"../nitrogen/generated/android/c++\"\n  \"../nitrogen/generated/android/\"\n)\n\n# Add all .cpp sources that were generated by Nitrogen\ntarget_sources(\n  # CMake project name (Android C++ library name)\n  ReactNativeVideoDrm PRIVATE\n  # Autolinking Setup\n  ../nitrogen/generated/android/ReactNativeVideoDrmOnLoad.cpp\n  # Shared Nitrogen C++ sources\n  ../nitrogen/generated/shared/c++/HybridPluginManagerSpec.cpp\n  # Android-specific Nitrogen C++ sources\n  ../nitrogen/generated/android/c++/JHybridPluginManagerSpec.cpp\n)\n\n# From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake\n# Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake\ntarget_compile_definitions(\n  ReactNativeVideoDrm PRIVATE\n  -DFOLLY_NO_CONFIG=1\n  -DFOLLY_HAVE_CLOCK_GETTIME=1\n  -DFOLLY_USE_LIBCPP=1\n  -DFOLLY_CFG_NO_COROUTINES=1\n  -DFOLLY_MOBILE=1\n  -DFOLLY_HAVE_RECVMMSG=1\n  -DFOLLY_HAVE_PTHREAD=1\n  # Once we target android-23 above, we can comment\n  # the following line. NDK uses GNU style stderror_r() after API 23.\n  -DFOLLY_HAVE_XSI_STRERROR_R=1\n)\n\n# Add all libraries required by the generated specs\nfind_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++\nfind_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule)\nfind_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library\n\n# Link all libraries together\ntarget_link_libraries(\n        ReactNativeVideoDrm\n        fbjni::fbjni                              # <-- Facebook C++ JNI helpers\n        ReactAndroid::jsi                         # <-- RN: JSI\n        react-native-nitro-modules::NitroModules  # <-- NitroModules Core :)\n)\n\n# Link react-native (different prefab between RN 0.75 and RN 0.76)\nif(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)\n    target_link_libraries(\n        ReactNativeVideoDrm\n        ReactAndroid::reactnative                 # <-- RN: Native Modules umbrella prefab\n    )\nelse()\n    target_link_libraries(\n        ReactNativeVideoDrm\n        ReactAndroid::react_nativemodule_core     # <-- RN: TurboModules Core\n    )\nendif()\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/android/ReactNativeVideoDrm+autolinking.gradle",
    "content": "///\n/// ReactNativeVideoDrm+autolinking.gradle\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/// This is a Gradle file that adds all files generated by Nitrogen\n/// to the current Gradle project.\n///\n/// To use it, add this to your build.gradle:\n/// ```gradle\n/// apply from: '../nitrogen/generated/android/ReactNativeVideoDrm+autolinking.gradle'\n/// ```\n\nlogger.warn(\"[NitroModules] 🔥 ReactNativeVideoDrm is boosted by nitro!\")\n\nandroid {\n  sourceSets {\n    main {\n      java.srcDirs += [\n        // Nitrogen files\n        \"${project.projectDir}/../nitrogen/generated/android/kotlin\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/android/ReactNativeVideoDrmOnLoad.cpp",
    "content": "///\n/// ReactNativeVideoDrmOnLoad.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#ifndef BUILDING_REACTNATIVEVIDEODRM_WITH_GENERATED_CMAKE_PROJECT\n#error ReactNativeVideoDrmOnLoad.cpp is not being built with the autogenerated CMakeLists.txt project. Is a different CMakeLists.txt building this?\n#endif\n\n#include \"ReactNativeVideoDrmOnLoad.hpp\"\n\n#include <jni.h>\n#include <fbjni/fbjni.h>\n#include <NitroModules/HybridObjectRegistry.hpp>\n\n#include \"JHybridPluginManagerSpec.hpp\"\n#include <NitroModules/DefaultConstructableObject.hpp>\n\nnamespace margelo::nitro::videodrm {\n\nint initialize(JavaVM* vm) {\n  return facebook::jni::initialize(vm, []() {\n    ::margelo::nitro::videodrm::registerAllNatives();\n  });\n}\n\nstruct JHybridPluginManagerSpecImpl: public jni::JavaClass<JHybridPluginManagerSpecImpl, JHybridPluginManagerSpec::JavaPart> {\n  static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/videodrm/PluginManager;\";\n  static std::shared_ptr<JHybridPluginManagerSpec> create() {\n    static auto constructorFn = javaClassStatic()->getConstructor<JHybridPluginManagerSpecImpl::javaobject()>();\n    jni::local_ref<JHybridPluginManagerSpec::JavaPart> javaPart = javaClassStatic()->newObject(constructorFn);\n    return javaPart->getJHybridPluginManagerSpec();\n  }\n};\n\nvoid registerAllNatives() {\n  using namespace margelo::nitro;\n  using namespace margelo::nitro::videodrm;\n\n  // Register native JNI methods\n  margelo::nitro::videodrm::JHybridPluginManagerSpec::CxxPart::registerNatives();\n\n  // Register Nitro Hybrid Objects\n  HybridObjectRegistry::registerHybridObjectConstructor(\n    \"PluginManager\",\n    []() -> std::shared_ptr<HybridObject> {\n      return JHybridPluginManagerSpecImpl::create();\n    }\n  );\n}\n\n} // namespace margelo::nitro::videodrm\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/android/ReactNativeVideoDrmOnLoad.hpp",
    "content": "///\n/// ReactNativeVideoDrmOnLoad.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include <jni.h>\n#include <functional>\n#include <NitroModules/NitroDefines.hpp>\n\nnamespace margelo::nitro::videodrm {\n\n  [[deprecated(\"Use registerNatives() instead.\")]]\n  int initialize(JavaVM* vm);\n\n  /**\n   * Register the native (C++) part of ReactNativeVideoDrm, and autolinks all Hybrid Objects.\n   * Call this in your `JNI_OnLoad` function (probably inside `cpp-adapter.cpp`),\n   * inside a `facebook::jni::initialize(vm, ...)` call.\n   * Example:\n   * ```cpp (cpp-adapter.cpp)\n   * JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {\n   *   return facebook::jni::initialize(vm, []() {\n   *     // register all ReactNativeVideoDrm HybridObjects\n   *     margelo::nitro::videodrm::registerNatives();\n   *     // any other custom registrations go here.\n   *   });\n   * }\n   * ```\n   */\n  void registerAllNatives();\n\n} // namespace margelo::nitro::videodrm\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/android/c++/JHybridPluginManagerSpec.cpp",
    "content": "///\n/// JHybridPluginManagerSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JHybridPluginManagerSpec.hpp\"\n\n\n\n\n\nnamespace margelo::nitro::videodrm {\n\n  std::shared_ptr<JHybridPluginManagerSpec> JHybridPluginManagerSpec::JavaPart::getJHybridPluginManagerSpec() {\n    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();\n    auto castHybridObject = std::dynamic_pointer_cast<JHybridPluginManagerSpec>(hybridObject);\n    if (castHybridObject == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to downcast JHybridObject to JHybridPluginManagerSpec!\");\n    }\n    return castHybridObject;\n  }\n\n  jni::local_ref<JHybridPluginManagerSpec::CxxPart::jhybriddata> JHybridPluginManagerSpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {\n    return makeCxxInstance(jThis);\n  }\n\n  std::shared_ptr<JHybridObject> JHybridPluginManagerSpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {\n    auto castJavaPart = jni::dynamic_ref_cast<JHybridPluginManagerSpec::JavaPart>(javaPart);\n    if (castJavaPart == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to cast JHybridObject::JavaPart to JHybridPluginManagerSpec::JavaPart!\");\n    }\n    return std::make_shared<JHybridPluginManagerSpec>(castJavaPart);\n  }\n\n  void JHybridPluginManagerSpec::CxxPart::registerNatives() {\n    registerHybrid({\n      makeNativeMethod(\"initHybrid\", JHybridPluginManagerSpec::CxxPart::initHybrid),\n    });\n  }\n\n  // Properties\n  bool JHybridPluginManagerSpec::getIsEnabled() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"isEnabled\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n\n  // Methods\n  void JHybridPluginManagerSpec::enable() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"enable\");\n    method(_javaPart);\n  }\n  void JHybridPluginManagerSpec::disable() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"disable\");\n    method(_javaPart);\n  }\n\n} // namespace margelo::nitro::videodrm\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/android/c++/JHybridPluginManagerSpec.hpp",
    "content": "///\n/// HybridPluginManagerSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <NitroModules/JHybridObject.hpp>\n#include <fbjni/fbjni.h>\n#include \"HybridPluginManagerSpec.hpp\"\n\n\n\n\nnamespace margelo::nitro::videodrm {\n\n  using namespace facebook;\n\n  class JHybridPluginManagerSpec: public virtual HybridPluginManagerSpec, public virtual JHybridObject {\n  public:\n    struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/videodrm/HybridPluginManagerSpec;\";\n      std::shared_ptr<JHybridPluginManagerSpec> getJHybridPluginManagerSpec();\n    };\n    struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/videodrm/HybridPluginManagerSpec$CxxPart;\";\n      static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);\n      static void registerNatives();\n      using HybridBase::HybridBase;\n    protected:\n      std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;\n    };\n\n  public:\n    explicit JHybridPluginManagerSpec(const jni::local_ref<JHybridPluginManagerSpec::JavaPart>& javaPart):\n      HybridObject(HybridPluginManagerSpec::TAG),\n      JHybridObject(javaPart),\n      _javaPart(jni::make_global(javaPart)) {}\n    ~JHybridPluginManagerSpec() override {\n      // Hermes GC can destroy JS objects on a non-JNI Thread.\n      jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });\n    }\n\n  public:\n    inline const jni::global_ref<JHybridPluginManagerSpec::JavaPart>& getJavaPart() const noexcept {\n      return _javaPart;\n    }\n\n  public:\n    // Properties\n    bool getIsEnabled() override;\n\n  public:\n    // Methods\n    void enable() override;\n    void disable() override;\n\n  private:\n    jni::global_ref<JHybridPluginManagerSpec::JavaPart> _javaPart;\n  };\n\n} // namespace margelo::nitro::videodrm\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/android/kotlin/com/margelo/nitro/videodrm/HybridPluginManagerSpec.kt",
    "content": "///\n/// HybridPluginManagerSpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.videodrm\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.HybridObject\n\n/**\n * A Kotlin class representing the PluginManager HybridObject.\n * Implement this abstract class to create Kotlin-based instances of PluginManager.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"SimpleRedundantLet\",\n  \"LocalVariableName\", \"PropertyName\", \"PrivatePropertyName\", \"FunctionName\"\n)\nabstract class HybridPluginManagerSpec: HybridObject() {\n  // Properties\n  @get:DoNotStrip\n  @get:Keep\n  abstract val isEnabled: Boolean\n\n  // Methods\n  @DoNotStrip\n  @Keep\n  abstract fun enable(): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun disable(): Unit\n\n  // Default implementation of `HybridObject.toString()`\n  override fun toString(): String {\n    return \"[HybridObject PluginManager]\"\n  }\n\n  // C++ backing class\n  @DoNotStrip\n  @Keep\n  protected open class CxxPart(javaPart: HybridPluginManagerSpec): HybridObject.CxxPart(javaPart) {\n    // C++ JHybridPluginManagerSpec::CxxPart::initHybrid(...)\n    external override fun initHybrid(): HybridData\n  }\n  override fun createCxxPart(): CxxPart {\n    return CxxPart(this)\n  }\n\n  companion object {\n    protected const val TAG = \"HybridPluginManagerSpec\"\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/android/kotlin/com/margelo/nitro/videodrm/ReactNativeVideoDrmOnLoad.kt",
    "content": "///\n/// ReactNativeVideoDrmOnLoad.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.videodrm\n\nimport android.util.Log\n\ninternal class ReactNativeVideoDrmOnLoad {\n  companion object {\n    private const val TAG = \"ReactNativeVideoDrmOnLoad\"\n    private var didLoad = false\n    /**\n     * Initializes the native part of \"ReactNativeVideoDrm\".\n     * This method is idempotent and can be called more than once.\n     */\n    @JvmStatic\n    fun initializeNative() {\n      if (didLoad) return\n      try {\n        Log.i(TAG, \"Loading ReactNativeVideoDrm C++ library...\")\n        System.loadLibrary(\"ReactNativeVideoDrm\")\n        Log.i(TAG, \"Successfully loaded ReactNativeVideoDrm C++ library!\")\n        didLoad = true\n      } catch (e: Error) {\n        Log.e(TAG, \"Failed to load ReactNativeVideoDrm C++ library! Is it properly installed and linked? \" +\n                    \"Is the name correct? (see `CMakeLists.txt`, at `add_library(...)`)\", e)\n        throw e\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/ReactNativeVideoDrm+autolinking.rb",
    "content": "#\n# ReactNativeVideoDrm+autolinking.rb\n# This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n# https://github.com/mrousavy/nitro\n# Copyright © Marc Rousavy @ Margelo\n#\n\n# This is a Ruby script that adds all files generated by Nitrogen\n# to the given podspec.\n#\n# To use it, add this to your .podspec:\n# ```ruby\n# Pod::Spec.new do |spec|\n#   # ...\n#\n#   # Add all files generated by Nitrogen\n#   load 'nitrogen/generated/ios/ReactNativeVideoDrm+autolinking.rb'\n#   add_nitrogen_files(spec)\n# end\n# ```\n\ndef add_nitrogen_files(spec)\n  Pod::UI.puts \"[NitroModules] 🔥 ReactNativeVideoDrm is boosted by nitro!\"\n\n  spec.dependency \"NitroModules\"\n\n  current_source_files = Array(spec.attributes_hash['source_files'])\n  spec.source_files = current_source_files + [\n    # Generated cross-platform specs\n    \"nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}\",\n    # Generated bridges for the cross-platform specs\n    \"nitrogen/generated/ios/**/*.{h,hpp,c,cpp,mm,swift}\",\n  ]\n\n  current_public_header_files = Array(spec.attributes_hash['public_header_files'])\n  spec.public_header_files = current_public_header_files + [\n    # Generated specs\n    \"nitrogen/generated/shared/**/*.{h,hpp}\",\n    # Swift to C++ bridging helpers\n    \"nitrogen/generated/ios/ReactNativeVideoDrm-Swift-Cxx-Bridge.hpp\"\n  ]\n\n  current_private_header_files = Array(spec.attributes_hash['private_header_files'])\n  spec.private_header_files = current_private_header_files + [\n    # iOS specific specs\n    \"nitrogen/generated/ios/c++/**/*.{h,hpp}\",\n    # Views are framework-specific and should be private\n    \"nitrogen/generated/shared/**/views/**/*\"\n  ]\n\n  current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {}\n  spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({\n    # Use C++ 20\n    \"CLANG_CXX_LANGUAGE_STANDARD\" => \"c++20\",\n    # Enables C++ <-> Swift interop (by default it's only ObjC)\n    \"SWIFT_OBJC_INTEROP_MODE\" => \"objcxx\",\n    # Enables stricter modular headers\n    \"DEFINES_MODULE\" => \"YES\",\n  })\nend\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/ReactNativeVideoDrm-Swift-Cxx-Bridge.cpp",
    "content": "///\n/// ReactNativeVideoDrm-Swift-Cxx-Bridge.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"ReactNativeVideoDrm-Swift-Cxx-Bridge.hpp\"\n\n// Include C++ implementation defined types\n#include \"HybridPluginManagerSpecSwift.hpp\"\n#include \"ReactNativeVideoDrm-Swift-Cxx-Umbrella.hpp\"\n#include <NitroModules/NitroDefines.hpp>\n\nnamespace margelo::nitro::videodrm::bridge::swift {\n\n  // pragma MARK: std::shared_ptr<HybridPluginManagerSpec>\n  std::shared_ptr<HybridPluginManagerSpec> create_std__shared_ptr_HybridPluginManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept {\n    ReactNativeVideoDrm::HybridPluginManagerSpec_cxx swiftPart = ReactNativeVideoDrm::HybridPluginManagerSpec_cxx::fromUnsafe(swiftUnsafePointer);\n    return std::make_shared<margelo::nitro::videodrm::HybridPluginManagerSpecSwift>(swiftPart);\n  }\n  void* NON_NULL get_std__shared_ptr_HybridPluginManagerSpec_(std__shared_ptr_HybridPluginManagerSpec_ cppType) {\n    std::shared_ptr<margelo::nitro::videodrm::HybridPluginManagerSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::videodrm::HybridPluginManagerSpecSwift>(cppType);\n    #ifdef NITRO_DEBUG\n    if (swiftWrapper == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Class \\\"HybridPluginManagerSpec\\\" is not implemented in Swift!\");\n    }\n    #endif\n    ReactNativeVideoDrm::HybridPluginManagerSpec_cxx& swiftPart = swiftWrapper->getSwiftPart();\n    return swiftPart.toUnsafe();\n  }\n\n} // namespace margelo::nitro::videodrm::bridge::swift\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/ReactNativeVideoDrm-Swift-Cxx-Bridge.hpp",
    "content": "///\n/// ReactNativeVideoDrm-Swift-Cxx-Bridge.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n// Forward declarations of C++ defined types\n// Forward declaration of `HybridPluginManagerSpec` to properly resolve imports.\nnamespace margelo::nitro::videodrm { class HybridPluginManagerSpec; }\n\n// Forward declarations of Swift defined types\n// Forward declaration of `HybridPluginManagerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideoDrm { class HybridPluginManagerSpec_cxx; }\n\n// Include C++ defined types\n#include \"HybridPluginManagerSpec.hpp\"\n#include <NitroModules/Result.hpp>\n#include <exception>\n#include <memory>\n\n/**\n * Contains specialized versions of C++ templated types so they can be accessed from Swift,\n * as well as helper functions to interact with those C++ types from Swift.\n */\nnamespace margelo::nitro::videodrm::bridge::swift {\n\n  // pragma MARK: std::shared_ptr<HybridPluginManagerSpec>\n  /**\n   * Specialized version of `std::shared_ptr<HybridPluginManagerSpec>`.\n   */\n  using std__shared_ptr_HybridPluginManagerSpec_ = std::shared_ptr<HybridPluginManagerSpec>;\n  std::shared_ptr<HybridPluginManagerSpec> create_std__shared_ptr_HybridPluginManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept;\n  void* NON_NULL get_std__shared_ptr_HybridPluginManagerSpec_(std__shared_ptr_HybridPluginManagerSpec_ cppType);\n  \n  // pragma MARK: std::weak_ptr<HybridPluginManagerSpec>\n  using std__weak_ptr_HybridPluginManagerSpec_ = std::weak_ptr<HybridPluginManagerSpec>;\n  inline std__weak_ptr_HybridPluginManagerSpec_ weakify_std__shared_ptr_HybridPluginManagerSpec_(const std::shared_ptr<HybridPluginManagerSpec>& strong) noexcept { return strong; }\n  \n  // pragma MARK: Result<void>\n  using Result_void_ = Result<void>;\n  inline Result_void_ create_Result_void_() noexcept {\n    return Result<void>::withValue();\n  }\n  inline Result_void_ create_Result_void_(const std::exception_ptr& error) noexcept {\n    return Result<void>::withError(error);\n  }\n\n} // namespace margelo::nitro::videodrm::bridge::swift\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/ReactNativeVideoDrm-Swift-Cxx-Umbrella.hpp",
    "content": "///\n/// ReactNativeVideoDrm-Swift-Cxx-Umbrella.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n// Forward declarations of C++ defined types\n// Forward declaration of `HybridPluginManagerSpec` to properly resolve imports.\nnamespace margelo::nitro::videodrm { class HybridPluginManagerSpec; }\n\n// Include C++ defined types\n#include \"HybridPluginManagerSpec.hpp\"\n#include <NitroModules/Result.hpp>\n#include <exception>\n#include <memory>\n\n// C++ helpers for Swift\n#include \"ReactNativeVideoDrm-Swift-Cxx-Bridge.hpp\"\n\n// Common C++ types used in Swift\n#include <NitroModules/ArrayBufferHolder.hpp>\n#include <NitroModules/AnyMapUtils.hpp>\n#include <NitroModules/RuntimeError.hpp>\n#include <NitroModules/DateToChronoDate.hpp>\n\n// Forward declarations of Swift defined types\n// Forward declaration of `HybridPluginManagerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideoDrm { class HybridPluginManagerSpec_cxx; }\n\n// Include Swift defined types\n#if __has_include(\"ReactNativeVideoDrm-Swift.h\")\n// This header is generated by Xcode/Swift on every app build.\n// If it cannot be found, make sure the Swift module's name (= podspec name) is actually \"ReactNativeVideoDrm\".\n#include \"ReactNativeVideoDrm-Swift.h\"\n// Same as above, but used when building with frameworks (`use_frameworks`)\n#elif __has_include(<ReactNativeVideoDrm/ReactNativeVideoDrm-Swift.h>)\n#include <ReactNativeVideoDrm/ReactNativeVideoDrm-Swift.h>\n#else\n#error ReactNativeVideoDrm's autogenerated Swift header cannot be found! Make sure the Swift module's name (= podspec name) is actually \"ReactNativeVideoDrm\", and try building the app first.\n#endif\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/ReactNativeVideoDrmAutolinking.mm",
    "content": "///\n/// ReactNativeVideoDrmAutolinking.mm\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#import <Foundation/Foundation.h>\n#import <NitroModules/HybridObjectRegistry.hpp>\n#import \"ReactNativeVideoDrm-Swift-Cxx-Umbrella.hpp\"\n#import <type_traits>\n\n#include \"HybridPluginManagerSpecSwift.hpp\"\n\n@interface ReactNativeVideoDrmAutolinking : NSObject\n@end\n\n@implementation ReactNativeVideoDrmAutolinking\n\n+ (void) load {\n  using namespace margelo::nitro;\n  using namespace margelo::nitro::videodrm;\n\n  HybridObjectRegistry::registerHybridObjectConstructor(\n    \"PluginManager\",\n    []() -> std::shared_ptr<HybridObject> {\n      std::shared_ptr<HybridPluginManagerSpec> hybridObject = ReactNativeVideoDrm::ReactNativeVideoDrmAutolinking::createPluginManager();\n      return hybridObject;\n    }\n  );\n}\n\n@end\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/ReactNativeVideoDrmAutolinking.swift",
    "content": "///\n/// ReactNativeVideoDrmAutolinking.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n// TODO: Use empty enums once Swift supports exporting them as namespaces\n//       See: https://github.com/swiftlang/swift/pull/83616\npublic final class ReactNativeVideoDrmAutolinking {\n  public typealias bridge = margelo.nitro.videodrm.bridge.swift\n\n  public static func createPluginManager() -> bridge.std__shared_ptr_HybridPluginManagerSpec_ {\n    let hybridObject = PluginManager()\n    return { () -> bridge.std__shared_ptr_HybridPluginManagerSpec_ in\n      let __cxxWrapped = hybridObject.getCxxWrapper()\n      return __cxxWrapped.getCxxPart()\n    }()\n  }\n  \n  public static func isPluginManagerRecyclable() -> Bool {\n    return PluginManager.self is any RecyclableView.Type\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/c++/HybridPluginManagerSpecSwift.cpp",
    "content": "///\n/// HybridPluginManagerSpecSwift.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridPluginManagerSpecSwift.hpp\"\n\nnamespace margelo::nitro::videodrm {\n} // namespace margelo::nitro::videodrm\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/c++/HybridPluginManagerSpecSwift.hpp",
    "content": "///\n/// HybridPluginManagerSpecSwift.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include \"HybridPluginManagerSpec.hpp\"\n\n// Forward declaration of `HybridPluginManagerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideoDrm { class HybridPluginManagerSpec_cxx; }\n\n\n\n\n\n#include \"ReactNativeVideoDrm-Swift-Cxx-Umbrella.hpp\"\n\nnamespace margelo::nitro::videodrm {\n\n  /**\n   * The C++ part of HybridPluginManagerSpec_cxx.swift.\n   *\n   * HybridPluginManagerSpecSwift (C++) accesses HybridPluginManagerSpec_cxx (Swift), and might\n   * contain some additional bridging code for C++ <> Swift interop.\n   *\n   * Since this obviously introduces an overhead, I hope at some point in\n   * the future, HybridPluginManagerSpec_cxx can directly inherit from the C++ class HybridPluginManagerSpec\n   * to simplify the whole structure and memory management.\n   */\n  class HybridPluginManagerSpecSwift: public virtual HybridPluginManagerSpec {\n  public:\n    // Constructor from a Swift instance\n    explicit HybridPluginManagerSpecSwift(const ReactNativeVideoDrm::HybridPluginManagerSpec_cxx& swiftPart):\n      HybridObject(HybridPluginManagerSpec::TAG),\n      _swiftPart(swiftPart) { }\n\n  public:\n    // Get the Swift part\n    inline ReactNativeVideoDrm::HybridPluginManagerSpec_cxx& getSwiftPart() noexcept {\n      return _swiftPart;\n    }\n\n  public:\n    inline size_t getExternalMemorySize() noexcept override {\n      return _swiftPart.getMemorySize();\n    }\n    bool equals(const std::shared_ptr<HybridObject>& other) override {\n      if (auto otherCast = std::dynamic_pointer_cast<HybridPluginManagerSpecSwift>(other)) {\n        return _swiftPart.equals(otherCast->_swiftPart);\n      }\n      return false;\n    }\n    void dispose() noexcept override {\n      _swiftPart.dispose();\n    }\n    std::string toString() override {\n      return _swiftPart.toString();\n    }\n\n  public:\n    // Properties\n    inline bool getIsEnabled() noexcept override {\n      return _swiftPart.isEnabled();\n    }\n\n  public:\n    // Methods\n    inline void enable() override {\n      auto __result = _swiftPart.enable();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline void disable() override {\n      auto __result = _swiftPart.disable();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n\n  private:\n    ReactNativeVideoDrm::HybridPluginManagerSpec_cxx _swiftPart;\n  };\n\n} // namespace margelo::nitro::videodrm\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/swift/HybridPluginManagerSpec.swift",
    "content": "///\n/// HybridPluginManagerSpec.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/// See ``HybridPluginManagerSpec``\npublic protocol HybridPluginManagerSpec_protocol: HybridObject {\n  // Properties\n  var isEnabled: Bool { get }\n\n  // Methods\n  func enable() throws -> Void\n  func disable() throws -> Void\n}\n\npublic extension HybridPluginManagerSpec_protocol {\n  /// Default implementation of ``HybridObject.toString``\n  func toString() -> String {\n    return \"[HybridObject PluginManager]\"\n  }\n}\n\n/// See ``HybridPluginManagerSpec``\nopen class HybridPluginManagerSpec_base {\n  private weak var cxxWrapper: HybridPluginManagerSpec_cxx? = nil\n  public init() { }\n  public func getCxxWrapper() -> HybridPluginManagerSpec_cxx {\n  #if DEBUG\n    guard self is any HybridPluginManagerSpec else {\n      fatalError(\"`self` is not a `HybridPluginManagerSpec`! Did you accidentally inherit from `HybridPluginManagerSpec_base` instead of `HybridPluginManagerSpec`?\")\n    }\n  #endif\n    if let cxxWrapper = self.cxxWrapper {\n      return cxxWrapper\n    } else {\n      let cxxWrapper = HybridPluginManagerSpec_cxx(self as! any HybridPluginManagerSpec)\n      self.cxxWrapper = cxxWrapper\n      return cxxWrapper\n    }\n  }\n}\n\n/**\n * A Swift base-protocol representing the PluginManager HybridObject.\n * Implement this protocol to create Swift-based instances of PluginManager.\n * ```swift\n * class HybridPluginManager : HybridPluginManagerSpec {\n *   // ...\n * }\n * ```\n */\npublic typealias HybridPluginManagerSpec = HybridPluginManagerSpec_protocol & HybridPluginManagerSpec_base\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/ios/swift/HybridPluginManagerSpec_cxx.swift",
    "content": "///\n/// HybridPluginManagerSpec_cxx.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * A class implementation that bridges HybridPluginManagerSpec over to C++.\n * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.\n *\n * Also, some Swift types need to be bridged with special handling:\n * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)\n * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper\n * - Throwing methods need to be wrapped with a Result<T, Error> type, as exceptions cannot be propagated to C++\n */\nopen class HybridPluginManagerSpec_cxx {\n  /**\n   * The Swift <> C++ bridge's namespace (`margelo::nitro::videodrm::bridge::swift`)\n   * from `ReactNativeVideoDrm-Swift-Cxx-Bridge.hpp`.\n   * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.\n   */\n  public typealias bridge = margelo.nitro.videodrm.bridge.swift\n\n  /**\n   * Holds an instance of the `HybridPluginManagerSpec` Swift protocol.\n   */\n  private var __implementation: any HybridPluginManagerSpec\n\n  /**\n   * Holds a weak pointer to the C++ class that wraps the Swift class.\n   */\n  private var __cxxPart: bridge.std__weak_ptr_HybridPluginManagerSpec_\n\n  /**\n   * Create a new `HybridPluginManagerSpec_cxx` that wraps the given `HybridPluginManagerSpec`.\n   * All properties and methods bridge to C++ types.\n   */\n  public init(_ implementation: any HybridPluginManagerSpec) {\n    self.__implementation = implementation\n    self.__cxxPart = .init()\n    /* no base class */\n  }\n\n  /**\n   * Get the actual `HybridPluginManagerSpec` instance this class wraps.\n   */\n  @inline(__always)\n  public func getHybridPluginManagerSpec() -> any HybridPluginManagerSpec {\n    return __implementation\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `HybridPluginManagerSpec_cxx`.\n   * The pointer has to be a retained opaque `Unmanaged<HybridPluginManagerSpec_cxx>`.\n   * This removes one strong reference from the object!\n   */\n  public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridPluginManagerSpec_cxx {\n    return Unmanaged<HybridPluginManagerSpec_cxx>.fromOpaque(pointer).takeRetainedValue()\n  }\n\n  /**\n   * Gets (or creates) the C++ part of this Hybrid Object.\n   * The C++ part is a `std::shared_ptr<HybridPluginManagerSpec>`.\n   */\n  public func getCxxPart() -> bridge.std__shared_ptr_HybridPluginManagerSpec_ {\n    let cachedCxxPart = self.__cxxPart.lock()\n    if Bool(fromCxx: cachedCxxPart) {\n      return cachedCxxPart\n    } else {\n      let newCxxPart = bridge.create_std__shared_ptr_HybridPluginManagerSpec_(self.toUnsafe())\n      __cxxPart = bridge.weakify_std__shared_ptr_HybridPluginManagerSpec_(newCxxPart)\n      return newCxxPart\n    }\n  }\n\n  \n\n  /**\n   * Get the memory size of the Swift class (plus size of any other allocations)\n   * so the JS VM can properly track it and garbage-collect the JS object if needed.\n   */\n  @inline(__always)\n  public var memorySize: Int {\n    return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize\n  }\n\n  /**\n   * Compares this object with the given [other] object for reference equality.\n   */\n  @inline(__always)\n  public func equals(other: HybridPluginManagerSpec_cxx) -> Bool {\n    return self.__implementation === other.__implementation\n  }\n\n  /**\n   * Call dispose() on the Swift class.\n   * This _may_ be called manually from JS.\n   */\n  @inline(__always)\n  public func dispose() {\n    self.__implementation.dispose()\n  }\n\n  /**\n   * Call toString() on the Swift class.\n   */\n  @inline(__always)\n  public func toString() -> String {\n    return self.__implementation.toString()\n  }\n\n  // Properties\n  public final var isEnabled: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.isEnabled\n    }\n  }\n\n  // Methods\n  @inline(__always)\n  public final func enable() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.enable()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func disable() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.disable()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/shared/c++/HybridPluginManagerSpec.cpp",
    "content": "///\n/// HybridPluginManagerSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridPluginManagerSpec.hpp\"\n\nnamespace margelo::nitro::videodrm {\n\n  void HybridPluginManagerSpec::loadHybridMethods() {\n    // load base methods/properties\n    HybridObject::loadHybridMethods();\n    // load custom methods/properties\n    registerHybrids(this, [](Prototype& prototype) {\n      prototype.registerHybridGetter(\"isEnabled\", &HybridPluginManagerSpec::getIsEnabled);\n      prototype.registerHybridMethod(\"enable\", &HybridPluginManagerSpec::enable);\n      prototype.registerHybridMethod(\"disable\", &HybridPluginManagerSpec::disable);\n    });\n  }\n\n} // namespace margelo::nitro::videodrm\n"
  },
  {
    "path": "packages/drm-plugin/nitrogen/generated/shared/c++/HybridPluginManagerSpec.hpp",
    "content": "///\n/// HybridPluginManagerSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/HybridObject.hpp>)\n#include <NitroModules/HybridObject.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n\n\nnamespace margelo::nitro::videodrm {\n\n  using namespace margelo::nitro;\n\n  /**\n   * An abstract base class for `PluginManager`\n   * Inherit this class to create instances of `HybridPluginManagerSpec` in C++.\n   * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.\n   * @example\n   * ```cpp\n   * class HybridPluginManager: public HybridPluginManagerSpec {\n   * public:\n   *   HybridPluginManager(...): HybridObject(TAG) { ... }\n   *   // ...\n   * };\n   * ```\n   */\n  class HybridPluginManagerSpec: public virtual HybridObject {\n    public:\n      // Constructor\n      explicit HybridPluginManagerSpec(): HybridObject(TAG) { }\n\n      // Destructor\n      ~HybridPluginManagerSpec() override = default;\n\n    public:\n      // Properties\n      virtual bool getIsEnabled() = 0;\n\n    public:\n      // Methods\n      virtual void enable() = 0;\n      virtual void disable() = 0;\n\n    protected:\n      // Hybrid Setup\n      void loadHybridMethods() override;\n\n    protected:\n      // Tag for logging\n      static constexpr auto TAG = \"PluginManager\";\n  };\n\n} // namespace margelo::nitro::videodrm\n"
  },
  {
    "path": "packages/drm-plugin/package.json",
    "content": "{\n  \"name\": \"@react-native-video/drm\",\n  \"version\": \"7.0.0-beta.8\",\n  \"description\": \"DRM plugin for react-native-video\",\n  \"main\": \"./lib/module/index.js\",\n  \"types\": \"./lib/typescript/src/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"source\": \"./src/index.tsx\",\n      \"types\": \"./lib/typescript/src/index.d.ts\",\n      \"default\": \"./lib/module/index.js\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"files\": [\n    \"src\",\n    \"lib\",\n    \"android\",\n    \"ios\",\n    \"cpp\",\n    \"nitrogen\",\n    \"nitro.json\",\n    \"*.podspec\",\n    \"react-native.config.js\",\n    \"!ios/build\",\n    \"!android/build\",\n    \"!android/gradle\",\n    \"!android/gradlew\",\n    \"!android/gradlew.bat\",\n    \"!android/local.properties\",\n    \"!**/__tests__\",\n    \"!**/__fixtures__\",\n    \"!**/__mocks__\",\n    \"!**/.*\"\n  ],\n  \"scripts\": {\n    \"test\": \"jest\",\n    \"typecheck\": \"tsc\",\n    \"lint\": \"eslint \\\"**/*.{js,ts,tsx}\\\"\",\n    \"clean\": \"del-cli android/build example/android/build example/android/app/build example/ios/build lib\",\n    \"prepare\": \"bun run build\",\n    \"build\": \"bob build\",\n    \"specs\": \"nitrogen\",\n    \"release\": \"release-it --preRelease beta --npm.tag=beta\"\n  },\n  \"keywords\": [\n    \"react-native\",\n    \"react-native-video\",\n    \"drm\",\n    \"ios\",\n    \"android\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TheWidlarzGroup/react-native-video.git\"\n  },\n  \"author\": \"TheWidlarzGroup <hi@thewidlarzgroup.com> (https://github.com/TheWidlarzGroup)\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/TheWidlarzGroup/react-native-video/issues\"\n  },\n  \"homepage\": \"https://github.com/TheWidlarzGroup/react-native-video#readme\",\n  \"publishConfig\": {\n    \"registry\": \"https://registry.npmjs.org/\",\n    \"access\": \"public\"\n  },\n  \"devDependencies\": {\n    \"@react-native/babel-preset\": \"0.79.2\",\n    \"@release-it/conventional-changelog\": \"^9.0.2\",\n    \"@types/react\": \"^18.3.0\",\n    \"del-cli\": \"^5.1.0\",\n    \"eslint\": \"^8.51.0\",\n    \"eslint-config-prettier\": \"9.0.0\",\n    \"eslint-plugin-prettier\": \"^5.0.1\",\n    \"nitrogen\": \"0.35.0\",\n    \"prettier\": \"^3.0.3\",\n    \"react\": \"18.3.1\",\n    \"react-native\": \"^0.77.0\",\n    \"react-native-builder-bob\": \"^0.40.13\",\n    \"react-native-nitro-modules\": \"0.35.0\",\n    \"release-it\": \"^17.10.0\",\n    \"typescript\": \"^5.8.3\",\n    \"react-native-video\": \"*\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"*\",\n    \"react-native\": \"*\",\n    \"react-native-video\": \">=7.0.0-alpha.3\",\n    \"react-native-nitro-modules\": \">=0.35.0\"\n  },\n  \"jest\": {\n    \"preset\": \"react-native\",\n    \"modulePathIgnorePatterns\": [\n      \"<rootDir>/example/node_modules\",\n      \"<rootDir>/lib/\"\n    ]\n  },\n  \"release-it\": {\n    \"git\": false,\n    \"npm\": {\n      \"publish\": true,\n      \"publishArgs\": \"--access public\"\n    },\n    \"github\": {\n      \"release\": false\n    },\n    \"hooks\": {\n      \"before:init\": \"bun typecheck && bun lint\",\n      \"after:bump\": \"bun run build && cp ../../LICENSE ./LICENSE\"\n    }\n  },\n  \"react-native-builder-bob\": {\n    \"source\": \"src\",\n    \"output\": \"lib\",\n    \"targets\": [\n      [\n        \"module\",\n        {\n          \"esm\": true\n        }\n      ],\n      [\n        \"typescript\",\n        {\n          \"project\": \"tsconfig.build.json\"\n        }\n      ]\n    ]\n  },\n  \"create-react-native-library\": {\n    \"languages\": \"kotlin-swift\",\n    \"type\": \"nitro-module\",\n    \"version\": \"0.52.0\"\n  }\n}\n"
  },
  {
    "path": "packages/drm-plugin/src/PluginManager.nitro.ts",
    "content": "import type { HybridObject } from 'react-native-nitro-modules';\n\nexport interface PluginManager\n  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {\n  enable(): void;\n  disable(): void;\n  readonly isEnabled: boolean;\n}\n"
  },
  {
    "path": "packages/drm-plugin/src/index.tsx",
    "content": "import { NitroModules } from 'react-native-nitro-modules';\nimport type { PluginManager as PluginManagerSpec } from './PluginManager.nitro';\n\nconst PluginManager =\n  NitroModules.createHybridObject<PluginManagerSpec>('PluginManager');\n\nexport function enable() {\n  return PluginManager.enable();\n}\n\nexport function disable() {\n  return PluginManager.disable();\n}\n\nexport const isEnabled: boolean = PluginManager.isEnabled;\n"
  },
  {
    "path": "packages/drm-plugin/tsconfig.build.json",
    "content": "{\n  \"extends\": \"./tsconfig\",\n  \"exclude\": [\"example\", \"lib\"]\n}\n"
  },
  {
    "path": "packages/drm-plugin/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"rootDir\": \".\",\n    \"paths\": {\n      \"react-native-video-drm\": [\"./src/index\"]\n    },\n    \"allowUnreachableCode\": false,\n    \"allowUnusedLabels\": false,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"jsx\": \"react-jsx\",\n    \"lib\": [\"ESNext\"],\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"noEmit\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noImplicitReturns\": true,\n    \"noImplicitUseStrict\": false,\n    \"noStrictGenericChecks\": false,\n    \"noUncheckedIndexedAccess\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"target\": \"ESNext\",\n    \"verbatimModuleSyntax\": true\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/.eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  extends: [\"../../config/.eslintrc.js\"],\n  parserOptions: {\n    tsconfigRootDir: __dirname,\n    project: true,\n  },\n};\n"
  },
  {
    "path": "packages/react-native-video/.gitignore",
    "content": "# OSX\n#\n.DS_Store\n\n# XDE\n.expo/\n\n# VSCode\n.vscode/\njsconfig.json\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\nproject.xcworkspace\n\n# Android/IJ\n#\n.classpath\n.cxx\n.gradle\n.idea\n.project\n.settings\nlocal.properties\nandroid.iml\n\n# Cocoapods\n#\nexample/ios/Pods\n\n# Ruby\nexample/vendor/\n\n# node.js\n#\nnode_modules/\nnpm-debug.log\nyarn-debug.log\nyarn-error.log\n\n# BUCK\nbuck-out/\n\\.buckd/\nandroid/app/libs\nandroid/keystores/debug.keystore\n\n# Yarn\n.yarn/*\n!.yarn/patches\n!.yarn/plugins\n!.yarn/releases\n!.yarn/sdks\n!.yarn/versions\n\n# Expo\n.expo/\n\n# Turborepo\n.turbo/\n\n# generated by bob\nlib/\n\n# React Native Codegen\nios/generated\nandroid/generated\n"
  },
  {
    "path": "packages/react-native-video/.watchmanconfig",
    "content": "{}"
  },
  {
    "path": "packages/react-native-video/ReactNativeVideo.podspec",
    "content": "require \"json\"\n\npackage = JSON.parse(File.read(File.join(__dir__, \"package.json\")))\nfolly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'\n\nfabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'\n\nPod::Spec.new do |s|\n  s.name         = \"ReactNativeVideo\"\n  s.version      = package[\"version\"]\n  s.summary      = package[\"description\"]\n  s.homepage     = package[\"homepage\"]\n  s.license      = package[\"license\"]\n  s.authors      = package[\"author\"]\n\n  s.platforms    = { :ios => min_ios_version_supported }\n  s.source       = { :git => \"https://github.com/KrzysztofMoch/react-native-video.git\", :tag => \"#{s.version}\" }\n\n  s.source_files = [\n    \"ios/*.{h,m,mm,swift}\",\n    \"ios/Core/**/*.{h,m,mm,swift}\", # Core library files\n    \"ios/Hybrids/**/*.{h,m,mm,swift}\", # Nitro Hybrid files\n    \"ios/View/**/*.{h,m,mm,swift}\"  # Video View files\n  ]\n\n  if fabric_enabled\n    s.exclude_files = [\"ios/view/paper/**/*.{h,m,mm,swift}\"]\n  else\n    s.exclude_files = [\"ios/view/fabric/**/*.{h,m,mm,swift}\"]\n  end\n\n  # Cxx to Swift bridging helpers\n  s.public_header_files = [\"ios/Video-Bridging-Header.h\"]\n\n  s.pod_target_xcconfig = {\n    \"GCC_PREPROCESSOR_DEFINITIONS\" => \"$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES FOLLY_MOBILE\"\n  }\n\n  # Try to manually add the dependencies\n  # because they are not automatically added by expo\n  # when USE_FRAMEWORKS is true\n  if ENV[\"USE_FRAMEWORKS\"]\n    s.dependency \"React-Core\"\n\n    puts \"[ReactNativeVideo] Detected USE_FRAMEWORKS, adding required dependencies...\"\n   \n    add_dependency(s, \"React-jsinspector\", :framework_name => \"jsinspector_modern\")\n    add_dependency(s, \"React-rendererconsistency\", :framework_name => \"React_rendererconsistency\")\n\n    # @KrzysztofMoch Note: We need to add this as well for newer versions of React Native, but it's not available in older versions\n    # add_dependency(s, \"React-jsinspectortracing\", :framework_name => 'jsinspector_moderntracing')\n  end\n\n  # Add all files generated by Nitrogen\n  load 'nitrogen/generated/ios/ReactNativeVideo+autolinking.rb'\n  add_nitrogen_files(s)\n\n  install_modules_dependencies(s)\nend\n"
  },
  {
    "path": "packages/react-native-video/android/CMakeLists.txt",
    "content": "\nproject(ReactNativeVideo)\ncmake_minimum_required(VERSION 3.9.0)\n\nset (PACKAGE_NAME ReactNativeVideo)\nset (CMAKE_VERBOSE_MAKEFILE ON)\nset (CMAKE_CXX_STANDARD 20)\n\n# Define C++ library and add all sources\nadd_library(${PACKAGE_NAME} SHARED\n        src/main/cpp/cpp-adapter.cpp\n)\n\n# Add Nitrogen specs :)\ninclude(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeVideo+autolinking.cmake)\n\n# Set up local includes\ninclude_directories(\n        \"src/main/cpp\"\n)\n\nfind_library(LOG_LIB log)\n\n# Link all libraries together\ntarget_link_libraries(\n        ${PACKAGE_NAME}\n        ${LOG_LIB}\n        android                                   # <-- Android core\n)"
  },
  {
    "path": "packages/react-native-video/android/build.gradle",
    "content": "buildscript {\n  // Buildscript is evaluated before everything else so we can't use getExtOrDefault\n  def kotlin_version = rootProject.ext.has(\"kotlinVersion\") ? rootProject.ext.get(\"kotlinVersion\") : project.properties[\"RNVideo_kotlinVersion\"]\n  def minKotlin_version = project.properties[\"RNVideo_minKotlinVersion\"]\n\n  def androidx_version = rootProject.ext.has('androidxActivityVersion') ? rootProject.ext.get('androidxActivityVersion') : project.properties['RNVideo_androidxActivityVersion']\n  def minAndroidx_version = project.properties[\"RNVideo_androidxActivityVersion\"]\n\n  def isVersionAtLeast = { version, minVersion ->\n    def (major, minor, patch) = version.tokenize('.')\n    def (minMajor, minMinor, minPatch) = minVersion.tokenize('.')\n\n    // major version is greater\n    if (major.toInteger() > minMajor.toInteger()) return true\n\n    // major version is equal, minor version is greater\n    if (major.toInteger() == minMajor.toInteger() && minor.toInteger() > minMinor.toInteger()) return true\n\n    // major version is equal, minor version is equal, patch version is greater\n    if (major.toInteger() == minMajor.toInteger() && minor.toInteger() == minMinor.toInteger() && patch.toInteger() >= minPatch.toInteger()) return true\n\n    return false\n  }\n\n  repositories {\n    google()\n    mavenCentral()\n  }\n\n  dependencies {\n    classpath \"com.android.tools.build:gradle:7.2.1\"\n    // noinspection DifferentKotlinGradleVersion\n    classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n  }\n\n  ext {\n    if (!isVersionAtLeast(kotlin_version, minKotlin_version)) {\n      throw new GradleException(\"Kotlin version must be at least $minKotlin_version (current: $kotlin_version)\")\n    }\n\n    if (!isVersionAtLeast(androidx_version, minAndroidx_version)) {\n      throw new GradleException(\"AndroidX version must be at least $minAndroidx_version (current: $androidx_version)\")\n    }\n  }\n}\n\ndef reactNativeArchitectures() {\n  def value = rootProject.getProperties().get(\"reactNativeArchitectures\")\n  return value ? value.split(\",\") : [\"armeabi-v7a\", \"x86\", \"x86_64\", \"arm64-v8a\"]\n}\n\ndef isNewArchitectureEnabled() {\n  return rootProject.hasProperty(\"newArchEnabled\") && rootProject.getProperty(\"newArchEnabled\") == \"true\"\n}\n\napply plugin: \"com.android.library\"\napply plugin: \"kotlin-android\"\napply from: '../nitrogen/generated/android/ReactNativeVideo+autolinking.gradle'\napply from: './fix-prefab.gradle'\n\nif (isNewArchitectureEnabled()) {\n  apply plugin: \"com.facebook.react\"\n}\n\ndef getExtOrDefault(name) {\n  return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties[\"RNVideo_\" + name]\n}\n\ndef getExtOrIntegerDefault(name) {\n  return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties[\"RNVideo_\" + name]).toInteger()\n}\n\ndef supportsNamespace() {\n  def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')\n  def major = parsed[0].toInteger()\n  def minor = parsed[1].toInteger()\n\n  // Namespace support was added in 7.3.0\n  return (major == 7 && minor >= 3) || major >= 8\n}\n\ndef ExoplayerDependenciesList = [\n  \"useExoplayerDash\",\n  \"useExoplayerHls\",\n]\n\ndef ExoplayerDependencies = ExoplayerDependenciesList.collectEntries { property ->\n  [(property): getExtOrDefault(property)?.toBoolean() ?: false]\n}\n\n// Print Configuration\nprintln \"[ReactNativeVideo] Exoplayer Dependencies Configuration:\"\nExoplayerDependenciesList.each { propertyName ->\n  def propertyValue = ExoplayerDependencies[propertyName]\n  println \"$propertyName: $propertyValue\"\n}\n\nandroid {\n  if (supportsNamespace()) {\n    namespace \"com.twg.video\"\n\n    sourceSets {\n      main {\n        manifest.srcFile \"src/main/AndroidManifestNew.xml\"\n      }\n    }\n  }\n\n  ndkVersion getExtOrDefault(\"ndkVersion\")\n  compileSdkVersion getExtOrIntegerDefault(\"compileSdkVersion\")\n\n  defaultConfig {\n    minSdkVersion getExtOrIntegerDefault(\"minSdkVersion\")\n    targetSdkVersion getExtOrIntegerDefault(\"targetSdkVersion\")\n\n    buildConfigField \"boolean\", \"IS_NEW_ARCHITECTURE_ENABLED\", isNewArchitectureEnabled().toString()\n    buildConfigField \"boolean\", \"USE_EXOPLAYER_DASH\", ExoplayerDependencies.useExoplayerDash.toString()\n    buildConfigField \"boolean\", \"USE_EXOPLAYER_HLS\", ExoplayerDependencies.useExoplayerHls.toString()\n\n    externalNativeBuild {\n      cmake {\n        cppFlags \"-O2 -frtti -fexceptions -Wall -fstack-protector-all\"\n        arguments \"-DANDROID_STL=c++_shared\", \"-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON\"\n        abiFilters (*reactNativeArchitectures())\n      }\n    }\n  }\n\n  externalNativeBuild {\n    cmake {\n      path \"CMakeLists.txt\"\n    }\n  }\n\n  packagingOptions {\n    excludes = [\n            \"META-INF\",\n            \"META-INF/**\",\n            \"**/libc++_shared.so\",\n            \"**/libfbjni.so\",\n            \"**/libjsi.so\",\n            \"**/libfolly_json.so\",\n            \"**/libfolly_runtime.so\",\n            \"**/libglog.so\",\n            \"**/libhermes.so\",\n            \"**/libhermes-executor-debug.so\",\n            \"**/libhermes_executor.so\",\n            \"**/libreactnativejni.so\",\n            \"**/libturbomodulejsijni.so\",\n            \"**/libreact_nativemodule_core.so\",\n            \"**/libjscexecutor.so\",\n            \"**/libreactnative.so\"\n    ]\n  }\n\n  buildFeatures {\n    buildConfig true\n    prefab true\n  }\n\n  buildTypes {\n    release {\n      minifyEnabled false\n    }\n  }\n\n  lintOptions {\n    disable \"GradleCompatible\"\n  }\n\n  compileOptions {\n    sourceCompatibility JavaVersion.VERSION_1_8\n    targetCompatibility JavaVersion.VERSION_1_8\n  }\n\n  sourceSets {\n    main {\n      if (!isNewArchitectureEnabled()) {\n        java.srcDirs += [\"src/paper/java\"]\n      }\n\n      if (!ExoplayerDependencies.useExoplayerDash) {\n        java.srcDirs += [\"src/stubs/dash\"]\n      }\n\n      if (!ExoplayerDependencies.useExoplayerHls) {\n        java.srcDirs += [\"src/stubs/hls\"]\n      }\n    }\n  }\n}\n\nrepositories {\n  mavenCentral()\n  google()\n}\n\ndef kotlin_version = getExtOrDefault(\"kotlinVersion\")\ndef media3_version = getExtOrDefault(\"media3Version\")\ndef androidxCore_version = getExtOrDefault(\"androidxCoreVersion\")\ndef androidxActivity_version = getExtOrDefault(\"androidxActivityVersion\")\n\ndependencies {\n  // For < 0.71, this will be from the local maven repo\n  // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin\n  //noinspection GradleDynamicVersion\n  implementation \"com.facebook.react:react-native:+\"\n  implementation \"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version\"\n\n  // Add a dependency on NitroModules\n  implementation project(\":react-native-nitro-modules\")\n\n  implementation \"androidx.core:core-ktx:$androidxCore_version\"\n  implementation \"androidx.activity:activity-ktx:$androidxActivity_version\"\n\n  // For media playback using ExoPlayer\n  implementation \"androidx.media3:media3-exoplayer:$media3_version\"\n\n  // Common functionality used across multiple media libraries\n  implementation \"androidx.media3:media3-common:$media3_version\"\n\n  // For building media playback UIs\n  implementation \"androidx.media3:media3-ui:$media3_version\"\n\n  // Common functionality for loading data\n  implementation \"androidx.media3:media3-datasource:$media3_version\"\n\n  // For loading data using the OkHttp network stack\n  implementation \"androidx.media3:media3-datasource-okhttp:$media3_version\"\n\n  // For Media Session\n  implementation \"androidx.media3:media3-session:$media3_version\"\n\n  if (ExoplayerDependencies.useExoplayerDash) {\n    implementation \"androidx.media3:media3-exoplayer-dash:$media3_version\"\n  }\n\n  if (ExoplayerDependencies.useExoplayerHls) {\n    implementation \"androidx.media3:media3-exoplayer-hls:$media3_version\"\n  }\n}\n\nif (isNewArchitectureEnabled()) {\n  react {\n    jsRootDir = file(\"../src/spec/fabric\")\n    libraryName = \"RNCVideoView\"\n    codegenJavaPackageName = \"com.twg.video\"\n  }\n}\n\n"
  },
  {
    "path": "packages/react-native-video/android/fix-prefab.gradle",
    "content": "tasks.configureEach { task ->\n  // Make sure that we generate our prefab publication file only after having built the native library\n  // so that not a header publication file, but a full configuration publication will be generated, which\n  // will include the .so file\n\n  def prefabConfigurePattern = ~/^prefab(.+)ConfigurePackage$/\n  def matcher = task.name =~ prefabConfigurePattern\n  if (matcher.matches()) {\n    def variantName = matcher[0][1]\n    task.outputs.upToDateWhen { false }\n    task.dependsOn(\"externalNativeBuild${variantName}\")\n  }\n}\n\nafterEvaluate {\n  def abis = reactNativeArchitectures()\n  rootProject.allprojects.each { proj ->\n    if (proj === rootProject) return\n\n    def dependsOnThisLib = proj.configurations.findAll { it.canBeResolved }.any { config ->\n      config.dependencies.any { dep ->\n        dep.group == project.group && dep.name == project.name\n      }\n    }\n    if (!dependsOnThisLib && proj != project) return\n\n    if (!proj.plugins.hasPlugin('com.android.application') && !proj.plugins.hasPlugin('com.android.library')) {\n      return\n    }\n\n    def variants = proj.android.hasProperty('applicationVariants') ? proj.android.applicationVariants : proj.android.libraryVariants\n    // Touch the prefab_config.json files to ensure that in ExternalNativeJsonGenerator.kt we will re-trigger the prefab CLI to\n    // generate a libnameConfig.cmake file that will contain our native library (.so).\n    // See this condition: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeJsonGenerator.kt;l=207-219?q=createPrefabBuildSystemGlue\n    variants.all { variant ->\n      def variantName = variant.name\n      abis.each { abi ->\n        def searchDir = new File(proj.projectDir, \".cxx/${variantName}\")\n        if (!searchDir.exists()) return\n        def matches = []\n        searchDir.eachDir { randomDir ->\n          def prefabFile = new File(randomDir, \"${abi}/prefab_config.json\")\n          if (prefabFile.exists()) matches << prefabFile\n        }\n        matches.each { prefabConfig ->\n          prefabConfig.setLastModified(System.currentTimeMillis())\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "packages/react-native-video/android/gradle.properties",
    "content": "RNVideo_kotlinVersion=1.9.24\nRNVideo_minKotlinVersion=1.8.0\nRNVideo_minSdkVersion=24\nRNVideo_targetSdkVersion=35\nRNVideo_compileSdkVersion=35\nRNVideo_ndkversion=27.1.12297006\n\nRNVideo_useExoplayerDash=true\nRNVideo_useExoplayerHls=true\n\nRNVideo_media3Version=1.4.1\nRNVideo_androidxCoreVersion=1.13.1\nRNVideo_androidxActivityVersion=1.9.3\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <uses-permission android:name=\"android.permission.INTERNET\" />\n</manifest>\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/AndroidManifestNew.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <uses-permission android:name=\"android.permission.INTERNET\" />\n</manifest>\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/cpp/cpp-adapter.cpp",
    "content": "#include <jni.h>\n#include \"ReactNativeVideoOnLoad.hpp\"\n\nJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {\n  return margelo::nitro::video::initialize(vm);\n}"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/AudioFocusManager.kt",
    "content": "package com.twg.video.core\n\nimport android.content.Context\nimport android.media.AudioAttributes\nimport android.media.AudioManager\nimport android.media.AudioFocusRequest\nimport android.os.Build\nimport androidx.annotation.OptIn\nimport androidx.annotation.RequiresApi\nimport androidx.media3.common.util.UnstableApi\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.video.HybridVideoPlayer\nimport com.margelo.nitro.video.MixAudioMode\nimport kotlin.getValue\nimport com.twg.video.core.utils.Threading\n\n@OptIn(UnstableApi::class)\nclass AudioFocusManager() {\n  private val players = mutableListOf<HybridVideoPlayer>()\n  private var currentMixAudioMode: MixAudioMode? = null\n  private var audioFocusRequest: AudioFocusRequest? = null\n\n  val appContext by lazy {\n    NitroModules.applicationContext ?: throw UnknownError()\n  }\n\n  private val audioManager by lazy {\n    appContext.getSystemService(Context.AUDIO_SERVICE) as? AudioManager ?: throw UnknownError()\n  }\n\n  private val audioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange ->\n    Threading.runOnMainThread {\n      when (focusChange) {\n        AudioManager.AUDIOFOCUS_GAIN -> {\n          unDuckActivePlayers()\n        }\n        AudioManager.AUDIOFOCUS_LOSS -> {\n          pauseActivePlayers()\n          currentMixAudioMode = null\n          audioFocusRequest = null\n        }\n        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {\n          val mixAudioMode = determineRequiredMixMode()\n          if (mixAudioMode != MixAudioMode.MIXWITHOTHERS) {\n            pauseActivePlayers()\n            currentMixAudioMode = null\n            audioFocusRequest = null\n          }\n        }\n        AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {\n          val mixAudioMode = determineRequiredMixMode()\n          when (mixAudioMode) {\n            MixAudioMode.DONOTMIX -> pauseActivePlayers()\n            else -> duckActivePlayers()\n          }\n        }\n      }\n    }\n  }\n\n  fun registerPlayer(player: HybridVideoPlayer) {\n    if (!players.contains(player)) {\n      players.add(player)\n    }\n  }\n\n  fun unregisterPlayer(player: HybridVideoPlayer) {\n    players.remove(player)\n    if (players.isEmpty()) {\n      abandonAudioFocus()\n    } else {\n      requestAudioFocusUpdate()\n    }\n  }\n\n  fun requestAudioFocusUpdate() {\n    Threading.runOnMainThread {\n      val requiredMixMode = determineRequiredMixMode()\n\n      if (requiredMixMode == null) {\n        abandonAudioFocus()\n        return@runOnMainThread\n      }\n\n      if (currentMixAudioMode != requiredMixMode) {\n        requestAudioFocus(requiredMixMode)\n      }\n    }\n  }\n\n  private fun determineRequiredMixMode(): MixAudioMode? {\n    val activePlayers = players.filter { player ->\n      player.player.isPlaying && player.player.volume != 0f\n    }\n\n    if (activePlayers.isEmpty()) {\n      return null\n    }\n\n    val anyPlayerNeedsMixWithOthers = activePlayers.any { player ->\n      player.mixAudioMode == MixAudioMode.MIXWITHOTHERS\n    }\n\n    if (anyPlayerNeedsMixWithOthers) {\n      abandonAudioFocus()\n      return MixAudioMode.MIXWITHOTHERS\n    }\n\n    val anyPlayerNeedsExclusiveFocus = activePlayers.any { player ->\n      player.mixAudioMode == MixAudioMode.DONOTMIX\n    }\n\n    val anyPlayerNeedsDucking = activePlayers.any { player ->\n      player.mixAudioMode == MixAudioMode.DUCKOTHERS\n    }\n\n    return when {\n      anyPlayerNeedsExclusiveFocus -> MixAudioMode.DONOTMIX\n      anyPlayerNeedsDucking -> MixAudioMode.DUCKOTHERS\n      else -> MixAudioMode.AUTO\n    }\n  }\n\n    private fun requestAudioFocus(mixMode: MixAudioMode) {\n    val focusType = when (mixMode) {\n      MixAudioMode.DONOTMIX -> AudioManager.AUDIOFOCUS_GAIN\n      MixAudioMode.DUCKOTHERS -> AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK\n      MixAudioMode.AUTO -> AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK\n      MixAudioMode.MIXWITHOTHERS -> return // No focus needed for mix with others\n    }\n\n    val result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n      requestAudioFocusNew(focusType)\n    } else {\n      requestAudioFocusLegacy(focusType)\n    }\n\n    if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {\n      currentMixAudioMode = mixMode\n    } else {\n      currentMixAudioMode = null\n      // Pause players since audio focus couldn't be obtained\n      pauseActivePlayers()\n    }\n  }\n\n  @RequiresApi(Build.VERSION_CODES.O)\n  private fun requestAudioFocusNew(focusType: Int): Int {\n\n    audioFocusRequest = AudioFocusRequest.Builder(focusType)\n      .setAudioAttributes(\n        AudioAttributes.Builder().run {\n          setUsage(AudioAttributes.USAGE_MEDIA)\n          setContentType(AudioAttributes.CONTENT_TYPE_MOVIE)\n          build()\n        }\n      )\n      .setOnAudioFocusChangeListener(audioFocusChangeListener)\n      .build()\n\n    return audioManager.requestAudioFocus(audioFocusRequest!!)\n  }\n\n  @Suppress(\"DEPRECATION\")\n  private fun requestAudioFocusLegacy(focusType: Int): Int {\n    return audioManager.requestAudioFocus(\n      audioFocusChangeListener,\n      AudioManager.STREAM_MUSIC,\n      focusType\n    )\n  }\n\n  private fun abandonAudioFocus() {\n    if (currentMixAudioMode != null) {\n      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n        abandonAudioFocusNew()\n      } else {\n        abandonAudioFocusLegacy()\n      }\n      currentMixAudioMode = null\n      audioFocusRequest = null\n    }\n  }\n\n  @RequiresApi(Build.VERSION_CODES.O)\n  private fun abandonAudioFocusNew() {\n    audioFocusRequest?.let { request ->\n      audioManager.abandonAudioFocusRequest(request)\n    }\n  }\n\n  @Suppress(\"DEPRECATION\")\n  private fun abandonAudioFocusLegacy() {\n    audioManager.abandonAudioFocus(audioFocusChangeListener)\n  }\n\n  private fun pauseActivePlayers() {\n    Threading.runOnMainThread {\n      players.forEach { player ->\n        player.player.let { mediaPlayer ->\n          if (mediaPlayer.volume != 0f && mediaPlayer.isPlaying) {\n            mediaPlayer.pause()\n          }\n        }\n      }\n    }\n  }\n\n  private fun duckActivePlayers() {\n    Threading.runOnMainThread {\n      players.forEach { player ->\n        player.player.let { mediaPlayer ->\n          // We need to duck the volume to 50%. After the audio focus is regained,\n          // we will restore the volume to the user's volume.\n          mediaPlayer.volume = mediaPlayer.volume * 0.5f\n        }\n      }\n    }\n  }\n\n  private fun unDuckActivePlayers() {\n    Threading.runOnMainThread {\n      // Resume players that were paused due to audio focus loss\n      players.forEach { player ->\n        player.player.let { mediaPlayer ->\n          // Restore full volume if it was ducked\n          if (mediaPlayer.volume != 0f && mediaPlayer.volume.toDouble() != player.userVolume) {\n            mediaPlayer.volume = player.userVolume.toFloat()\n          }\n        }\n      }\n    }\n  }\n}\n\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/VideoError.kt",
    "content": "package com.twg.video.core\n\n// Base class for all video errors\nabstract class VideoError(\n    open val code: String,\n    message: String\n) : Error(\"{%@$code::$message@%}\")\n\n// Library related errors\nsealed class LibraryError(code: String, message: String) : VideoError(code, message) {\n  object Deallocated : LibraryError(\n    \"library/deallocated\",\n    \"Object has been deallocated\"\n  )\n\n  object ApplicationContextNotFound : LibraryError(\n    \"library/application-context-not-found\",\n    \"Application context not found\"\n  )\n\n  class MethodNotSupported(val methodName: String) : LibraryError(\n    \"library/method-not-supported\",\n    \"Method $methodName() is not supported on Android\"\n  )\n\n  object DRMPluginNotFound : LibraryError(\n    \"library/drm-plugin-not-found\",\n    \"No DRM plugin have been found, please add one to the project\",\n  )\n}\n\n// Player related errors\nsealed class PlayerError(code: String, message: String) : VideoError(code, message) {\n  object NotInitialized : PlayerError(\n    \"player/not-initialized\",\n    \"Player has not been initialized (Or has been set to null)\"\n  )\n\n  object AssetNotInitialized : PlayerError(\n    \"player/asset-not-initialized\",\n    \"Asset has not been initialized (Or has been set to null)\"\n  )\n\n  object InvalidSource : PlayerError(\n    \"player/invalid-source\",\n    \"Invalid source passed to player\"\n  )\n\n  object Cancelled : PlayerError(\n    \"player/cancelled\",\n    \"Operation was cancelled\"\n  )\n}\n\n// Source related errors\nsealed class SourceError(code: String, message: String) : VideoError(code, message) {\n  class InvalidUri(val uri: String) : SourceError(\n    \"source/invalid-uri\",\n    \"Invalid source file uri: $uri\"\n  )\n\n  class MissingReadFilePermission(val uri: String) : SourceError(\n    \"source/missing-read-file-permission\",\n    \"Missing read file permission for source file at $uri\"\n  )\n\n  class FileDoesNotExist(val uri: String) : SourceError(\n    \"source/file-does-not-exist\",\n    \"File does not exist at URI: $uri\"\n  )\n\n  object FailedToInitializeAsset : SourceError(\n    \"source/failed-to-initialize-asset\",\n    \"Failed to initialize asset\"\n  )\n\n  class UnsupportedContentType(val uri: String) : SourceError(\n    \"source/unsupported-content-type\",\n    \"type of content (${uri}) is not supported\"\n  )\n\n  object Cancelled : SourceError(\n    \"source/cancelled\",\n    \"Operation was cancelled\"\n  )\n}\n\n// View related errors\nsealed class VideoViewError(code: String, message: String) : VideoError(code, message) {\n  class ViewNotFound(val viewId: Int) : VideoViewError(\n    \"view/not-found\",\n    \"View with viewId $viewId not found\"\n  )\n  object ViewIsDeallocated : VideoViewError(\n    \"view/deallocated\",\n    \"Attempt to access a view, but it has been deallocated (or not initialized)\"\n  )\n  object PictureInPictureNotSupported : VideoViewError(\n    \"view/picture-in-picture-not-supported\",\n    \"Picture in picture is not supported on this device\"\n  )\n}\n\n// Unknown error\nclass UnknownError : VideoError(\"unknown/unknown\", \"Unknown error\")\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/VideoManager.kt",
    "content": "package com.twg.video.core\n\nimport android.util.Log\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.UnstableApi\nimport com.facebook.react.bridge.LifecycleEventListener\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.video.HybridVideoPlayer\nimport com.margelo.nitro.video.MixAudioMode\nimport com.twg.video.core.plugins.PluginsRegistry\nimport com.twg.video.view.VideoView\nimport java.lang.ref.WeakReference\n\n@OptIn(UnstableApi::class)\nobject VideoManager : LifecycleEventListener {\n  private const val TAG = \"VideoManager\"\n  \n  // nitroId -> weak VideoView\n  private val views = mutableMapOf<Int, WeakReference<VideoView>>()\n  // player -> list of nitroIds of views that are using this player\n  private val players = mutableMapOf<HybridVideoPlayer, MutableList<Int>>()\n  \n  // Keep track of players that were paused due to PiP so that they can be resumed later\n  private val playersPausedForPip = mutableSetOf<HybridVideoPlayer>()\n  \n  private var currentPipVideoView: WeakReference<VideoView>? = null\n\n  var audioFocusManager = AudioFocusManager()\n\n  private var lastPlayedNitroId: Int? = null\n\n  init {\n    NitroModules.applicationContext?.apply {\n      addLifecycleEventListener(this@VideoManager)\n    }\n  }\n\n  fun requestPictureInPicture(videoView: VideoView): Boolean {\n    Log.d(TAG, \"PiP requested for video nitroId: ${videoView.nitroId}\")\n    \n    if (videoView.isInPictureInPicture) {\n      Log.d(TAG, \"Video nitroId: ${videoView.nitroId} is already in PiP\")\n      return true\n    }\n    \n    // Exit PiP from current video if there is one\n    currentPipVideoView?.get()?.let { currentPipVideo ->\n      if (currentPipVideo != videoView && currentPipVideo.isInPictureInPicture) {\n        Log.d(TAG, \"Forcing exit PiP for video nitroId: ${currentPipVideo.nitroId} to make room for nitroId: ${videoView.nitroId}\")\n        currentPipVideo.forceExitPictureInPicture()\n      }\n    }\n    \n    // Ensure the player that belongs to this view is attached back to this view\n    videoView.hybridPlayer?.movePlayerToVideoView(videoView)\n    \n    // Pause every other player that might be playing in the background so that only the PiP video plays\n    pauseOtherPlayers(videoView)\n    \n    // Set this video as the designated PiP video BEFORE entering PiP mode\n    // This ensures the PictureInPictureHelperFragment callbacks know which video should respond\n    currentPipVideoView = WeakReference(videoView)\n    Log.d(TAG, \"Designated video nitroId: ${videoView.nitroId} as the PiP video\")\n    \n    val success = videoView.internalEnterPictureInPicture()\n    Log.d(TAG, \"PiP enter result for video nitroId: ${videoView.nitroId} = $success\")\n    \n    if (!success) {\n      // If we failed to enter PiP, resume any players we just paused\n      resumePlayersPausedForPip()\n      currentPipVideoView = null\n      Log.w(TAG, \"Failed to enter PiP, clearing designated PiP video\")\n    }\n    \n    return success\n  }\n  \n  fun notifyPictureInPictureExited(videoView: VideoView) {\n    Log.d(TAG, \"PiP exit notification for video nitroId: ${videoView.nitroId}\")\n    currentPipVideoView?.get()?.let { currentPipVideo ->\n      if (currentPipVideo == videoView) {\n        Log.d(TAG, \"Clearing PiP reference for video nitroId: ${videoView.nitroId}\")\n        currentPipVideoView = null\n        // Resume any players that were paused when PiP was entered\n        resumePlayersPausedForPip()\n      }\n    }\n  }\n  \n  fun getCurrentPictureInPictureVideo(): VideoView? {\n    return currentPipVideoView?.get()\n  }\n  \n  fun setCurrentPictureInPictureVideo(videoView: VideoView) {\n    Log.d(TAG, \"Setting current PiP video to nitroId: ${videoView.nitroId}\")\n    currentPipVideoView = WeakReference(videoView)\n  }\n  \n  fun isAnyVideoInPictureInPicture(): Boolean {\n    return currentPipVideoView?.get()?.isInPictureInPicture == true\n  }\n  \n  fun forceExitAllPictureInPicture() {\n    currentPipVideoView?.get()?.let { currentPipVideo ->\n      if (currentPipVideo.isInPictureInPicture) {\n        currentPipVideo.forceExitPictureInPicture()\n      }\n    }\n    currentPipVideoView = null\n  }\n\n  fun maybePassPlayerToView(player: HybridVideoPlayer) {\n    val views = players[player]?.mapNotNull { getVideoViewWeakReferenceByNitroId(it)?.get() } ?: return\n    val latestView = views.lastOrNull() ?: return\n\n    player.movePlayerToVideoView(latestView)\n  }\n\n  fun registerView(view: VideoView) {\n    views[view.nitroId] = WeakReference<VideoView>(view)\n    PluginsRegistry.shared.notifyVideoViewCreated(WeakReference(view))\n  }\n\n  fun unregisterView(view: VideoView) {\n    view.hybridPlayer?.let {\n      removeViewFromPlayer(view, it)\n    }\n\n    // Clean up PiP reference if this view was in PiP\n    currentPipVideoView?.get()?.let { currentPipVideo ->\n      if (currentPipVideo == view) {\n        currentPipVideoView = null\n      }\n    }\n\n    views.remove(view.nitroId)\n    PluginsRegistry.shared.notifyVideoViewDestroyed(WeakReference(view))\n  }\n\n  fun addViewToPlayer(view: VideoView, player: HybridVideoPlayer) {\n    // Add player to list if it doesn't exist (should not happen)\n    if(!players.containsKey(player)) players[player] = mutableListOf()\n\n    // Check if view is already added to player\n    if(players[player]?.contains(view.nitroId) == true) return\n\n    // Add view to player\n    players[player]?.add(view.nitroId)\n  }\n\n  fun removeViewFromPlayer(view: VideoView, player: HybridVideoPlayer) {\n    players[player]?.remove(view.nitroId)\n\n    // If this was the last view using this player, clean up\n    if (players[player]?.isEmpty() == true) {\n      players.remove(player)\n    } else {\n      // If there are other views using this player, move to the latest one\n      maybePassPlayerToView(player)\n    }\n  }\n\n  fun registerPlayer(player: HybridVideoPlayer) {\n    if (!players.containsKey(player)) {\n      players[player] = mutableListOf()\n    }\n\n    audioFocusManager.registerPlayer(player)\n    PluginsRegistry.shared.notifyPlayerCreated(WeakReference(player))\n  }\n\n  fun unregisterPlayer(player: HybridVideoPlayer) {\n    audioFocusManager.unregisterPlayer(player)\n    PluginsRegistry.shared.notifyPlayerDestroyed(WeakReference(player))\n\n    // Remove player from any views that were using it\n    players[player]?.forEach { nitroId ->\n      views[nitroId]?.get()?.let { view ->\n        view.hybridPlayer = null\n      }\n    }\n\n    players.remove(player)\n  }\n\n  fun getPlayerByNitroId(nitroId: Int): HybridVideoPlayer? {\n    return players.keys.find { player ->\n      players[player]?.contains(nitroId) == true\n    }\n  }\n\n  fun updateVideoViewNitroId(oldNitroId: Int, newNitroId: Int, view: VideoView) {\n    // Remove old mapping\n    if (oldNitroId != -1) {\n      views.remove(oldNitroId)\n\n      // Update player mappings\n      players.keys.forEach { player ->\n        players[player]?.let { nitroIds ->\n          if (nitroIds.remove(oldNitroId)) {\n            nitroIds.add(newNitroId)\n    }\n        }\n      }\n    }\n\n    // Add new mapping\n    views[newNitroId] = WeakReference(view)\n  }\n\n  fun getVideoViewWeakReferenceByNitroId(nitroId: Int): WeakReference<VideoView>? {\n    return views[nitroId]\n  }\n\n  // ------------ Lifecycle Handler ------------\n  private fun onAppEnterForeground() {\n    players.keys.forEach { player ->\n      if (player.wasAutoPaused) {\n        player.play()\n      }\n    }\n  }\n\n  private fun onAppEnterBackground() {\n    players.keys.forEach { player ->\n      if (!player.playInBackground && player.isPlaying) {\n        player.wasAutoPaused = player.isPlaying\n        player.pause()\n      }\n    }\n  }\n\n  override fun onHostResume() {\n    onAppEnterForeground()\n  }\n\n  override fun onHostPause() {\n    onAppEnterBackground()\n  }\n\n  override fun onHostDestroy() {\n    forceExitAllPictureInPicture()\n  }\n\n  fun pauseOtherPlayers(pipVideoView: VideoView) {\n    val pipPlayer = pipVideoView.hybridPlayer\n    playersPausedForPip.clear()\n\n    players.keys.forEach { player ->\n      // Skip the player that is used for the PiP view\n      if (player == pipPlayer) return@forEach\n\n      // Pause only if it is currently playing\n      if (player.isPlaying && player.mixAudioMode != MixAudioMode.MIXWITHOTHERS) {\n        player.pause()\n        playersPausedForPip.add(player)\n        Log.v(TAG, \"Paused player for PiP (nitroIds: ${players[player]})\")\n      }\n    }\n  }\n\n  private fun resumePlayersPausedForPip() {\n    playersPausedForPip.forEach { player ->\n      // Ensure the player is attached to the latest visible VideoView before resuming\n      maybePassPlayerToView(player)\n\n      if (!player.isPlaying) {\n        player.play()\n        Log.v(TAG, \"Resumed player after PiP exit (nitroIds: ${players[player]})\")\n      }\n    }\n    playersPausedForPip.clear()\n  }\n\n  fun getAnyPlayingVideoView(): VideoView? {\n    return views.values.firstOrNull { ref ->\n      ref.get()?.hybridPlayer?.isPlaying == true\n    }?.get()\n  }\n\n  fun setLastPlayedPlayer(player: HybridVideoPlayer) {\n    // Resolve to the latest view using this player (usually the last one in the list)\n    val nitroIds = players[player] ?: return\n    if (nitroIds.isNotEmpty()) {\n      lastPlayedNitroId = nitroIds.last()\n    }\n  }\n\n  fun getLastPlayedVideoView(): VideoView? {\n    return lastPlayedNitroId?.let { views[it]?.get() }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/extensions/ResizeMode+AspectRatioFrameLayout.kt",
    "content": "package com.twg.video.core.extensions\n\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.ui.AspectRatioFrameLayout\nimport com.margelo.nitro.video.ResizeMode\n\n@OptIn(UnstableApi::class)\n/**\n * Converts a [ResizeMode] to a [AspectRatioFrameLayout] resize mode.\n * @return The corresponding [AspectRatioFrameLayout] resize mode.\n */\nfun ResizeMode.toAspectRatioFrameLayout(): Int {\n  return when (this) {\n    ResizeMode.CONTAIN -> AspectRatioFrameLayout.RESIZE_MODE_FIT\n    ResizeMode.COVER -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM\n    ResizeMode.STRETCH -> AspectRatioFrameLayout.RESIZE_MODE_FILL\n    ResizeMode.NONE -> AspectRatioFrameLayout.RESIZE_MODE_FIT\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/extensions/SubtitleType+toString.kt",
    "content": "package com.twg.video.core.extensions\n\nimport com.margelo.nitro.video.SubtitleType\n\nfun SubtitleType.toStringExtension(): String {\n  return when {\n    this == SubtitleType.AUTO -> \"auto\"\n    this == SubtitleType.VTT -> \"vtt\"\n    this == SubtitleType.SRT -> \"srt\"\n    this == SubtitleType.SSA -> \"ssa\"\n    this == SubtitleType.ASS -> \"ass\"\n    else -> throw IllegalArgumentException(\"Unknown SubtitleType: $this\")\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/extensions/VideoPlaybackService+ServiceManagment.kt",
    "content": "package com.twg.video.core.extensions\n\nimport android.content.Context\nimport android.content.Context.BIND_AUTO_CREATE\nimport android.content.Context.BIND_INCLUDE_CAPABILITIES\nimport android.content.Intent\nimport android.os.Build\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.UnstableApi\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.video.HybridVideoPlayer\nimport com.twg.video.core.services.playback.VideoPlaybackService\nimport com.twg.video.core.services.playback.VideoPlaybackServiceConnection\n\nfun VideoPlaybackService.Companion.startService(\n  context: Context,\n  serviceConnection: VideoPlaybackServiceConnection\n) {\n  val reactContext = NitroModules.applicationContext ?: return\n\n  val intent = Intent(context, VideoPlaybackService::class.java)\n  intent.action = VIDEO_PLAYBACK_SERVICE_INTERFACE\n\n  // Use startForegroundService on O+ so the service has the opportunity to call\n  // startForeground(...) quickly and avoid ForegroundServiceDidNotStartInTimeException.\n  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n    try {\n      reactContext.startForegroundService(intent)\n    } catch (_: Exception) {\n      // Fall back to startService if anything goes wrong\n      try { reactContext.startService(intent) } catch (_: Exception) {}\n    }\n  } else {\n    reactContext.startService(intent)\n  }\n\n  val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n    BIND_AUTO_CREATE or BIND_INCLUDE_CAPABILITIES\n  } else {\n    BIND_AUTO_CREATE\n  }\n\n  context.bindService(intent, serviceConnection, flags)\n}\n\n@OptIn(UnstableApi::class)\nfun VideoPlaybackService.Companion.stopService(\n  player: HybridVideoPlayer,\n  serviceConnection: VideoPlaybackServiceConnection\n) {\n  try {\n    // Unregister the player first; this might stop the service if no players remain\n    serviceConnection.unregisterPlayer(player)\n    // Ask service (if still connected) to stop when idle\n    try { serviceConnection.serviceBinder?.service?.stopIfNoPlayers() } catch (_: Exception) {}\n    // Then unbind\n    NitroModules.applicationContext?.currentActivity?.unbindService(serviceConnection)\n  } catch (_: Exception) {}\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/fragments/FullscreenVideoFragment.kt",
    "content": "package com.twg.video.core.fragments\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport android.content.res.Configuration\nimport android.os.Build\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.WindowInsets\nimport android.view.WindowInsetsController\nimport android.view.WindowManager\nimport android.widget.FrameLayout\nimport android.widget.ImageButton\nimport androidx.activity.OnBackPressedCallback\nimport androidx.annotation.OptIn\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.Fragment\nimport androidx.media3.common.util.UnstableApi\nimport com.twg.video.core.utils.PictureInPictureUtils.createPictureInPictureParams\nimport com.twg.video.core.utils.SmallVideoPlayerOptimizer\nimport com.twg.video.view.VideoView\nimport java.util.UUID\n\n@OptIn(UnstableApi::class)\nclass FullscreenVideoFragment(private val videoView: VideoView) : Fragment() {\n  val id: String = UUID.randomUUID().toString()\n\n  private var container: FrameLayout? = null\n  private var originalPlayerParent: ViewGroup? = null\n  private var originalPlayerLayoutParams: ViewGroup.LayoutParams? = null\n  private var rootContentViews: List<View> = listOf()\n\n  // Back press callback to handle back navigation\n  private val backPressCallback = object : OnBackPressedCallback(true) {\n    override fun handleOnBackPressed() {\n      videoView.exitFullscreen()\n    }\n  }\n\n  override fun onCreateView(\n    inflater: LayoutInflater,\n    container: ViewGroup?,\n    savedInstanceState: Bundle?\n  ): View? {\n    // Create a fullscreen container\n    this.container = FrameLayout(requireContext()).apply {\n      layoutParams = ViewGroup.LayoutParams(\n        ViewGroup.LayoutParams.MATCH_PARENT,\n        ViewGroup.LayoutParams.MATCH_PARENT\n      )\n      setBackgroundColor(android.graphics.Color.BLACK)\n      keepScreenOn = true\n    }\n    return this.container\n  }\n\n  override fun onResume() {\n    super.onResume()\n\n    // System UI is re-enabled when user have exited app and go back\n    // We need to hide it again\n    hideSystemUI()\n  }\n\n  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n    super.onViewCreated(view, savedInstanceState)\n\n    // Register back press callback\n    requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressCallback)\n\n    enterFullscreenMode()\n    setupPlayerView()\n    hideSystemUI()\n\n    // Update PiP params if supported\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n      try {\n        val params = createPictureInPictureParams(videoView)\n        requireActivity().setPictureInPictureParams(params)\n      } catch (_: Exception) {}\n    }\n  }\n\n  override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {\n    super.onPictureInPictureModeChanged(isInPictureInPictureMode)\n\n    if (isInPictureInPictureMode) {\n      videoView.playerView.useController = false\n      videoView.playerView.controllerAutoShow = false\n    } else {\n      videoView.playerView.useController = videoView.useController\n      videoView.playerView.controllerAutoShow = true\n    }\n  }\n\n  override fun onConfigurationChanged(newConfig: Configuration) {\n    super.onConfigurationChanged(newConfig)\n\n    val isInPictureInPictureMode = requireActivity().isInPictureInPictureMode\n\n    if (isInPictureInPictureMode) {\n      videoView.playerView.useController = false\n      videoView.playerView.controllerAutoShow = false\n    } else {\n      videoView.playerView.useController = videoView.useController\n      videoView.playerView.controllerAutoShow = true\n    }\n  }\n\n  private fun enterFullscreenMode() {\n    // Store original parent and layout params\n    originalPlayerParent = videoView.playerView.parent as? ViewGroup\n    originalPlayerLayoutParams = videoView.playerView.layoutParams\n\n    // Remove player from original parent\n    originalPlayerParent?.removeView(videoView.playerView)\n\n    // Hide all root content views\n    val currentActivity = requireActivity()\n    val rootContent = currentActivity.window.decorView.findViewById<ViewGroup>(android.R.id.content)\n    rootContentViews = (0 until rootContent.childCount)\n      .map { rootContent.getChildAt(it) }\n      .filter { it.isVisible }\n\n    rootContentViews.forEach { view ->\n      view.visibility = View.GONE\n    }\n\n    // Add our fullscreen container to root\n    rootContent.addView(container,\n      ViewGroup.LayoutParams(\n        ViewGroup.LayoutParams.MATCH_PARENT,\n        ViewGroup.LayoutParams.MATCH_PARENT\n      )\n    )\n  }\n\n  private fun setupPlayerView() {\n    // Add PlayerView to our container\n    container?.addView(videoView.playerView,\n      FrameLayout.LayoutParams(\n        FrameLayout.LayoutParams.MATCH_PARENT,\n        FrameLayout.LayoutParams.MATCH_PARENT\n      )\n    )\n\n    videoView.playerView.setBackgroundColor(android.graphics.Color.BLACK)\n    videoView.playerView.setShutterBackgroundColor(android.graphics.Color.BLACK)\n\n    // We need show controls in fullscreen\n    videoView.playerView.useController = true\n\n    setupFullscreenButton()\n    videoView.playerView.setShowSubtitleButton(true)\n    \n    // Apply optimizations based on video player size in fullscreen mode\n    SmallVideoPlayerOptimizer.applyOptimizations(videoView.playerView, requireContext(), isFullscreen = true)\n  }\n\n  @SuppressLint(\"PrivateResource\")\n  private fun setupFullscreenButton() {\n    videoView.playerView.setFullscreenButtonClickListener { _ ->\n      videoView.exitFullscreen()\n    }\n\n    // Change icon to exit fullscreen\n    val button = videoView.playerView.findViewById<ImageButton>(androidx.media3.ui.R.id.exo_fullscreen)\n    button?.setImageResource(androidx.media3.ui.R.drawable.exo_icon_fullscreen_exit)\n  }\n\n  @Suppress(\"DEPRECATION\")\n  private fun hideSystemUI() {\n    val currentActivity = requireActivity()\n    container?.let { container ->\n      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n        container.fitsSystemWindows = false\n        container.windowInsetsController?.let { controller ->\n          controller.hide(WindowInsets.Type.systemBars())\n          controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE\n        }\n      } else {\n        currentActivity.window.decorView.systemUiVisibility = (\n          View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY\n          or View.SYSTEM_UI_FLAG_LAYOUT_STABLE\n          or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION\n          or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN\n          or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION\n          or View.SYSTEM_UI_FLAG_FULLSCREEN\n        )\n      }\n    }\n  }\n\n  @Suppress(\"DEPRECATION\")\n  private fun restoreSystemUI() {\n    val currentActivity = requireActivity()\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n      container?.windowInsetsController?.show(WindowInsets.Type.systemBars())\n    } else {\n      currentActivity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE\n    }\n  }\n\n  fun exitFullscreen() {\n    // Remove back press callback since we're exiting\n    backPressCallback.remove()\n\n    restoreSystemUI()\n\n    // Keep controls disabled if in PiP mode - media session creates its own controls for PiP\n    val isInPictureInPictureMode = requireActivity().isInPictureInPictureMode\n    if (isInPictureInPictureMode) {\n      videoView.playerView.useController = false\n    } else if (videoView.useController == false) {\n      videoView.playerView.useController = false\n    }\n\n    // Ensure PlayerView keeps black background when returning to normal mode\n    videoView.playerView.setBackgroundColor(android.graphics.Color.BLACK)\n    videoView.playerView.setShutterBackgroundColor(android.graphics.Color.BLACK)\n\n  // Remove PlayerView from our container\n  container?.removeView(videoView.playerView)\n\n    // Remove our container from root\n    val currentActivity = requireActivity()\n    val rootContent = currentActivity.window.decorView.findViewById<ViewGroup>(android.R.id.content)\n    rootContent.removeView(container)\n\n    // Restore root content views\n    rootContentViews.forEach { it.visibility = View.VISIBLE }\n    rootContentViews = listOf()\n\n    // Safely restore PlayerView to original parent\n    // First, ensure PlayerView is removed from any current parent\n    val currentParent = videoView.playerView.parent as? ViewGroup\n    currentParent?.removeView(videoView.playerView)\n\n    // Now add it back to the original parent if it's not already the parent\n    if (videoView.playerView.parent != originalPlayerParent) {\n      originalPlayerParent?.addView(videoView.playerView, originalPlayerLayoutParams)\n    }\n\n    // Remove this fragment\n    parentFragmentManager.beginTransaction()\n      .remove(this)\n      .commitAllowingStateLoss()\n\n    // Notify VideoView that we've exited fullscreen\n    videoView.isInFullscreen = false\n  }\n\n\n\n  override fun onDestroy() {\n    super.onDestroy()\n\n    // Ensure we clean up properly if fragment is destroyed\n    if (videoView.isInFullscreen) {\n      exitFullscreen()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/fragments/PictureInPictureHelperFragment.kt",
    "content": "package com.twg.video.core.fragments\n\nimport android.content.res.Configuration\nimport android.os.Bundle\nimport android.os.Handler\nimport android.os.Looper\nimport android.util.Log\nimport androidx.annotation.OptIn\nimport androidx.fragment.app.Fragment\nimport androidx.media3.common.util.UnstableApi\nimport com.twg.video.core.VideoManager\nimport com.twg.video.view.VideoView\nimport java.util.UUID\n\n@OptIn(UnstableApi::class)\nclass PictureInPictureHelperFragment(private val videoView: VideoView) : Fragment() {\n  val id: String = UUID.randomUUID().toString()\n\n  override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {\n    super.onPictureInPictureModeChanged(isInPictureInPictureMode)\n\n    if (isInPictureInPictureMode) {\n      var currentPipVideo = VideoManager.getCurrentPictureInPictureVideo()\n      \n      if (currentPipVideo == null) {\n        synchronized(VideoManager) {\n          currentPipVideo = VideoManager.getCurrentPictureInPictureVideo()\n          if (currentPipVideo == null) {\n            if (videoView.hybridPlayer?.isPlaying == true) {\n              val lastPlayed = VideoManager.getLastPlayedVideoView()\n              val shouldDesignate = lastPlayed == null || lastPlayed.nitroId == videoView.nitroId\n\n              if (shouldDesignate) {\n                VideoManager.setCurrentPictureInPictureVideo(videoView)\n                videoView.hybridPlayer?.movePlayerToVideoView(videoView)\n                VideoManager.pauseOtherPlayers(videoView)\n                currentPipVideo = videoView\n              }\n            } else {\n              if (!VideoManager.isAnyVideoInPictureInPicture()) {\n                val lastPlayed = VideoManager.getLastPlayedVideoView()\n                val targetView = lastPlayed ?: videoView\n\n                VideoManager.setCurrentPictureInPictureVideo(targetView)\n                targetView.hybridPlayer?.movePlayerToVideoView(targetView)\n                VideoManager.pauseOtherPlayers(targetView)\n                currentPipVideo = targetView\n              }\n            }\n          }\n        }\n      }\n      \n      if (currentPipVideo == videoView) {\n        // Disable controls immediately when entering PiP - media session creates its own controls for PiP\n        videoView.playerView.useController = false\n        videoView.playerView.controllerAutoShow = false\n\n        // If we're currently in fullscreen, exit it first to prevent parent conflicts\n        if (videoView.isInFullscreen) {\n          try {\n            videoView.exitFullscreen()\n            // Post hideRootContentViews to main thread to ensure it runs after exitFullscreen completes\n            Handler(Looper.getMainLooper()).post {\n              videoView.hideRootContentViews()\n              videoView.isInPictureInPicture = true\n            }\n          } catch (e: Exception) {\n            Log.w(\"ReactNativeVideo\", \"Failed to exit fullscreen before entering PiP for nitroId: ${videoView.nitroId}\", e)\n            videoView.hideRootContentViews()\n            videoView.isInPictureInPicture = true\n          }\n        } else {\n          // Now move the PlayerView to the root for PiP and hide content\n          videoView.hideRootContentViews()\n          videoView.isInPictureInPicture = true\n        }\n      }\n    } else {\n      if (videoView.isInPictureInPicture) {\n        videoView.exitPictureInPicture()\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/player/DRMManagerSpec.kt",
    "content": "package com.twg.video.core.player\n\nimport androidx.annotation.OptIn\nimport androidx.media3.common.MediaItem\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.common.util.Util\nimport androidx.media3.exoplayer.drm.DrmSessionManager\nimport com.margelo.nitro.video.NativeDrmParams\nimport java.util.UUID\n\n@OptIn(UnstableApi::class)\ninterface DRMManagerSpec {\n  fun buildDrmSessionManager(drmParams: NativeDrmParams): DrmSessionManager {\n    val drmScheme = drmParams.type ?: \"widevine\"\n    val drmUuid = Util.getDrmUuid(drmScheme)\n\n    return buildDrmSessionManager(drmParams, drmUuid)\n  }\n\n  fun buildDrmSessionManager(drmParams: NativeDrmParams, drmUuid: UUID?, retryCount: Int = 0): DrmSessionManager\n\n  fun getDRMConfiguration(drmParams: NativeDrmParams): MediaItem.DrmConfiguration\n}"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/player/DataSourceFactoryUtils.kt",
    "content": "package com.twg.video.core.player\n\nimport android.content.Context\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.common.util.Util\nimport androidx.media3.datasource.DefaultDataSource\nimport androidx.media3.datasource.okhttp.OkHttpDataSource\nimport com.facebook.react.bridge.ReactContext\nimport com.facebook.react.modules.network.CookieJarContainer\nimport com.facebook.react.modules.network.ForwardingCookieHandler\nimport com.facebook.react.modules.network.OkHttpClientProvider\nimport com.margelo.nitro.video.HybridVideoPlayerSourceSpec\nimport okhttp3.JavaNetCookieJar\n\nfun buildBaseDataSourceFactory(context: Context, source: HybridVideoPlayerSourceSpec): DefaultDataSource.Factory {\n  return if (source.uri.startsWith(\"http\")) {\n    DefaultDataSource.Factory(context, buildHttpDataSourceFactory(context, source))\n  } else {\n    DefaultDataSource.Factory(context)\n  }\n}\n\n@OptIn(UnstableApi::class)\nfun buildHttpDataSourceFactory(context: Context, source: HybridVideoPlayerSourceSpec): OkHttpDataSource.Factory {\n  val client = OkHttpClientProvider.getOkHttpClient()\n\n  if (context is ReactContext) {\n    val handler = ForwardingCookieHandler(context)\n    (client.cookieJar as CookieJarContainer).setCookieJar(JavaNetCookieJar(handler))\n  }\n\n  val factory = OkHttpDataSource.Factory(client)\n\n  val headers: Map<String, String>? = source.config.headers\n\n  if (headers != null) {\n    factory.setDefaultRequestProperties(headers)\n  }\n\n  if (headers == null || !headers.containsKey(\"User-Agent\")) {\n    factory.setUserAgent(getUserAgent(context))\n  }\n\n  return factory\n}\n\n@OptIn(UnstableApi::class)\nfun getUserAgent(context: Context): String {\n  return Util.getUserAgent(context, context.packageName)\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/player/MediaItemUtils.kt",
    "content": "package com.twg.video.core.player\n\nimport android.util.Log\nimport android.webkit.MimeTypeMap\nimport androidx.annotation.OptIn\nimport androidx.core.net.toUri\nimport androidx.media3.common.MediaItem\nimport androidx.media3.common.C\nimport androidx.media3.common.MediaMetadata\nimport androidx.media3.common.MimeTypes\nimport androidx.media3.common.util.UnstableApi\nimport com.margelo.nitro.video.BufferConfig\nimport com.margelo.nitro.video.CustomVideoMetadata\nimport com.margelo.nitro.video.HybridVideoPlayerSource\nimport com.margelo.nitro.video.LivePlaybackParams\nimport com.margelo.nitro.video.NativeDrmParams\nimport com.margelo.nitro.video.NativeVideoConfig\nimport com.margelo.nitro.video.SubtitleType\nimport com.twg.video.core.LibraryError\nimport com.twg.video.core.SourceError\nimport com.twg.video.core.extensions.toStringExtension\nimport com.twg.video.core.plugins.PluginsRegistry\n\nprivate const val TAG = \"MediaItemUtils\"\n\n@OptIn(UnstableApi::class)\nfun createMediaItemFromVideoConfig(\n  source: HybridVideoPlayerSource\n): MediaItem {\n  val mediaItemBuilder = MediaItem.Builder()\n\n  mediaItemBuilder.setUri(source.config.uri)\n\n  source.config.drm?.let { drmParams ->\n    val drmManager = source.drmManager ?: throw LibraryError.DRMPluginNotFound\n    val drmConfiguration = drmManager.getDRMConfiguration(drmParams)\n    mediaItemBuilder.setDrmConfiguration(drmConfiguration)\n  }\n\n  source.config.bufferConfig?.livePlayback?.let { livePlaybackParams ->\n    mediaItemBuilder.setLiveConfiguration(getLiveConfiguration(livePlaybackParams))\n  }\n\n  source.config.metadata?.let { metadata ->\n    mediaItemBuilder.setMediaMetadata(getCustomMetadata(metadata))\n  }\n\n  return PluginsRegistry.shared.overrideMediaItemBuilder(\n    source,\n    mediaItemBuilder\n  ).build()\n}\n\nfun getSubtitlesConfiguration(\n  config: NativeVideoConfig,\n): List<MediaItem.SubtitleConfiguration> {\n  val subtitlesConfiguration: MutableList<MediaItem.SubtitleConfiguration> = mutableListOf()\n\n  if (config.externalSubtitles != null) {\n    for (subtitle in config.externalSubtitles) {\n      val ext = if (subtitle.type == SubtitleType.AUTO) {\n        MimeTypeMap.getFileExtensionFromUrl(subtitle.uri)\n      } else {\n        subtitle.type.toStringExtension()\n      }\n\n      val mimeType = when (ext?.lowercase()) {\n        \"srt\" -> MimeTypes.APPLICATION_SUBRIP\n        \"vtt\" -> MimeTypes.TEXT_VTT\n        \"ssa\", \"ass\" -> MimeTypes.TEXT_SSA\n        else -> {\n          Log.e(TAG, \"Unsupported subtitle extension '$ext' for URI: ${subtitle.uri}. Skipping this subtitle.\")\n          continue\n        }\n      }\n\n      try {\n        val subtitleConfig = MediaItem.SubtitleConfiguration.Builder(subtitle.uri.toUri())\n          .setId(\"external-subtitle-${subtitle.uri}\")\n          .setMimeType(mimeType)\n          .setSelectionFlags(C.SELECTION_FLAG_DEFAULT)\n          .setRoleFlags(C.ROLE_FLAG_SUBTITLE)\n          .setLabel(subtitle.label)\n          .build()\n        subtitlesConfiguration.add(subtitleConfig)\n      } catch (e: Exception) {\n        Log.e(TAG, \"Error creating SubtitleConfiguration for URI ${subtitle.uri}: ${e.message}\", e)\n      }\n    }\n  }\n  return subtitlesConfiguration\n}\n\nfun getLiveConfiguration(\n  livePlaybackParams: LivePlaybackParams\n): MediaItem.LiveConfiguration {\n  val liveConfiguration = MediaItem.LiveConfiguration.Builder()\n\n  livePlaybackParams.maxOffsetMs?.let {\n    if (it >= 0) {\n      liveConfiguration.setMaxOffsetMs(it.toLong())\n    }\n  }\n\n  livePlaybackParams.minOffsetMs?.let {\n    if (it >= 0) {\n      liveConfiguration.setMinOffsetMs(it.toLong())\n    }\n  }\n\n  livePlaybackParams.targetOffsetMs?.let {\n    if (it >= 0) {\n      liveConfiguration.setTargetOffsetMs(it.toLong())\n    }\n  }\n\n  livePlaybackParams.maxPlaybackSpeed?.let {\n    if (it >= 0) {\n      liveConfiguration.setMaxPlaybackSpeed(it.toFloat())\n    }\n  }\n\n  livePlaybackParams.minPlaybackSpeed?.let {\n    if (it >= 0) {\n      liveConfiguration.setMinPlaybackSpeed(it.toFloat())\n    }\n  }\n\n  return liveConfiguration.build()\n}\n\nfun getCustomMetadata(metadata: CustomVideoMetadata): MediaMetadata {\n  return MediaMetadata.Builder()\n    .setDisplayTitle(metadata.title)\n    .setTitle(metadata.title)\n    .setSubtitle(metadata.subtitle)\n    .setDescription(metadata.description)\n    .setArtist(metadata.artist)\n    .setArtworkUri(metadata.imageUri?.toUri())\n    .build()\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/player/MediaSourceUtils.kt",
    "content": "package com.twg.video.core.player\n\nimport android.content.Context\nimport android.net.Uri\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.Util\nimport androidx.media3.exoplayer.source.MediaSource\nimport com.margelo.nitro.video.HybridVideoPlayerSourceSpec\nimport androidx.core.net.toUri\nimport androidx.media3.common.C\nimport androidx.media3.common.MediaItem\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.exoplayer.dash.DashMediaSource\nimport androidx.media3.exoplayer.drm.DrmSessionManager\nimport androidx.media3.exoplayer.hls.HlsMediaSource\nimport androidx.media3.exoplayer.source.DefaultMediaSourceFactory\nimport androidx.media3.exoplayer.source.MergingMediaSource\nimport com.margelo.nitro.video.HybridVideoPlayerSource\nimport com.twg.video.core.LibraryError\nimport com.twg.video.core.SourceError\nimport com.twg.video.core.plugins.PluginsRegistry\n\n@OptIn(UnstableApi::class)\n@Throws(SourceError::class)\nfun buildMediaSource(context: Context, source: HybridVideoPlayerSource, mediaItem: MediaItem): MediaSource {\n  val uri = source.uri.toUri()\n\n  // Explanation:\n  // 1. Remove query params from uri to avoid getting false extension\n  // 2. Get extension from uri\n  val type = Util.inferContentType(uri)\n  val dataSourceFactory = PluginsRegistry.shared.overrideMediaDataSourceFactory(\n    source,\n    buildBaseDataSourceFactory(context, source)\n  )\n\n  if (!source.config.externalSubtitles.isNullOrEmpty()) {\n    return buildExternalSubtitlesMediaSource(context, source)\n  }\n\n  val mediaSourceFactory: MediaSource.Factory = when (type) {\n    C.CONTENT_TYPE_DASH -> {\n      DashMediaSource.Factory(dataSourceFactory)\n    }\n    C.CONTENT_TYPE_HLS -> {\n      HlsMediaSource.Factory(dataSourceFactory)\n    }\n    C.CONTENT_TYPE_OTHER -> {\n      DefaultMediaSourceFactory(context)\n        .setDataSourceFactory(dataSourceFactory)\n    }\n    else -> {\n      throw SourceError.UnsupportedContentType(source.uri)\n    }\n  }\n\n  source.config.drm?.let {\n    val drmSessionManager = source.drmSessionManager ?: throw LibraryError.DRMPluginNotFound\n    mediaSourceFactory.setDrmSessionManagerProvider { drmSessionManager }\n  }\n\n  return PluginsRegistry.shared.overrideMediaSourceFactory(\n    source,\n    mediaSourceFactory,\n    dataSourceFactory\n  ).createMediaSource(mediaItem)\n}\n\n@OptIn(UnstableApi::class)\nfun buildExternalSubtitlesMediaSource(context: Context, source: HybridVideoPlayerSource): MediaSource {\n  val dataSourceFactory = PluginsRegistry.shared.overrideMediaDataSourceFactory(\n    source,\n    buildBaseDataSourceFactory(context, source)\n  )\n\n  val mediaItemBuilderWithSubtitles = MediaItem.Builder()\n    .setUri(source.uri.toUri())\n    .setSubtitleConfigurations(getSubtitlesConfiguration(source.config))\n\n  source.config.metadata?.let { metadata ->\n    mediaItemBuilderWithSubtitles.setMediaMetadata(getCustomMetadata(metadata))\n  }\n\n  val mediaItemBuilder = PluginsRegistry.shared.overrideMediaItemBuilder(\n    source,\n    mediaItemBuilderWithSubtitles\n  )\n\n  val mediaSourceFactory = DefaultMediaSourceFactory(context)\n    .setDataSourceFactory(dataSourceFactory)\n\n  if (source.config.drm != null) {\n    if (source.drmManager == null)  {\n      throw LibraryError.DRMPluginNotFound\n    }\n\n    mediaSourceFactory.setDrmSessionManagerProvider {\n      source.drmManager as DrmSessionManager\n    }\n\n    val drmConfiguration = source.drmManager!!.getDRMConfiguration(source.config.drm!!)\n    mediaItemBuilder.setDrmConfiguration(drmConfiguration)\n  }\n\n  return PluginsRegistry.shared.overrideMediaSourceFactory(\n    source,\n    mediaSourceFactory,\n    dataSourceFactory\n  ).createMediaSource(mediaItemBuilder.build())\n}\n\n\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/player/OnAudioFocusChangedListener.kt",
    "content": "package com.twg.video.core.player\n\nimport android.media.AudioManager\nimport com.margelo.nitro.video.HybridVideoPlayerEventEmitter\n\n// TODO: We should make VideoFocusManager that will track focus globally for now lets just do simple listener\nclass OnAudioFocusChangedListener : AudioManager.OnAudioFocusChangeListener {\n  private var eventEmitter: HybridVideoPlayerEventEmitter? = null\n\n  override fun onAudioFocusChange(focusChange: Int) {\n    when (focusChange) {\n      AudioManager.AUDIOFOCUS_GAIN -> eventEmitter?.onAudioFocusChange(true)\n      AudioManager.AUDIOFOCUS_LOSS -> eventEmitter?.onAudioFocusChange(false)\n      AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> eventEmitter?.onAudioFocusChange(false)\n    }\n  }\n\n  fun setEventEmitter(eventEmitter: HybridVideoPlayerEventEmitter) {\n    this.eventEmitter = eventEmitter\n  }\n\n  fun removeEventEmitter() {\n    this.eventEmitter = null\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/plugins/PluginsRegistry.kt",
    "content": "package com.twg.video.core.plugins\n\nimport android.util.Log\nimport androidx.annotation.OptIn\nimport androidx.media3.common.MediaItem\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.datasource.DataSource\nimport androidx.media3.exoplayer.source.MediaSource\nimport com.margelo.nitro.video.HybridVideoPlayer\nimport com.margelo.nitro.video.HybridVideoPlayerSource\nimport com.twg.video.BuildConfig\nimport com.twg.video.core.LibraryError\nimport com.twg.video.core.player.DRMManagerSpec\nimport com.twg.video.view.VideoView\nimport java.lang.ref.WeakReference\n\n// Keep these types for platform compatibility\n// On iOS we cannot just export HybridVideoPlayer so we need to keep this typealias\ntypealias NativeVideoPlayer = HybridVideoPlayer\ntypealias NativeVideoPlayerSource = HybridVideoPlayerSource\n\nclass PluginsRegistry {\n  // Plugin ID -> ReactNativeVideoPluginSpec\n  private val plugins: MutableMap<String, ReactNativeVideoPluginSpec> = mutableMapOf()\n\n  companion object {\n    val shared = PluginsRegistry()\n    private const val TAG = \"ReactNativeVideoPluginsRegistry\"\n  }\n\n  // Public methods\n  fun register(plugin: ReactNativeVideoPluginSpec) {\n    if(hasPlugin(plugin)) {\n      plugins.replace(plugin.id, plugin)\n\n      if (BuildConfig.DEBUG) {\n        Log.d(TAG, \"Replaced plugin ${plugin.name} (ID: ${plugin.id})\")\n      }\n\n      return\n    }\n\n    plugins.put(plugin.id, plugin)\n\n    if (BuildConfig.DEBUG) {\n      Log.d(TAG, \"Registered plugin ${plugin.name} (ID: ${plugin.id})\")\n    }\n  }\n\n  @Suppress(\"unused\")\n  fun unregister(plugin: ReactNativeVideoPluginSpec) {\n    if (!hasPlugin(plugin)) {\n      if (BuildConfig.DEBUG) {\n        Log.d(TAG, \"Tried to unregister plugin ${plugin.name} (ID: ${plugin.id}), but it was not registered\")\n      }\n\n      return\n    }\n\n    plugins.remove(plugin.id)\n\n    if (BuildConfig.DEBUG) {\n      Log.d(TAG, \"Unregistered plugin ${plugin.name} (ID: ${plugin.id})\")\n    }\n  }\n\n  // Notifications\n  @OptIn(UnstableApi::class)\n  internal fun notifyPlayerCreated(player: WeakReference<NativeVideoPlayer>) {\n    plugins.values.forEach { it.onPlayerCreated(player) }\n  }\n\n  @OptIn(UnstableApi::class)\n  internal fun notifyPlayerDestroyed(player: WeakReference<NativeVideoPlayer>) {\n    plugins.values.forEach { it.onPlayerDestroyed(player) }\n  }\n\n  @OptIn(UnstableApi::class)\n  internal fun notifyVideoViewCreated(view: WeakReference<VideoView>) {\n    plugins.values.forEach { it.onVideoViewCreated(view) }\n  }\n\n  @OptIn(UnstableApi::class)\n  internal fun notifyVideoViewDestroyed(view: WeakReference<VideoView>) {\n    plugins.values.forEach { it.onVideoViewDestroyed(view) }\n  }\n\n  // Internal methods\n\n  /**\n   * Maybe override the source with the plugins.\n   * \n   * This method is used to override the source with the plugins.\n   * It is called when a source is created and is used to override the source with the plugins.\n   * \n   * It is not guaranteed that the source will be overridden with the plugins.\n   * If no plugin overrides the source, the original source is returned.\n   *\n   * @param source The source instance.\n   * @return The maybe overridden source instance.\n   */\n  internal fun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource {\n    var overriddenSource = source\n\n    for (plugin in plugins.values) {\n      overriddenSource = plugin.overrideSource(overriddenSource)\n    }\n\n    return overriddenSource\n  }\n\n  /**\n   * Returns the DRM manager instance from the plugins.\n   *\n   * @throws LibraryError.DRMPluginNotFound If no DRM manager is found.\n   * @return Any\n   */\n   internal fun getDRMManager(source: NativeVideoPlayerSource): DRMManagerSpec {\n    for (plugin in plugins.values) {\n      val manager = plugin.getDRMManager(source)\n\n      if (manager != null) return manager\n    }\n\n    throw LibraryError.DRMPluginNotFound\n  }\n\n  /**\n   * Maybe override the media data source factory with the plugins.\n   *\n   * If no plugin overrides the media data source factory, the original factory is returned.\n   *\n   * @param source The source instance.\n   * @param mediaDataSourceFactory The media data source factory instance.\n   * @return The maybe overridden media data source factory instance.\n   */\n  internal fun overrideMediaDataSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaDataSourceFactory: DataSource.Factory\n  ): DataSource.Factory {\n    for (plugin in plugins.values) {\n      val factory = plugin.getMediaDataSourceFactory(source, mediaDataSourceFactory)\n\n      if (factory != null) return factory\n    }\n\n    return mediaDataSourceFactory\n  }\n\n  /**\n   * Maybe override the media source factory with the plugins.\n   *\n   * If no plugin overrides the media source factory, the original factory is returned.\n   *\n   * @param source The source instance.\n   * @param mediaSourceFactory The media source factory instance.\n   * @param mediaDataSourceFactory The media data source factory instance.\n   * @return The maybe overridden media source factory instance.\n   */\n  internal fun overrideMediaSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaSourceFactory: MediaSource.Factory,\n    mediaDataSourceFactory: DataSource.Factory\n  ): MediaSource.Factory {\n    for (plugin in plugins.values) {\n      val factory = plugin.getMediaSourceFactory(source, mediaSourceFactory, mediaDataSourceFactory)\n\n      if (factory != null) return factory\n    }\n\n    return mediaSourceFactory\n  }\n\n  /**\n   * Maybe override the media item builder with the plugins.\n   *\n   * If no plugin overrides the media item builder, the original builder is returned.\n   *\n   * @param source The source instance.\n   * @param mediaItemBuilder The media item builder instance.\n   * @return The maybe overridden media item builder instance.\n   */\n  internal fun overrideMediaItemBuilder(\n    source: NativeVideoPlayerSource,\n    mediaItemBuilder: MediaItem.Builder\n  ): MediaItem.Builder {\n    for (plugin in plugins.values) {\n      val builder = plugin.getMediaItemBuilder(source, mediaItemBuilder)\n\n      if (builder != null) return builder\n    }\n\n    return mediaItemBuilder\n  }\n\n  /**\n   * Maybe disable the cache with the plugins.\n   *\n   * If no plugin disables the cache, the original cache is not disabled.\n   *\n   * @param source The source instance.\n   * @return The maybe disabled cache.\n   */\n  internal fun shouldDisableCache(source: NativeVideoPlayerSource): Boolean {\n    for (plugin in plugins.values) {\n      val shouldDisable = plugin.shouldDisableCache(source)\n\n      if (shouldDisable) return true\n    }\n\n    return false\n  }\n\n  /**\n   * Checks if a plugin is registered.\n   *\n   * @param plugin The plugin instance.\n   * @return True if the plugin is registered, false otherwise.\n   */\n  internal fun hasPlugin(plugin: ReactNativeVideoPluginSpec): Boolean {\n    return plugins.any { it.key == plugin.id }\n  }\n}"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/plugins/ReactNativeVideoPlugin.kt",
    "content": "package com.twg.video.core.plugins\n\nimport androidx.media3.common.MediaItem\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.datasource.DataSource\nimport androidx.media3.exoplayer.source.MediaSource\nimport com.twg.video.core.player.DRMManagerSpec\nimport com.twg.video.view.VideoView\nimport java.lang.ref.WeakReference\n\ninterface ReactNativeVideoPluginSpec {\n  /**\n   * The ID of the plugin.\n   */\n  val id: String\n\n  /**\n   * The name of the plugin.\n   */\n  val name: String\n\n  /**\n   * Called when a player is created.\n   *\n   * @param player The weak reference to the player instance.\n   */\n  @UnstableApi\n  fun onPlayerCreated(player: WeakReference<NativeVideoPlayer>)\n\n  /**\n   * Called when a player is destroyed.\n   *\n   * @param player The weak reference to the player instance.\n   */\n  @UnstableApi\n  fun onPlayerDestroyed(player: WeakReference<NativeVideoPlayer>)\n\n  /**\n   * Called when a video view is created.\n   *\n   * @param view The weak reference to the video view instance.\n   */\n  @UnstableApi\n  fun onVideoViewCreated(view: WeakReference<VideoView>)\n\n  /**\n   * Called when a video view is destroyed.\n   *\n   * @param view The weak reference to the video view instance.\n   */\n  @UnstableApi\n  fun onVideoViewDestroyed(view: WeakReference<VideoView>)\n  \n  /**\n   * Called when a source is being used to create mediaItem or MediaSource.\n   * You can use it to modify the source before it is used.\n   *\n   * @param source The source instance.\n   * @return The overridden source instance.\n   */\n  fun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource\n\n  /**\n   * Called when a DRM manager is requested.\n   *\n   * @return The DRM manager instance.\n   */\n  fun getDRMManager(source: NativeVideoPlayerSource): DRMManagerSpec?\n\n\n  /**\n   * Called when a media data source factory is requested.\n   *\n   * @param source The source instance.\n   * @param mediaDataSourceFactory The media data source factory.\n   * @return The media data source factory. If null is returned, the default factory will be used.\n   */\n  fun getMediaDataSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaDataSourceFactory: DataSource.Factory\n  ): DataSource.Factory?\n\n  /**\n   * Called when a media source factory is requested.\n   *\n   * @param source The source instance.\n   * @param mediaSourceFactory The media source factory.\n   * @param mediaDataSourceFactory The media data source factory.\n   * @return The media source factory. If null is returned, the default factory will be used.\n   */\n  fun getMediaSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaSourceFactory: MediaSource.Factory,\n    mediaDataSourceFactory: DataSource.Factory\n  ): MediaSource.Factory?\n\n  /**\n   * Called when a media item builder is requested.\n   *\n   * @param source The source instance.\n   * @param mediaItemBuilder The media item builder.\n   * @return The media item builder. If null is returned, the default builder will be used.\n   */\n  fun getMediaItemBuilder(\n    source: NativeVideoPlayerSource,\n    mediaItemBuilder: MediaItem.Builder\n  ): MediaItem.Builder?\n\n  /**\n   * Called when a cache should be disabled.\n   *\n   * @param source The source instance.\n   * @return True if cache should be disabled, false otherwise.\n   */\n  fun shouldDisableCache(source: NativeVideoPlayerSource): Boolean\n}\n\n@Suppress(\"Unused\")\n/**\n * A helper base implementation of the ReactNativeVideoPluginSpec interface.\n */\nopen class ReactNativeVideoPlugin(override val name: String) : ReactNativeVideoPluginSpec {\n  override val id = \"RNV_Plugin_${name}\"\n\n  init {\n    // Automatically register the plugin when it is created\n    PluginsRegistry.shared.register(this)\n  }\n\n  @UnstableApi\n  override fun onPlayerCreated(player: WeakReference<NativeVideoPlayer>) { /* NOOP */}\n\n  @UnstableApi\n  override fun onPlayerDestroyed(player: WeakReference<NativeVideoPlayer>) { /* NOOP */}\n\n  @UnstableApi\n  override fun onVideoViewCreated(view: WeakReference<VideoView>) { /* NOOP */}\n\n  @UnstableApi\n  override fun onVideoViewDestroyed(view: WeakReference<VideoView>) { /* NOOP */}\n\n  override fun overrideSource(source: NativeVideoPlayerSource): NativeVideoPlayerSource {\n    return source\n  }\n\n  override fun getDRMManager(source: NativeVideoPlayerSource): DRMManagerSpec? { return null }\n\n  override fun getMediaDataSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaDataSourceFactory: DataSource.Factory\n  ): DataSource.Factory? {\n    return null\n  }\n\n  override fun getMediaSourceFactory(\n    source: NativeVideoPlayerSource,\n    mediaSourceFactory: MediaSource.Factory,\n    mediaDataSourceFactory: DataSource.Factory\n  ): MediaSource.Factory? {\n    return null\n  }\n\n  override fun getMediaItemBuilder(\n    source: NativeVideoPlayerSource,\n    mediaItemBuilder: MediaItem.Builder\n  ): MediaItem.Builder? {\n    return null\n  }\n\n  override fun shouldDisableCache(source: NativeVideoPlayerSource): Boolean {\n    return false\n  }\n}"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/recivers/AudioBecomingNoisyReceiver.kt",
    "content": "package com.twg.video.core.recivers\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.media.AudioManager\nimport androidx.core.content.ContextCompat\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.video.HybridVideoPlayerEventEmitter\nimport com.twg.video.core.LibraryError\n\nclass AudioBecomingNoisyReceiver() : BroadcastReceiver() {\n  private var eventEmitter: HybridVideoPlayerEventEmitter? = null\n\n  override fun onReceive(context: Context?, intent: Intent?) {\n    if (intent?.action == AudioManager.ACTION_AUDIO_BECOMING_NOISY) {\n      eventEmitter?.onAudioBecomingNoisy()\n    }\n  }\n\n  fun setEventEmitter(eventEmitter: HybridVideoPlayerEventEmitter) {\n    val context = NitroModules.applicationContext ?: throw LibraryError.ApplicationContextNotFound\n\n    this.eventEmitter = eventEmitter\n    val intentFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)\n    ContextCompat.registerReceiver(\n      context.applicationContext,\n      this,\n      intentFilter,\n      ContextCompat.RECEIVER_NOT_EXPORTED\n    )\n  }\n\n  fun removeEventEmitter() {\n    this.eventEmitter = null\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/services/playback/CustomMediaNotificationProvider.kt",
    "content": "package com.twg.video.core.services.playback\n\nimport android.content.Context\nimport android.app.PendingIntent\nimport android.content.Intent\nimport android.util.Log\nimport androidx.annotation.OptIn\nimport androidx.media3.common.MediaMetadata\nimport androidx.media3.common.Player\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.session.CommandButton\nimport androidx.media3.session.DefaultMediaNotificationProvider\nimport androidx.media3.session.MediaSession\nimport com.google.common.collect.ImmutableList\nimport androidx.core.os.bundleOf\nimport android.os.Bundle\nimport com.margelo.nitro.NitroModules\nimport com.twg.video.core.LibraryError\n\n@OptIn(UnstableApi::class)\nclass CustomMediaNotificationProvider(context: Context) : DefaultMediaNotificationProvider(context) {\n\n  init {\n    setSmallIcon(androidx.media3.session.R.drawable.media3_notification_small_icon)\n  }\n\n  fun getContext(): Context {\n    return NitroModules.applicationContext ?: run {\n      throw LibraryError.ApplicationContextNotFound\n    }\n  }\n\n  override fun getNotificationContentTitle(metadata: MediaMetadata): CharSequence? {\n    return metadata.title\n      ?: metadata.displayTitle\n      ?: metadata.subtitle\n      ?: metadata.description\n      ?: \"${getAppName()} is playing\"\n  }\n\n  override fun getNotificationContentText(metadata: MediaMetadata): CharSequence? {\n    return metadata.artist\n      ?: metadata.subtitle\n      ?: metadata.description\n  }\n\n  companion object {\n    private const val SEEK_INTERVAL_MS = 10000L\n    private const val TAG = \"CustomMediaNotificationProvider\"\n\n    enum class COMMAND(val stringValue: String) {\n      NONE(\"NONE\"),\n      SEEK_FORWARD(\"COMMAND_SEEK_FORWARD\"),\n      SEEK_BACKWARD(\"COMMAND_SEEK_BACKWARD\"),\n      TOGGLE_PLAY(\"COMMAND_TOGGLE_PLAY\"),\n      PLAY(\"COMMAND_PLAY\"),\n      PAUSE(\"COMMAND_PAUSE\")\n    }\n\n    fun commandFromString(value: String): COMMAND =\n      when (value) {\n        COMMAND.SEEK_FORWARD.stringValue -> COMMAND.SEEK_FORWARD\n        COMMAND.SEEK_BACKWARD.stringValue -> COMMAND.SEEK_BACKWARD\n        COMMAND.TOGGLE_PLAY.stringValue -> COMMAND.TOGGLE_PLAY\n        COMMAND.PLAY.stringValue -> COMMAND.PLAY\n        COMMAND.PAUSE.stringValue -> COMMAND.PAUSE\n        else -> COMMAND.NONE\n      }\n\n    fun handleCommand(command: COMMAND, session: MediaSession) {\n      // TODO: get somehow ControlsConfig here - for now hardcoded 10000ms\n\n      when (command) {\n        COMMAND.SEEK_BACKWARD -> session.player.seekTo(session.player.contentPosition - SEEK_INTERVAL_MS)\n        COMMAND.SEEK_FORWARD -> session.player.seekTo(session.player.contentPosition + SEEK_INTERVAL_MS)\n        COMMAND.TOGGLE_PLAY -> handleCommand(if (session.player.isPlaying) COMMAND.PAUSE else COMMAND.PLAY, session)\n        COMMAND.PLAY -> session.player.play()\n        COMMAND.PAUSE -> session.player.pause()\n        else -> Log.w(TAG, \"Received COMMAND.NONE - was there an error?\")\n      }\n    }\n  }\n\n  private fun getAppName(): String {\n    return try {\n      val context = getContext()\n      val applicationInfo = context.applicationInfo\n      val labelRes = applicationInfo.labelRes\n      if (labelRes != 0) {\n        context.getString(labelRes)\n      } else {\n        applicationInfo.nonLocalizedLabel?.toString() ?: context.packageManager.getApplicationLabel(applicationInfo).toString()\n      }\n    } catch (e: Exception) {\n      return \"Unknown\"\n    }\n  }\n\n  override fun getMediaButtons(\n    session: MediaSession,\n    playerCommands: Player.Commands,\n    mediaButtonPreferences: ImmutableList<CommandButton>,\n    showPauseButton: Boolean\n  ): ImmutableList<CommandButton> {\n    val rewind = CommandButton.Builder()\n      .setDisplayName(\"Rewind\")\n      .setSessionCommand(androidx.media3.session.SessionCommand(\n        COMMAND.SEEK_BACKWARD.stringValue,\n        Bundle.EMPTY\n      ))\n      .setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_back_10)\n      .setExtras(bundleOf(COMMAND_KEY_COMPACT_VIEW_INDEX to 0))\n      .build()\n\n    val toggle = CommandButton.Builder()\n      .setDisplayName(if (showPauseButton) \"Pause\" else \"Play\")\n      .setSessionCommand(androidx.media3.session.SessionCommand(\n        COMMAND.TOGGLE_PLAY.stringValue,\n        Bundle.EMPTY\n      ))\n      .setIconResId(\n        if (showPauseButton) androidx.media3.session.R.drawable.media3_icon_pause\n        else androidx.media3.session.R.drawable.media3_icon_play\n      )\n      .setExtras(bundleOf(COMMAND_KEY_COMPACT_VIEW_INDEX to 1))\n      .build()\n\n    val forward = CommandButton.Builder()\n      .setDisplayName(\"Forward\")\n      .setSessionCommand(androidx.media3.session.SessionCommand(\n        COMMAND.SEEK_FORWARD.stringValue,\n        Bundle.EMPTY\n      ))\n      .setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_forward_10)\n      .setExtras(bundleOf(COMMAND_KEY_COMPACT_VIEW_INDEX to 2))\n      .build()\n\n    return ImmutableList.of(rewind, toggle, forward)\n  }\n\n  override fun addNotificationActions(\n    mediaSession: MediaSession,\n    mediaButtons: ImmutableList<CommandButton>,\n    builder: androidx.core.app.NotificationCompat.Builder,\n    actionFactory: androidx.media3.session.MediaNotification.ActionFactory\n  ): IntArray {\n    // Use default behavior to add actions from our custom buttons and return compact indices\n    val compact = super.addNotificationActions(mediaSession, mediaButtons, builder, actionFactory)\n    return if (compact.isEmpty()) intArrayOf(0, 1, 2) else compact\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackCallback.kt",
    "content": "package com.twg.video.core.services.playback\n\nimport android.os.Bundle\nimport androidx.annotation.OptIn\nimport androidx.media3.common.Player\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.session.CommandButton\nimport androidx.media3.session.MediaSession\nimport androidx.media3.session.SessionCommand\nimport androidx.media3.session.SessionResult\nimport com.google.common.util.concurrent.ListenableFuture\nimport com.google.common.collect.ImmutableList\n\n@OptIn(UnstableApi::class)\nclass VideoPlaybackCallback : MediaSession.Callback {\n  // For Android 13+\n  private fun buildCustomButtons(): ImmutableList<CommandButton> {\n    val rewind = CommandButton.Builder()\n      .setDisplayName(\"Rewind\")\n      .setSessionCommand(\n        SessionCommand(\n          CustomMediaNotificationProvider.Companion.COMMAND.SEEK_BACKWARD.stringValue,\n          Bundle.EMPTY\n        )\n      )\n      .setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_back_10)\n      .build()\n\n    val forward = CommandButton.Builder()\n      .setDisplayName(\"Forward\")\n      .setSessionCommand(\n        SessionCommand(\n          CustomMediaNotificationProvider.Companion.COMMAND.SEEK_FORWARD.stringValue,\n          Bundle.EMPTY\n        )\n      )\n      .setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_forward_10)\n      .build()\n\n    return ImmutableList.of(rewind, forward)\n  }\n\n  override fun onConnect(session: MediaSession, controller: MediaSession.ControllerInfo): MediaSession.ConnectionResult {\n    try {\n      return MediaSession.ConnectionResult.AcceptedResultBuilder(session)\n        .setAvailablePlayerCommands(\n          MediaSession.ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon()\n            .add(Player.COMMAND_SEEK_FORWARD)\n            .add(Player.COMMAND_SEEK_BACK)\n            .build()\n        ).setAvailableSessionCommands(\n          MediaSession.ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()\n            .add(\n              SessionCommand(\n                CustomMediaNotificationProvider.Companion.COMMAND.SEEK_FORWARD.stringValue,\n                Bundle.EMPTY\n              )\n            )\n            .add(\n                SessionCommand(\n                  CustomMediaNotificationProvider.Companion.COMMAND.SEEK_BACKWARD.stringValue,\n                  Bundle.EMPTY\n                )\n            )\n            .add(\n              SessionCommand(\n                CustomMediaNotificationProvider.Companion.COMMAND.TOGGLE_PLAY.stringValue,\n                Bundle.EMPTY\n              )\n            ).build()\n        ).build()\n    } catch (e: Exception) {\n      return MediaSession.ConnectionResult.reject()\n    }\n  }\n\n  override fun onPostConnect(session: MediaSession, controller: MediaSession.ControllerInfo) {\n    session.setCustomLayout(buildCustomButtons())\n    super.onPostConnect(session, controller)\n  }\n\n  override fun onCustomCommand(\n      session: MediaSession,\n      controller: MediaSession.ControllerInfo,\n      customCommand: SessionCommand,\n      args: Bundle\n  ): ListenableFuture<SessionResult> {\n    CustomMediaNotificationProvider.Companion.handleCommand(\n      CustomMediaNotificationProvider.Companion.commandFromString(\n          customCommand.customAction\n        ), session\n      )\n\n    return super.onCustomCommand(session, controller, customCommand, args)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackService.kt",
    "content": "package com.twg.video.core.services.playback\n\nimport android.app.Activity\nimport android.app.PendingIntent\nimport android.content.Intent\nimport android.os.Binder\nimport android.os.IBinder\nimport android.util.Log\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.BitmapLoader\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.session.DefaultMediaNotificationProvider\nimport androidx.media3.session.SimpleBitmapLoader\nimport androidx.media3.session.MediaSession\nimport androidx.media3.session.MediaSessionService\nimport android.app.Notification\nimport android.app.NotificationChannel\nimport android.app.NotificationManager\nimport android.os.Build\nimport androidx.core.app.NotificationCompat\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.video.HybridVideoPlayer\nimport java.util.concurrent.ExecutorService\nimport java.util.concurrent.Executors\n\nclass VideoPlaybackServiceBinder(val service: VideoPlaybackService): Binder()\n\n@OptIn(UnstableApi::class)\nclass VideoPlaybackService : MediaSessionService() {\n  private var mediaSessionsList = mutableMapOf<HybridVideoPlayer, MediaSession>()\n  private var binder = VideoPlaybackServiceBinder(this)\n  private var sourceActivity: Class<Activity>? = null // retained for future deep-links; currently unused\n  private var isForeground = false\n  private var cachedLaunchIntent: Intent? = null\n\n  override fun onCreate() {\n    super.onCreate()\n    setMediaNotificationProvider(CustomMediaNotificationProvider(this))\n  }\n\n  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {\n    // Ensure we call startForeground quickly on newer Android versions to avoid\n    // ForegroundServiceDidNotStartInTimeException when startForegroundService(...) was used.\n    try {\n      if (!isForeground && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n        startForeground(PLACEHOLDER_NOTIFICATION_ID, createPlaceholderNotification())\n        isForeground = true\n      }\n    } catch (_: Exception) {\n      Log.e(TAG, \"Failed to start foreground service!\")\n    }\n\n    return super.onStartCommand(intent, flags, startId)\n  }\n\n  // Player Registry\n  fun registerPlayer(player: HybridVideoPlayer, from: Class<Activity>) {\n    if (mediaSessionsList.containsKey(player)) {\n      return\n    }\n    sourceActivity = from\n\n    val builder = MediaSession.Builder(this, player.player)\n      .setId(\"RNVideoPlaybackService_\" + player.hashCode())\n      .setCallback(VideoPlaybackCallback())\n\n    // Ensure tapping the notification opens the app via sessionActivity\n    try {\n      var launchIntent = cachedLaunchIntent\n      if (launchIntent == null) {\n        launchIntent = packageManager.getLaunchIntentForPackage(packageName)\n        cachedLaunchIntent = launchIntent\n      }\n\n      if (launchIntent != null) {\n        // Clone the intent before modifying it to avoid mutating the cached instance\n        val intentToUse = launchIntent.clone() as Intent\n        intentToUse.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)\n        val contentIntent = PendingIntent.getActivity(\n          this,\n          0,\n          intentToUse,\n          PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE\n        )\n        builder.setSessionActivity(contentIntent)\n      }\n    } catch (_: Exception) {}\n\n\n    val mediaSession = builder.build()\n\n    mediaSessionsList[player] = mediaSession\n    addSession(mediaSession)\n  }\n\n  fun unregisterPlayer(player: HybridVideoPlayer) {\n    val session = mediaSessionsList.remove(player)\n    session?.release()\n    stopIfNoPlayers()\n  }\n\n  fun updatePlayerPreferences(player: HybridVideoPlayer) {\n    val session = mediaSessionsList[player]\n    if (session == null) {\n      // If not registered but now needs it, register\n      if (player.playInBackground || player.showNotificationControls) {\n        val activity = try { NitroModules.applicationContext?.currentActivity } catch (_: Exception) { null }\n        if (activity != null) registerPlayer(player, activity.javaClass)\n      }\n      return\n    }\n\n    // If no longer needs registration, unregister and possibly stop service\n    if (!player.playInBackground && !player.showNotificationControls) {\n      unregisterPlayer(player)\n      stopIfNoPlayers()\n      return\n    }\n  }\n\n  // Callbacks\n\n  override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? = null\n\n  override fun onBind(intent: Intent?): IBinder {\n    super.onBind(intent)\n    return binder\n  }\n\n  override fun onTaskRemoved(rootIntent: Intent?) {\n    stopForegroundSafely()\n    cleanup()\n    stopSelf()\n  }\n\n  override fun onDestroy() {\n    stopForegroundSafely()\n    cleanup()\n    super.onDestroy()\n  }\n\n  private fun stopForegroundSafely() {\n    try {\n      stopForeground(STOP_FOREGROUND_REMOVE)\n    } catch (_: Exception) {\n      Log.e(TAG, \"Failed to stop foreground service!\")\n    }\n  }\n\n  private fun cleanup() {\n    stopForegroundSafely()\n    stopSelf()\n    mediaSessionsList.forEach { (_, session) ->\n      session.release()\n    }\n    mediaSessionsList.clear()\n  }\n\n  // Stop the service if there are no active media sessions (no players need it)\n  fun stopIfNoPlayers() {\n    if (mediaSessionsList.isEmpty()) {\n      // Remove placeholder notification and stop the service when no active players exist\n      try {\n        if (isForeground) {\n          stopForegroundSafely()\n          isForeground = false\n        }\n      } catch (_: Exception) {\n        Log.e(TAG, \"Failed to stop foreground service!\")\n      }\n      cleanup()\n    }\n  }\n\n  companion object {\n    const val TAG = \"VideoPlaybackService\"\n    const val VIDEO_PLAYBACK_SERVICE_INTERFACE = SERVICE_INTERFACE\n    private const val PLACEHOLDER_NOTIFICATION_ID = 1729\n    private const val NOTIFICATION_CHANNEL_ID = \"twg_video_playback\"\n  }\n\n  private fun createPlaceholderNotification(): Notification {\n    val nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n      try {\n        if (nm.getNotificationChannel(NOTIFICATION_CHANNEL_ID) == null) {\n          val channel = NotificationChannel(\n            NOTIFICATION_CHANNEL_ID,\n            \"Media playback\",\n            NotificationManager.IMPORTANCE_LOW\n          )\n          channel.setShowBadge(false)\n          nm.createNotificationChannel(channel)\n        }\n      } catch (_: Exception) {\n        Log.e(TAG, \"Failed to create notification channel!\")\n      }\n    }\n\n    val appName = try {\n      val labelRes = applicationInfo.labelRes\n      if (labelRes != 0) {\n        getString(labelRes)\n      } else {\n        applicationInfo.nonLocalizedLabel?.toString() ?: applicationInfo.loadLabel(packageManager).toString()\n      }\n    } catch (_: Exception) {\n      \"Media Playback\"\n    }\n\n    return NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)\n      .setSmallIcon(android.R.drawable.ic_media_play)\n      .setContentTitle(appName)\n      .setContentText(\"\")\n      .setOngoing(true)\n      .setCategory(Notification.CATEGORY_SERVICE)\n      .build()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/services/playback/VideoPlaybackServiceConnection.kt",
    "content": "package com.twg.video.core.services.playback\n\nimport android.content.ComponentName\nimport android.content.ServiceConnection\nimport android.os.IBinder\nimport android.util.Log\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.UnstableApi\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.video.HybridVideoPlayer\nimport java.lang.ref.WeakReference\n\n@OptIn(UnstableApi::class)\nclass VideoPlaybackServiceConnection (private val player: WeakReference<HybridVideoPlayer>) :\n    ServiceConnection {\n  var serviceBinder: VideoPlaybackServiceBinder? = null\n\n  override fun onServiceConnected(componentName: ComponentName?, binder: IBinder?) {\n    val player = player.get() ?: return\n\n    try {\n      val activity = NitroModules.Companion.applicationContext?.currentActivity ?: run {\n        Log.e(\"VideoPlaybackServiceConnection\", \"Activity is null\")\n        return\n      }\n\n      serviceBinder = binder as? VideoPlaybackServiceBinder\n      // Only register when the player actually needs background service/notification\n      if (player.playInBackground || player.showNotificationControls) {\n        serviceBinder?.service?.registerPlayer(player, activity.javaClass)\n      }\n    } catch (err: Exception) {\n      Log.e(\"VideoPlaybackServiceConnection\", \"Could not bind to playback service\", err)\n    }\n  }\n\n  override fun onServiceDisconnected(componentName: ComponentName?) {\n    player.get()?.let {\n      unregisterPlayer(it)\n    }\n    serviceBinder = null\n  }\n\n  override fun onNullBinding(componentName: ComponentName?) {\n    Log.e(\n      \"VideoPlaybackServiceConnection\",\n      \"Could not bind to playback service - there can be issues with background playback\" +\n        \"and notification controls\"\n    )\n  }\n\n  fun unregisterPlayer(player: HybridVideoPlayer) {\n    try {\n      if (serviceBinder?.service != null) {\n        serviceBinder?.service?.unregisterPlayer(player)\n      }\n    } catch (_: Exception) {}\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/utils/PictureInPictureUtils.kt",
    "content": "package com.twg.video.core.utils\n\nimport android.app.PictureInPictureParams\nimport android.content.pm.PackageManager\nimport android.graphics.Rect\nimport android.os.Build\nimport android.util.Log\nimport android.util.Rational\nimport android.view.View\nimport androidx.annotation.OptIn\nimport androidx.annotation.RequiresApi\nimport androidx.media3.common.util.UnstableApi\nimport com.margelo.nitro.NitroModules\nimport com.twg.video.view.VideoView\n\n@OptIn(UnstableApi::class)\nobject PictureInPictureUtils {\n  private const val TAG = \"PictureInPictureUtils\"\n\n  fun canEnterPictureInPicture(): Boolean {\n    val applicationContent = NitroModules.applicationContext\n    val currentActivity = applicationContent?.currentActivity\n    return currentActivity?.packageManager?.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) == true\n  }\n\n  @RequiresApi(Build.VERSION_CODES.O)\n  fun createPictureInPictureParams(videoView: VideoView): PictureInPictureParams {\n    val builder = PictureInPictureParams.Builder()\n\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && videoView.autoEnterPictureInPicture) {\n      builder.setAutoEnterEnabled(videoView.autoEnterPictureInPicture)\n    }\n\n    return builder\n      .setAspectRatio(calculateAspectRatio(videoView))\n      .setSourceRectHint(calculateSourceRectHint(videoView.playerView))\n      .build()\n  }\n\n  @RequiresApi(Build.VERSION_CODES.O)\n  fun createDisabledPictureInPictureParams(videoView: VideoView): PictureInPictureParams {\n    val defaultParams = PictureInPictureParams.Builder()\n      .setAspectRatio(null) // Clear aspect ratio\n      .setSourceRectHint(null) // Clear source rect hint\n\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {\n      defaultParams.setAutoEnterEnabled(false)\n    }\n\n    return defaultParams.build()\n  }\n\n  fun calculateAspectRatio(videoView: VideoView): Rational {\n    // AspectRatio for PIP must be between 2.39:1 and 1:2.39\n    // see: https://developer.android.com/reference/android/app/PictureInPictureParams.Builder#setAspectRatio(android.util.Rational)\n\n    val maximumAspectRatio = Rational(239, 100)\n    val minimumAspectRatio = Rational(100, 239)\n\n    val player = videoView.hybridPlayer?.player\n    val videoFormat = player?.videoFormat\n    \n    var width: Int\n    var height: Int\n    \n    if (videoFormat != null && videoFormat.width > 0 && videoFormat.height > 0) {\n      width = videoFormat.width\n      height = videoFormat.height\n      \n      val rotationDegrees = videoFormat.rotationDegrees\n      if (rotationDegrees == 90 || rotationDegrees == 270) {\n        val temp = width\n        width = height\n        height = temp\n      }\n      \n      Log.d(TAG, \"Using video format dimensions for PiP: ${width}x${height} (rotation: ${rotationDegrees}°)\")\n    } else {\n      width = videoView.playerView.width\n      height = videoView.playerView.height\n      Log.d(TAG, \"Using view dimensions for PiP: ${width}x${height}\")\n    }\n\n    val currentAspectRatio = Rational(width, height)\n\n    return when {\n      currentAspectRatio > maximumAspectRatio -> maximumAspectRatio\n      currentAspectRatio < minimumAspectRatio -> minimumAspectRatio\n      else -> currentAspectRatio\n    }\n  }\n\n  fun calculateSourceRectHint(view: View): Rect {\n    // Get the visible rectangle of view in screen coordinates\n    val visibleRect = Rect()\n    view.getGlobalVisibleRect(visibleRect)\n\n    // Get the Y position of view on the screen\n    val locationOnScreen = IntArray(2)\n    view.getLocationOnScreen(locationOnScreen)\n    val yOnScreen = locationOnScreen[1]\n\n    // Preserve the original height\n    val height = visibleRect.height()\n\n    // Set the new top and bottom based on the view's screen position\n    visibleRect.top = yOnScreen\n    visibleRect.bottom = yOnScreen + height\n\n    return visibleRect\n  }\n\n  fun safeSetPictureInPictureParams(params: PictureInPictureParams) {\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n      try {\n        val currentActivity = NitroModules.applicationContext?.currentActivity\n        currentActivity?.setPictureInPictureParams(params)\n        Log.d(TAG, \"Successfully set PiP params\")\n      } catch (e: Exception) {\n        Log.w(TAG, \"Failed to set PiP params - PiP may not be enabled in manifest\", e)\n        // Ignore: We cannot check if user has added support for PIP in manifest\n        // so we need to catch error if he did not add it.\n      }\n    }\n  }\n  \n  @RequiresApi(Build.VERSION_CODES.O)\n  fun safeEnterPictureInPictureMode(params: PictureInPictureParams): Boolean {\n    return try {\n      val currentActivity = NitroModules.applicationContext?.currentActivity\n      val result = currentActivity?.enterPictureInPictureMode(params) ?: false\n      Log.d(TAG, \"PiP enter result: $result\")\n      result\n    } catch (e: Exception) {\n      Log.e(TAG, \"Failed to enter PiP mode\", e)\n      false\n    }\n  }\n  \n  fun isCurrentlyInPictureInPictureMode(): Boolean {\n    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n      try {\n        val currentActivity = NitroModules.applicationContext?.currentActivity\n        currentActivity?.isInPictureInPictureMode == true\n      } catch (e: Exception) {\n        Log.w(TAG, \"Failed to check PiP mode status\", e)\n        false\n      }\n    } else {\n      false\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/utils/SmallVideoPlayerOptimizer.kt",
    "content": "package com.twg.video.core.utils\n\nimport android.content.Context\nimport android.util.Log\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ImageButton\nimport androidx.media3.ui.PlayerView\n\nobject SmallVideoPlayerOptimizer {\n\n  fun isSmallVideoPlayer(playerView: PlayerView): Boolean {\n    // Check if the PlayerView dimensions are small enough to warrant optimizations\n    val width = playerView.width\n    val height = playerView.height\n\n    // If view hasn't been measured yet, use layout params or return false\n    if (width <= 0 || height <= 0) {\n      val layoutParams = playerView.layoutParams\n      if (layoutParams != null) {\n        // Convert any specific dimensions to pixels if needed\n        val widthPx = if (layoutParams.width > 0) layoutParams.width else playerView.measuredWidth\n        val heightPx = if (layoutParams.height > 0) layoutParams.height else playerView.measuredHeight\n\n        if (widthPx <= 0 || heightPx <= 0) return false\n\n        return isSmallDimensions(widthPx, heightPx, playerView.context)\n      }\n      return false\n    }\n\n    return isSmallDimensions(width, height, playerView.context)\n  }\n\n  private fun isSmallDimensions(widthPx: Int, heightPx: Int, context: Context): Boolean {\n    val density = context.resources.displayMetrics.density\n    val widthDp = widthPx / density\n    val heightDp = heightPx / density\n\n    // Consider the video player \"small\" if width <= 400dp or height <= 300dp\n    // These thresholds are more appropriate for actual video player sizes\n    return widthDp <= 400 || heightDp <= 300\n  }\n\n  fun applyOptimizations(\n    playerView: PlayerView,\n    context: Context,\n    isFullscreen: Boolean = false\n  ) {\n    playerView.post {\n      try {\n        if (isFullscreen) {\n          // For fullscreen mode, use system defaults - no custom optimizations\n          // Let ExoPlayer use its default controller timeout and styling\n          return@post\n        }\n\n        // Only apply optimizations if the video player itself is small\n        if (!isSmallVideoPlayer(playerView)) {\n          return@post\n        }\n\n        val controllerView = playerView.findViewById<ViewGroup>(androidx.media3.ui.R.id.exo_controller)\n        controllerView?.let { controller ->\n          optimizeControlElementsForSmallPlayer(controller, context)\n        }\n      } catch (e: Exception) {\n        Log.w(\"ReactNativeVideo\", \"Error applying small video player optimizations: ${e.message}\")\n      }\n    }\n  }\n\n  private fun optimizeControlElementsForSmallPlayer(\n    controller: ViewGroup,\n    context: Context\n  ) {\n    val density = context.resources.displayMetrics.density\n    val primaryButtonSize = (48 * density).toInt()\n    val secondaryButtonSize = (44 * density).toInt()\n\n    optimizeButtons(controller, primaryButtonSize, secondaryButtonSize)\n    optimizeProgressBar(controller, context)\n    optimizeTextElements(controller)\n  }\n\n  private fun optimizeButtons(\n    container: ViewGroup,\n    primarySize: Int,\n    secondarySize: Int\n  ) {\n    for (i in 0 until container.childCount) {\n      val child = container.getChildAt(i)\n      when (child) {\n        is ImageButton -> {\n          val buttonSize = when (child.id) {\n            androidx.media3.ui.R.id.exo_play_pause -> primarySize\n            androidx.media3.ui.R.id.exo_fullscreen -> primarySize\n            androidx.media3.ui.R.id.exo_settings -> primarySize\n            androidx.media3.ui.R.id.exo_rew -> secondarySize\n            androidx.media3.ui.R.id.exo_ffwd -> secondarySize\n            androidx.media3.ui.R.id.exo_subtitle -> secondarySize\n            androidx.media3.ui.R.id.exo_prev -> secondarySize\n            androidx.media3.ui.R.id.exo_next -> secondarySize\n            else -> secondarySize\n          }\n\n          val params = child.layoutParams\n          params.width = buttonSize\n          params.height = buttonSize\n          child.layoutParams = params\n\n          // Hide less essential buttons on small video players\n          when (child.id) {\n            androidx.media3.ui.R.id.exo_shuffle,\n            androidx.media3.ui.R.id.exo_repeat_toggle,\n            androidx.media3.ui.R.id.exo_vr -> {\n              child.visibility = View.GONE\n            }\n          }\n        }\n        is ViewGroup -> {\n          optimizeButtons(child, primarySize, secondarySize)\n        }\n      }\n    }\n  }\n\n  private fun optimizeProgressBar(\n    controller: ViewGroup,\n    context: Context\n  ) {\n    val progressContainer = controller.findViewById<View>(androidx.media3.ui.R.id.exo_progress)\n    progressContainer?.let { progress ->\n      val params = progress.layoutParams as? ViewGroup.MarginLayoutParams\n      params?.let {\n        it.height = (4 * context.resources.displayMetrics.density).toInt()\n        progress.layoutParams = it\n      }\n    }\n  }\n\n  private fun optimizeTextElements(\n    controller: ViewGroup\n  ) {\n    val timeContainer = controller.findViewById<ViewGroup>(androidx.media3.ui.R.id.exo_time)\n    timeContainer?.let { time ->\n      val positionView = time.findViewById<View>(androidx.media3.ui.R.id.exo_position)\n      val durationView = time.findViewById<View>(androidx.media3.ui.R.id.exo_duration)\n\n      listOf(positionView, durationView).forEach { textView ->\n        if (textView is android.widget.TextView) {\n          textView.textSize = 12f\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/utils/SourceLoader.kt",
    "content": "package com.twg.video.core.utils\n\nimport com.twg.video.core.SourceError\nimport java.util.concurrent.atomic.AtomicInteger\nimport java.util.concurrent.atomic.AtomicReference\n\nclass SourceLoader {\n  private val operationCounter = AtomicInteger(0)\n  private val currentOperationRef = AtomicReference<OperationHolder<*>?>(null)\n\n  fun <T> load(operation: () -> T): T {\n    cancel()\n\n    val currentOp = operationCounter.incrementAndGet()\n    val holder = OperationHolder<T>(currentOp)\n    currentOperationRef.set(holder)\n\n    return try {\n      val result = operation()\n      if (holder.operationId != operationCounter.get()) {\n        throw SourceError.Cancelled\n      }\n      result\n    } catch (e: SourceError.Cancelled) {\n      throw e\n    } catch (e: Exception) {\n      if (holder.operationId != operationCounter.get()) {\n        throw SourceError.Cancelled\n      }\n      throw e\n    } finally {\n      if (holder.operationId == operationCounter.get()) {\n        currentOperationRef.set(null)\n      }\n    }\n  }\n\n  fun cancel() {\n    val current = currentOperationRef.get()\n    if (current != null) {\n      operationCounter.incrementAndGet()\n      currentOperationRef.set(null)\n    }\n  }\n\n  private class OperationHolder<T>(val operationId: Int)\n}\n\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/utils/TextTrackUtils.kt",
    "content": "package com.twg.video.core.utils\n\nimport androidx.media3.common.C\nimport androidx.media3.common.TrackSelectionOverride\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.exoplayer.ExoPlayer\nimport com.margelo.nitro.video.HybridVideoPlayerSourceSpec\nimport com.margelo.nitro.video.TextTrack\n\n@UnstableApi\nobject TextTrackUtils {\n    fun getAvailableTextTracks(player: ExoPlayer, source: HybridVideoPlayerSourceSpec): Array<TextTrack> {\n        return Threading.runOnMainThreadSync {\n            val tracks = mutableListOf<TextTrack>()\n            val currentTracks = player.currentTracks\n            var globalTrackIndex = 0\n\n            // Get all text tracks from the current player tracks (includes both built-in and external)\n            for (trackGroup in currentTracks.groups) {\n                if (trackGroup.type == C.TRACK_TYPE_TEXT) {\n                    for (trackIndex in 0 until trackGroup.length) {\n                        val format = trackGroup.getTrackFormat(trackIndex)\n                        val trackId = format.id ?: \"text-$globalTrackIndex\"\n                        val label = format.label ?: \"Unknown ${globalTrackIndex + 1}\"\n                        val language = format.language\n                        val isSelected = trackGroup.isTrackSelected(trackIndex)\n\n                        // Determine if this is an external track by checking if it matches external subtitle labels\n                        val isExternal = source.config.externalSubtitles?.any { subtitle ->\n                            label.contains(subtitle.label, ignoreCase = true)\n                        } == true\n\n                        val finalTrackId = if (isExternal) \"external-$globalTrackIndex\" else trackId\n\n                        tracks.add(\n                            TextTrack(\n                                id = finalTrackId,\n                                label = label,\n                                language = language,\n                                selected = isSelected\n                            )\n                        )\n                        \n                        globalTrackIndex++\n                    }\n                }\n            }\n\n            tracks.toTypedArray()\n        }\n    }\n\n    fun selectTextTrack(\n        player: ExoPlayer,\n        textTrack: TextTrack?,\n        source: HybridVideoPlayerSourceSpec,\n        onTrackChange: (TextTrack?) -> Unit,\n    ): Int? {\n        return Threading.runOnMainThreadSync {\n            val trackSelector = player.trackSelectionParameters.buildUpon()\n\n            // If textTrack is null, disable all text tracks\n            if (textTrack == null) {\n                trackSelector.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, true)\n                player.trackSelectionParameters = trackSelector.build()\n                onTrackChange(null)\n                return@runOnMainThreadSync null\n            }\n\n            if (textTrack.id.isEmpty()) {\n                // Disable all text tracks\n                trackSelector.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, true)\n                player.trackSelectionParameters = trackSelector.build()\n                onTrackChange(null)\n                return@runOnMainThreadSync null\n            }\n\n            val currentTracks = player.currentTracks\n            var trackFound = false\n            var selectedExternalTrackIndex: Int? = null\n            var globalTrackIndex = 0\n\n            // Find and select the specific text track\n            for (trackGroup in currentTracks.groups) {\n                if (trackGroup.type == C.TRACK_TYPE_TEXT) {\n                    for (trackIndex in 0 until trackGroup.length) {\n                        val format = trackGroup.getTrackFormat(trackIndex)\n                        val currentTrackId = format.id ?: \"text-$globalTrackIndex\"\n                        val label = format.label ?: \"Unknown ${globalTrackIndex + 1}\"\n\n                        // Check if this matches our target track (either by original ID or by external ID)\n                        val isExternal = source.config.externalSubtitles?.any { subtitle ->\n                            label.contains(subtitle.label, ignoreCase = true)\n                        } == true\n\n                        val finalTrackId =\n                            if (isExternal) \"external-$globalTrackIndex\" else currentTrackId\n\n                        if (finalTrackId == textTrack.id) {\n                            // Enable this specific track\n                            trackSelector.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, false)\n                            trackSelector.setOverrideForType(\n                                TrackSelectionOverride(\n                                    trackGroup.mediaTrackGroup,\n                                    listOf(trackIndex)\n                                )\n                            )\n\n                            // Update selection state\n                            selectedExternalTrackIndex = if (isExternal) {\n                                globalTrackIndex\n                            } else {\n                                null\n                            }\n\n                            onTrackChange(textTrack)\n                            trackFound = true\n                            break\n                        }\n                        \n                        globalTrackIndex++\n                    }\n                    if (trackFound) {\n                        break\n                    }\n                }\n            }\n\n            // Apply the track selection parameters regardless of whether we found a track\n            player.trackSelectionParameters = trackSelector.build()\n            selectedExternalTrackIndex\n        }\n    }\n\n    fun getSelectedTrack(player: ExoPlayer, source: HybridVideoPlayerSourceSpec): TextTrack? {\n        return Threading.runOnMainThreadSync {\n            val currentTracks = player.currentTracks\n            var globalTrackIndex = 0\n\n            // Find the currently selected text track\n            for (trackGroup in currentTracks.groups) {\n                if (trackGroup.type == C.TRACK_TYPE_TEXT && trackGroup.isSelected) {\n                    for (trackIndex in 0 until trackGroup.length) {\n                        if (trackGroup.isTrackSelected(trackIndex)) {\n                            val format = trackGroup.getTrackFormat(trackIndex)\n                            val trackId = format.id ?: \"text-$globalTrackIndex\"\n                            val label = format.label ?: \"Unknown ${globalTrackIndex + 1}\"\n                            val language = format.language\n\n                            // Determine if this is an external track by checking if it matches external subtitle labels\n                            val isExternal = source.config.externalSubtitles?.any { subtitle ->\n                                label.contains(subtitle.label, ignoreCase = true)\n                            } == true\n\n                            val finalTrackId = if (isExternal) \"external-$globalTrackIndex\" else trackId\n\n                            return@runOnMainThreadSync TextTrack(\n                                id = finalTrackId,\n                                label = label,\n                                language = language,\n                                selected = true\n                            )\n                        }\n                        globalTrackIndex++\n                    }\n                } else if (trackGroup.type == C.TRACK_TYPE_TEXT) {\n                    // Still need to increment global index for non-selected text track groups\n                    globalTrackIndex += trackGroup.length\n                }\n            }\n\n            null\n        }\n    }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/utils/Threading.kt",
    "content": "package com.twg.video.core.utils\n\nimport android.os.Handler\nimport android.os.Looper\nimport com.margelo.nitro.NitroModules\nimport com.twg.video.core.LibraryError\nimport java.util.concurrent.Callable\nimport java.util.concurrent.FutureTask\nimport kotlin.reflect.KProperty\n\nobject Threading {\n  @JvmStatic\n  fun runOnMainThread(action: () -> Unit) {\n    // We are already on the main thread, run and return\n    if (Looper.myLooper() == Looper.getMainLooper()) {\n      action()\n      return\n    }\n\n    // If application context is null, throw an error\n    if (NitroModules.applicationContext == null) {\n      throw LibraryError.ApplicationContextNotFound\n    }\n\n    // Post the action to the main thread\n    Handler(NitroModules.applicationContext!!.mainLooper).post {\n      action()\n    }\n  }\n\n  @JvmStatic\n  fun <T> runOnMainThreadSync(action: Callable<T>): T {\n    return if (Looper.myLooper() == Looper.getMainLooper()) {\n      // Already on the main thread, run and return the result\n      action.call()\n    } else {\n      // Post the action to the main thread and wait for the result\n      val futureTask = FutureTask(action)\n      Handler(Looper.getMainLooper()).post(futureTask)\n      futureTask.get()\n    }\n  }\n\n  class MainThreadProperty<Reference, Type>(\n    private val get: Reference.() -> Type,\n    private val set: (Reference.(Type) -> Unit)? = null\n  ) {\n    operator fun getValue(thisRef: Reference, property: KProperty<*>): Type {\n      return runOnMainThreadSync { thisRef.get() }\n    }\n\n    operator fun setValue(thisRef: Reference, property: KProperty<*>, value: Type) {\n      val setter = set ?: throw IllegalStateException(\"Property ${property.name} is read-only\")\n      runOnMainThread { thisRef.setter(value) }\n    }\n  }\n\n  /**\n   * Read-only property that runs on main thread\n   * @param get The getter function that runs synchronously on the main thread.\n   *\n   * @throws [IllegalStateException] if there will be a write operation\n   */\n  fun <Reference, T> Reference.mainThreadProperty(get: Reference.() -> T) = MainThreadProperty(get)\n\n  /**\n   * Read-only property that runs on main thread\n   * @param get The getter function that runs synchronously on the main thread\n   * @param set The setter function that runs asynchronously on the main thread\n   */\n  fun <Reference, T> Reference.mainThreadProperty(\n    get: Reference.() -> T,\n    set: Reference.(T) -> Unit\n  ) = MainThreadProperty(get, set)\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/utils/VideoFileHelper.kt",
    "content": "package com.twg.video.core.utils\n\nimport android.Manifest\nimport android.content.pm.PackageManager\nimport android.net.Uri\nimport android.webkit.URLUtil\nimport com.margelo.nitro.NitroModules\nimport com.twg.video.core.SourceError\nimport java.io.File\nimport java.net.URL\nimport java.net.URLConnection\n\nobject VideoFileHelper {\n  private fun hasReadPermission(): Boolean {\n    return NitroModules.applicationContext?.checkSelfPermission(\n      Manifest.permission.READ_EXTERNAL_STORAGE\n    ) == PackageManager.PERMISSION_GRANTED\n  }\n\n  fun validateReadPermission(uri: String) {\n    if (!hasReadPermission()) throw SourceError.MissingReadFilePermission(uri)\n\n    val file = File(Uri.parse(uri).path ?: throw SourceError.InvalidUri(uri))\n\n    // Check if file exists and is readable\n    if (!file.exists()) throw SourceError.FileDoesNotExist(uri)\n\n    // Check if file is readable\n    if (!file.canRead()) throw SourceError.MissingReadFilePermission(uri)\n  }\n\n  fun getFileSizeFromUri(uri: String): Long {\n    return try {\n      when {\n        URLUtil.isFileUrl(uri) -> {\n          validateReadPermission(uri)\n          val file = File(Uri.parse(uri).path ?: return -1)\n          if (file.exists()) file.length() else -1\n        }\n        URLUtil.isNetworkUrl(uri) -> {\n          val connection: URLConnection = URL(uri).openConnection()\n          connection.connect()\n          connection.contentLength.toLong()\n        }\n        else -> -1\n      }\n    } catch (e: Exception) {\n      -1\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/utils/VideoInformationUtils.kt",
    "content": "package com.twg.video.core.utils\n\nimport android.media.MediaFormat\nimport android.media.MediaMetadataRetriever\nimport android.net.Uri\nimport android.os.Build\nimport android.webkit.URLUtil\nimport com.margelo.nitro.video.VideoInformation\nimport androidx.core.net.toUri\n\nobject VideoInformationUtils {\n  fun fromUri(uri: String, headers: Map<String, String> = emptyMap()): VideoInformation {\n    val retriever = MediaMetadataRetriever()\n\n    when {\n      URLUtil.isFileUrl(uri) -> {\n        retriever.setDataSource(uri.toUri().path)\n      }\n      else -> {\n        retriever.setDataSource(uri, headers)\n      }\n    }\n\n    // Get dimensions\n    val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toDoubleOrNull() ?: Double.NaN\n    val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toDoubleOrNull() ?: Double.NaN\n\n    // Get duration in milliseconds, convert to long\n    val duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLongOrNull() ?: -1L\n\n    // If we have some valid info, but there is no duration it might be live\n    val isLive = !width.isNaN() && !height.isNaN() && duration <= 0\n\n    // Get bitrate\n    val bitrate = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE)?.toDoubleOrNull() ?: Double.NaN\n\n    // Get rotation\n    val rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toIntOrNull() ?: 0\n\n    // Check for HDR by looking at color transfer (API 30+)\n    val isHDR = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n      val colorTransfer = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COLOR_TRANSFER)?.toIntOrNull()\n      colorTransfer == MediaFormat.COLOR_TRANSFER_ST2084 || colorTransfer == MediaFormat.COLOR_TRANSFER_HLG\n    } else {\n      false\n    }\n\n    // Clean up\n    retriever.release()\n\n    // Get file size\n    val fileSize = VideoFileHelper.getFileSizeFromUri(uri)\n\n    val videoInfo = VideoInformation(\n      bitrate = bitrate,\n      width = width,\n      height = height,\n      duration = duration,\n      fileSize = fileSize,\n      isHDR = isHDR,\n      isLive = isLive,\n      orientation = VideoOrientationUtils.fromWHR(width.toInt(), height.toInt(), rotation)\n    )\n\n    return videoInfo\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/core/utils/VideoOrientationUtils.kt",
    "content": "package com.twg.video.core.utils\n\nimport com.margelo.nitro.video.VideoOrientation\n\nobject VideoOrientationUtils {\n  fun fromWHR(width: Int?, height: Int?, rotation: Int?): VideoOrientation {\n    if (width == 0 || height == 0 || height == null || width == null) return VideoOrientation.UNKNOWN\n\n    if (width == height) return VideoOrientation.SQUARE\n\n    // Check if video is portrait or landscape using natural size\n    val isNaturalSizePortrait = height > width\n\n    // If rotation is not available, use natural size to determine orientation\n    if (rotation == null) {\n      return if (isNaturalSizePortrait) VideoOrientation.PORTRAIT else VideoOrientation.LANDSCAPE_RIGHT\n    }\n\n    // Normalize rotation to 0-360 range\n    val normalizedRotation = ((rotation % 360) + 360) % 360\n\n    return when (normalizedRotation) {\n      0 -> if (isNaturalSizePortrait) VideoOrientation.PORTRAIT else VideoOrientation.LANDSCAPE_RIGHT\n      90 -> VideoOrientation.PORTRAIT\n      180 -> if (isNaturalSizePortrait) VideoOrientation.PORTRAIT_UPSIDE_DOWN else VideoOrientation.LANDSCAPE_LEFT\n      270 -> VideoOrientation.PORTRAIT_UPSIDE_DOWN\n      else -> if (isNaturalSizePortrait) VideoOrientation.PORTRAIT else VideoOrientation.LANDSCAPE_RIGHT\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/hybrids/videoplayer/HybridVideoPlayer.kt",
    "content": "package com.margelo.nitro.video\n\nimport android.os.Handler\nimport android.os.Looper\nimport android.util.Log\nimport androidx.media3.common.C\nimport androidx.media3.common.Metadata\nimport androidx.media3.common.PlaybackException\nimport androidx.media3.common.PlaybackParameters\nimport androidx.media3.common.Player\nimport androidx.media3.common.Tracks\nimport androidx.media3.common.text.CueGroup\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.exoplayer.DefaultLoadControl\nimport androidx.media3.exoplayer.DefaultRenderersFactory\nimport androidx.media3.exoplayer.ExoPlayer\nimport androidx.media3.exoplayer.analytics.AnalyticsListener\nimport androidx.media3.exoplayer.upstream.DefaultAllocator\nimport androidx.media3.extractor.metadata.emsg.EventMessage\nimport androidx.media3.extractor.metadata.id3.Id3Frame\nimport androidx.media3.extractor.metadata.id3.TextInformationFrame\nimport androidx.media3.ui.PlayerView\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.core.Promise\nimport com.twg.video.core.LibraryError\nimport com.twg.video.core.PlayerError\nimport com.twg.video.core.VideoManager\nimport com.twg.video.core.extensions.startService\nimport com.twg.video.core.extensions.stopService\nimport com.twg.video.core.player.OnAudioFocusChangedListener\nimport com.twg.video.core.recivers.AudioBecomingNoisyReceiver\nimport com.twg.video.core.services.playback.VideoPlaybackService\nimport com.twg.video.core.services.playback.VideoPlaybackServiceConnection\nimport com.twg.video.core.utils.TextTrackUtils\nimport com.twg.video.core.utils.Threading.mainThreadProperty\nimport com.twg.video.core.utils.Threading.runOnMainThread\nimport com.twg.video.core.utils.Threading.runOnMainThreadSync\nimport com.twg.video.core.utils.VideoOrientationUtils\nimport com.twg.video.view.VideoView\nimport java.lang.ref.WeakReference\nimport kotlin.math.max\n\n@UnstableApi\n@DoNotStrip\nclass HybridVideoPlayer() : HybridVideoPlayerSpec(), AutoCloseable {\n  override lateinit var source: HybridVideoPlayerSourceSpec\n  override var eventEmitter = HybridVideoPlayerEventEmitter()\n    set(value) {\n      if (field != value) {\n        audioFocusChangedListener.setEventEmitter(value)\n        audioBecomingNoisyReceiver.setEventEmitter(value)\n      }\n      field = value\n    }\n\n  private var allocator: DefaultAllocator? = null\n  private var context = NitroModules.applicationContext\n    ?: run {\n    throw LibraryError.ApplicationContextNotFound\n  }\n\n  var player: ExoPlayer = runOnMainThreadSync {\n    // Build Temporary player that will be replaced when source is loaded\n    return@runOnMainThreadSync ExoPlayer.Builder(context).build()\n  }\n\n  var loadedWithSource = false\n  private var currentPlayerView: WeakReference<PlayerView>? = null\n\n  var wasAutoPaused = false\n\n  // Buffer Config\n  private var bufferConfig: BufferConfig? = null\n    get() = source.config.bufferConfig\n\n  // Time updates\n  private val progressHandler = Handler(Looper.getMainLooper())\n  private var progressRunnable: Runnable? = null\n\n  // Listeners\n  private val audioFocusChangedListener = OnAudioFocusChangedListener()\n  private val audioBecomingNoisyReceiver = AudioBecomingNoisyReceiver()\n\n  // Service Connection\n  private val videoPlaybackServiceConnection = VideoPlaybackServiceConnection(WeakReference(this))\n\n  // Text track selection state\n  private var selectedExternalTrackIndex: Int? = null\n\n  private companion object {\n    const val PROGRESS_UPDATE_INTERVAL_MS = 250L\n    private const val TAG = \"HybridVideoPlayer\"\n    private const val DEFAULT_MIN_BUFFER_DURATION_MS = 5000\n    private const val DEFAULT_MAX_BUFFER_DURATION_MS = 10000\n    private const val DEFAULT_BUFFER_FOR_PLAYBACK_DURATION_MS = 1000\n    private const val DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_DURATION_MS = 2000\n    private const val DEFAULT_BACK_BUFFER_DURATION_MS = 0\n  }\n\n  override var status: VideoPlayerStatus = VideoPlayerStatus.IDLE\n    set(value) {\n      if (field != value) {\n        eventEmitter.onStatusChange(value)\n      }\n      field = value\n    }\n\n  override var showNotificationControls: Boolean = false\n    set(value) {\n      val wasRunning = (field || playInBackground)\n      val shouldRun = (value || playInBackground)\n\n      if (shouldRun && !wasRunning) {\n        VideoPlaybackService.startService(context, videoPlaybackServiceConnection)\n      }\n      if (!shouldRun && wasRunning) {\n        VideoPlaybackService.stopService(this, videoPlaybackServiceConnection)\n      }\n\n      field = value\n      // Inform service to refresh notification/session layout\n      try { videoPlaybackServiceConnection.serviceBinder?.service?.updatePlayerPreferences(this) } catch (_: Exception) {}\n    }\n\n  // Player Properties\n  override var currentTime: Double by mainThreadProperty(\n    get = { player.currentPosition.toDouble() / 1000.0 },\n    set = { value -> runOnMainThread { player.seekTo((value * 1000).toLong()) } }\n  )\n\n  // volume defined by user\n  var userVolume: Double = 1.0\n\n  override var volume: Double by mainThreadProperty(\n    get = { player.volume.toDouble() },\n    set = { value ->\n      userVolume = value\n      player.volume = value.toFloat()\n    }\n  )\n\n  override val duration: Double by mainThreadProperty(\n    get = {\n      val duration = player.duration\n      return@mainThreadProperty if (duration == C.TIME_UNSET) Double.NaN else duration.toDouble() / 1000.0\n    }\n  )\n\n  override var loop: Boolean by mainThreadProperty(\n    get = {\n      player.repeatMode == Player.REPEAT_MODE_ONE\n    },\n    set = { value ->\n      player.repeatMode = if (value) Player.REPEAT_MODE_ONE else Player.REPEAT_MODE_OFF\n    }\n  )\n\n  override var muted: Boolean by mainThreadProperty(\n    get = {\n      val playerVolume = player.volume.toDouble()\n      return@mainThreadProperty playerVolume == 0.0\n    },\n    set = { value ->\n      if (value) {\n        userVolume = volume\n        player.volume = 0f\n      } else {\n        player.volume = userVolume.toFloat()\n      }\n      eventEmitter.onVolumeChange(onVolumeChangeData(\n        volume = player.volume.toDouble(),\n        muted = muted\n      ))\n    }\n  )\n\n  override var rate: Double by mainThreadProperty(\n    get = { player.playbackParameters.speed.toDouble() },\n    set = { value ->\n      player.playbackParameters = player.playbackParameters.withSpeed(value.toFloat())\n    }\n  )\n\n  override var mixAudioMode: MixAudioMode = MixAudioMode.AUTO\n    set(value) {\n      VideoManager.audioFocusManager.requestAudioFocusUpdate()\n      field = value\n    }\n\n  // iOS only property\n  override var ignoreSilentSwitchMode: IgnoreSilentSwitchMode = IgnoreSilentSwitchMode.AUTO\n\n  override var playInBackground: Boolean = false\n    set(value) {\n      val shouldRun = (value || showNotificationControls)\n      val wasRunning = (field || showNotificationControls)\n\n      if (shouldRun && !wasRunning) {\n        VideoPlaybackService.startService(context, videoPlaybackServiceConnection)\n      }\n      if (!shouldRun && wasRunning) {\n        VideoPlaybackService.stopService(this, videoPlaybackServiceConnection)\n      }\n      field = value\n      // Update preferences to refresh notifications/registration\n      try { videoPlaybackServiceConnection.serviceBinder?.service?.updatePlayerPreferences(this) } catch (_: Exception) {}\n    }\n\n  override var playWhenInactive: Boolean = false\n\n  override var isPlaying: Boolean by mainThreadProperty(\n    get = { player.isPlaying == true }\n  )\n\n  private fun initializePlayer() {\n    if (NitroModules.applicationContext == null) {\n      throw LibraryError.ApplicationContextNotFound\n    }\n\n    val hybridSource = source as? HybridVideoPlayerSource ?: throw PlayerError.InvalidSource\n\n    // Initialize the allocator\n    allocator = DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE)\n\n    // Create a LoadControl with the allocator\n    val loadControl = DefaultLoadControl.Builder()\n      .setAllocator(allocator!!)\n      .setBufferDurationsMs(\n        bufferConfig?.minBufferMs?.toInt() ?: DEFAULT_MIN_BUFFER_DURATION_MS, // minBufferMs\n        bufferConfig?.maxBufferMs?.toInt() ?: DEFAULT_MAX_BUFFER_DURATION_MS, // maxBufferMs\n        bufferConfig?.bufferForPlaybackMs?.toInt()\n          ?: DEFAULT_BUFFER_FOR_PLAYBACK_DURATION_MS, // bufferForPlaybackMs\n        bufferConfig?.bufferForPlaybackAfterRebufferMs?.toInt()\n          ?: DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_DURATION_MS // bufferForPlaybackAfterRebufferMs\n      )\n      .setBackBuffer(\n        bufferConfig?.backBufferDurationMs?.toInt()\n          ?: DEFAULT_BACK_BUFFER_DURATION_MS, // backBufferDurationMs,\n        false // retainBackBufferFromKeyframe\n      )\n      .build()\n\n    val renderersFactory = DefaultRenderersFactory(context)\n      .forceEnableMediaCodecAsynchronousQueueing()\n      .setEnableDecoderFallback(true)\n\n    // Build the player with the LoadControl\n    player = ExoPlayer.Builder(context)\n      .setLoadControl(loadControl)\n      .setLooper(Looper.getMainLooper())\n      .setRenderersFactory(renderersFactory)\n      .build()\n\n    loadedWithSource = true\n\n    player.addListener(playerListener)\n    player.addAnalyticsListener(analyticsListener)\n    player.setMediaSource(hybridSource.mediaSource)\n\n    // Emit onLoadStart\n    val sourceType = if (hybridSource.uri.startsWith(\"http\")) SourceType.NETWORK else SourceType.LOCAL\n    eventEmitter.onLoadStart(onLoadStartData(sourceType = sourceType, source = hybridSource))\n    status = VideoPlayerStatus.LOADING\n    startProgressUpdates()\n  }\n\n  override fun initialize(): Promise<Unit> {\n    return Promise.async {\n      return@async runOnMainThreadSync {\n        initializePlayer()\n        player.prepare()\n      }\n    }\n  }\n\n  constructor(source: HybridVideoPlayerSource) : this() {\n    this.source = source\n\n    runOnMainThread {\n      if (source.config.initializeOnCreation == true) {\n        initializePlayer()\n        player.prepare()\n      }\n    }\n\n    VideoManager.registerPlayer(this)\n  }\n\n  override fun play() {\n    runOnMainThread {\n      player.play()\n    }\n  }\n\n  override fun pause() {\n    runOnMainThread {\n      player.pause()\n    }\n  }\n\n  override fun seekBy(time: Double) {\n    currentTime = (currentTime + time).coerceIn(0.0, duration)\n  }\n\n  override fun seekTo(time: Double) {\n    currentTime = time.coerceIn(0.0, duration)\n  }\n\n  override fun replaceSourceAsync(source: Variant_NullType_HybridVideoPlayerSourceSpec?): Promise<Unit> {\n    return Promise.async {\n      val source = source?.asSecondOrNull()\n\n      if (source == null) {\n        release()\n        return@async\n      }\n\n      val hybridSource = source as? HybridVideoPlayerSource ?: throw PlayerError.InvalidSource\n\n      val oldSource = this.source as? HybridVideoPlayerSource\n      oldSource?.sourceLoader?.cancel()\n\n      runOnMainThreadSync {\n        // Update source\n        this.source = source\n        player.setMediaSource(hybridSource.mediaSource)\n\n        // Prepare player\n        player.prepare()\n      }\n    }\n  }\n\n  override fun preload(): Promise<Unit> {\n    return Promise.async {\n      runOnMainThreadSync {\n        if (!loadedWithSource) {\n          initializePlayer()\n        }\n\n        if (player.playbackState != Player.STATE_IDLE) {\n          return@runOnMainThreadSync\n        }\n\n        player.prepare()\n      }\n    }\n  }\n\n  override fun release() {\n    if (playInBackground || showNotificationControls) {\n      VideoPlaybackService.stopService(this, videoPlaybackServiceConnection)\n    }\n\n    runOnMainThread {\n      VideoManager.unregisterPlayer(this)\n      stopProgressUpdates()\n      loadedWithSource = false\n\n      eventEmitter.clearAllListeners()\n\n      player.removeListener(playerListener)\n      player.removeAnalyticsListener(analyticsListener)\n      player.release() // Release player\n\n      // Clean Listeners\n      audioFocusChangedListener.removeEventEmitter()\n      audioBecomingNoisyReceiver.removeEventEmitter()\n\n      // Update status\n      status = VideoPlayerStatus.IDLE\n    }\n  }\n\n  fun movePlayerToVideoView(videoView: VideoView) {\n    VideoManager.addViewToPlayer(videoView, this)\n\n    runOnMainThreadSync {\n      PlayerView.switchTargetView(player, currentPlayerView?.get(), videoView.playerView)\n      currentPlayerView = WeakReference(videoView.playerView)\n    }\n  }\n\n  override fun dispose() {\n    release()\n  }\n\n  override fun close() {\n    release()\n  }\n\n  override val memorySize: Long\n    // 1 MiB by default\n    get() = allocator?.totalBytesAllocated?.toLong() ?: (1024L * 1024L)\n\n  private fun startProgressUpdates() {\n    stopProgressUpdates() // Ensure no multiple runnables\n    progressRunnable = object : Runnable {\n      override fun run() {\n        if (player.playbackState != Player.STATE_IDLE && player.playbackState != Player.STATE_ENDED) {\n          val currentTimeSeconds = player.currentPosition / 1000.0\n          val bufferedDurationSeconds = player.bufferedPosition / 1000.0\n          // bufferDuration is the time from current time that is buffered.\n          val playableDurationFromNow = max(0.0, bufferedDurationSeconds - currentTimeSeconds)\n\n          eventEmitter.onProgress(\n            onProgressData(\n              currentTime = currentTimeSeconds,\n              bufferDuration = playableDurationFromNow\n            )\n          )\n          progressHandler.postDelayed(this, PROGRESS_UPDATE_INTERVAL_MS)\n        }\n      }\n    }\n    progressHandler.post(progressRunnable ?: return)\n  }\n\n  private fun stopProgressUpdates() {\n    progressRunnable?.let { progressHandler.removeCallbacks(it) }\n    progressRunnable = null\n  }\n\n  private val analyticsListener = object: AnalyticsListener {\n    override fun onBandwidthEstimate(\n      eventTime: AnalyticsListener.EventTime,\n      totalLoadTimeMs: Int,\n      totalBytesLoaded: Long,\n      bitrateEstimate: Long\n    ) {\n      val videoFormat = player.videoFormat\n      eventEmitter.onBandwidthUpdate(\n        BandwidthData(\n          bitrate = bitrateEstimate.toDouble(),\n          width = if (videoFormat != null) videoFormat.width.toDouble() else null,\n          height = if (videoFormat != null) videoFormat.height.toDouble() else null\n        )\n      )\n    }\n  }\n\n  private val playerListener = object : Player.Listener {\n    override fun onPlaybackStateChanged(playbackState: Int) {\n      val isPlayingUpdate = player.isPlaying\n      val isBufferingUpdate = playbackState == Player.STATE_BUFFERING\n\n      eventEmitter.onPlaybackStateChange(\n        onPlaybackStateChangeData(\n          isPlaying = isPlayingUpdate,\n          isBuffering = isBufferingUpdate\n        )\n      )\n\n      when (playbackState) {\n        Player.STATE_IDLE -> {\n          status = VideoPlayerStatus.IDLE\n          eventEmitter.onBuffer(false)\n        }\n        Player.STATE_BUFFERING -> {\n          status = VideoPlayerStatus.LOADING\n          eventEmitter.onBuffer(true)\n        }\n        Player.STATE_READY -> {\n          status = VideoPlayerStatus.READYTOPLAY\n          eventEmitter.onBuffer(false)\n\n          val generalVideoFormat = player.videoFormat\n          val currentTracks = player.currentTracks\n\n          val selectedVideoTrackGroup = currentTracks.groups.find { group -> group.type == C.TRACK_TYPE_VIDEO && group.isSelected }\n          val selectedVideoTrackFormat = if (selectedVideoTrackGroup != null && selectedVideoTrackGroup.length > 0) {\n            selectedVideoTrackGroup.getTrackFormat(0)\n          } else {\n            null\n          }\n\n          val width = selectedVideoTrackFormat?.width ?: generalVideoFormat?.width ?: 0\n          val height = selectedVideoTrackFormat?.height ?: generalVideoFormat?.height ?: 0\n          val rotationDegrees = selectedVideoTrackFormat?.rotationDegrees ?: generalVideoFormat?.rotationDegrees\n\n          eventEmitter.onLoad(\n            onLoadData(\n              currentTime = player.currentPosition / 1000.0,\n              duration = if (player.duration == C.TIME_UNSET) Double.NaN else player.duration / 1000.0,\n              width = width.toDouble(),\n              height = height.toDouble(),\n              orientation = VideoOrientationUtils.fromWHR(width, height, rotationDegrees)\n            )\n          )\n          // If player becomes ready and is set to play, start progress updates\n          if (player.playWhenReady) {\n            startProgressUpdates()\n          }\n\n          eventEmitter.onReadyToDisplay()\n        }\n        Player.STATE_ENDED -> {\n          status = VideoPlayerStatus.IDLE // Or a specific 'COMPLETED' status if you add one\n          eventEmitter.onEnd()\n          eventEmitter.onBuffer(false)\n          stopProgressUpdates()\n        }\n      }\n    }\n\n    override fun onIsPlayingChanged(isPlaying: Boolean) {\n      super.onIsPlayingChanged(isPlaying)\n      eventEmitter.onPlaybackStateChange(\n        onPlaybackStateChangeData(\n          isPlaying = isPlaying,\n          isBuffering = player.playbackState == Player.STATE_BUFFERING\n        )\n      )\n      if (isPlaying) {\n        VideoManager.setLastPlayedPlayer(this@HybridVideoPlayer)\n        startProgressUpdates()\n      } else {\n        if (player.playbackState == Player.STATE_ENDED || player.playbackState == Player.STATE_IDLE) {\n          stopProgressUpdates()\n        }\n      }\n    }\n\n    override fun onPlayerError(error: PlaybackException) {\n      status = VideoPlayerStatus.ERROR\n      stopProgressUpdates()\n    }\n\n    override fun onPositionDiscontinuity(\n      oldPosition: Player.PositionInfo,\n      newPosition: Player.PositionInfo,\n      reason: Int\n    ) {\n      if (reason == Player.DISCONTINUITY_REASON_SEEK || reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT) {\n        eventEmitter.onSeek(newPosition.positionMs / 1000.0)\n      }\n      // Update progress immediately after a discontinuity if needed by your logic\n       val currentTimeSeconds = newPosition.positionMs / 1000.0\n       val bufferedDurationSeconds = player.bufferedPosition / 1000.0\n       eventEmitter.onProgress(\n         onProgressData(\n           currentTime = currentTimeSeconds,\n           bufferDuration = max(0.0, bufferedDurationSeconds - currentTimeSeconds)\n         )\n       )\n    }\n\n    override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters) {\n      eventEmitter.onPlaybackRateChange(playbackParameters.speed.toDouble())\n    }\n\n    override fun onVolumeChanged(volume: Float) {\n      // We get here device volume changes, and if\n      // player is not muted we will sync it\n      if (!muted) {\n        this@HybridVideoPlayer.volume = volume.toDouble()\n      }\n\n      VideoManager.audioFocusManager.requestAudioFocusUpdate()\n      eventEmitter.onVolumeChange(onVolumeChangeData(\n        volume = volume.toDouble(),\n        muted = muted\n      ))\n    }\n\n    override fun onCues(cueGroup: CueGroup) {\n      val texts = cueGroup.cues.mapNotNull { it.text?.toString() }\n      if (texts.isNotEmpty()) {\n        eventEmitter.onTextTrackDataChanged(texts.toTypedArray())\n      }\n    }\n\n    override fun onMetadata(metadata: Metadata) {\n      val timedMetadataObjects = mutableListOf<TimedMetadataObject>()\n      for (i in 0 until metadata.length()) {\n        val entry = metadata.get(i)\n\n        when (entry) {\n          is Id3Frame -> {\n            var value = \"\"\n\n            if (entry is TextInformationFrame) {\n              value = entry.values.first()\n            }\n\n            timedMetadataObjects.add(TimedMetadataObject(entry.id, value))\n          }\n          is EventMessage ->\n            timedMetadataObjects.add(TimedMetadataObject(entry.schemeIdUri, entry.value))\n          else -> Log.d(TAG, \"Unknown metadata: $entry\")\n        }\n      }\n      if (timedMetadataObjects.isNotEmpty()) {\n        eventEmitter.onTimedMetadata(TimedMetadata(metadata = timedMetadataObjects.toTypedArray()))\n      }\n    }\n\n    override fun onTracksChanged(tracks: Tracks) {\n      super.onTracksChanged(tracks)\n    }\n  }\n\n  // MARK: - Text Track Management\n\n  override fun getAvailableTextTracks(): Array<TextTrack> {\n    return TextTrackUtils.getAvailableTextTracks(player, source)\n  }\n\n  override fun selectTextTrack(textTrack: Variant_NullType_TextTrack?) {\n    selectedExternalTrackIndex = TextTrackUtils.selectTextTrack(\n      player = player,\n      textTrack = textTrack?.asSecondOrNull(),\n      source = source,\n      onTrackChange = { track -> eventEmitter.onTrackChange(track) }\n    )\n  }\n\n  override val selectedTrack: TextTrack?\n    get() = TextTrackUtils.getSelectedTrack(player, source)\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/hybrids/videoplayer/HybridVideoPlayerFactory.kt",
    "content": "package com.margelo.nitro.video\n\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.UnstableApi\nimport com.facebook.proguard.annotations.DoNotStrip\n\n@DoNotStrip\nclass HybridVideoPlayerFactory(): HybridVideoPlayerFactorySpec() {\n  @OptIn(UnstableApi::class)\n  override fun createPlayer(source: HybridVideoPlayerSourceSpec): HybridVideoPlayerSpec {\n    return HybridVideoPlayer(source as HybridVideoPlayerSource)\n  }\n\n  override val memorySize: Long\n    get() = 0\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/hybrids/videoplayereventemitter/HybridVideoPlayerEventEmitter.kt",
    "content": "package com.margelo.nitro.video\n\nimport android.util.Log\nimport com.margelo.nitro.core.NullType\nimport java.util.UUID\n\ndata class ListenerPair(val id: UUID, val eventName: String, val callback: Any)\n\nclass HybridVideoPlayerEventEmitter : HybridVideoPlayerEventEmitterSpec() {\n  private val lock = Any()\n\n  var listeners: MutableList<ListenerPair> = mutableListOf()\n\n  // MARK: - Private helpers\n  private fun <T : Any> addListener(eventName: String, listener: T): ListenerSubscription {\n    val id = UUID.randomUUID()\n    synchronized(lock) {\n      listeners.add(ListenerPair(id, eventName, listener))\n    }\n    return ListenerSubscription {\n      synchronized(lock) {\n        listeners.removeAll { it.id == id }\n      }\n    }\n  }\n\n  private inline fun <reified T> emitEvent(eventName: String, invokeCallback: (T) -> Unit) {\n    val snapshot: List<ListenerPair> = synchronized(lock) {\n      listeners.filter { it.eventName == eventName }.toList()\n    }\n\n    snapshot.forEach { pair ->\n      try {\n        @Suppress(\"UNCHECKED_CAST\")\n        val callback = pair.callback as? T ?: run {\n          Log.d(TAG, \"Invalid callback type for $eventName\")\n          return@forEach\n        }\n        invokeCallback(callback)\n      } catch (t: Throwable) {\n        Log.d(TAG, \"Error calling $eventName listener\", t)\n      }\n    }\n  }\n\n\n  // MARK: - Listener registration methods\n  \n  override fun addOnAudioBecomingNoisyListener(listener: () -> Unit) =\n    addListener(\"onAudioBecomingNoisy\", listener)\n\n  override fun addOnAudioFocusChangeListener(listener: (Boolean) -> Unit) =\n    addListener(\"onAudioFocusChange\", listener)\n\n  override fun addOnBandwidthUpdateListener(listener: (BandwidthData) -> Unit) =\n    addListener(\"onBandwidthUpdate\", listener)\n\n  override fun addOnBufferListener(listener: (Boolean) -> Unit) =\n    addListener(\"onBuffer\", listener)\n\n  override fun addOnControlsVisibleChangeListener(listener: (Boolean) -> Unit) =\n    addListener(\"onControlsVisibleChange\", listener)\n\n  override fun addOnEndListener(listener: () -> Unit) =\n    addListener(\"onEnd\", listener)\n\n  override fun addOnExternalPlaybackChangeListener(listener: (Boolean) -> Unit) =\n    addListener(\"onExternalPlaybackChange\", listener)\n\n  override fun addOnLoadListener(listener: (onLoadData) -> Unit) =\n    addListener(\"onLoad\", listener)\n\n  override fun addOnLoadStartListener(listener: (onLoadStartData) -> Unit) =\n    addListener(\"onLoadStart\", listener)\n\n  override fun addOnPlaybackStateChangeListener(listener: (onPlaybackStateChangeData) -> Unit) =\n    addListener(\"onPlaybackStateChange\", listener)\n\n  override fun addOnPlaybackRateChangeListener(listener: (Double) -> Unit) =\n    addListener(\"onPlaybackRateChange\", listener)\n\n  override fun addOnProgressListener(listener: (onProgressData) -> Unit) =\n    addListener(\"onProgress\", listener)\n\n  override fun addOnReadyToDisplayListener(listener: () -> Unit) =\n    addListener(\"onReadyToDisplay\", listener)\n\n  override fun addOnSeekListener(listener: (Double) -> Unit) =\n    addListener(\"onSeek\", listener)\n\n  override fun addOnStatusChangeListener(listener: (VideoPlayerStatus) -> Unit) =\n    addListener(\"onStatusChange\", listener)\n\n  override fun addOnTimedMetadataListener(listener: (TimedMetadata) -> Unit) =\n    addListener(\"onTimedMetadata\", listener)\n\n  override fun addOnTextTrackDataChangedListener(listener: (Array<String>) -> Unit) =\n    addListener(\"onTextTrackDataChanged\", listener)\n\n  override fun addOnTrackChangeListener(listener: (Variant_NullType_TextTrack?) -> Unit) =\n    addListener(\"onTrackChange\", listener)\n\n  override fun addOnVolumeChangeListener(listener: (onVolumeChangeData) -> Unit) =\n    addListener(\"onVolumeChange\", listener)\n\n  override fun clearAllListeners() {\n    synchronized(lock) {\n      listeners.clear()\n    }\n  }\n\n  // MARK: - Event emission methods\n\n  fun onAudioBecomingNoisy() =\n    emitEvent<() -> Unit>(\"onAudioBecomingNoisy\") { it() }\n\n  fun onAudioFocusChange(hasFocus: Boolean) =\n    emitEvent<(Boolean) -> Unit>(\"onAudioFocusChange\") { it(hasFocus) }\n\n  fun onBandwidthUpdate(data: BandwidthData) =\n    emitEvent<(BandwidthData) -> Unit>(\"onBandwidthUpdate\") { it(data) }\n\n  fun onBuffer(isBuffering: Boolean) =\n    emitEvent<(Boolean) -> Unit>(\"onBuffer\") { it(isBuffering) }\n\n  fun onControlsVisibleChange(isVisible: Boolean) =\n    emitEvent<(Boolean) -> Unit>(\"onControlsVisibleChange\") { it(isVisible) }\n\n  fun onEnd() =\n    emitEvent<() -> Unit>(\"onEnd\") { it() }\n\n  fun onExternalPlaybackChange(isExternalPlayback: Boolean) =\n    emitEvent<(Boolean) -> Unit>(\"onExternalPlaybackChange\") { it(isExternalPlayback) }\n\n  fun onLoad(data: onLoadData) =\n    emitEvent<(onLoadData) -> Unit>(\"onLoad\") { it(data) }\n\n  fun onLoadStart(data: onLoadStartData) =\n    emitEvent<(onLoadStartData) -> Unit>(\"onLoadStart\") { it(data) }\n\n  fun onPlaybackStateChange(data: onPlaybackStateChangeData) =\n    emitEvent<(onPlaybackStateChangeData) -> Unit>(\"onPlaybackStateChange\") { it(data) }\n\n  fun onPlaybackRateChange(rate: Double) =\n    emitEvent<(Double) -> Unit>(\"onPlaybackRateChange\") { it(rate) }\n\n  fun onProgress(data: onProgressData) =\n    emitEvent<(onProgressData) -> Unit>(\"onProgress\") { it(data) }\n\n  fun onReadyToDisplay() =\n    emitEvent<() -> Unit>(\"onReadyToDisplay\") { it() }\n\n  fun onSeek(position: Double) =\n    emitEvent<(Double) -> Unit>(\"onSeek\") { it(position) }\n\n  fun onTimedMetadata(metadata: TimedMetadata) =\n    emitEvent<(TimedMetadata) -> Unit>(\"onTimedMetadata\") { it(metadata) }\n\n  fun onTextTrackDataChanged(tracks: Array<String>) =\n    emitEvent<(Array<String>) -> Unit>(\"onTextTrackDataChanged\") { it(tracks) }\n\n  fun onTrackChange(track: TextTrack?) {\n    val param = if (track == null) {\n      Variant_NullType_TextTrack.create(NullType.NULL)\n    } else {\n      Variant_NullType_TextTrack.create(track)\n    }\n    emitEvent<(Variant_NullType_TextTrack?) -> Unit>(\"onTrackChange\") { it(param) }\n  }\n\n  fun onVolumeChange(data: onVolumeChangeData) =\n    emitEvent<(onVolumeChangeData) -> Unit>(\"onVolumeChange\") { it(data) }\n\n  fun onStatusChange(status: VideoPlayerStatus) =\n    emitEvent<(VideoPlayerStatus) -> Unit>(\"onStatusChange\") { it(status) }\n\n  companion object {\n    const val TAG = \"HybridVideoPlayerEventEmitter\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/hybrids/videoplayersource/HybridVideoPlayerSource.kt",
    "content": "package com.margelo.nitro.video\n\nimport androidx.media3.common.MediaItem\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.exoplayer.drm.DrmSessionManager\nimport androidx.media3.exoplayer.source.MediaSource\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.core.Promise\nimport com.twg.video.core.LibraryError\nimport com.twg.video.core.player.DRMManagerSpec\nimport com.twg.video.core.player.buildMediaSource\nimport com.twg.video.core.player.createMediaItemFromVideoConfig\nimport com.twg.video.core.plugins.PluginsRegistry\nimport com.twg.video.core.utils.SourceLoader\nimport com.twg.video.core.utils.VideoInformationUtils\n\nclass HybridVideoPlayerSource(): HybridVideoPlayerSourceSpec() {\n  override lateinit var uri: String\n  override lateinit var config: NativeVideoConfig\n\n  private lateinit var mediaItem: MediaItem\n  lateinit var mediaSource: MediaSource\n\n  var drmManager: DRMManagerSpec? = null\n\n  @UnstableApi\n  var drmSessionManager: DrmSessionManager? = null\n\n  internal val sourceLoader = SourceLoader()\n\n  constructor(config: NativeVideoConfig) : this() {\n    this.uri = config.uri\n    this.config = config\n\n    val overriddenSource = PluginsRegistry.shared.overrideSource(this)\n\n    config.drm?.let {\n      drmManager = PluginsRegistry.shared.getDRMManager(this)\n      drmSessionManager = drmManager?.buildDrmSessionManager(it)\n    }\n\n    this.mediaItem = createMediaItemFromVideoConfig(\n      overriddenSource\n    )\n\n    NitroModules.applicationContext?.let {\n      this.mediaSource = buildMediaSource(\n        context = it,\n        source = overriddenSource,\n        mediaItem\n      )\n    } ?: run {\n      throw LibraryError.ApplicationContextNotFound\n    }\n  }\n\n  override fun getAssetInformationAsync(): Promise<VideoInformation> {\n    return Promise.async {\n      return@async sourceLoader.load {\n        VideoInformationUtils.fromUri(uri, config.headers ?: emptyMap())\n      }\n    }\n  }\n\n  override val memorySize: Long\n    get() = 0\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/hybrids/videoplayersource/HybridVideoPlayerSourceFactory.kt",
    "content": "package com.margelo.nitro.video\n\nimport android.content.Context\nimport android.net.Uri\nimport androidx.media3.common.MediaItem\nimport androidx.media3.datasource.RawResourceDataSource\nimport com.facebook.react.bridge.ReactApplicationContext\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.NitroModules\n\n@DoNotStrip\nclass HybridVideoPlayerSourceFactory: HybridVideoPlayerSourceFactorySpec() {\n  private val applicationContext: Context\n    get() = NitroModules.applicationContext\n      ?: throw IllegalStateException(\n        \"NitroModules.applicationContext has not been initialized.\"\n      )\n\n  private fun normalizeUri(input: String): String {\n    val parsedUri = Uri.parse(input)\n\n    if (parsedUri.scheme != null) {\n      return parsedUri.toString()\n    }\n\n    val resId = applicationContext.resources\n      .getIdentifier(input, \"raw\", applicationContext.packageName)\n\n    if (resId == 0) {\n      throw IllegalArgumentException(\"The video resource '$input' could not be found in res/raw\")\n    }\n\n    val mediaUri = RawResourceDataSource.buildRawResourceUri(resId)\n\n    return mediaUri.toString()\n  }\n\n  override fun fromUri(uri: String): HybridVideoPlayerSourceSpec {\n    val config = NativeVideoConfig(\n      uri = normalizeUri(uri),\n      externalSubtitles = null,\n      drm = null,\n      headers = null,\n      bufferConfig = null,\n      metadata = null,\n      initializeOnCreation = true\n    )\n\n    return HybridVideoPlayerSource(config)\n  }\n\n  override fun fromVideoConfig(config: NativeVideoConfig): HybridVideoPlayerSourceSpec {\n    return HybridVideoPlayerSource(config)\n  }\n\n  override val memorySize: Long\n    get() = 0\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/hybrids/videoviewviewmanager/HybridVideoViewViewManager.kt",
    "content": "package com.margelo.nitro.video\n\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.UnstableApi\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.twg.video.core.VideoManager\nimport com.twg.video.core.VideoViewError\nimport com.twg.video.core.utils.PictureInPictureUtils\nimport com.twg.video.core.utils.Threading\nimport java.util.UUID\n\ndata class ViewListenerPair(\n  val id: UUID,\n  val eventName: String,\n  val callback: Any\n)\n\n@DoNotStrip\n@OptIn(UnstableApi::class)\nclass HybridVideoViewViewManager(nitroId: Int): HybridVideoViewViewManagerSpec(), VideoViewEventsEmitter {\n  private var videoView =\n    VideoManager.getVideoViewWeakReferenceByNitroId(nitroId) ?: throw VideoViewError.ViewNotFound(nitroId)\n  private val listeners = mutableListOf<ViewListenerPair>()\n\n  init {\n    videoView.get()?.eventsEmitter = this\n  }\n\n  override var player: HybridVideoPlayerSpec?\n    get() {\n      return Threading.runOnMainThreadSync { return@runOnMainThreadSync videoView.get()?.hybridPlayer }\n    }\n    set(value) {\n      Threading.runOnMainThread {\n        videoView.get()?.hybridPlayer = value as? HybridVideoPlayer\n      }\n    }\n\n  override fun canEnterPictureInPicture(): Boolean {\n    return PictureInPictureUtils.canEnterPictureInPicture()\n  }\n\n  override fun enterFullscreen() {\n    videoView.get()?.enterFullscreen()\n  }\n\n  override fun exitFullscreen() {\n    videoView.get()?.exitFullscreen()\n  }\n\n  override fun enterPictureInPicture() {\n    Threading.runOnMainThread {\n      videoView.get()?.enterPictureInPicture()\n    }\n  }\n\n  override fun exitPictureInPicture() {\n    Threading.runOnMainThread {\n      videoView.get()?.exitPictureInPicture()\n    }\n  }\n\n  override var autoEnterPictureInPicture: Boolean\n    get() = videoView.get()?.autoEnterPictureInPicture == true\n    set(value) {\n      Threading.runOnMainThread {\n        videoView.get()?.autoEnterPictureInPicture = value\n      }\n    }\n\n  override var pictureInPicture: Boolean\n    get() = videoView.get()?.pictureInPictureEnabled == true\n    set(value) {\n      videoView.get()?.pictureInPictureEnabled = value\n    }\n\n  override var controls: Boolean\n    get() = videoView.get()?.useController == true\n    set(value) {\n      videoView.get()?.useController = value\n    }\n\n  override var resizeMode: ResizeMode\n    get() = videoView.get()?.resizeMode ?: ResizeMode.NONE\n    set(value) {\n      videoView.get()?.resizeMode = value\n    }\n\n  override var keepScreenAwake: Boolean\n    get() = videoView.get()?.keepScreenAwake == true\n    set(value) {\n      videoView.get()?.keepScreenAwake = value\n    }\n\n  override var surfaceType: SurfaceType\n    get() = videoView.get()?.surfaceType ?: SurfaceType.SURFACE\n    set(value) {\n      videoView.get()?.surfaceType = value\n    }\n\n  // MARK: - Private helpers\n\n  private fun <T> addListener(eventName: String, listener: T): ListenerSubscription {\n    val id = UUID.randomUUID()\n    listeners.add(ViewListenerPair(id, eventName, listener as Any))\n    return ListenerSubscription { listeners.removeAll { it.id == id } }\n  }\n\n  @Suppress(\"UNCHECKED_CAST\")\n  private fun <T> emitEvent(eventName: String, invoke: (T) -> Unit) {\n    listeners.filter { it.eventName == eventName }.forEach { pair ->\n      try {\n        invoke(pair.callback as T)\n      } catch (e: Exception) {\n        println(\"[ReactNativeVideo] Error calling $eventName listener: $e\")\n      }\n    }\n  }\n\n  // MARK: - Listener registration methods\n\n  override fun addOnPictureInPictureChangeListener(listener: (Boolean) -> Unit): ListenerSubscription {\n    return addListener(\"onPictureInPictureChange\", listener)\n  }\n\n  override fun addOnFullscreenChangeListener(listener: (Boolean) -> Unit): ListenerSubscription {\n    return addListener(\"onFullscreenChange\", listener)\n  }\n\n  override fun addWillEnterFullscreenListener(listener: () -> Unit): ListenerSubscription {\n    return addListener(\"willEnterFullscreen\", listener)\n  }\n\n  override fun addWillExitFullscreenListener(listener: () -> Unit): ListenerSubscription {\n    return addListener(\"willExitFullscreen\", listener)\n  }\n\n  override fun addWillEnterPictureInPictureListener(listener: () -> Unit): ListenerSubscription {\n    return addListener(\"willEnterPictureInPicture\", listener)\n  }\n\n  override fun addWillExitPictureInPictureListener(listener: () -> Unit): ListenerSubscription {\n    return addListener(\"willExitPictureInPicture\", listener)\n  }\n\n  override fun clearAllListeners() {\n    listeners.clear()\n  }\n\n  // MARK: - Event emission methods (called by VideoView)\n\n  override fun onPictureInPictureChange(isActive: Boolean) {\n    emitEvent<(Boolean) -> Unit>(\"onPictureInPictureChange\") { it(isActive) }\n  }\n\n  override fun onFullscreenChange(isActive: Boolean) {\n    emitEvent<(Boolean) -> Unit>(\"onFullscreenChange\") { it(isActive) }\n  }\n\n  override fun willEnterFullscreen() {\n    emitEvent<() -> Unit>(\"willEnterFullscreen\") { it() }\n  }\n\n  override fun willExitFullscreen() {\n    emitEvent<() -> Unit>(\"willExitFullscreen\") { it() }\n  }\n\n  override fun willEnterPictureInPicture() {\n    emitEvent<() -> Unit>(\"willEnterPictureInPicture\") { it() }\n  }\n\n  override fun willExitPictureInPicture() {\n    emitEvent<() -> Unit>(\"willExitPictureInPicture\") { it() }\n  }\n\n  override val memorySize: Long\n    get() = 0\n}\n\ninterface VideoViewEventsEmitter {\n  fun onPictureInPictureChange(isActive: Boolean)\n  fun onFullscreenChange(isActive: Boolean)\n  fun willEnterFullscreen()\n  fun willExitFullscreen()\n  fun willEnterPictureInPicture()\n  fun willExitPictureInPicture()\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/hybrids/videoviewviewmanager/HybridVideoViewViewManagerFactory.kt",
    "content": "package com.margelo.nitro.video\n\nimport com.facebook.proguard.annotations.DoNotStrip\n\n@DoNotStrip\nclass HybridVideoViewViewManagerFactory: HybridVideoViewViewManagerFactorySpec() {\n  override fun createViewManager(nitroId: Double): HybridVideoViewViewManagerSpec {\n    return HybridVideoViewViewManager(nitroId.toInt())\n  }\n\n  override val memorySize: Long\n    get() = 0\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/react/VideoPackage.kt",
    "content": "package com.twg.video.react\n\nimport androidx.annotation.OptIn\nimport androidx.media3.common.util.UnstableApi\nimport com.facebook.react.ReactPackage\nimport com.facebook.react.bridge.NativeModule\nimport com.facebook.react.bridge.ReactApplicationContext\nimport com.facebook.react.uimanager.ViewManager\n\nclass VideoPackage : ReactPackage {\n  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {\n    return emptyList()\n  }\n\n  @OptIn(UnstableApi::class)\n  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {\n    return listOf(VideoViewViewManager())\n  }\n\n  companion object {\n    init {\n      System.loadLibrary(\"ReactNativeVideo\")\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/react/VideoViewViewManager.kt",
    "content": "package com.twg.video.react\n\nimport androidx.media3.common.util.UnstableApi\nimport com.facebook.react.bridge.Arguments\nimport com.facebook.react.bridge.WritableMap\nimport com.facebook.react.common.MapBuilder\nimport com.facebook.react.module.annotations.ReactModule\nimport com.facebook.react.uimanager.SimpleViewManager\nimport com.facebook.react.uimanager.ThemedReactContext\nimport com.facebook.react.uimanager.UIManagerHelper\nimport com.facebook.react.uimanager.ViewManagerDelegate\nimport com.facebook.react.uimanager.annotations.ReactProp\nimport com.facebook.react.uimanager.events.Event\nimport com.facebook.react.viewmanagers.RNCVideoViewManagerDelegate\nimport com.facebook.react.viewmanagers.RNCVideoViewManagerInterface\nimport com.twg.video.view.VideoView\n\ninternal class NitroIdChange(\n  surfaceId: Int,\n  viewTag: Int,\n  val nitroId: Int\n) : Event<NitroIdChange>(surfaceId, viewTag) {\n  override fun getEventName() = EVENT_NAME\n\n  override fun getEventData(): WritableMap = Arguments.createMap().apply {\n    putInt(\"nitroId\", nitroId)\n  }\n\n  companion object {\n    const val EVENT_NAME = \"topNitroIdChange\"\n  }\n}\n\n@UnstableApi\n@ReactModule(name = VideoViewViewManager.NAME)\nclass VideoViewViewManager : SimpleViewManager<VideoView>(), RNCVideoViewManagerInterface<VideoView> {\n  private val mDelegate: ViewManagerDelegate<VideoView>\n\n  init {\n    mDelegate = RNCVideoViewManagerDelegate(this)\n  }\n\n  @ReactProp(name = \"nitroId\")\n  override fun setNitroId(view: VideoView, nitroId: Int) {\n    view.nitroId = nitroId\n  }\n\n  public override fun createViewInstance(reactContext: ThemedReactContext): VideoView {\n    return VideoView(reactContext)\n  }\n\n  override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {\n    return MapBuilder.builder<String, Any>()\n      .put(NitroIdChange.EVENT_NAME, MapBuilder.of(\"registrationName\", \"onNitroIdChange\"))\n      .build()\n  }\n\n  override fun getName() = NAME\n\n  override fun getDelegate() = mDelegate\n\n  override fun addEventEmitters(reactContext: ThemedReactContext, view: VideoView) {\n    super.addEventEmitters(reactContext, view)\n\n    val surfaceId = UIManagerHelper.getSurfaceId(reactContext)\n    val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id)\n\n    if (dispatcher != null) {\n      view.onNitroIdChange = {\n        dispatcher.dispatchEvent(NitroIdChange(surfaceId, view.id, view.nitroId))\n      }\n    }\n  }\n\n  companion object {\n    const val NAME = \"RNCVideoView\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/java/com/twg/video/view/VideoView.kt",
    "content": "package com.twg.video.view\n\nimport android.annotation.SuppressLint\nimport android.app.PictureInPictureParams\nimport android.content.Context\nimport android.graphics.Color\nimport android.os.Build\nimport android.util.AttributeSet\nimport android.util.DisplayMetrics\nimport android.util.Log\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.WindowManager\nimport android.widget.FrameLayout\nimport android.widget.ImageButton\nimport androidx.annotation.RequiresApi\nimport androidx.core.view.isVisible\nimport androidx.fragment.app.FragmentActivity\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.ui.PlayerView\nimport com.facebook.react.bridge.ReactApplicationContext\nimport com.margelo.nitro.NitroModules\nimport com.margelo.nitro.video.HybridVideoPlayer\nimport com.margelo.nitro.video.ResizeMode\nimport com.margelo.nitro.video.SurfaceType\nimport com.margelo.nitro.video.VideoViewEventsEmitter\nimport com.twg.video.core.LibraryError\nimport com.twg.video.core.VideoManager\nimport com.twg.video.core.VideoViewError\nimport com.twg.video.core.fragments.FullscreenVideoFragment\nimport com.twg.video.core.fragments.PictureInPictureHelperFragment\nimport com.twg.video.core.utils.PictureInPictureUtils.canEnterPictureInPicture\nimport com.twg.video.core.utils.PictureInPictureUtils.createPictureInPictureParams\nimport com.twg.video.core.utils.PictureInPictureUtils.safeEnterPictureInPictureMode\nimport com.twg.video.core.utils.Threading.runOnMainThread\nimport com.twg.video.core.extensions.toAspectRatioFrameLayout\nimport com.twg.video.core.utils.PictureInPictureUtils\nimport com.twg.video.core.utils.PictureInPictureUtils.createDisabledPictureInPictureParams\nimport com.twg.video.core.utils.SmallVideoPlayerOptimizer\nimport com.twg.video.R.layout.player_view_surface\nimport com.twg.video.R.layout.player_view_texture\n\n@UnstableApi\nclass VideoView @JvmOverloads constructor(\n  context: Context,\n  attrs: AttributeSet? = null,\n  defStyleAttr: Int = 0\n) : FrameLayout(context, attrs, defStyleAttr) {\n  var hybridPlayer: HybridVideoPlayer? = null\n    set(value) {\n      // Clear the SurfaceView when player is about to be set to null\n      if (value == null && field != null) {\n        VideoManager.removeViewFromPlayer(this, field!!)\n      }\n\n      field = value\n\n      field?.movePlayerToVideoView(this)\n    }\n\n  var nitroId: Int = -1\n    set(value) {\n      if (field == -1) {\n        post {\n          onNitroIdChange?.let { it(value) }\n          VideoManager.registerView(this)\n        }\n      }\n\n      VideoManager.updateVideoViewNitroId(oldNitroId = field, newNitroId = value, view = this)\n      field = value\n    }\n\n  var autoEnterPictureInPicture: Boolean = false\n    set(value) {\n      field = value\n\n      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n        PictureInPictureUtils.safeSetPictureInPictureParams(\n          if (value) createPictureInPictureParams(this)\n          else createDisabledPictureInPictureParams(this)\n        )\n      }\n    }\n\n  var useController: Boolean = false\n    set(value) {\n      field = value\n      runOnMainThread {\n        playerView.useController = value\n      }\n    }\n\n  var pictureInPictureEnabled: Boolean = false\n\n  var surfaceType: SurfaceType = SurfaceType.SURFACE\n    set(value) {\n      if (field == value) return\n      field = value\n\n      runOnMainThread {\n        removeView(playerView)\n        playerView.player = null\n        playerView = createPlayerView()\n        playerView.player = hybridPlayer?.player\n        addView(playerView)\n      }\n    }\n\n  var resizeMode: ResizeMode = ResizeMode.NONE\n    set(value) {\n      field = value\n      runOnMainThread {\n        applyResizeMode()\n      }\n    }\n\n  var keepScreenAwake: Boolean\n    get() = playerView.keepScreenOn\n    set(value) {\n      runOnMainThread {\n        playerView.keepScreenOn = value\n      }\n    }\n\n  var eventsEmitter: VideoViewEventsEmitter? = null\n\n  var onNitroIdChange: ((Int?) -> Unit)? = null\n  var playerView = createPlayerView()\n  var isInFullscreen: Boolean = false\n    set(value) {\n      if (value != field) {\n        eventsEmitter?.onFullscreenChange(value)\n      }\n      field = value\n    }\n  var isInPictureInPicture: Boolean = false\n    set(value) {\n      field = value\n      \n      if (value) {\n        playerView.useController = false\n        playerView.controllerAutoShow = false\n        playerView.controllerHideOnTouch = true\n      } else {\n        playerView.useController = useController\n        playerView.controllerAutoShow = true\n        playerView.controllerHideOnTouch = true\n      }\n      \n      eventsEmitter?.onPictureInPictureChange(value)\n    }\n  private var rootContentViews: List<View> = listOf()\n  private var pictureInPictureHelperTag: String? = null\n  private var fullscreenFragmentTag: String? = null\n  private var movedToRootForPiP: Boolean = false\n\n  val applicationContent: ReactApplicationContext\n    get() {\n      return NitroModules.applicationContext ?: throw LibraryError.ApplicationContextNotFound\n    }\n\n  init {\n    addView(playerView)\n    setupFullscreenButton()\n    applyResizeMode()\n  }\n\n  private fun applyResizeMode() {\n    playerView.resizeMode = resizeMode.toAspectRatioFrameLayout()\n  }\n\n  @SuppressLint(\"InflateParams\")\n  private fun createPlayerView(): PlayerView {\n    return when (surfaceType) {\n      SurfaceType.SURFACE -> LayoutInflater.from(context).inflate(player_view_surface, null) as PlayerView\n      SurfaceType.TEXTURE -> LayoutInflater.from(context).inflate(player_view_texture, null) as PlayerView\n    }.apply {\n      layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)\n      setShutterBackgroundColor(Color.TRANSPARENT)\n      setShowSubtitleButton(true)\n      useController = false\n\n      // Apply optimizations based on video player size if needed\n      configureForSmallPlayer()\n    }\n  }\n\n  private val layoutRunnable = Runnable {\n    measure(\n      MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),\n      MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)\n    )\n    layout(left, top, right, bottom)\n\n    // Additional layout fixes for small video players\n    applySmallPlayerLayoutFixes()\n  }\n\n  override fun requestLayout() {\n    super.requestLayout()\n\n    // https://github.com/facebook/react-native/blob/d19afc73f5048f81656d0b4424232ce6d69a6368/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbar.java#L166\n    // This fix issue where exoplayer views where wrong sizes\n    // Without it, controls, PictureInPicture, content fills, etc. don't work\n    post(layoutRunnable)\n  }\n\n  @SuppressLint(\"PrivateResource\")\n  private fun setupFullscreenButton() {\n    playerView.setFullscreenButtonClickListener { _ ->\n      enterFullscreen()\n    }\n\n    playerView.findViewById<ImageButton>(androidx.media3.ui.R.id.exo_fullscreen)\n      ?.setImageResource(androidx.media3.ui.R.drawable.exo_ic_fullscreen_enter)\n  }\n\n  fun enterFullscreen() {\n    if (isInFullscreen) {\n      return\n    }\n\n    val currentActivity = applicationContent.currentActivity\n    if (currentActivity !is FragmentActivity) {\n      Log.e(\"ReactNativeVideo\", \"Current activity is not a FragmentActivity, cannot enter fullscreen\")\n      return\n    }\n\n    try {\n      eventsEmitter?.willEnterFullscreen()\n\n      val fragment = FullscreenVideoFragment(this)\n      fullscreenFragmentTag = fragment.id\n\n      currentActivity.supportFragmentManager.beginTransaction()\n        .add(fragment, fragment.id)\n        .commitAllowingStateLoss()\n\n      isInFullscreen = true\n    } catch (err: Exception) {\n      val debugMessage = \"Failed to start fullscreen fragment for nitroId: $nitroId\"\n      Log.e(\"ReactNativeVideo\", debugMessage, err)\n    }\n  }\n\n  @SuppressLint(\"PrivateResource\")\n  fun exitFullscreen() {\n    if (!isInFullscreen) {\n      return\n    }\n\n    eventsEmitter?.willExitFullscreen()\n\n    val currentActivity = applicationContent.currentActivity\n    fullscreenFragmentTag?.let { tag ->\n      (currentActivity as? FragmentActivity)?.let { activity ->\n        activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment ->\n          // The fragment will handle its own removal in exitFullscreen()\n          if (fragment is FullscreenVideoFragment) {\n            runOnMainThread {\n              fragment.exitFullscreen()\n            }\n          }\n        }\n      }\n      fullscreenFragmentTag = null\n    }\n\n    // Change fullscreen button icon back to enter fullscreen and update callback\n    setupFullscreenButton()\n\n    isInFullscreen = false\n  }\n\n  private fun setupPipHelper() {\n    if (!canEnterPictureInPicture()) {\n      return\n    }\n\n    val currentActivity = applicationContent.currentActivity\n    (currentActivity as? FragmentActivity)?.let {\n      val fragment = PictureInPictureHelperFragment(this)\n      pictureInPictureHelperTag = fragment.id\n      it.supportFragmentManager.beginTransaction()\n        .add(fragment, fragment.id)\n        .commitAllowingStateLoss()\n    }\n  }\n\n  private fun removePipHelper() {\n    val currentActivity = applicationContent.currentActivity\n    pictureInPictureHelperTag?.let { tag ->\n      (currentActivity as? FragmentActivity)?.let { activity ->\n        activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment ->\n          activity.supportFragmentManager.beginTransaction()\n            .remove(fragment)\n            .commitAllowingStateLoss()\n        }\n      }\n      pictureInPictureHelperTag = null\n    }\n  }\n\n  private fun removeFullscreenFragment() {\n    val currentActivity = applicationContent.currentActivity\n    fullscreenFragmentTag?.let { tag ->\n      (currentActivity as? FragmentActivity)?.let { activity ->\n        activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment ->\n          activity.supportFragmentManager.beginTransaction()\n            .remove(fragment)\n            .commitAllowingStateLoss()\n        }\n      }\n      fullscreenFragmentTag = null\n    }\n  }\n\n  fun hideRootContentViews() {\n    // Safety check: Only proceed if this is the designated PiP video\n    if (VideoManager.getCurrentPictureInPictureVideo() != this) {\n      Log.w(\"ReactNativeVideo\", \"hideRootContentViews called on non-PiP video nitroId: $nitroId - ignoring\")\n      return\n    }\n    \n    Log.d(\"ReactNativeVideo\", \"Hiding root content views for PiP video nitroId: $nitroId\")\n    \n    // In PiP mode, disable controls immediately - media session creates its own controls for PiP\n    playerView.useController = false\n    \n    playerView.setBackgroundColor(Color.BLACK)\n    playerView.setShutterBackgroundColor(Color.BLACK)\n\n    val currentActivity = applicationContent.currentActivity ?: return\n    val rootContent = currentActivity.window.decorView.findViewById<ViewGroup>(android.R.id.content)\n    \n    val fullscreenContainer = fullscreenFragmentTag?.let { tag ->\n      (currentActivity as? FragmentActivity)?.supportFragmentManager?.findFragmentByTag(tag)\n        ?.view\n    }\n    \n    rootContentViews = (0 until rootContent.childCount)\n      .map { rootContent.getChildAt(it) }\n      .filter { \n        it.isVisible && \n        it != playerView && \n        it != fullscreenContainer\n      }\n\n    // If we're already in fullscreen, the PlayerView is inside the fullscreen container\n    // and root content is already hidden. Avoid moving the PlayerView again.\n    if (isInFullscreen) {\n      Log.d(\"ReactNativeVideo\", \"PiP entered while in fullscreen - skipping reparent to root for nitroId: $nitroId\")\n      // Still hide the views we captured, but don't move the player view\n      rootContentViews.forEach { view -> view.visibility = GONE }\n      movedToRootForPiP = false\n      return\n    }\n\n    (playerView.parent as? ViewGroup)?.removeView(playerView)\n\n    rootContentViews.forEach { view -> view.visibility = GONE }\n\n    rootContent.addView(\n      playerView,\n      LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)\n    )\n    movedToRootForPiP = true\n    \n    Log.d(\"ReactNativeVideo\", \"Successfully moved player view to root content for PiP nitroId: $nitroId\")\n  }\n\n  fun restoreRootContentViews() {\n    Log.d(\"ReactNativeVideo\", \"Restoring root content views for video nitroId: $nitroId\")\n    \n    // Reset PlayerView settings\n    playerView.useController = useController\n\n    playerView.setBackgroundColor(Color.BLACK)\n    playerView.setShutterBackgroundColor(Color.BLACK)\n\n    if (movedToRootForPiP) {\n      (playerView.parent as? ViewGroup)?.removeView(playerView)\n\n      val currentActivity = applicationContent.currentActivity ?: return\n      val rootContent = currentActivity.window.decorView.findViewById<ViewGroup>(android.R.id.content)\n\n      rootContent.removeView(playerView)\n\n      // Restore root content views\n      rootContentViews.forEach { it.visibility = View.VISIBLE }\n      rootContentViews = listOf()\n      movedToRootForPiP = false\n    } else {\n      // Even if we didn't move the player view to root, we might need to restore hidden views\n      // This can happen when entering PiP from fullscreen - the fullscreen fragment might have\n      // hidden views but we didn't track them in movedToRootForPiP\n      val currentActivity = applicationContent.currentActivity\n      if (currentActivity != null && rootContentViews.isNotEmpty()) {\n        Log.d(\"ReactNativeVideo\", \"Restoring root content views that were hidden (not moved to root) for nitroId: $nitroId\")\n        rootContentViews.forEach { it.visibility = View.VISIBLE }\n        rootContentViews = listOf()\n      }\n    }\n\n    // Add PlayerView back to this VideoView only if not already attached\n    if (playerView.parent != this) {\n      addView(playerView)\n    }\n    \n    Log.d(\"ReactNativeVideo\", \"Successfully restored root content views for video nitroId: $nitroId\")\n  }\n\n  fun enterPictureInPicture() {\n    if (isInPictureInPicture || isInFullscreen || !pictureInPictureEnabled) {\n      return\n    }\n\n    if (!canEnterPictureInPicture()) {\n      throw VideoViewError.PictureInPictureNotSupported\n    }\n\n    // Use centralized PiP manager to handle multiple videos\n    VideoManager.requestPictureInPicture(this)\n  }\n\n  internal fun internalEnterPictureInPicture(): Boolean {\n    if (isInPictureInPicture || isInFullscreen || !pictureInPictureEnabled) {\n      return false\n    }\n\n    if (!canEnterPictureInPicture()) {\n      return false\n    }\n\n    val currentActivity = applicationContent.currentActivity ?: return false\n\n    return try {\n      eventsEmitter?.willEnterPictureInPicture()\n\n      // Disable controls before entering PiP - media session creates its own controls for PiP\n      runOnMainThread {\n        playerView.useController = false\n        playerView.controllerAutoShow = false\n      }\n\n      val success = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n        val params = createPictureInPictureParams(this)\n        safeEnterPictureInPictureMode(params)\n      } else {\n        try {\n          @Suppress(\"Deprecation\")\n          currentActivity.enterPictureInPictureMode()\n          true\n        } catch (e: Exception) {\n          Log.e(\"ReactNativeVideo\", \"Failed to enter PiP mode (legacy)\", e)\n          false\n        }\n      }\n\n      if (success) {\n        Log.d(\"ReactNativeVideo\", \"Successfully requested PiP mode for nitroId: $nitroId\")\n        // Note: isInPictureInPicture will be set to true by the system callback in PictureInPictureHelperFragment\n      } else {\n        Log.w(\"ReactNativeVideo\", \"Failed to enter PiP mode for nitroId: $nitroId\")\n      }\n      \n      success\n    } catch (e: Exception) {\n      Log.e(\"ReactNativeVideo\", \"Exception in internalEnterPictureInPicture for nitroId: $nitroId\", e)\n      false\n    }\n  }\n\n  fun exitPictureInPicture() {\n    if (!isInPictureInPicture) return\n\n    VideoManager.notifyPictureInPictureExited(this)\n\n    eventsEmitter?.willExitPictureInPicture()\n\n    // Restore controls when exiting PiP - they were disabled because media session handles PiP controls\n    playerView.useController = useController\n    playerView.controllerAutoShow = true\n\n    if (movedToRootForPiP) {\n      restoreRootContentViews()\n    } else {\n      Log.d(\"ReactNativeVideo\", \"Exiting PiP while in fullscreen - no reparent needed for nitroId: $nitroId\")\n    }\n\n    isInPictureInPicture = false\n  }\n\n  internal fun forceExitPictureInPicture() {\n    if (!isInPictureInPicture) {\n      Log.d(\"ReactNativeVideo\", \"Force exit PiP skipped for nitroId: $nitroId (not in PiP)\")\n      return\n    }\n\n    Log.d(\"ReactNativeVideo\", \"Force exiting PiP for nitroId: $nitroId\")\n\n    try {\n      val currentActivity = applicationContent.currentActivity\n      if (currentActivity?.isInPictureInPictureMode == true) {\n        Log.d(\"ReactNativeVideo\", \"Activity is in PiP mode, preparing for transition\")\n      }\n      \n      eventsEmitter?.willExitPictureInPicture()\n      \n      // Restore controls when exiting PiP - they were disabled because media session handles PiP controls\n      playerView.useController = useController\n      playerView.controllerAutoShow = true\n      \n      if (movedToRootForPiP) {\n        restoreRootContentViews()\n      } else {\n        Log.d(\"ReactNativeVideo\", \"Force exit PiP while in fullscreen - no reparent needed for nitroId: $nitroId\")\n      }\n      isInPictureInPicture = false\n      \n      VideoManager.notifyPictureInPictureExited(this)\n      \n      Log.d(\"ReactNativeVideo\", \"Successfully force exited PiP for nitroId: $nitroId\")\n      \n    } catch (e: Exception) {\n      Log.e(\"ReactNativeVideo\", \"Failed to force exit PiP mode for nitroId: $nitroId\", e)\n    }\n  }\n\n  // -------- View Lifecycle Methods --------\n  override fun onDetachedFromWindow() {\n    removePipHelper()\n    removeFullscreenFragment()\n    VideoManager.unregisterView(this)\n\n    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n      PictureInPictureUtils.safeSetPictureInPictureParams(\n        createDisabledPictureInPictureParams(this)\n      )\n    }\n\n    super.onDetachedFromWindow()\n  }\n\n  override fun onAttachedToWindow() {\n    hybridPlayer?.movePlayerToVideoView(this)\n    setupPipHelper()\n    super.onAttachedToWindow()\n  }\n\n  private fun PlayerView.configureForSmallPlayer() {\n    SmallVideoPlayerOptimizer.applyOptimizations(this, context, isFullscreen = false)\n\n    // Also apply after any layout changes\n    viewTreeObserver.addOnGlobalLayoutListener {\n      SmallVideoPlayerOptimizer.applyOptimizations(this, context, isFullscreen = false)\n    }\n  }\n\n  private fun applySmallPlayerLayoutFixes() {\n    SmallVideoPlayerOptimizer.applyOptimizations(playerView, context, isFullscreen = false)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/res/layout/player_view_surface.xml",
    "content": "<androidx.media3.ui.PlayerView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/player_view_surface\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:clipChildren=\"false\"\n    android:clipToPadding=\"false\"\n    app:surface_type=\"surface_view\"\n    app:scrubber_enabled_size=\"0dp\"\n    app:scrubber_disabled_size=\"0dp\"\n    app:scrubber_dragged_size=\"0dp\"\n    app:touch_target_height=\"12dp\"\n    app:bar_height=\"5dp\" />\n"
  },
  {
    "path": "packages/react-native-video/android/src/main/res/layout/player_view_texture.xml",
    "content": "<androidx.media3.ui.PlayerView\n    android:id=\"@+id/player_view_texture\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    app:surface_type=\"texture_view\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:clipChildren=\"false\"\n    android:clipToPadding=\"false\"\n    app:scrubber_enabled_size=\"0dp\"\n    app:scrubber_disabled_size=\"0dp\"\n    app:scrubber_dragged_size=\"0dp\"\n    app:touch_target_height=\"12dp\"\n    app:bar_height=\"5dp\"\n    />"
  },
  {
    "path": "packages/react-native-video/android/src/paper/java/com/facebook/react/viewmanagers/RNCVideoViewManagerDelegate.java",
    "content": "/**\n* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).\n*\n* Do not edit this file as changes may cause incorrect behavior and will be lost\n* once the code is regenerated.\n*\n* @generated by codegen project: GeneratePropsJavaDelegate.js\n*/\n\npackage com.facebook.react.viewmanagers;\n\nimport android.view.View;\nimport androidx.annotation.Nullable;\nimport com.facebook.react.uimanager.BaseViewManager;\nimport com.facebook.react.uimanager.BaseViewManagerDelegate;\nimport com.facebook.react.uimanager.LayoutShadowNode;\n\npublic class RNCVideoViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & RNCVideoViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {\n  public RNCVideoViewManagerDelegate(U viewManager) {\n    super(viewManager);\n  }\n  @Override\n  public void setProperty(T view, String propName, @Nullable Object value) {\n    switch (propName) {\n      case \"nitroId\":\n        mViewManager.setNitroId(view, value == null ? 0 : ((Double) value).intValue());\n        break;\n      default:\n        super.setProperty(view, propName, value);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/paper/java/com/facebook/react/viewmanagers/RNCVideoViewManagerInterface.java",
    "content": "/**\n* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).\n*\n* Do not edit this file as changes may cause incorrect behavior and will be lost\n* once the code is regenerated.\n*\n* @generated by codegen project: GeneratePropsJavaInterface.js\n*/\n\npackage com.facebook.react.viewmanagers;\n\nimport android.view.View;\n\npublic interface RNCVideoViewManagerInterface<T extends View> {\n  void setNitroId(T view, int value);\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/stubs/dash/androidx/media3/exoplayer/dash/DashMediaSource.kt",
    "content": "package androidx.media3.exoplayer.dash;\n\nimport androidx.media3.common.MediaItem;\nimport androidx.media3.common.util.UnstableApi;\nimport androidx.media3.datasource.DataSource;\nimport androidx.media3.exoplayer.drm.DrmSessionManagerProvider;\nimport androidx.media3.exoplayer.source.MediaSource;\nimport androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;\n\nclass DashMediaSource {\n\n  @UnstableApi\n  class Factory(\n    factory: DataSource.Factory,\n  ) : MediaSource.Factory {\n    // NOOP\n\n    override fun setDrmSessionManagerProvider(drmSessionManagerProvider: DrmSessionManagerProvider): MediaSource.Factory {\n      throw UnsupportedOperationException(\"STUB\")\n    }\n\n    override fun setLoadErrorHandlingPolicy(loadErrorHandlingPolicy: LoadErrorHandlingPolicy): MediaSource.Factory {\n      throw UnsupportedOperationException(\"STUB\")\n    }\n\n    override fun getSupportedTypes(): IntArray {\n      return intArrayOf()\n    }\n\n    override fun createMediaSource(mediaItem: MediaItem): MediaSource {\n      throw UnsupportedOperationException(\"STUB\")\n    }\n  }\n}\n\n"
  },
  {
    "path": "packages/react-native-video/android/src/stubs/dash/androidx/media3/exoplayer/dash/DashUtil.kt",
    "content": "package androidx.media3.exoplayer.dash\n\nimport android.net.Uri\nimport androidx.media3.datasource.DataSource\nimport androidx.media3.exoplayer.dash.manifest.DashManifest\n\nobject DashUtil {\n    fun loadManifest(ds: DataSource?, uri: Uri?): DashManifest? {\n        return null\n    }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/AdaptationSet.kt",
    "content": "package androidx.media3.exoplayer.dash.manifest\n\nimport androidx.collection.CircularArray\n\nclass AdaptationSet {\n    var type: Int = 0\n    var representations: CircularArray<Representation?>? =\n        null\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/DashManifest.kt",
    "content": "package androidx.media3.exoplayer.dash.manifest\n\nclass DashManifest {\n    val periodCount: Int\n        get() = 0\n\n    fun getPeriod(index: Int): Period? {\n        return null\n    }\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/Period.kt",
    "content": "package androidx.media3.exoplayer.dash.manifest\n\nimport androidx.collection.CircularArray\n\nclass Period {\n    var adaptationSets: CircularArray<AdaptationSet?>? = null\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/stubs/dash/androidx/media3/exoplayer/dash/manifest/Representation.kt",
    "content": "package androidx.media3.exoplayer.dash.manifest\n\nimport androidx.media3.common.Format\n\nclass Representation {\n    var format: Format? = null\n    var presentationTimeOffsetUs: Long = 0\n}\n"
  },
  {
    "path": "packages/react-native-video/android/src/stubs/hls/androidx/media3/exoplayer/hls/HlsMediaSource.kt",
    "content": "package androidx.media3.exoplayer.hls\n\nimport androidx.media3.common.MediaItem\nimport androidx.media3.common.util.UnstableApi\nimport androidx.media3.datasource.DataSource\nimport androidx.media3.exoplayer.drm.DrmSessionManagerProvider\nimport androidx.media3.exoplayer.source.MediaSource\nimport androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy\n\nclass HlsMediaSource {\n    @UnstableApi\n    class Factory(private val mediaDataSourceFactory: DataSource.Factory) : MediaSource.Factory {\n        override fun setDrmSessionManagerProvider(drmSessionManagerProvider: DrmSessionManagerProvider): MediaSource.Factory {\n            throw UnsupportedOperationException(\"Not implemented\")\n        }\n\n        override fun setLoadErrorHandlingPolicy(loadErrorHandlingPolicy: LoadErrorHandlingPolicy): MediaSource.Factory {\n            throw UnsupportedOperationException(\"Not implemented\")\n        }\n\n        override fun getSupportedTypes(): IntArray {\n            return intArrayOf()\n        }\n\n        override fun createMediaSource(mediaItem: MediaItem): MediaSource {\n            throw UnsupportedOperationException(\"Not implemented\")\n        }\n\n        fun setAllowChunklessPreparation(allowChunklessPreparation: Boolean): Factory {\n            return this\n        }\n    }\n}\n"
  },
  {
    "path": "packages/react-native-video/app.plugin.js",
    "content": "module.exports = require('./lib/commonjs/expo-plugins/withReactNativeVideo');\n"
  },
  {
    "path": "packages/react-native-video/babel.config.js",
    "content": "module.exports = {\n  presets: [\n    ['module:react-native-builder-bob/babel-preset', { modules: 'commonjs' }],\n  ],\n};\n"
  },
  {
    "path": "packages/react-native-video/ios/Video-Bridging-Header.h",
    "content": "#import <React/RCTViewManager.h>\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVAsset+estimatedMemoryUsage.swift",
    "content": "//\n//  AVAsset+estimatedMemoryUsage.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 23/01/2025.\n//\n\nimport AVFoundation\nimport Foundation\n\nextension AVAsset {\n  var estimatedMemoryUsage: Int {\n    if let urlAsset = self as? AVURLAsset, urlAsset.url.isFileURL {\n      let resourceValues = try? urlAsset.url.resourceValues(forKeys: [.fileSizeKey])\n      if let fileSize = resourceValues?.fileSize, fileSize > 0 {\n        return fileSize\n      }\n    }\n\n    var estimatedSize = 0\n\n    let videoTracks = tracks(withMediaType: .video)\n    let audioTracks = tracks(withMediaType: .audio)\n\n    for track in videoTracks {\n      let size = track.naturalSize\n      let pixelCount = size.width * size.height\n      let duration = CMTimeGetSeconds(track.timeRange.duration)\n\n      if duration > 0 && !duration.isNaN && !duration.isInfinite {\n        let bitrate = track.estimatedDataRate > 0 ? track.estimatedDataRate : 2_000_000\n        estimatedSize += Int((bitrate * Float(duration)) / 8)\n      } else {\n        estimatedSize += Int(pixelCount * 4)\n      }\n    }\n\n    for track in audioTracks {\n      let duration = CMTimeGetSeconds(track.timeRange.duration)\n      let bitrate = track.estimatedDataRate > 0 ? track.estimatedDataRate : 128_000\n\n      if duration > 0 && !duration.isNaN && !duration.isInfinite {\n        estimatedSize += Int((bitrate * Float(duration)) / 8)\n      } else {\n        estimatedSize += 1_000_000\n      }\n    }\n\n    return estimatedSize > 0 ? estimatedSize : 0\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVAssetTrack+orientation.swift",
    "content": "//\n//  AVAssetTrack+orientation.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 23/01/2025.\n//\n\nimport AVFoundation\n\nextension AVAssetTrack {\n  var orientation: VideoOrientation {\n    let transform = preferredTransform\n    let size = naturalSize.applying(transform)\n    \n    // Check if video is square\n    if size.width == size.height {\n      return .square\n    }\n    \n    // Check if video is portrait or landscape\n    let isNaturalSizePortrait = size.width < size.height\n    \n    // Calculate video rotation\n    let angle = atan2(Double(transform.b), Double(transform.a))\n    let degrees = angle * 180 / .pi\n    let rotation = degrees < 0 ? degrees + 360 : degrees\n    \n    switch rotation {\n    case 0:\n      return isNaturalSizePortrait ? .portrait : .landscapeRight\n    case 90, -270:\n      return .portrait\n    case 180, -180:\n      return isNaturalSizePortrait ? .portraitUpsideDown : .landscapeLeft\n    case 270, -90:\n      return .portraitUpsideDown\n    default:\n      return isNaturalSizePortrait ? .portrait : .landscape\n    }\n  }\n}"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVMetadataItem+make.swift",
    "content": "//\n//  AVMetadataItem+make.swift\n//  ReactNativeVideo\n//\n//  Created by Kamil Moskała on 06/02/2026.\n//\n\nimport AVFoundation\n\nextension AVMetadataItem {\n  static func make(identifier: AVMetadataIdentifier, value: NSObjectProtocol & NSCopying) -> AVMutableMetadataItem {\n    let item = AVMutableMetadataItem()\n    item.identifier = identifier\n    item.value = value\n    item.extendedLanguageTag = \"und\"\n    return item\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVPlayerItem+externalSubtitles.swift",
    "content": "//\n//  AVPlayerItem+externalSubtitles.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 08/05/2025.\n//\n\nimport AVFoundation\nimport Foundation\n\nextension AVPlayerItem {\n  static func withExternalSubtitles(for asset: AVURLAsset, config: NativeVideoConfig) async throws\n    -> AVPlayerItem\n  {\n    if config.externalSubtitles?.isEmpty != false {\n      return AVPlayerItem(asset: asset)\n    }\n      \n    let supportedExternalSubtitles = config.externalSubtitles?.filter { subtitle in\n      ExternalSubtitlesUtils.isSubtitleTypeSupported(subtitle: subtitle)\n    }\n\n    if supportedExternalSubtitles?.isEmpty == true {\n      return AVPlayerItem(asset: asset)\n    }\n      \n    if asset.url.pathExtension == \"m3u8\" {\n        return try await ExternalSubtitlesUtils.modifyStreamManifestWithExternalSubtitles(\n          for: asset, config: config)\n    }\n\n    return try await ExternalSubtitlesUtils.createCompositionWithExternalSubtitles(\n      for: asset, config: config)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVPlayerItem+getBufferedDurration.swift",
    "content": "//\n//  AVPlayerItem+getBufferedPosition.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 06/05/2025.\n//\n\nimport Foundation\nimport AVFoundation\n\nextension AVPlayerItem {\n  \n  // Duration that can be played using only the buffer (seconds)\n  func getbufferDuration() -> Double {\n    var effectiveTimeRange: CMTimeRange?\n    \n    for value in loadedTimeRanges {\n      let timeRange: CMTimeRange = value.timeRangeValue\n      if CMTimeRangeContainsTime(timeRange, time: currentTime()) {\n        effectiveTimeRange = timeRange\n        break\n      }\n    }\n    \n    if let effectiveTimeRange {\n      let playableDuration: Float64 = CMTimeGetSeconds(CMTimeRangeGetEnd(effectiveTimeRange))\n      if playableDuration > 0 {\n        return playableDuration\n      }\n    }\n    \n    return 0\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVPlayerItem+setBufferConfig.swift",
    "content": "//\n//  AVPlayerItem+setBufferConfig.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 13/09/2025.\n//\n\nimport Foundation\nimport AVFoundation\n\nextension AVPlayerItem {\n  func setBufferConfig(config: BufferConfig) {\n    if let forwardBufferDurationMs = config.preferredForwardBufferDurationMs {\n      preferredForwardBufferDuration = TimeInterval(forwardBufferDurationMs / 1000.0)\n    }\n    \n    if let peakBitRate = config.preferredPeakBitRate {\n      preferredPeakBitRate = Double(peakBitRate)\n    }\n    \n    if let maximumResolution = config.preferredMaximumResolution {\n      preferredMaximumResolution = CGSize(width: maximumResolution.width, height: maximumResolution.height)\n    }\n    \n    if let peakBitRateForExpensiveNetworks = config.preferredPeakBitRateForExpensiveNetworks {\n      preferredPeakBitRateForExpensiveNetworks = Double(peakBitRateForExpensiveNetworks)\n    }\n    \n    if let maximumResolutionForExpensiveNetworks = config.preferredMaximumResolutionForExpensiveNetworks {\n      preferredMaximumResolutionForExpensiveNetworks = CGSize(width: maximumResolutionForExpensiveNetworks.width, height: maximumResolutionForExpensiveNetworks.height)\n    }\n    \n    if let liveTargetOffsetMs = config.livePlayback?.targetOffsetMs {\n      configuredTimeOffsetFromLive = CMTime(seconds: Double(liveTargetOffsetMs) / 1000.0, preferredTimescale: 1000)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVPlayerViewController+Fullscreen.swift",
    "content": "//\n//  AVPlayerViewController+Fullscreen.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 27/04/2025.\n//\n\nimport Foundation\nimport AVKit\n\nextension AVPlayerViewController {\n  // https://stackoverflow.com/a/64466924\n  \n  func enterFullscreen(animated: Bool) {\n    performIfResponds(NSSelectorFromString(\"enterFullScreenAnimated:completionHandler:\"), with: animated, with: nil)\n  }\n  \n  func exitFullscreen(animated: Bool) {\n    performIfResponds(NSSelectorFromString(\"exitFullScreenAnimated:completionHandler:\"), with: animated, with: nil)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVPlayerViewController+PictureInPicture.swift",
    "content": "//\n//  AVPlayerViewController+PictureInPicture.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 27/04/2025.\n//\n\nimport Foundation\nimport AVKit\n\nextension AVPlayerViewController {\n  // https://github.com/expo/expo/blob/d37ae17df23c58011a3c5b9f5dedd563bf8e6521/packages/expo-video/ios/VideoView.swift#L110\n  func startPictureInPicture() throws {\n    guard AVPictureInPictureController.isPictureInPictureSupported() else {\n      throw VideoViewError.pictureInPictureNotSupported.error()\n    }\n    \n    performIfResponds(NSSelectorFromString(\"startPictureInPicture\"))\n  }\n  \n  func stopPictureInPicture() {\n    performIfResponds(NSSelectorFromString(\"stopPictureInPicture\"))\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/AVURLAsset+getAssetInformation.swift",
    "content": "import AVFoundation\n\nextension AVURLAsset {\n  func getAssetInformation() async throws -> VideoInformation {\n    // Default values\n    var bitrate = Double.nan\n    var width = Double.nan\n    var height = Double.nan\n    var videoDuration: Double = -1\n    var isHDR = false\n    var isLive = false\n    var orientation: VideoOrientation = .unknown\n\n    let fileSize = try await VideoFileHelper.getFileSize(for: url)\n\n    // Check if asset is live stream\n    if duration.flags.contains(.indefinite) {\n      videoDuration = -1.0\n      isLive = true\n    } else {\n      videoDuration = CMTimeGetSeconds(duration)\n      isLive = false\n    }\n\n    if let videoTrack = tracks(withMediaType: .video).first {\n      let size = videoTrack.naturalSize.applying(videoTrack.preferredTransform)\n      width = size.width\n      height = size.height\n\n      bitrate = Double(videoTrack.estimatedDataRate)\n\n      orientation = videoTrack.orientation\n\n      if #available(iOS 14.0, tvOS 14.0, visionOS 1.0, *) {\n        isHDR = videoTrack.hasMediaCharacteristic(.containsHDRVideo)\n      }\n    } else if url.pathExtension == \"m3u8\" {\n      // For HLS streams, we cannot get video track information directly\n      // So we download manifest and try to extract video information from it\n\n      let manifestContent = try await HLSManifestParser.downloadManifest(from: url)\n      let manifestInfo = try HLSManifestParser.parseM3U8Manifest(manifestContent)\n\n      if let videoStream = manifestInfo.streams.first {\n        width = Double(videoStream.width ?? Int(Double.nan))\n        height = Double(videoStream.height ?? Int(Double.nan))\n        bitrate = Double(videoStream.bandwidth ?? Int(Double.nan))\n      }\n\n      if width > 0 && height > 0 {\n        if width == height {\n          orientation = .square\n        } else if width > height {\n          orientation = .landscapeRight\n        } else if width < height {\n          orientation = .portrait\n        } else {\n          orientation = .unknown\n        }\n      }\n    }\n\n    return VideoInformation(\n      bitrate: bitrate,\n      width: width,\n      height: height,\n      duration: videoDuration,\n      fileSize: fileSize,\n      isHDR: isHDR,\n      isLive: isLive,\n      orientation: orientation\n    )\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/NSObject+PerformIfResponds.swift",
    "content": "//\n//  NSObject+PerformIfResponds.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 27/04/2025.\n//\n\nimport Foundation\n\nextension NSObject {\n  // Safe perform methods for Objective-C selectors\n  \n  func performIfResponds(_ selector: Selector) {\n    if self.responds(to: selector) {\n      self.perform(selector)\n    }\n  }\n  \n  func performIfResponds(_ selector: Selector, with object: Any?) {\n    if self.responds(to: selector) {\n      self.perform(selector, with: object)\n    }\n  }\n  \n  func performIfResponds(_ selector: Selector, with object1: Any?, with object2: Any?) {\n    if self.responds(to: selector) {\n      self.perform(selector, with: object1, with: object2)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Extensions/ResizeMode+VideoGravity.swift",
    "content": "//\n//  ResizeMode.swift\n//  ReactNativeVideo\n//\n//  Created for resizeMode feature\n//\n\nimport Foundation\nimport AVFoundation\n\npublic extension ResizeMode {\n  func toVideoGravity() -> AVLayerVideoGravity {\n    switch self {\n      case .contain:\n        return .resizeAspect\n      case .cover:\n        return .resizeAspectFill\n      case .stretch:\n        return .resize\n      case .none:\n        return .resizeAspect // Default to aspect ratio if none specified\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/HLSSubtitleInjector.swift",
    "content": "import AVFoundation\nimport Foundation\nimport NitroModules\n\nclass HLSSubtitleInjector: NSObject {\n  private let originalManifestUrl: URL\n  private let externalSubtitles: [NativeExternalSubtitle]\n  private var modifiedManifestContent: String?\n  private static let customScheme = \"rnv-hls\"\n  private static let subtitleScheme = \"rnv-hls-subtitles\"\n  private static let subtitleGroupID = \"rnv-subs\"\n  private static let resourceLoaderQueue = DispatchQueue(\n    label: \"com.nitro.HLSSubtitleInjector.resourceLoaderQueue\",\n    qos: .userInitiated\n  )\n\n  init(manifestUrl: URL, externalSubtitles: [NativeExternalSubtitle]) {\n    self.originalManifestUrl = manifestUrl\n    self.externalSubtitles = externalSubtitles\n    super.init()\n  }\n\n  func createModifiedAsset() -> AVURLAsset {\n    let customURL = createCustomURL(from: originalManifestUrl)\n    let asset = AVURLAsset(url: customURL)\n    asset.resourceLoader.setDelegate(\n      self,\n      queue: Self.resourceLoaderQueue\n    )\n    return asset\n  }\n\n  private func createCustomURL(from originalURL: URL) -> URL {\n    var components = URLComponents(\n      url: originalURL,\n      resolvingAgainstBaseURL: false\n    )!\n    components.scheme = Self.customScheme\n    return components.url!\n  }\n\n  private func getModifiedManifestContent() async throws -> String {\n    if let cached = modifiedManifestContent {\n      return cached\n    }\n\n    let originalContent = try await HLSManifestParser.downloadManifest(from: originalManifestUrl)\n    let modifiedContent = try modifyM3U8Content(\n      originalContent,\n      with: externalSubtitles\n    )\n    modifiedManifestContent = modifiedContent\n    return modifiedContent\n  }\n\n  private func modifyM3U8Content(\n    _ originalContent: String,\n    with externalSubtitles: [NativeExternalSubtitle]\n  ) throws -> String {\n    let lines = originalContent.components(separatedBy: .newlines)\n    var modifiedLines: [String] = []\n    var foundExtM3U = false\n    var isAfterVersionOrM3U = false\n    var hasSubtitleGroup = false\n    let baseURL = originalManifestUrl.deletingLastPathComponent()\n\n    for line in lines {\n      let trimmedLine = line.trimmingCharacters(in: .whitespaces)\n\n      if trimmedLine.hasPrefix(\"#EXTM3U\") {\n        foundExtM3U = true\n        modifiedLines.append(line)\n        isAfterVersionOrM3U = true\n        continue\n      }\n\n      if isAfterVersionOrM3U && !hasSubtitleGroup\n        && shouldInsertSubtitlesHere(line: trimmedLine)\n      {\n        for (index, subtitle) in externalSubtitles.enumerated() {\n          let subtitleTrack = createSubtitleTrackEntry(for: subtitle, index: index)\n          modifiedLines.append(subtitleTrack)\n        }\n        hasSubtitleGroup = true\n        isAfterVersionOrM3U = false\n      }\n\n      let processedLine = HLSManifestParser.convertRelativeURLsToAbsolute(\n        line: line,\n        baseURL: baseURL\n      )\n\n      // Handle existing subtitle groups and stream info lines\n      if trimmedLine.hasPrefix(\"#EXT-X-MEDIA:\") && trimmedLine.contains(\"TYPE=SUBTITLES\") {\n        let modifiedMediaLine = replaceSubtitleGroupInMediaLine(processedLine)\n        modifiedLines.append(modifiedMediaLine)\n      } else if trimmedLine.hasPrefix(\"#EXT-X-STREAM-INF:\") {\n        let modifiedStreamLine = replaceSubtitleGroupInStreamInf(\n          processedLine, hasSubtitleGroup: hasSubtitleGroup)\n        modifiedLines.append(modifiedStreamLine)\n      } else {\n        modifiedLines.append(processedLine)\n      }\n    }\n\n    if foundExtM3U && !hasSubtitleGroup {\n      var finalLines: [String] = []\n      var insertedSubtitles = false\n\n      for line in modifiedLines {\n        finalLines.append(line)\n\n        if !insertedSubtitles\n          && (line.hasPrefix(\"#EXTM3U\") || line.hasPrefix(\"#EXT-X-VERSION\"))\n        {\n          for (index, subtitle) in externalSubtitles.enumerated() {\n            let subtitleTrack = createSubtitleTrackEntry(for: subtitle, index: index)\n            finalLines.append(subtitleTrack)\n          }\n          insertedSubtitles = true\n        }\n      }\n\n      modifiedLines = finalLines\n    }\n\n    if !foundExtM3U {\n      throw SourceError.invalidUri(uri: originalManifestUrl.absoluteString)\n        .error()\n    }\n\n    // Post-process: ensure every variant stream references our subtitle group if we injected it\n    if hasSubtitleGroup {\n      modifiedLines = modifiedLines.map { line in\n        if line.hasPrefix(\"#EXT-X-STREAM-INF:\") && !line.contains(\"SUBTITLES=\") {\n          if line.hasSuffix(\",\") {\n            return line + \"SUBTITLES=\\\"\\(Self.subtitleGroupID)\\\"\"\n          } else {\n            return line + \",SUBTITLES=\\\"\\(Self.subtitleGroupID)\\\"\"\n          }\n        }\n        return line\n      }\n    }\n\n    return modifiedLines.joined(separator: \"\\n\")\n  }\n\n  private func shouldInsertSubtitlesHere(line: String) -> Bool {\n    return line.hasPrefix(\"#EXT-X-STREAM-INF:\")\n      || line.hasPrefix(\"#EXT-X-I-FRAME-STREAM-INF:\")\n      || line.hasPrefix(\"#EXT-X-MEDIA:\")\n      || line.hasPrefix(\"#EXTINF:\")\n      || line.hasPrefix(\"#EXT-X-BYTERANGE:\")\n      || (!line.hasPrefix(\"#\") && !line.isEmpty\n        && !line.hasPrefix(\"#EXT-X-VERSION\"))\n  }\n\n  private func replaceSubtitleGroupInMediaLine(_ line: String) -> String {\n    // Find and replace GROUP-ID in subtitle media lines\n    let groupIdPattern = #\"GROUP-ID=\"[^\"]*\"\"#\n\n    if let regex = try? NSRegularExpression(pattern: groupIdPattern, options: []) {\n      let range = NSRange(location: 0, length: line.utf16.count)\n      let replacement = \"GROUP-ID=\\\"\\(Self.subtitleGroupID)\\\"\"\n      return regex.stringByReplacingMatches(\n        in: line, options: [], range: range, withTemplate: replacement)\n    }\n\n    return line\n  }\n\n  private func replaceSubtitleGroupInStreamInf(_ line: String, hasSubtitleGroup: Bool) -> String {\n    // First, handle existing SUBTITLES= references\n    let subtitlesPattern = #\"SUBTITLES=\"[^\"]*\"\"#\n\n    var modifiedLine = line\n    if let regex = try? NSRegularExpression(pattern: subtitlesPattern, options: []) {\n      let range = NSRange(location: 0, length: line.utf16.count)\n      let replacement = \"SUBTITLES=\\\"\\(Self.subtitleGroupID)\\\"\"\n      modifiedLine = regex.stringByReplacingMatches(\n        in: line, options: [], range: range, withTemplate: replacement)\n    } else if hasSubtitleGroup && !line.contains(\"SUBTITLES=\") {\n      // Add subtitle group reference if we have subtitles but no existing reference\n      if line.hasSuffix(\",\") {\n        modifiedLine = line + \"SUBTITLES=\\\"\\(Self.subtitleGroupID)\\\"\"\n      } else {\n        modifiedLine = line + \",SUBTITLES=\\\"\\(Self.subtitleGroupID)\\\"\"\n      }\n    }\n\n    return modifiedLine\n  }\n\n  private func createSubtitleTrackEntry(for subtitle: NativeExternalSubtitle, index: Int)\n    -> String\n  {\n    let subtitleM3U8URI = \"\\(Self.subtitleScheme)://\\(index)/subtitle.m3u8\"\n\n    return\n      \"#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\\\"\\(Self.subtitleGroupID)\\\",NAME=\\\"\\(subtitle.label)\\\",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE=\\\"\\(subtitle.language)\\\",URI=\\\"\\(subtitleM3U8URI)\\\"\"\n  }\n}\n\n// MARK: - AVAssetResourceLoaderDelegate\n\nextension HLSSubtitleInjector: AVAssetResourceLoaderDelegate {\n  func resourceLoader(\n    _ resourceLoader: AVAssetResourceLoader,\n    shouldWaitForLoadingOfRequestedResource loadingRequest:\n      AVAssetResourceLoadingRequest\n  ) -> Bool {\n\n    guard let url = loadingRequest.request.url else {\n      return false\n    }\n\n    switch url.scheme {\n    case Self.customScheme:\n      return handleMainManifest(url: url, loadingRequest: loadingRequest)\n    case Self.subtitleScheme:\n      return handleSubtitleM3U8(url: url, loadingRequest: loadingRequest)\n    default:\n      return false\n    }\n  }\n\n  private func handleMainManifest(url: URL, loadingRequest: AVAssetResourceLoadingRequest) -> Bool {\n    guard url.path.hasSuffix(\".m3u8\") else {\n      return false\n    }\n\n    Task {\n      do {\n        let modifiedContent = try await getModifiedManifestContent()\n\n        guard let data = modifiedContent.data(using: .utf8) else {\n          throw SourceError.invalidUri(uri: \"Failed to encode manifest content\")\n            .error()\n        }\n\n        if let contentRequest = loadingRequest.contentInformationRequest {\n          contentRequest.contentType = \"application/x-mpegURL\"\n          contentRequest.contentLength = Int64(data.count)\n          contentRequest.isByteRangeAccessSupported = true\n        }\n\n        if let dataRequest = loadingRequest.dataRequest {\n          let requestedData: Data\n\n          if dataRequest.requestedOffset > 0 || dataRequest.requestedLength > 0 {\n            let offset = Int(dataRequest.requestedOffset)\n            let length =\n              dataRequest.requestedLength > 0\n              ? min(Int(dataRequest.requestedLength), data.count - offset)\n              : data.count - offset\n\n            if offset < data.count && length > 0 {\n              requestedData = data.subdata(in: offset..<(offset + length))\n            } else {\n              requestedData = Data()\n            }\n          } else {\n            requestedData = data\n          }\n\n          dataRequest.respond(with: requestedData)\n        }\n\n        loadingRequest.finishLoading()\n      } catch {\n        loadingRequest.finishLoading(with: error)\n      }\n    }\n\n    return true\n  }\n\n  private func handleSubtitleM3U8(url: URL, loadingRequest: AVAssetResourceLoadingRequest) -> Bool {\n    guard let indexString = url.host, let index = Int(indexString) else {\n      return false\n    }\n\n    guard index < externalSubtitles.count else {\n      return false\n    }\n\n    let subtitle = externalSubtitles[index]\n\n    Task {\n      do {\n        guard let subtitleURL = URL(string: subtitle.uri) else {\n          throw SourceError.invalidUri(uri: \"Invalid subtitle URI: \\(subtitle.uri)\").error()\n        }\n\n        let (vttData, response) = try await URLSession.shared.data(from: subtitleURL)\n\n        guard let httpResponse = response as? HTTPURLResponse,\n          200...299 ~= httpResponse.statusCode\n        else {\n          throw SourceError.invalidUri(uri: \"Subtitle request failed with status: \\(response)\")\n            .error()\n        }\n\n        guard let vttString = String(data: vttData, encoding: .utf8) else {\n          throw SourceError.invalidUri(uri: \"Failed to decode VTT content\").error()\n        }\n\n        let duration = extractDurationFromVTT(vttString)\n\n        let m3u8Wrapper = \"\"\"\n          #EXTM3U\n          #EXT-X-VERSION:3\n          #EXT-X-MEDIA-SEQUENCE:1\n          #EXT-X-PLAYLIST-TYPE:VOD\n          #EXT-X-ALLOW-CACHE:NO\n          #EXT-X-TARGETDURATION:\\(Int(duration))\n          #EXTINF:\\(String(format: \"%.3f\", duration)), no desc\n          \\(subtitle.uri)\n          #EXT-X-ENDLIST\n          \"\"\"\n\n        guard let m3u8Data = m3u8Wrapper.data(using: .utf8) else {\n          throw SourceError.invalidUri(uri: \"Failed to create M3U8 wrapper\").error()\n        }\n\n        if let contentRequest = loadingRequest.contentInformationRequest {\n          contentRequest.contentType = \"application/x-mpegURL\"\n          contentRequest.contentLength = Int64(m3u8Data.count)\n          contentRequest.isByteRangeAccessSupported = true\n        }\n\n        if let dataRequest = loadingRequest.dataRequest {\n          dataRequest.respond(with: m3u8Data)\n        }\n\n        loadingRequest.finishLoading()\n      } catch {\n        loadingRequest.finishLoading(with: error)\n      }\n    }\n\n    return true\n  }\n\n  private func extractDurationFromVTT(_ vttString: String) -> Double {\n    // Extract duration from VTT timestamps (similar to the PR approach)\n    let timestampPattern = #\"(?:(\\d+):)?(\\d+):([\\d\\.]+)\"#\n\n    guard let regex = try? NSRegularExpression(pattern: timestampPattern, options: []) else {\n      return 60.0  // Default fallback\n    }\n\n    let matches = regex.matches(\n      in: vttString,\n      options: [],\n      range: NSRange(location: 0, length: vttString.utf16.count)\n    )\n\n    guard let lastMatch = matches.last,\n      let range = Range(lastMatch.range, in: vttString)\n    else {\n      return 60.0  // Default fallback\n    }\n\n    let lastTimestampString = String(vttString[range])\n    let components = lastTimestampString.components(separatedBy: \":\").reversed()\n      .compactMap { Double($0) }\n      .enumerated()\n      .map { pow(60.0, Double($0.offset)) * $0.element }\n      .reduce(0, +)\n\n    return max(components, 1.0)  // Ensure at least 1 second\n  }\n\n  func resourceLoader(\n    _ resourceLoader: AVAssetResourceLoader,\n    didCancel loadingRequest: AVAssetResourceLoadingRequest\n  ) {\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/NowPlayingInfoCenterManager.swift",
    "content": "import Foundation\nimport MediaPlayer\n\nclass NowPlayingInfoCenterManager {\n  static let shared = NowPlayingInfoCenterManager()\n\n  private let SEEK_INTERVAL_SECONDS: Double = 10\n\n  private weak var currentPlayer: AVPlayer?\n  private var players = NSHashTable<AVPlayer>.weakObjects()\n\n  private var observers: [Int: NSKeyValueObservation] = [:]\n  private var playbackObserver: Any?\n\n  private var playTarget: Any?\n  private var pauseTarget: Any?\n  private var skipForwardTarget: Any?\n  private var skipBackwardTarget: Any?\n  private var playbackPositionTarget: Any?\n  private var togglePlayPauseTarget: Any?\n\n  private let remoteCommandCenter = MPRemoteCommandCenter.shared()\n\n  var receivingRemoteControlEvents = false {\n    didSet {\n      if receivingRemoteControlEvents {\n        DispatchQueue.main.async { [weak self] in\n          VideoManager.shared.setRemoteControlEventsActive(true)\n          UIApplication.shared.beginReceivingRemoteControlEvents()\n          if self?.currentPlayer?.currentItem != nil {\n            self?.updateNowPlayingInfo()\n          }\n        }\n      } else {\n        DispatchQueue.main.async {\n          UIApplication.shared.endReceivingRemoteControlEvents()\n          VideoManager.shared.setRemoteControlEventsActive(false)\n        }\n      }\n    }\n  }\n\n  deinit {\n    cleanup()\n  }\n\n  func registerPlayer(player: AVPlayer) {\n    if players.contains(player) {\n      return\n    }\n\n    if !receivingRemoteControlEvents {\n      receivingRemoteControlEvents = true\n    }\n\n    if let oldObserver = observers[player.hashValue] {\n      oldObserver.invalidate()\n    }\n\n    observers[player.hashValue] = observePlayers(player: player)\n    players.add(player)\n\n    // Also take over if the new player is already playing — KVO won't fire since rate hasn't changed\n    if currentPlayer == nil || player.rate != 0 {\n      setCurrentPlayer(player: player)\n    }\n  }\n\n  func removePlayer(player: AVPlayer) {\n    if !players.contains(player) {\n      return\n    }\n\n    if let observer = observers[player.hashValue] {\n      observer.invalidate()\n    }\n\n    observers.removeValue(forKey: player.hashValue)\n    players.remove(player)\n\n    if players.allObjects.isEmpty {\n      cleanup()\n      return\n    }\n\n    if currentPlayer == player {\n      if let playbackObserver {\n        player.removeTimeObserver(playbackObserver)\n        self.playbackObserver = nil\n      }\n      currentPlayer = nil\n      findNewCurrentPlayer()\n      if currentPlayer == nil {\n        updatePlaybackState()\n      }\n    }\n  }\n\n  public func cleanup() {\n    observers.removeAll()\n    players.removeAllObjects()\n\n    if let playbackObserver {\n      currentPlayer?.removeTimeObserver(playbackObserver)\n      self.playbackObserver = nil\n    }\n    currentPlayer = nil\n\n    invalidateCommandTargets()\n\n    MPNowPlayingInfoCenter.default().nowPlayingInfo = [:]\n    receivingRemoteControlEvents = false\n  }\n\n  private func setCurrentPlayer(player: AVPlayer) {\n    if player == currentPlayer {\n      return\n    }\n\n    if let playbackObserver {\n      currentPlayer?.removeTimeObserver(playbackObserver)\n      self.playbackObserver = nil\n    }\n\n    currentPlayer = player\n    registerCommandTargets()\n\n    updateNowPlayingInfo()\n    playbackObserver = player.addPeriodicTimeObserver(\n      forInterval: CMTime(value: 1, timescale: 4),\n      queue: .main,\n      using: { [weak self] _ in\n        self?.updatePlaybackState()\n      }\n    )\n  }\n\n  private func registerCommandTargets() {\n    invalidateCommandTargets()\n\n    playTarget = remoteCommandCenter.playCommand.addTarget { [weak self] _ in\n      guard let self, let player = self.currentPlayer else {\n        return .commandFailed\n      }\n\n      if player.rate == 0 {\n        player.play()\n      }\n\n      return .success\n    }\n\n    pauseTarget = remoteCommandCenter.pauseCommand.addTarget { [weak self] _ in\n      guard let self, let player = self.currentPlayer else {\n        return .commandFailed\n      }\n\n      if player.rate != 0 {\n        player.pause()\n      }\n\n      return .success\n    }\n\n    skipBackwardTarget = remoteCommandCenter.skipBackwardCommand.addTarget {\n      [weak self] _ in\n      guard let self, let player = self.currentPlayer else {\n        return .commandFailed\n      }\n      let newTime =\n        player.currentTime()\n        - CMTime(seconds: self.SEEK_INTERVAL_SECONDS, preferredTimescale: .max)\n      player.seek(to: newTime)\n      return .success\n    }\n\n    skipForwardTarget = remoteCommandCenter.skipForwardCommand.addTarget {\n      [weak self] _ in\n      guard let self, let player = self.currentPlayer else {\n        return .commandFailed\n      }\n\n      let newTime =\n        player.currentTime()\n        + CMTime(seconds: self.SEEK_INTERVAL_SECONDS, preferredTimescale: .max)\n      player.seek(to: newTime)\n      return .success\n    }\n\n    playbackPositionTarget = remoteCommandCenter.changePlaybackPositionCommand\n      .addTarget { [weak self] event in\n        guard let self, let player = self.currentPlayer else {\n          return .commandFailed\n        }\n        if let event = event as? MPChangePlaybackPositionCommandEvent {\n          player.seek(\n            to: CMTime(seconds: event.positionTime, preferredTimescale: .max)\n          )\n          return .success\n        }\n        return .commandFailed\n      }\n\n    // Handler for togglePlayPauseCommand, sent by Apple's Earpods wired headphones\n    togglePlayPauseTarget = remoteCommandCenter.togglePlayPauseCommand.addTarget\n    { [weak self] _ in\n      guard let self, let player = self.currentPlayer else {\n        return .commandFailed\n      }\n\n      if player.rate == 0 {\n        player.play()\n      } else {\n        player.pause()\n      }\n\n      return .success\n    }\n  }\n\n  private func invalidateCommandTargets() {\n    remoteCommandCenter.playCommand.removeTarget(playTarget)\n    remoteCommandCenter.pauseCommand.removeTarget(pauseTarget)\n    remoteCommandCenter.skipForwardCommand.removeTarget(skipForwardTarget)\n    remoteCommandCenter.skipBackwardCommand.removeTarget(skipBackwardTarget)\n    remoteCommandCenter.changePlaybackPositionCommand.removeTarget(\n      playbackPositionTarget\n    )\n    remoteCommandCenter.togglePlayPauseCommand.removeTarget(\n      togglePlayPauseTarget\n    )\n  }\n\n  public func updateNowPlayingInfo() {\n    updateStaticInfo()\n    updatePlaybackState()\n  }\n\n  func updateStaticInfo(ifCurrentItem playerItem: AVPlayerItem) {\n    guard currentPlayer?.currentItem === playerItem else { return }\n    updateStaticInfo()\n  }\n\n  func updateStaticInfo() {\n    guard let player = currentPlayer, let currentItem = player.currentItem else {\n      return\n    }\n\n    // commonMetadata is metadata from asset, externalMetadata is custom metadata set by user\n    // externalMetadata should override commonMetadata to allow override metadata from source\n    // When the metadata has the tag \"iTunSMPB\" or \"iTunNORM\" then the metadata is not converted correctly and comes [nil, nil, ...]\n    // This leads to a crash of the app\n    let metadata: [AVMetadataItem] = {\n      let common = processMetadataItems(currentItem.asset.commonMetadata)\n      let external = processMetadataItems(currentItem.externalMetadata)\n      return Array(common.merging(external) { _, new in new }.values)\n    }()\n\n    let title = AVMetadataItem.metadataItems(\n      from: metadata,\n      filteredByIdentifier: .commonIdentifierTitle\n    ).first?.stringValue ?? \"\"\n\n    let artist = AVMetadataItem.metadataItems(\n      from: metadata,\n      filteredByIdentifier: .commonIdentifierArtist\n    ).first?.stringValue ?? \"\"\n\n    var info = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]\n    info[MPMediaItemPropertyTitle] = title\n    info[MPMediaItemPropertyArtist] = artist\n    info[MPMediaItemPropertyPlaybackDuration] = currentItem.duration.seconds\n    info[MPNowPlayingInfoPropertyIsLiveStream] = CMTIME_IS_INDEFINITE(currentItem.asset.duration)\n    info[MPMediaItemPropertyArtwork] = nil // Clear artwork from previous item; will be loaded asynchronously below\n    MPNowPlayingInfoCenter.default().nowPlayingInfo = info\n\n    // Load artwork asynchronously so notification controls appear immediately.\n    guard let artworkMetadataItem = AVMetadataItem.metadataItems(\n      from: metadata,\n      filteredByIdentifier: .commonIdentifierArtwork\n    ).first else { return }\n\n    Task { [weak self, weak player, weak currentItem] in\n      guard let data = try? await artworkMetadataItem.load(.dataValue),\n            let image = UIImage(data: data) else { return }\n      let artworkItem = MPMediaItemArtwork(boundsSize: image.size) { _ in image }\n      await MainActor.run {\n        guard let self, self.currentPlayer === player,\n              self.currentPlayer?.currentItem === currentItem else { return }\n        var info = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]\n        info[MPMediaItemPropertyArtwork] = artworkItem\n        MPNowPlayingInfoCenter.default().nowPlayingInfo = info\n      }\n    }\n  }\n\n  func updatePlaybackState() {\n    guard let player = currentPlayer else {\n      invalidateCommandTargets()\n      MPNowPlayingInfoCenter.default().nowPlayingInfo = [:]\n      return\n    }\n\n    guard let currentItem = player.currentItem else { return }\n\n    var info = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]\n    info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = currentItem.currentTime().seconds\n    info[MPNowPlayingInfoPropertyPlaybackRate] = player.rate\n    info[MPMediaItemPropertyPlaybackDuration] = currentItem.duration.seconds\n    MPNowPlayingInfoCenter.default().nowPlayingInfo = info\n  }\n\n  private func findNewCurrentPlayer() {\n    if let newPlayer = players.allObjects.first(where: {\n      $0.rate != 0\n    }) {\n      setCurrentPlayer(player: newPlayer)\n    }\n  }\n\n  // We will observe players rate to find last active player that info will be displayed\n  private func observePlayers(player: AVPlayer) -> NSKeyValueObservation {\n    return player.observe(\\.rate) { [weak self] player, _ in\n      guard let self else { return }\n\n      let rate = player.rate\n\n      // case where there is new player that is not paused\n      // In this case event is triggered by non currentPlayer\n      if rate != 0 && self.currentPlayer != player {\n        self.setCurrentPlayer(player: player)\n        return\n      }\n\n      // case where currentPlayer was paused\n      // In this case event is triggered by currentPlayer\n      if rate == 0 && self.currentPlayer == player {\n        self.findNewCurrentPlayer()\n      }\n    }\n  }\n\n  private func processMetadataItems(_ items: [AVMetadataItem]) -> [String:\n    AVMetadataItem]\n  {\n    var result = [String: AVMetadataItem]()\n\n    for item in items {\n      if let id = item.identifier?.rawValue, !id.isEmpty, result[id] == nil {\n        result[id] = item\n      }\n    }\n\n    return result\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Plugins/PluginsRegistry.swift",
    "content": "//\n//  PluginRegistry.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 22/07/2025.\n//\n\nimport AVFoundation\nimport Foundation\n\npublic final class PluginsRegistry {\n  public static let shared = PluginsRegistry()\n\n  // Plugin ID -> ReactNativeVideoPluginSpec\n  private var plugins: [String: ReactNativeVideoPluginSpec] = [:]\n\n  // MARK: - Public API\n\n  public func register(plugin: ReactNativeVideoPluginSpec) {\n    #if DEBUG\n      if hasPlugin(plugin: plugin) {\n        print(\n          \"[ReactNativeVideo] Plugin \\(plugin.name) (ID: \\(plugin.id)) is already registered - overwriting.\"\n        )\n      } else {\n        print(\n          \"[ReactNativeVideo] Registering plugin \\(plugin.name) (ID: \\(plugin.id)).\"\n        )\n      }\n    #endif\n\n    plugins.updateValue(plugin, forKey: plugin.id)\n  }\n\n  public func unregister(plugin: ReactNativeVideoPluginSpec) {\n    #if DEBUG\n      if !hasPlugin(plugin: plugin) {\n        print(\n          \"[ReactNativeVideo] Plugin \\(plugin.name) (ID: \\(plugin.id)) is not registered - skipping.\"\n        )\n      } else {\n        print(\"[ReactNativeVideo] Unregistering plugin \\(plugin.name) (ID: \\(plugin.id)).\")\n      }\n    #endif\n\n    plugins.removeValue(forKey: plugin.id)\n  }\n\n  // MARK: - Internal API\n\n  private func hasPlugin(plugin: ReactNativeVideoPluginSpec) -> Bool {\n    return plugins.contains { $0.value.id == plugin.id }\n  }\n\n  internal func getDrmManager(source: NativeVideoPlayerSource) throws -> DRMManagerSpec? {\n    for plugin in plugins.values {\n      if let drmManager = plugin.getDRMManager(source: source) {\n        return drmManager\n      }\n    }\n\n    throw LibraryError.DRMPluginNotFound.error()\n  }\n\n  internal func overrideSource(source: NativeVideoPlayerSource) async\n    -> NativeVideoPlayerSource\n  {\n    var overriddenSource = source\n\n    for plugin in plugins.values {\n      overriddenSource = await plugin.overrideSource(source: overriddenSource)\n    }\n\n    return overriddenSource\n  }\n\n  // MARK: - Notifications\n\n  internal func notifyPlayerCreated(player: NativeVideoPlayer) {\n    for plugin in plugins.values {\n      plugin.onPlayerCreated(player: Weak(value: player))\n    }\n  }\n\n  internal func notifyPlayerDestroyed(player: NativeVideoPlayer) {\n    for plugin in plugins.values {\n      plugin.onPlayerDestroyed(player: Weak(value: player))\n    }\n  }\n\n  internal func notifyVideoViewCreated(view: VideoComponentView) {\n    for plugin in plugins.values {\n      plugin.onVideoViewCreated(view: Weak(value: view))\n    }\n  }\n\n  internal func notifyVideoViewDestroyed(view: VideoComponentView) {\n    for plugin in plugins.values {\n      plugin.onVideoViewDestroyed(view: Weak(value: view))\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Plugins/ReactNativeVideoPlugin.swift",
    "content": "//\n//  ReactNativeVideoPlugin.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 22/07/2025.\n//\n\nimport AVFoundation\nimport Foundation\n\npublic protocol ReactNativeVideoPluginSpec {\n  /**\n   * The ID of the plugin.\n   */\n  var id: String { get }\n\n  /**\n   * The name of the plugin.\n   */\n  var name: String { get }\n\n  /**\n   * Called when a player is created.\n   *\n   * @param player The weak reference to the player instance.\n   */\n  func onPlayerCreated(player: Weak<NativeVideoPlayer>)\n\n  /**\n   * Called when a player is destroyed.\n   *\n   * @param player The weak reference to the player instance.\n   */\n  func onPlayerDestroyed(player: Weak<NativeVideoPlayer>)\n\n  /**\n   * Called when a video view is created.\n   *\n   * @param view The weak reference to the video view instance.\n   */\n  func onVideoViewCreated(view: Weak<VideoComponentView>)\n\n  /**\n   * Called when a video view is destroyed.\n   *\n   * @param view The weak reference to the video view instance.\n   */\n  func onVideoViewDestroyed(view: Weak<VideoComponentView>)\n\n  /**\n   * Called when a source is overridden.\n   *\n   * @param source The source instance.\n   * @return The overridden source instance.\n   */\n  func overrideSource(source: NativeVideoPlayerSource) async -> NativeVideoPlayerSource\n\n  /**\n   * Called when a DRM manager is requested.\n   *\n   * @param source The source instance.\n   * @return The DRM manager instance.\n   */\n  func getDRMManager(source: NativeVideoPlayerSource) -> DRMManagerSpec?\n}\n\nopen class ReactNativeVideoPlugin: ReactNativeVideoPluginSpec {\n  public let id: String\n  public let name: String\n\n  public init(name: String) {\n    self.name = name\n    self.id = \"RNV_Plugin_\\(name)\"\n\n    PluginsRegistry.shared.register(plugin: self)\n  }\n\n  open func onPlayerCreated(player: Weak<NativeVideoPlayer>) { /* no-op */  }\n  open func onPlayerDestroyed(player: Weak<NativeVideoPlayer>) { /* no-op */  }\n\n  open func onVideoViewCreated(view: Weak<VideoComponentView>) { /* no-op */  }\n  open func onVideoViewDestroyed(view: Weak<VideoComponentView>) { /* no-op */  }\n\n  open func overrideSource(source: NativeVideoPlayerSource) async -> NativeVideoPlayerSource {\n    return source\n  }\n\n  open func getDRMManager(source: NativeVideoPlayerSource) -> DRMManagerSpec? {\n    return nil\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Spec/DRMManagerSpec.swift",
    "content": "//\n//  DRMManagerSpec.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 05/08/2025.\n//\n\nimport Foundation\nimport AVFoundation\n\npublic protocol DRMManagerSpec: AVContentKeySessionDelegate {\n  /// Creates a content key request for the given asset and DRM parameters.\n  func createContentKeyRequest(for asset: AVURLAsset, drmParams: NativeDrmParams) throws\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Spec/NativeVideoPlayerSourceSpec.swift",
    "content": "//\n//  NativeVideoPlayerSourceSpec.swift\n//  react-native-video\n//\n// Created by Krzysztof Moch on 23/07/2025.\n//\n\nimport Foundation\nimport AVFoundation\n\n// Helper alias that allow to represet player source outside of module\npublic typealias NativeVideoPlayerSource = NativeVideoPlayerSourceSpec & HybridVideoPlayerSourceSpec\n\npublic protocol NativeVideoPlayerSourceSpec {\n  // MARK: - Properties\n  \n  /// The underlying AVURLAsset instance\n  var asset: AVURLAsset? { get set }\n  \n  /// The URL of the video source\n  var url: URL { get }\n  \n  /// The memory size used by the source\n  var memorySize: Int { get }\n  \n  // MARK: - Methods\n  \n  /// Initialize the asset asynchronously\n  func initializeAsset() async throws\n  \n  /// Get non-null AVURLAsset instance (self.asset)\n  func getAsset() async throws -> AVURLAsset\n  \n  /// Release the asset resources\n  func releaseAsset()\n} \n"
  },
  {
    "path": "packages/react-native-video/ios/core/Spec/NativeVideoPlayerSpec.swift",
    "content": "//\n//  NativeVideoPlayerSpec.swift\n//  react-native-video\n//\n// Created by Krzysztof Moch on 09/10/2024.\n//\n\nimport Foundation\nimport AVFoundation\n\n// Helper alias that allow to represet player outside of module\npublic typealias NativeVideoPlayer = NativeVideoPlayerSpec & HybridVideoPlayerSpec\n\npublic protocol NativeVideoPlayerSpec {\n  // MARK: - Properties\n  \n  /// The underlying AVPlayer instance (should not be used directly)\n  var player: AVPlayer { get set }\n  \n  /// The current player item\n  var playerItem: AVPlayerItem? { get set }\n  \n  /// The player observer for monitoring state changes\n  // var playerObserver: VideoPlayerObserver? { get set }\n  \n  /// Whether the player was auto-paused\n  var wasAutoPaused: Bool { get set }\n  \n  /// Whether the player is currently buffering\n  var isCurrentlyBuffering: Bool { get set }\n  \n  /// The memory size used by the player\n  var memorySize: Int { get }\n  \n  // MARK: - Methods\n  \n  /// Release the player resources\n  func release()\n  \n  /// Initialize the player item asynchronously\n  func initializePlayerItem() async throws -> AVPlayerItem\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Utils/ExternalSubtitlesUtils.swift",
    "content": "import AVFoundation\nimport ObjectiveC\n\nprivate var HLSSubtitleInjectorAssociatedKey: UInt8 = 0\n\nenum ExternalSubtitlesUtils {\n  static func isSubtitleTypeSupported(subtitle: NativeExternalSubtitle) -> Bool {\n    if subtitle.type == .vtt {\n      return true\n    }\n\n    if let url = URL(string: subtitle.uri), url.pathExtension == \"vtt\" {\n      return true\n    }\n\n    print(\"[ReactNativeVideo] Unsupported external subtitle. Expected VTT. uri: \\(subtitle.uri)\")\n    return false\n  }\n\n  static func createCompositionWithExternalSubtitles(\n    for asset: AVURLAsset,\n    config: NativeVideoConfig\n  ) async throws -> AVPlayerItem {\n    let supportedSubtitles = (config.externalSubtitles ?? []).filter { subtitle in\n      isSubtitleTypeSupported(subtitle: subtitle)\n    }\n\n    let subtitles: [(NativeExternalSubtitle, AVURLAsset)] = try supportedSubtitles.map { subtitle in\n      guard let url = URL(string: subtitle.uri) else {\n        throw PlayerError.invalidTrackUrl(url: subtitle.uri).error()\n      }\n      return (subtitle, AVURLAsset(url: url))\n    }\n\n    let mainDuration = try await asset.load(.duration)\n\n    let composition = AVMutableComposition()\n\n    let tracks = try await asset.load(.tracks)\n    for track in tracks {\n      guard let compTrack = composition.addMutableTrack(\n        withMediaType: track.mediaType,\n        preferredTrackID: kCMPersistentTrackID_Invalid\n      ) else { continue }\n\n      do {\n        try compTrack.insertTimeRange(\n          CMTimeRange(start: .zero, duration: mainDuration),\n          of: track,\n          at: .zero\n        )\n      } catch {\n        print(\"[ReactNativeVideo] Error inserting main track \\(track.mediaType.rawValue): \\(error.localizedDescription)\")\n      }\n    }\n\n    for (subtitle, subtitleAsset) in subtitles {\n      let track: AVAssetTrack? = try await subtitleAsset.loadTracks(withMediaType: .text).first\n\n      guard let track else { continue }\n\n      guard let compSubtitleTrack = composition.addMutableTrack(\n        withMediaType: track.mediaType,\n        preferredTrackID: kCMPersistentTrackID_Invalid\n      ) else { continue }\n\n      do {\n        let trackRange = try await track.load(.timeRange)\n        let effectiveDuration = CMTimeMinimum(trackRange.duration, mainDuration)\n        try compSubtitleTrack.insertTimeRange(\n          CMTimeRange(start: .zero, duration: effectiveDuration),\n          of: track,\n          at: .zero\n        )\n\n        compSubtitleTrack.languageCode = subtitle.language\n        compSubtitleTrack.isEnabled = true\n      } catch {\n        print(\"[ReactNativeVideo] Error inserting subtitle track: \\(error.localizedDescription)\")\n        continue\n      }\n    }\n\n    return await AVPlayerItem(asset: composition)\n  }\n\n  static func modifyStreamManifestWithExternalSubtitles(\n    for asset: AVURLAsset,\n    config: NativeVideoConfig\n  ) async throws -> AVPlayerItem {\n    guard let externalSubtitles = config.externalSubtitles,\n      !externalSubtitles.isEmpty\n    else {\n      return AVPlayerItem(asset: asset)\n    }\n\n    let supportedSubtitles = externalSubtitles.filter { subtitle in\n      isSubtitleTypeSupported(subtitle: subtitle)\n    }\n\n    guard !supportedSubtitles.isEmpty else {\n      return AVPlayerItem(asset: asset)\n    }\n\n    let subtitleInjector = HLSSubtitleInjector(\n      manifestUrl: asset.url,\n      externalSubtitles: supportedSubtitles\n    )\n    let modifiedAsset = subtitleInjector.createModifiedAsset()\n    let playerItem = AVPlayerItem(asset: modifiedAsset)\n\n    objc_setAssociatedObject(\n      playerItem,\n      &HLSSubtitleInjectorAssociatedKey,\n      subtitleInjector,\n      .OBJC_ASSOCIATION_RETAIN_NONATOMIC\n    )\n\n    return playerItem\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Utils/HLSManifestParser.swift",
    "content": "import AVFoundation\nimport Foundation\nimport NitroModules\n\nclass HLSManifestParser {\n\n  /// Downloads manifest content from the given URL\n  static func downloadManifest(from url: URL) async throws -> String {\n    let (data, response) = try await URLSession.shared.data(from: url)\n\n    guard let httpResponse = response as? HTTPURLResponse,\n      200...299 ~= httpResponse.statusCode\n    else {\n      throw SourceError.invalidUri(uri: url.absoluteString).error()\n    }\n\n    guard let manifestContent = String(data: data, encoding: .utf8) else {\n      throw SourceError.invalidUri(uri: url.absoluteString).error()\n    }\n\n    return manifestContent\n  }\n\n  /// Converts relative URLs in a manifest line to absolute URLs\n  static func convertRelativeURLsToAbsolute(line: String, baseURL: URL) -> String {\n    let trimmedLine = line.trimmingCharacters(in: .whitespaces)\n\n    if trimmedLine.isEmpty {\n      return line\n    }\n\n    if trimmedLine.hasPrefix(\"#\") {\n      if trimmedLine.contains(\"URI=\") {\n        return convertURIParametersToAbsolute(line: line, baseURL: baseURL)\n      }\n      return line\n    }\n\n    if !trimmedLine.hasPrefix(\"http://\") && !trimmedLine.hasPrefix(\"https://\") {\n      let absoluteURL = baseURL.appendingPathComponent(trimmedLine)\n      return absoluteURL.absoluteString\n    }\n\n    return line\n  }\n\n  /// Converts URI parameters in manifest lines to absolute URLs\n  static func convertURIParametersToAbsolute(line: String, baseURL: URL) -> String {\n    var modifiedLine = line\n    let uriPattern = #\"URI=\"([^\"]+)\"\"#\n\n    guard let regex = try? NSRegularExpression(pattern: uriPattern, options: [])\n    else {\n      return line\n    }\n\n    let nsLine = line as NSString\n    let matches = regex.matches(\n      in: line,\n      options: [],\n      range: NSRange(location: 0, length: nsLine.length)\n    )\n\n    for match in matches.reversed() {\n      if match.numberOfRanges >= 2 {\n        let uriRange = match.range(at: 1)\n        let uri = nsLine.substring(with: uriRange)\n\n        if !uri.hasPrefix(\"http://\") && !uri.hasPrefix(\"https://\") {\n          let absoluteURL = baseURL.appendingPathComponent(uri)\n          let fullRange = match.range(at: 0)\n          let replacement = \"URI=\\\"\\(absoluteURL.absoluteString)\\\"\"\n          modifiedLine = (modifiedLine as NSString).replacingCharacters(\n            in: fullRange,\n            with: replacement\n          )\n        }\n      }\n    }\n\n    return modifiedLine\n  }\n\n  /// Parses M3U8 manifest content and returns parsed information\n  static func parseM3U8Manifest(_ content: String) throws -> HLSManifestInfo {\n    let lines = content.components(separatedBy: .newlines)\n    var info = HLSManifestInfo()\n\n    for line in lines {\n      let trimmedLine = line.trimmingCharacters(in: .whitespaces)\n\n      if trimmedLine.hasPrefix(\"#EXTM3U\") {\n        info.isValid = true\n      }\n\n      // Parse version\n      if trimmedLine.hasPrefix(\"#EXT-X-VERSION:\") {\n        let versionString = String(trimmedLine.dropFirst(\"#EXT-X-VERSION:\".count))\n        info.version = Int(versionString)\n      }\n\n      // Parse stream info for resolution\n      if trimmedLine.hasPrefix(\"#EXT-X-STREAM-INF:\") {\n        let streamInfo = parseStreamInf(trimmedLine)\n        info.streams.append(streamInfo)\n      }\n    }\n\n    if !info.isValid {\n      throw SourceError.invalidUri(uri: \"Invalid M3U8 format\").error()\n    }\n\n    return info\n  }\n\n  /// Parses EXT-X-STREAM-INF line to extract stream information\n  private static func parseStreamInf(_ line: String) -> HLSStreamInfo {\n    var streamInfo = HLSStreamInfo()\n\n    // Parse RESOLUTION\n    if let resolutionRange = line.range(of: \"RESOLUTION=\") {\n      let afterResolution = line[resolutionRange.upperBound...]\n      if let commaRange = afterResolution.range(of: \",\") {\n        let resolutionValue = String(afterResolution[..<commaRange.lowerBound])\n        let components = resolutionValue.components(separatedBy: \"x\")\n        if components.count == 2 {\n          streamInfo.width = Int(components[0])\n          streamInfo.height = Int(components[1])\n        }\n      } else {\n        // Resolution is at the end of the line\n        let resolutionValue = String(afterResolution)\n        let components = resolutionValue.components(separatedBy: \"x\")\n        if components.count == 2 {\n          streamInfo.width = Int(components[0])\n          streamInfo.height = Int(components[1])\n        }\n      }\n    }\n\n    // Parse BANDWIDTH\n    if let bandwidthRange = line.range(of: \"BANDWIDTH=\") {\n      let afterBandwidth = line[bandwidthRange.upperBound...]\n      if let commaRange = afterBandwidth.range(of: \",\") {\n        let bandwidthValue = String(afterBandwidth[..<commaRange.lowerBound])\n        streamInfo.bandwidth = Int(bandwidthValue)\n      } else {\n        // Bandwidth is at the end of the line\n        let bandwidthValue = String(afterBandwidth)\n        streamInfo.bandwidth = Int(bandwidthValue)\n      }\n    }\n\n    return streamInfo\n  }\n}\n\n// MARK: - Data Structures\n\nstruct HLSManifestInfo {\n  var isValid: Bool = false\n  var version: Int?\n  var streams: [HLSStreamInfo] = []\n}\n\nstruct HLSStreamInfo {\n  var width: Int?\n  var height: Int?\n  var bandwidth: Int?\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/Utils/Weak.swift",
    "content": "//\n//  Weak.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 31/07/2025.\n//\n\nimport Foundation\n\n/// A generic class for managing weak references to objects.\n///\n/// The `Weak<T>` class is designed to hold a weak reference to an object of type `T`.\n/// This is particularly useful in scenarios where strong references could lead to retain cycles\n/// or memory leaks, such as in plugin systems or delegate patterns.\n///\n/// - Note: The `value` property provides access to the referenced object, or `nil` if the object has been deallocated.\npublic class Weak<T> {\n  private weak var _value: AnyObject?\n  public var value: T? {\n    return _value as? T\n  }\n\n  public init(value: T) {\n    _value = value as AnyObject\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/VideoError.swift",
    "content": "//\n//  VideoFileHelper.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 24/01/2025.\n//\n\nimport Foundation\nimport NitroModules\n\n// MARK: - LibraryError\nenum LibraryError: VideoError {\n  case deallocated(objectName: String)\n  case DRMPluginNotFound\n\n  var code: String {\n    switch self {\n    case .deallocated:\n      return \"library/deallocated\"\n    case .DRMPluginNotFound:\n      return \"library/drm-plugin-not-found\"\n    }\n  }\n\n  var message: String {\n    switch self {\n    case let .deallocated(objectName: objectName):\n      return \"Object \\(objectName) has been deallocated\"\n    case .DRMPluginNotFound:\n      return \"No DRM plugin have been found, please add one to the project\"\n    }\n  }\n}\n\n// MARK: - PlayerError\nenum PlayerError: VideoError {\n  case notInitialized\n  case assetNotInitialized\n  case invalidSource\n  case invalidTrackUrl(url: String)\n  case cancelled\n  \n  var code: String {\n    switch self {\n    case .notInitialized:\n      return \"player/not-initialized\"\n    case .assetNotInitialized:\n      return \"player/asset-not-initialized\"\n    case .invalidSource:\n      return \"player/invalid-source\"\n    case .invalidTrackUrl:\n      return \"player/invalid-track-url\"\n    case .cancelled:\n      return \"player/cancelled\"\n    }\n  }\n  \n  var message: String {\n    switch self {\n    case .notInitialized:\n      return \"Player has not been initialized (Or has been set to nil)\"\n    case .assetNotInitialized:\n      return \"Asset has not been initialized (Or has been set to nil)\"\n    case .invalidSource:\n      return \"Invalid source passed to player\"\n    case let .invalidTrackUrl(url: url):\n      return \"Invalid track URL: \\(url)\"\n    case .cancelled:\n      return \"Operation was cancelled\"\n    }\n  }\n}\n\n// MARK: - SourceError\nenum SourceError: VideoError {\n  case invalidUri(uri: String)\n  case missingReadFilePermission(uri: String)\n  case fileDoesNotExist(uri: String)\n  case failedToInitializeAsset\n  case unsupportedContentType(uri: String)\n  case cancelled\n\n  var code: String {\n    switch self {\n    case .invalidUri:\n      return \"source/invalid-uri\"\n    case .missingReadFilePermission:\n      return \"source/missing-read-file-permission\"\n    case .fileDoesNotExist:\n      return \"source/file-does-not-exist\"\n    case .failedToInitializeAsset:\n      return \"source/failed-to-initialize-asset\"\n    case .unsupportedContentType:\n      return \"source/unsupported-content-type\"\n    case .cancelled:\n      return \"source/cancelled\"\n    }\n  }\n\n  var message: String {\n    switch self {\n    case let .invalidUri(uri: uri):\n      return \"Invalid source file uri: \\(uri)\"\n    case let .missingReadFilePermission(uri: uri):\n      return \"Missing read file permission for source file at \\(uri)\"\n    case let .fileDoesNotExist(uri: uri):\n      return \"File does not exist at URI: \\(uri)\"\n    case .failedToInitializeAsset:\n      return \"Failed to initialize asset\"\n    case let .unsupportedContentType(uri: uri):\n      return \"type of content (\\(uri)) is not supported\"\n    case .cancelled:\n      return \"Operation was cancelled\"\n    }\n  }\n}\n\n// MARK: - VideoViewError\nenum VideoViewError: VideoError {\n  case viewNotFound(nitroId: Double)\n  case viewIsDeallocated\n  case pictureInPictureNotSupported\n  \n  var code: String {\n    switch self {\n    case .viewNotFound:\n      return \"view/not-found\"\n    case .viewIsDeallocated:\n      return \"view/deallocated\"\n    case .pictureInPictureNotSupported:\n      return \"view/picture-in-picture-not-supported\"\n    }\n  }\n  \n  var message: String {\n    switch self {\n    case let .viewNotFound(nitroId: nitroId):\n      return \"View with nitroId \\(nitroId) not found\"\n    case .viewIsDeallocated:\n      return \"Attempt to access a view, but it has been deallocated (or not initialized)\"\n    case .pictureInPictureNotSupported:\n      return \"Picture in picture is not supported on this device\"\n    }\n  }\n}\n\n// MARK: - UnknownError\nstruct UnknownError: VideoError {\n  var code: String { \"unknown/unknown\" }\n  var message: String { \"Unknown error\" }\n}\n\n// MARK: - VideoError\nprotocol VideoError {\n  var code: String { get }\n  var message: String { get }\n}\n\nextension VideoError {\n  private func getMessage() -> String {\n    return \"{%@\\(code)::\\(message)@%}\"\n  }\n\n  func error() -> Error {\n    return RuntimeError.error(withMessage: getMessage())\n  }\n}\n\n\n"
  },
  {
    "path": "packages/react-native-video/ios/core/VideoFileHelper.swift",
    "content": "//\n//  VideoFileHelper.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 23/01/2025.\n//\n\nimport Foundation\nimport NitroModules\n\nenum VideoFileHelper {\n  private static let fileManager = FileManager.default\n  \n  static func getFileSize(for url: URL) async throws -> Int64 {\n    if url.isFileURL {\n      return try getLocalFileSize(for: url)\n    }\n    return try await getRemoteFileSize(for: url)\n  }\n  \n  static func validateReadPermission(for url: URL) throws {\n    guard url.isFileURL else { return }\n    \n    if !fileManager.isReadableFile(atPath: url.path) {\n      throw SourceError.missingReadFilePermission(uri: url.path).error()\n    }\n  }\n  \n  // MARK: - Private\n  \n  private static func getLocalFileSize(for url: URL) throws -> Int64 {\n    Int64(try url.resourceValues(forKeys: [.fileSizeKey]).fileSize ?? -1)\n  }\n  \n  private static func getRemoteFileSize(for url: URL) async throws -> Int64 {\n    var request = URLRequest(url: url)\n    request.httpMethod = \"HEAD\"\n    \n    let (_, response) = try await URLSession.shared.data(for: request)\n    guard let httpResponse = response as? HTTPURLResponse,\n          let contentLength = httpResponse.allHeaderFields[\"Content-Length\"] as? String,\n          let size = Int64(contentLength) else {\n      return -1\n    }\n    \n    return size\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/VideoManager.swift",
    "content": "//\n//  VideoManager.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 27/04/2025.\n//\n\nimport Foundation\nimport AVFoundation\n\nclass VideoManager {\n  // MARK: - Singleton\n  static let shared = VideoManager()\n  \n  private var players = NSHashTable<HybridVideoPlayer>.weakObjects()\n  private var videoView = NSHashTable<VideoComponentView>.weakObjects()\n  \n  private var isAudioSessionActive = false\n  private var remoteControlEventsActive = false\n  \n  // TODO: Create Global Config, and expose it there\n  private var isAudioSessionManagementDisabled: Bool = false\n  \n  private init() {\n    // Subscribe to audio interruption notifications\n    NotificationCenter.default.addObserver(\n      self,\n      selector: #selector(handleAudioSessionInterruption),\n      name: AVAudioSession.interruptionNotification,\n      object: nil\n    )\n    \n    // Subscribe to route change notifications\n    NotificationCenter.default.addObserver(\n      self,\n      selector: #selector(handleAudioRouteChange),\n      name: AVAudioSession.routeChangeNotification,\n      object: nil\n    )\n    \n    NotificationCenter.default.addObserver(\n      self,\n      selector: #selector(applicationWillResignActive(notification:)),\n      name: UIApplication.willResignActiveNotification,\n      object: nil\n    )\n    \n    NotificationCenter.default.addObserver(\n      self,\n      selector: #selector(applicationDidBecomeActive(notification:)),\n      name: UIApplication.didBecomeActiveNotification,\n      object: nil\n    )\n    \n    NotificationCenter.default.addObserver(\n      self,\n      selector: #selector(applicationDidEnterBackground(notification:)),\n      name: UIApplication.didEnterBackgroundNotification,\n      object: nil\n    )\n    \n    NotificationCenter.default.addObserver(\n      self,\n      selector: #selector(applicationWillEnterForeground(notification:)),\n      name: UIApplication.willEnterForegroundNotification,\n      object: nil\n    )\n  }\n  \n  deinit {\n    NotificationCenter.default.removeObserver(self)\n  }\n  \n  // MARK: - public\n  \n  func register(player: HybridVideoPlayer) {\n    players.add(player)\n    PluginsRegistry.shared.notifyPlayerCreated(player: player)\n  }\n  \n  func unregister(player: HybridVideoPlayer) {\n    players.remove(player)\n    PluginsRegistry.shared.notifyPlayerDestroyed(player: player)\n  }\n  \n  func register(view: VideoComponentView) {\n    videoView.add(view)\n  }\n  \n  func unregister(view: VideoComponentView) {\n    videoView.remove(view)\n  }\n  \n  func requestAudioSessionUpdate() {\n    updateAudioSessionConfiguration()\n  }\n  \n  // MARK: - Remote Control Events\n  func setRemoteControlEventsActive(_ active: Bool) {\n    if isAudioSessionManagementDisabled || remoteControlEventsActive == active {\n      return\n    }\n    \n    remoteControlEventsActive = active\n    requestAudioSessionUpdate()\n  }\n  \n  // MARK: - Audio Session Management\n  private func activateAudioSession() {\n    if isAudioSessionActive {\n      return\n    }\n    \n    do {\n      try AVAudioSession.sharedInstance().setActive(true)\n      isAudioSessionActive = true\n    } catch {\n      print(\"Failed to activate audio session: \\(error.localizedDescription)\")\n    }\n  }\n  \n  private func deactivateAudioSession() {\n    if !isAudioSessionActive {\n      return\n    }\n    \n    do {\n      try AVAudioSession.sharedInstance().setActive(\n        false, options: .notifyOthersOnDeactivation\n      )\n      isAudioSessionActive = false\n    } catch {\n      print(\"Failed to deactivate audio session: \\(error.localizedDescription)\")\n    }\n  }\n  \n  private func updateAudioSessionConfiguration() {\n    let isAnyPlayerPlaying = players.allObjects.contains { hybridPlayer in\n      hybridPlayer.player.isMuted == false && hybridPlayer.player.rate != 0\n    }\n    \n    let anyPlayerNeedsNotMixWithOthers = players.allObjects.contains { player in\n      player.mixAudioMode == .donotmix\n    }\n    \n    let anyPlayerNeedsNotificationControls = players.allObjects.contains { player in\n      player.showNotificationControls\n    }\n    \n    if isAnyPlayerPlaying || anyPlayerNeedsNotMixWithOthers || anyPlayerNeedsNotificationControls || remoteControlEventsActive {\n      activateAudioSession()\n    } else {\n      deactivateAudioSession()\n    }\n    \n    configureAudioSession()\n  }\n\n  private func configureAudioSession() {\n    let audioSession = AVAudioSession.sharedInstance()\n    var audioSessionCategoryOptions: AVAudioSession.CategoryOptions = audioSession.categoryOptions\n    \n    let anyViewNeedsPictureInPicture = videoView.allObjects.contains { view in\n      view.allowsPictureInPicturePlayback\n    }\n    \n    let anyPlayerNeedsSilentSwitchObey = players.allObjects.contains { player in\n      player.ignoreSilentSwitchMode == .obey\n    }\n    \n    let anyPlayerNeedsSilentSwitchIgnore = players.allObjects.contains { player in\n      player.ignoreSilentSwitchMode == .ignore\n    }\n\n    let anyPlayerNeedsBackgroundPlayback = players.allObjects.contains { player in\n      player.playInBackground\n    }\n    \n    let anyPlayerNeedsNotificationControls = players.allObjects.contains { player in\n      player.showNotificationControls\n    }\n    \n    if isAudioSessionManagementDisabled {\n      return\n    }\n    \n    let category: AVAudioSession.Category = determineAudioCategory(\n      silentSwitchObey: anyPlayerNeedsSilentSwitchObey,\n      silentSwitchIgnore: anyPlayerNeedsSilentSwitchIgnore,\n      earpiece: false, // TODO: Pass actual value after we add prop\n      pip: anyViewNeedsPictureInPicture,\n      backgroundPlayback: anyPlayerNeedsBackgroundPlayback,\n      notificationControls: anyPlayerNeedsNotificationControls\n    )\n    \n    let audioMixingMode = determineAudioMixingMode()\n\n  \n    audioSessionCategoryOptions.remove(.duckOthers)\n    audioSessionCategoryOptions.remove(.mixWithOthers)\n\n    switch audioMixingMode {\n    case .mixwithothers:\n      audioSessionCategoryOptions.insert(.mixWithOthers)\n    case .duckothers:\n      audioSessionCategoryOptions.insert(.duckOthers)\n    case .auto, .donotmix:\n      // Do nothing as we already cleared the options\n      break\n    }\n    \n    do {\n      try audioSession.setCategory(category, mode: .moviePlayback, options: audioSessionCategoryOptions)\n    } catch {\n      print(\"ReactNativeVideo: Failed to set audio session category: \\(error.localizedDescription)\")\n    }\n  }\n  \n  private func determineAudioCategory(\n    silentSwitchObey: Bool,\n    silentSwitchIgnore: Bool,\n    earpiece: Bool,\n    pip: Bool,\n    backgroundPlayback: Bool,\n    notificationControls: Bool\n  ) -> AVAudioSession.Category {\n    // Handle conflicting settings\n    if silentSwitchObey && silentSwitchIgnore {\n      print(\n        \"Warning: Conflicting ignoreSilentSwitch settings found (obey vs ignore) - defaulting to ignore\"\n      )\n      return .playback\n    }\n    \n    // PiP, background playback, or notification controls require playback category\n    if pip || backgroundPlayback || notificationControls || remoteControlEventsActive {\n      if silentSwitchObey {\n        print(\n          \"Warning: ignoreSilentSwitch=obey cannot be used with PiP, backgroundPlayback, or notification controls - using playback category\"\n        )\n      }\n      \n      if earpiece {\n        print(\n          \"Warning: audioOutput=earpiece cannot be used with PiP, backgroundPlayback, or notification controls - using playback category\"\n        )\n      }\n      \n      // Set up background playback policy if needed\n      if backgroundPlayback {\n        players.allObjects.forEach { player in\n          if player.playInBackground {\n            player.player.audiovisualBackgroundPlaybackPolicy = .continuesIfPossible\n          } else {\n            player.player.audiovisualBackgroundPlaybackPolicy = .pauses\n          }\n        }\n      }\n      \n      return .playback\n    }\n    \n    // Earpiece requires playAndRecord\n    if earpiece {\n      if silentSwitchObey {\n        print(\n          \"Warning: audioOutput=earpiece cannot be used with ignoreSilentSwitch=obey - using playAndRecord category\"\n        )\n      }\n      return .playAndRecord\n    }\n    \n    // Honor silent switch if requested\n    if silentSwitchObey {\n      return .ambient\n    }\n    \n    // Default to playback for most cases\n    return .playback\n  }\n  \n  func determineAudioMixingMode() -> MixAudioMode {\n    let activePlayers = players.allObjects.filter { player in\n      player.isPlaying && player.player.isMuted != true\n    }\n    \n    if activePlayers.isEmpty {\n      return .mixwithothers\n    }\n    \n    let anyPlayerNeedsMixWithOthers = activePlayers.contains { player in\n      player.mixAudioMode == .mixwithothers\n    }\n    \n    let anyPlayerNeedsNotMixWithOthers = activePlayers.contains { player in\n      player.mixAudioMode == .donotmix\n    }\n    \n    let anyPlayerNeedsDucksOthers = activePlayers.contains { player in\n      player.mixAudioMode == .duckothers\n    }\n    \n    let anyPlayerHasAutoMixAudioMode = activePlayers.contains { player in\n      player.mixAudioMode == .auto\n    }\n    \n    if anyPlayerNeedsNotMixWithOthers {\n      return .donotmix\n    }\n    \n    if anyPlayerHasAutoMixAudioMode {\n      return .auto\n    }\n    \n    if anyPlayerNeedsDucksOthers {\n      return .duckothers\n    }\n    \n    return .mixwithothers\n  }\n  \n  \n  // MARK: - Notification Handlers\n  \n  @objc\n  private func handleAudioSessionInterruption(notification: Notification) {\n    guard let userInfo = notification.userInfo,\n          let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,\n          let type = AVAudioSession.InterruptionType(rawValue: typeValue)\n    else {\n      return\n    }\n    \n    switch type {\n    case .began:\n      // Audio session interrupted, nothing to do as players will pause automatically\n      break\n      \n    case .ended:\n      // Interruption ended, check if we should resume audio session\n      if let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt {\n        let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)\n        if options.contains(.shouldResume) {\n          updateAudioSessionConfiguration()\n        }\n      }\n      \n    @unknown default:\n      break\n    }\n  }\n  \n  @objc\n  private func handleAudioRouteChange(notification: Notification) {\n    guard let userInfo = notification.userInfo,\n          let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,\n          let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue)\n    else {\n      return\n    }\n    \n    switch reason {\n    case .categoryChange, .override, .wakeFromSleep, .newDeviceAvailable, .oldDeviceUnavailable:\n      // Reconfigure audio session when route changes\n      updateAudioSessionConfiguration()\n    default:\n      break\n    }\n  }\n  \n  @objc func applicationWillResignActive(notification: Notification) {\n    // Pause all players when the app is about to become inactive\n    for player in players.allObjects {\n      if player.playInBackground || player.playWhenInactive || !player.isPlaying || player.player.isExternalPlaybackActive == true {\n        continue\n      }\n      \n      try? player.pause()\n      player.wasAutoPaused = true\n    }\n  }\n  \n  @objc func applicationDidBecomeActive(notification: Notification) {\n    // Resume all players when the app becomes active\n    for player in players.allObjects {\n      if player.wasAutoPaused {\n        try? player.play()\n        player.wasAutoPaused = false\n      }\n    }\n  }\n  \n  @objc func applicationDidEnterBackground(notification: Notification) {\n    // Pause all players when the app enters background\n    for player in players.allObjects {\n      if player.playInBackground || player.player.isExternalPlaybackActive == true || !player.isPlaying {\n        continue\n      }\n      \n      try? player.pause()\n      player.wasAutoPaused = true\n    }\n  }\n  \n  @objc func applicationWillEnterForeground(notification: Notification) {\n    // Resume all players when the app enters foreground\n    for player in players.allObjects {\n      if player.wasAutoPaused {\n        try? player.play()\n        player.wasAutoPaused = false\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/core/VideoPlayerObserver.swift",
    "content": "//\n//  VideoPlayerObserver.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 15/04/2025.\n//\n\nimport Foundation\nimport AVFoundation\n\nprotocol VideoPlayerObserverDelegate: AnyObject {\n  func onPlayedToEnd(player: AVPlayer)\n  func onPlayerItemChange(player: AVPlayer, playerItem: AVPlayerItem?)\n  func onPlayerItemWillChange(hasNewPlayerItem: Bool)\n  func onTextTrackDataChanged(texts: [NSAttributedString])\n  func onTimedMetadataChanged(timedMetadata: [AVMetadataItem])\n  func onRateChanged(rate: Float)\n  func onPlaybackBufferEmpty()\n  func onPlaybackLikelyToKeepUp()\n  func onVolumeChanged(volume: Float)\n  func onExternalPlaybackActiveChanged(isActive: Bool)\n  func onTimeControlStatusChanged(status: AVPlayer.TimeControlStatus)\n  func onPlayerStatusChanged(status: AVPlayer.Status)\n  func onPlayerItemStatusChanged(status: AVPlayerItem.Status)\n  func onBandwidthUpdate(bitrate: Double)\n  func onProgressUpdate(currentTime: Double, bufferDuration: Double)\n}\n\nextension VideoPlayerObserverDelegate {\n  func onPlayedToEnd(player: AVPlayer) {}\n  func onPlayerItemChange(player: AVPlayer, playerItem: AVPlayerItem?) {}\n  func onPlayerItemWillChange(hasNewPlayerItem: Bool) {}\n  func onTextTrackDataChanged(texts: [NSAttributedString]) {}\n  func onTimedMetadataChanged(timedMetadata: [AVMetadataItem]) {}\n  func onRateChanged(rate: Float) {}\n  func onPlaybackBufferEmpty() {}\n  func onPlaybackLikelyToKeepUp() {}\n  func onVolumeChanged(volume: Float) {}\n  func onExternalPlaybackActiveChanged(isActive: Bool) {}\n  func onTimeControlStatusChanged(status: AVPlayer.TimeControlStatus) {}\n  func onPlayerStatusChanged(status: AVPlayer.Status) {}\n  func onPlayerItemStatusChanged(status: AVPlayerItem.Status) {}\n  func onBandwidthUpdate(bitrate: Double) {}\n  func onProgressUpdate(currentTime: Double, bufferDuration: Double) {}\n}\n\nclass VideoPlayerObserver: NSObject, AVPlayerItemMetadataOutputPushDelegate, AVPlayerItemLegibleOutputPushDelegate {\n  private weak var delegate: HybridVideoPlayer?\n  var player: AVPlayer? {\n    delegate?.player\n  }\n  \n  // Player observers\n  var playerCurrentItemObserver: NSKeyValueObservation?\n  var playerRateObserver: NSKeyValueObservation?\n  var playerTimeControlStatusObserver: NSKeyValueObservation?\n  var playerExternalPlaybackActiveObserver: NSKeyValueObservation?\n  var playerVolumeObserver: NSKeyValueObservation?\n  var playerTimedMetadataObserver: NSKeyValueObservation?\n  var playerStatusObserver: NSKeyValueObservation?\n  var playerProgressPeriodicObserver: Any?\n  \n  // Player item observers\n  var playbackEndedObserver: NSObjectProtocol?\n  var playbackBufferEmptyObserver: NSKeyValueObservation?\n  var playbackLikelyToKeepUpObserver: NSKeyValueObservation?\n  var playbackBufferFullObserver: NSKeyValueObservation?\n  var playerItemStatusObserver: NSKeyValueObservation?\n  var playerItemAccessLogObserver: NSObjectProtocol?\n  \n  var metadataOutput: AVPlayerItemMetadataOutput?\n  var legibleOutput: AVPlayerItemLegibleOutput?\n  \n  init(delegate: HybridVideoPlayer) {\n    self.delegate = delegate\n  }\n  \n  deinit {\n    invalidatePlayerObservers()\n    invalidatePlayerItemObservers()\n  }\n  \n  public func updatePlayerObservers() {\n    invalidatePlayerItemObservers()\n    invalidatePlayerObservers()\n    \n    initializePlayerObservers()\n  }\n  \n  func initializePlayerObservers() {\n    guard let player else {\n      return\n    }\n    \n    playerCurrentItemObserver = player.observe(\\.currentItem, options: [.new, .old]) { [weak self] _, change in\n      self?.onPlayerCurrentItemChanged(player: player, change: change)\n    }\n    \n    playerRateObserver = player.observe(\\.rate, options: [.new]) { [weak self] _, change in\n      guard let rate = change.newValue else { return }\n      self?.delegate?.onRateChanged(rate: rate)\n    }\n    \n    playerTimeControlStatusObserver = player.observe(\\.timeControlStatus, options: [.new]) { [weak self] _, change in\n      guard let status = change.newValue else { return }\n      self?.delegate?.onTimeControlStatusChanged(status: status)\n    }\n    \n    playerExternalPlaybackActiveObserver = player.observe(\\.isExternalPlaybackActive, options: [.new]) { [weak self] _, change in\n      guard let isActive = change.newValue else { return }\n      self?.delegate?.onExternalPlaybackActiveChanged(isActive: isActive)\n    }\n    \n    playerVolumeObserver = player.observe(\\.volume, options: [.new]) { [weak self] _, change in\n      guard let volume = change.newValue else { return }\n      self?.delegate?.onVolumeChanged(volume: volume)\n    }\n    \n    playerStatusObserver = player.observe(\\.status, options: [.new]) { [weak self] _, change in\n      guard let status = change.newValue else { return }\n      self?.delegate?.onPlayerStatusChanged(status: status)\n    }\n    \n    // 500ms interval TODO: Make this configurable\n    let interval = CMTime(seconds: 0.5, preferredTimescale: 600)\n    playerProgressPeriodicObserver = player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] _ in\n      guard let self, let player = self.player, let delegate = self.delegate else { return }\n      \n      delegate.onProgressUpdate(currentTime: player.currentTime().seconds, bufferDuration: player.currentItem?.getbufferDuration() ?? 0)\n    }\n  }\n  \n  private func initializePlayerItemObservers(player: AVPlayer, playerItem: AVPlayerItem) {\n    playbackEndedObserver = NotificationCenter.default.addObserver(\n      forName: .AVPlayerItemDidPlayToEndTime,\n      object: playerItem,\n      queue: nil\n    ) { [weak self] notification in\n      self?.delegate?.onPlayedToEnd(player: player)\n    }\n    \n    playerItemAccessLogObserver = NotificationCenter.default.addObserver(\n      forName: .AVPlayerItemNewAccessLogEntry,\n      object: playerItem,\n      queue: nil\n    ) { [weak self] notification in\n      self?.onPlayerAccessLog(playerItem: playerItem)\n    }\n    \n    setupBufferObservers(for: playerItem)\n    \n    playerItemStatusObserver = playerItem.observe(\\.status, options: [.new]) { [weak self] _, change in\n      self?.delegate?.onPlayerItemStatusChanged(status: playerItem.status)\n    }\n    \n    let metadataOutput = AVPlayerItemMetadataOutput()\n    playerItem.add(metadataOutput)\n    metadataOutput.setDelegate(self, queue: .global(qos: .userInteractive))\n    \n    let legibleOutput = AVPlayerItemLegibleOutput()\n    playerItem.add(legibleOutput)\n    metadataOutput.setDelegate(self, queue: .global(qos: .userInteractive))\n  }\n  \n  func invalidatePlayerItemObservers() {\n    // Remove NotificationCenter observers\n    if let playbackEndedObserver = playbackEndedObserver {\n      NotificationCenter.default.removeObserver(playbackEndedObserver)\n      self.playbackEndedObserver = nil\n    }\n    if let playerItemAccessLogObserver = playerItemAccessLogObserver {\n      NotificationCenter.default.removeObserver(playerItemAccessLogObserver)\n      self.playerItemAccessLogObserver = nil\n    }\n    // Invalidate KVO observers\n    clearBufferObservers()\n    playerItemStatusObserver?.invalidate()\n    playerItemStatusObserver = nil\n    // Remove outputs if needed\n    // (Assumes outputs are not shared between items)\n    if let playerItem = player?.currentItem {\n      if let metadataOutput = metadataOutput {\n        playerItem.remove(metadataOutput)\n      }\n      if let legibleOutput = legibleOutput {\n        playerItem.remove(legibleOutput)\n      }\n    }\n    metadataOutput = nil\n    legibleOutput = nil\n  }\n  \n  func invalidatePlayerObservers() {\n    // Invalidate KVO observers\n    playerCurrentItemObserver?.invalidate()\n    playerCurrentItemObserver = nil\n    playerRateObserver?.invalidate()\n    playerRateObserver = nil\n    playerTimeControlStatusObserver?.invalidate()\n    playerTimeControlStatusObserver = nil\n    playerExternalPlaybackActiveObserver?.invalidate()\n    playerExternalPlaybackActiveObserver = nil\n    playerVolumeObserver?.invalidate()\n    playerVolumeObserver = nil\n    playerStatusObserver?.invalidate()\n    playerStatusObserver = nil\n    // Remove periodic time observer from player\n    if let player = player, let periodicObserver = playerProgressPeriodicObserver {\n      player.removeTimeObserver(periodicObserver)\n      playerProgressPeriodicObserver = nil\n    }\n  }\n  \n  // MARK: - AVPlayerItemLegibleOutputPushDelegate\n  public func legibleOutput(_: AVPlayerItemLegibleOutput,\n                     didOutputAttributedStrings strings: [NSAttributedString],\n                     nativeSampleBuffers _: [Any],\n                     forItemTime _: CMTime) {\n    delegate?.onTextTrackDataChanged(texts: strings)\n  }\n  \n  // MARK: - AVPlayerItemMetadataOutputPushDelegate\n  public func metadataOutput(_: AVPlayerItemMetadataOutput, didOutputTimedMetadataGroups groups: [AVTimedMetadataGroup], from _: AVPlayerItemTrack?) {\n    for metadataGroup in groups {\n      delegate?.onTimedMetadataChanged(timedMetadata: metadataGroup.items)\n    }\n  }\n  \n  // MARK: - AVPlayer Observers\n  func onPlayerCurrentItemChanged(player: AVPlayer, change: NSKeyValueObservedChange<AVPlayerItem?>) {\n    let newPlayerItem = change.newValue?.flatMap { $0 }\n    \n    // Remove observers for old player item\n    invalidatePlayerItemObservers()\n    \n    // Notify delegate about player item state change\n    delegate?.onPlayerItemWillChange(hasNewPlayerItem: newPlayerItem != nil)\n    \n    if let playerItem = newPlayerItem {\n      // Initialize observers for new player item\n      initializePlayerItemObservers(player: player, playerItem: playerItem)\n      \n      delegate?.onPlayerItemChange(player: player, playerItem: playerItem)\n    }\n  }\n  \n  // MARK: - AVPlayerItem Observers\n  func onPlayerAccessLog(playerItem: AVPlayerItem) {\n    guard let accessLog = playerItem.accessLog() else { return }\n    guard let lastEvent = accessLog.events.last else { return }\n    \n    delegate?.onBandwidthUpdate(bitrate: lastEvent.indicatedBitrate)\n  }\n  \n  // MARK: - Buffer State Management\n  \n  func setupBufferObservers(for playerItem: AVPlayerItem) {\n    clearBufferObservers()\n    \n    // Observe buffer empty - this indicates definite buffering\n    playbackBufferEmptyObserver = playerItem.observe(\\.isPlaybackBufferEmpty, options: [.new, .initial]) { [weak self] playerItem, change in\n      let isEmpty = change.newValue ?? playerItem.isPlaybackBufferEmpty\n      if isEmpty {\n        self?.delegate?.onPlaybackBufferEmpty()\n      }\n    }\n    \n    // Observe likely to keep up - this indicates that buffering has finished\n    playbackLikelyToKeepUpObserver = playerItem.observe(\\.isPlaybackLikelyToKeepUp, options: [.new, .initial]) { [weak self] playerItem, change in\n      let isLikelyToKeepUp = change.newValue ?? playerItem.isPlaybackLikelyToKeepUp\n      if isLikelyToKeepUp {\n        self?.delegate?.onPlaybackLikelyToKeepUp()\n      }\n    }\n    \n    // Observe buffer full as an additional signal\n    playbackBufferFullObserver = playerItem.observe(\\.isPlaybackBufferFull, options: [.new, .initial]) { [weak self] playerItem, change in\n      let isFull = change.newValue ?? playerItem.isPlaybackBufferFull\n      if isFull {\n        self?.delegate?.onPlaybackLikelyToKeepUp()\n      }\n    }\n  }\n  \n  func clearBufferObservers() {\n    playbackBufferEmptyObserver?.invalidate()\n    playbackBufferFullObserver?.invalidate()\n    playbackLikelyToKeepUpObserver?.invalidate()\n    \n    playbackBufferEmptyObserver = nil\n    playbackBufferFullObserver = nil\n    playbackLikelyToKeepUpObserver = nil\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoPlayer/HybridVideoPlayer+Events.swift",
    "content": "//\n//  HybridVideoPlayer+Events.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 02/05/2025.\n//\n\nimport AVFoundation\nimport Foundation\n\nextension HybridVideoPlayer: VideoPlayerObserverDelegate {\n  // MARK: - VideoPlayerObserverDelegate\n\n  func onPlayedToEnd(player: AVPlayer) {\n    _eventEmitter?.onEnd()\n\n    if loop {\n      currentTime = 0\n      try? play()\n    }\n  }\n\n  func onRateChanged(rate: Float) {\n    _eventEmitter?.onPlaybackRateChange(Double(rate))\n    NowPlayingInfoCenterManager.shared.updatePlaybackState()\n    updateAndEmitPlaybackState()\n  }\n\n  func onVolumeChanged(volume: Float) {\n    _eventEmitter?.onVolumeChange(\n      onVolumeChangeData(\n        volume: Double(volume),\n        muted: muted\n      )\n    )\n  }\n\n  func onPlaybackBufferEmpty() {\n    isCurrentlyBuffering = true\n    status = .loading\n    updateAndEmitPlaybackState()\n  }\n\n  func onProgressUpdate(currentTime: Double, bufferDuration: Double) {\n    _eventEmitter?.onProgress(\n      .init(currentTime: currentTime, bufferDuration: bufferDuration)\n    )\n  }\n\n  func onPlaybackLikelyToKeepUp() {\n    isCurrentlyBuffering = false\n    if player.timeControlStatus != .waitingToPlayAtSpecifiedRate {\n      status = .readytoplay\n    }\n    updateAndEmitPlaybackState()\n  }\n\n  func onExternalPlaybackActiveChanged(isActive: Bool) {\n    _eventEmitter?.onExternalPlaybackChange(isActive)\n  }\n\n  func onTimeControlStatusChanged(status: AVPlayer.TimeControlStatus) {\n    if player.status == .failed || playerItem?.status == .failed {\n      self.status = .error\n      isCurrentlyBuffering = false\n      _eventEmitter?.onPlaybackStateChange(\n        .init(isPlaying: false, isBuffering: false)\n      )\n      return\n    }\n\n    switch status {\n    case .waitingToPlayAtSpecifiedRate:\n      isCurrentlyBuffering = true\n      self.status = .loading\n      break\n\n    case .playing:\n      isCurrentlyBuffering = false\n      self.status = .readytoplay\n      break\n\n    case .paused:\n      isCurrentlyBuffering = false\n      self.status = .readytoplay\n      break\n\n    @unknown default:\n      break\n    }\n\n    updateAndEmitPlaybackState()\n  }\n\n  func onPlayerStatusChanged(status: AVPlayer.Status) {\n    if status == .failed || playerItem?.status == .failed {\n      self.status = .error\n      isCurrentlyBuffering = false\n      updateAndEmitPlaybackState()\n    }\n  }\n\n  func onPlayerItemStatusChanged(status: AVPlayerItem.Status) {\n    if status == .failed {\n      self.status = .error\n      isCurrentlyBuffering = false\n      updateAndEmitPlaybackState()\n      return\n    }\n\n    switch status {\n    case .unknown:\n      isCurrentlyBuffering = true\n      self.status = .loading\n\n      // Set initial buffering state when we have a playerItem\n      if let playerItem = self.playerItem {\n        if playerItem.isPlaybackBufferEmpty {\n          isCurrentlyBuffering = true\n        }\n      }\n\n    case .readyToPlay:\n      guard let playerItem else { return }\n\n      let height = playerItem.presentationSize.height\n      let width = playerItem.presentationSize.width\n      let orientation: VideoOrientation =\n        playerItem.asset.tracks.first(where: { $0.mediaType == .video })?\n        .orientation ?? .unknown\n\n      _eventEmitter?.onLoad(\n        .init(currentTime, duration, height, width, orientation)\n      )\n\n      if playerItem.isPlaybackLikelyToKeepUp\n        && !playerItem.isPlaybackBufferEmpty\n      {\n        isCurrentlyBuffering = false\n        self.status = .readytoplay\n      }\n\n    case .failed:\n      self.status = .error\n      isCurrentlyBuffering = false\n\n    @unknown default:\n      break\n    }\n\n    updateAndEmitPlaybackState()\n  }\n\n  func onTextTrackDataChanged(texts: [NSAttributedString]) {\n    _eventEmitter?.onTextTrackDataChanged(texts.map { $0.string })\n  }\n\n  func onTimedMetadataChanged(timedMetadata: [AVMetadataItem]) {\n    var metadata: [TimedMetadataObject] = []\n    for item in timedMetadata {\n      let value = item.value as? String\n      let identifier = item.identifier?.rawValue\n\n      if let value, let identifier {\n        metadata.append(.init(value: value, identifier: identifier))\n      }\n    }\n\n    _eventEmitter?.onTimedMetadata(.init(metadata: metadata))\n  }\n\n  func onBandwidthUpdate(bitrate: Double) {\n    _eventEmitter?.onBandwidthUpdate(\n      .init(bitrate: bitrate, width: nil, height: nil)\n    )\n  }\n\n  func onPlayerItemChange(player _: AVPlayer, playerItem: AVPlayerItem?) {\n    guard showNotificationControls, let playerItem else { return }\n    DispatchQueue.main.async {\n      NowPlayingInfoCenterManager.shared.updateStaticInfo(ifCurrentItem: playerItem)\n    }\n  }\n\n  func onPlayerItemWillChange(hasNewPlayerItem: Bool) {\n    if hasNewPlayerItem {\n      // Set initial buffering state when playerItem is assigned\n      isCurrentlyBuffering = true\n      status = .loading\n      updateAndEmitPlaybackState()\n    } else {\n      // Clean up state when playerItem is cleared\n      isCurrentlyBuffering = false\n    }\n  }\n\n  func updateAndEmitPlaybackState() {\n    let isPlaying = player.rate > 0 && !isCurrentlyBuffering\n\n    _eventEmitter?.onPlaybackStateChange(\n      .init(isPlaying: isPlaying, isBuffering: isCurrentlyBuffering)\n    )\n    _eventEmitter?.onBuffer(isCurrentlyBuffering)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoPlayer/HybridVideoPlayer.swift",
    "content": "//\n//  HybridVideoPlayer.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 09/10/2024.\n//\n\nimport AVFoundation\nimport Foundation\nimport NitroModules\n\nclass HybridVideoPlayer: HybridVideoPlayerSpec, NativeVideoPlayerSpec {\n\n  /**\n   * Player instance for video playback\n   */\n  var player: AVPlayer {\n    didSet {\n      playerObserver?.initializePlayerObservers()\n    }\n    willSet {\n      playerObserver?.invalidatePlayerObservers()\n    }\n  }\n\n  var playerItem: AVPlayerItem? {\n    didSet {\n      if let bufferConfig = source.config.bufferConfig {\n        playerItem?.setBufferConfig(config: bufferConfig)\n      }\n    }\n  }\n  var playerObserver: VideoPlayerObserver?\n  private let sourceLoader = SourceLoader()\n\n  init(source: (any HybridVideoPlayerSourceSpec)) throws {\n    self.source = source\n    self.eventEmitter = HybridVideoPlayerEventEmitter()\n\n    // Initialize AVPlayer with empty item\n    self.player = AVPlayer()\n\n    super.init()\n    self.playerObserver = VideoPlayerObserver(delegate: self)\n    self.playerObserver?.initializePlayerObservers()\n\n    Task {\n      if source.config.initializeOnCreation == true {\n        do {\n          self.playerItem = try await self.sourceLoader.load {\n            try await self.initializePlayerItem()\n          }\n          self.player.replaceCurrentItem(with: self.playerItem)\n        } catch {\n          // Ignore cancellation errors during initialization\n        }\n      }\n    }\n\n    VideoManager.shared.register(player: self)\n  }\n\n  deinit {\n    release()\n  }\n\n  // MARK: - Hybrid Impl\n\n  var source: any HybridVideoPlayerSourceSpec\n\n  var status: VideoPlayerStatus = .idle {\n    didSet {\n      if status != oldValue {\n        _eventEmitter?.onStatusChange(status)\n      }\n    }\n  }\n\n  var eventEmitter: HybridVideoPlayerEventEmitterSpec\n  var _eventEmitter: HybridVideoPlayerEventEmitter? {\n    return eventEmitter as? HybridVideoPlayerEventEmitter\n  }\n\n  var volume: Double {\n    set {\n      player.volume = Float(newValue)\n    }\n    get {\n      return Double(player.volume)\n    }\n  }\n\n  var muted: Bool {\n    set {\n      player.isMuted = newValue\n      _eventEmitter?.onVolumeChange(\n        onVolumeChangeData(\n          volume: Double(player.volume),\n          muted: muted\n        )\n      )\n    }\n    get {\n      return player.isMuted\n    }\n  }\n\n  var currentTime: Double {\n    set {\n      _eventEmitter?.onSeek(newValue)\n      player.seek(\n        to: CMTime(seconds: newValue, preferredTimescale: 1000),\n        toleranceBefore: .zero,\n        toleranceAfter: .zero\n      )\n    }\n    get {\n      player.currentTime().seconds\n    }\n  }\n\n  var duration: Double {\n    Double(player.currentItem?.duration.seconds ?? Double.nan)\n  }\n\n  var rate: Double {\n    set {\n      if #available(iOS 16.0, tvOS 16.0, *) {\n        player.defaultRate = Float(newValue)\n      }\n\n      player.rate = Float(newValue)\n    }\n    get {\n      return Double(player.rate)\n    }\n  }\n\n  var loop: Bool = false\n\n  var mixAudioMode: MixAudioMode = .auto {\n    didSet {\n      VideoManager.shared.requestAudioSessionUpdate()\n    }\n  }\n\n  var ignoreSilentSwitchMode: IgnoreSilentSwitchMode = .auto {\n    didSet {\n      VideoManager.shared.requestAudioSessionUpdate()\n    }\n  }\n\n  var playInBackground: Bool = false {\n    didSet {\n      VideoManager.shared.requestAudioSessionUpdate()\n    }\n  }\n\n  var playWhenInactive: Bool = false\n\n  var wasAutoPaused: Bool = false\n\n  // Text track selection state\n  private var selectedExternalTrackIndex: Int? = nil\n\n  var isCurrentlyBuffering: Bool = false\n\n  var isPlaying: Bool {\n    return player.rate != 0\n  }\n\n  var showNotificationControls: Bool = false {\n    didSet {\n      if showNotificationControls {\n        NowPlayingInfoCenterManager.shared.registerPlayer(player: player)\n      } else {\n        NowPlayingInfoCenterManager.shared.removePlayer(player: player)\n      }\n    }\n  }\n\n  func initialize() throws -> Promise<Void> {\n    return Promise.async { [weak self] in\n      guard let self else {\n        throw LibraryError.deallocated(objectName: \"HybridVideoPlayer\").error()\n      }\n\n      if self.playerItem != nil {\n        return\n      }\n\n      do {\n        self.playerItem = try await self.sourceLoader.load {\n          try await self.initializePlayerItem()\n        }\n        self.player.replaceCurrentItem(with: self.playerItem)\n      } catch {\n        if error is CancellationError {\n          throw PlayerError.cancelled.error()\n        }\n        throw error\n      }\n    }\n  }\n\n  func release() {\n    sourceLoader.cancelSync()\n    NowPlayingInfoCenterManager.shared.removePlayer(player: player)\n\n    try? _eventEmitter?.clearAllListeners()\n\n    self.playerItem = nil\n\n    if let source = self.source as? HybridVideoPlayerSource {\n      source.releaseAsset()\n    }\n\n    // Clear player observer\n    playerObserver?.invalidatePlayerItemObservers()\n    playerObserver?.invalidatePlayerObservers()\n    self.playerObserver = nil\n\n    self.player.replaceCurrentItem(with: nil)\n    status = .idle\n\n    VideoManager.shared.unregister(player: self)\n  }\n\n  func preload() throws -> NitroModules.Promise<Void> {\n    let promise = Promise<Void>()\n\n    if status != .idle {\n      promise.resolve(withResult: ())\n      return promise\n    }\n\n    Task.detached(priority: .userInitiated) { [weak self] in\n      guard let self else {\n        promise.reject(\n          withError: LibraryError.deallocated(objectName: \"HybridVideoPlayer\")\n            .error()\n        )\n        return\n      }\n\n      do {\n        let playerItem = try await self.sourceLoader.load {\n          try await self.initializePlayerItem()\n        }\n        self.playerItem = playerItem\n\n        self.player.replaceCurrentItem(with: playerItem)\n        promise.resolve(withResult: ())\n      } catch {\n        if error is CancellationError {\n          promise.reject(withError: PlayerError.cancelled.error())\n        } else {\n          promise.reject(withError: error)\n        }\n      }\n    }\n\n    return promise\n  }\n\n  func play() throws {\n    player.play()\n  }\n\n  func pause() throws {\n    player.pause()\n  }\n\n  func seekBy(time: Double) throws {\n    guard let currentItem = player.currentItem else {\n      throw PlayerError.notInitialized.error()\n    }\n\n    let currentItemTime = currentItem.currentTime()\n\n    // Duration is NaN for live streams\n    let fixedDurration = duration.isNaN ? Double.infinity : duration\n\n    // Clap by <0, duration>\n    let newTime = max(0, min(currentItemTime.seconds + time, fixedDurration))\n\n    currentTime = newTime\n  }\n\n  func seekTo(time: Double) {\n    currentTime = time\n  }\n\n  func replaceSourceAsync(\n    source: Variant_NullType__any_HybridVideoPlayerSourceSpec_?\n  ) throws\n    -> Promise<Void>\n  {\n    let promise = Promise<Void>()\n\n    /**\n     @frozen\n     public indirect enum Variant_NullType__any_HybridVideoPlayerSourceSpec_ {\n       case first(NullType)\n       case second((any HybridVideoPlayerSourceSpec))\n     }\n     */\n\n    // if source is nil, release player\n    // if source is not NullType, set source\n    guard let source else {\n      release()\n      promise.resolve(withResult: ())\n      return promise\n    }\n\n    switch source {\n    case .first(_):\n      release()\n      promise.resolve(withResult: ())\n      return promise\n    case .second(let newSource):\n      Task.detached(priority: .userInitiated) { [weak self] in\n        guard let self else {\n          promise.reject(\n            withError: LibraryError.deallocated(objectName: \"HybridVideoPlayer\")\n              .error()\n          )\n          return\n        }\n\n        await self.sourceLoader.cancel()\n\n        if let oldSource = self.source as? HybridVideoPlayerSource {\n          oldSource.releaseAsset()\n        }\n\n        self.source = newSource\n\n        do {\n          self.playerItem = try await self.sourceLoader.load {\n            try await self.initializePlayerItem()\n          }\n          self.player.replaceCurrentItem(with: self.playerItem)\n          promise.resolve(withResult: ())\n        } catch {\n          if error is CancellationError {\n            promise.reject(withError: PlayerError.cancelled.error())\n          } else {\n            promise.reject(withError: error)\n          }\n        }\n      }\n    }\n\n    return promise\n  }\n\n  // MARK: - Methods\n\n  func initializePlayerItem() async throws -> AVPlayerItem {\n    // Ensure the source is a valid HybridVideoPlayerSource\n    guard let _hybridSource = source as? HybridVideoPlayerSource else {\n      status = .error\n      throw PlayerError.invalidSource.error()\n    }\n\n    // (maybe) Override source with plugins\n    let _source = await PluginsRegistry.shared.overrideSource(\n      source: _hybridSource\n    )\n\n    let isNetworkSource = _source.url.isFileURL == false\n    _eventEmitter?.onLoadStart(\n      .init(sourceType: isNetworkSource ? .network : .local, source: _source)\n    )\n\n    let asset = try await _source.getAsset()\n\n    let playerItem: AVPlayerItem\n\n    if let externalSubtitles = source.config.externalSubtitles,\n      externalSubtitles.isEmpty == false\n    {\n      playerItem = try await AVPlayerItem.withExternalSubtitles(\n        for: asset,\n        config: source.config\n      )\n    } else {\n      playerItem = AVPlayerItem(asset: asset)\n    }\n\n    if let metadata = source.config.metadata {\n      let title = metadata.title\n      let artist = metadata.artist\n      let imageUri = metadata.imageUri\n\n      DispatchQueue.main.async { [weak playerItem] in\n        guard let playerItem else { return }\n        var items: [AVMetadataItem] = []\n\n        if let title {\n          items.append(.make(identifier: .commonIdentifierTitle, value: title as NSString))\n        }\n        if let artist {\n          items.append(.make(identifier: .commonIdentifierArtist, value: artist as NSString))\n        }\n        if !items.isEmpty {\n          playerItem.externalMetadata = items\n          NowPlayingInfoCenterManager.shared.updateStaticInfo(ifCurrentItem: playerItem)\n        }\n      }\n\n      // Load artwork in background to not block player initialization\n      if let imageUri, let imageUrl = URL(string: imageUri) {\n        Task { [weak playerItem] in\n          guard let (data, _) = try? await URLSession.shared.data(from: imageUrl) else {\n            print(\"[RNV] Failed to load artwork from: \\(imageUrl)\")\n            return\n          }\n          DispatchQueue.main.async {\n            guard let playerItem else { return }\n            playerItem.externalMetadata = playerItem.externalMetadata + [.make(identifier: .commonIdentifierArtwork, value: data as NSData)]\n            NowPlayingInfoCenterManager.shared.updateStaticInfo(ifCurrentItem: playerItem)\n          }\n        }\n      } else if let imageUri {\n        print(\"[RNV] Invalid imageUri for artwork: \\(imageUri)\")\n      }\n    }\n\n    return playerItem\n  }\n\n  // MARK: - Text Track Management\n\n  func getAvailableTextTracks() throws -> [TextTrack] {\n    guard let currentItem = player.currentItem else {\n      return []\n    }\n\n    var tracks: [TextTrack] = []\n\n    if let mediaSelection = currentItem.asset.mediaSelectionGroup(\n      forMediaCharacteristic: .legible\n    ) {\n      for (index, option) in mediaSelection.options.enumerated() {\n        let isSelected =\n          currentItem.currentMediaSelection.selectedMediaOption(\n            in: mediaSelection\n          ) == option\n\n        let name =\n          option.commonMetadata.first(where: { $0.commonKey == .commonKeyTitle }\n          )?.stringValue\n          ?? option.displayName\n\n        let isExternal =\n          source.config.externalSubtitles?.contains { subtitle in\n            name.contains(subtitle.label)\n          } ?? false\n\n        let trackId =\n          isExternal\n          ? \"external-\\(index)\"\n          : \"builtin-\\(option.displayName)-\\(option.locale?.identifier ?? \"unknown\")\"\n\n        tracks.append(\n          TextTrack(\n            id: trackId,\n            label: option.displayName,\n            language: option.locale?.identifier,\n            selected: isSelected\n          )\n        )\n      }\n    }\n\n    return tracks\n  }\n\n  func selectTextTrack(textTrack: Variant_NullType_TextTrack?) throws {\n    guard let currentItem = player.currentItem else {\n      throw PlayerError.notInitialized.error()\n    }\n\n    guard\n      let mediaSelection = currentItem.asset.mediaSelectionGroup(\n        forMediaCharacteristic: .legible\n      )\n    else {\n      return\n    }\n\n    // If textTrack is nil, deselect any selected track\n    guard let textTrack = textTrack else {\n      currentItem.select(nil, in: mediaSelection)\n      selectedExternalTrackIndex = nil\n      _eventEmitter?.onTrackChange(nil)\n      return\n    }\n\n    switch textTrack {\n    case .first(_):\n      currentItem.select(nil, in: mediaSelection)\n      selectedExternalTrackIndex = nil\n      _eventEmitter?.onTrackChange(nil)\n      return\n    case .second(let textTrack):\n      // If textTrack id is empty, deselect any selected track\n      if textTrack.id.isEmpty {\n        currentItem.select(nil, in: mediaSelection)\n        selectedExternalTrackIndex = nil\n        _eventEmitter?.onTrackChange(nil)\n        return\n      }\n\n      if textTrack.id.hasPrefix(\"external-\") {\n        let trackIndexStr = String(textTrack.id.dropFirst(\"external-\".count))\n        if let trackIndex = Int(trackIndexStr),\n          trackIndex < mediaSelection.options.count\n        {\n          let option = mediaSelection.options[trackIndex]\n          currentItem.select(option, in: mediaSelection)\n          selectedExternalTrackIndex = trackIndex\n          _eventEmitter?.onTrackChange(.second(textTrack))\n        }\n      } else if textTrack.id.hasPrefix(\"builtin-\") {\n        for option in mediaSelection.options {\n          let optionId =\n            \"builtin-\\(option.displayName)-\\(option.locale?.identifier ?? \"unknown\")\"\n          if optionId == textTrack.id {\n            currentItem.select(option, in: mediaSelection)\n            selectedExternalTrackIndex = nil\n            _eventEmitter?.onTrackChange(.second(textTrack))\n            return\n          }\n        }\n      }\n    }\n  }\n\n  var selectedTrack: TextTrack? {\n    guard let currentItem = player.currentItem else {\n      return nil\n    }\n\n    guard\n      let mediaSelection = currentItem.asset.mediaSelectionGroup(\n        forMediaCharacteristic: .legible\n      )\n    else {\n      return nil\n    }\n\n    guard\n      let selectedOption = currentItem.currentMediaSelection\n        .selectedMediaOption(in: mediaSelection)\n    else {\n      return nil\n    }\n\n    guard let index = mediaSelection.options.firstIndex(of: selectedOption)\n    else {\n      return nil\n    }\n\n    let isExternal =\n      source.config.externalSubtitles?.contains { subtitle in\n        selectedOption.displayName.contains(subtitle.label)\n      } ?? false\n\n    let trackId =\n      isExternal\n      ? \"external-\\(index)\"\n      : \"builtin-\\(selectedOption.displayName)-\\(selectedOption.locale?.identifier ?? \"unknown\")\"\n\n    return TextTrack(\n      id: trackId,\n      label: selectedOption.displayName,\n      language: selectedOption.locale?.identifier,\n      selected: true\n    )\n  }\n\n  // MARK: - Memory Management\n\n  func dispose() {\n    release()\n  }\n\n  var memorySize: Int {\n    var size = 0\n\n    size += playerItem?.asset.estimatedMemoryUsage ?? 0\n\n    return size\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoPlayer/HybridVideoPlayerFactory.swift",
    "content": "//\n//  HybridVideoPlayerFactory.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 09/10/2024.\n//\n\nimport Foundation\nimport NitroModules\n\nclass HybridVideoPlayerFactory: HybridVideoPlayerFactorySpec {\n  func createPlayer(source: HybridVideoPlayerSourceSpec) throws -> HybridVideoPlayerSpec {\n    return try HybridVideoPlayer(source: source)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoPlayerEmitter/HybridVideoPlayerEventEmitter.swift",
    "content": "//\n//  HybridVideoPlayerEventEmitter.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 02/05/2025.\n//\n\nimport Foundation\nimport NitroModules\n\nstruct ListenerPair {\n  let id: UUID\n  let eventName: String\n  let callback: Any\n}\n\nclass HybridVideoPlayerEventEmitter: HybridVideoPlayerEventEmitterSpec {\n  var listeners: [ListenerPair] = []\n\n  // MARK: - Private helpers\n\n  private func addListener<T>(eventName: String, listener: T) -> ListenerSubscription {\n    let id = UUID()\n    listeners.append(ListenerPair(id: id, eventName: eventName, callback: listener))\n    return ListenerSubscription(remove: { [weak self] in\n      self?.listeners.removeAll { $0.id == id }\n    })\n  }\n\n  private func emitEvent<T>(eventName: String, invoke: (T) throws -> Void) {\n    for pair in listeners where pair.eventName == eventName {\n      if let callback = pair.callback as? T {\n        do {\n          try invoke(callback)\n        } catch {\n          print(\"[ReactNativeVideo] Error calling \\(eventName) listener: \\(error)\")\n        }\n      } else {\n        print(\"[ReactNativeVideo] Invalid callback type for \\(eventName)\")\n      }\n    }\n  }\n\n  // MARK: - Listener registration methods\n\n  func addOnAudioBecomingNoisyListener(listener: @escaping () -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onAudioBecomingNoisy\", listener: listener)\n  }\n\n  func addOnAudioFocusChangeListener(listener: @escaping (Bool) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onAudioFocusChange\", listener: listener)\n  }\n\n  func addOnBandwidthUpdateListener(listener: @escaping (BandwidthData) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onBandwidthUpdate\", listener: listener)\n  }\n\n  func addOnBufferListener(listener: @escaping (Bool) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onBuffer\", listener: listener)\n  }\n\n  func addOnControlsVisibleChangeListener(listener: @escaping (Bool) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onControlsVisibleChange\", listener: listener)\n  }\n\n  func addOnEndListener(listener: @escaping () -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onEnd\", listener: listener)\n  }\n\n  func addOnExternalPlaybackChangeListener(listener: @escaping (Bool) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onExternalPlaybackChange\", listener: listener)\n  }\n\n  func addOnLoadListener(listener: @escaping (onLoadData) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onLoad\", listener: listener)\n  }\n\n  func addOnLoadStartListener(listener: @escaping (onLoadStartData) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onLoadStart\", listener: listener)\n  }\n\n  func addOnPlaybackStateChangeListener(listener: @escaping (onPlaybackStateChangeData) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onPlaybackStateChange\", listener: listener)\n  }\n\n  func addOnPlaybackRateChangeListener(listener: @escaping (Double) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onPlaybackRateChange\", listener: listener)\n  }\n\n  func addOnProgressListener(listener: @escaping (onProgressData) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onProgress\", listener: listener)\n  }\n\n  func addOnReadyToDisplayListener(listener: @escaping () -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onReadyToDisplay\", listener: listener)\n  }\n\n  func addOnSeekListener(listener: @escaping (Double) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onSeek\", listener: listener)\n  }\n\n  func addOnStatusChangeListener(listener: @escaping (VideoPlayerStatus) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onStatusChange\", listener: listener)\n  }\n\n  func addOnTimedMetadataListener(listener: @escaping (TimedMetadata) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onTimedMetadata\", listener: listener)\n  }\n\n  func addOnTextTrackDataChangedListener(listener: @escaping ([String]) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onTextTrackDataChanged\", listener: listener)\n  }\n\n  func addOnTrackChangeListener(listener: @escaping (Variant_NullType_TextTrack?) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onTrackChange\", listener: listener)\n  }\n\n  func addOnVolumeChangeListener(listener: @escaping (onVolumeChangeData) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onVolumeChange\", listener: listener)\n  }\n\n  func clearAllListeners() throws {\n    listeners.removeAll()\n  }\n\n  // MARK: - Event emission methods\n\n  func onAudioBecomingNoisy() {\n    emitEvent(eventName: \"onAudioBecomingNoisy\") { (callback: () throws -> Void) in try callback() }\n  }\n\n  func onAudioFocusChange(_ hasFocus: Bool) {\n    emitEvent(eventName: \"onAudioFocusChange\") { (callback: (Bool) throws -> Void) in try callback(hasFocus) }\n  }\n\n  func onBandwidthUpdate(_ data: BandwidthData) {\n    emitEvent(eventName: \"onBandwidthUpdate\") { (callback: (BandwidthData) throws -> Void) in try callback(data) }\n  }\n\n  func onBuffer(_ isBuffering: Bool) {\n    emitEvent(eventName: \"onBuffer\") { (callback: (Bool) throws -> Void) in try callback(isBuffering) }\n  }\n\n  func onControlsVisibleChange(_ isVisible: Bool) {\n    emitEvent(eventName: \"onControlsVisibleChange\") { (callback: (Bool) throws -> Void) in try callback(isVisible) }\n  }\n\n  func onEnd() {\n    emitEvent(eventName: \"onEnd\") { (callback: () throws -> Void) in try callback() }\n  }\n\n  func onExternalPlaybackChange(_ isExternalPlaybackActive: Bool) {\n    emitEvent(eventName: \"onExternalPlaybackChange\") { (callback: (Bool) throws -> Void) in try callback(isExternalPlaybackActive) }\n  }\n\n  func onLoad(_ data: onLoadData) {\n    emitEvent(eventName: \"onLoad\") { (callback: (onLoadData) throws -> Void) in try callback(data) }\n  }\n\n  func onLoadStart(_ data: onLoadStartData) {\n    emitEvent(eventName: \"onLoadStart\") { (callback: (onLoadStartData) throws -> Void) in try callback(data) }\n  }\n\n  func onPlaybackStateChange(_ data: onPlaybackStateChangeData) {\n    emitEvent(eventName: \"onPlaybackStateChange\") { (callback: (onPlaybackStateChangeData) throws -> Void) in try callback(data) }\n  }\n\n  func onPlaybackRateChange(_ rate: Double) {\n    emitEvent(eventName: \"onPlaybackRateChange\") { (callback: (Double) throws -> Void) in try callback(rate) }\n  }\n\n  func onProgress(_ data: onProgressData) {\n    emitEvent(eventName: \"onProgress\") { (callback: (onProgressData) throws -> Void) in try callback(data) }\n  }\n\n  func onReadyToDisplay() {\n    emitEvent(eventName: \"onReadyToDisplay\") { (callback: () throws -> Void) in try callback() }\n  }\n\n  func onSeek(_ position: Double) {\n    emitEvent(eventName: \"onSeek\") { (callback: (Double) throws -> Void) in try callback(position) }\n  }\n\n  func onStatusChange(_ status: VideoPlayerStatus) {\n    emitEvent(eventName: \"onStatusChange\") { (callback: (VideoPlayerStatus) throws -> Void) in try callback(status) }\n  }\n\n  func onTimedMetadata(_ metadata: TimedMetadata) {\n    emitEvent(eventName: \"onTimedMetadata\") { (callback: (TimedMetadata) throws -> Void) in try callback(metadata) }\n  }\n\n  func onTextTrackDataChanged(_ tracks: [String]) {\n    emitEvent(eventName: \"onTextTrackDataChanged\") { (callback: ([String]) throws -> Void) in try callback(tracks) }\n  }\n\n  func onTrackChange(_ track: Variant_NullType_TextTrack?) {\n    emitEvent(eventName: \"onTrackChange\") { (callback: (Variant_NullType_TextTrack?) throws -> Void) in try callback(track) }\n  }\n\n  func onVolumeChange(_ data: onVolumeChangeData) {\n    emitEvent(eventName: \"onVolumeChange\") { (callback: (onVolumeChangeData) throws -> Void) in try callback(data) }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoPlayerSource/HybridVideoPlayerSource.swift",
    "content": "//\n//  HybridVideoPlayerSource.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 23/09/2024.\n//\n\nimport AVFoundation\nimport Foundation\nimport NitroModules\n\nclass HybridVideoPlayerSource: HybridVideoPlayerSourceSpec, NativeVideoPlayerSourceSpec {\n  var asset: AVURLAsset?\n  var uri: String\n  var config: NativeVideoConfig\n\n  var drmManager: DRMManagerSpec?\n\n  let url: URL\n  private let sourceLoader = SourceLoader()\n\n  init(config: NativeVideoConfig) throws {\n    self.uri = config.uri\n    self.config = config\n\n    guard let url = URL(string: uri) else {\n      throw SourceError.invalidUri(uri: uri).error()\n    }\n\n    self.url = url\n\n    super.init()\n\n    if config.drm != nil {\n      // Try to get the DRM manager\n      // If no DRM manager is found, it will throw an error\n      _ = try PluginsRegistry.shared.getDrmManager(source: self)\n    }\n  }\n\n  deinit {\n    releaseAsset()\n  }\n\n  func getAssetInformationAsync() -> Promise<VideoInformation> {\n    let promise = Promise<VideoInformation>()\n\n    Task.detached(priority: .utility) { [weak self] in\n      guard let self else {\n        promise.reject(\n          withError: LibraryError.deallocated(objectName: \"HybridVideoPlayerSource\").error())\n        return\n      }\n\n      do {\n        let videoInformation = try await self.sourceLoader.load(priority: .utility) {\n          if self.url.isFileURL {\n            try VideoFileHelper.validateReadPermission(for: self.url)\n          }\n\n          try await self.initializeAsset()\n\n          guard let asset = self.asset else {\n            throw PlayerError.assetNotInitialized.error()\n          }\n\n          return try await asset.getAssetInformation()\n        }\n\n        promise.resolve(withResult: videoInformation)\n      } catch {\n        if error is CancellationError {\n          promise.reject(withError: SourceError.cancelled.error())\n        } else {\n          promise.reject(withError: error)\n        }\n      }\n    }\n\n    return promise\n  }\n\n  func initializeAsset() async throws {\n    guard asset == nil else {\n      return\n    }\n\n    if let headers = config.headers {\n      let options = [\n        \"AVURLAssetHTTPHeaderFieldsKey\": headers\n      ]\n      asset = AVURLAsset(url: url, options: options)\n    } else {\n      asset = AVURLAsset(url: url)\n    }\n\n    guard let asset else {\n      throw SourceError.failedToInitializeAsset.error()\n    }\n\n    do {\n      if let drmParams = config.drm {\n        drmManager = try PluginsRegistry.shared.getDrmManager(source: self)\n\n        guard let drmManager else {\n          throw LibraryError.DRMPluginNotFound.error()\n        }\n\n        do {\n          try drmManager.createContentKeyRequest(for: asset, drmParams: drmParams)\n        } catch {\n          print(\"[ReactNativeVideo] Failed to create content key request for DRM: \\(drmParams)\")\n        }\n      }\n\n      // Code browned from expo-video https://github.com/expo/expo/blob/ea17c9b1ce5111e1454b089ba381f3feb93f33cc/packages/expo-video/ios/VideoPlayerItem.swift#L40C30-L40C73\n      // If we don't load those properties, they will be loaded on main thread causing lags\n      _ = try? await asset.load(.duration, .preferredTransform, .isPlayable) as Any\n\n      try Task.checkCancellation()\n    } catch {\n      self.asset = nil\n      if error is CancellationError {\n        throw SourceError.cancelled.error()\n      }\n      throw error\n    }\n  }\n\n  func getAsset() async throws -> AVURLAsset {\n    if let asset {\n      return asset\n    }\n\n    do {\n      try await sourceLoader.load {\n        try await self.initializeAsset()\n      }\n\n      guard let asset else {\n        throw SourceError.failedToInitializeAsset.error()\n      }\n\n      return asset\n    } catch {\n      if error is CancellationError {\n        self.asset = nil\n        throw SourceError.cancelled.error()\n      }\n      throw error\n    }\n  }\n\n  func releaseAsset() {\n    sourceLoader.cancelSync()\n    asset = nil\n  }\n\n  var memorySize: Int {\n    var size = 0\n\n    size += asset?.estimatedMemoryUsage ?? 0\n\n    return size\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoPlayerSource/HybridVideoPlayerSourceFactory.swift",
    "content": "//\n//  HybridVideoPlayerSourceFactory.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 23/09/2024.\n//\n\nimport Foundation\n\nclass HybridVideoPlayerSourceFactory: HybridVideoPlayerSourceFactorySpec {\n  func fromVideoConfig(config: NativeVideoConfig) throws\n    -> any HybridVideoPlayerSourceSpec\n  {\n    return try HybridVideoPlayerSource(config: config)\n  }\n\n  func fromUri(uri: String) throws -> HybridVideoPlayerSourceSpec {\n    let config = NativeVideoConfig(\n      uri: uri,\n      externalSubtitles: nil,\n      drm: nil,\n      headers: nil,\n      bufferConfig: nil,\n      metadata: nil,\n      initializeOnCreation: true\n    )\n    return try HybridVideoPlayerSource(config: config)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoPlayerSource/SourceLoader.swift",
    "content": "//\n//  SourceLoader.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 27/01/2025.\n//\n\nimport Foundation\n\nprivate class AnyCancellable {\n  private let _cancel: () -> Void\n\n  init(_ cancel: @escaping () -> Void) {\n    self._cancel = cancel\n  }\n\n  func cancel() {\n    _cancel()\n  }\n}\n\nactor SourceLoaderActor {\n  private var currentCancellable: AnyCancellable?\n\n  func load<T>(priority: TaskPriority, operation: @escaping () async throws -> T) async throws -> T\n  {\n    await cancelCurrentTask()\n\n    let cancellableTask = Task(priority: priority) {\n      try await operation()\n    }\n\n    let cancellable = AnyCancellable {\n      cancellableTask.cancel()\n    }\n    currentCancellable = cancellable\n\n    do {\n      let result = try await cancellableTask.value\n      if currentCancellable === cancellable {\n        currentCancellable = nil\n      }\n      return result\n    } catch {\n      if currentCancellable === cancellable {\n        currentCancellable = nil\n      }\n      if error is CancellationError {\n        throw error\n      }\n      throw error\n    }\n  }\n\n  func cancel() async {\n    await cancelCurrentTask()\n  }\n\n  private func cancelCurrentTask() async {\n    currentCancellable?.cancel()\n    currentCancellable = nil\n  }\n}\n\nclass SourceLoader {\n  private let actor = SourceLoaderActor()\n\n  func load<T>(priority: TaskPriority = .userInitiated, operation: @escaping () async throws -> T)\n    async throws -> T\n  {\n    return try await actor.load(priority: priority, operation: operation)\n  }\n\n  func cancel() async {\n    await actor.cancel()\n  }\n\n  func cancelSync() {\n    Task {\n      await actor.cancel()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoViewViewManager/HybridVideoViewViewManager.swift",
    "content": "//\n//  HybridVideoViewViewManager.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 23/09/2024.\n//\n\nimport Foundation\nimport AVKit\nimport NitroModules\n\nstruct ViewListenerPair {\n  let id: UUID\n  let eventName: String\n  let callback: Any\n}\n\nclass HybridVideoViewViewManager: HybridVideoViewViewManagerSpec {\n  weak var view: VideoComponentView?\n  var listeners: [ViewListenerPair] = []\n  \n  let DEALOCATED_WARNING = \"ReactNativeVideo: VideoComponentView is no longer available. It is likely that the view was deallocated.\"\n  \n  init(nitroId: Double) throws {\n    guard let view = VideoComponentView.globalViewsMap.object(forKey: NSNumber(value: nitroId)) else {\n      throw VideoViewError.viewNotFound(nitroId: nitroId).error()\n    }\n    \n    self.view = view\n    super.init()\n    view.delegate = VideoViewDelegate(viewManager: self)\n  }\n  \n  // MARK: - Private helpers\n  \n  private func addListener<T>(eventName: String, listener: T) -> ListenerSubscription {\n    let id = UUID()\n    listeners.append(ViewListenerPair(id: id, eventName: eventName, callback: listener))\n    return ListenerSubscription(remove: { [weak self] in\n      self?.listeners.removeAll { $0.id == id }\n    })\n  }\n  \n  private func emitEvent<T>(eventName: String, invoke: (T) throws -> Void) {\n    for pair in listeners where pair.eventName == eventName {\n      if let callback = pair.callback as? T {\n        do {\n          try invoke(callback)\n        } catch {\n          print(\"[ReactNativeVideo] Error calling \\(eventName) listener: \\(error)\")\n        }\n      } else {\n        print(\"[ReactNativeVideo] Invalid callback type for \\(eventName)\")\n      }\n    }\n  }\n  \n  // MARK: - Properties\n  \n  weak var player: (any HybridVideoPlayerSpec)? {\n    get {\n      guard let view = view else {\n        print(DEALOCATED_WARNING)\n        return nil\n      }\n      return view.player\n    }\n    set {\n      guard let view = view else {\n        print(DEALOCATED_WARNING)\n        return\n      }\n      view.player = newValue\n    }\n  }\n  \n  var controls: Bool {\n    get {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return false\n      }\n      \n      return view.controls\n    }\n    set {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return\n      }\n      \n      view.controls = newValue\n    }\n  }\n  \n  var pictureInPicture: Bool {\n    get {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return false\n      }\n      \n      return view.allowsPictureInPicturePlayback\n    }\n    set {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return\n      }\n      \n      view.allowsPictureInPicturePlayback = newValue\n    }\n  }\n  \n  var autoEnterPictureInPicture: Bool {\n    get {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return false\n      }\n      \n      return view.autoEnterPictureInPicture\n    }\n    set {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return\n      }\n      \n      view.autoEnterPictureInPicture = newValue\n    }\n  }\n  \n  var resizeMode: ResizeMode {\n    get {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return .none\n      }\n      \n      return view.resizeMode\n    }\n    set {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return\n      }\n      \n      view.resizeMode = newValue\n    }\n  }\n  \n  var keepScreenAwake: Bool {\n    get {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return false\n      }\n      \n      return view.keepScreenAwake\n    }\n    set {\n      guard let view else {\n        print(DEALOCATED_WARNING)\n        return\n      }\n      \n      view.keepScreenAwake = newValue\n    }\n  }\n  \n  // Android only - no-op on iOS\n  var surfaceType: SurfaceType = .surface\n  \n  func enterFullscreen() throws {\n    guard let view else {\n      throw VideoViewError.viewIsDeallocated.error()\n    }\n    \n    try view.enterFullscreen()\n  }\n  \n  func exitFullscreen() throws {\n    guard let view else {\n      throw VideoViewError.viewIsDeallocated.error()\n    }\n    \n    try view.exitFullscreen()\n  }\n  \n  func enterPictureInPicture() throws {\n    guard let view else {\n      throw VideoViewError.viewIsDeallocated.error()\n    }\n    \n    try view.startPictureInPicture()\n  }\n  \n  func exitPictureInPicture() throws {\n    guard let view else {\n      throw VideoViewError.viewIsDeallocated.error()\n    }\n    \n    try view.stopPictureInPicture()\n  }\n  \n  func canEnterPictureInPicture() -> Bool {\n    return AVPictureInPictureController.isPictureInPictureSupported()\n  }\n  \n  // MARK: - Listener registration methods\n  \n  func addOnPictureInPictureChangeListener(listener: @escaping (Bool) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onPictureInPictureChange\", listener: listener)\n  }\n  \n  func addOnFullscreenChangeListener(listener: @escaping (Bool) -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"onFullscreenChange\", listener: listener)\n  }\n  \n  func addWillEnterFullscreenListener(listener: @escaping () -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"willEnterFullscreen\", listener: listener)\n  }\n  \n  func addWillExitFullscreenListener(listener: @escaping () -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"willExitFullscreen\", listener: listener)\n  }\n  \n  func addWillEnterPictureInPictureListener(listener: @escaping () -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"willEnterPictureInPicture\", listener: listener)\n  }\n  \n  func addWillExitPictureInPictureListener(listener: @escaping () -> Void) throws -> ListenerSubscription {\n    addListener(eventName: \"willExitPictureInPicture\", listener: listener)\n  }\n  \n  func clearAllListeners() throws {\n    listeners.removeAll()\n  }\n  \n  // MARK: - Event emission methods\n  \n  func onPictureInPictureChange(_ isActive: Bool) {\n    emitEvent(eventName: \"onPictureInPictureChange\") { (callback: (Bool) throws -> Void) in try callback(isActive) }\n  }\n  \n  func onFullscreenChange(_ isActive: Bool) {\n    emitEvent(eventName: \"onFullscreenChange\") { (callback: (Bool) throws -> Void) in try callback(isActive) }\n  }\n  \n  func willEnterFullscreen() {\n    emitEvent(eventName: \"willEnterFullscreen\") { (callback: () throws -> Void) in try callback() }\n  }\n  \n  func willExitFullscreen() {\n    emitEvent(eventName: \"willExitFullscreen\") { (callback: () throws -> Void) in try callback() }\n  }\n  \n  func willEnterPictureInPicture() {\n    emitEvent(eventName: \"willEnterPictureInPicture\") { (callback: () throws -> Void) in try callback() }\n  }\n  \n  func willExitPictureInPicture() {\n    emitEvent(eventName: \"willExitPictureInPicture\") { (callback: () throws -> Void) in try callback() }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/hybrids/VideoViewViewManager/HybridVideoViewViewManagerFactory.swift",
    "content": "//\n//  HybridVideoViewViewManagerFactory.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 23/09/2024.\n//\n\nimport Foundation\n\nclass HybridVideoViewViewManagerFactory: HybridVideoViewViewManagerFactorySpec {\n  func createViewManager(nitroId: Double) throws -> any HybridVideoViewViewManagerSpec {\n    return try HybridVideoViewViewManager(nitroId: nitroId)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/view/VideoComponentView.swift",
    "content": "//\n//  VideoComponent.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 30/09/2024.\n//\n\nimport AVFoundation\nimport AVKit\nimport Foundation\nimport UIKit\n\n@objc public class VideoComponentView: UIView {\n  public weak var player: HybridVideoPlayerSpec? = nil {\n    didSet {\n      guard let player = player as? HybridVideoPlayer else { return }\n      configureAVPlayerViewController(with: player.player)\n    }\n  }\n\n  var delegate: VideoViewDelegate?\n  private var playerView: UIView? = nil\n\n  private var observer: VideoComponentViewObserver? {\n    didSet {\n      playerViewController?.delegate = observer\n      observer?.updatePlayerViewControllerObservers()\n    }\n  }\n\n  private var _keepScreenAwake: Bool = false\n  var keepScreenAwake: Bool {\n    get {\n      guard let player = player as? HybridVideoPlayer else { return false }\n      return player.player.preventsDisplaySleepDuringVideoPlayback\n    }\n    set {\n      guard let player = player as? HybridVideoPlayer else { return }\n      player.player.preventsDisplaySleepDuringVideoPlayback = newValue\n      _keepScreenAwake = newValue\n    }\n  }\n\n  var playerViewController: AVPlayerViewController? {\n    didSet {\n      guard let observer, let playerViewController else { return }\n      playerViewController.delegate = observer\n      observer.updatePlayerViewControllerObservers()\n    }\n  }\n\n  public var controls: Bool = false {\n    didSet {\n      DispatchQueue.main.async { [weak self] in\n        guard let self = self, let playerViewController = self.playerViewController else { return }\n        playerViewController.showsPlaybackControls = self.controls\n      }\n    }\n  }\n\n  public var allowsPictureInPicturePlayback: Bool = false {\n    didSet {\n      DispatchQueue.main.async { [weak self] in\n        guard let self = self, let playerViewController = self.playerViewController else { return }\n\n        VideoManager.shared.requestAudioSessionUpdate()\n        playerViewController.allowsPictureInPicturePlayback = self.allowsPictureInPicturePlayback\n      }\n    }\n  }\n\n  public var autoEnterPictureInPicture: Bool = false {\n    didSet {\n      DispatchQueue.main.async { [weak self] in\n        guard let self = self, let playerViewController = self.playerViewController else { return }\n\n        VideoManager.shared.requestAudioSessionUpdate()\n        playerViewController.canStartPictureInPictureAutomaticallyFromInline =\n          self.autoEnterPictureInPicture\n      }\n    }\n  }\n\n  public var resizeMode: ResizeMode = .none {\n    didSet {\n      DispatchQueue.main.async { [weak self] in\n        guard let self = self, let playerViewController = self.playerViewController else { return }\n        playerViewController.videoGravity = resizeMode.toVideoGravity()\n      }\n    }\n  }\n\n  @objc public var nitroId: NSNumber = -1 {\n    didSet {\n      VideoComponentView.globalViewsMap.setObject(self, forKey: nitroId)\n    }\n  }\n\n  @objc public static var globalViewsMap: NSMapTable<NSNumber, VideoComponentView> =\n    .strongToWeakObjects()\n\n  @objc public override init(frame: CGRect) {\n    super.init(frame: frame)\n    VideoManager.shared.register(view: self)\n    setupPlayerView()\n    observer = VideoComponentViewObserver(view: self)\n  }\n\n  deinit {\n    VideoManager.shared.unregister(view: self)\n  }\n\n  @objc public required init?(coder: NSCoder) {\n    super.init(coder: coder)\n    setupPlayerView()\n  }\n\n  func setNitroId(nitroId: NSNumber) {\n    self.nitroId = nitroId\n  }\n\n  private func setupPlayerView() {\n    // Create a UIView to hold the video player layer\n    playerView = UIView(frame: self.bounds)\n    playerView?.translatesAutoresizingMaskIntoConstraints = false\n    if let playerView = playerView {\n      addSubview(playerView)\n      NSLayoutConstraint.activate([\n        playerView.leadingAnchor.constraint(equalTo: self.leadingAnchor),\n        playerView.trailingAnchor.constraint(equalTo: self.trailingAnchor),\n        playerView.topAnchor.constraint(equalTo: self.topAnchor),\n        playerView.bottomAnchor.constraint(equalTo: self.bottomAnchor),\n      ])\n    }\n  }\n\n  public func configureAVPlayerViewController(with player: AVPlayer) {\n    DispatchQueue.main.async { [weak self] in\n      guard let self = self, let playerView = self.playerView else { return }\n\n      // Skip reconfiguration if player hasn't changed and controller already exists\n      if let existingController = self.playerViewController,\n        existingController.player === player\n      {\n        return\n      }\n\n      // Remove previous controller if any\n      self.playerViewController?.willMove(toParent: nil)\n      self.playerViewController?.view.removeFromSuperview()\n      self.playerViewController?.removeFromParent()\n\n      let controller = AVPlayerViewController()\n      controller.player = player\n      controller.showsPlaybackControls = controls\n      controller.videoGravity = self.resizeMode.toVideoGravity()\n      controller.view.frame = playerView.bounds\n      controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]\n      controller.view.backgroundColor = .clear\n\n      // We manage this manually in NowPlayingInfoCenterManager\n      controller.updatesNowPlayingInfoCenter = false\n\n      if #available(iOS 16.0, *) {\n        if let initialSpeed = controller.speeds.first(where: { $0.rate == player.rate }) {\n          controller.selectSpeed(initialSpeed)\n        }\n      }\n       // Disable video frame analysis to prevent visual lookup\n      if #available(iOS 16.0, iPadOS 16.0, macCatalyst 18.0, *) {\n        controller.allowsVideoFrameAnalysis = false\n      }\n\n      // Find nearest UIViewController\n      if let parentVC = self.findViewController() {\n        parentVC.addChild(controller)\n        playerView.addSubview(controller.view)\n        controller.didMove(toParent: parentVC)\n        self.playerViewController = controller\n      }\n    }\n  }\n\n  // Helper to find nearest UIViewController\n  private func findViewController() -> UIViewController? {\n    var responder: UIResponder? = self\n    while let r = responder {\n      if let vc = r as? UIViewController {\n        return vc\n      }\n      responder = r.next\n    }\n    return nil\n  }\n\n  public override func willMove(toSuperview newSuperview: UIView?) {\n    super.willMove(toSuperview: newSuperview)\n\n    if newSuperview == nil {\n      PluginsRegistry.shared.notifyVideoViewDestroyed(view: self)\n\n      // We want to disable this when view is about to unmount\n      if keepScreenAwake {\n        keepScreenAwake = false\n      }\n    } else {\n      PluginsRegistry.shared.notifyVideoViewCreated(view: self)\n\n      // We want to restore keepScreenAwake after component remount\n      if _keepScreenAwake {\n        keepScreenAwake = true\n      }\n    }\n  }\n\n  public override func layoutSubviews() {\n    super.layoutSubviews()\n\n    // Update the frame of the playerViewController's view when the view's layout changes\n    playerViewController?.view.frame = playerView?.bounds ?? .zero\n    playerViewController?.contentOverlayView?.frame = playerView?.bounds ?? .zero\n    for subview in playerViewController?.contentOverlayView?.subviews ?? [] {\n      subview.frame = playerView?.bounds ?? .zero\n    }\n  }\n\n  public func enterFullscreen() throws {\n    guard let playerViewController else {\n      throw VideoViewError.viewIsDeallocated.error()\n    }\n\n    DispatchQueue.main.async {\n      playerViewController.enterFullscreen(animated: true)\n    }\n  }\n\n  public func exitFullscreen() throws {\n    guard let playerViewController else {\n      throw VideoViewError.viewIsDeallocated.error()\n    }\n\n    DispatchQueue.main.async {\n      playerViewController.exitFullscreen(animated: true)\n    }\n  }\n\n  public func startPictureInPicture() throws {\n    guard let playerViewController else {\n      throw VideoViewError.viewIsDeallocated.error()\n    }\n\n    guard AVPictureInPictureController.isPictureInPictureSupported() else {\n      throw VideoViewError.pictureInPictureNotSupported.error()\n    }\n\n    DispatchQueue.main.async {\n      // Here we skip error handling for simplicity\n      // We do check for PiP support earlier in the code\n      try? playerViewController.startPictureInPicture()\n    }\n  }\n\n  public func stopPictureInPicture() throws {\n    guard let playerViewController else {\n      throw VideoViewError.viewIsDeallocated.error()\n    }\n\n    DispatchQueue.main.async {\n      // Here we skip error handling for simplicity\n      // We do check for PiP support earlier in the code\n      playerViewController.stopPictureInPicture()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/view/VideoComponentViewObserver.swift",
    "content": "//\n//  VideoComponentViewObserver.swift\n//  ReactNativeVideo\n//\n//  Created by Krzysztof Moch on 06/05/2025.\n//\n\nimport Foundation\nimport AVKit\nimport AVFoundation\n\nprotocol VideoComponentViewDelegate: AnyObject {\n  func onPictureInPictureChange(_ isActive: Bool)\n  func onFullscreenChange(_ isActive: Bool)\n  func willEnterFullscreen()\n  func willExitFullscreen()\n  func willEnterPictureInPicture()\n  func willExitPictureInPicture()\n  func onReadyToDisplay()\n}\n\n// Map delegate methods to view manager methods\nfinal class VideoViewDelegate: NSObject, VideoComponentViewDelegate {\n  weak var viewManager: HybridVideoViewViewManager?\n  \n  init(viewManager: HybridVideoViewViewManager) {\n    self.viewManager = viewManager\n  }\n  \n  func onPictureInPictureChange(_ isActive: Bool) {\n    viewManager?.onPictureInPictureChange(isActive)\n  }\n  \n  func onFullscreenChange(_ isActive: Bool) {\n    viewManager?.onFullscreenChange(isActive)\n  }\n  \n  func willEnterFullscreen() {\n    viewManager?.willEnterFullscreen()\n  }\n  \n  func willExitFullscreen() {\n    viewManager?.willExitFullscreen()\n  }\n  \n  func willEnterPictureInPicture() {\n    viewManager?.willEnterPictureInPicture()\n  }\n  \n  func willExitPictureInPicture() {\n    viewManager?.willExitPictureInPicture()\n  }\n  \n  func onReadyToDisplay() {\n    if let player = viewManager?.player as? HybridVideoPlayer {\n      player._eventEmitter?.onReadyToDisplay()\n    }\n  }\n}\n\nclass VideoComponentViewObserver: NSObject, AVPlayerViewControllerDelegate {\n  private weak var view: VideoComponentView?\n  \n  var delegate: VideoViewDelegate? {\n    get {\n      return view?.delegate\n    }\n  }\n  \n  var playerViewController: AVPlayerViewController? {\n    return view?.playerViewController\n  }\n  \n  // playerViewController observers\n  var onReadyToDisplayObserver: NSKeyValueObservation?\n  \n  init(view: VideoComponentView) {\n    self.view = view\n    super.init()\n  }\n  \n  func initializePlayerViewContorollerObservers() {\n    guard let playerViewController = playerViewController else {\n      return\n    }\n    \n    onReadyToDisplayObserver = playerViewController.observe(\\.isReadyForDisplay, options: [.new]) { [weak self] _, change in\n      guard let self = self else { return }\n      if change.newValue == true {\n        self.delegate?.onReadyToDisplay()\n      }\n    }\n  }\n  \n  func removePlayerViewControllerObservers() {\n    onReadyToDisplayObserver?.invalidate()\n    onReadyToDisplayObserver = nil\n  }\n  \n  func updatePlayerViewControllerObservers() {\n    removePlayerViewControllerObservers()\n    initializePlayerViewContorollerObservers()\n  }\n  \n  func playerViewControllerDidStartPictureInPicture(_: AVPlayerViewController) {\n    delegate?.onPictureInPictureChange(true)\n  }\n  \n  func playerViewControllerDidStopPictureInPicture(_: AVPlayerViewController) {\n    delegate?.onPictureInPictureChange(false)\n  }\n  \n  func playerViewControllerWillStartPictureInPicture(_: AVPlayerViewController) {\n    delegate?.willEnterPictureInPicture()\n  }\n  \n  func playerViewControllerWillStopPictureInPicture(_: AVPlayerViewController) {\n    delegate?.willExitPictureInPicture()\n  }\n\n  func playerViewControllerRestoreUserInterfaceForPictureInPictureStop(\n    _ playerViewController: AVPlayerViewController,\n    completionHandler: @escaping (Bool) -> Void\n  ) {\n    let isViewAttached = view?.window != nil\n    completionHandler(isViewAttached)\n  }\n  \n  func playerViewController(\n    _: AVPlayerViewController,\n    willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator\n  ) {\n    delegate?.willExitFullscreen()\n\n    coordinator.animate(alongsideTransition: nil) { [weak self] context in\n      guard let self = self else { return }\n        \n      if context.isCancelled {\n        // iOS bug: window.isUserInteractionEnabled is left as false after cancelled fullscreen dismiss\n        if let window = self.playerViewController?.view.window, !window.isUserInteractionEnabled {\n          window.isUserInteractionEnabled = true\n        }\n\n        self.delegate?.willEnterFullscreen()\n\n        return\n      }\n\n      self.delegate?.onFullscreenChange(false)\n    }\n  }\n  \n  func playerViewController(\n    _: AVPlayerViewController,\n    willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator\n  ) {\n    delegate?.willEnterFullscreen()\n\n    coordinator.animate(alongsideTransition: nil) { [weak self] context in\n      guard let self = self else { return }\n\n      if context.isCancelled {\n        // iOS bug: window.isUserInteractionEnabled is left as false after cancelled fullscreen transition\n        if let window = self.playerViewController?.view.window, !window.isUserInteractionEnabled {\n          window.isUserInteractionEnabled = true\n        }\n\n        self.delegate?.willExitFullscreen()\n\n        return\n      }\n\n      self.delegate?.onFullscreenChange(true)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/ios/view/fabric/RCTVideoViewComponentView.h",
    "content": "#import <React/RCTViewComponentView.h>\n#import <UIKit/UIKit.h>\n\nNS_ASSUME_NONNULL_BEGIN\n\n@interface RCTVideoViewComponentView : RCTViewComponentView\n\n@end\n\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "packages/react-native-video/ios/view/fabric/RCTVideoViewComponentView.mm",
    "content": "#import \"RCTVideoViewComponentView.h\"\n\n#import <react/renderer/components/RNCVideoViewSpec/ComponentDescriptors.h>\n#import <react/renderer/components/RNCVideoViewSpec/EventEmitters.h>\n#import <react/renderer/components/RNCVideoViewSpec/Props.h>\n#import <react/renderer/components/RNCVideoViewSpec/RCTComponentViewHelpers.h>\n\n#import \"RCTFabricComponentsPlugins.h\"\n\n#import \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\n#if __has_include(\"ReactNativeVideo/ReactNativeVideo-Swift.h\")\n#import \"ReactNativeVideo/ReactNativeVideo-Swift.h\"\n#else\n#import \"ReactNativeVideo-Swift.h\"\n#endif\n\nusing namespace facebook::react;\n\n@interface RCTVideoViewComponentView () <RCTRNCVideoViewViewProtocol>\n@end\n\n@implementation RCTVideoViewComponentView {\n  VideoComponentView *_view;\n  int _nitroId;\n}\n\n- (instancetype)initWithFrame:(CGRect)frame {\n  if (self = [super initWithFrame:frame]) {\n    static const auto defaultProps =\n        std::make_shared<const RNCVideoViewProps>();\n    _props = defaultProps;\n\n    _view = [[VideoComponentView alloc] initWithFrame:frame];\n\n    self.contentView = _view;\n  }\n\n  // -1 means that nitroId wasn't set yet\n  _nitroId = -1;\n\n  return self;\n}\n\n- (void)updateProps:(Props::Shared const &)props\n           oldProps:(Props::Shared const &)oldProps {\n  const auto &oldViewProps =\n      *std::static_pointer_cast<RNCVideoViewProps const>(_props);\n  const auto &newViewProps =\n      *std::static_pointer_cast<RNCVideoViewProps const>(props);\n\n  if (oldViewProps.nitroId != newViewProps.nitroId) {\n    [self setNitroId:newViewProps.nitroId];\n  }\n\n  [super updateProps:props oldProps:oldProps];\n}\n\n- (void)setNitroId:(int)nitroId {\n  _nitroId = nitroId;\n  [_view setNitroId:[NSNumber numberWithInt:nitroId]];\n  [self onNitroIdChange:nitroId];\n}\n\n+ (BOOL)shouldBeRecycled\n{\n  return NO;\n}\n\n// Event emitter convenience method\n- (void)onNitroIdChange:(int)nitroId {\n  auto eventEmitter =\n      std::dynamic_pointer_cast<const RNCVideoViewEventEmitter>(_eventEmitter);\n  if (!eventEmitter || nitroId == -1) {\n    return;\n  }\n\n  eventEmitter->onNitroIdChange({.nitroId = nitroId});\n}\n\n- (void)updateEventEmitter:(EventEmitter::Shared const &)eventEmitter {\n  [super updateEventEmitter:eventEmitter];\n  [self onNitroIdChange:_nitroId];\n}\n\n+ (ComponentDescriptorProvider)componentDescriptorProvider {\n  return concreteComponentDescriptorProvider<RNCVideoViewComponentDescriptor>();\n}\n\nClass<RCTComponentViewProtocol> RNCVideoViewCls(void) {\n  return RCTVideoViewComponentView.class;\n}\n\n@end\n"
  },
  {
    "path": "packages/react-native-video/ios/view/fabric/RCTVideoViewViewManager.mm",
    "content": "#import <React/RCTViewManager.h>\n#import <React/RCTUIManager.h>\n#import \"RCTBridge.h\"\n\n@interface RCTVideoViewViewManager : RCTViewManager\n@end\n\n@implementation RCTVideoViewViewManager\n\nRCT_EXPORT_MODULE(RNCVideoView)\n\nRCT_EXPORT_VIEW_PROPERTY(nitroId, NSNumber)\n\n@end\n"
  },
  {
    "path": "packages/react-native-video/ios/view/paper/RCTVideoViewComponentView.h",
    "content": "#import <React/RCTView.h>\n\n@interface RCTVideoViewComponentView : RCTView\n\n@property (nonatomic, copy) NSNumber *nitroId;\n@property (nonatomic, copy) RCTDirectEventBlock onNitroIdChange;\n\n@end\n\n"
  },
  {
    "path": "packages/react-native-video/ios/view/paper/RCTVideoViewComponentView.mm",
    "content": "#import \"RCTVideoViewComponentView.h\"\n\n#import \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\n#if __has_include(\"ReactNativeVideo/ReactNativeVideo-Swift.h\")\n#import \"ReactNativeVideo/ReactNativeVideo-Swift.h\"\n#else\n#import \"ReactNativeVideo-Swift.h\"\n#endif\n\n@implementation RCTVideoViewComponentView {\n  VideoComponentView *_view;\n}\n\n- (instancetype)initWithFrame:(CGRect)frame {\n  self = [super initWithFrame:frame];\n  if (self) {\n    // Initialize VideoComponentView with the given frame\n    _view = [[VideoComponentView alloc] initWithFrame:frame];\n    _view.translatesAutoresizingMaskIntoConstraints = NO;\n    [self addSubview:_view];\n\n    // Set up constraints to make VideoComponentView fill\n    // RCTVideoViewComponentView\n    [NSLayoutConstraint activateConstraints:@[\n      [_view.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],\n      [_view.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],\n      [_view.topAnchor constraintEqualToAnchor:self.topAnchor],\n      [_view.bottomAnchor constraintEqualToAnchor:self.bottomAnchor]\n    ]];\n  }\n  return self;\n}\n\n- (void)setNitroId:(NSNumber *)nitroId {\n  _nitroId = nitroId;\n  [_view setNitroId:nitroId];\n\n  // Emit the onNitroIdChange event when nitroId is updated\n  if (self.onNitroIdChange) {\n    self.onNitroIdChange(@{@\"nitroId\" : nitroId});\n  }\n}\n\n@end\n"
  },
  {
    "path": "packages/react-native-video/ios/view/paper/RCTVideoViewViewManager.m",
    "content": "#import <React/RCTViewManager.h>\n#import \"RCTEventDispatcher.h\"\n#import \"RCTVideoViewComponentView.h\"\n\n@interface RCTVideoViewViewManager : RCTViewManager\n@end\n\n@implementation RCTVideoViewViewManager\n\nRCT_EXPORT_MODULE(RNCVideoView)\nRCT_EXPORT_VIEW_PROPERTY(nitroId, NSNumber)\nRCT_EXPORT_VIEW_PROPERTY(onNitroIdChange, RCTDirectEventBlock)\n\n- (UIView *)view {\n  return [[RCTVideoViewComponentView alloc] init];\n}\n\n@end\n"
  },
  {
    "path": "packages/react-native-video/nitro.json",
    "content": "{\n  \"android\": {\n    \"androidCxxLibName\": \"ReactNativeVideo\",\n    \"androidNamespace\": [\n      \"video\"\n    ]\n  },\n  \"cxxNamespace\": [\n    \"video\"\n  ],\n  \"ios\": {\n    \"iosModuleName\": \"ReactNativeVideo\"\n  },\n  \"autolinking\": {\n    \"VideoPlayerFactory\": {\n      \"swift\": \"HybridVideoPlayerFactory\",\n      \"kotlin\": \"HybridVideoPlayerFactory\"\n    },\n    \"VideoPlayerSourceFactory\": {\n      \"swift\": \"HybridVideoPlayerSourceFactory\",\n      \"kotlin\": \"HybridVideoPlayerSourceFactory\"\n    },\n    \"VideoViewViewManagerFactory\": {\n      \"swift\": \"HybridVideoViewViewManagerFactory\",\n      \"kotlin\": \"HybridVideoViewViewManagerFactory\"\n    }\n  }\n}"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/.gitattributes",
    "content": "** linguist-generated=true\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/ReactNativeVideo+autolinking.cmake",
    "content": "#\n# ReactNativeVideo+autolinking.cmake\n# This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n# https://github.com/mrousavy/nitro\n# Copyright © Marc Rousavy @ Margelo\n#\n\n# This is a CMake file that adds all files generated by Nitrogen\n# to the current CMake project.\n#\n# To use it, add this to your CMakeLists.txt:\n# ```cmake\n# include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/ReactNativeVideo+autolinking.cmake)\n# ```\n\n# Define a flag to check if we are building properly\nadd_definitions(-DBUILDING_REACTNATIVEVIDEO_WITH_GENERATED_CMAKE_PROJECT)\n\n# Enable Raw Props parsing in react-native (for Nitro Views)\nadd_definitions(-DRN_SERIALIZABLE_STATE)\n\n# Add all headers that were generated by Nitrogen\ninclude_directories(\n  \"../nitrogen/generated/shared/c++\"\n  \"../nitrogen/generated/android/c++\"\n  \"../nitrogen/generated/android/\"\n)\n\n# Add all .cpp sources that were generated by Nitrogen\ntarget_sources(\n  # CMake project name (Android C++ library name)\n  ReactNativeVideo PRIVATE\n  # Autolinking Setup\n  ../nitrogen/generated/android/ReactNativeVideoOnLoad.cpp\n  # Shared Nitrogen C++ sources\n  ../nitrogen/generated/shared/c++/HybridVideoPlayerSpec.cpp\n  ../nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.cpp\n  ../nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.cpp\n  ../nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.cpp\n  ../nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.cpp\n  ../nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.cpp\n  ../nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.cpp\n  # Android-specific Nitrogen C++ sources\n  ../nitrogen/generated/android/c++/JHybridVideoPlayerSpec.cpp\n  ../nitrogen/generated/android/c++/JVariant_NullType_HybridVideoPlayerSourceSpec.cpp\n  ../nitrogen/generated/android/c++/JVariant_NullType_TextTrack.cpp\n  ../nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.cpp\n  ../nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.cpp\n  ../nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.cpp\n  ../nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.cpp\n  ../nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.cpp\n  ../nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.cpp\n)\n\n# From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake\n# Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake\ntarget_compile_definitions(\n  ReactNativeVideo PRIVATE\n  -DFOLLY_NO_CONFIG=1\n  -DFOLLY_HAVE_CLOCK_GETTIME=1\n  -DFOLLY_USE_LIBCPP=1\n  -DFOLLY_CFG_NO_COROUTINES=1\n  -DFOLLY_MOBILE=1\n  -DFOLLY_HAVE_RECVMMSG=1\n  -DFOLLY_HAVE_PTHREAD=1\n  # Once we target android-23 above, we can comment\n  # the following line. NDK uses GNU style stderror_r() after API 23.\n  -DFOLLY_HAVE_XSI_STRERROR_R=1\n)\n\n# Add all libraries required by the generated specs\nfind_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++\nfind_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule)\nfind_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library\n\n# Link all libraries together\ntarget_link_libraries(\n        ReactNativeVideo\n        fbjni::fbjni                              # <-- Facebook C++ JNI helpers\n        ReactAndroid::jsi                         # <-- RN: JSI\n        react-native-nitro-modules::NitroModules  # <-- NitroModules Core :)\n)\n\n# Link react-native (different prefab between RN 0.75 and RN 0.76)\nif(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)\n    target_link_libraries(\n        ReactNativeVideo\n        ReactAndroid::reactnative                 # <-- RN: Native Modules umbrella prefab\n    )\nelse()\n    target_link_libraries(\n        ReactNativeVideo\n        ReactAndroid::react_nativemodule_core     # <-- RN: TurboModules Core\n    )\nendif()\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/ReactNativeVideo+autolinking.gradle",
    "content": "///\n/// ReactNativeVideo+autolinking.gradle\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/// This is a Gradle file that adds all files generated by Nitrogen\n/// to the current Gradle project.\n///\n/// To use it, add this to your build.gradle:\n/// ```gradle\n/// apply from: '../nitrogen/generated/android/ReactNativeVideo+autolinking.gradle'\n/// ```\n\nlogger.warn(\"[NitroModules] 🔥 ReactNativeVideo is boosted by nitro!\")\n\nandroid {\n  sourceSets {\n    main {\n      java.srcDirs += [\n        // Nitrogen files\n        \"${project.projectDir}/../nitrogen/generated/android/kotlin\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/ReactNativeVideoOnLoad.cpp",
    "content": "///\n/// ReactNativeVideoOnLoad.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#ifndef BUILDING_REACTNATIVEVIDEO_WITH_GENERATED_CMAKE_PROJECT\n#error ReactNativeVideoOnLoad.cpp is not being built with the autogenerated CMakeLists.txt project. Is a different CMakeLists.txt building this?\n#endif\n\n#include \"ReactNativeVideoOnLoad.hpp\"\n\n#include <jni.h>\n#include <fbjni/fbjni.h>\n#include <NitroModules/HybridObjectRegistry.hpp>\n\n#include \"JHybridVideoPlayerSpec.hpp\"\n#include \"JHybridVideoPlayerFactorySpec.hpp\"\n#include \"JHybridVideoPlayerEventEmitterSpec.hpp\"\n#include \"JFunc_void.hpp\"\n#include \"JFunc_void_bool.hpp\"\n#include \"JFunc_void_BandwidthData.hpp\"\n#include \"JFunc_void_onLoadData.hpp\"\n#include \"JFunc_void_onLoadStartData.hpp\"\n#include \"JFunc_void_onPlaybackStateChangeData.hpp\"\n#include \"JFunc_void_double.hpp\"\n#include \"JFunc_void_onProgressData.hpp\"\n#include \"JFunc_void_VideoPlayerStatus.hpp\"\n#include \"JFunc_void_TimedMetadata.hpp\"\n#include \"JFunc_void_std__vector_std__string_.hpp\"\n#include \"JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__.hpp\"\n#include \"JFunc_void_onVolumeChangeData.hpp\"\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n#include \"JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp\"\n#include \"JHybridVideoPlayerSourceFactorySpec.hpp\"\n#include \"JHybridVideoViewViewManagerSpec.hpp\"\n#include \"JHybridVideoViewViewManagerFactorySpec.hpp\"\n#include <NitroModules/DefaultConstructableObject.hpp>\n\nnamespace margelo::nitro::video {\n\nint initialize(JavaVM* vm) {\n  return facebook::jni::initialize(vm, []() {\n    ::margelo::nitro::video::registerAllNatives();\n  });\n}\n\nstruct JHybridVideoPlayerFactorySpecImpl: public jni::JavaClass<JHybridVideoPlayerFactorySpecImpl, JHybridVideoPlayerFactorySpec::JavaPart> {\n  static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerFactory;\";\n  static std::shared_ptr<JHybridVideoPlayerFactorySpec> create() {\n    static auto constructorFn = javaClassStatic()->getConstructor<JHybridVideoPlayerFactorySpecImpl::javaobject()>();\n    jni::local_ref<JHybridVideoPlayerFactorySpec::JavaPart> javaPart = javaClassStatic()->newObject(constructorFn);\n    return javaPart->getJHybridVideoPlayerFactorySpec();\n  }\n};\nstruct JHybridVideoPlayerSourceFactorySpecImpl: public jni::JavaClass<JHybridVideoPlayerSourceFactorySpecImpl, JHybridVideoPlayerSourceFactorySpec::JavaPart> {\n  static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerSourceFactory;\";\n  static std::shared_ptr<JHybridVideoPlayerSourceFactorySpec> create() {\n    static auto constructorFn = javaClassStatic()->getConstructor<JHybridVideoPlayerSourceFactorySpecImpl::javaobject()>();\n    jni::local_ref<JHybridVideoPlayerSourceFactorySpec::JavaPart> javaPart = javaClassStatic()->newObject(constructorFn);\n    return javaPart->getJHybridVideoPlayerSourceFactorySpec();\n  }\n};\nstruct JHybridVideoViewViewManagerFactorySpecImpl: public jni::JavaClass<JHybridVideoViewViewManagerFactorySpecImpl, JHybridVideoViewViewManagerFactorySpec::JavaPart> {\n  static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoViewViewManagerFactory;\";\n  static std::shared_ptr<JHybridVideoViewViewManagerFactorySpec> create() {\n    static auto constructorFn = javaClassStatic()->getConstructor<JHybridVideoViewViewManagerFactorySpecImpl::javaobject()>();\n    jni::local_ref<JHybridVideoViewViewManagerFactorySpec::JavaPart> javaPart = javaClassStatic()->newObject(constructorFn);\n    return javaPart->getJHybridVideoViewViewManagerFactorySpec();\n  }\n};\n\nvoid registerAllNatives() {\n  using namespace margelo::nitro;\n  using namespace margelo::nitro::video;\n\n  // Register native JNI methods\n  margelo::nitro::video::JHybridVideoPlayerSpec::CxxPart::registerNatives();\n  margelo::nitro::video::JHybridVideoPlayerFactorySpec::CxxPart::registerNatives();\n  margelo::nitro::video::JHybridVideoPlayerEventEmitterSpec::CxxPart::registerNatives();\n  margelo::nitro::video::JFunc_void_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_bool_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_BandwidthData_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_onLoadData_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_onLoadStartData_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_onPlaybackStateChangeData_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_double_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_onProgressData_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_VideoPlayerStatus_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_TimedMetadata_cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_std__vector_std__string__cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx::registerNatives();\n  margelo::nitro::video::JFunc_void_onVolumeChangeData_cxx::registerNatives();\n  margelo::nitro::video::JHybridVideoPlayerSourceSpec::CxxPart::registerNatives();\n  margelo::nitro::video::JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::registerNatives();\n  margelo::nitro::video::JHybridVideoPlayerSourceFactorySpec::CxxPart::registerNatives();\n  margelo::nitro::video::JHybridVideoViewViewManagerSpec::CxxPart::registerNatives();\n  margelo::nitro::video::JHybridVideoViewViewManagerFactorySpec::CxxPart::registerNatives();\n\n  // Register Nitro Hybrid Objects\n  HybridObjectRegistry::registerHybridObjectConstructor(\n    \"VideoPlayerFactory\",\n    []() -> std::shared_ptr<HybridObject> {\n      return JHybridVideoPlayerFactorySpecImpl::create();\n    }\n  );\n  HybridObjectRegistry::registerHybridObjectConstructor(\n    \"VideoPlayerSourceFactory\",\n    []() -> std::shared_ptr<HybridObject> {\n      return JHybridVideoPlayerSourceFactorySpecImpl::create();\n    }\n  );\n  HybridObjectRegistry::registerHybridObjectConstructor(\n    \"VideoViewViewManagerFactory\",\n    []() -> std::shared_ptr<HybridObject> {\n      return JHybridVideoViewViewManagerFactorySpecImpl::create();\n    }\n  );\n}\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/ReactNativeVideoOnLoad.hpp",
    "content": "///\n/// ReactNativeVideoOnLoad.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include <jni.h>\n#include <functional>\n#include <NitroModules/NitroDefines.hpp>\n\nnamespace margelo::nitro::video {\n\n  [[deprecated(\"Use registerNatives() instead.\")]]\n  int initialize(JavaVM* vm);\n\n  /**\n   * Register the native (C++) part of ReactNativeVideo, and autolinks all Hybrid Objects.\n   * Call this in your `JNI_OnLoad` function (probably inside `cpp-adapter.cpp`),\n   * inside a `facebook::jni::initialize(vm, ...)` call.\n   * Example:\n   * ```cpp (cpp-adapter.cpp)\n   * JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {\n   *   return facebook::jni::initialize(vm, []() {\n   *     // register all ReactNativeVideo HybridObjects\n   *     margelo::nitro::video::registerNatives();\n   *     // any other custom registrations go here.\n   *   });\n   * }\n   * ```\n   */\n  void registerAllNatives();\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JBandwidthData.hpp",
    "content": "///\n/// JBandwidthData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"BandwidthData.hpp\"\n\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"BandwidthData\" and the the Kotlin data class \"BandwidthData\".\n   */\n  struct JBandwidthData final: public jni::JavaClass<JBandwidthData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/BandwidthData;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct BandwidthData by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    BandwidthData toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldBitrate = clazz->getField<double>(\"bitrate\");\n      double bitrate = this->getFieldValue(fieldBitrate);\n      static const auto fieldWidth = clazz->getField<jni::JDouble>(\"width\");\n      jni::local_ref<jni::JDouble> width = this->getFieldValue(fieldWidth);\n      static const auto fieldHeight = clazz->getField<jni::JDouble>(\"height\");\n      jni::local_ref<jni::JDouble> height = this->getFieldValue(fieldHeight);\n      return BandwidthData(\n        bitrate,\n        width != nullptr ? std::make_optional(width->value()) : std::nullopt,\n        height != nullptr ? std::make_optional(height->value()) : std::nullopt\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JBandwidthData::javaobject> fromCpp(const BandwidthData& value) {\n      using JSignature = JBandwidthData(double, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.bitrate,\n        value.width.has_value() ? jni::JDouble::valueOf(value.width.value()) : nullptr,\n        value.height.has_value() ? jni::JDouble::valueOf(value.height.value()) : nullptr\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JBufferConfig.hpp",
    "content": "///\n/// JBufferConfig.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"BufferConfig.hpp\"\n\n#include \"JLivePlaybackParams.hpp\"\n#include \"JResolution.hpp\"\n#include \"LivePlaybackParams.hpp\"\n#include \"Resolution.hpp\"\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"BufferConfig\" and the the Kotlin data class \"BufferConfig\".\n   */\n  struct JBufferConfig final: public jni::JavaClass<JBufferConfig> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/BufferConfig;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct BufferConfig by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    BufferConfig toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldLivePlayback = clazz->getField<JLivePlaybackParams>(\"livePlayback\");\n      jni::local_ref<JLivePlaybackParams> livePlayback = this->getFieldValue(fieldLivePlayback);\n      static const auto fieldMinBufferMs = clazz->getField<jni::JDouble>(\"minBufferMs\");\n      jni::local_ref<jni::JDouble> minBufferMs = this->getFieldValue(fieldMinBufferMs);\n      static const auto fieldMaxBufferMs = clazz->getField<jni::JDouble>(\"maxBufferMs\");\n      jni::local_ref<jni::JDouble> maxBufferMs = this->getFieldValue(fieldMaxBufferMs);\n      static const auto fieldBufferForPlaybackMs = clazz->getField<jni::JDouble>(\"bufferForPlaybackMs\");\n      jni::local_ref<jni::JDouble> bufferForPlaybackMs = this->getFieldValue(fieldBufferForPlaybackMs);\n      static const auto fieldBufferForPlaybackAfterRebufferMs = clazz->getField<jni::JDouble>(\"bufferForPlaybackAfterRebufferMs\");\n      jni::local_ref<jni::JDouble> bufferForPlaybackAfterRebufferMs = this->getFieldValue(fieldBufferForPlaybackAfterRebufferMs);\n      static const auto fieldBackBufferDurationMs = clazz->getField<jni::JDouble>(\"backBufferDurationMs\");\n      jni::local_ref<jni::JDouble> backBufferDurationMs = this->getFieldValue(fieldBackBufferDurationMs);\n      static const auto fieldPreferredForwardBufferDurationMs = clazz->getField<jni::JDouble>(\"preferredForwardBufferDurationMs\");\n      jni::local_ref<jni::JDouble> preferredForwardBufferDurationMs = this->getFieldValue(fieldPreferredForwardBufferDurationMs);\n      static const auto fieldPreferredPeakBitRate = clazz->getField<jni::JDouble>(\"preferredPeakBitRate\");\n      jni::local_ref<jni::JDouble> preferredPeakBitRate = this->getFieldValue(fieldPreferredPeakBitRate);\n      static const auto fieldPreferredMaximumResolution = clazz->getField<JResolution>(\"preferredMaximumResolution\");\n      jni::local_ref<JResolution> preferredMaximumResolution = this->getFieldValue(fieldPreferredMaximumResolution);\n      static const auto fieldPreferredPeakBitRateForExpensiveNetworks = clazz->getField<jni::JDouble>(\"preferredPeakBitRateForExpensiveNetworks\");\n      jni::local_ref<jni::JDouble> preferredPeakBitRateForExpensiveNetworks = this->getFieldValue(fieldPreferredPeakBitRateForExpensiveNetworks);\n      static const auto fieldPreferredMaximumResolutionForExpensiveNetworks = clazz->getField<JResolution>(\"preferredMaximumResolutionForExpensiveNetworks\");\n      jni::local_ref<JResolution> preferredMaximumResolutionForExpensiveNetworks = this->getFieldValue(fieldPreferredMaximumResolutionForExpensiveNetworks);\n      return BufferConfig(\n        livePlayback != nullptr ? std::make_optional(livePlayback->toCpp()) : std::nullopt,\n        minBufferMs != nullptr ? std::make_optional(minBufferMs->value()) : std::nullopt,\n        maxBufferMs != nullptr ? std::make_optional(maxBufferMs->value()) : std::nullopt,\n        bufferForPlaybackMs != nullptr ? std::make_optional(bufferForPlaybackMs->value()) : std::nullopt,\n        bufferForPlaybackAfterRebufferMs != nullptr ? std::make_optional(bufferForPlaybackAfterRebufferMs->value()) : std::nullopt,\n        backBufferDurationMs != nullptr ? std::make_optional(backBufferDurationMs->value()) : std::nullopt,\n        preferredForwardBufferDurationMs != nullptr ? std::make_optional(preferredForwardBufferDurationMs->value()) : std::nullopt,\n        preferredPeakBitRate != nullptr ? std::make_optional(preferredPeakBitRate->value()) : std::nullopt,\n        preferredMaximumResolution != nullptr ? std::make_optional(preferredMaximumResolution->toCpp()) : std::nullopt,\n        preferredPeakBitRateForExpensiveNetworks != nullptr ? std::make_optional(preferredPeakBitRateForExpensiveNetworks->value()) : std::nullopt,\n        preferredMaximumResolutionForExpensiveNetworks != nullptr ? std::make_optional(preferredMaximumResolutionForExpensiveNetworks->toCpp()) : std::nullopt\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JBufferConfig::javaobject> fromCpp(const BufferConfig& value) {\n      using JSignature = JBufferConfig(jni::alias_ref<JLivePlaybackParams>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<JResolution>, jni::alias_ref<jni::JDouble>, jni::alias_ref<JResolution>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.livePlayback.has_value() ? JLivePlaybackParams::fromCpp(value.livePlayback.value()) : nullptr,\n        value.minBufferMs.has_value() ? jni::JDouble::valueOf(value.minBufferMs.value()) : nullptr,\n        value.maxBufferMs.has_value() ? jni::JDouble::valueOf(value.maxBufferMs.value()) : nullptr,\n        value.bufferForPlaybackMs.has_value() ? jni::JDouble::valueOf(value.bufferForPlaybackMs.value()) : nullptr,\n        value.bufferForPlaybackAfterRebufferMs.has_value() ? jni::JDouble::valueOf(value.bufferForPlaybackAfterRebufferMs.value()) : nullptr,\n        value.backBufferDurationMs.has_value() ? jni::JDouble::valueOf(value.backBufferDurationMs.value()) : nullptr,\n        value.preferredForwardBufferDurationMs.has_value() ? jni::JDouble::valueOf(value.preferredForwardBufferDurationMs.value()) : nullptr,\n        value.preferredPeakBitRate.has_value() ? jni::JDouble::valueOf(value.preferredPeakBitRate.value()) : nullptr,\n        value.preferredMaximumResolution.has_value() ? JResolution::fromCpp(value.preferredMaximumResolution.value()) : nullptr,\n        value.preferredPeakBitRateForExpensiveNetworks.has_value() ? jni::JDouble::valueOf(value.preferredPeakBitRateForExpensiveNetworks.value()) : nullptr,\n        value.preferredMaximumResolutionForExpensiveNetworks.has_value() ? JResolution::fromCpp(value.preferredMaximumResolutionForExpensiveNetworks.value()) : nullptr\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JCustomVideoMetadata.hpp",
    "content": "///\n/// JCustomVideoMetadata.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"CustomVideoMetadata.hpp\"\n\n#include <optional>\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"CustomVideoMetadata\" and the the Kotlin data class \"CustomVideoMetadata\".\n   */\n  struct JCustomVideoMetadata final: public jni::JavaClass<JCustomVideoMetadata> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/CustomVideoMetadata;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct CustomVideoMetadata by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    CustomVideoMetadata toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldTitle = clazz->getField<jni::JString>(\"title\");\n      jni::local_ref<jni::JString> title = this->getFieldValue(fieldTitle);\n      static const auto fieldSubtitle = clazz->getField<jni::JString>(\"subtitle\");\n      jni::local_ref<jni::JString> subtitle = this->getFieldValue(fieldSubtitle);\n      static const auto fieldDescription = clazz->getField<jni::JString>(\"description\");\n      jni::local_ref<jni::JString> description = this->getFieldValue(fieldDescription);\n      static const auto fieldArtist = clazz->getField<jni::JString>(\"artist\");\n      jni::local_ref<jni::JString> artist = this->getFieldValue(fieldArtist);\n      static const auto fieldImageUri = clazz->getField<jni::JString>(\"imageUri\");\n      jni::local_ref<jni::JString> imageUri = this->getFieldValue(fieldImageUri);\n      return CustomVideoMetadata(\n        title != nullptr ? std::make_optional(title->toStdString()) : std::nullopt,\n        subtitle != nullptr ? std::make_optional(subtitle->toStdString()) : std::nullopt,\n        description != nullptr ? std::make_optional(description->toStdString()) : std::nullopt,\n        artist != nullptr ? std::make_optional(artist->toStdString()) : std::nullopt,\n        imageUri != nullptr ? std::make_optional(imageUri->toStdString()) : std::nullopt\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JCustomVideoMetadata::javaobject> fromCpp(const CustomVideoMetadata& value) {\n      using JSignature = JCustomVideoMetadata(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.title.has_value() ? jni::make_jstring(value.title.value()) : nullptr,\n        value.subtitle.has_value() ? jni::make_jstring(value.subtitle.value()) : nullptr,\n        value.description.has_value() ? jni::make_jstring(value.description.value()) : nullptr,\n        value.artist.has_value() ? jni::make_jstring(value.artist.value()) : nullptr,\n        value.imageUri.has_value() ? jni::make_jstring(value.imageUri.value()) : nullptr\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp",
    "content": "///\n/// JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include <string>\n#include <NitroModules/Promise.hpp>\n#include \"OnGetLicensePayload.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include <NitroModules/JPromise.hpp>\n#include \"JOnGetLicensePayload.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(payload: OnGetLicensePayload) -> Promise<Promise<String>>`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload: public jni::JavaClass<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload` instance holds through JNI.\n     */\n    std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> invoke(const OnGetLicensePayload& payload) const {\n      static const auto method = javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<JOnGetLicensePayload> /* payload */)>(\"invoke\");\n      auto __result = method(self(), JOnGetLicensePayload::fromCpp(payload));\n      return [&]() {\n        auto __promise = Promise<std::shared_ptr<Promise<std::string>>>::create();\n        __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {\n          auto __result = jni::static_ref_cast<JPromise::javaobject>(__boxedResult);\n          __promise->resolve([&]() {\n            auto __promise = Promise<std::string>::create();\n            __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {\n              auto __result = jni::static_ref_cast<jni::JString>(__boxedResult);\n              __promise->resolve(__result->toStdString());\n            });\n            __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {\n              jni::JniException __jniError(__throwable);\n              __promise->reject(std::make_exception_ptr(__jniError));\n            });\n            return __promise;\n          }());\n        });\n        __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {\n          jni::JniException __jniError(__throwable);\n          __promise->reject(std::make_exception_ptr(__jniError));\n        });\n        return __promise;\n      }();\n    }\n  };\n\n  /**\n   * An implementation of Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx final: public jni::HybridClass<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx, JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload> {\n  public:\n    static jni::local_ref<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload::javaobject> fromCpp(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>& func) {\n      return JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx` instance holds.\n     */\n    jni::local_ref<JPromise::javaobject> invoke_cxx(jni::alias_ref<JOnGetLicensePayload> payload) {\n      std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> __result = _func(payload->toCpp());\n      return [&]() {\n        jni::local_ref<JPromise::javaobject> __localPromise = JPromise::create();\n        jni::global_ref<JPromise::javaobject> __promise = jni::make_global(__localPromise);\n        __result->addOnResolvedListener([=](const std::shared_ptr<Promise<std::string>>& __result) {\n          __promise->cthis()->resolve([&]() {\n            jni::local_ref<JPromise::javaobject> __localPromise = JPromise::create();\n            jni::global_ref<JPromise::javaobject> __promise = jni::make_global(__localPromise);\n            __result->addOnResolvedListener([=](const std::string& __result) {\n              __promise->cthis()->resolve(jni::make_jstring(__result));\n            });\n            __result->addOnRejectedListener([=](const std::exception_ptr& __error) {\n              auto __jniError = jni::getJavaExceptionForCppException(__error);\n              __promise->cthis()->reject(__jniError);\n            });\n            return __localPromise;\n          }());\n        });\n        __result->addOnRejectedListener([=](const std::exception_ptr& __error) {\n          auto __jniError = jni::getJavaExceptionForCppException(__error);\n          __promise->cthis()->reject(__jniError);\n        });\n        return __localPromise;\n      }();\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void.hpp",
    "content": "///\n/// JFunc_void.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `() -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void: public jni::JavaClass<JFunc_void> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void` instance holds through JNI.\n     */\n    void invoke() const {\n      static const auto method = javaClassStatic()->getMethod<void()>(\"invoke\");\n      method(self());\n    }\n  };\n\n  /**\n   * An implementation of Func_void that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_cxx final: public jni::HybridClass<JFunc_void_cxx, JFunc_void> {\n  public:\n    static jni::local_ref<JFunc_void::javaobject> fromCpp(const std::function<void()>& func) {\n      return JFunc_void_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_cxx` instance holds.\n     */\n    void invoke_cxx() {\n      _func();\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void()>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_cxx(const std::function<void()>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void()> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_BandwidthData.hpp",
    "content": "///\n/// JFunc_void_BandwidthData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include \"BandwidthData.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JBandwidthData.hpp\"\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(data: BandwidthData) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_BandwidthData: public jni::JavaClass<JFunc_void_BandwidthData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_BandwidthData;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_BandwidthData` instance holds through JNI.\n     */\n    void invoke(const BandwidthData& data) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JBandwidthData> /* data */)>(\"invoke\");\n      method(self(), JBandwidthData::fromCpp(data));\n    }\n  };\n\n  /**\n   * An implementation of Func_void_BandwidthData that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_BandwidthData_cxx final: public jni::HybridClass<JFunc_void_BandwidthData_cxx, JFunc_void_BandwidthData> {\n  public:\n    static jni::local_ref<JFunc_void_BandwidthData::javaobject> fromCpp(const std::function<void(const BandwidthData& /* data */)>& func) {\n      return JFunc_void_BandwidthData_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_BandwidthData_cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JBandwidthData> data) {\n      _func(data->toCpp());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const BandwidthData& /* data */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_BandwidthData_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_BandwidthData_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_BandwidthData_cxx(const std::function<void(const BandwidthData& /* data */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const BandwidthData& /* data */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp",
    "content": "///\n/// JFunc_void_TimedMetadata.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include \"TimedMetadata.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JTimedMetadata.hpp\"\n#include \"TimedMetadataObject.hpp\"\n#include <vector>\n#include \"JTimedMetadataObject.hpp\"\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(data: TimedMetadata) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_TimedMetadata: public jni::JavaClass<JFunc_void_TimedMetadata> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_TimedMetadata;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_TimedMetadata` instance holds through JNI.\n     */\n    void invoke(const TimedMetadata& data) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JTimedMetadata> /* data */)>(\"invoke\");\n      method(self(), JTimedMetadata::fromCpp(data));\n    }\n  };\n\n  /**\n   * An implementation of Func_void_TimedMetadata that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_TimedMetadata_cxx final: public jni::HybridClass<JFunc_void_TimedMetadata_cxx, JFunc_void_TimedMetadata> {\n  public:\n    static jni::local_ref<JFunc_void_TimedMetadata::javaobject> fromCpp(const std::function<void(const TimedMetadata& /* data */)>& func) {\n      return JFunc_void_TimedMetadata_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_TimedMetadata_cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JTimedMetadata> data) {\n      _func(data->toCpp());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const TimedMetadata& /* data */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_TimedMetadata_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_TimedMetadata_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_TimedMetadata_cxx(const std::function<void(const TimedMetadata& /* data */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const TimedMetadata& /* data */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_VideoPlayerStatus.hpp",
    "content": "///\n/// JFunc_void_VideoPlayerStatus.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include \"VideoPlayerStatus.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JVideoPlayerStatus.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(status: VideoPlayerStatus) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_VideoPlayerStatus: public jni::JavaClass<JFunc_void_VideoPlayerStatus> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_VideoPlayerStatus;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_VideoPlayerStatus` instance holds through JNI.\n     */\n    void invoke(VideoPlayerStatus status) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JVideoPlayerStatus> /* status */)>(\"invoke\");\n      method(self(), JVideoPlayerStatus::fromCpp(status));\n    }\n  };\n\n  /**\n   * An implementation of Func_void_VideoPlayerStatus that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_VideoPlayerStatus_cxx final: public jni::HybridClass<JFunc_void_VideoPlayerStatus_cxx, JFunc_void_VideoPlayerStatus> {\n  public:\n    static jni::local_ref<JFunc_void_VideoPlayerStatus::javaobject> fromCpp(const std::function<void(VideoPlayerStatus /* status */)>& func) {\n      return JFunc_void_VideoPlayerStatus_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_VideoPlayerStatus_cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JVideoPlayerStatus> status) {\n      _func(status->toCpp());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(VideoPlayerStatus /* status */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_VideoPlayerStatus_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_VideoPlayerStatus_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_VideoPlayerStatus_cxx(const std::function<void(VideoPlayerStatus /* status */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(VideoPlayerStatus /* status */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_bool.hpp",
    "content": "///\n/// JFunc_void_bool.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(isInPictureInPicture: Boolean) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_bool: public jni::JavaClass<JFunc_void_bool> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_bool;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_bool` instance holds through JNI.\n     */\n    void invoke(bool isInPictureInPicture) const {\n      static const auto method = javaClassStatic()->getMethod<void(jboolean /* isInPictureInPicture */)>(\"invoke\");\n      method(self(), isInPictureInPicture);\n    }\n  };\n\n  /**\n   * An implementation of Func_void_bool that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_bool_cxx final: public jni::HybridClass<JFunc_void_bool_cxx, JFunc_void_bool> {\n  public:\n    static jni::local_ref<JFunc_void_bool::javaobject> fromCpp(const std::function<void(bool /* isInPictureInPicture */)>& func) {\n      return JFunc_void_bool_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_bool_cxx` instance holds.\n     */\n    void invoke_cxx(jboolean isInPictureInPicture) {\n      _func(static_cast<bool>(isInPictureInPicture));\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(bool /* isInPictureInPicture */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_bool_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_bool_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_bool_cxx(const std::function<void(bool /* isInPictureInPicture */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(bool /* isInPictureInPicture */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_double.hpp",
    "content": "///\n/// JFunc_void_double.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(rate: Double) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_double: public jni::JavaClass<JFunc_void_double> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_double;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_double` instance holds through JNI.\n     */\n    void invoke(double rate) const {\n      static const auto method = javaClassStatic()->getMethod<void(double /* rate */)>(\"invoke\");\n      method(self(), rate);\n    }\n  };\n\n  /**\n   * An implementation of Func_void_double that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_double_cxx final: public jni::HybridClass<JFunc_void_double_cxx, JFunc_void_double> {\n  public:\n    static jni::local_ref<JFunc_void_double::javaobject> fromCpp(const std::function<void(double /* rate */)>& func) {\n      return JFunc_void_double_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_double_cxx` instance holds.\n     */\n    void invoke_cxx(double rate) {\n      _func(rate);\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(double /* rate */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_double_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_double_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_double_cxx(const std::function<void(double /* rate */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(double /* rate */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_onLoadData.hpp",
    "content": "///\n/// JFunc_void_onLoadData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include \"onLoadData.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JonLoadData.hpp\"\n#include \"VideoOrientation.hpp\"\n#include \"JVideoOrientation.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(data: onLoadData) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_onLoadData: public jni::JavaClass<JFunc_void_onLoadData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onLoadData;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_onLoadData` instance holds through JNI.\n     */\n    void invoke(const onLoadData& data) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JonLoadData> /* data */)>(\"invoke\");\n      method(self(), JonLoadData::fromCpp(data));\n    }\n  };\n\n  /**\n   * An implementation of Func_void_onLoadData that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_onLoadData_cxx final: public jni::HybridClass<JFunc_void_onLoadData_cxx, JFunc_void_onLoadData> {\n  public:\n    static jni::local_ref<JFunc_void_onLoadData::javaobject> fromCpp(const std::function<void(const onLoadData& /* data */)>& func) {\n      return JFunc_void_onLoadData_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_onLoadData_cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JonLoadData> data) {\n      _func(data->toCpp());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const onLoadData& /* data */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onLoadData_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_onLoadData_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_onLoadData_cxx(const std::function<void(const onLoadData& /* data */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const onLoadData& /* data */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_onLoadStartData.hpp",
    "content": "///\n/// JFunc_void_onLoadStartData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include \"onLoadStartData.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JonLoadStartData.hpp\"\n#include \"SourceType.hpp\"\n#include \"JSourceType.hpp\"\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(data: onLoadStartData) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_onLoadStartData: public jni::JavaClass<JFunc_void_onLoadStartData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onLoadStartData;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_onLoadStartData` instance holds through JNI.\n     */\n    void invoke(const onLoadStartData& data) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JonLoadStartData> /* data */)>(\"invoke\");\n      method(self(), JonLoadStartData::fromCpp(data));\n    }\n  };\n\n  /**\n   * An implementation of Func_void_onLoadStartData that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_onLoadStartData_cxx final: public jni::HybridClass<JFunc_void_onLoadStartData_cxx, JFunc_void_onLoadStartData> {\n  public:\n    static jni::local_ref<JFunc_void_onLoadStartData::javaobject> fromCpp(const std::function<void(const onLoadStartData& /* data */)>& func) {\n      return JFunc_void_onLoadStartData_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_onLoadStartData_cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JonLoadStartData> data) {\n      _func(data->toCpp());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const onLoadStartData& /* data */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onLoadStartData_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_onLoadStartData_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_onLoadStartData_cxx(const std::function<void(const onLoadStartData& /* data */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const onLoadStartData& /* data */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_onPlaybackStateChangeData.hpp",
    "content": "///\n/// JFunc_void_onPlaybackStateChangeData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include \"onPlaybackStateChangeData.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JonPlaybackStateChangeData.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(data: onPlaybackStateChangeData) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_onPlaybackStateChangeData: public jni::JavaClass<JFunc_void_onPlaybackStateChangeData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onPlaybackStateChangeData;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_onPlaybackStateChangeData` instance holds through JNI.\n     */\n    void invoke(const onPlaybackStateChangeData& data) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JonPlaybackStateChangeData> /* data */)>(\"invoke\");\n      method(self(), JonPlaybackStateChangeData::fromCpp(data));\n    }\n  };\n\n  /**\n   * An implementation of Func_void_onPlaybackStateChangeData that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_onPlaybackStateChangeData_cxx final: public jni::HybridClass<JFunc_void_onPlaybackStateChangeData_cxx, JFunc_void_onPlaybackStateChangeData> {\n  public:\n    static jni::local_ref<JFunc_void_onPlaybackStateChangeData::javaobject> fromCpp(const std::function<void(const onPlaybackStateChangeData& /* data */)>& func) {\n      return JFunc_void_onPlaybackStateChangeData_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_onPlaybackStateChangeData_cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JonPlaybackStateChangeData> data) {\n      _func(data->toCpp());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const onPlaybackStateChangeData& /* data */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onPlaybackStateChangeData_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_onPlaybackStateChangeData_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_onPlaybackStateChangeData_cxx(const std::function<void(const onPlaybackStateChangeData& /* data */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const onPlaybackStateChangeData& /* data */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_onProgressData.hpp",
    "content": "///\n/// JFunc_void_onProgressData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include \"onProgressData.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JonProgressData.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(data: onProgressData) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_onProgressData: public jni::JavaClass<JFunc_void_onProgressData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onProgressData;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_onProgressData` instance holds through JNI.\n     */\n    void invoke(const onProgressData& data) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JonProgressData> /* data */)>(\"invoke\");\n      method(self(), JonProgressData::fromCpp(data));\n    }\n  };\n\n  /**\n   * An implementation of Func_void_onProgressData that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_onProgressData_cxx final: public jni::HybridClass<JFunc_void_onProgressData_cxx, JFunc_void_onProgressData> {\n  public:\n    static jni::local_ref<JFunc_void_onProgressData::javaobject> fromCpp(const std::function<void(const onProgressData& /* data */)>& func) {\n      return JFunc_void_onProgressData_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_onProgressData_cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JonProgressData> data) {\n      _func(data->toCpp());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const onProgressData& /* data */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onProgressData_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_onProgressData_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_onProgressData_cxx(const std::function<void(const onProgressData& /* data */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const onProgressData& /* data */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_onVolumeChangeData.hpp",
    "content": "///\n/// JFunc_void_onVolumeChangeData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include \"onVolumeChangeData.hpp\"\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JonVolumeChangeData.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(data: onVolumeChangeData) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_onVolumeChangeData: public jni::JavaClass<JFunc_void_onVolumeChangeData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onVolumeChangeData;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_onVolumeChangeData` instance holds through JNI.\n     */\n    void invoke(const onVolumeChangeData& data) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JonVolumeChangeData> /* data */)>(\"invoke\");\n      method(self(), JonVolumeChangeData::fromCpp(data));\n    }\n  };\n\n  /**\n   * An implementation of Func_void_onVolumeChangeData that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_onVolumeChangeData_cxx final: public jni::HybridClass<JFunc_void_onVolumeChangeData_cxx, JFunc_void_onVolumeChangeData> {\n  public:\n    static jni::local_ref<JFunc_void_onVolumeChangeData::javaobject> fromCpp(const std::function<void(const onVolumeChangeData& /* data */)>& func) {\n      return JFunc_void_onVolumeChangeData_cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_onVolumeChangeData_cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JonVolumeChangeData> data) {\n      _func(data->toCpp());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const onVolumeChangeData& /* data */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_onVolumeChangeData_cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_onVolumeChangeData_cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_onVolumeChangeData_cxx(const std::function<void(const onVolumeChangeData& /* data */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const onVolumeChangeData& /* data */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__.hpp",
    "content": "///\n/// JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include <NitroModules/Null.hpp>\n#include \"TextTrack.hpp\"\n#include <variant>\n#include <optional>\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n#include \"JVariant_NullType_TextTrack.hpp\"\n#include <NitroModules/JNull.hpp>\n#include \"JTextTrack.hpp\"\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(track: Variant_NullType_TextTrack?) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__: public jni::JavaClass<JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_std__optional_std__variant_nitro__NullType__TextTrack__;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__` instance holds through JNI.\n     */\n    void invoke(const std::optional<std::variant<nitro::NullType, TextTrack>>& track) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JVariant_NullType_TextTrack> /* track */)>(\"invoke\");\n      method(self(), track.has_value() ? JVariant_NullType_TextTrack::fromCpp(track.value()) : nullptr);\n    }\n  };\n\n  /**\n   * An implementation of Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx final: public jni::HybridClass<JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx, JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__> {\n  public:\n    static jni::local_ref<JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__::javaobject> fromCpp(const std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>& func) {\n      return JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<JVariant_NullType_TextTrack> track) {\n      _func(track != nullptr ? std::make_optional(track->toCpp()) : std::nullopt);\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx(const std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JFunc_void_std__vector_std__string_.hpp",
    "content": "///\n/// JFunc_void_std__vector_std__string_.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <functional>\n\n#include <string>\n#include <vector>\n#include <functional>\n#include <NitroModules/JNICallable.hpp>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * Represents the Java/Kotlin callback `(data: Array<String>) -> Unit`.\n   * This can be passed around between C++ and Java/Kotlin.\n   */\n  struct JFunc_void_std__vector_std__string_: public jni::JavaClass<JFunc_void_std__vector_std__string_> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_std__vector_std__string_;\";\n\n  public:\n    /**\n     * Invokes the function this `JFunc_void_std__vector_std__string_` instance holds through JNI.\n     */\n    void invoke(const std::vector<std::string>& data) const {\n      static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<jni::JArrayClass<jni::JString>> /* data */)>(\"invoke\");\n      method(self(), [&]() {\n        size_t __size = data.size();\n        jni::local_ref<jni::JArrayClass<jni::JString>> __array = jni::JArrayClass<jni::JString>::newArray(__size);\n        for (size_t __i = 0; __i < __size; __i++) {\n          const auto& __element = data[__i];\n          auto __elementJni = jni::make_jstring(__element);\n          __array->setElement(__i, *__elementJni);\n        }\n        return __array;\n      }());\n    }\n  };\n\n  /**\n   * An implementation of Func_void_std__vector_std__string_ that is backed by a C++ implementation (using `std::function<...>`)\n   */\n  class JFunc_void_std__vector_std__string__cxx final: public jni::HybridClass<JFunc_void_std__vector_std__string__cxx, JFunc_void_std__vector_std__string_> {\n  public:\n    static jni::local_ref<JFunc_void_std__vector_std__string_::javaobject> fromCpp(const std::function<void(const std::vector<std::string>& /* data */)>& func) {\n      return JFunc_void_std__vector_std__string__cxx::newObjectCxxArgs(func);\n    }\n\n  public:\n    /**\n     * Invokes the C++ `std::function<...>` this `JFunc_void_std__vector_std__string__cxx` instance holds.\n     */\n    void invoke_cxx(jni::alias_ref<jni::JArrayClass<jni::JString>> data) {\n      _func([&]() {\n              size_t __size = data->size();\n              std::vector<std::string> __vector;\n              __vector.reserve(__size);\n              for (size_t __i = 0; __i < __size; __i++) {\n                auto __element = data->getElement(__i);\n                __vector.push_back(__element->toStdString());\n              }\n              return __vector;\n            }());\n    }\n\n  public:\n    [[nodiscard]]\n    inline const std::function<void(const std::vector<std::string>& /* data */)>& getFunction() const {\n      return _func;\n    }\n\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Func_void_std__vector_std__string__cxx;\";\n    static void registerNatives() {\n      registerHybrid({makeNativeMethod(\"invoke_cxx\", JFunc_void_std__vector_std__string__cxx::invoke_cxx)});\n    }\n\n  private:\n    explicit JFunc_void_std__vector_std__string__cxx(const std::function<void(const std::vector<std::string>& /* data */)>& func): _func(func) { }\n\n  private:\n    friend HybridBase;\n    std::function<void(const std::vector<std::string>& /* data */)> _func;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.cpp",
    "content": "///\n/// JHybridVideoPlayerEventEmitterSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JHybridVideoPlayerEventEmitterSpec.hpp\"\n\n// Forward declaration of `ListenerSubscription` to properly resolve imports.\nnamespace margelo::nitro::video { struct ListenerSubscription; }\n// Forward declaration of `BandwidthData` to properly resolve imports.\nnamespace margelo::nitro::video { struct BandwidthData; }\n// Forward declaration of `onLoadData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadData; }\n// Forward declaration of `VideoOrientation` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoOrientation; }\n// Forward declaration of `onLoadStartData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadStartData; }\n// Forward declaration of `SourceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SourceType; }\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onPlaybackStateChangeData; }\n// Forward declaration of `onProgressData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onProgressData; }\n// Forward declaration of `VideoPlayerStatus` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoPlayerStatus; }\n// Forward declaration of `TimedMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadata; }\n// Forward declaration of `TimedMetadataObject` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadataObject; }\n// Forward declaration of `TextTrack` to properly resolve imports.\nnamespace margelo::nitro::video { struct TextTrack; }\n// Forward declaration of `onVolumeChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onVolumeChangeData; }\n\n#include \"ListenerSubscription.hpp\"\n#include \"JListenerSubscription.hpp\"\n#include <functional>\n#include \"JFunc_void.hpp\"\n#include <NitroModules/JNICallable.hpp>\n#include \"JFunc_void_bool.hpp\"\n#include \"BandwidthData.hpp\"\n#include \"JFunc_void_BandwidthData.hpp\"\n#include \"JBandwidthData.hpp\"\n#include <optional>\n#include \"onLoadData.hpp\"\n#include \"JFunc_void_onLoadData.hpp\"\n#include \"JonLoadData.hpp\"\n#include \"VideoOrientation.hpp\"\n#include \"JVideoOrientation.hpp\"\n#include \"onLoadStartData.hpp\"\n#include \"JFunc_void_onLoadStartData.hpp\"\n#include \"JonLoadStartData.hpp\"\n#include \"SourceType.hpp\"\n#include \"JSourceType.hpp\"\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n#include \"onPlaybackStateChangeData.hpp\"\n#include \"JFunc_void_onPlaybackStateChangeData.hpp\"\n#include \"JonPlaybackStateChangeData.hpp\"\n#include \"JFunc_void_double.hpp\"\n#include \"onProgressData.hpp\"\n#include \"JFunc_void_onProgressData.hpp\"\n#include \"JonProgressData.hpp\"\n#include \"VideoPlayerStatus.hpp\"\n#include \"JFunc_void_VideoPlayerStatus.hpp\"\n#include \"JVideoPlayerStatus.hpp\"\n#include \"TimedMetadata.hpp\"\n#include \"JFunc_void_TimedMetadata.hpp\"\n#include \"JTimedMetadata.hpp\"\n#include \"TimedMetadataObject.hpp\"\n#include <vector>\n#include \"JTimedMetadataObject.hpp\"\n#include <string>\n#include \"JFunc_void_std__vector_std__string_.hpp\"\n#include <NitroModules/Null.hpp>\n#include \"TextTrack.hpp\"\n#include <variant>\n#include \"JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__.hpp\"\n#include \"JVariant_NullType_TextTrack.hpp\"\n#include <NitroModules/JNull.hpp>\n#include \"JTextTrack.hpp\"\n#include \"onVolumeChangeData.hpp\"\n#include \"JFunc_void_onVolumeChangeData.hpp\"\n#include \"JonVolumeChangeData.hpp\"\n\nnamespace margelo::nitro::video {\n\n  std::shared_ptr<JHybridVideoPlayerEventEmitterSpec> JHybridVideoPlayerEventEmitterSpec::JavaPart::getJHybridVideoPlayerEventEmitterSpec() {\n    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();\n    auto castHybridObject = std::dynamic_pointer_cast<JHybridVideoPlayerEventEmitterSpec>(hybridObject);\n    if (castHybridObject == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to downcast JHybridObject to JHybridVideoPlayerEventEmitterSpec!\");\n    }\n    return castHybridObject;\n  }\n\n  jni::local_ref<JHybridVideoPlayerEventEmitterSpec::CxxPart::jhybriddata> JHybridVideoPlayerEventEmitterSpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {\n    return makeCxxInstance(jThis);\n  }\n\n  std::shared_ptr<JHybridObject> JHybridVideoPlayerEventEmitterSpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {\n    auto castJavaPart = jni::dynamic_ref_cast<JHybridVideoPlayerEventEmitterSpec::JavaPart>(javaPart);\n    if (castJavaPart == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to cast JHybridObject::JavaPart to JHybridVideoPlayerEventEmitterSpec::JavaPart!\");\n    }\n    return std::make_shared<JHybridVideoPlayerEventEmitterSpec>(castJavaPart);\n  }\n\n  void JHybridVideoPlayerEventEmitterSpec::CxxPart::registerNatives() {\n    registerHybrid({\n      makeNativeMethod(\"initHybrid\", JHybridVideoPlayerEventEmitterSpec::CxxPart::initHybrid),\n    });\n  }\n\n  // Properties\n  \n\n  // Methods\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnAudioBecomingNoisyListener(const std::function<void()>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void::javaobject> /* listener */)>(\"addOnAudioBecomingNoisyListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnAudioFocusChangeListener(const std::function<void(bool /* hasAudioFocus */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_bool::javaobject> /* listener */)>(\"addOnAudioFocusChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_bool_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnBandwidthUpdateListener(const std::function<void(const BandwidthData& /* data */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_BandwidthData::javaobject> /* listener */)>(\"addOnBandwidthUpdateListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_BandwidthData_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnBufferListener(const std::function<void(bool /* buffering */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_bool::javaobject> /* listener */)>(\"addOnBufferListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_bool_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnControlsVisibleChangeListener(const std::function<void(bool /* visible */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_bool::javaobject> /* listener */)>(\"addOnControlsVisibleChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_bool_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnEndListener(const std::function<void()>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void::javaobject> /* listener */)>(\"addOnEndListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnExternalPlaybackChangeListener(const std::function<void(bool /* externalPlaybackActive */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_bool::javaobject> /* listener */)>(\"addOnExternalPlaybackChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_bool_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnLoadListener(const std::function<void(const onLoadData& /* data */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_onLoadData::javaobject> /* listener */)>(\"addOnLoadListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_onLoadData_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnLoadStartListener(const std::function<void(const onLoadStartData& /* data */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_onLoadStartData::javaobject> /* listener */)>(\"addOnLoadStartListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_onLoadStartData_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnPlaybackStateChangeListener(const std::function<void(const onPlaybackStateChangeData& /* data */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_onPlaybackStateChangeData::javaobject> /* listener */)>(\"addOnPlaybackStateChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_onPlaybackStateChangeData_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnPlaybackRateChangeListener(const std::function<void(double /* rate */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_double::javaobject> /* listener */)>(\"addOnPlaybackRateChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_double_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnProgressListener(const std::function<void(const onProgressData& /* data */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_onProgressData::javaobject> /* listener */)>(\"addOnProgressListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_onProgressData_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnReadyToDisplayListener(const std::function<void()>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void::javaobject> /* listener */)>(\"addOnReadyToDisplayListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnSeekListener(const std::function<void(double /* position */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_double::javaobject> /* listener */)>(\"addOnSeekListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_double_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnStatusChangeListener(const std::function<void(VideoPlayerStatus /* status */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_VideoPlayerStatus::javaobject> /* listener */)>(\"addOnStatusChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_VideoPlayerStatus_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnTimedMetadataListener(const std::function<void(const TimedMetadata& /* data */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_TimedMetadata::javaobject> /* listener */)>(\"addOnTimedMetadataListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_TimedMetadata_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnTextTrackDataChangedListener(const std::function<void(const std::vector<std::string>& /* data */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_std__vector_std__string_::javaobject> /* listener */)>(\"addOnTextTrackDataChangedListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_std__vector_std__string__cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnTrackChangeListener(const std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack__::javaobject> /* listener */)>(\"addOnTrackChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoPlayerEventEmitterSpec::addOnVolumeChangeListener(const std::function<void(const onVolumeChangeData& /* data */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_onVolumeChangeData::javaobject> /* listener */)>(\"addOnVolumeChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_onVolumeChangeData_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  void JHybridVideoPlayerEventEmitterSpec::clearAllListeners() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"clearAllListeners\");\n    method(_javaPart);\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerEventEmitterSpec.hpp",
    "content": "///\n/// HybridVideoPlayerEventEmitterSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <NitroModules/JHybridObject.hpp>\n#include <fbjni/fbjni.h>\n#include \"HybridVideoPlayerEventEmitterSpec.hpp\"\n\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  class JHybridVideoPlayerEventEmitterSpec: public virtual HybridVideoPlayerEventEmitterSpec, public virtual JHybridObject {\n  public:\n    struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerEventEmitterSpec;\";\n      std::shared_ptr<JHybridVideoPlayerEventEmitterSpec> getJHybridVideoPlayerEventEmitterSpec();\n    };\n    struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerEventEmitterSpec$CxxPart;\";\n      static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);\n      static void registerNatives();\n      using HybridBase::HybridBase;\n    protected:\n      std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;\n    };\n\n  public:\n    explicit JHybridVideoPlayerEventEmitterSpec(const jni::local_ref<JHybridVideoPlayerEventEmitterSpec::JavaPart>& javaPart):\n      HybridObject(HybridVideoPlayerEventEmitterSpec::TAG),\n      JHybridObject(javaPart),\n      _javaPart(jni::make_global(javaPart)) {}\n    ~JHybridVideoPlayerEventEmitterSpec() override {\n      // Hermes GC can destroy JS objects on a non-JNI Thread.\n      jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });\n    }\n\n  public:\n    inline const jni::global_ref<JHybridVideoPlayerEventEmitterSpec::JavaPart>& getJavaPart() const noexcept {\n      return _javaPart;\n    }\n\n  public:\n    // Properties\n    \n\n  public:\n    // Methods\n    ListenerSubscription addOnAudioBecomingNoisyListener(const std::function<void()>& listener) override;\n    ListenerSubscription addOnAudioFocusChangeListener(const std::function<void(bool /* hasAudioFocus */)>& listener) override;\n    ListenerSubscription addOnBandwidthUpdateListener(const std::function<void(const BandwidthData& /* data */)>& listener) override;\n    ListenerSubscription addOnBufferListener(const std::function<void(bool /* buffering */)>& listener) override;\n    ListenerSubscription addOnControlsVisibleChangeListener(const std::function<void(bool /* visible */)>& listener) override;\n    ListenerSubscription addOnEndListener(const std::function<void()>& listener) override;\n    ListenerSubscription addOnExternalPlaybackChangeListener(const std::function<void(bool /* externalPlaybackActive */)>& listener) override;\n    ListenerSubscription addOnLoadListener(const std::function<void(const onLoadData& /* data */)>& listener) override;\n    ListenerSubscription addOnLoadStartListener(const std::function<void(const onLoadStartData& /* data */)>& listener) override;\n    ListenerSubscription addOnPlaybackStateChangeListener(const std::function<void(const onPlaybackStateChangeData& /* data */)>& listener) override;\n    ListenerSubscription addOnPlaybackRateChangeListener(const std::function<void(double /* rate */)>& listener) override;\n    ListenerSubscription addOnProgressListener(const std::function<void(const onProgressData& /* data */)>& listener) override;\n    ListenerSubscription addOnReadyToDisplayListener(const std::function<void()>& listener) override;\n    ListenerSubscription addOnSeekListener(const std::function<void(double /* position */)>& listener) override;\n    ListenerSubscription addOnStatusChangeListener(const std::function<void(VideoPlayerStatus /* status */)>& listener) override;\n    ListenerSubscription addOnTimedMetadataListener(const std::function<void(const TimedMetadata& /* data */)>& listener) override;\n    ListenerSubscription addOnTextTrackDataChangedListener(const std::function<void(const std::vector<std::string>& /* data */)>& listener) override;\n    ListenerSubscription addOnTrackChangeListener(const std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>& listener) override;\n    ListenerSubscription addOnVolumeChangeListener(const std::function<void(const onVolumeChangeData& /* data */)>& listener) override;\n    void clearAllListeners() override;\n\n  private:\n    jni::global_ref<JHybridVideoPlayerEventEmitterSpec::JavaPart> _javaPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.cpp",
    "content": "///\n/// JHybridVideoPlayerFactorySpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JHybridVideoPlayerFactorySpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSpec; }\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n\n#include <memory>\n#include \"HybridVideoPlayerSpec.hpp\"\n#include \"JHybridVideoPlayerSpec.hpp\"\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  std::shared_ptr<JHybridVideoPlayerFactorySpec> JHybridVideoPlayerFactorySpec::JavaPart::getJHybridVideoPlayerFactorySpec() {\n    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();\n    auto castHybridObject = std::dynamic_pointer_cast<JHybridVideoPlayerFactorySpec>(hybridObject);\n    if (castHybridObject == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to downcast JHybridObject to JHybridVideoPlayerFactorySpec!\");\n    }\n    return castHybridObject;\n  }\n\n  jni::local_ref<JHybridVideoPlayerFactorySpec::CxxPart::jhybriddata> JHybridVideoPlayerFactorySpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {\n    return makeCxxInstance(jThis);\n  }\n\n  std::shared_ptr<JHybridObject> JHybridVideoPlayerFactorySpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {\n    auto castJavaPart = jni::dynamic_ref_cast<JHybridVideoPlayerFactorySpec::JavaPart>(javaPart);\n    if (castJavaPart == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to cast JHybridObject::JavaPart to JHybridVideoPlayerFactorySpec::JavaPart!\");\n    }\n    return std::make_shared<JHybridVideoPlayerFactorySpec>(castJavaPart);\n  }\n\n  void JHybridVideoPlayerFactorySpec::CxxPart::registerNatives() {\n    registerHybrid({\n      makeNativeMethod(\"initHybrid\", JHybridVideoPlayerFactorySpec::CxxPart::initHybrid),\n    });\n  }\n\n  // Properties\n  \n\n  // Methods\n  std::shared_ptr<HybridVideoPlayerSpec> JHybridVideoPlayerFactorySpec::createPlayer(const std::shared_ptr<HybridVideoPlayerSourceSpec>& source) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridVideoPlayerSpec::JavaPart>(jni::alias_ref<JHybridVideoPlayerSourceSpec::JavaPart> /* source */)>(\"createPlayer\");\n    auto __result = method(_javaPart, std::dynamic_pointer_cast<JHybridVideoPlayerSourceSpec>(source)->getJavaPart());\n    return __result->getJHybridVideoPlayerSpec();\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerFactorySpec.hpp",
    "content": "///\n/// HybridVideoPlayerFactorySpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <NitroModules/JHybridObject.hpp>\n#include <fbjni/fbjni.h>\n#include \"HybridVideoPlayerFactorySpec.hpp\"\n\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  class JHybridVideoPlayerFactorySpec: public virtual HybridVideoPlayerFactorySpec, public virtual JHybridObject {\n  public:\n    struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerFactorySpec;\";\n      std::shared_ptr<JHybridVideoPlayerFactorySpec> getJHybridVideoPlayerFactorySpec();\n    };\n    struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerFactorySpec$CxxPart;\";\n      static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);\n      static void registerNatives();\n      using HybridBase::HybridBase;\n    protected:\n      std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;\n    };\n\n  public:\n    explicit JHybridVideoPlayerFactorySpec(const jni::local_ref<JHybridVideoPlayerFactorySpec::JavaPart>& javaPart):\n      HybridObject(HybridVideoPlayerFactorySpec::TAG),\n      JHybridObject(javaPart),\n      _javaPart(jni::make_global(javaPart)) {}\n    ~JHybridVideoPlayerFactorySpec() override {\n      // Hermes GC can destroy JS objects on a non-JNI Thread.\n      jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });\n    }\n\n  public:\n    inline const jni::global_ref<JHybridVideoPlayerFactorySpec::JavaPart>& getJavaPart() const noexcept {\n      return _javaPart;\n    }\n\n  public:\n    // Properties\n    \n\n  public:\n    // Methods\n    std::shared_ptr<HybridVideoPlayerSpec> createPlayer(const std::shared_ptr<HybridVideoPlayerSourceSpec>& source) override;\n\n  private:\n    jni::global_ref<JHybridVideoPlayerFactorySpec::JavaPart> _javaPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.cpp",
    "content": "///\n/// JHybridVideoPlayerSourceFactorySpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JHybridVideoPlayerSourceFactorySpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `NativeVideoConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeVideoConfig; }\n// Forward declaration of `NativeExternalSubtitle` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeExternalSubtitle; }\n// Forward declaration of `SubtitleType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SubtitleType; }\n// Forward declaration of `NativeDrmParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeDrmParams; }\n// Forward declaration of `OnGetLicensePayload` to properly resolve imports.\nnamespace margelo::nitro::video { struct OnGetLicensePayload; }\n// Forward declaration of `BufferConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct BufferConfig; }\n// Forward declaration of `LivePlaybackParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct LivePlaybackParams; }\n// Forward declaration of `Resolution` to properly resolve imports.\nnamespace margelo::nitro::video { struct Resolution; }\n// Forward declaration of `CustomVideoMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct CustomVideoMetadata; }\n\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n#include <string>\n#include \"NativeVideoConfig.hpp\"\n#include \"JNativeVideoConfig.hpp\"\n#include \"NativeExternalSubtitle.hpp\"\n#include <vector>\n#include <optional>\n#include \"JNativeExternalSubtitle.hpp\"\n#include \"SubtitleType.hpp\"\n#include \"JSubtitleType.hpp\"\n#include \"NativeDrmParams.hpp\"\n#include \"JNativeDrmParams.hpp\"\n#include <unordered_map>\n#include <NitroModules/Promise.hpp>\n#include \"OnGetLicensePayload.hpp\"\n#include <functional>\n#include \"JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp\"\n#include <NitroModules/JNICallable.hpp>\n#include <NitroModules/JPromise.hpp>\n#include \"JOnGetLicensePayload.hpp\"\n#include \"BufferConfig.hpp\"\n#include \"JBufferConfig.hpp\"\n#include \"LivePlaybackParams.hpp\"\n#include \"JLivePlaybackParams.hpp\"\n#include \"Resolution.hpp\"\n#include \"JResolution.hpp\"\n#include \"CustomVideoMetadata.hpp\"\n#include \"JCustomVideoMetadata.hpp\"\n\nnamespace margelo::nitro::video {\n\n  std::shared_ptr<JHybridVideoPlayerSourceFactorySpec> JHybridVideoPlayerSourceFactorySpec::JavaPart::getJHybridVideoPlayerSourceFactorySpec() {\n    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();\n    auto castHybridObject = std::dynamic_pointer_cast<JHybridVideoPlayerSourceFactorySpec>(hybridObject);\n    if (castHybridObject == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to downcast JHybridObject to JHybridVideoPlayerSourceFactorySpec!\");\n    }\n    return castHybridObject;\n  }\n\n  jni::local_ref<JHybridVideoPlayerSourceFactorySpec::CxxPart::jhybriddata> JHybridVideoPlayerSourceFactorySpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {\n    return makeCxxInstance(jThis);\n  }\n\n  std::shared_ptr<JHybridObject> JHybridVideoPlayerSourceFactorySpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {\n    auto castJavaPart = jni::dynamic_ref_cast<JHybridVideoPlayerSourceFactorySpec::JavaPart>(javaPart);\n    if (castJavaPart == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to cast JHybridObject::JavaPart to JHybridVideoPlayerSourceFactorySpec::JavaPart!\");\n    }\n    return std::make_shared<JHybridVideoPlayerSourceFactorySpec>(castJavaPart);\n  }\n\n  void JHybridVideoPlayerSourceFactorySpec::CxxPart::registerNatives() {\n    registerHybrid({\n      makeNativeMethod(\"initHybrid\", JHybridVideoPlayerSourceFactorySpec::CxxPart::initHybrid),\n    });\n  }\n\n  // Properties\n  \n\n  // Methods\n  std::shared_ptr<HybridVideoPlayerSourceSpec> JHybridVideoPlayerSourceFactorySpec::fromUri(const std::string& uri) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridVideoPlayerSourceSpec::JavaPart>(jni::alias_ref<jni::JString> /* uri */)>(\"fromUri\");\n    auto __result = method(_javaPart, jni::make_jstring(uri));\n    return __result->getJHybridVideoPlayerSourceSpec();\n  }\n  std::shared_ptr<HybridVideoPlayerSourceSpec> JHybridVideoPlayerSourceFactorySpec::fromVideoConfig(const NativeVideoConfig& config) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridVideoPlayerSourceSpec::JavaPart>(jni::alias_ref<JNativeVideoConfig> /* config */)>(\"fromVideoConfig\");\n    auto __result = method(_javaPart, JNativeVideoConfig::fromCpp(config));\n    return __result->getJHybridVideoPlayerSourceSpec();\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerSourceFactorySpec.hpp",
    "content": "///\n/// HybridVideoPlayerSourceFactorySpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <NitroModules/JHybridObject.hpp>\n#include <fbjni/fbjni.h>\n#include \"HybridVideoPlayerSourceFactorySpec.hpp\"\n\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  class JHybridVideoPlayerSourceFactorySpec: public virtual HybridVideoPlayerSourceFactorySpec, public virtual JHybridObject {\n  public:\n    struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerSourceFactorySpec;\";\n      std::shared_ptr<JHybridVideoPlayerSourceFactorySpec> getJHybridVideoPlayerSourceFactorySpec();\n    };\n    struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerSourceFactorySpec$CxxPart;\";\n      static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);\n      static void registerNatives();\n      using HybridBase::HybridBase;\n    protected:\n      std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;\n    };\n\n  public:\n    explicit JHybridVideoPlayerSourceFactorySpec(const jni::local_ref<JHybridVideoPlayerSourceFactorySpec::JavaPart>& javaPart):\n      HybridObject(HybridVideoPlayerSourceFactorySpec::TAG),\n      JHybridObject(javaPart),\n      _javaPart(jni::make_global(javaPart)) {}\n    ~JHybridVideoPlayerSourceFactorySpec() override {\n      // Hermes GC can destroy JS objects on a non-JNI Thread.\n      jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });\n    }\n\n  public:\n    inline const jni::global_ref<JHybridVideoPlayerSourceFactorySpec::JavaPart>& getJavaPart() const noexcept {\n      return _javaPart;\n    }\n\n  public:\n    // Properties\n    \n\n  public:\n    // Methods\n    std::shared_ptr<HybridVideoPlayerSourceSpec> fromUri(const std::string& uri) override;\n    std::shared_ptr<HybridVideoPlayerSourceSpec> fromVideoConfig(const NativeVideoConfig& config) override;\n\n  private:\n    jni::global_ref<JHybridVideoPlayerSourceFactorySpec::JavaPart> _javaPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.cpp",
    "content": "///\n/// JHybridVideoPlayerSourceSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n\n// Forward declaration of `NativeVideoConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeVideoConfig; }\n// Forward declaration of `NativeExternalSubtitle` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeExternalSubtitle; }\n// Forward declaration of `SubtitleType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SubtitleType; }\n// Forward declaration of `NativeDrmParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeDrmParams; }\n// Forward declaration of `OnGetLicensePayload` to properly resolve imports.\nnamespace margelo::nitro::video { struct OnGetLicensePayload; }\n// Forward declaration of `BufferConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct BufferConfig; }\n// Forward declaration of `LivePlaybackParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct LivePlaybackParams; }\n// Forward declaration of `Resolution` to properly resolve imports.\nnamespace margelo::nitro::video { struct Resolution; }\n// Forward declaration of `CustomVideoMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct CustomVideoMetadata; }\n// Forward declaration of `VideoInformation` to properly resolve imports.\nnamespace margelo::nitro::video { struct VideoInformation; }\n// Forward declaration of `VideoOrientation` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoOrientation; }\n\n#include <string>\n#include \"NativeVideoConfig.hpp\"\n#include \"JNativeVideoConfig.hpp\"\n#include \"NativeExternalSubtitle.hpp\"\n#include <vector>\n#include <optional>\n#include \"JNativeExternalSubtitle.hpp\"\n#include \"SubtitleType.hpp\"\n#include \"JSubtitleType.hpp\"\n#include \"NativeDrmParams.hpp\"\n#include \"JNativeDrmParams.hpp\"\n#include <unordered_map>\n#include <NitroModules/Promise.hpp>\n#include \"OnGetLicensePayload.hpp\"\n#include <functional>\n#include \"JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp\"\n#include <NitroModules/JNICallable.hpp>\n#include <NitroModules/JPromise.hpp>\n#include \"JOnGetLicensePayload.hpp\"\n#include \"BufferConfig.hpp\"\n#include \"JBufferConfig.hpp\"\n#include \"LivePlaybackParams.hpp\"\n#include \"JLivePlaybackParams.hpp\"\n#include \"Resolution.hpp\"\n#include \"JResolution.hpp\"\n#include \"CustomVideoMetadata.hpp\"\n#include \"JCustomVideoMetadata.hpp\"\n#include \"VideoInformation.hpp\"\n#include \"JVideoInformation.hpp\"\n#include \"VideoOrientation.hpp\"\n#include \"JVideoOrientation.hpp\"\n\nnamespace margelo::nitro::video {\n\n  std::shared_ptr<JHybridVideoPlayerSourceSpec> JHybridVideoPlayerSourceSpec::JavaPart::getJHybridVideoPlayerSourceSpec() {\n    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();\n    auto castHybridObject = std::dynamic_pointer_cast<JHybridVideoPlayerSourceSpec>(hybridObject);\n    if (castHybridObject == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to downcast JHybridObject to JHybridVideoPlayerSourceSpec!\");\n    }\n    return castHybridObject;\n  }\n\n  jni::local_ref<JHybridVideoPlayerSourceSpec::CxxPart::jhybriddata> JHybridVideoPlayerSourceSpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {\n    return makeCxxInstance(jThis);\n  }\n\n  std::shared_ptr<JHybridObject> JHybridVideoPlayerSourceSpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {\n    auto castJavaPart = jni::dynamic_ref_cast<JHybridVideoPlayerSourceSpec::JavaPart>(javaPart);\n    if (castJavaPart == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to cast JHybridObject::JavaPart to JHybridVideoPlayerSourceSpec::JavaPart!\");\n    }\n    return std::make_shared<JHybridVideoPlayerSourceSpec>(castJavaPart);\n  }\n\n  void JHybridVideoPlayerSourceSpec::CxxPart::registerNatives() {\n    registerHybrid({\n      makeNativeMethod(\"initHybrid\", JHybridVideoPlayerSourceSpec::CxxPart::initHybrid),\n    });\n  }\n\n  // Properties\n  std::string JHybridVideoPlayerSourceSpec::getUri() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>(\"getUri\");\n    auto __result = method(_javaPart);\n    return __result->toStdString();\n  }\n  NativeVideoConfig JHybridVideoPlayerSourceSpec::getConfig() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JNativeVideoConfig>()>(\"getConfig\");\n    auto __result = method(_javaPart);\n    return __result->toCpp();\n  }\n\n  // Methods\n  std::shared_ptr<Promise<VideoInformation>> JHybridVideoPlayerSourceSpec::getAssetInformationAsync() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>(\"getAssetInformationAsync\");\n    auto __result = method(_javaPart);\n    return [&]() {\n      auto __promise = Promise<VideoInformation>::create();\n      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {\n        auto __result = jni::static_ref_cast<JVideoInformation>(__boxedResult);\n        __promise->resolve(__result->toCpp());\n      });\n      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {\n        jni::JniException __jniError(__throwable);\n        __promise->reject(std::make_exception_ptr(__jniError));\n      });\n      return __promise;\n    }();\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerSourceSpec.hpp",
    "content": "///\n/// HybridVideoPlayerSourceSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <NitroModules/JHybridObject.hpp>\n#include <fbjni/fbjni.h>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  class JHybridVideoPlayerSourceSpec: public virtual HybridVideoPlayerSourceSpec, public virtual JHybridObject {\n  public:\n    struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerSourceSpec;\";\n      std::shared_ptr<JHybridVideoPlayerSourceSpec> getJHybridVideoPlayerSourceSpec();\n    };\n    struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerSourceSpec$CxxPart;\";\n      static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);\n      static void registerNatives();\n      using HybridBase::HybridBase;\n    protected:\n      std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;\n    };\n\n  public:\n    explicit JHybridVideoPlayerSourceSpec(const jni::local_ref<JHybridVideoPlayerSourceSpec::JavaPart>& javaPart):\n      HybridObject(HybridVideoPlayerSourceSpec::TAG),\n      JHybridObject(javaPart),\n      _javaPart(jni::make_global(javaPart)) {}\n    ~JHybridVideoPlayerSourceSpec() override {\n      // Hermes GC can destroy JS objects on a non-JNI Thread.\n      jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });\n    }\n\n  public:\n    inline const jni::global_ref<JHybridVideoPlayerSourceSpec::JavaPart>& getJavaPart() const noexcept {\n      return _javaPart;\n    }\n\n  public:\n    // Properties\n    std::string getUri() override;\n    NativeVideoConfig getConfig() override;\n\n  public:\n    // Methods\n    std::shared_ptr<Promise<VideoInformation>> getAssetInformationAsync() override;\n\n  private:\n    jni::global_ref<JHybridVideoPlayerSourceSpec::JavaPart> _javaPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerSpec.cpp",
    "content": "///\n/// JHybridVideoPlayerSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JHybridVideoPlayerSpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; }\n// Forward declaration of `VideoPlayerStatus` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoPlayerStatus; }\n// Forward declaration of `MixAudioMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class MixAudioMode; }\n// Forward declaration of `IgnoreSilentSwitchMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class IgnoreSilentSwitchMode; }\n// Forward declaration of `TextTrack` to properly resolve imports.\nnamespace margelo::nitro::video { struct TextTrack; }\n\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n#include \"HybridVideoPlayerEventEmitterSpec.hpp\"\n#include \"JHybridVideoPlayerEventEmitterSpec.hpp\"\n#include \"VideoPlayerStatus.hpp\"\n#include \"JVideoPlayerStatus.hpp\"\n#include \"MixAudioMode.hpp\"\n#include \"JMixAudioMode.hpp\"\n#include \"IgnoreSilentSwitchMode.hpp\"\n#include \"JIgnoreSilentSwitchMode.hpp\"\n#include \"TextTrack.hpp\"\n#include <optional>\n#include \"JTextTrack.hpp\"\n#include <string>\n#include <NitroModules/Promise.hpp>\n#include <NitroModules/JPromise.hpp>\n#include <NitroModules/JUnit.hpp>\n#include <vector>\n#include <NitroModules/Null.hpp>\n#include <variant>\n#include \"JVariant_NullType_HybridVideoPlayerSourceSpec.hpp\"\n#include <NitroModules/JNull.hpp>\n#include \"JVariant_NullType_TextTrack.hpp\"\n\nnamespace margelo::nitro::video {\n\n  std::shared_ptr<JHybridVideoPlayerSpec> JHybridVideoPlayerSpec::JavaPart::getJHybridVideoPlayerSpec() {\n    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();\n    auto castHybridObject = std::dynamic_pointer_cast<JHybridVideoPlayerSpec>(hybridObject);\n    if (castHybridObject == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to downcast JHybridObject to JHybridVideoPlayerSpec!\");\n    }\n    return castHybridObject;\n  }\n\n  jni::local_ref<JHybridVideoPlayerSpec::CxxPart::jhybriddata> JHybridVideoPlayerSpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {\n    return makeCxxInstance(jThis);\n  }\n\n  std::shared_ptr<JHybridObject> JHybridVideoPlayerSpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {\n    auto castJavaPart = jni::dynamic_ref_cast<JHybridVideoPlayerSpec::JavaPart>(javaPart);\n    if (castJavaPart == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to cast JHybridObject::JavaPart to JHybridVideoPlayerSpec::JavaPart!\");\n    }\n    return std::make_shared<JHybridVideoPlayerSpec>(castJavaPart);\n  }\n\n  void JHybridVideoPlayerSpec::CxxPart::registerNatives() {\n    registerHybrid({\n      makeNativeMethod(\"initHybrid\", JHybridVideoPlayerSpec::CxxPart::initHybrid),\n    });\n  }\n\n  // Properties\n  std::shared_ptr<HybridVideoPlayerSourceSpec> JHybridVideoPlayerSpec::getSource() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridVideoPlayerSourceSpec::JavaPart>()>(\"getSource\");\n    auto __result = method(_javaPart);\n    return __result->getJHybridVideoPlayerSourceSpec();\n  }\n  std::shared_ptr<HybridVideoPlayerEventEmitterSpec> JHybridVideoPlayerSpec::getEventEmitter() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridVideoPlayerEventEmitterSpec::JavaPart>()>(\"getEventEmitter\");\n    auto __result = method(_javaPart);\n    return __result->getJHybridVideoPlayerEventEmitterSpec();\n  }\n  bool JHybridVideoPlayerSpec::getShowNotificationControls() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getShowNotificationControls\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoPlayerSpec::setShowNotificationControls(bool showNotificationControls) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* showNotificationControls */)>(\"setShowNotificationControls\");\n    method(_javaPart, showNotificationControls);\n  }\n  VideoPlayerStatus JHybridVideoPlayerSpec::getStatus() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JVideoPlayerStatus>()>(\"getStatus\");\n    auto __result = method(_javaPart);\n    return __result->toCpp();\n  }\n  double JHybridVideoPlayerSpec::getDuration() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<double()>(\"getDuration\");\n    auto __result = method(_javaPart);\n    return __result;\n  }\n  double JHybridVideoPlayerSpec::getVolume() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<double()>(\"getVolume\");\n    auto __result = method(_javaPart);\n    return __result;\n  }\n  void JHybridVideoPlayerSpec::setVolume(double volume) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(double /* volume */)>(\"setVolume\");\n    method(_javaPart, volume);\n  }\n  double JHybridVideoPlayerSpec::getCurrentTime() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<double()>(\"getCurrentTime\");\n    auto __result = method(_javaPart);\n    return __result;\n  }\n  void JHybridVideoPlayerSpec::setCurrentTime(double currentTime) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(double /* currentTime */)>(\"setCurrentTime\");\n    method(_javaPart, currentTime);\n  }\n  bool JHybridVideoPlayerSpec::getMuted() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getMuted\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoPlayerSpec::setMuted(bool muted) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* muted */)>(\"setMuted\");\n    method(_javaPart, muted);\n  }\n  bool JHybridVideoPlayerSpec::getLoop() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getLoop\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoPlayerSpec::setLoop(bool loop) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* loop */)>(\"setLoop\");\n    method(_javaPart, loop);\n  }\n  double JHybridVideoPlayerSpec::getRate() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<double()>(\"getRate\");\n    auto __result = method(_javaPart);\n    return __result;\n  }\n  void JHybridVideoPlayerSpec::setRate(double rate) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(double /* rate */)>(\"setRate\");\n    method(_javaPart, rate);\n  }\n  MixAudioMode JHybridVideoPlayerSpec::getMixAudioMode() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JMixAudioMode>()>(\"getMixAudioMode\");\n    auto __result = method(_javaPart);\n    return __result->toCpp();\n  }\n  void JHybridVideoPlayerSpec::setMixAudioMode(MixAudioMode mixAudioMode) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JMixAudioMode> /* mixAudioMode */)>(\"setMixAudioMode\");\n    method(_javaPart, JMixAudioMode::fromCpp(mixAudioMode));\n  }\n  IgnoreSilentSwitchMode JHybridVideoPlayerSpec::getIgnoreSilentSwitchMode() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JIgnoreSilentSwitchMode>()>(\"getIgnoreSilentSwitchMode\");\n    auto __result = method(_javaPart);\n    return __result->toCpp();\n  }\n  void JHybridVideoPlayerSpec::setIgnoreSilentSwitchMode(IgnoreSilentSwitchMode ignoreSilentSwitchMode) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JIgnoreSilentSwitchMode> /* ignoreSilentSwitchMode */)>(\"setIgnoreSilentSwitchMode\");\n    method(_javaPart, JIgnoreSilentSwitchMode::fromCpp(ignoreSilentSwitchMode));\n  }\n  bool JHybridVideoPlayerSpec::getPlayInBackground() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getPlayInBackground\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoPlayerSpec::setPlayInBackground(bool playInBackground) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* playInBackground */)>(\"setPlayInBackground\");\n    method(_javaPart, playInBackground);\n  }\n  bool JHybridVideoPlayerSpec::getPlayWhenInactive() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getPlayWhenInactive\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoPlayerSpec::setPlayWhenInactive(bool playWhenInactive) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* playWhenInactive */)>(\"setPlayWhenInactive\");\n    method(_javaPart, playWhenInactive);\n  }\n  bool JHybridVideoPlayerSpec::getIsPlaying() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"isPlaying\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  std::optional<TextTrack> JHybridVideoPlayerSpec::getSelectedTrack() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JTextTrack>()>(\"getSelectedTrack\");\n    auto __result = method(_javaPart);\n    return __result != nullptr ? std::make_optional(__result->toCpp()) : std::nullopt;\n  }\n\n  // Methods\n  std::shared_ptr<Promise<void>> JHybridVideoPlayerSpec::replaceSourceAsync(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& source) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<JVariant_NullType_HybridVideoPlayerSourceSpec> /* source */)>(\"replaceSourceAsync\");\n    auto __result = method(_javaPart, source.has_value() ? JVariant_NullType_HybridVideoPlayerSourceSpec::fromCpp(source.value()) : nullptr);\n    return [&]() {\n      auto __promise = Promise<void>::create();\n      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {\n        __promise->resolve();\n      });\n      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {\n        jni::JniException __jniError(__throwable);\n        __promise->reject(std::make_exception_ptr(__jniError));\n      });\n      return __promise;\n    }();\n  }\n  std::vector<TextTrack> JHybridVideoPlayerSpec::getAvailableTextTracks() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JArrayClass<JTextTrack>>()>(\"getAvailableTextTracks\");\n    auto __result = method(_javaPart);\n    return [&]() {\n      size_t __size = __result->size();\n      std::vector<TextTrack> __vector;\n      __vector.reserve(__size);\n      for (size_t __i = 0; __i < __size; __i++) {\n        auto __element = __result->getElement(__i);\n        __vector.push_back(__element->toCpp());\n      }\n      return __vector;\n    }();\n  }\n  void JHybridVideoPlayerSpec::selectTextTrack(const std::optional<std::variant<nitro::NullType, TextTrack>>& textTrack) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JVariant_NullType_TextTrack> /* textTrack */)>(\"selectTextTrack\");\n    method(_javaPart, textTrack.has_value() ? JVariant_NullType_TextTrack::fromCpp(textTrack.value()) : nullptr);\n  }\n  void JHybridVideoPlayerSpec::release() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"release\");\n    method(_javaPart);\n  }\n  std::shared_ptr<Promise<void>> JHybridVideoPlayerSpec::initialize() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>(\"initialize\");\n    auto __result = method(_javaPart);\n    return [&]() {\n      auto __promise = Promise<void>::create();\n      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {\n        __promise->resolve();\n      });\n      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {\n        jni::JniException __jniError(__throwable);\n        __promise->reject(std::make_exception_ptr(__jniError));\n      });\n      return __promise;\n    }();\n  }\n  std::shared_ptr<Promise<void>> JHybridVideoPlayerSpec::preload() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>(\"preload\");\n    auto __result = method(_javaPart);\n    return [&]() {\n      auto __promise = Promise<void>::create();\n      __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& /* unit */) {\n        __promise->resolve();\n      });\n      __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {\n        jni::JniException __jniError(__throwable);\n        __promise->reject(std::make_exception_ptr(__jniError));\n      });\n      return __promise;\n    }();\n  }\n  void JHybridVideoPlayerSpec::play() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"play\");\n    method(_javaPart);\n  }\n  void JHybridVideoPlayerSpec::pause() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"pause\");\n    method(_javaPart);\n  }\n  void JHybridVideoPlayerSpec::seekBy(double time) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(double /* time */)>(\"seekBy\");\n    method(_javaPart, time);\n  }\n  void JHybridVideoPlayerSpec::seekTo(double time) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(double /* time */)>(\"seekTo\");\n    method(_javaPart, time);\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoPlayerSpec.hpp",
    "content": "///\n/// HybridVideoPlayerSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <NitroModules/JHybridObject.hpp>\n#include <fbjni/fbjni.h>\n#include \"HybridVideoPlayerSpec.hpp\"\n\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  class JHybridVideoPlayerSpec: public virtual HybridVideoPlayerSpec, public virtual JHybridObject {\n  public:\n    struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerSpec;\";\n      std::shared_ptr<JHybridVideoPlayerSpec> getJHybridVideoPlayerSpec();\n    };\n    struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoPlayerSpec$CxxPart;\";\n      static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);\n      static void registerNatives();\n      using HybridBase::HybridBase;\n    protected:\n      std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;\n    };\n\n  public:\n    explicit JHybridVideoPlayerSpec(const jni::local_ref<JHybridVideoPlayerSpec::JavaPart>& javaPart):\n      HybridObject(HybridVideoPlayerSpec::TAG),\n      JHybridObject(javaPart),\n      _javaPart(jni::make_global(javaPart)) {}\n    ~JHybridVideoPlayerSpec() override {\n      // Hermes GC can destroy JS objects on a non-JNI Thread.\n      jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });\n    }\n\n  public:\n    inline const jni::global_ref<JHybridVideoPlayerSpec::JavaPart>& getJavaPart() const noexcept {\n      return _javaPart;\n    }\n\n  public:\n    // Properties\n    std::shared_ptr<HybridVideoPlayerSourceSpec> getSource() override;\n    std::shared_ptr<HybridVideoPlayerEventEmitterSpec> getEventEmitter() override;\n    bool getShowNotificationControls() override;\n    void setShowNotificationControls(bool showNotificationControls) override;\n    VideoPlayerStatus getStatus() override;\n    double getDuration() override;\n    double getVolume() override;\n    void setVolume(double volume) override;\n    double getCurrentTime() override;\n    void setCurrentTime(double currentTime) override;\n    bool getMuted() override;\n    void setMuted(bool muted) override;\n    bool getLoop() override;\n    void setLoop(bool loop) override;\n    double getRate() override;\n    void setRate(double rate) override;\n    MixAudioMode getMixAudioMode() override;\n    void setMixAudioMode(MixAudioMode mixAudioMode) override;\n    IgnoreSilentSwitchMode getIgnoreSilentSwitchMode() override;\n    void setIgnoreSilentSwitchMode(IgnoreSilentSwitchMode ignoreSilentSwitchMode) override;\n    bool getPlayInBackground() override;\n    void setPlayInBackground(bool playInBackground) override;\n    bool getPlayWhenInactive() override;\n    void setPlayWhenInactive(bool playWhenInactive) override;\n    bool getIsPlaying() override;\n    std::optional<TextTrack> getSelectedTrack() override;\n\n  public:\n    // Methods\n    std::shared_ptr<Promise<void>> replaceSourceAsync(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& source) override;\n    std::vector<TextTrack> getAvailableTextTracks() override;\n    void selectTextTrack(const std::optional<std::variant<nitro::NullType, TextTrack>>& textTrack) override;\n    void release() override;\n    std::shared_ptr<Promise<void>> initialize() override;\n    std::shared_ptr<Promise<void>> preload() override;\n    void play() override;\n    void pause() override;\n    void seekBy(double time) override;\n    void seekTo(double time) override;\n\n  private:\n    jni::global_ref<JHybridVideoPlayerSpec::JavaPart> _javaPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.cpp",
    "content": "///\n/// JHybridVideoViewViewManagerFactorySpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JHybridVideoViewViewManagerFactorySpec.hpp\"\n\n// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; }\n\n#include <memory>\n#include \"HybridVideoViewViewManagerSpec.hpp\"\n#include \"JHybridVideoViewViewManagerSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  std::shared_ptr<JHybridVideoViewViewManagerFactorySpec> JHybridVideoViewViewManagerFactorySpec::JavaPart::getJHybridVideoViewViewManagerFactorySpec() {\n    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();\n    auto castHybridObject = std::dynamic_pointer_cast<JHybridVideoViewViewManagerFactorySpec>(hybridObject);\n    if (castHybridObject == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to downcast JHybridObject to JHybridVideoViewViewManagerFactorySpec!\");\n    }\n    return castHybridObject;\n  }\n\n  jni::local_ref<JHybridVideoViewViewManagerFactorySpec::CxxPart::jhybriddata> JHybridVideoViewViewManagerFactorySpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {\n    return makeCxxInstance(jThis);\n  }\n\n  std::shared_ptr<JHybridObject> JHybridVideoViewViewManagerFactorySpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {\n    auto castJavaPart = jni::dynamic_ref_cast<JHybridVideoViewViewManagerFactorySpec::JavaPart>(javaPart);\n    if (castJavaPart == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to cast JHybridObject::JavaPart to JHybridVideoViewViewManagerFactorySpec::JavaPart!\");\n    }\n    return std::make_shared<JHybridVideoViewViewManagerFactorySpec>(castJavaPart);\n  }\n\n  void JHybridVideoViewViewManagerFactorySpec::CxxPart::registerNatives() {\n    registerHybrid({\n      makeNativeMethod(\"initHybrid\", JHybridVideoViewViewManagerFactorySpec::CxxPart::initHybrid),\n    });\n  }\n\n  // Properties\n  \n\n  // Methods\n  std::shared_ptr<HybridVideoViewViewManagerSpec> JHybridVideoViewViewManagerFactorySpec::createViewManager(double nitroId) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridVideoViewViewManagerSpec::JavaPart>(double /* nitroId */)>(\"createViewManager\");\n    auto __result = method(_javaPart, nitroId);\n    return __result->getJHybridVideoViewViewManagerSpec();\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoViewViewManagerFactorySpec.hpp",
    "content": "///\n/// HybridVideoViewViewManagerFactorySpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <NitroModules/JHybridObject.hpp>\n#include <fbjni/fbjni.h>\n#include \"HybridVideoViewViewManagerFactorySpec.hpp\"\n\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  class JHybridVideoViewViewManagerFactorySpec: public virtual HybridVideoViewViewManagerFactorySpec, public virtual JHybridObject {\n  public:\n    struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoViewViewManagerFactorySpec;\";\n      std::shared_ptr<JHybridVideoViewViewManagerFactorySpec> getJHybridVideoViewViewManagerFactorySpec();\n    };\n    struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoViewViewManagerFactorySpec$CxxPart;\";\n      static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);\n      static void registerNatives();\n      using HybridBase::HybridBase;\n    protected:\n      std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;\n    };\n\n  public:\n    explicit JHybridVideoViewViewManagerFactorySpec(const jni::local_ref<JHybridVideoViewViewManagerFactorySpec::JavaPart>& javaPart):\n      HybridObject(HybridVideoViewViewManagerFactorySpec::TAG),\n      JHybridObject(javaPart),\n      _javaPart(jni::make_global(javaPart)) {}\n    ~JHybridVideoViewViewManagerFactorySpec() override {\n      // Hermes GC can destroy JS objects on a non-JNI Thread.\n      jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });\n    }\n\n  public:\n    inline const jni::global_ref<JHybridVideoViewViewManagerFactorySpec::JavaPart>& getJavaPart() const noexcept {\n      return _javaPart;\n    }\n\n  public:\n    // Properties\n    \n\n  public:\n    // Methods\n    std::shared_ptr<HybridVideoViewViewManagerSpec> createViewManager(double nitroId) override;\n\n  private:\n    jni::global_ref<JHybridVideoViewViewManagerFactorySpec::JavaPart> _javaPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.cpp",
    "content": "///\n/// JHybridVideoViewViewManagerSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JHybridVideoViewViewManagerSpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSpec; }\n// Forward declaration of `ResizeMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class ResizeMode; }\n// Forward declaration of `SurfaceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SurfaceType; }\n// Forward declaration of `ListenerSubscription` to properly resolve imports.\nnamespace margelo::nitro::video { struct ListenerSubscription; }\n\n#include <memory>\n#include \"HybridVideoPlayerSpec.hpp\"\n#include <optional>\n#include \"JHybridVideoPlayerSpec.hpp\"\n#include \"ResizeMode.hpp\"\n#include \"JResizeMode.hpp\"\n#include \"SurfaceType.hpp\"\n#include \"JSurfaceType.hpp\"\n#include \"ListenerSubscription.hpp\"\n#include \"JListenerSubscription.hpp\"\n#include <functional>\n#include \"JFunc_void.hpp\"\n#include <NitroModules/JNICallable.hpp>\n#include \"JFunc_void_bool.hpp\"\n\nnamespace margelo::nitro::video {\n\n  std::shared_ptr<JHybridVideoViewViewManagerSpec> JHybridVideoViewViewManagerSpec::JavaPart::getJHybridVideoViewViewManagerSpec() {\n    auto hybridObject = JHybridObject::JavaPart::getJHybridObject();\n    auto castHybridObject = std::dynamic_pointer_cast<JHybridVideoViewViewManagerSpec>(hybridObject);\n    if (castHybridObject == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to downcast JHybridObject to JHybridVideoViewViewManagerSpec!\");\n    }\n    return castHybridObject;\n  }\n\n  jni::local_ref<JHybridVideoViewViewManagerSpec::CxxPart::jhybriddata> JHybridVideoViewViewManagerSpec::CxxPart::initHybrid(jni::alias_ref<jhybridobject> jThis) {\n    return makeCxxInstance(jThis);\n  }\n\n  std::shared_ptr<JHybridObject> JHybridVideoViewViewManagerSpec::CxxPart::createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) {\n    auto castJavaPart = jni::dynamic_ref_cast<JHybridVideoViewViewManagerSpec::JavaPart>(javaPart);\n    if (castJavaPart == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Failed to cast JHybridObject::JavaPart to JHybridVideoViewViewManagerSpec::JavaPart!\");\n    }\n    return std::make_shared<JHybridVideoViewViewManagerSpec>(castJavaPart);\n  }\n\n  void JHybridVideoViewViewManagerSpec::CxxPart::registerNatives() {\n    registerHybrid({\n      makeNativeMethod(\"initHybrid\", JHybridVideoViewViewManagerSpec::CxxPart::initHybrid),\n    });\n  }\n\n  // Properties\n  std::optional<std::shared_ptr<HybridVideoPlayerSpec>> JHybridVideoViewViewManagerSpec::getPlayer() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JHybridVideoPlayerSpec::JavaPart>()>(\"getPlayer\");\n    auto __result = method(_javaPart);\n    return __result != nullptr ? std::make_optional(__result->getJHybridVideoPlayerSpec()) : std::nullopt;\n  }\n  void JHybridVideoViewViewManagerSpec::setPlayer(const std::optional<std::shared_ptr<HybridVideoPlayerSpec>>& player) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JHybridVideoPlayerSpec::JavaPart> /* player */)>(\"setPlayer\");\n    method(_javaPart, player.has_value() ? std::dynamic_pointer_cast<JHybridVideoPlayerSpec>(player.value())->getJavaPart() : nullptr);\n  }\n  bool JHybridVideoViewViewManagerSpec::getControls() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getControls\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoViewViewManagerSpec::setControls(bool controls) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* controls */)>(\"setControls\");\n    method(_javaPart, controls);\n  }\n  bool JHybridVideoViewViewManagerSpec::getPictureInPicture() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getPictureInPicture\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoViewViewManagerSpec::setPictureInPicture(bool pictureInPicture) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* pictureInPicture */)>(\"setPictureInPicture\");\n    method(_javaPart, pictureInPicture);\n  }\n  bool JHybridVideoViewViewManagerSpec::getAutoEnterPictureInPicture() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getAutoEnterPictureInPicture\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoViewViewManagerSpec::setAutoEnterPictureInPicture(bool autoEnterPictureInPicture) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* autoEnterPictureInPicture */)>(\"setAutoEnterPictureInPicture\");\n    method(_javaPart, autoEnterPictureInPicture);\n  }\n  ResizeMode JHybridVideoViewViewManagerSpec::getResizeMode() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JResizeMode>()>(\"getResizeMode\");\n    auto __result = method(_javaPart);\n    return __result->toCpp();\n  }\n  void JHybridVideoViewViewManagerSpec::setResizeMode(ResizeMode resizeMode) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JResizeMode> /* resizeMode */)>(\"setResizeMode\");\n    method(_javaPart, JResizeMode::fromCpp(resizeMode));\n  }\n  bool JHybridVideoViewViewManagerSpec::getKeepScreenAwake() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"getKeepScreenAwake\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  void JHybridVideoViewViewManagerSpec::setKeepScreenAwake(bool keepScreenAwake) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* keepScreenAwake */)>(\"setKeepScreenAwake\");\n    method(_javaPart, keepScreenAwake);\n  }\n  SurfaceType JHybridVideoViewViewManagerSpec::getSurfaceType() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JSurfaceType>()>(\"getSurfaceType\");\n    auto __result = method(_javaPart);\n    return __result->toCpp();\n  }\n  void JHybridVideoViewViewManagerSpec::setSurfaceType(SurfaceType surfaceType) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JSurfaceType> /* surfaceType */)>(\"setSurfaceType\");\n    method(_javaPart, JSurfaceType::fromCpp(surfaceType));\n  }\n\n  // Methods\n  void JHybridVideoViewViewManagerSpec::enterFullscreen() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"enterFullscreen\");\n    method(_javaPart);\n  }\n  void JHybridVideoViewViewManagerSpec::exitFullscreen() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"exitFullscreen\");\n    method(_javaPart);\n  }\n  void JHybridVideoViewViewManagerSpec::enterPictureInPicture() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"enterPictureInPicture\");\n    method(_javaPart);\n  }\n  void JHybridVideoViewViewManagerSpec::exitPictureInPicture() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"exitPictureInPicture\");\n    method(_javaPart);\n  }\n  bool JHybridVideoViewViewManagerSpec::canEnterPictureInPicture() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>(\"canEnterPictureInPicture\");\n    auto __result = method(_javaPart);\n    return static_cast<bool>(__result);\n  }\n  ListenerSubscription JHybridVideoViewViewManagerSpec::addOnPictureInPictureChangeListener(const std::function<void(bool /* isInPictureInPicture */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_bool::javaobject> /* listener */)>(\"addOnPictureInPictureChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_bool_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoViewViewManagerSpec::addOnFullscreenChangeListener(const std::function<void(bool /* fullscreen */)>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void_bool::javaobject> /* listener */)>(\"addOnFullscreenChangeListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_bool_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoViewViewManagerSpec::addWillEnterFullscreenListener(const std::function<void()>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void::javaobject> /* listener */)>(\"addWillEnterFullscreenListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoViewViewManagerSpec::addWillExitFullscreenListener(const std::function<void()>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void::javaobject> /* listener */)>(\"addWillExitFullscreenListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoViewViewManagerSpec::addWillEnterPictureInPictureListener(const std::function<void()>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void::javaobject> /* listener */)>(\"addWillEnterPictureInPictureListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  ListenerSubscription JHybridVideoViewViewManagerSpec::addWillExitPictureInPictureListener(const std::function<void()>& listener) {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JListenerSubscription>(jni::alias_ref<JFunc_void::javaobject> /* listener */)>(\"addWillExitPictureInPictureListener_cxx\");\n    auto __result = method(_javaPart, JFunc_void_cxx::fromCpp(listener));\n    return __result->toCpp();\n  }\n  void JHybridVideoViewViewManagerSpec::clearAllListeners() {\n    static const auto method = _javaPart->javaClassStatic()->getMethod<void()>(\"clearAllListeners\");\n    method(_javaPart);\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JHybridVideoViewViewManagerSpec.hpp",
    "content": "///\n/// HybridVideoViewViewManagerSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <NitroModules/JHybridObject.hpp>\n#include <fbjni/fbjni.h>\n#include \"HybridVideoViewViewManagerSpec.hpp\"\n\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  class JHybridVideoViewViewManagerSpec: public virtual HybridVideoViewViewManagerSpec, public virtual JHybridObject {\n  public:\n    struct JavaPart: public jni::JavaClass<JavaPart, JHybridObject::JavaPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoViewViewManagerSpec;\";\n      std::shared_ptr<JHybridVideoViewViewManagerSpec> getJHybridVideoViewViewManagerSpec();\n    };\n    struct CxxPart: public jni::HybridClass<CxxPart, JHybridObject::CxxPart> {\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/HybridVideoViewViewManagerSpec$CxxPart;\";\n      static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);\n      static void registerNatives();\n      using HybridBase::HybridBase;\n    protected:\n      std::shared_ptr<JHybridObject> createHybridObject(const jni::local_ref<JHybridObject::JavaPart>& javaPart) override;\n    };\n\n  public:\n    explicit JHybridVideoViewViewManagerSpec(const jni::local_ref<JHybridVideoViewViewManagerSpec::JavaPart>& javaPart):\n      HybridObject(HybridVideoViewViewManagerSpec::TAG),\n      JHybridObject(javaPart),\n      _javaPart(jni::make_global(javaPart)) {}\n    ~JHybridVideoViewViewManagerSpec() override {\n      // Hermes GC can destroy JS objects on a non-JNI Thread.\n      jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });\n    }\n\n  public:\n    inline const jni::global_ref<JHybridVideoViewViewManagerSpec::JavaPart>& getJavaPart() const noexcept {\n      return _javaPart;\n    }\n\n  public:\n    // Properties\n    std::optional<std::shared_ptr<HybridVideoPlayerSpec>> getPlayer() override;\n    void setPlayer(const std::optional<std::shared_ptr<HybridVideoPlayerSpec>>& player) override;\n    bool getControls() override;\n    void setControls(bool controls) override;\n    bool getPictureInPicture() override;\n    void setPictureInPicture(bool pictureInPicture) override;\n    bool getAutoEnterPictureInPicture() override;\n    void setAutoEnterPictureInPicture(bool autoEnterPictureInPicture) override;\n    ResizeMode getResizeMode() override;\n    void setResizeMode(ResizeMode resizeMode) override;\n    bool getKeepScreenAwake() override;\n    void setKeepScreenAwake(bool keepScreenAwake) override;\n    SurfaceType getSurfaceType() override;\n    void setSurfaceType(SurfaceType surfaceType) override;\n\n  public:\n    // Methods\n    void enterFullscreen() override;\n    void exitFullscreen() override;\n    void enterPictureInPicture() override;\n    void exitPictureInPicture() override;\n    bool canEnterPictureInPicture() override;\n    ListenerSubscription addOnPictureInPictureChangeListener(const std::function<void(bool /* isInPictureInPicture */)>& listener) override;\n    ListenerSubscription addOnFullscreenChangeListener(const std::function<void(bool /* fullscreen */)>& listener) override;\n    ListenerSubscription addWillEnterFullscreenListener(const std::function<void()>& listener) override;\n    ListenerSubscription addWillExitFullscreenListener(const std::function<void()>& listener) override;\n    ListenerSubscription addWillEnterPictureInPictureListener(const std::function<void()>& listener) override;\n    ListenerSubscription addWillExitPictureInPictureListener(const std::function<void()>& listener) override;\n    void clearAllListeners() override;\n\n  private:\n    jni::global_ref<JHybridVideoViewViewManagerSpec::JavaPart> _javaPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JIgnoreSilentSwitchMode.hpp",
    "content": "///\n/// JIgnoreSilentSwitchMode.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"IgnoreSilentSwitchMode.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ enum \"IgnoreSilentSwitchMode\" and the the Kotlin enum \"IgnoreSilentSwitchMode\".\n   */\n  struct JIgnoreSilentSwitchMode final: public jni::JavaClass<JIgnoreSilentSwitchMode> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/IgnoreSilentSwitchMode;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based enum to the C++ enum IgnoreSilentSwitchMode.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    IgnoreSilentSwitchMode toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldOrdinal = clazz->getField<int>(\"value\");\n      int ordinal = this->getFieldValue(fieldOrdinal);\n      return static_cast<IgnoreSilentSwitchMode>(ordinal);\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based enum with the given C++ enum's value.\n     */\n    [[maybe_unused]]\n    static jni::alias_ref<JIgnoreSilentSwitchMode> fromCpp(IgnoreSilentSwitchMode value) {\n      static const auto clazz = javaClassStatic();\n      switch (value) {\n        case IgnoreSilentSwitchMode::AUTO:\n          static const auto fieldAUTO = clazz->getStaticField<JIgnoreSilentSwitchMode>(\"AUTO\");\n          return clazz->getStaticFieldValue(fieldAUTO);\n        case IgnoreSilentSwitchMode::IGNORE:\n          static const auto fieldIGNORE = clazz->getStaticField<JIgnoreSilentSwitchMode>(\"IGNORE\");\n          return clazz->getStaticFieldValue(fieldIGNORE);\n        case IgnoreSilentSwitchMode::OBEY:\n          static const auto fieldOBEY = clazz->getStaticField<JIgnoreSilentSwitchMode>(\"OBEY\");\n          return clazz->getStaticFieldValue(fieldOBEY);\n        default:\n          std::string stringValue = std::to_string(static_cast<int>(value));\n          throw std::invalid_argument(\"Invalid enum value (\" + stringValue + \"!\");\n      }\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JListenerSubscription.hpp",
    "content": "///\n/// JListenerSubscription.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"ListenerSubscription.hpp\"\n\n#include \"JFunc_void.hpp\"\n#include <NitroModules/JNICallable.hpp>\n#include <functional>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"ListenerSubscription\" and the the Kotlin data class \"ListenerSubscription\".\n   */\n  struct JListenerSubscription final: public jni::JavaClass<JListenerSubscription> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/ListenerSubscription;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct ListenerSubscription by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    ListenerSubscription toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldRemove = clazz->getField<JFunc_void::javaobject>(\"remove\");\n      jni::local_ref<JFunc_void::javaobject> remove = this->getFieldValue(fieldRemove);\n      return ListenerSubscription(\n        [&]() -> std::function<void()> {\n          if (remove->isInstanceOf(JFunc_void_cxx::javaClassStatic())) [[likely]] {\n            auto downcast = jni::static_ref_cast<JFunc_void_cxx::javaobject>(remove);\n            return downcast->cthis()->getFunction();\n          } else {\n            auto removeRef = jni::make_global(remove);\n            return JNICallable<JFunc_void, void()>(std::move(removeRef));\n          }\n        }()\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JListenerSubscription::javaobject> fromCpp(const ListenerSubscription& value) {\n      using JSignature = JListenerSubscription(jni::alias_ref<JFunc_void::javaobject>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        JFunc_void_cxx::fromCpp(value.remove)\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JLivePlaybackParams.hpp",
    "content": "///\n/// JLivePlaybackParams.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"LivePlaybackParams.hpp\"\n\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"LivePlaybackParams\" and the the Kotlin data class \"LivePlaybackParams\".\n   */\n  struct JLivePlaybackParams final: public jni::JavaClass<JLivePlaybackParams> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/LivePlaybackParams;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct LivePlaybackParams by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    LivePlaybackParams toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldMinPlaybackSpeed = clazz->getField<jni::JDouble>(\"minPlaybackSpeed\");\n      jni::local_ref<jni::JDouble> minPlaybackSpeed = this->getFieldValue(fieldMinPlaybackSpeed);\n      static const auto fieldMaxPlaybackSpeed = clazz->getField<jni::JDouble>(\"maxPlaybackSpeed\");\n      jni::local_ref<jni::JDouble> maxPlaybackSpeed = this->getFieldValue(fieldMaxPlaybackSpeed);\n      static const auto fieldMaxOffsetMs = clazz->getField<jni::JDouble>(\"maxOffsetMs\");\n      jni::local_ref<jni::JDouble> maxOffsetMs = this->getFieldValue(fieldMaxOffsetMs);\n      static const auto fieldMinOffsetMs = clazz->getField<jni::JDouble>(\"minOffsetMs\");\n      jni::local_ref<jni::JDouble> minOffsetMs = this->getFieldValue(fieldMinOffsetMs);\n      static const auto fieldTargetOffsetMs = clazz->getField<jni::JDouble>(\"targetOffsetMs\");\n      jni::local_ref<jni::JDouble> targetOffsetMs = this->getFieldValue(fieldTargetOffsetMs);\n      return LivePlaybackParams(\n        minPlaybackSpeed != nullptr ? std::make_optional(minPlaybackSpeed->value()) : std::nullopt,\n        maxPlaybackSpeed != nullptr ? std::make_optional(maxPlaybackSpeed->value()) : std::nullopt,\n        maxOffsetMs != nullptr ? std::make_optional(maxOffsetMs->value()) : std::nullopt,\n        minOffsetMs != nullptr ? std::make_optional(minOffsetMs->value()) : std::nullopt,\n        targetOffsetMs != nullptr ? std::make_optional(targetOffsetMs->value()) : std::nullopt\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JLivePlaybackParams::javaobject> fromCpp(const LivePlaybackParams& value) {\n      using JSignature = JLivePlaybackParams(jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JDouble>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.minPlaybackSpeed.has_value() ? jni::JDouble::valueOf(value.minPlaybackSpeed.value()) : nullptr,\n        value.maxPlaybackSpeed.has_value() ? jni::JDouble::valueOf(value.maxPlaybackSpeed.value()) : nullptr,\n        value.maxOffsetMs.has_value() ? jni::JDouble::valueOf(value.maxOffsetMs.value()) : nullptr,\n        value.minOffsetMs.has_value() ? jni::JDouble::valueOf(value.minOffsetMs.value()) : nullptr,\n        value.targetOffsetMs.has_value() ? jni::JDouble::valueOf(value.targetOffsetMs.value()) : nullptr\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JMixAudioMode.hpp",
    "content": "///\n/// JMixAudioMode.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"MixAudioMode.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ enum \"MixAudioMode\" and the the Kotlin enum \"MixAudioMode\".\n   */\n  struct JMixAudioMode final: public jni::JavaClass<JMixAudioMode> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/MixAudioMode;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based enum to the C++ enum MixAudioMode.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    MixAudioMode toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldOrdinal = clazz->getField<int>(\"value\");\n      int ordinal = this->getFieldValue(fieldOrdinal);\n      return static_cast<MixAudioMode>(ordinal);\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based enum with the given C++ enum's value.\n     */\n    [[maybe_unused]]\n    static jni::alias_ref<JMixAudioMode> fromCpp(MixAudioMode value) {\n      static const auto clazz = javaClassStatic();\n      switch (value) {\n        case MixAudioMode::MIXWITHOTHERS:\n          static const auto fieldMIXWITHOTHERS = clazz->getStaticField<JMixAudioMode>(\"MIXWITHOTHERS\");\n          return clazz->getStaticFieldValue(fieldMIXWITHOTHERS);\n        case MixAudioMode::DONOTMIX:\n          static const auto fieldDONOTMIX = clazz->getStaticField<JMixAudioMode>(\"DONOTMIX\");\n          return clazz->getStaticFieldValue(fieldDONOTMIX);\n        case MixAudioMode::DUCKOTHERS:\n          static const auto fieldDUCKOTHERS = clazz->getStaticField<JMixAudioMode>(\"DUCKOTHERS\");\n          return clazz->getStaticFieldValue(fieldDUCKOTHERS);\n        case MixAudioMode::AUTO:\n          static const auto fieldAUTO = clazz->getStaticField<JMixAudioMode>(\"AUTO\");\n          return clazz->getStaticFieldValue(fieldAUTO);\n        default:\n          std::string stringValue = std::to_string(static_cast<int>(value));\n          throw std::invalid_argument(\"Invalid enum value (\" + stringValue + \"!\");\n      }\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JNativeDrmParams.hpp",
    "content": "///\n/// JNativeDrmParams.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"NativeDrmParams.hpp\"\n\n#include \"JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp\"\n#include \"JOnGetLicensePayload.hpp\"\n#include \"OnGetLicensePayload.hpp\"\n#include <NitroModules/JNICallable.hpp>\n#include <NitroModules/JPromise.hpp>\n#include <NitroModules/Promise.hpp>\n#include <functional>\n#include <optional>\n#include <string>\n#include <unordered_map>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"NativeDrmParams\" and the the Kotlin data class \"NativeDrmParams\".\n   */\n  struct JNativeDrmParams final: public jni::JavaClass<JNativeDrmParams> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/NativeDrmParams;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct NativeDrmParams by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    NativeDrmParams toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldType = clazz->getField<jni::JString>(\"type\");\n      jni::local_ref<jni::JString> type = this->getFieldValue(fieldType);\n      static const auto fieldLicenseUrl = clazz->getField<jni::JString>(\"licenseUrl\");\n      jni::local_ref<jni::JString> licenseUrl = this->getFieldValue(fieldLicenseUrl);\n      static const auto fieldCertificateUrl = clazz->getField<jni::JString>(\"certificateUrl\");\n      jni::local_ref<jni::JString> certificateUrl = this->getFieldValue(fieldCertificateUrl);\n      static const auto fieldContentId = clazz->getField<jni::JString>(\"contentId\");\n      jni::local_ref<jni::JString> contentId = this->getFieldValue(fieldContentId);\n      static const auto fieldLicenseHeaders = clazz->getField<jni::JMap<jni::JString, jni::JString>>(\"licenseHeaders\");\n      jni::local_ref<jni::JMap<jni::JString, jni::JString>> licenseHeaders = this->getFieldValue(fieldLicenseHeaders);\n      static const auto fieldMultiSession = clazz->getField<jni::JBoolean>(\"multiSession\");\n      jni::local_ref<jni::JBoolean> multiSession = this->getFieldValue(fieldMultiSession);\n      static const auto fieldGetLicense = clazz->getField<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload::javaobject>(\"getLicense\");\n      jni::local_ref<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload::javaobject> getLicense = this->getFieldValue(fieldGetLicense);\n      return NativeDrmParams(\n        type != nullptr ? std::make_optional(type->toStdString()) : std::nullopt,\n        licenseUrl != nullptr ? std::make_optional(licenseUrl->toStdString()) : std::nullopt,\n        certificateUrl != nullptr ? std::make_optional(certificateUrl->toStdString()) : std::nullopt,\n        contentId != nullptr ? std::make_optional(contentId->toStdString()) : std::nullopt,\n        licenseHeaders != nullptr ? std::make_optional([&]() {\n          std::unordered_map<std::string, std::string> __map;\n          __map.reserve(licenseHeaders->size());\n          for (const auto& __entry : *licenseHeaders) {\n            __map.emplace(__entry.first->toStdString(), __entry.second->toStdString());\n          }\n          return __map;\n        }()) : std::nullopt,\n        multiSession != nullptr ? std::make_optional(static_cast<bool>(multiSession->value())) : std::nullopt,\n        getLicense != nullptr ? std::make_optional([&]() -> std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)> {\n          if (getLicense->isInstanceOf(JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::javaClassStatic())) [[likely]] {\n            auto downcast = jni::static_ref_cast<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::javaobject>(getLicense);\n            return downcast->cthis()->getFunction();\n          } else {\n            auto getLicenseRef = jni::make_global(getLicense);\n            return JNICallable<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload, std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(OnGetLicensePayload)>(std::move(getLicenseRef));\n          }\n        }()) : std::nullopt\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JNativeDrmParams::javaobject> fromCpp(const NativeDrmParams& value) {\n      using JSignature = JNativeDrmParams(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JMap<jni::JString, jni::JString>>, jni::alias_ref<jni::JBoolean>, jni::alias_ref<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload::javaobject>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.type.has_value() ? jni::make_jstring(value.type.value()) : nullptr,\n        value.licenseUrl.has_value() ? jni::make_jstring(value.licenseUrl.value()) : nullptr,\n        value.certificateUrl.has_value() ? jni::make_jstring(value.certificateUrl.value()) : nullptr,\n        value.contentId.has_value() ? jni::make_jstring(value.contentId.value()) : nullptr,\n        value.licenseHeaders.has_value() ? [&]() -> jni::local_ref<jni::JMap<jni::JString, jni::JString>> {\n          auto __map = jni::JHashMap<jni::JString, jni::JString>::create(value.licenseHeaders.value().size());\n          for (const auto& __entry : value.licenseHeaders.value()) {\n            __map->put(jni::make_jstring(__entry.first), jni::make_jstring(__entry.second));\n          }\n          return __map;\n        }() : nullptr,\n        value.multiSession.has_value() ? jni::JBoolean::valueOf(value.multiSession.value()) : nullptr,\n        value.getLicense.has_value() ? JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx::fromCpp(value.getLicense.value()) : nullptr\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JNativeExternalSubtitle.hpp",
    "content": "///\n/// JNativeExternalSubtitle.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"NativeExternalSubtitle.hpp\"\n\n#include \"JSubtitleType.hpp\"\n#include \"SubtitleType.hpp\"\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"NativeExternalSubtitle\" and the the Kotlin data class \"NativeExternalSubtitle\".\n   */\n  struct JNativeExternalSubtitle final: public jni::JavaClass<JNativeExternalSubtitle> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/NativeExternalSubtitle;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct NativeExternalSubtitle by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    NativeExternalSubtitle toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldUri = clazz->getField<jni::JString>(\"uri\");\n      jni::local_ref<jni::JString> uri = this->getFieldValue(fieldUri);\n      static const auto fieldLabel = clazz->getField<jni::JString>(\"label\");\n      jni::local_ref<jni::JString> label = this->getFieldValue(fieldLabel);\n      static const auto fieldType = clazz->getField<JSubtitleType>(\"type\");\n      jni::local_ref<JSubtitleType> type = this->getFieldValue(fieldType);\n      static const auto fieldLanguage = clazz->getField<jni::JString>(\"language\");\n      jni::local_ref<jni::JString> language = this->getFieldValue(fieldLanguage);\n      return NativeExternalSubtitle(\n        uri->toStdString(),\n        label->toStdString(),\n        type->toCpp(),\n        language->toStdString()\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JNativeExternalSubtitle::javaobject> fromCpp(const NativeExternalSubtitle& value) {\n      using JSignature = JNativeExternalSubtitle(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<JSubtitleType>, jni::alias_ref<jni::JString>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        jni::make_jstring(value.uri),\n        jni::make_jstring(value.label),\n        JSubtitleType::fromCpp(value.type),\n        jni::make_jstring(value.language)\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JNativeVideoConfig.hpp",
    "content": "///\n/// JNativeVideoConfig.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"NativeVideoConfig.hpp\"\n\n#include \"BufferConfig.hpp\"\n#include \"CustomVideoMetadata.hpp\"\n#include \"JBufferConfig.hpp\"\n#include \"JCustomVideoMetadata.hpp\"\n#include \"JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.hpp\"\n#include \"JLivePlaybackParams.hpp\"\n#include \"JNativeDrmParams.hpp\"\n#include \"JNativeExternalSubtitle.hpp\"\n#include \"JOnGetLicensePayload.hpp\"\n#include \"JResolution.hpp\"\n#include \"JSubtitleType.hpp\"\n#include \"LivePlaybackParams.hpp\"\n#include \"NativeDrmParams.hpp\"\n#include \"NativeExternalSubtitle.hpp\"\n#include \"OnGetLicensePayload.hpp\"\n#include \"Resolution.hpp\"\n#include \"SubtitleType.hpp\"\n#include <NitroModules/JNICallable.hpp>\n#include <NitroModules/JPromise.hpp>\n#include <NitroModules/Promise.hpp>\n#include <functional>\n#include <optional>\n#include <string>\n#include <unordered_map>\n#include <vector>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"NativeVideoConfig\" and the the Kotlin data class \"NativeVideoConfig\".\n   */\n  struct JNativeVideoConfig final: public jni::JavaClass<JNativeVideoConfig> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/NativeVideoConfig;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct NativeVideoConfig by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    NativeVideoConfig toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldUri = clazz->getField<jni::JString>(\"uri\");\n      jni::local_ref<jni::JString> uri = this->getFieldValue(fieldUri);\n      static const auto fieldExternalSubtitles = clazz->getField<jni::JArrayClass<JNativeExternalSubtitle>>(\"externalSubtitles\");\n      jni::local_ref<jni::JArrayClass<JNativeExternalSubtitle>> externalSubtitles = this->getFieldValue(fieldExternalSubtitles);\n      static const auto fieldDrm = clazz->getField<JNativeDrmParams>(\"drm\");\n      jni::local_ref<JNativeDrmParams> drm = this->getFieldValue(fieldDrm);\n      static const auto fieldHeaders = clazz->getField<jni::JMap<jni::JString, jni::JString>>(\"headers\");\n      jni::local_ref<jni::JMap<jni::JString, jni::JString>> headers = this->getFieldValue(fieldHeaders);\n      static const auto fieldBufferConfig = clazz->getField<JBufferConfig>(\"bufferConfig\");\n      jni::local_ref<JBufferConfig> bufferConfig = this->getFieldValue(fieldBufferConfig);\n      static const auto fieldMetadata = clazz->getField<JCustomVideoMetadata>(\"metadata\");\n      jni::local_ref<JCustomVideoMetadata> metadata = this->getFieldValue(fieldMetadata);\n      static const auto fieldInitializeOnCreation = clazz->getField<jni::JBoolean>(\"initializeOnCreation\");\n      jni::local_ref<jni::JBoolean> initializeOnCreation = this->getFieldValue(fieldInitializeOnCreation);\n      return NativeVideoConfig(\n        uri->toStdString(),\n        externalSubtitles != nullptr ? std::make_optional([&]() {\n          size_t __size = externalSubtitles->size();\n          std::vector<NativeExternalSubtitle> __vector;\n          __vector.reserve(__size);\n          for (size_t __i = 0; __i < __size; __i++) {\n            auto __element = externalSubtitles->getElement(__i);\n            __vector.push_back(__element->toCpp());\n          }\n          return __vector;\n        }()) : std::nullopt,\n        drm != nullptr ? std::make_optional(drm->toCpp()) : std::nullopt,\n        headers != nullptr ? std::make_optional([&]() {\n          std::unordered_map<std::string, std::string> __map;\n          __map.reserve(headers->size());\n          for (const auto& __entry : *headers) {\n            __map.emplace(__entry.first->toStdString(), __entry.second->toStdString());\n          }\n          return __map;\n        }()) : std::nullopt,\n        bufferConfig != nullptr ? std::make_optional(bufferConfig->toCpp()) : std::nullopt,\n        metadata != nullptr ? std::make_optional(metadata->toCpp()) : std::nullopt,\n        initializeOnCreation != nullptr ? std::make_optional(static_cast<bool>(initializeOnCreation->value())) : std::nullopt\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JNativeVideoConfig::javaobject> fromCpp(const NativeVideoConfig& value) {\n      using JSignature = JNativeVideoConfig(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JArrayClass<JNativeExternalSubtitle>>, jni::alias_ref<JNativeDrmParams>, jni::alias_ref<jni::JMap<jni::JString, jni::JString>>, jni::alias_ref<JBufferConfig>, jni::alias_ref<JCustomVideoMetadata>, jni::alias_ref<jni::JBoolean>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        jni::make_jstring(value.uri),\n        value.externalSubtitles.has_value() ? [&]() {\n          size_t __size = value.externalSubtitles.value().size();\n          jni::local_ref<jni::JArrayClass<JNativeExternalSubtitle>> __array = jni::JArrayClass<JNativeExternalSubtitle>::newArray(__size);\n          for (size_t __i = 0; __i < __size; __i++) {\n            const auto& __element = value.externalSubtitles.value()[__i];\n            auto __elementJni = JNativeExternalSubtitle::fromCpp(__element);\n            __array->setElement(__i, *__elementJni);\n          }\n          return __array;\n        }() : nullptr,\n        value.drm.has_value() ? JNativeDrmParams::fromCpp(value.drm.value()) : nullptr,\n        value.headers.has_value() ? [&]() -> jni::local_ref<jni::JMap<jni::JString, jni::JString>> {\n          auto __map = jni::JHashMap<jni::JString, jni::JString>::create(value.headers.value().size());\n          for (const auto& __entry : value.headers.value()) {\n            __map->put(jni::make_jstring(__entry.first), jni::make_jstring(__entry.second));\n          }\n          return __map;\n        }() : nullptr,\n        value.bufferConfig.has_value() ? JBufferConfig::fromCpp(value.bufferConfig.value()) : nullptr,\n        value.metadata.has_value() ? JCustomVideoMetadata::fromCpp(value.metadata.value()) : nullptr,\n        value.initializeOnCreation.has_value() ? jni::JBoolean::valueOf(value.initializeOnCreation.value()) : nullptr\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JOnGetLicensePayload.hpp",
    "content": "///\n/// JOnGetLicensePayload.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"OnGetLicensePayload.hpp\"\n\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"OnGetLicensePayload\" and the the Kotlin data class \"OnGetLicensePayload\".\n   */\n  struct JOnGetLicensePayload final: public jni::JavaClass<JOnGetLicensePayload> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/OnGetLicensePayload;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct OnGetLicensePayload by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    OnGetLicensePayload toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldContentId = clazz->getField<jni::JString>(\"contentId\");\n      jni::local_ref<jni::JString> contentId = this->getFieldValue(fieldContentId);\n      static const auto fieldLicenseUrl = clazz->getField<jni::JString>(\"licenseUrl\");\n      jni::local_ref<jni::JString> licenseUrl = this->getFieldValue(fieldLicenseUrl);\n      static const auto fieldKeyUrl = clazz->getField<jni::JString>(\"keyUrl\");\n      jni::local_ref<jni::JString> keyUrl = this->getFieldValue(fieldKeyUrl);\n      static const auto fieldSpc = clazz->getField<jni::JString>(\"spc\");\n      jni::local_ref<jni::JString> spc = this->getFieldValue(fieldSpc);\n      return OnGetLicensePayload(\n        contentId->toStdString(),\n        licenseUrl->toStdString(),\n        keyUrl->toStdString(),\n        spc->toStdString()\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JOnGetLicensePayload::javaobject> fromCpp(const OnGetLicensePayload& value) {\n      using JSignature = JOnGetLicensePayload(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        jni::make_jstring(value.contentId),\n        jni::make_jstring(value.licenseUrl),\n        jni::make_jstring(value.keyUrl),\n        jni::make_jstring(value.spc)\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JResizeMode.hpp",
    "content": "///\n/// JResizeMode.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"ResizeMode.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ enum \"ResizeMode\" and the the Kotlin enum \"ResizeMode\".\n   */\n  struct JResizeMode final: public jni::JavaClass<JResizeMode> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/ResizeMode;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based enum to the C++ enum ResizeMode.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    ResizeMode toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldOrdinal = clazz->getField<int>(\"value\");\n      int ordinal = this->getFieldValue(fieldOrdinal);\n      return static_cast<ResizeMode>(ordinal);\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based enum with the given C++ enum's value.\n     */\n    [[maybe_unused]]\n    static jni::alias_ref<JResizeMode> fromCpp(ResizeMode value) {\n      static const auto clazz = javaClassStatic();\n      switch (value) {\n        case ResizeMode::CONTAIN:\n          static const auto fieldCONTAIN = clazz->getStaticField<JResizeMode>(\"CONTAIN\");\n          return clazz->getStaticFieldValue(fieldCONTAIN);\n        case ResizeMode::COVER:\n          static const auto fieldCOVER = clazz->getStaticField<JResizeMode>(\"COVER\");\n          return clazz->getStaticFieldValue(fieldCOVER);\n        case ResizeMode::STRETCH:\n          static const auto fieldSTRETCH = clazz->getStaticField<JResizeMode>(\"STRETCH\");\n          return clazz->getStaticFieldValue(fieldSTRETCH);\n        case ResizeMode::NONE:\n          static const auto fieldNONE = clazz->getStaticField<JResizeMode>(\"NONE\");\n          return clazz->getStaticFieldValue(fieldNONE);\n        default:\n          std::string stringValue = std::to_string(static_cast<int>(value));\n          throw std::invalid_argument(\"Invalid enum value (\" + stringValue + \"!\");\n      }\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JResolution.hpp",
    "content": "///\n/// JResolution.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"Resolution.hpp\"\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"Resolution\" and the the Kotlin data class \"Resolution\".\n   */\n  struct JResolution final: public jni::JavaClass<JResolution> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Resolution;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct Resolution by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    Resolution toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldWidth = clazz->getField<double>(\"width\");\n      double width = this->getFieldValue(fieldWidth);\n      static const auto fieldHeight = clazz->getField<double>(\"height\");\n      double height = this->getFieldValue(fieldHeight);\n      return Resolution(\n        width,\n        height\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JResolution::javaobject> fromCpp(const Resolution& value) {\n      using JSignature = JResolution(double, double);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.width,\n        value.height\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JSourceType.hpp",
    "content": "///\n/// JSourceType.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"SourceType.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ enum \"SourceType\" and the the Kotlin enum \"SourceType\".\n   */\n  struct JSourceType final: public jni::JavaClass<JSourceType> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/SourceType;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based enum to the C++ enum SourceType.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    SourceType toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldOrdinal = clazz->getField<int>(\"value\");\n      int ordinal = this->getFieldValue(fieldOrdinal);\n      return static_cast<SourceType>(ordinal);\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based enum with the given C++ enum's value.\n     */\n    [[maybe_unused]]\n    static jni::alias_ref<JSourceType> fromCpp(SourceType value) {\n      static const auto clazz = javaClassStatic();\n      switch (value) {\n        case SourceType::LOCAL:\n          static const auto fieldLOCAL = clazz->getStaticField<JSourceType>(\"LOCAL\");\n          return clazz->getStaticFieldValue(fieldLOCAL);\n        case SourceType::NETWORK:\n          static const auto fieldNETWORK = clazz->getStaticField<JSourceType>(\"NETWORK\");\n          return clazz->getStaticFieldValue(fieldNETWORK);\n        default:\n          std::string stringValue = std::to_string(static_cast<int>(value));\n          throw std::invalid_argument(\"Invalid enum value (\" + stringValue + \"!\");\n      }\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JSubtitleType.hpp",
    "content": "///\n/// JSubtitleType.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"SubtitleType.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ enum \"SubtitleType\" and the the Kotlin enum \"SubtitleType\".\n   */\n  struct JSubtitleType final: public jni::JavaClass<JSubtitleType> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/SubtitleType;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based enum to the C++ enum SubtitleType.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    SubtitleType toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldOrdinal = clazz->getField<int>(\"value\");\n      int ordinal = this->getFieldValue(fieldOrdinal);\n      return static_cast<SubtitleType>(ordinal);\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based enum with the given C++ enum's value.\n     */\n    [[maybe_unused]]\n    static jni::alias_ref<JSubtitleType> fromCpp(SubtitleType value) {\n      static const auto clazz = javaClassStatic();\n      switch (value) {\n        case SubtitleType::AUTO:\n          static const auto fieldAUTO = clazz->getStaticField<JSubtitleType>(\"AUTO\");\n          return clazz->getStaticFieldValue(fieldAUTO);\n        case SubtitleType::VTT:\n          static const auto fieldVTT = clazz->getStaticField<JSubtitleType>(\"VTT\");\n          return clazz->getStaticFieldValue(fieldVTT);\n        case SubtitleType::SRT:\n          static const auto fieldSRT = clazz->getStaticField<JSubtitleType>(\"SRT\");\n          return clazz->getStaticFieldValue(fieldSRT);\n        case SubtitleType::SSA:\n          static const auto fieldSSA = clazz->getStaticField<JSubtitleType>(\"SSA\");\n          return clazz->getStaticFieldValue(fieldSSA);\n        case SubtitleType::ASS:\n          static const auto fieldASS = clazz->getStaticField<JSubtitleType>(\"ASS\");\n          return clazz->getStaticFieldValue(fieldASS);\n        default:\n          std::string stringValue = std::to_string(static_cast<int>(value));\n          throw std::invalid_argument(\"Invalid enum value (\" + stringValue + \"!\");\n      }\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JSurfaceType.hpp",
    "content": "///\n/// JSurfaceType.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"SurfaceType.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ enum \"SurfaceType\" and the the Kotlin enum \"SurfaceType\".\n   */\n  struct JSurfaceType final: public jni::JavaClass<JSurfaceType> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/SurfaceType;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based enum to the C++ enum SurfaceType.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    SurfaceType toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldOrdinal = clazz->getField<int>(\"value\");\n      int ordinal = this->getFieldValue(fieldOrdinal);\n      return static_cast<SurfaceType>(ordinal);\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based enum with the given C++ enum's value.\n     */\n    [[maybe_unused]]\n    static jni::alias_ref<JSurfaceType> fromCpp(SurfaceType value) {\n      static const auto clazz = javaClassStatic();\n      switch (value) {\n        case SurfaceType::SURFACE:\n          static const auto fieldSURFACE = clazz->getStaticField<JSurfaceType>(\"SURFACE\");\n          return clazz->getStaticFieldValue(fieldSURFACE);\n        case SurfaceType::TEXTURE:\n          static const auto fieldTEXTURE = clazz->getStaticField<JSurfaceType>(\"TEXTURE\");\n          return clazz->getStaticFieldValue(fieldTEXTURE);\n        default:\n          std::string stringValue = std::to_string(static_cast<int>(value));\n          throw std::invalid_argument(\"Invalid enum value (\" + stringValue + \"!\");\n      }\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JTextTrack.hpp",
    "content": "///\n/// JTextTrack.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"TextTrack.hpp\"\n\n#include <optional>\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"TextTrack\" and the the Kotlin data class \"TextTrack\".\n   */\n  struct JTextTrack final: public jni::JavaClass<JTextTrack> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/TextTrack;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct TextTrack by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    TextTrack toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldId = clazz->getField<jni::JString>(\"id\");\n      jni::local_ref<jni::JString> id = this->getFieldValue(fieldId);\n      static const auto fieldLabel = clazz->getField<jni::JString>(\"label\");\n      jni::local_ref<jni::JString> label = this->getFieldValue(fieldLabel);\n      static const auto fieldLanguage = clazz->getField<jni::JString>(\"language\");\n      jni::local_ref<jni::JString> language = this->getFieldValue(fieldLanguage);\n      static const auto fieldSelected = clazz->getField<jboolean>(\"selected\");\n      jboolean selected = this->getFieldValue(fieldSelected);\n      return TextTrack(\n        id->toStdString(),\n        label->toStdString(),\n        language != nullptr ? std::make_optional(language->toStdString()) : std::nullopt,\n        static_cast<bool>(selected)\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JTextTrack::javaobject> fromCpp(const TextTrack& value) {\n      using JSignature = JTextTrack(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jboolean);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        jni::make_jstring(value.id),\n        jni::make_jstring(value.label),\n        value.language.has_value() ? jni::make_jstring(value.language.value()) : nullptr,\n        value.selected\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JTimedMetadata.hpp",
    "content": "///\n/// JTimedMetadata.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"TimedMetadata.hpp\"\n\n#include \"JTimedMetadataObject.hpp\"\n#include \"TimedMetadataObject.hpp\"\n#include <string>\n#include <vector>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"TimedMetadata\" and the the Kotlin data class \"TimedMetadata\".\n   */\n  struct JTimedMetadata final: public jni::JavaClass<JTimedMetadata> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/TimedMetadata;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct TimedMetadata by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    TimedMetadata toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldMetadata = clazz->getField<jni::JArrayClass<JTimedMetadataObject>>(\"metadata\");\n      jni::local_ref<jni::JArrayClass<JTimedMetadataObject>> metadata = this->getFieldValue(fieldMetadata);\n      return TimedMetadata(\n        [&]() {\n          size_t __size = metadata->size();\n          std::vector<TimedMetadataObject> __vector;\n          __vector.reserve(__size);\n          for (size_t __i = 0; __i < __size; __i++) {\n            auto __element = metadata->getElement(__i);\n            __vector.push_back(__element->toCpp());\n          }\n          return __vector;\n        }()\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JTimedMetadata::javaobject> fromCpp(const TimedMetadata& value) {\n      using JSignature = JTimedMetadata(jni::alias_ref<jni::JArrayClass<JTimedMetadataObject>>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        [&]() {\n          size_t __size = value.metadata.size();\n          jni::local_ref<jni::JArrayClass<JTimedMetadataObject>> __array = jni::JArrayClass<JTimedMetadataObject>::newArray(__size);\n          for (size_t __i = 0; __i < __size; __i++) {\n            const auto& __element = value.metadata[__i];\n            auto __elementJni = JTimedMetadataObject::fromCpp(__element);\n            __array->setElement(__i, *__elementJni);\n          }\n          return __array;\n        }()\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JTimedMetadataObject.hpp",
    "content": "///\n/// JTimedMetadataObject.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"TimedMetadataObject.hpp\"\n\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"TimedMetadataObject\" and the the Kotlin data class \"TimedMetadataObject\".\n   */\n  struct JTimedMetadataObject final: public jni::JavaClass<JTimedMetadataObject> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/TimedMetadataObject;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct TimedMetadataObject by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    TimedMetadataObject toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldValue = clazz->getField<jni::JString>(\"value\");\n      jni::local_ref<jni::JString> value = this->getFieldValue(fieldValue);\n      static const auto fieldIdentifier = clazz->getField<jni::JString>(\"identifier\");\n      jni::local_ref<jni::JString> identifier = this->getFieldValue(fieldIdentifier);\n      return TimedMetadataObject(\n        value->toStdString(),\n        identifier->toStdString()\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JTimedMetadataObject::javaobject> fromCpp(const TimedMetadataObject& value) {\n      using JSignature = JTimedMetadataObject(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        jni::make_jstring(value.value),\n        jni::make_jstring(value.identifier)\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JVariant_NullType_HybridVideoPlayerSourceSpec.cpp",
    "content": "///\n/// JVariant_NullType_HybridVideoPlayerSourceSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JVariant_NullType_HybridVideoPlayerSourceSpec.hpp\"\n\nnamespace margelo::nitro::video {\n  /**\n   * Converts JVariant_NullType_HybridVideoPlayerSourceSpec to std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>\n   */\n  std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>> JVariant_NullType_HybridVideoPlayerSourceSpec::toCpp() const {\n    if (isInstanceOf(JVariant_NullType_HybridVideoPlayerSourceSpec_impl::First::javaClassStatic())) {\n      // It's a `nitro::NullType`\n      auto jniValue = static_cast<const JVariant_NullType_HybridVideoPlayerSourceSpec_impl::First*>(this)->getValue();\n      return nitro::null;\n    } else if (isInstanceOf(JVariant_NullType_HybridVideoPlayerSourceSpec_impl::Second::javaClassStatic())) {\n      // It's a `std::shared_ptr<HybridVideoPlayerSourceSpec>`\n      auto jniValue = static_cast<const JVariant_NullType_HybridVideoPlayerSourceSpec_impl::Second*>(this)->getValue();\n      return jniValue->getJHybridVideoPlayerSourceSpec();\n    }\n    throw std::invalid_argument(\"Variant is unknown Kotlin instance!\");\n  }\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JVariant_NullType_HybridVideoPlayerSourceSpec.hpp",
    "content": "///\n/// JVariant_NullType_HybridVideoPlayerSourceSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <variant>\n\n#include <NitroModules/Null.hpp>\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include <variant>\n#include <NitroModules/JNull.hpp>\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ std::variant and the Java class \"Variant_NullType_HybridVideoPlayerSourceSpec\".\n   */\n  class JVariant_NullType_HybridVideoPlayerSourceSpec: public jni::JavaClass<JVariant_NullType_HybridVideoPlayerSourceSpec> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Variant_NullType_HybridVideoPlayerSourceSpec;\";\n\n    static jni::local_ref<JVariant_NullType_HybridVideoPlayerSourceSpec> create_0(jni::alias_ref<JNull> value) {\n      static const auto method = javaClassStatic()->getStaticMethod<JVariant_NullType_HybridVideoPlayerSourceSpec(jni::alias_ref<JNull>)>(\"create\");\n      return method(javaClassStatic(), value);\n    }\n    static jni::local_ref<JVariant_NullType_HybridVideoPlayerSourceSpec> create_1(jni::alias_ref<JHybridVideoPlayerSourceSpec::JavaPart> value) {\n      static const auto method = javaClassStatic()->getStaticMethod<JVariant_NullType_HybridVideoPlayerSourceSpec(jni::alias_ref<JHybridVideoPlayerSourceSpec::JavaPart>)>(\"create\");\n      return method(javaClassStatic(), value);\n    }\n\n    static jni::local_ref<JVariant_NullType_HybridVideoPlayerSourceSpec> fromCpp(const std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>& variant) {\n      switch (variant.index()) {\n        case 0: return create_0(JNull::null());\n        case 1: return create_1(std::dynamic_pointer_cast<JHybridVideoPlayerSourceSpec>(std::get<1>(variant))->getJavaPart());\n        default: throw std::invalid_argument(\"Variant holds unknown index! (\" + std::to_string(variant.index()) + \")\");\n      }\n    }\n\n    [[nodiscard]] std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>> toCpp() const;\n  };\n\n  namespace JVariant_NullType_HybridVideoPlayerSourceSpec_impl {\n    class First final: public jni::JavaClass<First, JVariant_NullType_HybridVideoPlayerSourceSpec> {\n    public:\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Variant_NullType_HybridVideoPlayerSourceSpec$First;\";\n    \n      [[nodiscard]] jni::local_ref<JNull> getValue() const {\n        static const auto field = javaClassStatic()->getField<JNull>(\"value\");\n        return getFieldValue(field);\n      }\n    };\n    \n    class Second final: public jni::JavaClass<Second, JVariant_NullType_HybridVideoPlayerSourceSpec> {\n    public:\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Variant_NullType_HybridVideoPlayerSourceSpec$Second;\";\n    \n      [[nodiscard]] jni::local_ref<JHybridVideoPlayerSourceSpec::JavaPart> getValue() const {\n        static const auto field = javaClassStatic()->getField<JHybridVideoPlayerSourceSpec::JavaPart>(\"value\");\n        return getFieldValue(field);\n      }\n    };\n  } // namespace JVariant_NullType_HybridVideoPlayerSourceSpec_impl\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JVariant_NullType_TextTrack.cpp",
    "content": "///\n/// JVariant_NullType_TextTrack.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"JVariant_NullType_TextTrack.hpp\"\n\nnamespace margelo::nitro::video {\n  /**\n   * Converts JVariant_NullType_TextTrack to std::variant<nitro::NullType, TextTrack>\n   */\n  std::variant<nitro::NullType, TextTrack> JVariant_NullType_TextTrack::toCpp() const {\n    if (isInstanceOf(JVariant_NullType_TextTrack_impl::First::javaClassStatic())) {\n      // It's a `nitro::NullType`\n      auto jniValue = static_cast<const JVariant_NullType_TextTrack_impl::First*>(this)->getValue();\n      return nitro::null;\n    } else if (isInstanceOf(JVariant_NullType_TextTrack_impl::Second::javaClassStatic())) {\n      // It's a `TextTrack`\n      auto jniValue = static_cast<const JVariant_NullType_TextTrack_impl::Second*>(this)->getValue();\n      return jniValue->toCpp();\n    }\n    throw std::invalid_argument(\"Variant is unknown Kotlin instance!\");\n  }\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JVariant_NullType_TextTrack.hpp",
    "content": "///\n/// JVariant_NullType_TextTrack.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include <variant>\n\n#include <NitroModules/Null.hpp>\n#include \"TextTrack.hpp\"\n#include <variant>\n#include <NitroModules/JNull.hpp>\n#include \"JTextTrack.hpp\"\n#include <string>\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ std::variant and the Java class \"Variant_NullType_TextTrack\".\n   */\n  class JVariant_NullType_TextTrack: public jni::JavaClass<JVariant_NullType_TextTrack> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Variant_NullType_TextTrack;\";\n\n    static jni::local_ref<JVariant_NullType_TextTrack> create_0(jni::alias_ref<JNull> value) {\n      static const auto method = javaClassStatic()->getStaticMethod<JVariant_NullType_TextTrack(jni::alias_ref<JNull>)>(\"create\");\n      return method(javaClassStatic(), value);\n    }\n    static jni::local_ref<JVariant_NullType_TextTrack> create_1(jni::alias_ref<JTextTrack> value) {\n      static const auto method = javaClassStatic()->getStaticMethod<JVariant_NullType_TextTrack(jni::alias_ref<JTextTrack>)>(\"create\");\n      return method(javaClassStatic(), value);\n    }\n\n    static jni::local_ref<JVariant_NullType_TextTrack> fromCpp(const std::variant<nitro::NullType, TextTrack>& variant) {\n      switch (variant.index()) {\n        case 0: return create_0(JNull::null());\n        case 1: return create_1(JTextTrack::fromCpp(std::get<1>(variant)));\n        default: throw std::invalid_argument(\"Variant holds unknown index! (\" + std::to_string(variant.index()) + \")\");\n      }\n    }\n\n    [[nodiscard]] std::variant<nitro::NullType, TextTrack> toCpp() const;\n  };\n\n  namespace JVariant_NullType_TextTrack_impl {\n    class First final: public jni::JavaClass<First, JVariant_NullType_TextTrack> {\n    public:\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Variant_NullType_TextTrack$First;\";\n    \n      [[nodiscard]] jni::local_ref<JNull> getValue() const {\n        static const auto field = javaClassStatic()->getField<JNull>(\"value\");\n        return getFieldValue(field);\n      }\n    };\n    \n    class Second final: public jni::JavaClass<Second, JVariant_NullType_TextTrack> {\n    public:\n      static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/Variant_NullType_TextTrack$Second;\";\n    \n      [[nodiscard]] jni::local_ref<JTextTrack> getValue() const {\n        static const auto field = javaClassStatic()->getField<JTextTrack>(\"value\");\n        return getFieldValue(field);\n      }\n    };\n  } // namespace JVariant_NullType_TextTrack_impl\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JVideoInformation.hpp",
    "content": "///\n/// JVideoInformation.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"VideoInformation.hpp\"\n\n#include \"JVideoOrientation.hpp\"\n#include \"VideoOrientation.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"VideoInformation\" and the the Kotlin data class \"VideoInformation\".\n   */\n  struct JVideoInformation final: public jni::JavaClass<JVideoInformation> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/VideoInformation;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct VideoInformation by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    VideoInformation toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldBitrate = clazz->getField<double>(\"bitrate\");\n      double bitrate = this->getFieldValue(fieldBitrate);\n      static const auto fieldWidth = clazz->getField<double>(\"width\");\n      double width = this->getFieldValue(fieldWidth);\n      static const auto fieldHeight = clazz->getField<double>(\"height\");\n      double height = this->getFieldValue(fieldHeight);\n      static const auto fieldDuration = clazz->getField<double>(\"duration\");\n      double duration = this->getFieldValue(fieldDuration);\n      static const auto fieldFileSize = clazz->getField<int64_t>(\"fileSize\");\n      int64_t fileSize = this->getFieldValue(fieldFileSize);\n      static const auto fieldIsHDR = clazz->getField<jboolean>(\"isHDR\");\n      jboolean isHDR = this->getFieldValue(fieldIsHDR);\n      static const auto fieldIsLive = clazz->getField<jboolean>(\"isLive\");\n      jboolean isLive = this->getFieldValue(fieldIsLive);\n      static const auto fieldOrientation = clazz->getField<JVideoOrientation>(\"orientation\");\n      jni::local_ref<JVideoOrientation> orientation = this->getFieldValue(fieldOrientation);\n      return VideoInformation(\n        bitrate,\n        width,\n        height,\n        duration,\n        fileSize,\n        static_cast<bool>(isHDR),\n        static_cast<bool>(isLive),\n        orientation->toCpp()\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JVideoInformation::javaobject> fromCpp(const VideoInformation& value) {\n      using JSignature = JVideoInformation(double, double, double, double, int64_t, jboolean, jboolean, jni::alias_ref<JVideoOrientation>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.bitrate,\n        value.width,\n        value.height,\n        value.duration,\n        value.fileSize,\n        value.isHDR,\n        value.isLive,\n        JVideoOrientation::fromCpp(value.orientation)\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JVideoOrientation.hpp",
    "content": "///\n/// JVideoOrientation.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"VideoOrientation.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ enum \"VideoOrientation\" and the the Kotlin enum \"VideoOrientation\".\n   */\n  struct JVideoOrientation final: public jni::JavaClass<JVideoOrientation> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/VideoOrientation;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based enum to the C++ enum VideoOrientation.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    VideoOrientation toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldOrdinal = clazz->getField<int>(\"value\");\n      int ordinal = this->getFieldValue(fieldOrdinal);\n      return static_cast<VideoOrientation>(ordinal);\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based enum with the given C++ enum's value.\n     */\n    [[maybe_unused]]\n    static jni::alias_ref<JVideoOrientation> fromCpp(VideoOrientation value) {\n      static const auto clazz = javaClassStatic();\n      switch (value) {\n        case VideoOrientation::PORTRAIT:\n          static const auto fieldPORTRAIT = clazz->getStaticField<JVideoOrientation>(\"PORTRAIT\");\n          return clazz->getStaticFieldValue(fieldPORTRAIT);\n        case VideoOrientation::LANDSCAPE:\n          static const auto fieldLANDSCAPE = clazz->getStaticField<JVideoOrientation>(\"LANDSCAPE\");\n          return clazz->getStaticFieldValue(fieldLANDSCAPE);\n        case VideoOrientation::PORTRAIT_UPSIDE_DOWN:\n          static const auto fieldPORTRAIT_UPSIDE_DOWN = clazz->getStaticField<JVideoOrientation>(\"PORTRAIT_UPSIDE_DOWN\");\n          return clazz->getStaticFieldValue(fieldPORTRAIT_UPSIDE_DOWN);\n        case VideoOrientation::LANDSCAPE_LEFT:\n          static const auto fieldLANDSCAPE_LEFT = clazz->getStaticField<JVideoOrientation>(\"LANDSCAPE_LEFT\");\n          return clazz->getStaticFieldValue(fieldLANDSCAPE_LEFT);\n        case VideoOrientation::LANDSCAPE_RIGHT:\n          static const auto fieldLANDSCAPE_RIGHT = clazz->getStaticField<JVideoOrientation>(\"LANDSCAPE_RIGHT\");\n          return clazz->getStaticFieldValue(fieldLANDSCAPE_RIGHT);\n        case VideoOrientation::SQUARE:\n          static const auto fieldSQUARE = clazz->getStaticField<JVideoOrientation>(\"SQUARE\");\n          return clazz->getStaticFieldValue(fieldSQUARE);\n        case VideoOrientation::UNKNOWN:\n          static const auto fieldUNKNOWN = clazz->getStaticField<JVideoOrientation>(\"UNKNOWN\");\n          return clazz->getStaticFieldValue(fieldUNKNOWN);\n        default:\n          std::string stringValue = std::to_string(static_cast<int>(value));\n          throw std::invalid_argument(\"Invalid enum value (\" + stringValue + \"!\");\n      }\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JVideoPlayerStatus.hpp",
    "content": "///\n/// JVideoPlayerStatus.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"VideoPlayerStatus.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ enum \"VideoPlayerStatus\" and the the Kotlin enum \"VideoPlayerStatus\".\n   */\n  struct JVideoPlayerStatus final: public jni::JavaClass<JVideoPlayerStatus> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/VideoPlayerStatus;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based enum to the C++ enum VideoPlayerStatus.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    VideoPlayerStatus toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldOrdinal = clazz->getField<int>(\"value\");\n      int ordinal = this->getFieldValue(fieldOrdinal);\n      return static_cast<VideoPlayerStatus>(ordinal);\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based enum with the given C++ enum's value.\n     */\n    [[maybe_unused]]\n    static jni::alias_ref<JVideoPlayerStatus> fromCpp(VideoPlayerStatus value) {\n      static const auto clazz = javaClassStatic();\n      switch (value) {\n        case VideoPlayerStatus::IDLE:\n          static const auto fieldIDLE = clazz->getStaticField<JVideoPlayerStatus>(\"IDLE\");\n          return clazz->getStaticFieldValue(fieldIDLE);\n        case VideoPlayerStatus::LOADING:\n          static const auto fieldLOADING = clazz->getStaticField<JVideoPlayerStatus>(\"LOADING\");\n          return clazz->getStaticFieldValue(fieldLOADING);\n        case VideoPlayerStatus::READYTOPLAY:\n          static const auto fieldREADYTOPLAY = clazz->getStaticField<JVideoPlayerStatus>(\"READYTOPLAY\");\n          return clazz->getStaticFieldValue(fieldREADYTOPLAY);\n        case VideoPlayerStatus::ERROR:\n          static const auto fieldERROR = clazz->getStaticField<JVideoPlayerStatus>(\"ERROR\");\n          return clazz->getStaticFieldValue(fieldERROR);\n        default:\n          std::string stringValue = std::to_string(static_cast<int>(value));\n          throw std::invalid_argument(\"Invalid enum value (\" + stringValue + \"!\");\n      }\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JonLoadData.hpp",
    "content": "///\n/// JonLoadData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"onLoadData.hpp\"\n\n#include \"JVideoOrientation.hpp\"\n#include \"VideoOrientation.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"onLoadData\" and the the Kotlin data class \"onLoadData\".\n   */\n  struct JonLoadData final: public jni::JavaClass<JonLoadData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/onLoadData;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct onLoadData by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    onLoadData toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldCurrentTime = clazz->getField<double>(\"currentTime\");\n      double currentTime = this->getFieldValue(fieldCurrentTime);\n      static const auto fieldDuration = clazz->getField<double>(\"duration\");\n      double duration = this->getFieldValue(fieldDuration);\n      static const auto fieldHeight = clazz->getField<double>(\"height\");\n      double height = this->getFieldValue(fieldHeight);\n      static const auto fieldWidth = clazz->getField<double>(\"width\");\n      double width = this->getFieldValue(fieldWidth);\n      static const auto fieldOrientation = clazz->getField<JVideoOrientation>(\"orientation\");\n      jni::local_ref<JVideoOrientation> orientation = this->getFieldValue(fieldOrientation);\n      return onLoadData(\n        currentTime,\n        duration,\n        height,\n        width,\n        orientation->toCpp()\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JonLoadData::javaobject> fromCpp(const onLoadData& value) {\n      using JSignature = JonLoadData(double, double, double, double, jni::alias_ref<JVideoOrientation>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.currentTime,\n        value.duration,\n        value.height,\n        value.width,\n        JVideoOrientation::fromCpp(value.orientation)\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JonLoadStartData.hpp",
    "content": "///\n/// JonLoadStartData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"onLoadStartData.hpp\"\n\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"JHybridVideoPlayerSourceSpec.hpp\"\n#include \"JSourceType.hpp\"\n#include \"SourceType.hpp\"\n#include <memory>\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"onLoadStartData\" and the the Kotlin data class \"onLoadStartData\".\n   */\n  struct JonLoadStartData final: public jni::JavaClass<JonLoadStartData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/onLoadStartData;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct onLoadStartData by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    onLoadStartData toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldSourceType = clazz->getField<JSourceType>(\"sourceType\");\n      jni::local_ref<JSourceType> sourceType = this->getFieldValue(fieldSourceType);\n      static const auto fieldSource = clazz->getField<JHybridVideoPlayerSourceSpec::JavaPart>(\"source\");\n      jni::local_ref<JHybridVideoPlayerSourceSpec::JavaPart> source = this->getFieldValue(fieldSource);\n      return onLoadStartData(\n        sourceType->toCpp(),\n        source->getJHybridVideoPlayerSourceSpec()\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JonLoadStartData::javaobject> fromCpp(const onLoadStartData& value) {\n      using JSignature = JonLoadStartData(jni::alias_ref<JSourceType>, jni::alias_ref<JHybridVideoPlayerSourceSpec::JavaPart>);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        JSourceType::fromCpp(value.sourceType),\n        std::dynamic_pointer_cast<JHybridVideoPlayerSourceSpec>(value.source)->getJavaPart()\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JonPlaybackStateChangeData.hpp",
    "content": "///\n/// JonPlaybackStateChangeData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"onPlaybackStateChangeData.hpp\"\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"onPlaybackStateChangeData\" and the the Kotlin data class \"onPlaybackStateChangeData\".\n   */\n  struct JonPlaybackStateChangeData final: public jni::JavaClass<JonPlaybackStateChangeData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/onPlaybackStateChangeData;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct onPlaybackStateChangeData by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    onPlaybackStateChangeData toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldIsPlaying = clazz->getField<jboolean>(\"isPlaying\");\n      jboolean isPlaying = this->getFieldValue(fieldIsPlaying);\n      static const auto fieldIsBuffering = clazz->getField<jboolean>(\"isBuffering\");\n      jboolean isBuffering = this->getFieldValue(fieldIsBuffering);\n      return onPlaybackStateChangeData(\n        static_cast<bool>(isPlaying),\n        static_cast<bool>(isBuffering)\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JonPlaybackStateChangeData::javaobject> fromCpp(const onPlaybackStateChangeData& value) {\n      using JSignature = JonPlaybackStateChangeData(jboolean, jboolean);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.isPlaying,\n        value.isBuffering\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JonProgressData.hpp",
    "content": "///\n/// JonProgressData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"onProgressData.hpp\"\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"onProgressData\" and the the Kotlin data class \"onProgressData\".\n   */\n  struct JonProgressData final: public jni::JavaClass<JonProgressData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/onProgressData;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct onProgressData by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    onProgressData toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldCurrentTime = clazz->getField<double>(\"currentTime\");\n      double currentTime = this->getFieldValue(fieldCurrentTime);\n      static const auto fieldBufferDuration = clazz->getField<double>(\"bufferDuration\");\n      double bufferDuration = this->getFieldValue(fieldBufferDuration);\n      return onProgressData(\n        currentTime,\n        bufferDuration\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JonProgressData::javaobject> fromCpp(const onProgressData& value) {\n      using JSignature = JonProgressData(double, double);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.currentTime,\n        value.bufferDuration\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/c++/JonVolumeChangeData.hpp",
    "content": "///\n/// JonVolumeChangeData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include <fbjni/fbjni.h>\n#include \"onVolumeChangeData.hpp\"\n\n\n\nnamespace margelo::nitro::video {\n\n  using namespace facebook;\n\n  /**\n   * The C++ JNI bridge between the C++ struct \"onVolumeChangeData\" and the the Kotlin data class \"onVolumeChangeData\".\n   */\n  struct JonVolumeChangeData final: public jni::JavaClass<JonVolumeChangeData> {\n  public:\n    static auto constexpr kJavaDescriptor = \"Lcom/margelo/nitro/video/onVolumeChangeData;\";\n\n  public:\n    /**\n     * Convert this Java/Kotlin-based struct to the C++ struct onVolumeChangeData by copying all values to C++.\n     */\n    [[maybe_unused]]\n    [[nodiscard]]\n    onVolumeChangeData toCpp() const {\n      static const auto clazz = javaClassStatic();\n      static const auto fieldVolume = clazz->getField<double>(\"volume\");\n      double volume = this->getFieldValue(fieldVolume);\n      static const auto fieldMuted = clazz->getField<jboolean>(\"muted\");\n      jboolean muted = this->getFieldValue(fieldMuted);\n      return onVolumeChangeData(\n        volume,\n        static_cast<bool>(muted)\n      );\n    }\n\n  public:\n    /**\n     * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.\n     */\n    [[maybe_unused]]\n    static jni::local_ref<JonVolumeChangeData::javaobject> fromCpp(const onVolumeChangeData& value) {\n      using JSignature = JonVolumeChangeData(double, jboolean);\n      static const auto clazz = javaClassStatic();\n      static const auto create = clazz->getStaticMethod<JSignature>(\"fromCpp\");\n      return create(\n        clazz,\n        value.volume,\n        value.muted\n      );\n    }\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/BandwidthData.kt",
    "content": "///\n/// BandwidthData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"BandwidthData\".\n */\n@DoNotStrip\n@Keep\ndata class BandwidthData(\n  @DoNotStrip\n  @Keep\n  val bitrate: Double,\n  @DoNotStrip\n  @Keep\n  val width: Double?,\n  @DoNotStrip\n  @Keep\n  val height: Double?\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(bitrate: Double, width: Double?, height: Double?): BandwidthData {\n      return BandwidthData(bitrate, width, height)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/BufferConfig.kt",
    "content": "///\n/// BufferConfig.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"BufferConfig\".\n */\n@DoNotStrip\n@Keep\ndata class BufferConfig(\n  @DoNotStrip\n  @Keep\n  val livePlayback: LivePlaybackParams?,\n  @DoNotStrip\n  @Keep\n  val minBufferMs: Double?,\n  @DoNotStrip\n  @Keep\n  val maxBufferMs: Double?,\n  @DoNotStrip\n  @Keep\n  val bufferForPlaybackMs: Double?,\n  @DoNotStrip\n  @Keep\n  val bufferForPlaybackAfterRebufferMs: Double?,\n  @DoNotStrip\n  @Keep\n  val backBufferDurationMs: Double?,\n  @DoNotStrip\n  @Keep\n  val preferredForwardBufferDurationMs: Double?,\n  @DoNotStrip\n  @Keep\n  val preferredPeakBitRate: Double?,\n  @DoNotStrip\n  @Keep\n  val preferredMaximumResolution: Resolution?,\n  @DoNotStrip\n  @Keep\n  val preferredPeakBitRateForExpensiveNetworks: Double?,\n  @DoNotStrip\n  @Keep\n  val preferredMaximumResolutionForExpensiveNetworks: Resolution?\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(livePlayback: LivePlaybackParams?, minBufferMs: Double?, maxBufferMs: Double?, bufferForPlaybackMs: Double?, bufferForPlaybackAfterRebufferMs: Double?, backBufferDurationMs: Double?, preferredForwardBufferDurationMs: Double?, preferredPeakBitRate: Double?, preferredMaximumResolution: Resolution?, preferredPeakBitRateForExpensiveNetworks: Double?, preferredMaximumResolutionForExpensiveNetworks: Resolution?): BufferConfig {\n      return BufferConfig(livePlayback, minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, backBufferDurationMs, preferredForwardBufferDurationMs, preferredPeakBitRate, preferredMaximumResolution, preferredPeakBitRateForExpensiveNetworks, preferredMaximumResolutionForExpensiveNetworks)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/CustomVideoMetadata.kt",
    "content": "///\n/// CustomVideoMetadata.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"CustomVideoMetadata\".\n */\n@DoNotStrip\n@Keep\ndata class CustomVideoMetadata(\n  @DoNotStrip\n  @Keep\n  val title: String?,\n  @DoNotStrip\n  @Keep\n  val subtitle: String?,\n  @DoNotStrip\n  @Keep\n  val description: String?,\n  @DoNotStrip\n  @Keep\n  val artist: String?,\n  @DoNotStrip\n  @Keep\n  val imageUri: String?\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(title: String?, subtitle: String?, description: String?, artist: String?, imageUri: String?): CustomVideoMetadata {\n      return CustomVideoMetadata(title, subtitle, description, artist, imageUri)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.kt",
    "content": "///\n/// Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\nimport com.margelo.nitro.core.Promise\n\n/**\n * Represents the JavaScript callback `(payload: struct) => std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload: (OnGetLicensePayload) -> Promise<Promise<String>> {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(payload: OnGetLicensePayload): Promise<Promise<String>>\n}\n\n/**\n * Represents the JavaScript callback `(payload: struct) => std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_cxx: Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(payload: OnGetLicensePayload): Promise<Promise<String>>\n    = invoke_cxx(payload)\n\n  @FastNative\n  private external fun invoke_cxx(payload: OnGetLicensePayload): Promise<Promise<String>>\n}\n\n/**\n * Represents the JavaScript callback `(payload: struct) => std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>`.\n * This is implemented in Java/Kotlin, via a `(OnGetLicensePayload) -> Promise<Promise<String>>`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_java(private val function: (OnGetLicensePayload) -> Promise<Promise<String>>): Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload {\n  @DoNotStrip\n  @Keep\n  override fun invoke(payload: OnGetLicensePayload): Promise<Promise<String>> {\n    return this.function(payload)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void.kt",
    "content": "///\n/// Func_void.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `() => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void: () -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(): Unit\n}\n\n/**\n * Represents the JavaScript callback `() => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_cxx: Func_void {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(): Unit\n    = invoke_cxx()\n\n  @FastNative\n  private external fun invoke_cxx(): Unit\n}\n\n/**\n * Represents the JavaScript callback `() => void`.\n * This is implemented in Java/Kotlin, via a `() -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_java(private val function: () -> Unit): Func_void {\n  @DoNotStrip\n  @Keep\n  override fun invoke(): Unit {\n    return this.function()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_BandwidthData.kt",
    "content": "///\n/// Func_void_BandwidthData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_BandwidthData: (BandwidthData) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: BandwidthData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_BandwidthData_cxx: Func_void_BandwidthData {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: BandwidthData): Unit\n    = invoke_cxx(data)\n\n  @FastNative\n  private external fun invoke_cxx(data: BandwidthData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in Java/Kotlin, via a `(BandwidthData) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_BandwidthData_java(private val function: (BandwidthData) -> Unit): Func_void_BandwidthData {\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: BandwidthData): Unit {\n    return this.function(data)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_TimedMetadata.kt",
    "content": "///\n/// Func_void_TimedMetadata.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_TimedMetadata: (TimedMetadata) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: TimedMetadata): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_TimedMetadata_cxx: Func_void_TimedMetadata {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: TimedMetadata): Unit\n    = invoke_cxx(data)\n\n  @FastNative\n  private external fun invoke_cxx(data: TimedMetadata): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in Java/Kotlin, via a `(TimedMetadata) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_TimedMetadata_java(private val function: (TimedMetadata) -> Unit): Func_void_TimedMetadata {\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: TimedMetadata): Unit {\n    return this.function(data)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_VideoPlayerStatus.kt",
    "content": "///\n/// Func_void_VideoPlayerStatus.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(status: enum) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_VideoPlayerStatus: (VideoPlayerStatus) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(status: VideoPlayerStatus): Unit\n}\n\n/**\n * Represents the JavaScript callback `(status: enum) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_VideoPlayerStatus_cxx: Func_void_VideoPlayerStatus {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(status: VideoPlayerStatus): Unit\n    = invoke_cxx(status)\n\n  @FastNative\n  private external fun invoke_cxx(status: VideoPlayerStatus): Unit\n}\n\n/**\n * Represents the JavaScript callback `(status: enum) => void`.\n * This is implemented in Java/Kotlin, via a `(VideoPlayerStatus) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_VideoPlayerStatus_java(private val function: (VideoPlayerStatus) -> Unit): Func_void_VideoPlayerStatus {\n  @DoNotStrip\n  @Keep\n  override fun invoke(status: VideoPlayerStatus): Unit {\n    return this.function(status)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_bool.kt",
    "content": "///\n/// Func_void_bool.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(isInPictureInPicture: boolean) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_bool: (Boolean) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(isInPictureInPicture: Boolean): Unit\n}\n\n/**\n * Represents the JavaScript callback `(isInPictureInPicture: boolean) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_bool_cxx: Func_void_bool {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(isInPictureInPicture: Boolean): Unit\n    = invoke_cxx(isInPictureInPicture)\n\n  @FastNative\n  private external fun invoke_cxx(isInPictureInPicture: Boolean): Unit\n}\n\n/**\n * Represents the JavaScript callback `(isInPictureInPicture: boolean) => void`.\n * This is implemented in Java/Kotlin, via a `(Boolean) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_bool_java(private val function: (Boolean) -> Unit): Func_void_bool {\n  @DoNotStrip\n  @Keep\n  override fun invoke(isInPictureInPicture: Boolean): Unit {\n    return this.function(isInPictureInPicture)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_double.kt",
    "content": "///\n/// Func_void_double.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(rate: number) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_double: (Double) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(rate: Double): Unit\n}\n\n/**\n * Represents the JavaScript callback `(rate: number) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_double_cxx: Func_void_double {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(rate: Double): Unit\n    = invoke_cxx(rate)\n\n  @FastNative\n  private external fun invoke_cxx(rate: Double): Unit\n}\n\n/**\n * Represents the JavaScript callback `(rate: number) => void`.\n * This is implemented in Java/Kotlin, via a `(Double) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_double_java(private val function: (Double) -> Unit): Func_void_double {\n  @DoNotStrip\n  @Keep\n  override fun invoke(rate: Double): Unit {\n    return this.function(rate)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onLoadData.kt",
    "content": "///\n/// Func_void_onLoadData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_onLoadData: (onLoadData) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onLoadData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_onLoadData_cxx: Func_void_onLoadData {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onLoadData): Unit\n    = invoke_cxx(data)\n\n  @FastNative\n  private external fun invoke_cxx(data: onLoadData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in Java/Kotlin, via a `(onLoadData) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_onLoadData_java(private val function: (onLoadData) -> Unit): Func_void_onLoadData {\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onLoadData): Unit {\n    return this.function(data)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onLoadStartData.kt",
    "content": "///\n/// Func_void_onLoadStartData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_onLoadStartData: (onLoadStartData) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onLoadStartData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_onLoadStartData_cxx: Func_void_onLoadStartData {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onLoadStartData): Unit\n    = invoke_cxx(data)\n\n  @FastNative\n  private external fun invoke_cxx(data: onLoadStartData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in Java/Kotlin, via a `(onLoadStartData) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_onLoadStartData_java(private val function: (onLoadStartData) -> Unit): Func_void_onLoadStartData {\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onLoadStartData): Unit {\n    return this.function(data)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onPlaybackStateChangeData.kt",
    "content": "///\n/// Func_void_onPlaybackStateChangeData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_onPlaybackStateChangeData: (onPlaybackStateChangeData) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onPlaybackStateChangeData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_onPlaybackStateChangeData_cxx: Func_void_onPlaybackStateChangeData {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onPlaybackStateChangeData): Unit\n    = invoke_cxx(data)\n\n  @FastNative\n  private external fun invoke_cxx(data: onPlaybackStateChangeData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in Java/Kotlin, via a `(onPlaybackStateChangeData) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_onPlaybackStateChangeData_java(private val function: (onPlaybackStateChangeData) -> Unit): Func_void_onPlaybackStateChangeData {\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onPlaybackStateChangeData): Unit {\n    return this.function(data)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onProgressData.kt",
    "content": "///\n/// Func_void_onProgressData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_onProgressData: (onProgressData) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onProgressData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_onProgressData_cxx: Func_void_onProgressData {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onProgressData): Unit\n    = invoke_cxx(data)\n\n  @FastNative\n  private external fun invoke_cxx(data: onProgressData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in Java/Kotlin, via a `(onProgressData) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_onProgressData_java(private val function: (onProgressData) -> Unit): Func_void_onProgressData {\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onProgressData): Unit {\n    return this.function(data)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_onVolumeChangeData.kt",
    "content": "///\n/// Func_void_onVolumeChangeData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_onVolumeChangeData: (onVolumeChangeData) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onVolumeChangeData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_onVolumeChangeData_cxx: Func_void_onVolumeChangeData {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onVolumeChangeData): Unit\n    = invoke_cxx(data)\n\n  @FastNative\n  private external fun invoke_cxx(data: onVolumeChangeData): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: struct) => void`.\n * This is implemented in Java/Kotlin, via a `(onVolumeChangeData) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_onVolumeChangeData_java(private val function: (onVolumeChangeData) -> Unit): Func_void_onVolumeChangeData {\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: onVolumeChangeData): Unit {\n    return this.function(data)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_std__optional_std__variant_nitro__NullType__TextTrack__.kt",
    "content": "///\n/// Func_void_std__optional_std__variant_nitro__NullType__TextTrack__.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\nimport com.margelo.nitro.core.NullType\n\n/**\n * Represents the JavaScript callback `(track: optional) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_std__optional_std__variant_nitro__NullType__TextTrack__: (Variant_NullType_TextTrack?) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(track: Variant_NullType_TextTrack?): Unit\n}\n\n/**\n * Represents the JavaScript callback `(track: optional) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_std__optional_std__variant_nitro__NullType__TextTrack___cxx: Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(track: Variant_NullType_TextTrack?): Unit\n    = invoke_cxx(track)\n\n  @FastNative\n  private external fun invoke_cxx(track: Variant_NullType_TextTrack?): Unit\n}\n\n/**\n * Represents the JavaScript callback `(track: optional) => void`.\n * This is implemented in Java/Kotlin, via a `(Variant_NullType_TextTrack?) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_std__optional_std__variant_nitro__NullType__TextTrack___java(private val function: (Variant_NullType_TextTrack?) -> Unit): Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ {\n  @DoNotStrip\n  @Keep\n  override fun invoke(track: Variant_NullType_TextTrack?): Unit {\n    return this.function(track)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Func_void_std__vector_std__string_.kt",
    "content": "///\n/// Func_void_std__vector_std__string_.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport dalvik.annotation.optimization.FastNative\n\n\n/**\n * Represents the JavaScript callback `(data: array) => void`.\n * This can be either implemented in C++ (in which case it might be a callback coming from JS),\n * or in Kotlin/Java (in which case it is a native callback).\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\")\nfun interface Func_void_std__vector_std__string_: (Array<String>) -> Unit {\n  /**\n   * Call the given JS callback.\n   * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.\n   */\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: Array<String>): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: array) => void`.\n * This is implemented in C++, via a `std::function<...>`.\n * The callback might be coming from JS.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"FunctionName\",\n  \"ConvertSecondaryConstructorToPrimary\", \"ClassName\", \"LocalVariableName\",\n)\nclass Func_void_std__vector_std__string__cxx: Func_void_std__vector_std__string_ {\n  @DoNotStrip\n  @Keep\n  private val mHybridData: HybridData\n\n  @DoNotStrip\n  @Keep\n  private constructor(hybridData: HybridData) {\n    mHybridData = hybridData\n  }\n\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: Array<String>): Unit\n    = invoke_cxx(data)\n\n  @FastNative\n  private external fun invoke_cxx(data: Array<String>): Unit\n}\n\n/**\n * Represents the JavaScript callback `(data: array) => void`.\n * This is implemented in Java/Kotlin, via a `(Array<String>) -> Unit`.\n * The callback is always coming from native.\n */\n@DoNotStrip\n@Keep\n@Suppress(\"ClassName\", \"RedundantUnitReturnType\", \"unused\")\nclass Func_void_std__vector_std__string__java(private val function: (Array<String>) -> Unit): Func_void_std__vector_std__string_ {\n  @DoNotStrip\n  @Keep\n  override fun invoke(data: Array<String>): Unit {\n    return this.function(data)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerEventEmitterSpec.kt",
    "content": "///\n/// HybridVideoPlayerEventEmitterSpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.NullType\nimport com.margelo.nitro.core.HybridObject\n\n/**\n * A Kotlin class representing the VideoPlayerEventEmitter HybridObject.\n * Implement this abstract class to create Kotlin-based instances of VideoPlayerEventEmitter.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"SimpleRedundantLet\",\n  \"LocalVariableName\", \"PropertyName\", \"PrivatePropertyName\", \"FunctionName\"\n)\nabstract class HybridVideoPlayerEventEmitterSpec: HybridObject() {\n  // Properties\n  \n\n  // Methods\n  abstract fun addOnAudioBecomingNoisyListener(listener: () -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnAudioBecomingNoisyListener_cxx(listener: Func_void): ListenerSubscription {\n    val __result = addOnAudioBecomingNoisyListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnAudioFocusChangeListener(listener: (hasAudioFocus: Boolean) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnAudioFocusChangeListener_cxx(listener: Func_void_bool): ListenerSubscription {\n    val __result = addOnAudioFocusChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnBandwidthUpdateListener(listener: (data: BandwidthData) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnBandwidthUpdateListener_cxx(listener: Func_void_BandwidthData): ListenerSubscription {\n    val __result = addOnBandwidthUpdateListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnBufferListener(listener: (buffering: Boolean) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnBufferListener_cxx(listener: Func_void_bool): ListenerSubscription {\n    val __result = addOnBufferListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnControlsVisibleChangeListener(listener: (visible: Boolean) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnControlsVisibleChangeListener_cxx(listener: Func_void_bool): ListenerSubscription {\n    val __result = addOnControlsVisibleChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnEndListener(listener: () -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnEndListener_cxx(listener: Func_void): ListenerSubscription {\n    val __result = addOnEndListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnExternalPlaybackChangeListener(listener: (externalPlaybackActive: Boolean) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnExternalPlaybackChangeListener_cxx(listener: Func_void_bool): ListenerSubscription {\n    val __result = addOnExternalPlaybackChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnLoadListener(listener: (data: onLoadData) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnLoadListener_cxx(listener: Func_void_onLoadData): ListenerSubscription {\n    val __result = addOnLoadListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnLoadStartListener(listener: (data: onLoadStartData) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnLoadStartListener_cxx(listener: Func_void_onLoadStartData): ListenerSubscription {\n    val __result = addOnLoadStartListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnPlaybackStateChangeListener(listener: (data: onPlaybackStateChangeData) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnPlaybackStateChangeListener_cxx(listener: Func_void_onPlaybackStateChangeData): ListenerSubscription {\n    val __result = addOnPlaybackStateChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnPlaybackRateChangeListener(listener: (rate: Double) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnPlaybackRateChangeListener_cxx(listener: Func_void_double): ListenerSubscription {\n    val __result = addOnPlaybackRateChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnProgressListener(listener: (data: onProgressData) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnProgressListener_cxx(listener: Func_void_onProgressData): ListenerSubscription {\n    val __result = addOnProgressListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnReadyToDisplayListener(listener: () -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnReadyToDisplayListener_cxx(listener: Func_void): ListenerSubscription {\n    val __result = addOnReadyToDisplayListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnSeekListener(listener: (position: Double) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnSeekListener_cxx(listener: Func_void_double): ListenerSubscription {\n    val __result = addOnSeekListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnStatusChangeListener(listener: (status: VideoPlayerStatus) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnStatusChangeListener_cxx(listener: Func_void_VideoPlayerStatus): ListenerSubscription {\n    val __result = addOnStatusChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnTimedMetadataListener(listener: (data: TimedMetadata) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnTimedMetadataListener_cxx(listener: Func_void_TimedMetadata): ListenerSubscription {\n    val __result = addOnTimedMetadataListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnTextTrackDataChangedListener(listener: (data: Array<String>) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnTextTrackDataChangedListener_cxx(listener: Func_void_std__vector_std__string_): ListenerSubscription {\n    val __result = addOnTextTrackDataChangedListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnTrackChangeListener(listener: (track: Variant_NullType_TextTrack?) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnTrackChangeListener_cxx(listener: Func_void_std__optional_std__variant_nitro__NullType__TextTrack__): ListenerSubscription {\n    val __result = addOnTrackChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnVolumeChangeListener(listener: (data: onVolumeChangeData) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnVolumeChangeListener_cxx(listener: Func_void_onVolumeChangeData): ListenerSubscription {\n    val __result = addOnVolumeChangeListener(listener)\n    return __result\n  }\n  \n  @DoNotStrip\n  @Keep\n  abstract fun clearAllListeners(): Unit\n\n  // Default implementation of `HybridObject.toString()`\n  override fun toString(): String {\n    return \"[HybridObject VideoPlayerEventEmitter]\"\n  }\n\n  // C++ backing class\n  @DoNotStrip\n  @Keep\n  protected open class CxxPart(javaPart: HybridVideoPlayerEventEmitterSpec): HybridObject.CxxPart(javaPart) {\n    // C++ JHybridVideoPlayerEventEmitterSpec::CxxPart::initHybrid(...)\n    external override fun initHybrid(): HybridData\n  }\n  override fun createCxxPart(): CxxPart {\n    return CxxPart(this)\n  }\n\n  companion object {\n    protected const val TAG = \"HybridVideoPlayerEventEmitterSpec\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerFactorySpec.kt",
    "content": "///\n/// HybridVideoPlayerFactorySpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.HybridObject\n\n/**\n * A Kotlin class representing the VideoPlayerFactory HybridObject.\n * Implement this abstract class to create Kotlin-based instances of VideoPlayerFactory.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"SimpleRedundantLet\",\n  \"LocalVariableName\", \"PropertyName\", \"PrivatePropertyName\", \"FunctionName\"\n)\nabstract class HybridVideoPlayerFactorySpec: HybridObject() {\n  // Properties\n  \n\n  // Methods\n  @DoNotStrip\n  @Keep\n  abstract fun createPlayer(source: HybridVideoPlayerSourceSpec): HybridVideoPlayerSpec\n\n  // Default implementation of `HybridObject.toString()`\n  override fun toString(): String {\n    return \"[HybridObject VideoPlayerFactory]\"\n  }\n\n  // C++ backing class\n  @DoNotStrip\n  @Keep\n  protected open class CxxPart(javaPart: HybridVideoPlayerFactorySpec): HybridObject.CxxPart(javaPart) {\n    // C++ JHybridVideoPlayerFactorySpec::CxxPart::initHybrid(...)\n    external override fun initHybrid(): HybridData\n  }\n  override fun createCxxPart(): CxxPart {\n    return CxxPart(this)\n  }\n\n  companion object {\n    protected const val TAG = \"HybridVideoPlayerFactorySpec\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSourceFactorySpec.kt",
    "content": "///\n/// HybridVideoPlayerSourceFactorySpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.HybridObject\n\n/**\n * A Kotlin class representing the VideoPlayerSourceFactory HybridObject.\n * Implement this abstract class to create Kotlin-based instances of VideoPlayerSourceFactory.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"SimpleRedundantLet\",\n  \"LocalVariableName\", \"PropertyName\", \"PrivatePropertyName\", \"FunctionName\"\n)\nabstract class HybridVideoPlayerSourceFactorySpec: HybridObject() {\n  // Properties\n  \n\n  // Methods\n  @DoNotStrip\n  @Keep\n  abstract fun fromUri(uri: String): HybridVideoPlayerSourceSpec\n  \n  @DoNotStrip\n  @Keep\n  abstract fun fromVideoConfig(config: NativeVideoConfig): HybridVideoPlayerSourceSpec\n\n  // Default implementation of `HybridObject.toString()`\n  override fun toString(): String {\n    return \"[HybridObject VideoPlayerSourceFactory]\"\n  }\n\n  // C++ backing class\n  @DoNotStrip\n  @Keep\n  protected open class CxxPart(javaPart: HybridVideoPlayerSourceFactorySpec): HybridObject.CxxPart(javaPart) {\n    // C++ JHybridVideoPlayerSourceFactorySpec::CxxPart::initHybrid(...)\n    external override fun initHybrid(): HybridData\n  }\n  override fun createCxxPart(): CxxPart {\n    return CxxPart(this)\n  }\n\n  companion object {\n    protected const val TAG = \"HybridVideoPlayerSourceFactorySpec\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSourceSpec.kt",
    "content": "///\n/// HybridVideoPlayerSourceSpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.Promise\nimport com.margelo.nitro.core.HybridObject\n\n/**\n * A Kotlin class representing the VideoPlayerSource HybridObject.\n * Implement this abstract class to create Kotlin-based instances of VideoPlayerSource.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"SimpleRedundantLet\",\n  \"LocalVariableName\", \"PropertyName\", \"PrivatePropertyName\", \"FunctionName\"\n)\nabstract class HybridVideoPlayerSourceSpec: HybridObject() {\n  // Properties\n  @get:DoNotStrip\n  @get:Keep\n  abstract val uri: String\n  \n  @get:DoNotStrip\n  @get:Keep\n  abstract val config: NativeVideoConfig\n\n  // Methods\n  @DoNotStrip\n  @Keep\n  abstract fun getAssetInformationAsync(): Promise<VideoInformation>\n\n  // Default implementation of `HybridObject.toString()`\n  override fun toString(): String {\n    return \"[HybridObject VideoPlayerSource]\"\n  }\n\n  // C++ backing class\n  @DoNotStrip\n  @Keep\n  protected open class CxxPart(javaPart: HybridVideoPlayerSourceSpec): HybridObject.CxxPart(javaPart) {\n    // C++ JHybridVideoPlayerSourceSpec::CxxPart::initHybrid(...)\n    external override fun initHybrid(): HybridData\n  }\n  override fun createCxxPart(): CxxPart {\n    return CxxPart(this)\n  }\n\n  companion object {\n    protected const val TAG = \"HybridVideoPlayerSourceSpec\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoPlayerSpec.kt",
    "content": "///\n/// HybridVideoPlayerSpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.Promise\nimport com.margelo.nitro.core.NullType\nimport com.margelo.nitro.core.HybridObject\n\n/**\n * A Kotlin class representing the VideoPlayer HybridObject.\n * Implement this abstract class to create Kotlin-based instances of VideoPlayer.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"SimpleRedundantLet\",\n  \"LocalVariableName\", \"PropertyName\", \"PrivatePropertyName\", \"FunctionName\"\n)\nabstract class HybridVideoPlayerSpec: HybridObject() {\n  // Properties\n  @get:DoNotStrip\n  @get:Keep\n  abstract val source: HybridVideoPlayerSourceSpec\n  \n  @get:DoNotStrip\n  @get:Keep\n  abstract val eventEmitter: HybridVideoPlayerEventEmitterSpec\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var showNotificationControls: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  abstract val status: VideoPlayerStatus\n  \n  @get:DoNotStrip\n  @get:Keep\n  abstract val duration: Double\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var volume: Double\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var currentTime: Double\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var muted: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var loop: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var rate: Double\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var mixAudioMode: MixAudioMode\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var ignoreSilentSwitchMode: IgnoreSilentSwitchMode\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var playInBackground: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var playWhenInactive: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  abstract val isPlaying: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  abstract val selectedTrack: TextTrack?\n\n  // Methods\n  @DoNotStrip\n  @Keep\n  abstract fun replaceSourceAsync(source: Variant_NullType_HybridVideoPlayerSourceSpec?): Promise<Unit>\n  \n  @DoNotStrip\n  @Keep\n  abstract fun getAvailableTextTracks(): Array<TextTrack>\n  \n  @DoNotStrip\n  @Keep\n  abstract fun selectTextTrack(textTrack: Variant_NullType_TextTrack?): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun release(): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun initialize(): Promise<Unit>\n  \n  @DoNotStrip\n  @Keep\n  abstract fun preload(): Promise<Unit>\n  \n  @DoNotStrip\n  @Keep\n  abstract fun play(): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun pause(): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun seekBy(time: Double): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun seekTo(time: Double): Unit\n\n  // Default implementation of `HybridObject.toString()`\n  override fun toString(): String {\n    return \"[HybridObject VideoPlayer]\"\n  }\n\n  // C++ backing class\n  @DoNotStrip\n  @Keep\n  protected open class CxxPart(javaPart: HybridVideoPlayerSpec): HybridObject.CxxPart(javaPart) {\n    // C++ JHybridVideoPlayerSpec::CxxPart::initHybrid(...)\n    external override fun initHybrid(): HybridData\n  }\n  override fun createCxxPart(): CxxPart {\n    return CxxPart(this)\n  }\n\n  companion object {\n    protected const val TAG = \"HybridVideoPlayerSpec\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoViewViewManagerFactorySpec.kt",
    "content": "///\n/// HybridVideoViewViewManagerFactorySpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.HybridObject\n\n/**\n * A Kotlin class representing the VideoViewViewManagerFactory HybridObject.\n * Implement this abstract class to create Kotlin-based instances of VideoViewViewManagerFactory.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"SimpleRedundantLet\",\n  \"LocalVariableName\", \"PropertyName\", \"PrivatePropertyName\", \"FunctionName\"\n)\nabstract class HybridVideoViewViewManagerFactorySpec: HybridObject() {\n  // Properties\n  \n\n  // Methods\n  @DoNotStrip\n  @Keep\n  abstract fun createViewManager(nitroId: Double): HybridVideoViewViewManagerSpec\n\n  // Default implementation of `HybridObject.toString()`\n  override fun toString(): String {\n    return \"[HybridObject VideoViewViewManagerFactory]\"\n  }\n\n  // C++ backing class\n  @DoNotStrip\n  @Keep\n  protected open class CxxPart(javaPart: HybridVideoViewViewManagerFactorySpec): HybridObject.CxxPart(javaPart) {\n    // C++ JHybridVideoViewViewManagerFactorySpec::CxxPart::initHybrid(...)\n    external override fun initHybrid(): HybridData\n  }\n  override fun createCxxPart(): CxxPart {\n    return CxxPart(this)\n  }\n\n  companion object {\n    protected const val TAG = \"HybridVideoViewViewManagerFactorySpec\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/HybridVideoViewViewManagerSpec.kt",
    "content": "///\n/// HybridVideoViewViewManagerSpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.jni.HybridData\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.HybridObject\n\n/**\n * A Kotlin class representing the VideoViewViewManager HybridObject.\n * Implement this abstract class to create Kotlin-based instances of VideoViewViewManager.\n */\n@DoNotStrip\n@Keep\n@Suppress(\n  \"KotlinJniMissingFunction\", \"unused\",\n  \"RedundantSuppression\", \"RedundantUnitReturnType\", \"SimpleRedundantLet\",\n  \"LocalVariableName\", \"PropertyName\", \"PrivatePropertyName\", \"FunctionName\"\n)\nabstract class HybridVideoViewViewManagerSpec: HybridObject() {\n  // Properties\n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var player: HybridVideoPlayerSpec?\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var controls: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var pictureInPicture: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var autoEnterPictureInPicture: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var resizeMode: ResizeMode\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var keepScreenAwake: Boolean\n  \n  @get:DoNotStrip\n  @get:Keep\n  @set:DoNotStrip\n  @set:Keep\n  abstract var surfaceType: SurfaceType\n\n  // Methods\n  @DoNotStrip\n  @Keep\n  abstract fun enterFullscreen(): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun exitFullscreen(): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun enterPictureInPicture(): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun exitPictureInPicture(): Unit\n  \n  @DoNotStrip\n  @Keep\n  abstract fun canEnterPictureInPicture(): Boolean\n  \n  abstract fun addOnPictureInPictureChangeListener(listener: (isInPictureInPicture: Boolean) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnPictureInPictureChangeListener_cxx(listener: Func_void_bool): ListenerSubscription {\n    val __result = addOnPictureInPictureChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addOnFullscreenChangeListener(listener: (fullscreen: Boolean) -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addOnFullscreenChangeListener_cxx(listener: Func_void_bool): ListenerSubscription {\n    val __result = addOnFullscreenChangeListener(listener)\n    return __result\n  }\n  \n  abstract fun addWillEnterFullscreenListener(listener: () -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addWillEnterFullscreenListener_cxx(listener: Func_void): ListenerSubscription {\n    val __result = addWillEnterFullscreenListener(listener)\n    return __result\n  }\n  \n  abstract fun addWillExitFullscreenListener(listener: () -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addWillExitFullscreenListener_cxx(listener: Func_void): ListenerSubscription {\n    val __result = addWillExitFullscreenListener(listener)\n    return __result\n  }\n  \n  abstract fun addWillEnterPictureInPictureListener(listener: () -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addWillEnterPictureInPictureListener_cxx(listener: Func_void): ListenerSubscription {\n    val __result = addWillEnterPictureInPictureListener(listener)\n    return __result\n  }\n  \n  abstract fun addWillExitPictureInPictureListener(listener: () -> Unit): ListenerSubscription\n  \n  @DoNotStrip\n  @Keep\n  private fun addWillExitPictureInPictureListener_cxx(listener: Func_void): ListenerSubscription {\n    val __result = addWillExitPictureInPictureListener(listener)\n    return __result\n  }\n  \n  @DoNotStrip\n  @Keep\n  abstract fun clearAllListeners(): Unit\n\n  // Default implementation of `HybridObject.toString()`\n  override fun toString(): String {\n    return \"[HybridObject VideoViewViewManager]\"\n  }\n\n  // C++ backing class\n  @DoNotStrip\n  @Keep\n  protected open class CxxPart(javaPart: HybridVideoViewViewManagerSpec): HybridObject.CxxPart(javaPart) {\n    // C++ JHybridVideoViewViewManagerSpec::CxxPart::initHybrid(...)\n    external override fun initHybrid(): HybridData\n  }\n  override fun createCxxPart(): CxxPart {\n    return CxxPart(this)\n  }\n\n  companion object {\n    protected const val TAG = \"HybridVideoViewViewManagerSpec\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/IgnoreSilentSwitchMode.kt",
    "content": "///\n/// IgnoreSilentSwitchMode.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n/**\n * Represents the JavaScript enum/union \"IgnoreSilentSwitchMode\".\n */\n@DoNotStrip\n@Keep\nenum class IgnoreSilentSwitchMode(@DoNotStrip @Keep val value: Int) {\n  AUTO(0),\n  IGNORE(1),\n  OBEY(2);\n\n  companion object\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ListenerSubscription.kt",
    "content": "///\n/// ListenerSubscription.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"ListenerSubscription\".\n */\n@DoNotStrip\n@Keep\ndata class ListenerSubscription(\n  @DoNotStrip\n  @Keep\n  val remove: Func_void\n) {\n  /**\n   * Create a new instance of ListenerSubscription from Kotlin\n   */\n  constructor(remove: () -> Unit):\n         this(Func_void_java(remove))\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(remove: Func_void): ListenerSubscription {\n      return ListenerSubscription(remove)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/LivePlaybackParams.kt",
    "content": "///\n/// LivePlaybackParams.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"LivePlaybackParams\".\n */\n@DoNotStrip\n@Keep\ndata class LivePlaybackParams(\n  @DoNotStrip\n  @Keep\n  val minPlaybackSpeed: Double?,\n  @DoNotStrip\n  @Keep\n  val maxPlaybackSpeed: Double?,\n  @DoNotStrip\n  @Keep\n  val maxOffsetMs: Double?,\n  @DoNotStrip\n  @Keep\n  val minOffsetMs: Double?,\n  @DoNotStrip\n  @Keep\n  val targetOffsetMs: Double?\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(minPlaybackSpeed: Double?, maxPlaybackSpeed: Double?, maxOffsetMs: Double?, minOffsetMs: Double?, targetOffsetMs: Double?): LivePlaybackParams {\n      return LivePlaybackParams(minPlaybackSpeed, maxPlaybackSpeed, maxOffsetMs, minOffsetMs, targetOffsetMs)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/MixAudioMode.kt",
    "content": "///\n/// MixAudioMode.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n/**\n * Represents the JavaScript enum/union \"MixAudioMode\".\n */\n@DoNotStrip\n@Keep\nenum class MixAudioMode(@DoNotStrip @Keep val value: Int) {\n  MIXWITHOTHERS(0),\n  DONOTMIX(1),\n  DUCKOTHERS(2),\n  AUTO(3);\n\n  companion object\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeDrmParams.kt",
    "content": "///\n/// NativeDrmParams.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.Promise\n\n/**\n * Represents the JavaScript object/struct \"NativeDrmParams\".\n */\n@DoNotStrip\n@Keep\ndata class NativeDrmParams(\n  @DoNotStrip\n  @Keep\n  val type: String?,\n  @DoNotStrip\n  @Keep\n  val licenseUrl: String?,\n  @DoNotStrip\n  @Keep\n  val certificateUrl: String?,\n  @DoNotStrip\n  @Keep\n  val contentId: String?,\n  @DoNotStrip\n  @Keep\n  val licenseHeaders: Map<String, String>?,\n  @DoNotStrip\n  @Keep\n  val multiSession: Boolean?,\n  @DoNotStrip\n  @Keep\n  val getLicense: Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload?\n) {\n  /**\n   * Create a new instance of NativeDrmParams from Kotlin\n   */\n  constructor(type: String?, licenseUrl: String?, certificateUrl: String?, contentId: String?, licenseHeaders: Map<String, String>?, multiSession: Boolean?, getLicense: ((payload: OnGetLicensePayload) -> Promise<Promise<String>>)?):\n         this(type, licenseUrl, certificateUrl, contentId, licenseHeaders, multiSession, getLicense?.let { Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_java(it) })\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(type: String?, licenseUrl: String?, certificateUrl: String?, contentId: String?, licenseHeaders: Map<String, String>?, multiSession: Boolean?, getLicense: Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload?): NativeDrmParams {\n      return NativeDrmParams(type, licenseUrl, certificateUrl, contentId, licenseHeaders, multiSession, getLicense)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeExternalSubtitle.kt",
    "content": "///\n/// NativeExternalSubtitle.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"NativeExternalSubtitle\".\n */\n@DoNotStrip\n@Keep\ndata class NativeExternalSubtitle(\n  @DoNotStrip\n  @Keep\n  val uri: String,\n  @DoNotStrip\n  @Keep\n  val label: String,\n  @DoNotStrip\n  @Keep\n  val type: SubtitleType,\n  @DoNotStrip\n  @Keep\n  val language: String\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(uri: String, label: String, type: SubtitleType, language: String): NativeExternalSubtitle {\n      return NativeExternalSubtitle(uri, label, type, language)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/NativeVideoConfig.kt",
    "content": "///\n/// NativeVideoConfig.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"NativeVideoConfig\".\n */\n@DoNotStrip\n@Keep\ndata class NativeVideoConfig(\n  @DoNotStrip\n  @Keep\n  val uri: String,\n  @DoNotStrip\n  @Keep\n  val externalSubtitles: Array<NativeExternalSubtitle>?,\n  @DoNotStrip\n  @Keep\n  val drm: NativeDrmParams?,\n  @DoNotStrip\n  @Keep\n  val headers: Map<String, String>?,\n  @DoNotStrip\n  @Keep\n  val bufferConfig: BufferConfig?,\n  @DoNotStrip\n  @Keep\n  val metadata: CustomVideoMetadata?,\n  @DoNotStrip\n  @Keep\n  val initializeOnCreation: Boolean?\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(uri: String, externalSubtitles: Array<NativeExternalSubtitle>?, drm: NativeDrmParams?, headers: Map<String, String>?, bufferConfig: BufferConfig?, metadata: CustomVideoMetadata?, initializeOnCreation: Boolean?): NativeVideoConfig {\n      return NativeVideoConfig(uri, externalSubtitles, drm, headers, bufferConfig, metadata, initializeOnCreation)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/OnGetLicensePayload.kt",
    "content": "///\n/// OnGetLicensePayload.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"OnGetLicensePayload\".\n */\n@DoNotStrip\n@Keep\ndata class OnGetLicensePayload(\n  @DoNotStrip\n  @Keep\n  val contentId: String,\n  @DoNotStrip\n  @Keep\n  val licenseUrl: String,\n  @DoNotStrip\n  @Keep\n  val keyUrl: String,\n  @DoNotStrip\n  @Keep\n  val spc: String\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(contentId: String, licenseUrl: String, keyUrl: String, spc: String): OnGetLicensePayload {\n      return OnGetLicensePayload(contentId, licenseUrl, keyUrl, spc)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ReactNativeVideoOnLoad.kt",
    "content": "///\n/// ReactNativeVideoOnLoad.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport android.util.Log\n\ninternal class ReactNativeVideoOnLoad {\n  companion object {\n    private const val TAG = \"ReactNativeVideoOnLoad\"\n    private var didLoad = false\n    /**\n     * Initializes the native part of \"ReactNativeVideo\".\n     * This method is idempotent and can be called more than once.\n     */\n    @JvmStatic\n    fun initializeNative() {\n      if (didLoad) return\n      try {\n        Log.i(TAG, \"Loading ReactNativeVideo C++ library...\")\n        System.loadLibrary(\"ReactNativeVideo\")\n        Log.i(TAG, \"Successfully loaded ReactNativeVideo C++ library!\")\n        didLoad = true\n      } catch (e: Error) {\n        Log.e(TAG, \"Failed to load ReactNativeVideo C++ library! Is it properly installed and linked? \" +\n                    \"Is the name correct? (see `CMakeLists.txt`, at `add_library(...)`)\", e)\n        throw e\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/ResizeMode.kt",
    "content": "///\n/// ResizeMode.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n/**\n * Represents the JavaScript enum/union \"ResizeMode\".\n */\n@DoNotStrip\n@Keep\nenum class ResizeMode(@DoNotStrip @Keep val value: Int) {\n  CONTAIN(0),\n  COVER(1),\n  STRETCH(2),\n  NONE(3);\n\n  companion object\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Resolution.kt",
    "content": "///\n/// Resolution.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"Resolution\".\n */\n@DoNotStrip\n@Keep\ndata class Resolution(\n  @DoNotStrip\n  @Keep\n  val width: Double,\n  @DoNotStrip\n  @Keep\n  val height: Double\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(width: Double, height: Double): Resolution {\n      return Resolution(width, height)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SourceType.kt",
    "content": "///\n/// SourceType.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n/**\n * Represents the JavaScript enum/union \"SourceType\".\n */\n@DoNotStrip\n@Keep\nenum class SourceType(@DoNotStrip @Keep val value: Int) {\n  LOCAL(0),\n  NETWORK(1);\n\n  companion object\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SubtitleType.kt",
    "content": "///\n/// SubtitleType.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n/**\n * Represents the JavaScript enum/union \"SubtitleType\".\n */\n@DoNotStrip\n@Keep\nenum class SubtitleType(@DoNotStrip @Keep val value: Int) {\n  AUTO(0),\n  VTT(1),\n  SRT(2),\n  SSA(3),\n  ASS(4);\n\n  companion object\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/SurfaceType.kt",
    "content": "///\n/// SurfaceType.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n/**\n * Represents the JavaScript enum/union \"SurfaceType\".\n */\n@DoNotStrip\n@Keep\nenum class SurfaceType(@DoNotStrip @Keep val value: Int) {\n  SURFACE(0),\n  TEXTURE(1);\n\n  companion object\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TextTrack.kt",
    "content": "///\n/// TextTrack.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"TextTrack\".\n */\n@DoNotStrip\n@Keep\ndata class TextTrack(\n  @DoNotStrip\n  @Keep\n  val id: String,\n  @DoNotStrip\n  @Keep\n  val label: String,\n  @DoNotStrip\n  @Keep\n  val language: String?,\n  @DoNotStrip\n  @Keep\n  val selected: Boolean\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(id: String, label: String, language: String?, selected: Boolean): TextTrack {\n      return TextTrack(id, label, language, selected)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TimedMetadata.kt",
    "content": "///\n/// TimedMetadata.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"TimedMetadata\".\n */\n@DoNotStrip\n@Keep\ndata class TimedMetadata(\n  @DoNotStrip\n  @Keep\n  val metadata: Array<TimedMetadataObject>\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(metadata: Array<TimedMetadataObject>): TimedMetadata {\n      return TimedMetadata(metadata)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/TimedMetadataObject.kt",
    "content": "///\n/// TimedMetadataObject.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"TimedMetadataObject\".\n */\n@DoNotStrip\n@Keep\ndata class TimedMetadataObject(\n  @DoNotStrip\n  @Keep\n  val value: String,\n  @DoNotStrip\n  @Keep\n  val identifier: String\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(value: String, identifier: String): TimedMetadataObject {\n      return TimedMetadataObject(value, identifier)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Variant_NullType_HybridVideoPlayerSourceSpec.kt",
    "content": "///\n/// Variant_NullType_HybridVideoPlayerSourceSpec.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.NullType\n\n/**\n * Represents the TypeScript variant \"NullType | HybridVideoPlayerSourceSpec\".\n */\n@Suppress(\"ClassName\")\n@DoNotStrip\nsealed class Variant_NullType_HybridVideoPlayerSourceSpec {\n  @DoNotStrip\n  data class First(@DoNotStrip val value: NullType): Variant_NullType_HybridVideoPlayerSourceSpec()\n  @DoNotStrip\n  data class Second(@DoNotStrip val value: HybridVideoPlayerSourceSpec): Variant_NullType_HybridVideoPlayerSourceSpec()\n\n  val isFirst: Boolean\n    get() = this is First\n  val isSecond: Boolean\n    get() = this is Second\n\n  fun asFirstOrNull(): NullType? {\n    val value = (this as? First)?.value ?: return null\n    return value\n  }\n  fun asSecondOrNull(): HybridVideoPlayerSourceSpec? {\n    val value = (this as? Second)?.value ?: return null\n    return value\n  }\n\n  inline fun <R> match(first: (NullType) -> R, second: (HybridVideoPlayerSourceSpec) -> R): R {\n    return when (this) {\n      is First -> first(value)\n      is Second -> second(value)\n    }\n  }\n\n  companion object {\n    @JvmStatic\n    @DoNotStrip\n    fun create(value: NullType): Variant_NullType_HybridVideoPlayerSourceSpec = First(value)\n    @JvmStatic\n    @DoNotStrip\n    fun create(value: HybridVideoPlayerSourceSpec): Variant_NullType_HybridVideoPlayerSourceSpec = Second(value)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/Variant_NullType_TextTrack.kt",
    "content": "///\n/// Variant_NullType_TextTrack.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport com.facebook.proguard.annotations.DoNotStrip\nimport com.margelo.nitro.core.NullType\n\n/**\n * Represents the TypeScript variant \"NullType | TextTrack\".\n */\n@Suppress(\"ClassName\")\n@DoNotStrip\nsealed class Variant_NullType_TextTrack {\n  @DoNotStrip\n  data class First(@DoNotStrip val value: NullType): Variant_NullType_TextTrack()\n  @DoNotStrip\n  data class Second(@DoNotStrip val value: TextTrack): Variant_NullType_TextTrack()\n\n  val isFirst: Boolean\n    get() = this is First\n  val isSecond: Boolean\n    get() = this is Second\n\n  fun asFirstOrNull(): NullType? {\n    val value = (this as? First)?.value ?: return null\n    return value\n  }\n  fun asSecondOrNull(): TextTrack? {\n    val value = (this as? Second)?.value ?: return null\n    return value\n  }\n\n  inline fun <R> match(first: (NullType) -> R, second: (TextTrack) -> R): R {\n    return when (this) {\n      is First -> first(value)\n      is Second -> second(value)\n    }\n  }\n\n  companion object {\n    @JvmStatic\n    @DoNotStrip\n    fun create(value: NullType): Variant_NullType_TextTrack = First(value)\n    @JvmStatic\n    @DoNotStrip\n    fun create(value: TextTrack): Variant_NullType_TextTrack = Second(value)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoInformation.kt",
    "content": "///\n/// VideoInformation.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"VideoInformation\".\n */\n@DoNotStrip\n@Keep\ndata class VideoInformation(\n  @DoNotStrip\n  @Keep\n  val bitrate: Double,\n  @DoNotStrip\n  @Keep\n  val width: Double,\n  @DoNotStrip\n  @Keep\n  val height: Double,\n  @DoNotStrip\n  @Keep\n  val duration: Double,\n  @DoNotStrip\n  @Keep\n  val fileSize: Long,\n  @DoNotStrip\n  @Keep\n  val isHDR: Boolean,\n  @DoNotStrip\n  @Keep\n  val isLive: Boolean,\n  @DoNotStrip\n  @Keep\n  val orientation: VideoOrientation\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(bitrate: Double, width: Double, height: Double, duration: Double, fileSize: Long, isHDR: Boolean, isLive: Boolean, orientation: VideoOrientation): VideoInformation {\n      return VideoInformation(bitrate, width, height, duration, fileSize, isHDR, isLive, orientation)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoOrientation.kt",
    "content": "///\n/// VideoOrientation.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n/**\n * Represents the JavaScript enum/union \"VideoOrientation\".\n */\n@DoNotStrip\n@Keep\nenum class VideoOrientation(@DoNotStrip @Keep val value: Int) {\n  PORTRAIT(0),\n  LANDSCAPE(1),\n  PORTRAIT_UPSIDE_DOWN(2),\n  LANDSCAPE_LEFT(3),\n  LANDSCAPE_RIGHT(4),\n  SQUARE(5),\n  UNKNOWN(6);\n\n  companion object\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/VideoPlayerStatus.kt",
    "content": "///\n/// VideoPlayerStatus.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n/**\n * Represents the JavaScript enum/union \"VideoPlayerStatus\".\n */\n@DoNotStrip\n@Keep\nenum class VideoPlayerStatus(@DoNotStrip @Keep val value: Int) {\n  IDLE(0),\n  LOADING(1),\n  READYTOPLAY(2),\n  ERROR(3);\n\n  companion object\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onLoadData.kt",
    "content": "///\n/// onLoadData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"onLoadData\".\n */\n@DoNotStrip\n@Keep\ndata class onLoadData(\n  @DoNotStrip\n  @Keep\n  val currentTime: Double,\n  @DoNotStrip\n  @Keep\n  val duration: Double,\n  @DoNotStrip\n  @Keep\n  val height: Double,\n  @DoNotStrip\n  @Keep\n  val width: Double,\n  @DoNotStrip\n  @Keep\n  val orientation: VideoOrientation\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(currentTime: Double, duration: Double, height: Double, width: Double, orientation: VideoOrientation): onLoadData {\n      return onLoadData(currentTime, duration, height, width, orientation)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onLoadStartData.kt",
    "content": "///\n/// onLoadStartData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"onLoadStartData\".\n */\n@DoNotStrip\n@Keep\ndata class onLoadStartData(\n  @DoNotStrip\n  @Keep\n  val sourceType: SourceType,\n  @DoNotStrip\n  @Keep\n  val source: HybridVideoPlayerSourceSpec\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(sourceType: SourceType, source: HybridVideoPlayerSourceSpec): onLoadStartData {\n      return onLoadStartData(sourceType, source)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onPlaybackStateChangeData.kt",
    "content": "///\n/// onPlaybackStateChangeData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"onPlaybackStateChangeData\".\n */\n@DoNotStrip\n@Keep\ndata class onPlaybackStateChangeData(\n  @DoNotStrip\n  @Keep\n  val isPlaying: Boolean,\n  @DoNotStrip\n  @Keep\n  val isBuffering: Boolean\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(isPlaying: Boolean, isBuffering: Boolean): onPlaybackStateChangeData {\n      return onPlaybackStateChangeData(isPlaying, isBuffering)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onProgressData.kt",
    "content": "///\n/// onProgressData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"onProgressData\".\n */\n@DoNotStrip\n@Keep\ndata class onProgressData(\n  @DoNotStrip\n  @Keep\n  val currentTime: Double,\n  @DoNotStrip\n  @Keep\n  val bufferDuration: Double\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(currentTime: Double, bufferDuration: Double): onProgressData {\n      return onProgressData(currentTime, bufferDuration)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/android/kotlin/com/margelo/nitro/video/onVolumeChangeData.kt",
    "content": "///\n/// onVolumeChangeData.kt\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\npackage com.margelo.nitro.video\n\nimport androidx.annotation.Keep\nimport com.facebook.proguard.annotations.DoNotStrip\n\n\n/**\n * Represents the JavaScript object/struct \"onVolumeChangeData\".\n */\n@DoNotStrip\n@Keep\ndata class onVolumeChangeData(\n  @DoNotStrip\n  @Keep\n  val volume: Double,\n  @DoNotStrip\n  @Keep\n  val muted: Boolean\n) {\n  /* primary constructor */\n\n  companion object {\n    /**\n     * Constructor called from C++\n     */\n    @DoNotStrip\n    @Keep\n    @Suppress(\"unused\")\n    @JvmStatic\n    private fun fromCpp(volume: Double, muted: Boolean): onVolumeChangeData {\n      return onVolumeChangeData(volume, muted)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/ReactNativeVideo+autolinking.rb",
    "content": "#\n# ReactNativeVideo+autolinking.rb\n# This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n# https://github.com/mrousavy/nitro\n# Copyright © Marc Rousavy @ Margelo\n#\n\n# This is a Ruby script that adds all files generated by Nitrogen\n# to the given podspec.\n#\n# To use it, add this to your .podspec:\n# ```ruby\n# Pod::Spec.new do |spec|\n#   # ...\n#\n#   # Add all files generated by Nitrogen\n#   load 'nitrogen/generated/ios/ReactNativeVideo+autolinking.rb'\n#   add_nitrogen_files(spec)\n# end\n# ```\n\ndef add_nitrogen_files(spec)\n  Pod::UI.puts \"[NitroModules] 🔥 ReactNativeVideo is boosted by nitro!\"\n\n  spec.dependency \"NitroModules\"\n\n  current_source_files = Array(spec.attributes_hash['source_files'])\n  spec.source_files = current_source_files + [\n    # Generated cross-platform specs\n    \"nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}\",\n    # Generated bridges for the cross-platform specs\n    \"nitrogen/generated/ios/**/*.{h,hpp,c,cpp,mm,swift}\",\n  ]\n\n  current_public_header_files = Array(spec.attributes_hash['public_header_files'])\n  spec.public_header_files = current_public_header_files + [\n    # Generated specs\n    \"nitrogen/generated/shared/**/*.{h,hpp}\",\n    # Swift to C++ bridging helpers\n    \"nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.hpp\"\n  ]\n\n  current_private_header_files = Array(spec.attributes_hash['private_header_files'])\n  spec.private_header_files = current_private_header_files + [\n    # iOS specific specs\n    \"nitrogen/generated/ios/c++/**/*.{h,hpp}\",\n    # Views are framework-specific and should be private\n    \"nitrogen/generated/shared/**/views/**/*\"\n  ]\n\n  current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {}\n  spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({\n    # Use C++ 20\n    \"CLANG_CXX_LANGUAGE_STANDARD\" => \"c++20\",\n    # Enables C++ <-> Swift interop (by default it's only ObjC)\n    \"SWIFT_OBJC_INTEROP_MODE\" => \"objcxx\",\n    # Enables stricter modular headers\n    \"DEFINES_MODULE\" => \"YES\",\n  })\nend\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.cpp",
    "content": "///\n/// ReactNativeVideo-Swift-Cxx-Bridge.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"ReactNativeVideo-Swift-Cxx-Bridge.hpp\"\n\n// Include C++ implementation defined types\n#include \"HybridVideoPlayerEventEmitterSpecSwift.hpp\"\n#include \"HybridVideoPlayerFactorySpecSwift.hpp\"\n#include \"HybridVideoPlayerSourceFactorySpecSwift.hpp\"\n#include \"HybridVideoPlayerSourceSpecSwift.hpp\"\n#include \"HybridVideoPlayerSpecSwift.hpp\"\n#include \"HybridVideoViewViewManagerFactorySpecSwift.hpp\"\n#include \"HybridVideoViewViewManagerSpecSwift.hpp\"\n#include \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n#include <NitroModules/NitroDefines.hpp>\n\nnamespace margelo::nitro::video::bridge::swift {\n\n  // pragma MARK: std::shared_ptr<HybridVideoPlayerSourceSpec>\n  std::shared_ptr<HybridVideoPlayerSourceSpec> create_std__shared_ptr_HybridVideoPlayerSourceSpec_(void* NON_NULL swiftUnsafePointer) noexcept {\n    ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx::fromUnsafe(swiftUnsafePointer);\n    return std::make_shared<margelo::nitro::video::HybridVideoPlayerSourceSpecSwift>(swiftPart);\n  }\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceSpec_(std__shared_ptr_HybridVideoPlayerSourceSpec_ cppType) {\n    std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSourceSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerSourceSpecSwift>(cppType);\n    #ifdef NITRO_DEBUG\n    if (swiftWrapper == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Class \\\"HybridVideoPlayerSourceSpec\\\" is not implemented in Swift!\");\n    }\n    #endif\n    ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx& swiftPart = swiftWrapper->getSwiftPart();\n    return swiftPart.toUnsafe();\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoPlayerEventEmitterSpec>\n  std::shared_ptr<HybridVideoPlayerEventEmitterSpec> create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(void* NON_NULL swiftUnsafePointer) noexcept {\n    ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx::fromUnsafe(swiftUnsafePointer);\n    return std::make_shared<margelo::nitro::video::HybridVideoPlayerEventEmitterSpecSwift>(swiftPart);\n  }\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ cppType) {\n    std::shared_ptr<margelo::nitro::video::HybridVideoPlayerEventEmitterSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerEventEmitterSpecSwift>(cppType);\n    #ifdef NITRO_DEBUG\n    if (swiftWrapper == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Class \\\"HybridVideoPlayerEventEmitterSpec\\\" is not implemented in Swift!\");\n    }\n    #endif\n    ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx& swiftPart = swiftWrapper->getSwiftPart();\n    return swiftPart.toUnsafe();\n  }\n  \n  // pragma MARK: std::function<void()>\n  Func_void create_Func_void(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)]() mutable -> void {\n      swiftClosure.call();\n    };\n  }\n  \n  // pragma MARK: std::function<void(const std::exception_ptr& /* error */)>\n  Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_std__exception_ptr::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const std::exception_ptr& error) mutable -> void {\n      swiftClosure.call(error);\n    };\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoPlayerSpec>\n  std::shared_ptr<HybridVideoPlayerSpec> create_std__shared_ptr_HybridVideoPlayerSpec_(void* NON_NULL swiftUnsafePointer) noexcept {\n    ReactNativeVideo::HybridVideoPlayerSpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSpec_cxx::fromUnsafe(swiftUnsafePointer);\n    return std::make_shared<margelo::nitro::video::HybridVideoPlayerSpecSwift>(swiftPart);\n  }\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSpec_(std__shared_ptr_HybridVideoPlayerSpec_ cppType) {\n    std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerSpecSwift>(cppType);\n    #ifdef NITRO_DEBUG\n    if (swiftWrapper == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Class \\\"HybridVideoPlayerSpec\\\" is not implemented in Swift!\");\n    }\n    #endif\n    ReactNativeVideo::HybridVideoPlayerSpec_cxx& swiftPart = swiftWrapper->getSwiftPart();\n    return swiftPart.toUnsafe();\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoPlayerFactorySpec>\n  std::shared_ptr<HybridVideoPlayerFactorySpec> create_std__shared_ptr_HybridVideoPlayerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept {\n    ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx::fromUnsafe(swiftUnsafePointer);\n    return std::make_shared<margelo::nitro::video::HybridVideoPlayerFactorySpecSwift>(swiftPart);\n  }\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerFactorySpec_(std__shared_ptr_HybridVideoPlayerFactorySpec_ cppType) {\n    std::shared_ptr<margelo::nitro::video::HybridVideoPlayerFactorySpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerFactorySpecSwift>(cppType);\n    #ifdef NITRO_DEBUG\n    if (swiftWrapper == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Class \\\"HybridVideoPlayerFactorySpec\\\" is not implemented in Swift!\");\n    }\n    #endif\n    ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx& swiftPart = swiftWrapper->getSwiftPart();\n    return swiftPart.toUnsafe();\n  }\n  \n  // pragma MARK: std::function<void(bool /* hasAudioFocus */)>\n  Func_void_bool create_Func_void_bool(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_bool::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](bool hasAudioFocus) mutable -> void {\n      swiftClosure.call(hasAudioFocus);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const BandwidthData& /* data */)>\n  Func_void_BandwidthData create_Func_void_BandwidthData(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_BandwidthData::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const BandwidthData& data) mutable -> void {\n      swiftClosure.call(data);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const onLoadData& /* data */)>\n  Func_void_onLoadData create_Func_void_onLoadData(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_onLoadData::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const onLoadData& data) mutable -> void {\n      swiftClosure.call(data);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const onLoadStartData& /* data */)>\n  Func_void_onLoadStartData create_Func_void_onLoadStartData(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_onLoadStartData::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const onLoadStartData& data) mutable -> void {\n      swiftClosure.call(data);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const onPlaybackStateChangeData& /* data */)>\n  Func_void_onPlaybackStateChangeData create_Func_void_onPlaybackStateChangeData(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_onPlaybackStateChangeData::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const onPlaybackStateChangeData& data) mutable -> void {\n      swiftClosure.call(data);\n    };\n  }\n  \n  // pragma MARK: std::function<void(double /* rate */)>\n  Func_void_double create_Func_void_double(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_double::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](double rate) mutable -> void {\n      swiftClosure.call(rate);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const onProgressData& /* data */)>\n  Func_void_onProgressData create_Func_void_onProgressData(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_onProgressData::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const onProgressData& data) mutable -> void {\n      swiftClosure.call(data);\n    };\n  }\n  \n  // pragma MARK: std::function<void(VideoPlayerStatus /* status */)>\n  Func_void_VideoPlayerStatus create_Func_void_VideoPlayerStatus(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_VideoPlayerStatus::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](VideoPlayerStatus status) mutable -> void {\n      swiftClosure.call(static_cast<int>(status));\n    };\n  }\n  \n  // pragma MARK: std::function<void(const TimedMetadata& /* data */)>\n  Func_void_TimedMetadata create_Func_void_TimedMetadata(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_TimedMetadata::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const TimedMetadata& data) mutable -> void {\n      swiftClosure.call(data);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const std::vector<std::string>& /* data */)>\n  Func_void_std__vector_std__string_ create_Func_void_std__vector_std__string_(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_std__vector_std__string_::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const std::vector<std::string>& data) mutable -> void {\n      swiftClosure.call(data);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>\n  Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ create_Func_void_std__optional_std__variant_nitro__NullType__TextTrack__(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_std__optional_std__variant_nitro__NullType__TextTrack__::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const std::optional<std::variant<nitro::NullType, TextTrack>>& track) mutable -> void {\n      swiftClosure.call(track);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const onVolumeChangeData& /* data */)>\n  Func_void_onVolumeChangeData create_Func_void_onVolumeChangeData(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_onVolumeChangeData::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const onVolumeChangeData& data) mutable -> void {\n      swiftClosure.call(data);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const std::string& /* result */)>\n  Func_void_std__string create_Func_void_std__string(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_std__string::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const std::string& result) mutable -> void {\n      swiftClosure.call(result);\n    };\n  }\n  \n  // pragma MARK: std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>\n  Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload create_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const OnGetLicensePayload& payload) mutable -> std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> {\n      auto __result = swiftClosure.call(payload);\n      return __result;\n    };\n  }\n  \n  // pragma MARK: std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>\n  Func_void_std__shared_ptr_Promise_std__string__ create_Func_void_std__shared_ptr_Promise_std__string__(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_std__shared_ptr_Promise_std__string__::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const std::shared_ptr<Promise<std::string>>& result) mutable -> void {\n      swiftClosure.call(result);\n    };\n  }\n  \n  // pragma MARK: std::function<void(const VideoInformation& /* result */)>\n  Func_void_VideoInformation create_Func_void_VideoInformation(void* NON_NULL swiftClosureWrapper) noexcept {\n    auto swiftClosure = ReactNativeVideo::Func_void_VideoInformation::fromUnsafe(swiftClosureWrapper);\n    return [swiftClosure = std::move(swiftClosure)](const VideoInformation& result) mutable -> void {\n      swiftClosure.call(result);\n    };\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoPlayerSourceFactorySpec>\n  std::shared_ptr<HybridVideoPlayerSourceFactorySpec> create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept {\n    ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx::fromUnsafe(swiftUnsafePointer);\n    return std::make_shared<margelo::nitro::video::HybridVideoPlayerSourceFactorySpecSwift>(swiftPart);\n  }\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ cppType) {\n    std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSourceFactorySpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoPlayerSourceFactorySpecSwift>(cppType);\n    #ifdef NITRO_DEBUG\n    if (swiftWrapper == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Class \\\"HybridVideoPlayerSourceFactorySpec\\\" is not implemented in Swift!\");\n    }\n    #endif\n    ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx& swiftPart = swiftWrapper->getSwiftPart();\n    return swiftPart.toUnsafe();\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoViewViewManagerSpec>\n  std::shared_ptr<HybridVideoViewViewManagerSpec> create_std__shared_ptr_HybridVideoViewViewManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept {\n    ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx swiftPart = ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx::fromUnsafe(swiftUnsafePointer);\n    return std::make_shared<margelo::nitro::video::HybridVideoViewViewManagerSpecSwift>(swiftPart);\n  }\n  void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerSpec_(std__shared_ptr_HybridVideoViewViewManagerSpec_ cppType) {\n    std::shared_ptr<margelo::nitro::video::HybridVideoViewViewManagerSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoViewViewManagerSpecSwift>(cppType);\n    #ifdef NITRO_DEBUG\n    if (swiftWrapper == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Class \\\"HybridVideoViewViewManagerSpec\\\" is not implemented in Swift!\");\n    }\n    #endif\n    ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx& swiftPart = swiftWrapper->getSwiftPart();\n    return swiftPart.toUnsafe();\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoViewViewManagerFactorySpec>\n  std::shared_ptr<HybridVideoViewViewManagerFactorySpec> create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept {\n    ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx swiftPart = ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx::fromUnsafe(swiftUnsafePointer);\n    return std::make_shared<margelo::nitro::video::HybridVideoViewViewManagerFactorySpecSwift>(swiftPart);\n  }\n  void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ cppType) {\n    std::shared_ptr<margelo::nitro::video::HybridVideoViewViewManagerFactorySpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::video::HybridVideoViewViewManagerFactorySpecSwift>(cppType);\n    #ifdef NITRO_DEBUG\n    if (swiftWrapper == nullptr) [[unlikely]] {\n      throw std::runtime_error(\"Class \\\"HybridVideoViewViewManagerFactorySpec\\\" is not implemented in Swift!\");\n    }\n    #endif\n    ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx& swiftPart = swiftWrapper->getSwiftPart();\n    return swiftPart.toUnsafe();\n  }\n\n} // namespace margelo::nitro::video::bridge::swift\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Bridge.hpp",
    "content": "///\n/// ReactNativeVideo-Swift-Cxx-Bridge.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n// Forward declarations of C++ defined types\n// Forward declaration of `BandwidthData` to properly resolve imports.\nnamespace margelo::nitro::video { struct BandwidthData; }\n// Forward declaration of `BufferConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct BufferConfig; }\n// Forward declaration of `CustomVideoMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct CustomVideoMetadata; }\n// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; }\n// Forward declaration of `HybridVideoPlayerFactorySpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerFactorySpec; }\n// Forward declaration of `HybridVideoPlayerSourceFactorySpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceFactorySpec; }\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSpec; }\n// Forward declaration of `HybridVideoViewViewManagerFactorySpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoViewViewManagerFactorySpec; }\n// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; }\n// Forward declaration of `ListenerSubscription` to properly resolve imports.\nnamespace margelo::nitro::video { struct ListenerSubscription; }\n// Forward declaration of `LivePlaybackParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct LivePlaybackParams; }\n// Forward declaration of `NativeDrmParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeDrmParams; }\n// Forward declaration of `NativeExternalSubtitle` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeExternalSubtitle; }\n// Forward declaration of `OnGetLicensePayload` to properly resolve imports.\nnamespace margelo::nitro::video { struct OnGetLicensePayload; }\n// Forward declaration of `Resolution` to properly resolve imports.\nnamespace margelo::nitro::video { struct Resolution; }\n// Forward declaration of `SourceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SourceType; }\n// Forward declaration of `SubtitleType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SubtitleType; }\n// Forward declaration of `TextTrack` to properly resolve imports.\nnamespace margelo::nitro::video { struct TextTrack; }\n// Forward declaration of `TimedMetadataObject` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadataObject; }\n// Forward declaration of `TimedMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadata; }\n// Forward declaration of `VideoInformation` to properly resolve imports.\nnamespace margelo::nitro::video { struct VideoInformation; }\n// Forward declaration of `VideoOrientation` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoOrientation; }\n// Forward declaration of `VideoPlayerStatus` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoPlayerStatus; }\n// Forward declaration of `onLoadData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadData; }\n// Forward declaration of `onLoadStartData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadStartData; }\n// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onPlaybackStateChangeData; }\n// Forward declaration of `onProgressData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onProgressData; }\n// Forward declaration of `onVolumeChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onVolumeChangeData; }\n\n// Forward declarations of Swift defined types\n// Forward declaration of `HybridVideoPlayerEventEmitterSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerEventEmitterSpec_cxx; }\n// Forward declaration of `HybridVideoPlayerFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerFactorySpec_cxx; }\n// Forward declaration of `HybridVideoPlayerSourceFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSourceFactorySpec_cxx; }\n// Forward declaration of `HybridVideoPlayerSourceSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSourceSpec_cxx; }\n// Forward declaration of `HybridVideoPlayerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSpec_cxx; }\n// Forward declaration of `HybridVideoViewViewManagerFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoViewViewManagerFactorySpec_cxx; }\n// Forward declaration of `HybridVideoViewViewManagerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoViewViewManagerSpec_cxx; }\n\n// Include C++ defined types\n#include \"BandwidthData.hpp\"\n#include \"BufferConfig.hpp\"\n#include \"CustomVideoMetadata.hpp\"\n#include \"HybridVideoPlayerEventEmitterSpec.hpp\"\n#include \"HybridVideoPlayerFactorySpec.hpp\"\n#include \"HybridVideoPlayerSourceFactorySpec.hpp\"\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"HybridVideoPlayerSpec.hpp\"\n#include \"HybridVideoViewViewManagerFactorySpec.hpp\"\n#include \"HybridVideoViewViewManagerSpec.hpp\"\n#include \"ListenerSubscription.hpp\"\n#include \"LivePlaybackParams.hpp\"\n#include \"NativeDrmParams.hpp\"\n#include \"NativeExternalSubtitle.hpp\"\n#include \"OnGetLicensePayload.hpp\"\n#include \"Resolution.hpp\"\n#include \"SourceType.hpp\"\n#include \"SubtitleType.hpp\"\n#include \"TextTrack.hpp\"\n#include \"TimedMetadata.hpp\"\n#include \"TimedMetadataObject.hpp\"\n#include \"VideoInformation.hpp\"\n#include \"VideoOrientation.hpp\"\n#include \"VideoPlayerStatus.hpp\"\n#include \"onLoadData.hpp\"\n#include \"onLoadStartData.hpp\"\n#include \"onPlaybackStateChangeData.hpp\"\n#include \"onProgressData.hpp\"\n#include \"onVolumeChangeData.hpp\"\n#include <NitroModules/Null.hpp>\n#include <NitroModules/Promise.hpp>\n#include <NitroModules/PromiseHolder.hpp>\n#include <NitroModules/Result.hpp>\n#include <exception>\n#include <functional>\n#include <memory>\n#include <optional>\n#include <string>\n#include <unordered_map>\n#include <variant>\n#include <vector>\n\n/**\n * Contains specialized versions of C++ templated types so they can be accessed from Swift,\n * as well as helper functions to interact with those C++ types from Swift.\n */\nnamespace margelo::nitro::video::bridge::swift {\n\n  // pragma MARK: std::shared_ptr<HybridVideoPlayerSourceSpec>\n  /**\n   * Specialized version of `std::shared_ptr<HybridVideoPlayerSourceSpec>`.\n   */\n  using std__shared_ptr_HybridVideoPlayerSourceSpec_ = std::shared_ptr<HybridVideoPlayerSourceSpec>;\n  std::shared_ptr<HybridVideoPlayerSourceSpec> create_std__shared_ptr_HybridVideoPlayerSourceSpec_(void* NON_NULL swiftUnsafePointer) noexcept;\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceSpec_(std__shared_ptr_HybridVideoPlayerSourceSpec_ cppType);\n  \n  // pragma MARK: std::weak_ptr<HybridVideoPlayerSourceSpec>\n  using std__weak_ptr_HybridVideoPlayerSourceSpec_ = std::weak_ptr<HybridVideoPlayerSourceSpec>;\n  inline std__weak_ptr_HybridVideoPlayerSourceSpec_ weakify_std__shared_ptr_HybridVideoPlayerSourceSpec_(const std::shared_ptr<HybridVideoPlayerSourceSpec>& strong) noexcept { return strong; }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoPlayerEventEmitterSpec>\n  /**\n   * Specialized version of `std::shared_ptr<HybridVideoPlayerEventEmitterSpec>`.\n   */\n  using std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ = std::shared_ptr<HybridVideoPlayerEventEmitterSpec>;\n  std::shared_ptr<HybridVideoPlayerEventEmitterSpec> create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(void* NON_NULL swiftUnsafePointer) noexcept;\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ cppType);\n  \n  // pragma MARK: std::weak_ptr<HybridVideoPlayerEventEmitterSpec>\n  using std__weak_ptr_HybridVideoPlayerEventEmitterSpec_ = std::weak_ptr<HybridVideoPlayerEventEmitterSpec>;\n  inline std__weak_ptr_HybridVideoPlayerEventEmitterSpec_ weakify_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(const std::shared_ptr<HybridVideoPlayerEventEmitterSpec>& strong) noexcept { return strong; }\n  \n  // pragma MARK: std::shared_ptr<Promise<void>>\n  /**\n   * Specialized version of `std::shared_ptr<Promise<void>>`.\n   */\n  using std__shared_ptr_Promise_void__ = std::shared_ptr<Promise<void>>;\n  inline std::shared_ptr<Promise<void>> create_std__shared_ptr_Promise_void__() noexcept {\n    return Promise<void>::create();\n  }\n  inline PromiseHolder<void> wrap_std__shared_ptr_Promise_void__(std::shared_ptr<Promise<void>> promise) noexcept {\n    return PromiseHolder<void>(std::move(promise));\n  }\n  \n  // pragma MARK: std::function<void()>\n  /**\n   * Specialized version of `std::function<void()>`.\n   */\n  using Func_void = std::function<void()>;\n  /**\n   * Wrapper class for a `std::function<void()>`, this can be used from Swift.\n   */\n  class Func_void_Wrapper final {\n  public:\n    explicit Func_void_Wrapper(std::function<void()>&& func): _function(std::make_unique<std::function<void()>>(std::move(func))) {}\n    inline void call() const noexcept {\n      _function->operator()();\n    }\n  private:\n    std::unique_ptr<std::function<void()>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void create_Func_void(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_Wrapper wrap_Func_void(Func_void value) noexcept {\n    return Func_void_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(const std::exception_ptr& /* error */)>\n  /**\n   * Specialized version of `std::function<void(const std::exception_ptr&)>`.\n   */\n  using Func_void_std__exception_ptr = std::function<void(const std::exception_ptr& /* error */)>;\n  /**\n   * Wrapper class for a `std::function<void(const std::exception_ptr& / * error * /)>`, this can be used from Swift.\n   */\n  class Func_void_std__exception_ptr_Wrapper final {\n  public:\n    explicit Func_void_std__exception_ptr_Wrapper(std::function<void(const std::exception_ptr& /* error */)>&& func): _function(std::make_unique<std::function<void(const std::exception_ptr& /* error */)>>(std::move(func))) {}\n    inline void call(std::exception_ptr error) const noexcept {\n      _function->operator()(error);\n    }\n  private:\n    std::unique_ptr<std::function<void(const std::exception_ptr& /* error */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_std__exception_ptr_Wrapper wrap_Func_void_std__exception_ptr(Func_void_std__exception_ptr value) noexcept {\n    return Func_void_std__exception_ptr_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>\n  /**\n   * Wrapper struct for `std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>`.\n   * std::variant cannot be used in Swift because of a Swift bug.\n   * Not even specializing it works. So we create a wrapper struct.\n   */\n  struct std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__ final {\n    std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>> variant;\n    std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__(std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>> variant): variant(variant) { }\n    operator std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>() const noexcept {\n      return variant;\n    }\n    inline size_t index() const noexcept {\n      return variant.index();\n    }\n    inline nitro::NullType get_0() const noexcept {\n      return std::get<0>(variant);\n    }\n    inline std::shared_ptr<HybridVideoPlayerSourceSpec> get_1() const noexcept {\n      return std::get<1>(variant);\n    }\n  };\n  inline std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__ create_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__(nitro::NullType value) noexcept {\n    return std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__(value);\n  }\n  inline std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__ create_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::shared_ptr<HybridVideoPlayerSourceSpec>& value) noexcept {\n    return std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__(value);\n  }\n  \n  // pragma MARK: std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>\n  /**\n   * Specialized version of `std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>`.\n   */\n  using std__optional_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec___ = std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>;\n  inline std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>> create_std__optional_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec___(const std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>& value) noexcept {\n    return std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>(value);\n  }\n  inline bool has_value_std__optional_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec___(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>> get_std__optional_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec___(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::optional<std::string>\n  /**\n   * Specialized version of `std::optional<std::string>`.\n   */\n  using std__optional_std__string_ = std::optional<std::string>;\n  inline std::optional<std::string> create_std__optional_std__string_(const std::string& value) noexcept {\n    return std::optional<std::string>(value);\n  }\n  inline bool has_value_std__optional_std__string_(const std::optional<std::string>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline std::string get_std__optional_std__string_(const std::optional<std::string>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::vector<TextTrack>\n  /**\n   * Specialized version of `std::vector<TextTrack>`.\n   */\n  using std__vector_TextTrack_ = std::vector<TextTrack>;\n  inline std::vector<TextTrack> create_std__vector_TextTrack_(size_t size) noexcept {\n    std::vector<TextTrack> vector;\n    vector.reserve(size);\n    return vector;\n  }\n  \n  // pragma MARK: std::variant<nitro::NullType, TextTrack>\n  /**\n   * Wrapper struct for `std::variant<nitro::NullType, TextTrack>`.\n   * std::variant cannot be used in Swift because of a Swift bug.\n   * Not even specializing it works. So we create a wrapper struct.\n   */\n  struct std__variant_nitro__NullType__TextTrack_ final {\n    std::variant<nitro::NullType, TextTrack> variant;\n    std__variant_nitro__NullType__TextTrack_(std::variant<nitro::NullType, TextTrack> variant): variant(variant) { }\n    operator std::variant<nitro::NullType, TextTrack>() const noexcept {\n      return variant;\n    }\n    inline size_t index() const noexcept {\n      return variant.index();\n    }\n    inline nitro::NullType get_0() const noexcept {\n      return std::get<0>(variant);\n    }\n    inline TextTrack get_1() const noexcept {\n      return std::get<1>(variant);\n    }\n  };\n  inline std__variant_nitro__NullType__TextTrack_ create_std__variant_nitro__NullType__TextTrack_(nitro::NullType value) noexcept {\n    return std__variant_nitro__NullType__TextTrack_(value);\n  }\n  inline std__variant_nitro__NullType__TextTrack_ create_std__variant_nitro__NullType__TextTrack_(const TextTrack& value) noexcept {\n    return std__variant_nitro__NullType__TextTrack_(value);\n  }\n  \n  // pragma MARK: std::optional<std::variant<nitro::NullType, TextTrack>>\n  /**\n   * Specialized version of `std::optional<std::variant<nitro::NullType, TextTrack>>`.\n   */\n  using std__optional_std__variant_nitro__NullType__TextTrack__ = std::optional<std::variant<nitro::NullType, TextTrack>>;\n  inline std::optional<std::variant<nitro::NullType, TextTrack>> create_std__optional_std__variant_nitro__NullType__TextTrack__(const std::variant<nitro::NullType, TextTrack>& value) noexcept {\n    return std::optional<std::variant<nitro::NullType, TextTrack>>(value);\n  }\n  inline bool has_value_std__optional_std__variant_nitro__NullType__TextTrack__(const std::optional<std::variant<nitro::NullType, TextTrack>>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline std::variant<nitro::NullType, TextTrack> get_std__optional_std__variant_nitro__NullType__TextTrack__(const std::optional<std::variant<nitro::NullType, TextTrack>>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::optional<TextTrack>\n  /**\n   * Specialized version of `std::optional<TextTrack>`.\n   */\n  using std__optional_TextTrack_ = std::optional<TextTrack>;\n  inline std::optional<TextTrack> create_std__optional_TextTrack_(const TextTrack& value) noexcept {\n    return std::optional<TextTrack>(value);\n  }\n  inline bool has_value_std__optional_TextTrack_(const std::optional<TextTrack>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline TextTrack get_std__optional_TextTrack_(const std::optional<TextTrack>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoPlayerSpec>\n  /**\n   * Specialized version of `std::shared_ptr<HybridVideoPlayerSpec>`.\n   */\n  using std__shared_ptr_HybridVideoPlayerSpec_ = std::shared_ptr<HybridVideoPlayerSpec>;\n  std::shared_ptr<HybridVideoPlayerSpec> create_std__shared_ptr_HybridVideoPlayerSpec_(void* NON_NULL swiftUnsafePointer) noexcept;\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSpec_(std__shared_ptr_HybridVideoPlayerSpec_ cppType);\n  \n  // pragma MARK: std::weak_ptr<HybridVideoPlayerSpec>\n  using std__weak_ptr_HybridVideoPlayerSpec_ = std::weak_ptr<HybridVideoPlayerSpec>;\n  inline std__weak_ptr_HybridVideoPlayerSpec_ weakify_std__shared_ptr_HybridVideoPlayerSpec_(const std::shared_ptr<HybridVideoPlayerSpec>& strong) noexcept { return strong; }\n  \n  // pragma MARK: Result<std::shared_ptr<Promise<void>>>\n  using Result_std__shared_ptr_Promise_void___ = Result<std::shared_ptr<Promise<void>>>;\n  inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::shared_ptr<Promise<void>>& value) noexcept {\n    return Result<std::shared_ptr<Promise<void>>>::withValue(value);\n  }\n  inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::exception_ptr& error) noexcept {\n    return Result<std::shared_ptr<Promise<void>>>::withError(error);\n  }\n  \n  // pragma MARK: Result<std::vector<TextTrack>>\n  using Result_std__vector_TextTrack__ = Result<std::vector<TextTrack>>;\n  inline Result_std__vector_TextTrack__ create_Result_std__vector_TextTrack__(const std::vector<TextTrack>& value) noexcept {\n    return Result<std::vector<TextTrack>>::withValue(value);\n  }\n  inline Result_std__vector_TextTrack__ create_Result_std__vector_TextTrack__(const std::exception_ptr& error) noexcept {\n    return Result<std::vector<TextTrack>>::withError(error);\n  }\n  \n  // pragma MARK: Result<void>\n  using Result_void_ = Result<void>;\n  inline Result_void_ create_Result_void_() noexcept {\n    return Result<void>::withValue();\n  }\n  inline Result_void_ create_Result_void_(const std::exception_ptr& error) noexcept {\n    return Result<void>::withError(error);\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoPlayerFactorySpec>\n  /**\n   * Specialized version of `std::shared_ptr<HybridVideoPlayerFactorySpec>`.\n   */\n  using std__shared_ptr_HybridVideoPlayerFactorySpec_ = std::shared_ptr<HybridVideoPlayerFactorySpec>;\n  std::shared_ptr<HybridVideoPlayerFactorySpec> create_std__shared_ptr_HybridVideoPlayerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept;\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerFactorySpec_(std__shared_ptr_HybridVideoPlayerFactorySpec_ cppType);\n  \n  // pragma MARK: std::weak_ptr<HybridVideoPlayerFactorySpec>\n  using std__weak_ptr_HybridVideoPlayerFactorySpec_ = std::weak_ptr<HybridVideoPlayerFactorySpec>;\n  inline std__weak_ptr_HybridVideoPlayerFactorySpec_ weakify_std__shared_ptr_HybridVideoPlayerFactorySpec_(const std::shared_ptr<HybridVideoPlayerFactorySpec>& strong) noexcept { return strong; }\n  \n  // pragma MARK: Result<std::shared_ptr<HybridVideoPlayerSpec>>\n  using Result_std__shared_ptr_HybridVideoPlayerSpec__ = Result<std::shared_ptr<HybridVideoPlayerSpec>>;\n  inline Result_std__shared_ptr_HybridVideoPlayerSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSpec__(const std::shared_ptr<HybridVideoPlayerSpec>& value) noexcept {\n    return Result<std::shared_ptr<HybridVideoPlayerSpec>>::withValue(value);\n  }\n  inline Result_std__shared_ptr_HybridVideoPlayerSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSpec__(const std::exception_ptr& error) noexcept {\n    return Result<std::shared_ptr<HybridVideoPlayerSpec>>::withError(error);\n  }\n  \n  // pragma MARK: std::function<void(bool /* hasAudioFocus */)>\n  /**\n   * Specialized version of `std::function<void(bool)>`.\n   */\n  using Func_void_bool = std::function<void(bool /* hasAudioFocus */)>;\n  /**\n   * Wrapper class for a `std::function<void(bool / * hasAudioFocus * /)>`, this can be used from Swift.\n   */\n  class Func_void_bool_Wrapper final {\n  public:\n    explicit Func_void_bool_Wrapper(std::function<void(bool /* hasAudioFocus */)>&& func): _function(std::make_unique<std::function<void(bool /* hasAudioFocus */)>>(std::move(func))) {}\n    inline void call(bool hasAudioFocus) const noexcept {\n      _function->operator()(hasAudioFocus);\n    }\n  private:\n    std::unique_ptr<std::function<void(bool /* hasAudioFocus */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_bool create_Func_void_bool(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_bool_Wrapper wrap_Func_void_bool(Func_void_bool value) noexcept {\n    return Func_void_bool_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::optional<double>\n  /**\n   * Specialized version of `std::optional<double>`.\n   */\n  using std__optional_double_ = std::optional<double>;\n  inline std::optional<double> create_std__optional_double_(const double& value) noexcept {\n    return std::optional<double>(value);\n  }\n  inline bool has_value_std__optional_double_(const std::optional<double>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline double get_std__optional_double_(const std::optional<double>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::function<void(const BandwidthData& /* data */)>\n  /**\n   * Specialized version of `std::function<void(const BandwidthData&)>`.\n   */\n  using Func_void_BandwidthData = std::function<void(const BandwidthData& /* data */)>;\n  /**\n   * Wrapper class for a `std::function<void(const BandwidthData& / * data * /)>`, this can be used from Swift.\n   */\n  class Func_void_BandwidthData_Wrapper final {\n  public:\n    explicit Func_void_BandwidthData_Wrapper(std::function<void(const BandwidthData& /* data */)>&& func): _function(std::make_unique<std::function<void(const BandwidthData& /* data */)>>(std::move(func))) {}\n    inline void call(BandwidthData data) const noexcept {\n      _function->operator()(data);\n    }\n  private:\n    std::unique_ptr<std::function<void(const BandwidthData& /* data */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_BandwidthData create_Func_void_BandwidthData(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_BandwidthData_Wrapper wrap_Func_void_BandwidthData(Func_void_BandwidthData value) noexcept {\n    return Func_void_BandwidthData_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(const onLoadData& /* data */)>\n  /**\n   * Specialized version of `std::function<void(const onLoadData&)>`.\n   */\n  using Func_void_onLoadData = std::function<void(const onLoadData& /* data */)>;\n  /**\n   * Wrapper class for a `std::function<void(const onLoadData& / * data * /)>`, this can be used from Swift.\n   */\n  class Func_void_onLoadData_Wrapper final {\n  public:\n    explicit Func_void_onLoadData_Wrapper(std::function<void(const onLoadData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onLoadData& /* data */)>>(std::move(func))) {}\n    inline void call(onLoadData data) const noexcept {\n      _function->operator()(data);\n    }\n  private:\n    std::unique_ptr<std::function<void(const onLoadData& /* data */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_onLoadData create_Func_void_onLoadData(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_onLoadData_Wrapper wrap_Func_void_onLoadData(Func_void_onLoadData value) noexcept {\n    return Func_void_onLoadData_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(const onLoadStartData& /* data */)>\n  /**\n   * Specialized version of `std::function<void(const onLoadStartData&)>`.\n   */\n  using Func_void_onLoadStartData = std::function<void(const onLoadStartData& /* data */)>;\n  /**\n   * Wrapper class for a `std::function<void(const onLoadStartData& / * data * /)>`, this can be used from Swift.\n   */\n  class Func_void_onLoadStartData_Wrapper final {\n  public:\n    explicit Func_void_onLoadStartData_Wrapper(std::function<void(const onLoadStartData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onLoadStartData& /* data */)>>(std::move(func))) {}\n    inline void call(onLoadStartData data) const noexcept {\n      _function->operator()(data);\n    }\n  private:\n    std::unique_ptr<std::function<void(const onLoadStartData& /* data */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_onLoadStartData create_Func_void_onLoadStartData(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_onLoadStartData_Wrapper wrap_Func_void_onLoadStartData(Func_void_onLoadStartData value) noexcept {\n    return Func_void_onLoadStartData_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(const onPlaybackStateChangeData& /* data */)>\n  /**\n   * Specialized version of `std::function<void(const onPlaybackStateChangeData&)>`.\n   */\n  using Func_void_onPlaybackStateChangeData = std::function<void(const onPlaybackStateChangeData& /* data */)>;\n  /**\n   * Wrapper class for a `std::function<void(const onPlaybackStateChangeData& / * data * /)>`, this can be used from Swift.\n   */\n  class Func_void_onPlaybackStateChangeData_Wrapper final {\n  public:\n    explicit Func_void_onPlaybackStateChangeData_Wrapper(std::function<void(const onPlaybackStateChangeData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onPlaybackStateChangeData& /* data */)>>(std::move(func))) {}\n    inline void call(onPlaybackStateChangeData data) const noexcept {\n      _function->operator()(data);\n    }\n  private:\n    std::unique_ptr<std::function<void(const onPlaybackStateChangeData& /* data */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_onPlaybackStateChangeData create_Func_void_onPlaybackStateChangeData(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_onPlaybackStateChangeData_Wrapper wrap_Func_void_onPlaybackStateChangeData(Func_void_onPlaybackStateChangeData value) noexcept {\n    return Func_void_onPlaybackStateChangeData_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(double /* rate */)>\n  /**\n   * Specialized version of `std::function<void(double)>`.\n   */\n  using Func_void_double = std::function<void(double /* rate */)>;\n  /**\n   * Wrapper class for a `std::function<void(double / * rate * /)>`, this can be used from Swift.\n   */\n  class Func_void_double_Wrapper final {\n  public:\n    explicit Func_void_double_Wrapper(std::function<void(double /* rate */)>&& func): _function(std::make_unique<std::function<void(double /* rate */)>>(std::move(func))) {}\n    inline void call(double rate) const noexcept {\n      _function->operator()(rate);\n    }\n  private:\n    std::unique_ptr<std::function<void(double /* rate */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_double create_Func_void_double(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_double_Wrapper wrap_Func_void_double(Func_void_double value) noexcept {\n    return Func_void_double_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(const onProgressData& /* data */)>\n  /**\n   * Specialized version of `std::function<void(const onProgressData&)>`.\n   */\n  using Func_void_onProgressData = std::function<void(const onProgressData& /* data */)>;\n  /**\n   * Wrapper class for a `std::function<void(const onProgressData& / * data * /)>`, this can be used from Swift.\n   */\n  class Func_void_onProgressData_Wrapper final {\n  public:\n    explicit Func_void_onProgressData_Wrapper(std::function<void(const onProgressData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onProgressData& /* data */)>>(std::move(func))) {}\n    inline void call(onProgressData data) const noexcept {\n      _function->operator()(data);\n    }\n  private:\n    std::unique_ptr<std::function<void(const onProgressData& /* data */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_onProgressData create_Func_void_onProgressData(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_onProgressData_Wrapper wrap_Func_void_onProgressData(Func_void_onProgressData value) noexcept {\n    return Func_void_onProgressData_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(VideoPlayerStatus /* status */)>\n  /**\n   * Specialized version of `std::function<void(VideoPlayerStatus)>`.\n   */\n  using Func_void_VideoPlayerStatus = std::function<void(VideoPlayerStatus /* status */)>;\n  /**\n   * Wrapper class for a `std::function<void(VideoPlayerStatus / * status * /)>`, this can be used from Swift.\n   */\n  class Func_void_VideoPlayerStatus_Wrapper final {\n  public:\n    explicit Func_void_VideoPlayerStatus_Wrapper(std::function<void(VideoPlayerStatus /* status */)>&& func): _function(std::make_unique<std::function<void(VideoPlayerStatus /* status */)>>(std::move(func))) {}\n    inline void call(int status) const noexcept {\n      _function->operator()(static_cast<VideoPlayerStatus>(status));\n    }\n  private:\n    std::unique_ptr<std::function<void(VideoPlayerStatus /* status */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_VideoPlayerStatus create_Func_void_VideoPlayerStatus(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_VideoPlayerStatus_Wrapper wrap_Func_void_VideoPlayerStatus(Func_void_VideoPlayerStatus value) noexcept {\n    return Func_void_VideoPlayerStatus_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::vector<TimedMetadataObject>\n  /**\n   * Specialized version of `std::vector<TimedMetadataObject>`.\n   */\n  using std__vector_TimedMetadataObject_ = std::vector<TimedMetadataObject>;\n  inline std::vector<TimedMetadataObject> create_std__vector_TimedMetadataObject_(size_t size) noexcept {\n    std::vector<TimedMetadataObject> vector;\n    vector.reserve(size);\n    return vector;\n  }\n  \n  // pragma MARK: std::function<void(const TimedMetadata& /* data */)>\n  /**\n   * Specialized version of `std::function<void(const TimedMetadata&)>`.\n   */\n  using Func_void_TimedMetadata = std::function<void(const TimedMetadata& /* data */)>;\n  /**\n   * Wrapper class for a `std::function<void(const TimedMetadata& / * data * /)>`, this can be used from Swift.\n   */\n  class Func_void_TimedMetadata_Wrapper final {\n  public:\n    explicit Func_void_TimedMetadata_Wrapper(std::function<void(const TimedMetadata& /* data */)>&& func): _function(std::make_unique<std::function<void(const TimedMetadata& /* data */)>>(std::move(func))) {}\n    inline void call(TimedMetadata data) const noexcept {\n      _function->operator()(data);\n    }\n  private:\n    std::unique_ptr<std::function<void(const TimedMetadata& /* data */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_TimedMetadata create_Func_void_TimedMetadata(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_TimedMetadata_Wrapper wrap_Func_void_TimedMetadata(Func_void_TimedMetadata value) noexcept {\n    return Func_void_TimedMetadata_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::vector<std::string>\n  /**\n   * Specialized version of `std::vector<std::string>`.\n   */\n  using std__vector_std__string_ = std::vector<std::string>;\n  inline std::vector<std::string> create_std__vector_std__string_(size_t size) noexcept {\n    std::vector<std::string> vector;\n    vector.reserve(size);\n    return vector;\n  }\n  \n  // pragma MARK: std::function<void(const std::vector<std::string>& /* data */)>\n  /**\n   * Specialized version of `std::function<void(const std::vector<std::string>&)>`.\n   */\n  using Func_void_std__vector_std__string_ = std::function<void(const std::vector<std::string>& /* data */)>;\n  /**\n   * Wrapper class for a `std::function<void(const std::vector<std::string>& / * data * /)>`, this can be used from Swift.\n   */\n  class Func_void_std__vector_std__string__Wrapper final {\n  public:\n    explicit Func_void_std__vector_std__string__Wrapper(std::function<void(const std::vector<std::string>& /* data */)>&& func): _function(std::make_unique<std::function<void(const std::vector<std::string>& /* data */)>>(std::move(func))) {}\n    inline void call(std::vector<std::string> data) const noexcept {\n      _function->operator()(data);\n    }\n  private:\n    std::unique_ptr<std::function<void(const std::vector<std::string>& /* data */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_std__vector_std__string_ create_Func_void_std__vector_std__string_(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_std__vector_std__string__Wrapper wrap_Func_void_std__vector_std__string_(Func_void_std__vector_std__string_ value) noexcept {\n    return Func_void_std__vector_std__string__Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>\n  /**\n   * Specialized version of `std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>&)>`.\n   */\n  using Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ = std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>;\n  /**\n   * Wrapper class for a `std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& / * track * /)>`, this can be used from Swift.\n   */\n  class Func_void_std__optional_std__variant_nitro__NullType__TextTrack___Wrapper final {\n  public:\n    explicit Func_void_std__optional_std__variant_nitro__NullType__TextTrack___Wrapper(std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>&& func): _function(std::make_unique<std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>>(std::move(func))) {}\n    inline void call(std::optional<std::variant<nitro::NullType, TextTrack>> track) const noexcept {\n      _function->operator()(track);\n    }\n  private:\n    std::unique_ptr<std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ create_Func_void_std__optional_std__variant_nitro__NullType__TextTrack__(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_std__optional_std__variant_nitro__NullType__TextTrack___Wrapper wrap_Func_void_std__optional_std__variant_nitro__NullType__TextTrack__(Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ value) noexcept {\n    return Func_void_std__optional_std__variant_nitro__NullType__TextTrack___Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<void(const onVolumeChangeData& /* data */)>\n  /**\n   * Specialized version of `std::function<void(const onVolumeChangeData&)>`.\n   */\n  using Func_void_onVolumeChangeData = std::function<void(const onVolumeChangeData& /* data */)>;\n  /**\n   * Wrapper class for a `std::function<void(const onVolumeChangeData& / * data * /)>`, this can be used from Swift.\n   */\n  class Func_void_onVolumeChangeData_Wrapper final {\n  public:\n    explicit Func_void_onVolumeChangeData_Wrapper(std::function<void(const onVolumeChangeData& /* data */)>&& func): _function(std::make_unique<std::function<void(const onVolumeChangeData& /* data */)>>(std::move(func))) {}\n    inline void call(onVolumeChangeData data) const noexcept {\n      _function->operator()(data);\n    }\n  private:\n    std::unique_ptr<std::function<void(const onVolumeChangeData& /* data */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_onVolumeChangeData create_Func_void_onVolumeChangeData(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_onVolumeChangeData_Wrapper wrap_Func_void_onVolumeChangeData(Func_void_onVolumeChangeData value) noexcept {\n    return Func_void_onVolumeChangeData_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: Result<ListenerSubscription>\n  using Result_ListenerSubscription_ = Result<ListenerSubscription>;\n  inline Result_ListenerSubscription_ create_Result_ListenerSubscription_(const ListenerSubscription& value) noexcept {\n    return Result<ListenerSubscription>::withValue(value);\n  }\n  inline Result_ListenerSubscription_ create_Result_ListenerSubscription_(const std::exception_ptr& error) noexcept {\n    return Result<ListenerSubscription>::withError(error);\n  }\n  \n  // pragma MARK: std::vector<NativeExternalSubtitle>\n  /**\n   * Specialized version of `std::vector<NativeExternalSubtitle>`.\n   */\n  using std__vector_NativeExternalSubtitle_ = std::vector<NativeExternalSubtitle>;\n  inline std::vector<NativeExternalSubtitle> create_std__vector_NativeExternalSubtitle_(size_t size) noexcept {\n    std::vector<NativeExternalSubtitle> vector;\n    vector.reserve(size);\n    return vector;\n  }\n  \n  // pragma MARK: std::optional<std::vector<NativeExternalSubtitle>>\n  /**\n   * Specialized version of `std::optional<std::vector<NativeExternalSubtitle>>`.\n   */\n  using std__optional_std__vector_NativeExternalSubtitle__ = std::optional<std::vector<NativeExternalSubtitle>>;\n  inline std::optional<std::vector<NativeExternalSubtitle>> create_std__optional_std__vector_NativeExternalSubtitle__(const std::vector<NativeExternalSubtitle>& value) noexcept {\n    return std::optional<std::vector<NativeExternalSubtitle>>(value);\n  }\n  inline bool has_value_std__optional_std__vector_NativeExternalSubtitle__(const std::optional<std::vector<NativeExternalSubtitle>>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline std::vector<NativeExternalSubtitle> get_std__optional_std__vector_NativeExternalSubtitle__(const std::optional<std::vector<NativeExternalSubtitle>>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::unordered_map<std::string, std::string>\n  /**\n   * Specialized version of `std::unordered_map<std::string, std::string>`.\n   */\n  using std__unordered_map_std__string__std__string_ = std::unordered_map<std::string, std::string>;\n  inline std::unordered_map<std::string, std::string> create_std__unordered_map_std__string__std__string_(size_t size) noexcept {\n    std::unordered_map<std::string, std::string> map;\n    map.reserve(size);\n    return map;\n  }\n  inline std::vector<std::string> get_std__unordered_map_std__string__std__string__keys(const std__unordered_map_std__string__std__string_& map) noexcept {\n    std::vector<std::string> keys;\n    keys.reserve(map.size());\n    for (const auto& entry : map) {\n      keys.push_back(entry.first);\n    }\n    return keys;\n  }\n  inline std::string get_std__unordered_map_std__string__std__string__value(const std__unordered_map_std__string__std__string_& map, const std::string& key) noexcept {\n    return map.find(key)->second;\n  }\n  inline void emplace_std__unordered_map_std__string__std__string_(std__unordered_map_std__string__std__string_& map, const std::string& key, const std::string& value) noexcept {\n    map.emplace(key, value);\n  }\n  \n  // pragma MARK: std::optional<std::unordered_map<std::string, std::string>>\n  /**\n   * Specialized version of `std::optional<std::unordered_map<std::string, std::string>>`.\n   */\n  using std__optional_std__unordered_map_std__string__std__string__ = std::optional<std::unordered_map<std::string, std::string>>;\n  inline std::optional<std::unordered_map<std::string, std::string>> create_std__optional_std__unordered_map_std__string__std__string__(const std::unordered_map<std::string, std::string>& value) noexcept {\n    return std::optional<std::unordered_map<std::string, std::string>>(value);\n  }\n  inline bool has_value_std__optional_std__unordered_map_std__string__std__string__(const std::optional<std::unordered_map<std::string, std::string>>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline std::unordered_map<std::string, std::string> get_std__optional_std__unordered_map_std__string__std__string__(const std::optional<std::unordered_map<std::string, std::string>>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::optional<bool>\n  /**\n   * Specialized version of `std::optional<bool>`.\n   */\n  using std__optional_bool_ = std::optional<bool>;\n  inline std::optional<bool> create_std__optional_bool_(const bool& value) noexcept {\n    return std::optional<bool>(value);\n  }\n  inline bool has_value_std__optional_bool_(const std::optional<bool>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline bool get_std__optional_bool_(const std::optional<bool>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::shared_ptr<Promise<std::string>>\n  /**\n   * Specialized version of `std::shared_ptr<Promise<std::string>>`.\n   */\n  using std__shared_ptr_Promise_std__string__ = std::shared_ptr<Promise<std::string>>;\n  inline std::shared_ptr<Promise<std::string>> create_std__shared_ptr_Promise_std__string__() noexcept {\n    return Promise<std::string>::create();\n  }\n  inline PromiseHolder<std::string> wrap_std__shared_ptr_Promise_std__string__(std::shared_ptr<Promise<std::string>> promise) noexcept {\n    return PromiseHolder<std::string>(std::move(promise));\n  }\n  \n  // pragma MARK: std::function<void(const std::string& /* result */)>\n  /**\n   * Specialized version of `std::function<void(const std::string&)>`.\n   */\n  using Func_void_std__string = std::function<void(const std::string& /* result */)>;\n  /**\n   * Wrapper class for a `std::function<void(const std::string& / * result * /)>`, this can be used from Swift.\n   */\n  class Func_void_std__string_Wrapper final {\n  public:\n    explicit Func_void_std__string_Wrapper(std::function<void(const std::string& /* result */)>&& func): _function(std::make_unique<std::function<void(const std::string& /* result */)>>(std::move(func))) {}\n    inline void call(std::string result) const noexcept {\n      _function->operator()(result);\n    }\n  private:\n    std::unique_ptr<std::function<void(const std::string& /* result */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_std__string create_Func_void_std__string(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_std__string_Wrapper wrap_Func_void_std__string(Func_void_std__string value) noexcept {\n    return Func_void_std__string_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>\n  /**\n   * Specialized version of `std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload&)>`.\n   */\n  using Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload = std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>;\n  /**\n   * Wrapper class for a `std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& / * payload * /)>`, this can be used from Swift.\n   */\n  class Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_Wrapper final {\n  public:\n    explicit Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_Wrapper(std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>&& func): _function(std::make_unique<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>(std::move(func))) {}\n    inline std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> call(OnGetLicensePayload payload) const noexcept {\n      auto __result = _function->operator()(payload);\n      return __result;\n    }\n  private:\n    std::unique_ptr<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload create_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_Wrapper wrap_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload value) noexcept {\n    return Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>\n  /**\n   * Specialized version of `std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>`.\n   */\n  using std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____ = std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>;\n  inline std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> create_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____() noexcept {\n    return Promise<std::shared_ptr<Promise<std::string>>>::create();\n  }\n  inline PromiseHolder<std::shared_ptr<Promise<std::string>>> wrap_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____(std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>> promise) noexcept {\n    return PromiseHolder<std::shared_ptr<Promise<std::string>>>(std::move(promise));\n  }\n  \n  // pragma MARK: std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>\n  /**\n   * Specialized version of `std::function<void(const std::shared_ptr<Promise<std::string>>&)>`.\n   */\n  using Func_void_std__shared_ptr_Promise_std__string__ = std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>;\n  /**\n   * Wrapper class for a `std::function<void(const std::shared_ptr<Promise<std::string>>& / * result * /)>`, this can be used from Swift.\n   */\n  class Func_void_std__shared_ptr_Promise_std__string___Wrapper final {\n  public:\n    explicit Func_void_std__shared_ptr_Promise_std__string___Wrapper(std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>&& func): _function(std::make_unique<std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>>(std::move(func))) {}\n    inline void call(std::shared_ptr<Promise<std::string>> result) const noexcept {\n      _function->operator()(result);\n    }\n  private:\n    std::unique_ptr<std::function<void(const std::shared_ptr<Promise<std::string>>& /* result */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_std__shared_ptr_Promise_std__string__ create_Func_void_std__shared_ptr_Promise_std__string__(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_std__shared_ptr_Promise_std__string___Wrapper wrap_Func_void_std__shared_ptr_Promise_std__string__(Func_void_std__shared_ptr_Promise_std__string__ value) noexcept {\n    return Func_void_std__shared_ptr_Promise_std__string___Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>\n  /**\n   * Specialized version of `std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& / * payload * /)>>`.\n   */\n  using std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______ = std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>;\n  inline std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>> create_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>& value) noexcept {\n    return std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>(value);\n  }\n  inline bool has_value_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)> get_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(const std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::optional<NativeDrmParams>\n  /**\n   * Specialized version of `std::optional<NativeDrmParams>`.\n   */\n  using std__optional_NativeDrmParams_ = std::optional<NativeDrmParams>;\n  inline std::optional<NativeDrmParams> create_std__optional_NativeDrmParams_(const NativeDrmParams& value) noexcept {\n    return std::optional<NativeDrmParams>(value);\n  }\n  inline bool has_value_std__optional_NativeDrmParams_(const std::optional<NativeDrmParams>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline NativeDrmParams get_std__optional_NativeDrmParams_(const std::optional<NativeDrmParams>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::optional<LivePlaybackParams>\n  /**\n   * Specialized version of `std::optional<LivePlaybackParams>`.\n   */\n  using std__optional_LivePlaybackParams_ = std::optional<LivePlaybackParams>;\n  inline std::optional<LivePlaybackParams> create_std__optional_LivePlaybackParams_(const LivePlaybackParams& value) noexcept {\n    return std::optional<LivePlaybackParams>(value);\n  }\n  inline bool has_value_std__optional_LivePlaybackParams_(const std::optional<LivePlaybackParams>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline LivePlaybackParams get_std__optional_LivePlaybackParams_(const std::optional<LivePlaybackParams>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::optional<Resolution>\n  /**\n   * Specialized version of `std::optional<Resolution>`.\n   */\n  using std__optional_Resolution_ = std::optional<Resolution>;\n  inline std::optional<Resolution> create_std__optional_Resolution_(const Resolution& value) noexcept {\n    return std::optional<Resolution>(value);\n  }\n  inline bool has_value_std__optional_Resolution_(const std::optional<Resolution>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline Resolution get_std__optional_Resolution_(const std::optional<Resolution>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::optional<BufferConfig>\n  /**\n   * Specialized version of `std::optional<BufferConfig>`.\n   */\n  using std__optional_BufferConfig_ = std::optional<BufferConfig>;\n  inline std::optional<BufferConfig> create_std__optional_BufferConfig_(const BufferConfig& value) noexcept {\n    return std::optional<BufferConfig>(value);\n  }\n  inline bool has_value_std__optional_BufferConfig_(const std::optional<BufferConfig>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline BufferConfig get_std__optional_BufferConfig_(const std::optional<BufferConfig>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::optional<CustomVideoMetadata>\n  /**\n   * Specialized version of `std::optional<CustomVideoMetadata>`.\n   */\n  using std__optional_CustomVideoMetadata_ = std::optional<CustomVideoMetadata>;\n  inline std::optional<CustomVideoMetadata> create_std__optional_CustomVideoMetadata_(const CustomVideoMetadata& value) noexcept {\n    return std::optional<CustomVideoMetadata>(value);\n  }\n  inline bool has_value_std__optional_CustomVideoMetadata_(const std::optional<CustomVideoMetadata>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline CustomVideoMetadata get_std__optional_CustomVideoMetadata_(const std::optional<CustomVideoMetadata>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::shared_ptr<Promise<VideoInformation>>\n  /**\n   * Specialized version of `std::shared_ptr<Promise<VideoInformation>>`.\n   */\n  using std__shared_ptr_Promise_VideoInformation__ = std::shared_ptr<Promise<VideoInformation>>;\n  inline std::shared_ptr<Promise<VideoInformation>> create_std__shared_ptr_Promise_VideoInformation__() noexcept {\n    return Promise<VideoInformation>::create();\n  }\n  inline PromiseHolder<VideoInformation> wrap_std__shared_ptr_Promise_VideoInformation__(std::shared_ptr<Promise<VideoInformation>> promise) noexcept {\n    return PromiseHolder<VideoInformation>(std::move(promise));\n  }\n  \n  // pragma MARK: std::function<void(const VideoInformation& /* result */)>\n  /**\n   * Specialized version of `std::function<void(const VideoInformation&)>`.\n   */\n  using Func_void_VideoInformation = std::function<void(const VideoInformation& /* result */)>;\n  /**\n   * Wrapper class for a `std::function<void(const VideoInformation& / * result * /)>`, this can be used from Swift.\n   */\n  class Func_void_VideoInformation_Wrapper final {\n  public:\n    explicit Func_void_VideoInformation_Wrapper(std::function<void(const VideoInformation& /* result */)>&& func): _function(std::make_unique<std::function<void(const VideoInformation& /* result */)>>(std::move(func))) {}\n    inline void call(VideoInformation result) const noexcept {\n      _function->operator()(result);\n    }\n  private:\n    std::unique_ptr<std::function<void(const VideoInformation& /* result */)>> _function;\n  } SWIFT_NONCOPYABLE;\n  Func_void_VideoInformation create_Func_void_VideoInformation(void* NON_NULL swiftClosureWrapper) noexcept;\n  inline Func_void_VideoInformation_Wrapper wrap_Func_void_VideoInformation(Func_void_VideoInformation value) noexcept {\n    return Func_void_VideoInformation_Wrapper(std::move(value));\n  }\n  \n  // pragma MARK: Result<std::shared_ptr<Promise<VideoInformation>>>\n  using Result_std__shared_ptr_Promise_VideoInformation___ = Result<std::shared_ptr<Promise<VideoInformation>>>;\n  inline Result_std__shared_ptr_Promise_VideoInformation___ create_Result_std__shared_ptr_Promise_VideoInformation___(const std::shared_ptr<Promise<VideoInformation>>& value) noexcept {\n    return Result<std::shared_ptr<Promise<VideoInformation>>>::withValue(value);\n  }\n  inline Result_std__shared_ptr_Promise_VideoInformation___ create_Result_std__shared_ptr_Promise_VideoInformation___(const std::exception_ptr& error) noexcept {\n    return Result<std::shared_ptr<Promise<VideoInformation>>>::withError(error);\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoPlayerSourceFactorySpec>\n  /**\n   * Specialized version of `std::shared_ptr<HybridVideoPlayerSourceFactorySpec>`.\n   */\n  using std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ = std::shared_ptr<HybridVideoPlayerSourceFactorySpec>;\n  std::shared_ptr<HybridVideoPlayerSourceFactorySpec> create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept;\n  void* NON_NULL get_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ cppType);\n  \n  // pragma MARK: std::weak_ptr<HybridVideoPlayerSourceFactorySpec>\n  using std__weak_ptr_HybridVideoPlayerSourceFactorySpec_ = std::weak_ptr<HybridVideoPlayerSourceFactorySpec>;\n  inline std__weak_ptr_HybridVideoPlayerSourceFactorySpec_ weakify_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(const std::shared_ptr<HybridVideoPlayerSourceFactorySpec>& strong) noexcept { return strong; }\n  \n  // pragma MARK: Result<std::shared_ptr<HybridVideoPlayerSourceSpec>>\n  using Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ = Result<std::shared_ptr<HybridVideoPlayerSourceSpec>>;\n  inline Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::shared_ptr<HybridVideoPlayerSourceSpec>& value) noexcept {\n    return Result<std::shared_ptr<HybridVideoPlayerSourceSpec>>::withValue(value);\n  }\n  inline Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(const std::exception_ptr& error) noexcept {\n    return Result<std::shared_ptr<HybridVideoPlayerSourceSpec>>::withError(error);\n  }\n  \n  // pragma MARK: std::optional<std::shared_ptr<HybridVideoPlayerSpec>>\n  /**\n   * Specialized version of `std::optional<std::shared_ptr<HybridVideoPlayerSpec>>`.\n   */\n  using std__optional_std__shared_ptr_HybridVideoPlayerSpec__ = std::optional<std::shared_ptr<HybridVideoPlayerSpec>>;\n  inline std::optional<std::shared_ptr<HybridVideoPlayerSpec>> create_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::shared_ptr<HybridVideoPlayerSpec>& value) noexcept {\n    return std::optional<std::shared_ptr<HybridVideoPlayerSpec>>(value);\n  }\n  inline bool has_value_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::optional<std::shared_ptr<HybridVideoPlayerSpec>>& optional) noexcept {\n    return optional.has_value();\n  }\n  inline std::shared_ptr<HybridVideoPlayerSpec> get_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(const std::optional<std::shared_ptr<HybridVideoPlayerSpec>>& optional) noexcept {\n    return optional.value();\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoViewViewManagerSpec>\n  /**\n   * Specialized version of `std::shared_ptr<HybridVideoViewViewManagerSpec>`.\n   */\n  using std__shared_ptr_HybridVideoViewViewManagerSpec_ = std::shared_ptr<HybridVideoViewViewManagerSpec>;\n  std::shared_ptr<HybridVideoViewViewManagerSpec> create_std__shared_ptr_HybridVideoViewViewManagerSpec_(void* NON_NULL swiftUnsafePointer) noexcept;\n  void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerSpec_(std__shared_ptr_HybridVideoViewViewManagerSpec_ cppType);\n  \n  // pragma MARK: std::weak_ptr<HybridVideoViewViewManagerSpec>\n  using std__weak_ptr_HybridVideoViewViewManagerSpec_ = std::weak_ptr<HybridVideoViewViewManagerSpec>;\n  inline std__weak_ptr_HybridVideoViewViewManagerSpec_ weakify_std__shared_ptr_HybridVideoViewViewManagerSpec_(const std::shared_ptr<HybridVideoViewViewManagerSpec>& strong) noexcept { return strong; }\n  \n  // pragma MARK: Result<bool>\n  using Result_bool_ = Result<bool>;\n  inline Result_bool_ create_Result_bool_(bool value) noexcept {\n    return Result<bool>::withValue(std::move(value));\n  }\n  inline Result_bool_ create_Result_bool_(const std::exception_ptr& error) noexcept {\n    return Result<bool>::withError(error);\n  }\n  \n  // pragma MARK: std::shared_ptr<HybridVideoViewViewManagerFactorySpec>\n  /**\n   * Specialized version of `std::shared_ptr<HybridVideoViewViewManagerFactorySpec>`.\n   */\n  using std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ = std::shared_ptr<HybridVideoViewViewManagerFactorySpec>;\n  std::shared_ptr<HybridVideoViewViewManagerFactorySpec> create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(void* NON_NULL swiftUnsafePointer) noexcept;\n  void* NON_NULL get_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ cppType);\n  \n  // pragma MARK: std::weak_ptr<HybridVideoViewViewManagerFactorySpec>\n  using std__weak_ptr_HybridVideoViewViewManagerFactorySpec_ = std::weak_ptr<HybridVideoViewViewManagerFactorySpec>;\n  inline std__weak_ptr_HybridVideoViewViewManagerFactorySpec_ weakify_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(const std::shared_ptr<HybridVideoViewViewManagerFactorySpec>& strong) noexcept { return strong; }\n  \n  // pragma MARK: Result<std::shared_ptr<HybridVideoViewViewManagerSpec>>\n  using Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ = Result<std::shared_ptr<HybridVideoViewViewManagerSpec>>;\n  inline Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(const std::shared_ptr<HybridVideoViewViewManagerSpec>& value) noexcept {\n    return Result<std::shared_ptr<HybridVideoViewViewManagerSpec>>::withValue(value);\n  }\n  inline Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(const std::exception_ptr& error) noexcept {\n    return Result<std::shared_ptr<HybridVideoViewViewManagerSpec>>::withError(error);\n  }\n\n} // namespace margelo::nitro::video::bridge::swift\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/ReactNativeVideo-Swift-Cxx-Umbrella.hpp",
    "content": "///\n/// ReactNativeVideo-Swift-Cxx-Umbrella.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n// Forward declarations of C++ defined types\n// Forward declaration of `BandwidthData` to properly resolve imports.\nnamespace margelo::nitro::video { struct BandwidthData; }\n// Forward declaration of `BufferConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct BufferConfig; }\n// Forward declaration of `CustomVideoMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct CustomVideoMetadata; }\n// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; }\n// Forward declaration of `HybridVideoPlayerFactorySpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerFactorySpec; }\n// Forward declaration of `HybridVideoPlayerSourceFactorySpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceFactorySpec; }\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSpec; }\n// Forward declaration of `HybridVideoViewViewManagerFactorySpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoViewViewManagerFactorySpec; }\n// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; }\n// Forward declaration of `IgnoreSilentSwitchMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class IgnoreSilentSwitchMode; }\n// Forward declaration of `ListenerSubscription` to properly resolve imports.\nnamespace margelo::nitro::video { struct ListenerSubscription; }\n// Forward declaration of `LivePlaybackParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct LivePlaybackParams; }\n// Forward declaration of `MixAudioMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class MixAudioMode; }\n// Forward declaration of `NativeDrmParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeDrmParams; }\n// Forward declaration of `NativeExternalSubtitle` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeExternalSubtitle; }\n// Forward declaration of `NativeVideoConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeVideoConfig; }\n// Forward declaration of `OnGetLicensePayload` to properly resolve imports.\nnamespace margelo::nitro::video { struct OnGetLicensePayload; }\n// Forward declaration of `ResizeMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class ResizeMode; }\n// Forward declaration of `Resolution` to properly resolve imports.\nnamespace margelo::nitro::video { struct Resolution; }\n// Forward declaration of `SourceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SourceType; }\n// Forward declaration of `SubtitleType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SubtitleType; }\n// Forward declaration of `SurfaceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SurfaceType; }\n// Forward declaration of `TextTrack` to properly resolve imports.\nnamespace margelo::nitro::video { struct TextTrack; }\n// Forward declaration of `TimedMetadataObject` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadataObject; }\n// Forward declaration of `TimedMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadata; }\n// Forward declaration of `VideoInformation` to properly resolve imports.\nnamespace margelo::nitro::video { struct VideoInformation; }\n// Forward declaration of `VideoOrientation` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoOrientation; }\n// Forward declaration of `VideoPlayerStatus` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoPlayerStatus; }\n// Forward declaration of `onLoadData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadData; }\n// Forward declaration of `onLoadStartData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadStartData; }\n// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onPlaybackStateChangeData; }\n// Forward declaration of `onProgressData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onProgressData; }\n// Forward declaration of `onVolumeChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onVolumeChangeData; }\n\n// Include C++ defined types\n#include \"BandwidthData.hpp\"\n#include \"BufferConfig.hpp\"\n#include \"CustomVideoMetadata.hpp\"\n#include \"HybridVideoPlayerEventEmitterSpec.hpp\"\n#include \"HybridVideoPlayerFactorySpec.hpp\"\n#include \"HybridVideoPlayerSourceFactorySpec.hpp\"\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"HybridVideoPlayerSpec.hpp\"\n#include \"HybridVideoViewViewManagerFactorySpec.hpp\"\n#include \"HybridVideoViewViewManagerSpec.hpp\"\n#include \"IgnoreSilentSwitchMode.hpp\"\n#include \"ListenerSubscription.hpp\"\n#include \"LivePlaybackParams.hpp\"\n#include \"MixAudioMode.hpp\"\n#include \"NativeDrmParams.hpp\"\n#include \"NativeExternalSubtitle.hpp\"\n#include \"NativeVideoConfig.hpp\"\n#include \"OnGetLicensePayload.hpp\"\n#include \"ResizeMode.hpp\"\n#include \"Resolution.hpp\"\n#include \"SourceType.hpp\"\n#include \"SubtitleType.hpp\"\n#include \"SurfaceType.hpp\"\n#include \"TextTrack.hpp\"\n#include \"TimedMetadata.hpp\"\n#include \"TimedMetadataObject.hpp\"\n#include \"VideoInformation.hpp\"\n#include \"VideoOrientation.hpp\"\n#include \"VideoPlayerStatus.hpp\"\n#include \"onLoadData.hpp\"\n#include \"onLoadStartData.hpp\"\n#include \"onPlaybackStateChangeData.hpp\"\n#include \"onProgressData.hpp\"\n#include \"onVolumeChangeData.hpp\"\n#include <NitroModules/Null.hpp>\n#include <NitroModules/Promise.hpp>\n#include <NitroModules/Result.hpp>\n#include <exception>\n#include <functional>\n#include <memory>\n#include <optional>\n#include <string>\n#include <unordered_map>\n#include <variant>\n#include <vector>\n\n// C++ helpers for Swift\n#include \"ReactNativeVideo-Swift-Cxx-Bridge.hpp\"\n\n// Common C++ types used in Swift\n#include <NitroModules/ArrayBufferHolder.hpp>\n#include <NitroModules/AnyMapUtils.hpp>\n#include <NitroModules/RuntimeError.hpp>\n#include <NitroModules/DateToChronoDate.hpp>\n\n// Forward declarations of Swift defined types\n// Forward declaration of `HybridVideoPlayerEventEmitterSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerEventEmitterSpec_cxx; }\n// Forward declaration of `HybridVideoPlayerFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerFactorySpec_cxx; }\n// Forward declaration of `HybridVideoPlayerSourceFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSourceFactorySpec_cxx; }\n// Forward declaration of `HybridVideoPlayerSourceSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSourceSpec_cxx; }\n// Forward declaration of `HybridVideoPlayerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSpec_cxx; }\n// Forward declaration of `HybridVideoViewViewManagerFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoViewViewManagerFactorySpec_cxx; }\n// Forward declaration of `HybridVideoViewViewManagerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoViewViewManagerSpec_cxx; }\n\n// Include Swift defined types\n#if __has_include(\"ReactNativeVideo-Swift.h\")\n// This header is generated by Xcode/Swift on every app build.\n// If it cannot be found, make sure the Swift module's name (= podspec name) is actually \"ReactNativeVideo\".\n#include \"ReactNativeVideo-Swift.h\"\n// Same as above, but used when building with frameworks (`use_frameworks`)\n#elif __has_include(<ReactNativeVideo/ReactNativeVideo-Swift.h>)\n#include <ReactNativeVideo/ReactNativeVideo-Swift.h>\n#else\n#error ReactNativeVideo's autogenerated Swift header cannot be found! Make sure the Swift module's name (= podspec name) is actually \"ReactNativeVideo\", and try building the app first.\n#endif\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/ReactNativeVideoAutolinking.mm",
    "content": "///\n/// ReactNativeVideoAutolinking.mm\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#import <Foundation/Foundation.h>\n#import <NitroModules/HybridObjectRegistry.hpp>\n#import \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n#import <type_traits>\n\n#include \"HybridVideoPlayerFactorySpecSwift.hpp\"\n#include \"HybridVideoPlayerSourceFactorySpecSwift.hpp\"\n#include \"HybridVideoViewViewManagerFactorySpecSwift.hpp\"\n\n@interface ReactNativeVideoAutolinking : NSObject\n@end\n\n@implementation ReactNativeVideoAutolinking\n\n+ (void) load {\n  using namespace margelo::nitro;\n  using namespace margelo::nitro::video;\n\n  HybridObjectRegistry::registerHybridObjectConstructor(\n    \"VideoPlayerFactory\",\n    []() -> std::shared_ptr<HybridObject> {\n      std::shared_ptr<HybridVideoPlayerFactorySpec> hybridObject = ReactNativeVideo::ReactNativeVideoAutolinking::createVideoPlayerFactory();\n      return hybridObject;\n    }\n  );\n  HybridObjectRegistry::registerHybridObjectConstructor(\n    \"VideoPlayerSourceFactory\",\n    []() -> std::shared_ptr<HybridObject> {\n      std::shared_ptr<HybridVideoPlayerSourceFactorySpec> hybridObject = ReactNativeVideo::ReactNativeVideoAutolinking::createVideoPlayerSourceFactory();\n      return hybridObject;\n    }\n  );\n  HybridObjectRegistry::registerHybridObjectConstructor(\n    \"VideoViewViewManagerFactory\",\n    []() -> std::shared_ptr<HybridObject> {\n      std::shared_ptr<HybridVideoViewViewManagerFactorySpec> hybridObject = ReactNativeVideo::ReactNativeVideoAutolinking::createVideoViewViewManagerFactory();\n      return hybridObject;\n    }\n  );\n}\n\n@end\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/ReactNativeVideoAutolinking.swift",
    "content": "///\n/// ReactNativeVideoAutolinking.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n// TODO: Use empty enums once Swift supports exporting them as namespaces\n//       See: https://github.com/swiftlang/swift/pull/83616\npublic final class ReactNativeVideoAutolinking {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  public static func createVideoPlayerFactory() -> bridge.std__shared_ptr_HybridVideoPlayerFactorySpec_ {\n    let hybridObject = HybridVideoPlayerFactory()\n    return { () -> bridge.std__shared_ptr_HybridVideoPlayerFactorySpec_ in\n      let __cxxWrapped = hybridObject.getCxxWrapper()\n      return __cxxWrapped.getCxxPart()\n    }()\n  }\n  \n  public static func isVideoPlayerFactoryRecyclable() -> Bool {\n    return HybridVideoPlayerFactory.self is any RecyclableView.Type\n  }\n  \n  public static func createVideoPlayerSourceFactory() -> bridge.std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ {\n    let hybridObject = HybridVideoPlayerSourceFactory()\n    return { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ in\n      let __cxxWrapped = hybridObject.getCxxWrapper()\n      return __cxxWrapped.getCxxPart()\n    }()\n  }\n  \n  public static func isVideoPlayerSourceFactoryRecyclable() -> Bool {\n    return HybridVideoPlayerSourceFactory.self is any RecyclableView.Type\n  }\n  \n  public static func createVideoViewViewManagerFactory() -> bridge.std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ {\n    let hybridObject = HybridVideoViewViewManagerFactory()\n    return { () -> bridge.std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ in\n      let __cxxWrapped = hybridObject.getCxxWrapper()\n      return __cxxWrapped.getCxxPart()\n    }()\n  }\n  \n  public static func isVideoViewViewManagerFactoryRecyclable() -> Bool {\n    return HybridVideoViewViewManagerFactory.self is any RecyclableView.Type\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerEventEmitterSpecSwift.cpp",
    "content": "///\n/// HybridVideoPlayerEventEmitterSpecSwift.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerEventEmitterSpecSwift.hpp\"\n\nnamespace margelo::nitro::video {\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerEventEmitterSpecSwift.hpp",
    "content": "///\n/// HybridVideoPlayerEventEmitterSpecSwift.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include \"HybridVideoPlayerEventEmitterSpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerEventEmitterSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerEventEmitterSpec_cxx; }\n\n// Forward declaration of `ListenerSubscription` to properly resolve imports.\nnamespace margelo::nitro::video { struct ListenerSubscription; }\n// Forward declaration of `BandwidthData` to properly resolve imports.\nnamespace margelo::nitro::video { struct BandwidthData; }\n// Forward declaration of `onLoadData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadData; }\n// Forward declaration of `VideoOrientation` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoOrientation; }\n// Forward declaration of `onLoadStartData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadStartData; }\n// Forward declaration of `SourceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SourceType; }\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onPlaybackStateChangeData; }\n// Forward declaration of `onProgressData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onProgressData; }\n// Forward declaration of `VideoPlayerStatus` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoPlayerStatus; }\n// Forward declaration of `TimedMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadata; }\n// Forward declaration of `TimedMetadataObject` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadataObject; }\n// Forward declaration of `TextTrack` to properly resolve imports.\nnamespace margelo::nitro::video { struct TextTrack; }\n// Forward declaration of `onVolumeChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onVolumeChangeData; }\n\n#include \"ListenerSubscription.hpp\"\n#include <functional>\n#include \"BandwidthData.hpp\"\n#include <optional>\n#include \"onLoadData.hpp\"\n#include \"VideoOrientation.hpp\"\n#include \"onLoadStartData.hpp\"\n#include \"SourceType.hpp\"\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"onPlaybackStateChangeData.hpp\"\n#include \"onProgressData.hpp\"\n#include \"VideoPlayerStatus.hpp\"\n#include \"TimedMetadata.hpp\"\n#include \"TimedMetadataObject.hpp\"\n#include <vector>\n#include <string>\n#include <NitroModules/Null.hpp>\n#include \"TextTrack.hpp\"\n#include <variant>\n#include \"onVolumeChangeData.hpp\"\n\n#include \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * The C++ part of HybridVideoPlayerEventEmitterSpec_cxx.swift.\n   *\n   * HybridVideoPlayerEventEmitterSpecSwift (C++) accesses HybridVideoPlayerEventEmitterSpec_cxx (Swift), and might\n   * contain some additional bridging code for C++ <> Swift interop.\n   *\n   * Since this obviously introduces an overhead, I hope at some point in\n   * the future, HybridVideoPlayerEventEmitterSpec_cxx can directly inherit from the C++ class HybridVideoPlayerEventEmitterSpec\n   * to simplify the whole structure and memory management.\n   */\n  class HybridVideoPlayerEventEmitterSpecSwift: public virtual HybridVideoPlayerEventEmitterSpec {\n  public:\n    // Constructor from a Swift instance\n    explicit HybridVideoPlayerEventEmitterSpecSwift(const ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx& swiftPart):\n      HybridObject(HybridVideoPlayerEventEmitterSpec::TAG),\n      _swiftPart(swiftPart) { }\n\n  public:\n    // Get the Swift part\n    inline ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx& getSwiftPart() noexcept {\n      return _swiftPart;\n    }\n\n  public:\n    inline size_t getExternalMemorySize() noexcept override {\n      return _swiftPart.getMemorySize();\n    }\n    bool equals(const std::shared_ptr<HybridObject>& other) override {\n      if (auto otherCast = std::dynamic_pointer_cast<HybridVideoPlayerEventEmitterSpecSwift>(other)) {\n        return _swiftPart.equals(otherCast->_swiftPart);\n      }\n      return false;\n    }\n    void dispose() noexcept override {\n      _swiftPart.dispose();\n    }\n    std::string toString() override {\n      return _swiftPart.toString();\n    }\n\n  public:\n    // Properties\n    \n\n  public:\n    // Methods\n    inline ListenerSubscription addOnAudioBecomingNoisyListener(const std::function<void()>& listener) override {\n      auto __result = _swiftPart.addOnAudioBecomingNoisyListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnAudioFocusChangeListener(const std::function<void(bool /* hasAudioFocus */)>& listener) override {\n      auto __result = _swiftPart.addOnAudioFocusChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnBandwidthUpdateListener(const std::function<void(const BandwidthData& /* data */)>& listener) override {\n      auto __result = _swiftPart.addOnBandwidthUpdateListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnBufferListener(const std::function<void(bool /* buffering */)>& listener) override {\n      auto __result = _swiftPart.addOnBufferListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnControlsVisibleChangeListener(const std::function<void(bool /* visible */)>& listener) override {\n      auto __result = _swiftPart.addOnControlsVisibleChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnEndListener(const std::function<void()>& listener) override {\n      auto __result = _swiftPart.addOnEndListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnExternalPlaybackChangeListener(const std::function<void(bool /* externalPlaybackActive */)>& listener) override {\n      auto __result = _swiftPart.addOnExternalPlaybackChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnLoadListener(const std::function<void(const onLoadData& /* data */)>& listener) override {\n      auto __result = _swiftPart.addOnLoadListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnLoadStartListener(const std::function<void(const onLoadStartData& /* data */)>& listener) override {\n      auto __result = _swiftPart.addOnLoadStartListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnPlaybackStateChangeListener(const std::function<void(const onPlaybackStateChangeData& /* data */)>& listener) override {\n      auto __result = _swiftPart.addOnPlaybackStateChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnPlaybackRateChangeListener(const std::function<void(double /* rate */)>& listener) override {\n      auto __result = _swiftPart.addOnPlaybackRateChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnProgressListener(const std::function<void(const onProgressData& /* data */)>& listener) override {\n      auto __result = _swiftPart.addOnProgressListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnReadyToDisplayListener(const std::function<void()>& listener) override {\n      auto __result = _swiftPart.addOnReadyToDisplayListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnSeekListener(const std::function<void(double /* position */)>& listener) override {\n      auto __result = _swiftPart.addOnSeekListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnStatusChangeListener(const std::function<void(VideoPlayerStatus /* status */)>& listener) override {\n      auto __result = _swiftPart.addOnStatusChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnTimedMetadataListener(const std::function<void(const TimedMetadata& /* data */)>& listener) override {\n      auto __result = _swiftPart.addOnTimedMetadataListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnTextTrackDataChangedListener(const std::function<void(const std::vector<std::string>& /* data */)>& listener) override {\n      auto __result = _swiftPart.addOnTextTrackDataChangedListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnTrackChangeListener(const std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>& listener) override {\n      auto __result = _swiftPart.addOnTrackChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnVolumeChangeListener(const std::function<void(const onVolumeChangeData& /* data */)>& listener) override {\n      auto __result = _swiftPart.addOnVolumeChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline void clearAllListeners() override {\n      auto __result = _swiftPart.clearAllListeners();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n\n  private:\n    ReactNativeVideo::HybridVideoPlayerEventEmitterSpec_cxx _swiftPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerFactorySpecSwift.cpp",
    "content": "///\n/// HybridVideoPlayerFactorySpecSwift.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerFactorySpecSwift.hpp\"\n\nnamespace margelo::nitro::video {\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerFactorySpecSwift.hpp",
    "content": "///\n/// HybridVideoPlayerFactorySpecSwift.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include \"HybridVideoPlayerFactorySpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerFactorySpec_cxx; }\n\n// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSpec; }\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n\n#include <memory>\n#include \"HybridVideoPlayerSpec.hpp\"\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n\n#include \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * The C++ part of HybridVideoPlayerFactorySpec_cxx.swift.\n   *\n   * HybridVideoPlayerFactorySpecSwift (C++) accesses HybridVideoPlayerFactorySpec_cxx (Swift), and might\n   * contain some additional bridging code for C++ <> Swift interop.\n   *\n   * Since this obviously introduces an overhead, I hope at some point in\n   * the future, HybridVideoPlayerFactorySpec_cxx can directly inherit from the C++ class HybridVideoPlayerFactorySpec\n   * to simplify the whole structure and memory management.\n   */\n  class HybridVideoPlayerFactorySpecSwift: public virtual HybridVideoPlayerFactorySpec {\n  public:\n    // Constructor from a Swift instance\n    explicit HybridVideoPlayerFactorySpecSwift(const ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx& swiftPart):\n      HybridObject(HybridVideoPlayerFactorySpec::TAG),\n      _swiftPart(swiftPart) { }\n\n  public:\n    // Get the Swift part\n    inline ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx& getSwiftPart() noexcept {\n      return _swiftPart;\n    }\n\n  public:\n    inline size_t getExternalMemorySize() noexcept override {\n      return _swiftPart.getMemorySize();\n    }\n    bool equals(const std::shared_ptr<HybridObject>& other) override {\n      if (auto otherCast = std::dynamic_pointer_cast<HybridVideoPlayerFactorySpecSwift>(other)) {\n        return _swiftPart.equals(otherCast->_swiftPart);\n      }\n      return false;\n    }\n    void dispose() noexcept override {\n      _swiftPart.dispose();\n    }\n    std::string toString() override {\n      return _swiftPart.toString();\n    }\n\n  public:\n    // Properties\n    \n\n  public:\n    // Methods\n    inline std::shared_ptr<HybridVideoPlayerSpec> createPlayer(const std::shared_ptr<HybridVideoPlayerSourceSpec>& source) override {\n      auto __result = _swiftPart.createPlayer(source);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n\n  private:\n    ReactNativeVideo::HybridVideoPlayerFactorySpec_cxx _swiftPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerSourceFactorySpecSwift.cpp",
    "content": "///\n/// HybridVideoPlayerSourceFactorySpecSwift.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerSourceFactorySpecSwift.hpp\"\n\nnamespace margelo::nitro::video {\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerSourceFactorySpecSwift.hpp",
    "content": "///\n/// HybridVideoPlayerSourceFactorySpecSwift.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include \"HybridVideoPlayerSourceFactorySpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerSourceFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSourceFactorySpec_cxx; }\n\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `NativeVideoConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeVideoConfig; }\n// Forward declaration of `NativeExternalSubtitle` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeExternalSubtitle; }\n// Forward declaration of `SubtitleType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SubtitleType; }\n// Forward declaration of `NativeDrmParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeDrmParams; }\n// Forward declaration of `OnGetLicensePayload` to properly resolve imports.\nnamespace margelo::nitro::video { struct OnGetLicensePayload; }\n// Forward declaration of `BufferConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct BufferConfig; }\n// Forward declaration of `LivePlaybackParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct LivePlaybackParams; }\n// Forward declaration of `Resolution` to properly resolve imports.\nnamespace margelo::nitro::video { struct Resolution; }\n// Forward declaration of `CustomVideoMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct CustomVideoMetadata; }\n\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include <string>\n#include \"NativeVideoConfig.hpp\"\n#include \"NativeExternalSubtitle.hpp\"\n#include <vector>\n#include <optional>\n#include \"SubtitleType.hpp\"\n#include \"NativeDrmParams.hpp\"\n#include <unordered_map>\n#include <NitroModules/Promise.hpp>\n#include \"OnGetLicensePayload.hpp\"\n#include <functional>\n#include \"BufferConfig.hpp\"\n#include \"LivePlaybackParams.hpp\"\n#include \"Resolution.hpp\"\n#include \"CustomVideoMetadata.hpp\"\n\n#include \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * The C++ part of HybridVideoPlayerSourceFactorySpec_cxx.swift.\n   *\n   * HybridVideoPlayerSourceFactorySpecSwift (C++) accesses HybridVideoPlayerSourceFactorySpec_cxx (Swift), and might\n   * contain some additional bridging code for C++ <> Swift interop.\n   *\n   * Since this obviously introduces an overhead, I hope at some point in\n   * the future, HybridVideoPlayerSourceFactorySpec_cxx can directly inherit from the C++ class HybridVideoPlayerSourceFactorySpec\n   * to simplify the whole structure and memory management.\n   */\n  class HybridVideoPlayerSourceFactorySpecSwift: public virtual HybridVideoPlayerSourceFactorySpec {\n  public:\n    // Constructor from a Swift instance\n    explicit HybridVideoPlayerSourceFactorySpecSwift(const ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx& swiftPart):\n      HybridObject(HybridVideoPlayerSourceFactorySpec::TAG),\n      _swiftPart(swiftPart) { }\n\n  public:\n    // Get the Swift part\n    inline ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx& getSwiftPart() noexcept {\n      return _swiftPart;\n    }\n\n  public:\n    inline size_t getExternalMemorySize() noexcept override {\n      return _swiftPart.getMemorySize();\n    }\n    bool equals(const std::shared_ptr<HybridObject>& other) override {\n      if (auto otherCast = std::dynamic_pointer_cast<HybridVideoPlayerSourceFactorySpecSwift>(other)) {\n        return _swiftPart.equals(otherCast->_swiftPart);\n      }\n      return false;\n    }\n    void dispose() noexcept override {\n      _swiftPart.dispose();\n    }\n    std::string toString() override {\n      return _swiftPart.toString();\n    }\n\n  public:\n    // Properties\n    \n\n  public:\n    // Methods\n    inline std::shared_ptr<HybridVideoPlayerSourceSpec> fromUri(const std::string& uri) override {\n      auto __result = _swiftPart.fromUri(uri);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline std::shared_ptr<HybridVideoPlayerSourceSpec> fromVideoConfig(const NativeVideoConfig& config) override {\n      auto __result = _swiftPart.fromVideoConfig(std::forward<decltype(config)>(config));\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n\n  private:\n    ReactNativeVideo::HybridVideoPlayerSourceFactorySpec_cxx _swiftPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerSourceSpecSwift.cpp",
    "content": "///\n/// HybridVideoPlayerSourceSpecSwift.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerSourceSpecSwift.hpp\"\n\nnamespace margelo::nitro::video {\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerSourceSpecSwift.hpp",
    "content": "///\n/// HybridVideoPlayerSourceSpecSwift.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerSourceSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSourceSpec_cxx; }\n\n// Forward declaration of `NativeVideoConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeVideoConfig; }\n// Forward declaration of `NativeExternalSubtitle` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeExternalSubtitle; }\n// Forward declaration of `SubtitleType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SubtitleType; }\n// Forward declaration of `NativeDrmParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeDrmParams; }\n// Forward declaration of `OnGetLicensePayload` to properly resolve imports.\nnamespace margelo::nitro::video { struct OnGetLicensePayload; }\n// Forward declaration of `BufferConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct BufferConfig; }\n// Forward declaration of `LivePlaybackParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct LivePlaybackParams; }\n// Forward declaration of `Resolution` to properly resolve imports.\nnamespace margelo::nitro::video { struct Resolution; }\n// Forward declaration of `CustomVideoMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct CustomVideoMetadata; }\n// Forward declaration of `VideoInformation` to properly resolve imports.\nnamespace margelo::nitro::video { struct VideoInformation; }\n// Forward declaration of `VideoOrientation` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoOrientation; }\n\n#include <string>\n#include \"NativeVideoConfig.hpp\"\n#include \"NativeExternalSubtitle.hpp\"\n#include <vector>\n#include <optional>\n#include \"SubtitleType.hpp\"\n#include \"NativeDrmParams.hpp\"\n#include <unordered_map>\n#include <NitroModules/Promise.hpp>\n#include \"OnGetLicensePayload.hpp\"\n#include <functional>\n#include \"BufferConfig.hpp\"\n#include \"LivePlaybackParams.hpp\"\n#include \"Resolution.hpp\"\n#include \"CustomVideoMetadata.hpp\"\n#include \"VideoInformation.hpp\"\n#include \"VideoOrientation.hpp\"\n\n#include \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * The C++ part of HybridVideoPlayerSourceSpec_cxx.swift.\n   *\n   * HybridVideoPlayerSourceSpecSwift (C++) accesses HybridVideoPlayerSourceSpec_cxx (Swift), and might\n   * contain some additional bridging code for C++ <> Swift interop.\n   *\n   * Since this obviously introduces an overhead, I hope at some point in\n   * the future, HybridVideoPlayerSourceSpec_cxx can directly inherit from the C++ class HybridVideoPlayerSourceSpec\n   * to simplify the whole structure and memory management.\n   */\n  class HybridVideoPlayerSourceSpecSwift: public virtual HybridVideoPlayerSourceSpec {\n  public:\n    // Constructor from a Swift instance\n    explicit HybridVideoPlayerSourceSpecSwift(const ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx& swiftPart):\n      HybridObject(HybridVideoPlayerSourceSpec::TAG),\n      _swiftPart(swiftPart) { }\n\n  public:\n    // Get the Swift part\n    inline ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx& getSwiftPart() noexcept {\n      return _swiftPart;\n    }\n\n  public:\n    inline size_t getExternalMemorySize() noexcept override {\n      return _swiftPart.getMemorySize();\n    }\n    bool equals(const std::shared_ptr<HybridObject>& other) override {\n      if (auto otherCast = std::dynamic_pointer_cast<HybridVideoPlayerSourceSpecSwift>(other)) {\n        return _swiftPart.equals(otherCast->_swiftPart);\n      }\n      return false;\n    }\n    void dispose() noexcept override {\n      _swiftPart.dispose();\n    }\n    std::string toString() override {\n      return _swiftPart.toString();\n    }\n\n  public:\n    // Properties\n    inline std::string getUri() noexcept override {\n      auto __result = _swiftPart.getUri();\n      return __result;\n    }\n    inline NativeVideoConfig getConfig() noexcept override {\n      return _swiftPart.getConfig();\n    }\n\n  public:\n    // Methods\n    inline std::shared_ptr<Promise<VideoInformation>> getAssetInformationAsync() override {\n      auto __result = _swiftPart.getAssetInformationAsync();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n\n  private:\n    ReactNativeVideo::HybridVideoPlayerSourceSpec_cxx _swiftPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerSpecSwift.cpp",
    "content": "///\n/// HybridVideoPlayerSpecSwift.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerSpecSwift.hpp\"\n\nnamespace margelo::nitro::video {\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoPlayerSpecSwift.hpp",
    "content": "///\n/// HybridVideoPlayerSpecSwift.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include \"HybridVideoPlayerSpec.hpp\"\n\n// Forward declaration of `HybridVideoPlayerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoPlayerSpec_cxx; }\n\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; }\n// Forward declaration of `VideoPlayerStatus` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoPlayerStatus; }\n// Forward declaration of `MixAudioMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class MixAudioMode; }\n// Forward declaration of `IgnoreSilentSwitchMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class IgnoreSilentSwitchMode; }\n// Forward declaration of `TextTrack` to properly resolve imports.\nnamespace margelo::nitro::video { struct TextTrack; }\n\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"HybridVideoPlayerEventEmitterSpec.hpp\"\n#include \"VideoPlayerStatus.hpp\"\n#include \"MixAudioMode.hpp\"\n#include \"IgnoreSilentSwitchMode.hpp\"\n#include \"TextTrack.hpp\"\n#include <optional>\n#include <string>\n#include <NitroModules/Promise.hpp>\n#include <NitroModules/Null.hpp>\n#include <variant>\n#include <vector>\n\n#include \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * The C++ part of HybridVideoPlayerSpec_cxx.swift.\n   *\n   * HybridVideoPlayerSpecSwift (C++) accesses HybridVideoPlayerSpec_cxx (Swift), and might\n   * contain some additional bridging code for C++ <> Swift interop.\n   *\n   * Since this obviously introduces an overhead, I hope at some point in\n   * the future, HybridVideoPlayerSpec_cxx can directly inherit from the C++ class HybridVideoPlayerSpec\n   * to simplify the whole structure and memory management.\n   */\n  class HybridVideoPlayerSpecSwift: public virtual HybridVideoPlayerSpec {\n  public:\n    // Constructor from a Swift instance\n    explicit HybridVideoPlayerSpecSwift(const ReactNativeVideo::HybridVideoPlayerSpec_cxx& swiftPart):\n      HybridObject(HybridVideoPlayerSpec::TAG),\n      _swiftPart(swiftPart) { }\n\n  public:\n    // Get the Swift part\n    inline ReactNativeVideo::HybridVideoPlayerSpec_cxx& getSwiftPart() noexcept {\n      return _swiftPart;\n    }\n\n  public:\n    inline size_t getExternalMemorySize() noexcept override {\n      return _swiftPart.getMemorySize();\n    }\n    bool equals(const std::shared_ptr<HybridObject>& other) override {\n      if (auto otherCast = std::dynamic_pointer_cast<HybridVideoPlayerSpecSwift>(other)) {\n        return _swiftPart.equals(otherCast->_swiftPart);\n      }\n      return false;\n    }\n    void dispose() noexcept override {\n      _swiftPart.dispose();\n    }\n    std::string toString() override {\n      return _swiftPart.toString();\n    }\n\n  public:\n    // Properties\n    inline std::shared_ptr<HybridVideoPlayerSourceSpec> getSource() noexcept override {\n      auto __result = _swiftPart.getSource();\n      return __result;\n    }\n    inline std::shared_ptr<HybridVideoPlayerEventEmitterSpec> getEventEmitter() noexcept override {\n      auto __result = _swiftPart.getEventEmitter();\n      return __result;\n    }\n    inline bool getShowNotificationControls() noexcept override {\n      return _swiftPart.getShowNotificationControls();\n    }\n    inline void setShowNotificationControls(bool showNotificationControls) noexcept override {\n      _swiftPart.setShowNotificationControls(std::forward<decltype(showNotificationControls)>(showNotificationControls));\n    }\n    inline VideoPlayerStatus getStatus() noexcept override {\n      auto __result = _swiftPart.getStatus();\n      return static_cast<VideoPlayerStatus>(__result);\n    }\n    inline double getDuration() noexcept override {\n      return _swiftPart.getDuration();\n    }\n    inline double getVolume() noexcept override {\n      return _swiftPart.getVolume();\n    }\n    inline void setVolume(double volume) noexcept override {\n      _swiftPart.setVolume(std::forward<decltype(volume)>(volume));\n    }\n    inline double getCurrentTime() noexcept override {\n      return _swiftPart.getCurrentTime();\n    }\n    inline void setCurrentTime(double currentTime) noexcept override {\n      _swiftPart.setCurrentTime(std::forward<decltype(currentTime)>(currentTime));\n    }\n    inline bool getMuted() noexcept override {\n      return _swiftPart.getMuted();\n    }\n    inline void setMuted(bool muted) noexcept override {\n      _swiftPart.setMuted(std::forward<decltype(muted)>(muted));\n    }\n    inline bool getLoop() noexcept override {\n      return _swiftPart.getLoop();\n    }\n    inline void setLoop(bool loop) noexcept override {\n      _swiftPart.setLoop(std::forward<decltype(loop)>(loop));\n    }\n    inline double getRate() noexcept override {\n      return _swiftPart.getRate();\n    }\n    inline void setRate(double rate) noexcept override {\n      _swiftPart.setRate(std::forward<decltype(rate)>(rate));\n    }\n    inline MixAudioMode getMixAudioMode() noexcept override {\n      auto __result = _swiftPart.getMixAudioMode();\n      return static_cast<MixAudioMode>(__result);\n    }\n    inline void setMixAudioMode(MixAudioMode mixAudioMode) noexcept override {\n      _swiftPart.setMixAudioMode(static_cast<int>(mixAudioMode));\n    }\n    inline IgnoreSilentSwitchMode getIgnoreSilentSwitchMode() noexcept override {\n      auto __result = _swiftPart.getIgnoreSilentSwitchMode();\n      return static_cast<IgnoreSilentSwitchMode>(__result);\n    }\n    inline void setIgnoreSilentSwitchMode(IgnoreSilentSwitchMode ignoreSilentSwitchMode) noexcept override {\n      _swiftPart.setIgnoreSilentSwitchMode(static_cast<int>(ignoreSilentSwitchMode));\n    }\n    inline bool getPlayInBackground() noexcept override {\n      return _swiftPart.getPlayInBackground();\n    }\n    inline void setPlayInBackground(bool playInBackground) noexcept override {\n      _swiftPart.setPlayInBackground(std::forward<decltype(playInBackground)>(playInBackground));\n    }\n    inline bool getPlayWhenInactive() noexcept override {\n      return _swiftPart.getPlayWhenInactive();\n    }\n    inline void setPlayWhenInactive(bool playWhenInactive) noexcept override {\n      _swiftPart.setPlayWhenInactive(std::forward<decltype(playWhenInactive)>(playWhenInactive));\n    }\n    inline bool getIsPlaying() noexcept override {\n      return _swiftPart.isPlaying();\n    }\n    inline std::optional<TextTrack> getSelectedTrack() noexcept override {\n      auto __result = _swiftPart.getSelectedTrack();\n      return __result;\n    }\n\n  public:\n    // Methods\n    inline std::shared_ptr<Promise<void>> replaceSourceAsync(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& source) override {\n      auto __result = _swiftPart.replaceSourceAsync(source);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline std::vector<TextTrack> getAvailableTextTracks() override {\n      auto __result = _swiftPart.getAvailableTextTracks();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline void selectTextTrack(const std::optional<std::variant<nitro::NullType, TextTrack>>& textTrack) override {\n      auto __result = _swiftPart.selectTextTrack(textTrack);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline void release() override {\n      auto __result = _swiftPart.release();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline std::shared_ptr<Promise<void>> initialize() override {\n      auto __result = _swiftPart.initialize();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline std::shared_ptr<Promise<void>> preload() override {\n      auto __result = _swiftPart.preload();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline void play() override {\n      auto __result = _swiftPart.play();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline void pause() override {\n      auto __result = _swiftPart.pause();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline void seekBy(double time) override {\n      auto __result = _swiftPart.seekBy(std::forward<decltype(time)>(time));\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline void seekTo(double time) override {\n      auto __result = _swiftPart.seekTo(std::forward<decltype(time)>(time));\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n\n  private:\n    ReactNativeVideo::HybridVideoPlayerSpec_cxx _swiftPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoViewViewManagerFactorySpecSwift.cpp",
    "content": "///\n/// HybridVideoViewViewManagerFactorySpecSwift.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoViewViewManagerFactorySpecSwift.hpp\"\n\nnamespace margelo::nitro::video {\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoViewViewManagerFactorySpecSwift.hpp",
    "content": "///\n/// HybridVideoViewViewManagerFactorySpecSwift.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include \"HybridVideoViewViewManagerFactorySpec.hpp\"\n\n// Forward declaration of `HybridVideoViewViewManagerFactorySpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoViewViewManagerFactorySpec_cxx; }\n\n// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; }\n\n#include <memory>\n#include \"HybridVideoViewViewManagerSpec.hpp\"\n\n#include \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * The C++ part of HybridVideoViewViewManagerFactorySpec_cxx.swift.\n   *\n   * HybridVideoViewViewManagerFactorySpecSwift (C++) accesses HybridVideoViewViewManagerFactorySpec_cxx (Swift), and might\n   * contain some additional bridging code for C++ <> Swift interop.\n   *\n   * Since this obviously introduces an overhead, I hope at some point in\n   * the future, HybridVideoViewViewManagerFactorySpec_cxx can directly inherit from the C++ class HybridVideoViewViewManagerFactorySpec\n   * to simplify the whole structure and memory management.\n   */\n  class HybridVideoViewViewManagerFactorySpecSwift: public virtual HybridVideoViewViewManagerFactorySpec {\n  public:\n    // Constructor from a Swift instance\n    explicit HybridVideoViewViewManagerFactorySpecSwift(const ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx& swiftPart):\n      HybridObject(HybridVideoViewViewManagerFactorySpec::TAG),\n      _swiftPart(swiftPart) { }\n\n  public:\n    // Get the Swift part\n    inline ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx& getSwiftPart() noexcept {\n      return _swiftPart;\n    }\n\n  public:\n    inline size_t getExternalMemorySize() noexcept override {\n      return _swiftPart.getMemorySize();\n    }\n    bool equals(const std::shared_ptr<HybridObject>& other) override {\n      if (auto otherCast = std::dynamic_pointer_cast<HybridVideoViewViewManagerFactorySpecSwift>(other)) {\n        return _swiftPart.equals(otherCast->_swiftPart);\n      }\n      return false;\n    }\n    void dispose() noexcept override {\n      _swiftPart.dispose();\n    }\n    std::string toString() override {\n      return _swiftPart.toString();\n    }\n\n  public:\n    // Properties\n    \n\n  public:\n    // Methods\n    inline std::shared_ptr<HybridVideoViewViewManagerSpec> createViewManager(double nitroId) override {\n      auto __result = _swiftPart.createViewManager(std::forward<decltype(nitroId)>(nitroId));\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n\n  private:\n    ReactNativeVideo::HybridVideoViewViewManagerFactorySpec_cxx _swiftPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoViewViewManagerSpecSwift.cpp",
    "content": "///\n/// HybridVideoViewViewManagerSpecSwift.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoViewViewManagerSpecSwift.hpp\"\n\nnamespace margelo::nitro::video {\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/c++/HybridVideoViewViewManagerSpecSwift.hpp",
    "content": "///\n/// HybridVideoViewViewManagerSpecSwift.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#include \"HybridVideoViewViewManagerSpec.hpp\"\n\n// Forward declaration of `HybridVideoViewViewManagerSpec_cxx` to properly resolve imports.\nnamespace ReactNativeVideo { class HybridVideoViewViewManagerSpec_cxx; }\n\n// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSpec; }\n// Forward declaration of `ResizeMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class ResizeMode; }\n// Forward declaration of `SurfaceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SurfaceType; }\n// Forward declaration of `ListenerSubscription` to properly resolve imports.\nnamespace margelo::nitro::video { struct ListenerSubscription; }\n\n#include <memory>\n#include \"HybridVideoPlayerSpec.hpp\"\n#include <optional>\n#include \"ResizeMode.hpp\"\n#include \"SurfaceType.hpp\"\n#include \"ListenerSubscription.hpp\"\n#include <functional>\n\n#include \"ReactNativeVideo-Swift-Cxx-Umbrella.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * The C++ part of HybridVideoViewViewManagerSpec_cxx.swift.\n   *\n   * HybridVideoViewViewManagerSpecSwift (C++) accesses HybridVideoViewViewManagerSpec_cxx (Swift), and might\n   * contain some additional bridging code for C++ <> Swift interop.\n   *\n   * Since this obviously introduces an overhead, I hope at some point in\n   * the future, HybridVideoViewViewManagerSpec_cxx can directly inherit from the C++ class HybridVideoViewViewManagerSpec\n   * to simplify the whole structure and memory management.\n   */\n  class HybridVideoViewViewManagerSpecSwift: public virtual HybridVideoViewViewManagerSpec {\n  public:\n    // Constructor from a Swift instance\n    explicit HybridVideoViewViewManagerSpecSwift(const ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx& swiftPart):\n      HybridObject(HybridVideoViewViewManagerSpec::TAG),\n      _swiftPart(swiftPart) { }\n\n  public:\n    // Get the Swift part\n    inline ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx& getSwiftPart() noexcept {\n      return _swiftPart;\n    }\n\n  public:\n    inline size_t getExternalMemorySize() noexcept override {\n      return _swiftPart.getMemorySize();\n    }\n    bool equals(const std::shared_ptr<HybridObject>& other) override {\n      if (auto otherCast = std::dynamic_pointer_cast<HybridVideoViewViewManagerSpecSwift>(other)) {\n        return _swiftPart.equals(otherCast->_swiftPart);\n      }\n      return false;\n    }\n    void dispose() noexcept override {\n      _swiftPart.dispose();\n    }\n    std::string toString() override {\n      return _swiftPart.toString();\n    }\n\n  public:\n    // Properties\n    inline std::optional<std::shared_ptr<HybridVideoPlayerSpec>> getPlayer() noexcept override {\n      auto __result = _swiftPart.getPlayer();\n      return __result;\n    }\n    inline void setPlayer(const std::optional<std::shared_ptr<HybridVideoPlayerSpec>>& player) noexcept override {\n      _swiftPart.setPlayer(player);\n    }\n    inline bool getControls() noexcept override {\n      return _swiftPart.getControls();\n    }\n    inline void setControls(bool controls) noexcept override {\n      _swiftPart.setControls(std::forward<decltype(controls)>(controls));\n    }\n    inline bool getPictureInPicture() noexcept override {\n      return _swiftPart.getPictureInPicture();\n    }\n    inline void setPictureInPicture(bool pictureInPicture) noexcept override {\n      _swiftPart.setPictureInPicture(std::forward<decltype(pictureInPicture)>(pictureInPicture));\n    }\n    inline bool getAutoEnterPictureInPicture() noexcept override {\n      return _swiftPart.getAutoEnterPictureInPicture();\n    }\n    inline void setAutoEnterPictureInPicture(bool autoEnterPictureInPicture) noexcept override {\n      _swiftPart.setAutoEnterPictureInPicture(std::forward<decltype(autoEnterPictureInPicture)>(autoEnterPictureInPicture));\n    }\n    inline ResizeMode getResizeMode() noexcept override {\n      auto __result = _swiftPart.getResizeMode();\n      return static_cast<ResizeMode>(__result);\n    }\n    inline void setResizeMode(ResizeMode resizeMode) noexcept override {\n      _swiftPart.setResizeMode(static_cast<int>(resizeMode));\n    }\n    inline bool getKeepScreenAwake() noexcept override {\n      return _swiftPart.getKeepScreenAwake();\n    }\n    inline void setKeepScreenAwake(bool keepScreenAwake) noexcept override {\n      _swiftPart.setKeepScreenAwake(std::forward<decltype(keepScreenAwake)>(keepScreenAwake));\n    }\n    inline SurfaceType getSurfaceType() noexcept override {\n      auto __result = _swiftPart.getSurfaceType();\n      return static_cast<SurfaceType>(__result);\n    }\n    inline void setSurfaceType(SurfaceType surfaceType) noexcept override {\n      _swiftPart.setSurfaceType(static_cast<int>(surfaceType));\n    }\n\n  public:\n    // Methods\n    inline void enterFullscreen() override {\n      auto __result = _swiftPart.enterFullscreen();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline void exitFullscreen() override {\n      auto __result = _swiftPart.exitFullscreen();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline void enterPictureInPicture() override {\n      auto __result = _swiftPart.enterPictureInPicture();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline void exitPictureInPicture() override {\n      auto __result = _swiftPart.exitPictureInPicture();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n    inline bool canEnterPictureInPicture() override {\n      auto __result = _swiftPart.canEnterPictureInPicture();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnPictureInPictureChangeListener(const std::function<void(bool /* isInPictureInPicture */)>& listener) override {\n      auto __result = _swiftPart.addOnPictureInPictureChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addOnFullscreenChangeListener(const std::function<void(bool /* fullscreen */)>& listener) override {\n      auto __result = _swiftPart.addOnFullscreenChangeListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addWillEnterFullscreenListener(const std::function<void()>& listener) override {\n      auto __result = _swiftPart.addWillEnterFullscreenListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addWillExitFullscreenListener(const std::function<void()>& listener) override {\n      auto __result = _swiftPart.addWillExitFullscreenListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addWillEnterPictureInPictureListener(const std::function<void()>& listener) override {\n      auto __result = _swiftPart.addWillEnterPictureInPictureListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline ListenerSubscription addWillExitPictureInPictureListener(const std::function<void()>& listener) override {\n      auto __result = _swiftPart.addWillExitPictureInPictureListener(listener);\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n      auto __value = std::move(__result.value());\n      return __value;\n    }\n    inline void clearAllListeners() override {\n      auto __result = _swiftPart.clearAllListeners();\n      if (__result.hasError()) [[unlikely]] {\n        std::rethrow_exception(__result.error());\n      }\n    }\n\n  private:\n    ReactNativeVideo::HybridVideoViewViewManagerSpec_cxx _swiftPart;\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/BandwidthData.swift",
    "content": "///\n/// BandwidthData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `BandwidthData`, backed by a C++ struct.\n */\npublic typealias BandwidthData = margelo.nitro.video.BandwidthData\n\npublic extension BandwidthData {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `BandwidthData`.\n   */\n  init(bitrate: Double, width: Double?, height: Double?) {\n    self.init(bitrate, { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = width {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = height {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }())\n  }\n\n  @inline(__always)\n  var bitrate: Double {\n    return self.__bitrate\n  }\n  \n  @inline(__always)\n  var width: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__width) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__width)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var height: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__height) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__height)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/BufferConfig.swift",
    "content": "///\n/// BufferConfig.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `BufferConfig`, backed by a C++ struct.\n */\npublic typealias BufferConfig = margelo.nitro.video.BufferConfig\n\npublic extension BufferConfig {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `BufferConfig`.\n   */\n  init(livePlayback: LivePlaybackParams?, minBufferMs: Double?, maxBufferMs: Double?, bufferForPlaybackMs: Double?, bufferForPlaybackAfterRebufferMs: Double?, backBufferDurationMs: Double?, preferredForwardBufferDurationMs: Double?, preferredPeakBitRate: Double?, preferredMaximumResolution: Resolution?, preferredPeakBitRateForExpensiveNetworks: Double?, preferredMaximumResolutionForExpensiveNetworks: Resolution?) {\n    self.init({ () -> bridge.std__optional_LivePlaybackParams_ in\n      if let __unwrappedValue = livePlayback {\n        return bridge.create_std__optional_LivePlaybackParams_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = minBufferMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = maxBufferMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = bufferForPlaybackMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = bufferForPlaybackAfterRebufferMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = backBufferDurationMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = preferredForwardBufferDurationMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = preferredPeakBitRate {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_Resolution_ in\n      if let __unwrappedValue = preferredMaximumResolution {\n        return bridge.create_std__optional_Resolution_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = preferredPeakBitRateForExpensiveNetworks {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_Resolution_ in\n      if let __unwrappedValue = preferredMaximumResolutionForExpensiveNetworks {\n        return bridge.create_std__optional_Resolution_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }())\n  }\n\n  @inline(__always)\n  var livePlayback: LivePlaybackParams? {\n    return self.__livePlayback.value\n  }\n  \n  @inline(__always)\n  var minBufferMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__minBufferMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__minBufferMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var maxBufferMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__maxBufferMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__maxBufferMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var bufferForPlaybackMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__bufferForPlaybackMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__bufferForPlaybackMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var bufferForPlaybackAfterRebufferMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__bufferForPlaybackAfterRebufferMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__bufferForPlaybackAfterRebufferMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var backBufferDurationMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__backBufferDurationMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__backBufferDurationMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var preferredForwardBufferDurationMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__preferredForwardBufferDurationMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__preferredForwardBufferDurationMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var preferredPeakBitRate: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__preferredPeakBitRate) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__preferredPeakBitRate)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var preferredMaximumResolution: Resolution? {\n    return self.__preferredMaximumResolution.value\n  }\n  \n  @inline(__always)\n  var preferredPeakBitRateForExpensiveNetworks: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__preferredPeakBitRateForExpensiveNetworks) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__preferredPeakBitRateForExpensiveNetworks)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var preferredMaximumResolutionForExpensiveNetworks: Resolution? {\n    return self.__preferredMaximumResolutionForExpensiveNetworks.value\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/CustomVideoMetadata.swift",
    "content": "///\n/// CustomVideoMetadata.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `CustomVideoMetadata`, backed by a C++ struct.\n */\npublic typealias CustomVideoMetadata = margelo.nitro.video.CustomVideoMetadata\n\npublic extension CustomVideoMetadata {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `CustomVideoMetadata`.\n   */\n  init(title: String?, subtitle: String?, description: String?, artist: String?, imageUri: String?) {\n    self.init({ () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = title {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = subtitle {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = description {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = artist {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = imageUri {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }())\n  }\n\n  @inline(__always)\n  var title: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__title) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__title)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var subtitle: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__subtitle) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__subtitle)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var description: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__description) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__description)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var artist: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__artist) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__artist)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var imageUri: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__imageUri) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__imageUri)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.swift",
    "content": "///\n/// Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ payload: OnGetLicensePayload) -> Promise<Promise<String>>` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ payload: OnGetLicensePayload) -> Promise<Promise<String>>\n\n  public init(_ closure: @escaping (_ payload: OnGetLicensePayload) -> Promise<Promise<String>>) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(payload: OnGetLicensePayload) -> bridge.std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____ {\n    let __result: Promise<Promise<String>> = self.closure(payload)\n    return { () -> bridge.std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____ in\n      let __promise = bridge.create_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____()\n      let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____(__promise)\n      __result\n        .then({ __result in __promiseHolder.resolve({ () -> bridge.std__shared_ptr_Promise_std__string__ in\n            let __promise = bridge.create_std__shared_ptr_Promise_std__string__()\n            let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__string__(__promise)\n            __result\n              .then({ __result in __promiseHolder.resolve(std.string(__result)) })\n              .catch({ __error in __promiseHolder.reject(__error.toCpp()) })\n            return __promise\n          }()) })\n        .catch({ __error in __promiseHolder.reject(__error.toCpp()) })\n      return __promise\n    }()\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload {\n    return Unmanaged<Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void.swift",
    "content": "///\n/// Func_void.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `() -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: () -> Void\n\n  public init(_ closure: @escaping () -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call() -> Void {\n    self.closure()\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void {\n    return Unmanaged<Func_void>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_BandwidthData.swift",
    "content": "///\n/// Func_void_BandwidthData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ data: BandwidthData) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_BandwidthData {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ data: BandwidthData) -> Void\n\n  public init(_ closure: @escaping (_ data: BandwidthData) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(data: BandwidthData) -> Void {\n    self.closure(data)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_BandwidthData`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_BandwidthData>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_BandwidthData {\n    return Unmanaged<Func_void_BandwidthData>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift",
    "content": "///\n/// Func_void_TimedMetadata.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ data: TimedMetadata) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_TimedMetadata {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ data: TimedMetadata) -> Void\n\n  public init(_ closure: @escaping (_ data: TimedMetadata) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(data: TimedMetadata) -> Void {\n    self.closure(data)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_TimedMetadata`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_TimedMetadata>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_TimedMetadata {\n    return Unmanaged<Func_void_TimedMetadata>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_VideoInformation.swift",
    "content": "///\n/// Func_void_VideoInformation.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ value: VideoInformation) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_VideoInformation {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ value: VideoInformation) -> Void\n\n  public init(_ closure: @escaping (_ value: VideoInformation) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(value: VideoInformation) -> Void {\n    self.closure(value)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_VideoInformation`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_VideoInformation>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_VideoInformation {\n    return Unmanaged<Func_void_VideoInformation>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_VideoPlayerStatus.swift",
    "content": "///\n/// Func_void_VideoPlayerStatus.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ status: VideoPlayerStatus) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_VideoPlayerStatus {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ status: VideoPlayerStatus) -> Void\n\n  public init(_ closure: @escaping (_ status: VideoPlayerStatus) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(status: Int32) -> Void {\n    self.closure(margelo.nitro.video.VideoPlayerStatus(rawValue: status)!)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_VideoPlayerStatus`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_VideoPlayerStatus>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_VideoPlayerStatus {\n    return Unmanaged<Func_void_VideoPlayerStatus>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_bool.swift",
    "content": "///\n/// Func_void_bool.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ isInPictureInPicture: Bool) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_bool {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ isInPictureInPicture: Bool) -> Void\n\n  public init(_ closure: @escaping (_ isInPictureInPicture: Bool) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(isInPictureInPicture: Bool) -> Void {\n    self.closure(isInPictureInPicture)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_bool`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_bool>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_bool {\n    return Unmanaged<Func_void_bool>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_double.swift",
    "content": "///\n/// Func_void_double.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ rate: Double) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_double {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ rate: Double) -> Void\n\n  public init(_ closure: @escaping (_ rate: Double) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(rate: Double) -> Void {\n    self.closure(rate)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_double`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_double>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_double {\n    return Unmanaged<Func_void_double>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_onLoadData.swift",
    "content": "///\n/// Func_void_onLoadData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ data: onLoadData) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_onLoadData {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ data: onLoadData) -> Void\n\n  public init(_ closure: @escaping (_ data: onLoadData) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(data: onLoadData) -> Void {\n    self.closure(data)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_onLoadData`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_onLoadData>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onLoadData {\n    return Unmanaged<Func_void_onLoadData>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_onLoadStartData.swift",
    "content": "///\n/// Func_void_onLoadStartData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ data: onLoadStartData) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_onLoadStartData {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ data: onLoadStartData) -> Void\n\n  public init(_ closure: @escaping (_ data: onLoadStartData) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(data: onLoadStartData) -> Void {\n    self.closure(data)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_onLoadStartData`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_onLoadStartData>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onLoadStartData {\n    return Unmanaged<Func_void_onLoadStartData>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_onPlaybackStateChangeData.swift",
    "content": "///\n/// Func_void_onPlaybackStateChangeData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ data: onPlaybackStateChangeData) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_onPlaybackStateChangeData {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ data: onPlaybackStateChangeData) -> Void\n\n  public init(_ closure: @escaping (_ data: onPlaybackStateChangeData) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(data: onPlaybackStateChangeData) -> Void {\n    self.closure(data)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_onPlaybackStateChangeData`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_onPlaybackStateChangeData>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onPlaybackStateChangeData {\n    return Unmanaged<Func_void_onPlaybackStateChangeData>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_onProgressData.swift",
    "content": "///\n/// Func_void_onProgressData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ data: onProgressData) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_onProgressData {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ data: onProgressData) -> Void\n\n  public init(_ closure: @escaping (_ data: onProgressData) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(data: onProgressData) -> Void {\n    self.closure(data)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_onProgressData`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_onProgressData>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onProgressData {\n    return Unmanaged<Func_void_onProgressData>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_onVolumeChangeData.swift",
    "content": "///\n/// Func_void_onVolumeChangeData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ data: onVolumeChangeData) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_onVolumeChangeData {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ data: onVolumeChangeData) -> Void\n\n  public init(_ closure: @escaping (_ data: onVolumeChangeData) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(data: onVolumeChangeData) -> Void {\n    self.closure(data)\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_onVolumeChangeData`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_onVolumeChangeData>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_onVolumeChangeData {\n    return Unmanaged<Func_void_onVolumeChangeData>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift",
    "content": "///\n/// Func_void_std__exception_ptr.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ error: Error) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_std__exception_ptr {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ error: Error) -> Void\n\n  public init(_ closure: @escaping (_ error: Error) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(error: std.exception_ptr) -> Void {\n    self.closure(RuntimeError.from(cppError: error))\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_std__exception_ptr`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_std__exception_ptr>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__exception_ptr {\n    return Unmanaged<Func_void_std__exception_ptr>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__TextTrack__.swift",
    "content": "///\n/// Func_void_std__optional_std__variant_nitro__NullType__TextTrack__.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ track: Variant_NullType_TextTrack?) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ track: Variant_NullType_TextTrack?) -> Void\n\n  public init(_ closure: @escaping (_ track: Variant_NullType_TextTrack?) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(track: bridge.std__optional_std__variant_nitro__NullType__TextTrack__) -> Void {\n    self.closure({ () -> Variant_NullType_TextTrack? in\n      if bridge.has_value_std__optional_std__variant_nitro__NullType__TextTrack__(track) {\n        let __unwrapped = bridge.get_std__optional_std__variant_nitro__NullType__TextTrack__(track)\n        return { () -> Variant_NullType_TextTrack in\n          let __variant = bridge.std__variant_nitro__NullType__TextTrack_(__unwrapped)\n          switch __variant.index() {\n            case 0:\n              let __actual = __variant.get_0()\n              return .first(NullType.null)\n            case 1:\n              let __actual = __variant.get_1()\n              return .second(__actual)\n            default:\n              fatalError(\"Variant can never have index \\(__variant.index())!\")\n          }\n        }()\n      } else {\n        return nil\n      }\n    }())\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_std__optional_std__variant_nitro__NullType__TextTrack__`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_std__optional_std__variant_nitro__NullType__TextTrack__>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__optional_std__variant_nitro__NullType__TextTrack__ {\n    return Unmanaged<Func_void_std__optional_std__variant_nitro__NullType__TextTrack__>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__string__.swift",
    "content": "///\n/// Func_void_std__shared_ptr_Promise_std__string__.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ value: Promise<String>) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_std__shared_ptr_Promise_std__string__ {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ value: Promise<String>) -> Void\n\n  public init(_ closure: @escaping (_ value: Promise<String>) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(value: bridge.std__shared_ptr_Promise_std__string__) -> Void {\n    self.closure({ () -> Promise<String> in\n      let __promise = Promise<String>()\n      let __resolver = { (__result: String) in\n        __promise.resolve(withResult: __result)\n      }\n      let __rejecter = { (__error: Error) in\n        __promise.reject(withError: __error)\n      }\n      let __resolverCpp = { () -> bridge.Func_void_std__string in\n        let __closureWrapper = Func_void_std__string(__resolver)\n        return bridge.create_Func_void_std__string(__closureWrapper.toUnsafe())\n      }()\n      let __rejecterCpp = { () -> bridge.Func_void_std__exception_ptr in\n        let __closureWrapper = Func_void_std__exception_ptr(__rejecter)\n        return bridge.create_Func_void_std__exception_ptr(__closureWrapper.toUnsafe())\n      }()\n      let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__string__(value)\n      __promiseHolder.addOnResolvedListener(__resolverCpp)\n      __promiseHolder.addOnRejectedListener(__rejecterCpp)\n      return __promise\n    }())\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_std__shared_ptr_Promise_std__string__`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_std__shared_ptr_Promise_std__string__>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__shared_ptr_Promise_std__string__ {\n    return Unmanaged<Func_void_std__shared_ptr_Promise_std__string__>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_std__string.swift",
    "content": "///\n/// Func_void_std__string.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ value: String) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_std__string {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ value: String) -> Void\n\n  public init(_ closure: @escaping (_ value: String) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(value: std.string) -> Void {\n    self.closure(String(value))\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_std__string`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_std__string>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__string {\n    return Unmanaged<Func_void_std__string>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift",
    "content": "///\n/// Func_void_std__vector_std__string_.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Wraps a Swift `(_ data: [String]) -> Void` as a class.\n * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.\n */\npublic final class Func_void_std__vector_std__string_ {\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  private let closure: (_ data: [String]) -> Void\n\n  public init(_ closure: @escaping (_ data: [String]) -> Void) {\n    self.closure = closure\n  }\n\n  @inline(__always)\n  public func call(data: bridge.std__vector_std__string_) -> Void {\n    self.closure(data.map({ __item in String(__item) }))\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  @inline(__always)\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `Func_void_std__vector_std__string_`.\n   * The pointer has to be a retained opaque `Unmanaged<Func_void_std__vector_std__string_>`.\n   * This removes one strong reference from the object!\n   */\n  @inline(__always)\n  public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__vector_std__string_ {\n    return Unmanaged<Func_void_std__vector_std__string_>.fromOpaque(pointer).takeRetainedValue()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerEventEmitterSpec.swift",
    "content": "///\n/// HybridVideoPlayerEventEmitterSpec.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/// See ``HybridVideoPlayerEventEmitterSpec``\npublic protocol HybridVideoPlayerEventEmitterSpec_protocol: HybridObject {\n  // Properties\n  \n\n  // Methods\n  func addOnAudioBecomingNoisyListener(listener: @escaping () -> Void) throws -> ListenerSubscription\n  func addOnAudioFocusChangeListener(listener: @escaping (_ hasAudioFocus: Bool) -> Void) throws -> ListenerSubscription\n  func addOnBandwidthUpdateListener(listener: @escaping (_ data: BandwidthData) -> Void) throws -> ListenerSubscription\n  func addOnBufferListener(listener: @escaping (_ buffering: Bool) -> Void) throws -> ListenerSubscription\n  func addOnControlsVisibleChangeListener(listener: @escaping (_ visible: Bool) -> Void) throws -> ListenerSubscription\n  func addOnEndListener(listener: @escaping () -> Void) throws -> ListenerSubscription\n  func addOnExternalPlaybackChangeListener(listener: @escaping (_ externalPlaybackActive: Bool) -> Void) throws -> ListenerSubscription\n  func addOnLoadListener(listener: @escaping (_ data: onLoadData) -> Void) throws -> ListenerSubscription\n  func addOnLoadStartListener(listener: @escaping (_ data: onLoadStartData) -> Void) throws -> ListenerSubscription\n  func addOnPlaybackStateChangeListener(listener: @escaping (_ data: onPlaybackStateChangeData) -> Void) throws -> ListenerSubscription\n  func addOnPlaybackRateChangeListener(listener: @escaping (_ rate: Double) -> Void) throws -> ListenerSubscription\n  func addOnProgressListener(listener: @escaping (_ data: onProgressData) -> Void) throws -> ListenerSubscription\n  func addOnReadyToDisplayListener(listener: @escaping () -> Void) throws -> ListenerSubscription\n  func addOnSeekListener(listener: @escaping (_ position: Double) -> Void) throws -> ListenerSubscription\n  func addOnStatusChangeListener(listener: @escaping (_ status: VideoPlayerStatus) -> Void) throws -> ListenerSubscription\n  func addOnTimedMetadataListener(listener: @escaping (_ data: TimedMetadata) -> Void) throws -> ListenerSubscription\n  func addOnTextTrackDataChangedListener(listener: @escaping (_ data: [String]) -> Void) throws -> ListenerSubscription\n  func addOnTrackChangeListener(listener: @escaping (_ track: Variant_NullType_TextTrack?) -> Void) throws -> ListenerSubscription\n  func addOnVolumeChangeListener(listener: @escaping (_ data: onVolumeChangeData) -> Void) throws -> ListenerSubscription\n  func clearAllListeners() throws -> Void\n}\n\npublic extension HybridVideoPlayerEventEmitterSpec_protocol {\n  /// Default implementation of ``HybridObject.toString``\n  func toString() -> String {\n    return \"[HybridObject VideoPlayerEventEmitter]\"\n  }\n}\n\n/// See ``HybridVideoPlayerEventEmitterSpec``\nopen class HybridVideoPlayerEventEmitterSpec_base {\n  private weak var cxxWrapper: HybridVideoPlayerEventEmitterSpec_cxx? = nil\n  public init() { }\n  public func getCxxWrapper() -> HybridVideoPlayerEventEmitterSpec_cxx {\n  #if DEBUG\n    guard self is any HybridVideoPlayerEventEmitterSpec else {\n      fatalError(\"`self` is not a `HybridVideoPlayerEventEmitterSpec`! Did you accidentally inherit from `HybridVideoPlayerEventEmitterSpec_base` instead of `HybridVideoPlayerEventEmitterSpec`?\")\n    }\n  #endif\n    if let cxxWrapper = self.cxxWrapper {\n      return cxxWrapper\n    } else {\n      let cxxWrapper = HybridVideoPlayerEventEmitterSpec_cxx(self as! any HybridVideoPlayerEventEmitterSpec)\n      self.cxxWrapper = cxxWrapper\n      return cxxWrapper\n    }\n  }\n}\n\n/**\n * A Swift base-protocol representing the VideoPlayerEventEmitter HybridObject.\n * Implement this protocol to create Swift-based instances of VideoPlayerEventEmitter.\n * ```swift\n * class HybridVideoPlayerEventEmitter : HybridVideoPlayerEventEmitterSpec {\n *   // ...\n * }\n * ```\n */\npublic typealias HybridVideoPlayerEventEmitterSpec = HybridVideoPlayerEventEmitterSpec_protocol & HybridVideoPlayerEventEmitterSpec_base\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerEventEmitterSpec_cxx.swift",
    "content": "///\n/// HybridVideoPlayerEventEmitterSpec_cxx.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * A class implementation that bridges HybridVideoPlayerEventEmitterSpec over to C++.\n * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.\n *\n * Also, some Swift types need to be bridged with special handling:\n * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)\n * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper\n * - Throwing methods need to be wrapped with a Result<T, Error> type, as exceptions cannot be propagated to C++\n */\nopen class HybridVideoPlayerEventEmitterSpec_cxx {\n  /**\n   * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`)\n   * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`.\n   * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.\n   */\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Holds an instance of the `HybridVideoPlayerEventEmitterSpec` Swift protocol.\n   */\n  private var __implementation: any HybridVideoPlayerEventEmitterSpec\n\n  /**\n   * Holds a weak pointer to the C++ class that wraps the Swift class.\n   */\n  private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerEventEmitterSpec_\n\n  /**\n   * Create a new `HybridVideoPlayerEventEmitterSpec_cxx` that wraps the given `HybridVideoPlayerEventEmitterSpec`.\n   * All properties and methods bridge to C++ types.\n   */\n  public init(_ implementation: any HybridVideoPlayerEventEmitterSpec) {\n    self.__implementation = implementation\n    self.__cxxPart = .init()\n    /* no base class */\n  }\n\n  /**\n   * Get the actual `HybridVideoPlayerEventEmitterSpec` instance this class wraps.\n   */\n  @inline(__always)\n  public func getHybridVideoPlayerEventEmitterSpec() -> any HybridVideoPlayerEventEmitterSpec {\n    return __implementation\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `HybridVideoPlayerEventEmitterSpec_cxx`.\n   * The pointer has to be a retained opaque `Unmanaged<HybridVideoPlayerEventEmitterSpec_cxx>`.\n   * This removes one strong reference from the object!\n   */\n  public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerEventEmitterSpec_cxx {\n    return Unmanaged<HybridVideoPlayerEventEmitterSpec_cxx>.fromOpaque(pointer).takeRetainedValue()\n  }\n\n  /**\n   * Gets (or creates) the C++ part of this Hybrid Object.\n   * The C++ part is a `std::shared_ptr<HybridVideoPlayerEventEmitterSpec>`.\n   */\n  public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ {\n    let cachedCxxPart = self.__cxxPart.lock()\n    if Bool(fromCxx: cachedCxxPart) {\n      return cachedCxxPart\n    } else {\n      let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(self.toUnsafe())\n      __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerEventEmitterSpec_(newCxxPart)\n      return newCxxPart\n    }\n  }\n\n  \n\n  /**\n   * Get the memory size of the Swift class (plus size of any other allocations)\n   * so the JS VM can properly track it and garbage-collect the JS object if needed.\n   */\n  @inline(__always)\n  public var memorySize: Int {\n    return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize\n  }\n\n  /**\n   * Compares this object with the given [other] object for reference equality.\n   */\n  @inline(__always)\n  public func equals(other: HybridVideoPlayerEventEmitterSpec_cxx) -> Bool {\n    return self.__implementation === other.__implementation\n  }\n\n  /**\n   * Call dispose() on the Swift class.\n   * This _may_ be called manually from JS.\n   */\n  @inline(__always)\n  public func dispose() {\n    self.__implementation.dispose()\n  }\n\n  /**\n   * Call toString() on the Swift class.\n   */\n  @inline(__always)\n  public func toString() -> String {\n    return self.__implementation.toString()\n  }\n\n  // Properties\n  \n\n  // Methods\n  @inline(__always)\n  public final func addOnAudioBecomingNoisyListener(listener: bridge.Func_void) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnAudioBecomingNoisyListener(listener: { () -> () -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void(listener)\n        return { () -> Void in\n          __wrappedFunction.call()\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnAudioFocusChangeListener(listener: bridge.Func_void_bool) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnAudioFocusChangeListener(listener: { () -> (Bool) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_bool(listener)\n        return { (__hasAudioFocus: Bool) -> Void in\n          __wrappedFunction.call(__hasAudioFocus)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnBandwidthUpdateListener(listener: bridge.Func_void_BandwidthData) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnBandwidthUpdateListener(listener: { () -> (BandwidthData) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_BandwidthData(listener)\n        return { (__data: BandwidthData) -> Void in\n          __wrappedFunction.call(__data)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnBufferListener(listener: bridge.Func_void_bool) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnBufferListener(listener: { () -> (Bool) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_bool(listener)\n        return { (__buffering: Bool) -> Void in\n          __wrappedFunction.call(__buffering)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnControlsVisibleChangeListener(listener: bridge.Func_void_bool) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnControlsVisibleChangeListener(listener: { () -> (Bool) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_bool(listener)\n        return { (__visible: Bool) -> Void in\n          __wrappedFunction.call(__visible)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnEndListener(listener: bridge.Func_void) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnEndListener(listener: { () -> () -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void(listener)\n        return { () -> Void in\n          __wrappedFunction.call()\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnExternalPlaybackChangeListener(listener: bridge.Func_void_bool) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnExternalPlaybackChangeListener(listener: { () -> (Bool) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_bool(listener)\n        return { (__externalPlaybackActive: Bool) -> Void in\n          __wrappedFunction.call(__externalPlaybackActive)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnLoadListener(listener: bridge.Func_void_onLoadData) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnLoadListener(listener: { () -> (onLoadData) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_onLoadData(listener)\n        return { (__data: onLoadData) -> Void in\n          __wrappedFunction.call(__data)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnLoadStartListener(listener: bridge.Func_void_onLoadStartData) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnLoadStartListener(listener: { () -> (onLoadStartData) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_onLoadStartData(listener)\n        return { (__data: onLoadStartData) -> Void in\n          __wrappedFunction.call(__data)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnPlaybackStateChangeListener(listener: bridge.Func_void_onPlaybackStateChangeData) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnPlaybackStateChangeListener(listener: { () -> (onPlaybackStateChangeData) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_onPlaybackStateChangeData(listener)\n        return { (__data: onPlaybackStateChangeData) -> Void in\n          __wrappedFunction.call(__data)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnPlaybackRateChangeListener(listener: bridge.Func_void_double) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnPlaybackRateChangeListener(listener: { () -> (Double) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_double(listener)\n        return { (__rate: Double) -> Void in\n          __wrappedFunction.call(__rate)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnProgressListener(listener: bridge.Func_void_onProgressData) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnProgressListener(listener: { () -> (onProgressData) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_onProgressData(listener)\n        return { (__data: onProgressData) -> Void in\n          __wrappedFunction.call(__data)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnReadyToDisplayListener(listener: bridge.Func_void) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnReadyToDisplayListener(listener: { () -> () -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void(listener)\n        return { () -> Void in\n          __wrappedFunction.call()\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnSeekListener(listener: bridge.Func_void_double) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnSeekListener(listener: { () -> (Double) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_double(listener)\n        return { (__position: Double) -> Void in\n          __wrappedFunction.call(__position)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnStatusChangeListener(listener: bridge.Func_void_VideoPlayerStatus) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnStatusChangeListener(listener: { () -> (VideoPlayerStatus) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_VideoPlayerStatus(listener)\n        return { (__status: VideoPlayerStatus) -> Void in\n          __wrappedFunction.call(__status.rawValue)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnTimedMetadataListener(listener: bridge.Func_void_TimedMetadata) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnTimedMetadataListener(listener: { () -> (TimedMetadata) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_TimedMetadata(listener)\n        return { (__data: TimedMetadata) -> Void in\n          __wrappedFunction.call(__data)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnTextTrackDataChangedListener(listener: bridge.Func_void_std__vector_std__string_) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnTextTrackDataChangedListener(listener: { () -> ([String]) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_std__vector_std__string_(listener)\n        return { (__data: [String]) -> Void in\n          __wrappedFunction.call({ () -> bridge.std__vector_std__string_ in\n            var __vector = bridge.create_std__vector_std__string_(__data.count)\n            for __item in __data {\n              __vector.push_back(std.string(__item))\n            }\n            return __vector\n          }())\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnTrackChangeListener(listener: bridge.Func_void_std__optional_std__variant_nitro__NullType__TextTrack__) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnTrackChangeListener(listener: { () -> (Variant_NullType_TextTrack?) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_std__optional_std__variant_nitro__NullType__TextTrack__(listener)\n        return { (__track: Variant_NullType_TextTrack?) -> Void in\n          __wrappedFunction.call({ () -> bridge.std__optional_std__variant_nitro__NullType__TextTrack__ in\n            if let __unwrappedValue = __track {\n              return bridge.create_std__optional_std__variant_nitro__NullType__TextTrack__({ () -> bridge.std__variant_nitro__NullType__TextTrack_ in\n                switch __unwrappedValue {\n                  case .first(let __value):\n                    return bridge.create_std__variant_nitro__NullType__TextTrack_(margelo.nitro.NullType.null)\n                  case .second(let __value):\n                    return bridge.create_std__variant_nitro__NullType__TextTrack_(__value)\n                }\n              }().variant)\n            } else {\n              return .init()\n            }\n          }())\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnVolumeChangeListener(listener: bridge.Func_void_onVolumeChangeData) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnVolumeChangeListener(listener: { () -> (onVolumeChangeData) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_onVolumeChangeData(listener)\n        return { (__data: onVolumeChangeData) -> Void in\n          __wrappedFunction.call(__data)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func clearAllListeners() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.clearAllListeners()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerFactorySpec.swift",
    "content": "///\n/// HybridVideoPlayerFactorySpec.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/// See ``HybridVideoPlayerFactorySpec``\npublic protocol HybridVideoPlayerFactorySpec_protocol: HybridObject {\n  // Properties\n  \n\n  // Methods\n  func createPlayer(source: (any HybridVideoPlayerSourceSpec)) throws -> (any HybridVideoPlayerSpec)\n}\n\npublic extension HybridVideoPlayerFactorySpec_protocol {\n  /// Default implementation of ``HybridObject.toString``\n  func toString() -> String {\n    return \"[HybridObject VideoPlayerFactory]\"\n  }\n}\n\n/// See ``HybridVideoPlayerFactorySpec``\nopen class HybridVideoPlayerFactorySpec_base {\n  private weak var cxxWrapper: HybridVideoPlayerFactorySpec_cxx? = nil\n  public init() { }\n  public func getCxxWrapper() -> HybridVideoPlayerFactorySpec_cxx {\n  #if DEBUG\n    guard self is any HybridVideoPlayerFactorySpec else {\n      fatalError(\"`self` is not a `HybridVideoPlayerFactorySpec`! Did you accidentally inherit from `HybridVideoPlayerFactorySpec_base` instead of `HybridVideoPlayerFactorySpec`?\")\n    }\n  #endif\n    if let cxxWrapper = self.cxxWrapper {\n      return cxxWrapper\n    } else {\n      let cxxWrapper = HybridVideoPlayerFactorySpec_cxx(self as! any HybridVideoPlayerFactorySpec)\n      self.cxxWrapper = cxxWrapper\n      return cxxWrapper\n    }\n  }\n}\n\n/**\n * A Swift base-protocol representing the VideoPlayerFactory HybridObject.\n * Implement this protocol to create Swift-based instances of VideoPlayerFactory.\n * ```swift\n * class HybridVideoPlayerFactory : HybridVideoPlayerFactorySpec {\n *   // ...\n * }\n * ```\n */\npublic typealias HybridVideoPlayerFactorySpec = HybridVideoPlayerFactorySpec_protocol & HybridVideoPlayerFactorySpec_base\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerFactorySpec_cxx.swift",
    "content": "///\n/// HybridVideoPlayerFactorySpec_cxx.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * A class implementation that bridges HybridVideoPlayerFactorySpec over to C++.\n * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.\n *\n * Also, some Swift types need to be bridged with special handling:\n * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)\n * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper\n * - Throwing methods need to be wrapped with a Result<T, Error> type, as exceptions cannot be propagated to C++\n */\nopen class HybridVideoPlayerFactorySpec_cxx {\n  /**\n   * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`)\n   * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`.\n   * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.\n   */\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Holds an instance of the `HybridVideoPlayerFactorySpec` Swift protocol.\n   */\n  private var __implementation: any HybridVideoPlayerFactorySpec\n\n  /**\n   * Holds a weak pointer to the C++ class that wraps the Swift class.\n   */\n  private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerFactorySpec_\n\n  /**\n   * Create a new `HybridVideoPlayerFactorySpec_cxx` that wraps the given `HybridVideoPlayerFactorySpec`.\n   * All properties and methods bridge to C++ types.\n   */\n  public init(_ implementation: any HybridVideoPlayerFactorySpec) {\n    self.__implementation = implementation\n    self.__cxxPart = .init()\n    /* no base class */\n  }\n\n  /**\n   * Get the actual `HybridVideoPlayerFactorySpec` instance this class wraps.\n   */\n  @inline(__always)\n  public func getHybridVideoPlayerFactorySpec() -> any HybridVideoPlayerFactorySpec {\n    return __implementation\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `HybridVideoPlayerFactorySpec_cxx`.\n   * The pointer has to be a retained opaque `Unmanaged<HybridVideoPlayerFactorySpec_cxx>`.\n   * This removes one strong reference from the object!\n   */\n  public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerFactorySpec_cxx {\n    return Unmanaged<HybridVideoPlayerFactorySpec_cxx>.fromOpaque(pointer).takeRetainedValue()\n  }\n\n  /**\n   * Gets (or creates) the C++ part of this Hybrid Object.\n   * The C++ part is a `std::shared_ptr<HybridVideoPlayerFactorySpec>`.\n   */\n  public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerFactorySpec_ {\n    let cachedCxxPart = self.__cxxPart.lock()\n    if Bool(fromCxx: cachedCxxPart) {\n      return cachedCxxPart\n    } else {\n      let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerFactorySpec_(self.toUnsafe())\n      __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerFactorySpec_(newCxxPart)\n      return newCxxPart\n    }\n  }\n\n  \n\n  /**\n   * Get the memory size of the Swift class (plus size of any other allocations)\n   * so the JS VM can properly track it and garbage-collect the JS object if needed.\n   */\n  @inline(__always)\n  public var memorySize: Int {\n    return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize\n  }\n\n  /**\n   * Compares this object with the given [other] object for reference equality.\n   */\n  @inline(__always)\n  public func equals(other: HybridVideoPlayerFactorySpec_cxx) -> Bool {\n    return self.__implementation === other.__implementation\n  }\n\n  /**\n   * Call dispose() on the Swift class.\n   * This _may_ be called manually from JS.\n   */\n  @inline(__always)\n  public func dispose() {\n    self.__implementation.dispose()\n  }\n\n  /**\n   * Call toString() on the Swift class.\n   */\n  @inline(__always)\n  public func toString() -> String {\n    return self.__implementation.toString()\n  }\n\n  // Properties\n  \n\n  // Methods\n  @inline(__always)\n  public final func createPlayer(source: bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_) -> bridge.Result_std__shared_ptr_HybridVideoPlayerSpec__ {\n    do {\n      let __result = try self.__implementation.createPlayer(source: { () -> any HybridVideoPlayerSourceSpec in\n        let __unsafePointer = bridge.get_std__shared_ptr_HybridVideoPlayerSourceSpec_(source)\n        let __instance = HybridVideoPlayerSourceSpec_cxx.fromUnsafe(__unsafePointer)\n        return __instance.getHybridVideoPlayerSourceSpec()\n      }())\n      let __resultCpp = { () -> bridge.std__shared_ptr_HybridVideoPlayerSpec_ in\n        let __cxxWrapped = __result.getCxxWrapper()\n        return __cxxWrapped.getCxxPart()\n      }()\n      return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSpec__(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSpec__(__exceptionPtr)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerSourceFactorySpec.swift",
    "content": "///\n/// HybridVideoPlayerSourceFactorySpec.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/// See ``HybridVideoPlayerSourceFactorySpec``\npublic protocol HybridVideoPlayerSourceFactorySpec_protocol: HybridObject {\n  // Properties\n  \n\n  // Methods\n  func fromUri(uri: String) throws -> (any HybridVideoPlayerSourceSpec)\n  func fromVideoConfig(config: NativeVideoConfig) throws -> (any HybridVideoPlayerSourceSpec)\n}\n\npublic extension HybridVideoPlayerSourceFactorySpec_protocol {\n  /// Default implementation of ``HybridObject.toString``\n  func toString() -> String {\n    return \"[HybridObject VideoPlayerSourceFactory]\"\n  }\n}\n\n/// See ``HybridVideoPlayerSourceFactorySpec``\nopen class HybridVideoPlayerSourceFactorySpec_base {\n  private weak var cxxWrapper: HybridVideoPlayerSourceFactorySpec_cxx? = nil\n  public init() { }\n  public func getCxxWrapper() -> HybridVideoPlayerSourceFactorySpec_cxx {\n  #if DEBUG\n    guard self is any HybridVideoPlayerSourceFactorySpec else {\n      fatalError(\"`self` is not a `HybridVideoPlayerSourceFactorySpec`! Did you accidentally inherit from `HybridVideoPlayerSourceFactorySpec_base` instead of `HybridVideoPlayerSourceFactorySpec`?\")\n    }\n  #endif\n    if let cxxWrapper = self.cxxWrapper {\n      return cxxWrapper\n    } else {\n      let cxxWrapper = HybridVideoPlayerSourceFactorySpec_cxx(self as! any HybridVideoPlayerSourceFactorySpec)\n      self.cxxWrapper = cxxWrapper\n      return cxxWrapper\n    }\n  }\n}\n\n/**\n * A Swift base-protocol representing the VideoPlayerSourceFactory HybridObject.\n * Implement this protocol to create Swift-based instances of VideoPlayerSourceFactory.\n * ```swift\n * class HybridVideoPlayerSourceFactory : HybridVideoPlayerSourceFactorySpec {\n *   // ...\n * }\n * ```\n */\npublic typealias HybridVideoPlayerSourceFactorySpec = HybridVideoPlayerSourceFactorySpec_protocol & HybridVideoPlayerSourceFactorySpec_base\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerSourceFactorySpec_cxx.swift",
    "content": "///\n/// HybridVideoPlayerSourceFactorySpec_cxx.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * A class implementation that bridges HybridVideoPlayerSourceFactorySpec over to C++.\n * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.\n *\n * Also, some Swift types need to be bridged with special handling:\n * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)\n * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper\n * - Throwing methods need to be wrapped with a Result<T, Error> type, as exceptions cannot be propagated to C++\n */\nopen class HybridVideoPlayerSourceFactorySpec_cxx {\n  /**\n   * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`)\n   * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`.\n   * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.\n   */\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Holds an instance of the `HybridVideoPlayerSourceFactorySpec` Swift protocol.\n   */\n  private var __implementation: any HybridVideoPlayerSourceFactorySpec\n\n  /**\n   * Holds a weak pointer to the C++ class that wraps the Swift class.\n   */\n  private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerSourceFactorySpec_\n\n  /**\n   * Create a new `HybridVideoPlayerSourceFactorySpec_cxx` that wraps the given `HybridVideoPlayerSourceFactorySpec`.\n   * All properties and methods bridge to C++ types.\n   */\n  public init(_ implementation: any HybridVideoPlayerSourceFactorySpec) {\n    self.__implementation = implementation\n    self.__cxxPart = .init()\n    /* no base class */\n  }\n\n  /**\n   * Get the actual `HybridVideoPlayerSourceFactorySpec` instance this class wraps.\n   */\n  @inline(__always)\n  public func getHybridVideoPlayerSourceFactorySpec() -> any HybridVideoPlayerSourceFactorySpec {\n    return __implementation\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `HybridVideoPlayerSourceFactorySpec_cxx`.\n   * The pointer has to be a retained opaque `Unmanaged<HybridVideoPlayerSourceFactorySpec_cxx>`.\n   * This removes one strong reference from the object!\n   */\n  public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerSourceFactorySpec_cxx {\n    return Unmanaged<HybridVideoPlayerSourceFactorySpec_cxx>.fromOpaque(pointer).takeRetainedValue()\n  }\n\n  /**\n   * Gets (or creates) the C++ part of this Hybrid Object.\n   * The C++ part is a `std::shared_ptr<HybridVideoPlayerSourceFactorySpec>`.\n   */\n  public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerSourceFactorySpec_ {\n    let cachedCxxPart = self.__cxxPart.lock()\n    if Bool(fromCxx: cachedCxxPart) {\n      return cachedCxxPart\n    } else {\n      let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(self.toUnsafe())\n      __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerSourceFactorySpec_(newCxxPart)\n      return newCxxPart\n    }\n  }\n\n  \n\n  /**\n   * Get the memory size of the Swift class (plus size of any other allocations)\n   * so the JS VM can properly track it and garbage-collect the JS object if needed.\n   */\n  @inline(__always)\n  public var memorySize: Int {\n    return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize\n  }\n\n  /**\n   * Compares this object with the given [other] object for reference equality.\n   */\n  @inline(__always)\n  public func equals(other: HybridVideoPlayerSourceFactorySpec_cxx) -> Bool {\n    return self.__implementation === other.__implementation\n  }\n\n  /**\n   * Call dispose() on the Swift class.\n   * This _may_ be called manually from JS.\n   */\n  @inline(__always)\n  public func dispose() {\n    self.__implementation.dispose()\n  }\n\n  /**\n   * Call toString() on the Swift class.\n   */\n  @inline(__always)\n  public func toString() -> String {\n    return self.__implementation.toString()\n  }\n\n  // Properties\n  \n\n  // Methods\n  @inline(__always)\n  public final func fromUri(uri: std.string) -> bridge.Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ {\n    do {\n      let __result = try self.__implementation.fromUri(uri: String(uri))\n      let __resultCpp = { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in\n        let __cxxWrapped = __result.getCxxWrapper()\n        return __cxxWrapped.getCxxPart()\n      }()\n      return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func fromVideoConfig(config: NativeVideoConfig) -> bridge.Result_std__shared_ptr_HybridVideoPlayerSourceSpec__ {\n    do {\n      let __result = try self.__implementation.fromVideoConfig(config: config)\n      let __resultCpp = { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in\n        let __cxxWrapped = __result.getCxxWrapper()\n        return __cxxWrapped.getCxxPart()\n      }()\n      return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__shared_ptr_HybridVideoPlayerSourceSpec__(__exceptionPtr)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerSourceSpec.swift",
    "content": "///\n/// HybridVideoPlayerSourceSpec.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/// See ``HybridVideoPlayerSourceSpec``\npublic protocol HybridVideoPlayerSourceSpec_protocol: HybridObject {\n  // Properties\n  var uri: String { get }\n  var config: NativeVideoConfig { get }\n\n  // Methods\n  func getAssetInformationAsync() throws -> Promise<VideoInformation>\n}\n\npublic extension HybridVideoPlayerSourceSpec_protocol {\n  /// Default implementation of ``HybridObject.toString``\n  func toString() -> String {\n    return \"[HybridObject VideoPlayerSource]\"\n  }\n}\n\n/// See ``HybridVideoPlayerSourceSpec``\nopen class HybridVideoPlayerSourceSpec_base {\n  private weak var cxxWrapper: HybridVideoPlayerSourceSpec_cxx? = nil\n  public init() { }\n  public func getCxxWrapper() -> HybridVideoPlayerSourceSpec_cxx {\n  #if DEBUG\n    guard self is any HybridVideoPlayerSourceSpec else {\n      fatalError(\"`self` is not a `HybridVideoPlayerSourceSpec`! Did you accidentally inherit from `HybridVideoPlayerSourceSpec_base` instead of `HybridVideoPlayerSourceSpec`?\")\n    }\n  #endif\n    if let cxxWrapper = self.cxxWrapper {\n      return cxxWrapper\n    } else {\n      let cxxWrapper = HybridVideoPlayerSourceSpec_cxx(self as! any HybridVideoPlayerSourceSpec)\n      self.cxxWrapper = cxxWrapper\n      return cxxWrapper\n    }\n  }\n}\n\n/**\n * A Swift base-protocol representing the VideoPlayerSource HybridObject.\n * Implement this protocol to create Swift-based instances of VideoPlayerSource.\n * ```swift\n * class HybridVideoPlayerSource : HybridVideoPlayerSourceSpec {\n *   // ...\n * }\n * ```\n */\npublic typealias HybridVideoPlayerSourceSpec = HybridVideoPlayerSourceSpec_protocol & HybridVideoPlayerSourceSpec_base\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerSourceSpec_cxx.swift",
    "content": "///\n/// HybridVideoPlayerSourceSpec_cxx.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * A class implementation that bridges HybridVideoPlayerSourceSpec over to C++.\n * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.\n *\n * Also, some Swift types need to be bridged with special handling:\n * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)\n * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper\n * - Throwing methods need to be wrapped with a Result<T, Error> type, as exceptions cannot be propagated to C++\n */\nopen class HybridVideoPlayerSourceSpec_cxx {\n  /**\n   * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`)\n   * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`.\n   * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.\n   */\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Holds an instance of the `HybridVideoPlayerSourceSpec` Swift protocol.\n   */\n  private var __implementation: any HybridVideoPlayerSourceSpec\n\n  /**\n   * Holds a weak pointer to the C++ class that wraps the Swift class.\n   */\n  private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerSourceSpec_\n\n  /**\n   * Create a new `HybridVideoPlayerSourceSpec_cxx` that wraps the given `HybridVideoPlayerSourceSpec`.\n   * All properties and methods bridge to C++ types.\n   */\n  public init(_ implementation: any HybridVideoPlayerSourceSpec) {\n    self.__implementation = implementation\n    self.__cxxPart = .init()\n    /* no base class */\n  }\n\n  /**\n   * Get the actual `HybridVideoPlayerSourceSpec` instance this class wraps.\n   */\n  @inline(__always)\n  public func getHybridVideoPlayerSourceSpec() -> any HybridVideoPlayerSourceSpec {\n    return __implementation\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `HybridVideoPlayerSourceSpec_cxx`.\n   * The pointer has to be a retained opaque `Unmanaged<HybridVideoPlayerSourceSpec_cxx>`.\n   * This removes one strong reference from the object!\n   */\n  public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerSourceSpec_cxx {\n    return Unmanaged<HybridVideoPlayerSourceSpec_cxx>.fromOpaque(pointer).takeRetainedValue()\n  }\n\n  /**\n   * Gets (or creates) the C++ part of this Hybrid Object.\n   * The C++ part is a `std::shared_ptr<HybridVideoPlayerSourceSpec>`.\n   */\n  public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ {\n    let cachedCxxPart = self.__cxxPart.lock()\n    if Bool(fromCxx: cachedCxxPart) {\n      return cachedCxxPart\n    } else {\n      let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerSourceSpec_(self.toUnsafe())\n      __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerSourceSpec_(newCxxPart)\n      return newCxxPart\n    }\n  }\n\n  \n\n  /**\n   * Get the memory size of the Swift class (plus size of any other allocations)\n   * so the JS VM can properly track it and garbage-collect the JS object if needed.\n   */\n  @inline(__always)\n  public var memorySize: Int {\n    return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize\n  }\n\n  /**\n   * Compares this object with the given [other] object for reference equality.\n   */\n  @inline(__always)\n  public func equals(other: HybridVideoPlayerSourceSpec_cxx) -> Bool {\n    return self.__implementation === other.__implementation\n  }\n\n  /**\n   * Call dispose() on the Swift class.\n   * This _may_ be called manually from JS.\n   */\n  @inline(__always)\n  public func dispose() {\n    self.__implementation.dispose()\n  }\n\n  /**\n   * Call toString() on the Swift class.\n   */\n  @inline(__always)\n  public func toString() -> String {\n    return self.__implementation.toString()\n  }\n\n  // Properties\n  public final var uri: std.string {\n    @inline(__always)\n    get {\n      return std.string(self.__implementation.uri)\n    }\n  }\n  \n  public final var config: NativeVideoConfig {\n    @inline(__always)\n    get {\n      return self.__implementation.config\n    }\n  }\n\n  // Methods\n  @inline(__always)\n  public final func getAssetInformationAsync() -> bridge.Result_std__shared_ptr_Promise_VideoInformation___ {\n    do {\n      let __result = try self.__implementation.getAssetInformationAsync()\n      let __resultCpp = { () -> bridge.std__shared_ptr_Promise_VideoInformation__ in\n        let __promise = bridge.create_std__shared_ptr_Promise_VideoInformation__()\n        let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_VideoInformation__(__promise)\n        __result\n          .then({ __result in __promiseHolder.resolve(__result) })\n          .catch({ __error in __promiseHolder.reject(__error.toCpp()) })\n        return __promise\n      }()\n      return bridge.create_Result_std__shared_ptr_Promise_VideoInformation___(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__shared_ptr_Promise_VideoInformation___(__exceptionPtr)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerSpec.swift",
    "content": "///\n/// HybridVideoPlayerSpec.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/// See ``HybridVideoPlayerSpec``\npublic protocol HybridVideoPlayerSpec_protocol: HybridObject {\n  // Properties\n  var source: (any HybridVideoPlayerSourceSpec) { get }\n  var eventEmitter: (any HybridVideoPlayerEventEmitterSpec) { get }\n  var showNotificationControls: Bool { get set }\n  var status: VideoPlayerStatus { get }\n  var duration: Double { get }\n  var volume: Double { get set }\n  var currentTime: Double { get set }\n  var muted: Bool { get set }\n  var loop: Bool { get set }\n  var rate: Double { get set }\n  var mixAudioMode: MixAudioMode { get set }\n  var ignoreSilentSwitchMode: IgnoreSilentSwitchMode { get set }\n  var playInBackground: Bool { get set }\n  var playWhenInactive: Bool { get set }\n  var isPlaying: Bool { get }\n  var selectedTrack: TextTrack? { get }\n\n  // Methods\n  func replaceSourceAsync(source: Variant_NullType__any_HybridVideoPlayerSourceSpec_?) throws -> Promise<Void>\n  func getAvailableTextTracks() throws -> [TextTrack]\n  func selectTextTrack(textTrack: Variant_NullType_TextTrack?) throws -> Void\n  func release() throws -> Void\n  func initialize() throws -> Promise<Void>\n  func preload() throws -> Promise<Void>\n  func play() throws -> Void\n  func pause() throws -> Void\n  func seekBy(time: Double) throws -> Void\n  func seekTo(time: Double) throws -> Void\n}\n\npublic extension HybridVideoPlayerSpec_protocol {\n  /// Default implementation of ``HybridObject.toString``\n  func toString() -> String {\n    return \"[HybridObject VideoPlayer]\"\n  }\n}\n\n/// See ``HybridVideoPlayerSpec``\nopen class HybridVideoPlayerSpec_base {\n  private weak var cxxWrapper: HybridVideoPlayerSpec_cxx? = nil\n  public init() { }\n  public func getCxxWrapper() -> HybridVideoPlayerSpec_cxx {\n  #if DEBUG\n    guard self is any HybridVideoPlayerSpec else {\n      fatalError(\"`self` is not a `HybridVideoPlayerSpec`! Did you accidentally inherit from `HybridVideoPlayerSpec_base` instead of `HybridVideoPlayerSpec`?\")\n    }\n  #endif\n    if let cxxWrapper = self.cxxWrapper {\n      return cxxWrapper\n    } else {\n      let cxxWrapper = HybridVideoPlayerSpec_cxx(self as! any HybridVideoPlayerSpec)\n      self.cxxWrapper = cxxWrapper\n      return cxxWrapper\n    }\n  }\n}\n\n/**\n * A Swift base-protocol representing the VideoPlayer HybridObject.\n * Implement this protocol to create Swift-based instances of VideoPlayer.\n * ```swift\n * class HybridVideoPlayer : HybridVideoPlayerSpec {\n *   // ...\n * }\n * ```\n */\npublic typealias HybridVideoPlayerSpec = HybridVideoPlayerSpec_protocol & HybridVideoPlayerSpec_base\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoPlayerSpec_cxx.swift",
    "content": "///\n/// HybridVideoPlayerSpec_cxx.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * A class implementation that bridges HybridVideoPlayerSpec over to C++.\n * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.\n *\n * Also, some Swift types need to be bridged with special handling:\n * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)\n * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper\n * - Throwing methods need to be wrapped with a Result<T, Error> type, as exceptions cannot be propagated to C++\n */\nopen class HybridVideoPlayerSpec_cxx {\n  /**\n   * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`)\n   * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`.\n   * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.\n   */\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Holds an instance of the `HybridVideoPlayerSpec` Swift protocol.\n   */\n  private var __implementation: any HybridVideoPlayerSpec\n\n  /**\n   * Holds a weak pointer to the C++ class that wraps the Swift class.\n   */\n  private var __cxxPart: bridge.std__weak_ptr_HybridVideoPlayerSpec_\n\n  /**\n   * Create a new `HybridVideoPlayerSpec_cxx` that wraps the given `HybridVideoPlayerSpec`.\n   * All properties and methods bridge to C++ types.\n   */\n  public init(_ implementation: any HybridVideoPlayerSpec) {\n    self.__implementation = implementation\n    self.__cxxPart = .init()\n    /* no base class */\n  }\n\n  /**\n   * Get the actual `HybridVideoPlayerSpec` instance this class wraps.\n   */\n  @inline(__always)\n  public func getHybridVideoPlayerSpec() -> any HybridVideoPlayerSpec {\n    return __implementation\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `HybridVideoPlayerSpec_cxx`.\n   * The pointer has to be a retained opaque `Unmanaged<HybridVideoPlayerSpec_cxx>`.\n   * This removes one strong reference from the object!\n   */\n  public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoPlayerSpec_cxx {\n    return Unmanaged<HybridVideoPlayerSpec_cxx>.fromOpaque(pointer).takeRetainedValue()\n  }\n\n  /**\n   * Gets (or creates) the C++ part of this Hybrid Object.\n   * The C++ part is a `std::shared_ptr<HybridVideoPlayerSpec>`.\n   */\n  public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoPlayerSpec_ {\n    let cachedCxxPart = self.__cxxPart.lock()\n    if Bool(fromCxx: cachedCxxPart) {\n      return cachedCxxPart\n    } else {\n      let newCxxPart = bridge.create_std__shared_ptr_HybridVideoPlayerSpec_(self.toUnsafe())\n      __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoPlayerSpec_(newCxxPart)\n      return newCxxPart\n    }\n  }\n\n  \n\n  /**\n   * Get the memory size of the Swift class (plus size of any other allocations)\n   * so the JS VM can properly track it and garbage-collect the JS object if needed.\n   */\n  @inline(__always)\n  public var memorySize: Int {\n    return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize\n  }\n\n  /**\n   * Compares this object with the given [other] object for reference equality.\n   */\n  @inline(__always)\n  public func equals(other: HybridVideoPlayerSpec_cxx) -> Bool {\n    return self.__implementation === other.__implementation\n  }\n\n  /**\n   * Call dispose() on the Swift class.\n   * This _may_ be called manually from JS.\n   */\n  @inline(__always)\n  public func dispose() {\n    self.__implementation.dispose()\n  }\n\n  /**\n   * Call toString() on the Swift class.\n   */\n  @inline(__always)\n  public func toString() -> String {\n    return self.__implementation.toString()\n  }\n\n  // Properties\n  public final var source: bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ {\n    @inline(__always)\n    get {\n      return { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in\n        let __cxxWrapped = self.__implementation.source.getCxxWrapper()\n        return __cxxWrapped.getCxxPart()\n      }()\n    }\n  }\n  \n  public final var eventEmitter: bridge.std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ {\n    @inline(__always)\n    get {\n      return { () -> bridge.std__shared_ptr_HybridVideoPlayerEventEmitterSpec_ in\n        let __cxxWrapped = self.__implementation.eventEmitter.getCxxWrapper()\n        return __cxxWrapped.getCxxPart()\n      }()\n    }\n  }\n  \n  public final var showNotificationControls: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.showNotificationControls\n    }\n    @inline(__always)\n    set {\n      self.__implementation.showNotificationControls = newValue\n    }\n  }\n  \n  public final var status: Int32 {\n    @inline(__always)\n    get {\n      return self.__implementation.status.rawValue\n    }\n  }\n  \n  public final var duration: Double {\n    @inline(__always)\n    get {\n      return self.__implementation.duration\n    }\n  }\n  \n  public final var volume: Double {\n    @inline(__always)\n    get {\n      return self.__implementation.volume\n    }\n    @inline(__always)\n    set {\n      self.__implementation.volume = newValue\n    }\n  }\n  \n  public final var currentTime: Double {\n    @inline(__always)\n    get {\n      return self.__implementation.currentTime\n    }\n    @inline(__always)\n    set {\n      self.__implementation.currentTime = newValue\n    }\n  }\n  \n  public final var muted: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.muted\n    }\n    @inline(__always)\n    set {\n      self.__implementation.muted = newValue\n    }\n  }\n  \n  public final var loop: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.loop\n    }\n    @inline(__always)\n    set {\n      self.__implementation.loop = newValue\n    }\n  }\n  \n  public final var rate: Double {\n    @inline(__always)\n    get {\n      return self.__implementation.rate\n    }\n    @inline(__always)\n    set {\n      self.__implementation.rate = newValue\n    }\n  }\n  \n  public final var mixAudioMode: Int32 {\n    @inline(__always)\n    get {\n      return self.__implementation.mixAudioMode.rawValue\n    }\n    @inline(__always)\n    set {\n      self.__implementation.mixAudioMode = margelo.nitro.video.MixAudioMode(rawValue: newValue)!\n    }\n  }\n  \n  public final var ignoreSilentSwitchMode: Int32 {\n    @inline(__always)\n    get {\n      return self.__implementation.ignoreSilentSwitchMode.rawValue\n    }\n    @inline(__always)\n    set {\n      self.__implementation.ignoreSilentSwitchMode = margelo.nitro.video.IgnoreSilentSwitchMode(rawValue: newValue)!\n    }\n  }\n  \n  public final var playInBackground: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.playInBackground\n    }\n    @inline(__always)\n    set {\n      self.__implementation.playInBackground = newValue\n    }\n  }\n  \n  public final var playWhenInactive: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.playWhenInactive\n    }\n    @inline(__always)\n    set {\n      self.__implementation.playWhenInactive = newValue\n    }\n  }\n  \n  public final var isPlaying: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.isPlaying\n    }\n  }\n  \n  public final var selectedTrack: bridge.std__optional_TextTrack_ {\n    @inline(__always)\n    get {\n      return { () -> bridge.std__optional_TextTrack_ in\n        if let __unwrappedValue = self.__implementation.selectedTrack {\n          return bridge.create_std__optional_TextTrack_(__unwrappedValue)\n        } else {\n          return .init()\n        }\n      }()\n    }\n  }\n\n  // Methods\n  @inline(__always)\n  public final func replaceSourceAsync(source: bridge.std__optional_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec___) -> bridge.Result_std__shared_ptr_Promise_void___ {\n    do {\n      let __result = try self.__implementation.replaceSourceAsync(source: { () -> Variant_NullType__any_HybridVideoPlayerSourceSpec_? in\n        if bridge.has_value_std__optional_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec___(source) {\n          let __unwrapped = bridge.get_std__optional_std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec___(source)\n          return { () -> Variant_NullType__any_HybridVideoPlayerSourceSpec_ in\n            let __variant = bridge.std__variant_nitro__NullType__std__shared_ptr_HybridVideoPlayerSourceSpec__(__unwrapped)\n            switch __variant.index() {\n              case 0:\n                let __actual = __variant.get_0()\n                return .first(NullType.null)\n              case 1:\n                let __actual = __variant.get_1()\n                return .second({ () -> any HybridVideoPlayerSourceSpec in\n                  let __unsafePointer = bridge.get_std__shared_ptr_HybridVideoPlayerSourceSpec_(__actual)\n                  let __instance = HybridVideoPlayerSourceSpec_cxx.fromUnsafe(__unsafePointer)\n                  return __instance.getHybridVideoPlayerSourceSpec()\n                }())\n              default:\n                fatalError(\"Variant can never have index \\(__variant.index())!\")\n            }\n          }()\n        } else {\n          return nil\n        }\n      }())\n      let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in\n        let __promise = bridge.create_std__shared_ptr_Promise_void__()\n        let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise)\n        __result\n          .then({ __result in __promiseHolder.resolve() })\n          .catch({ __error in __promiseHolder.reject(__error.toCpp()) })\n        return __promise\n      }()\n      return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func getAvailableTextTracks() -> bridge.Result_std__vector_TextTrack__ {\n    do {\n      let __result = try self.__implementation.getAvailableTextTracks()\n      let __resultCpp = { () -> bridge.std__vector_TextTrack_ in\n        var __vector = bridge.create_std__vector_TextTrack_(__result.count)\n        for __item in __result {\n          __vector.push_back(__item)\n        }\n        return __vector\n      }()\n      return bridge.create_Result_std__vector_TextTrack__(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__vector_TextTrack__(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func selectTextTrack(textTrack: bridge.std__optional_std__variant_nitro__NullType__TextTrack__) -> bridge.Result_void_ {\n    do {\n      try self.__implementation.selectTextTrack(textTrack: { () -> Variant_NullType_TextTrack? in\n        if bridge.has_value_std__optional_std__variant_nitro__NullType__TextTrack__(textTrack) {\n          let __unwrapped = bridge.get_std__optional_std__variant_nitro__NullType__TextTrack__(textTrack)\n          return { () -> Variant_NullType_TextTrack in\n            let __variant = bridge.std__variant_nitro__NullType__TextTrack_(__unwrapped)\n            switch __variant.index() {\n              case 0:\n                let __actual = __variant.get_0()\n                return .first(NullType.null)\n              case 1:\n                let __actual = __variant.get_1()\n                return .second(__actual)\n              default:\n                fatalError(\"Variant can never have index \\(__variant.index())!\")\n            }\n          }()\n        } else {\n          return nil\n        }\n      }())\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func release() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.release()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func initialize() -> bridge.Result_std__shared_ptr_Promise_void___ {\n    do {\n      let __result = try self.__implementation.initialize()\n      let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in\n        let __promise = bridge.create_std__shared_ptr_Promise_void__()\n        let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise)\n        __result\n          .then({ __result in __promiseHolder.resolve() })\n          .catch({ __error in __promiseHolder.reject(__error.toCpp()) })\n        return __promise\n      }()\n      return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func preload() -> bridge.Result_std__shared_ptr_Promise_void___ {\n    do {\n      let __result = try self.__implementation.preload()\n      let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in\n        let __promise = bridge.create_std__shared_ptr_Promise_void__()\n        let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise)\n        __result\n          .then({ __result in __promiseHolder.resolve() })\n          .catch({ __error in __promiseHolder.reject(__error.toCpp()) })\n        return __promise\n      }()\n      return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func play() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.play()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func pause() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.pause()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func seekBy(time: Double) -> bridge.Result_void_ {\n    do {\n      try self.__implementation.seekBy(time: time)\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func seekTo(time: Double) -> bridge.Result_void_ {\n    do {\n      try self.__implementation.seekTo(time: time)\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoViewViewManagerFactorySpec.swift",
    "content": "///\n/// HybridVideoViewViewManagerFactorySpec.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/// See ``HybridVideoViewViewManagerFactorySpec``\npublic protocol HybridVideoViewViewManagerFactorySpec_protocol: HybridObject {\n  // Properties\n  \n\n  // Methods\n  func createViewManager(nitroId: Double) throws -> (any HybridVideoViewViewManagerSpec)\n}\n\npublic extension HybridVideoViewViewManagerFactorySpec_protocol {\n  /// Default implementation of ``HybridObject.toString``\n  func toString() -> String {\n    return \"[HybridObject VideoViewViewManagerFactory]\"\n  }\n}\n\n/// See ``HybridVideoViewViewManagerFactorySpec``\nopen class HybridVideoViewViewManagerFactorySpec_base {\n  private weak var cxxWrapper: HybridVideoViewViewManagerFactorySpec_cxx? = nil\n  public init() { }\n  public func getCxxWrapper() -> HybridVideoViewViewManagerFactorySpec_cxx {\n  #if DEBUG\n    guard self is any HybridVideoViewViewManagerFactorySpec else {\n      fatalError(\"`self` is not a `HybridVideoViewViewManagerFactorySpec`! Did you accidentally inherit from `HybridVideoViewViewManagerFactorySpec_base` instead of `HybridVideoViewViewManagerFactorySpec`?\")\n    }\n  #endif\n    if let cxxWrapper = self.cxxWrapper {\n      return cxxWrapper\n    } else {\n      let cxxWrapper = HybridVideoViewViewManagerFactorySpec_cxx(self as! any HybridVideoViewViewManagerFactorySpec)\n      self.cxxWrapper = cxxWrapper\n      return cxxWrapper\n    }\n  }\n}\n\n/**\n * A Swift base-protocol representing the VideoViewViewManagerFactory HybridObject.\n * Implement this protocol to create Swift-based instances of VideoViewViewManagerFactory.\n * ```swift\n * class HybridVideoViewViewManagerFactory : HybridVideoViewViewManagerFactorySpec {\n *   // ...\n * }\n * ```\n */\npublic typealias HybridVideoViewViewManagerFactorySpec = HybridVideoViewViewManagerFactorySpec_protocol & HybridVideoViewViewManagerFactorySpec_base\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoViewViewManagerFactorySpec_cxx.swift",
    "content": "///\n/// HybridVideoViewViewManagerFactorySpec_cxx.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * A class implementation that bridges HybridVideoViewViewManagerFactorySpec over to C++.\n * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.\n *\n * Also, some Swift types need to be bridged with special handling:\n * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)\n * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper\n * - Throwing methods need to be wrapped with a Result<T, Error> type, as exceptions cannot be propagated to C++\n */\nopen class HybridVideoViewViewManagerFactorySpec_cxx {\n  /**\n   * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`)\n   * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`.\n   * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.\n   */\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Holds an instance of the `HybridVideoViewViewManagerFactorySpec` Swift protocol.\n   */\n  private var __implementation: any HybridVideoViewViewManagerFactorySpec\n\n  /**\n   * Holds a weak pointer to the C++ class that wraps the Swift class.\n   */\n  private var __cxxPart: bridge.std__weak_ptr_HybridVideoViewViewManagerFactorySpec_\n\n  /**\n   * Create a new `HybridVideoViewViewManagerFactorySpec_cxx` that wraps the given `HybridVideoViewViewManagerFactorySpec`.\n   * All properties and methods bridge to C++ types.\n   */\n  public init(_ implementation: any HybridVideoViewViewManagerFactorySpec) {\n    self.__implementation = implementation\n    self.__cxxPart = .init()\n    /* no base class */\n  }\n\n  /**\n   * Get the actual `HybridVideoViewViewManagerFactorySpec` instance this class wraps.\n   */\n  @inline(__always)\n  public func getHybridVideoViewViewManagerFactorySpec() -> any HybridVideoViewViewManagerFactorySpec {\n    return __implementation\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `HybridVideoViewViewManagerFactorySpec_cxx`.\n   * The pointer has to be a retained opaque `Unmanaged<HybridVideoViewViewManagerFactorySpec_cxx>`.\n   * This removes one strong reference from the object!\n   */\n  public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoViewViewManagerFactorySpec_cxx {\n    return Unmanaged<HybridVideoViewViewManagerFactorySpec_cxx>.fromOpaque(pointer).takeRetainedValue()\n  }\n\n  /**\n   * Gets (or creates) the C++ part of this Hybrid Object.\n   * The C++ part is a `std::shared_ptr<HybridVideoViewViewManagerFactorySpec>`.\n   */\n  public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoViewViewManagerFactorySpec_ {\n    let cachedCxxPart = self.__cxxPart.lock()\n    if Bool(fromCxx: cachedCxxPart) {\n      return cachedCxxPart\n    } else {\n      let newCxxPart = bridge.create_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(self.toUnsafe())\n      __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoViewViewManagerFactorySpec_(newCxxPart)\n      return newCxxPart\n    }\n  }\n\n  \n\n  /**\n   * Get the memory size of the Swift class (plus size of any other allocations)\n   * so the JS VM can properly track it and garbage-collect the JS object if needed.\n   */\n  @inline(__always)\n  public var memorySize: Int {\n    return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize\n  }\n\n  /**\n   * Compares this object with the given [other] object for reference equality.\n   */\n  @inline(__always)\n  public func equals(other: HybridVideoViewViewManagerFactorySpec_cxx) -> Bool {\n    return self.__implementation === other.__implementation\n  }\n\n  /**\n   * Call dispose() on the Swift class.\n   * This _may_ be called manually from JS.\n   */\n  @inline(__always)\n  public func dispose() {\n    self.__implementation.dispose()\n  }\n\n  /**\n   * Call toString() on the Swift class.\n   */\n  @inline(__always)\n  public func toString() -> String {\n    return self.__implementation.toString()\n  }\n\n  // Properties\n  \n\n  // Methods\n  @inline(__always)\n  public final func createViewManager(nitroId: Double) -> bridge.Result_std__shared_ptr_HybridVideoViewViewManagerSpec__ {\n    do {\n      let __result = try self.__implementation.createViewManager(nitroId: nitroId)\n      let __resultCpp = { () -> bridge.std__shared_ptr_HybridVideoViewViewManagerSpec_ in\n        let __cxxWrapped = __result.getCxxWrapper()\n        return __cxxWrapped.getCxxPart()\n      }()\n      return bridge.create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_std__shared_ptr_HybridVideoViewViewManagerSpec__(__exceptionPtr)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoViewViewManagerSpec.swift",
    "content": "///\n/// HybridVideoViewViewManagerSpec.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/// See ``HybridVideoViewViewManagerSpec``\npublic protocol HybridVideoViewViewManagerSpec_protocol: HybridObject {\n  // Properties\n  var player: (any HybridVideoPlayerSpec)? { get set }\n  var controls: Bool { get set }\n  var pictureInPicture: Bool { get set }\n  var autoEnterPictureInPicture: Bool { get set }\n  var resizeMode: ResizeMode { get set }\n  var keepScreenAwake: Bool { get set }\n  var surfaceType: SurfaceType { get set }\n\n  // Methods\n  func enterFullscreen() throws -> Void\n  func exitFullscreen() throws -> Void\n  func enterPictureInPicture() throws -> Void\n  func exitPictureInPicture() throws -> Void\n  func canEnterPictureInPicture() throws -> Bool\n  func addOnPictureInPictureChangeListener(listener: @escaping (_ isInPictureInPicture: Bool) -> Void) throws -> ListenerSubscription\n  func addOnFullscreenChangeListener(listener: @escaping (_ fullscreen: Bool) -> Void) throws -> ListenerSubscription\n  func addWillEnterFullscreenListener(listener: @escaping () -> Void) throws -> ListenerSubscription\n  func addWillExitFullscreenListener(listener: @escaping () -> Void) throws -> ListenerSubscription\n  func addWillEnterPictureInPictureListener(listener: @escaping () -> Void) throws -> ListenerSubscription\n  func addWillExitPictureInPictureListener(listener: @escaping () -> Void) throws -> ListenerSubscription\n  func clearAllListeners() throws -> Void\n}\n\npublic extension HybridVideoViewViewManagerSpec_protocol {\n  /// Default implementation of ``HybridObject.toString``\n  func toString() -> String {\n    return \"[HybridObject VideoViewViewManager]\"\n  }\n}\n\n/// See ``HybridVideoViewViewManagerSpec``\nopen class HybridVideoViewViewManagerSpec_base {\n  private weak var cxxWrapper: HybridVideoViewViewManagerSpec_cxx? = nil\n  public init() { }\n  public func getCxxWrapper() -> HybridVideoViewViewManagerSpec_cxx {\n  #if DEBUG\n    guard self is any HybridVideoViewViewManagerSpec else {\n      fatalError(\"`self` is not a `HybridVideoViewViewManagerSpec`! Did you accidentally inherit from `HybridVideoViewViewManagerSpec_base` instead of `HybridVideoViewViewManagerSpec`?\")\n    }\n  #endif\n    if let cxxWrapper = self.cxxWrapper {\n      return cxxWrapper\n    } else {\n      let cxxWrapper = HybridVideoViewViewManagerSpec_cxx(self as! any HybridVideoViewViewManagerSpec)\n      self.cxxWrapper = cxxWrapper\n      return cxxWrapper\n    }\n  }\n}\n\n/**\n * A Swift base-protocol representing the VideoViewViewManager HybridObject.\n * Implement this protocol to create Swift-based instances of VideoViewViewManager.\n * ```swift\n * class HybridVideoViewViewManager : HybridVideoViewViewManagerSpec {\n *   // ...\n * }\n * ```\n */\npublic typealias HybridVideoViewViewManagerSpec = HybridVideoViewViewManagerSpec_protocol & HybridVideoViewViewManagerSpec_base\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/HybridVideoViewViewManagerSpec_cxx.swift",
    "content": "///\n/// HybridVideoViewViewManagerSpec_cxx.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * A class implementation that bridges HybridVideoViewViewManagerSpec over to C++.\n * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.\n *\n * Also, some Swift types need to be bridged with special handling:\n * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)\n * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper\n * - Throwing methods need to be wrapped with a Result<T, Error> type, as exceptions cannot be propagated to C++\n */\nopen class HybridVideoViewViewManagerSpec_cxx {\n  /**\n   * The Swift <> C++ bridge's namespace (`margelo::nitro::video::bridge::swift`)\n   * from `ReactNativeVideo-Swift-Cxx-Bridge.hpp`.\n   * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.\n   */\n  public typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Holds an instance of the `HybridVideoViewViewManagerSpec` Swift protocol.\n   */\n  private var __implementation: any HybridVideoViewViewManagerSpec\n\n  /**\n   * Holds a weak pointer to the C++ class that wraps the Swift class.\n   */\n  private var __cxxPart: bridge.std__weak_ptr_HybridVideoViewViewManagerSpec_\n\n  /**\n   * Create a new `HybridVideoViewViewManagerSpec_cxx` that wraps the given `HybridVideoViewViewManagerSpec`.\n   * All properties and methods bridge to C++ types.\n   */\n  public init(_ implementation: any HybridVideoViewViewManagerSpec) {\n    self.__implementation = implementation\n    self.__cxxPart = .init()\n    /* no base class */\n  }\n\n  /**\n   * Get the actual `HybridVideoViewViewManagerSpec` instance this class wraps.\n   */\n  @inline(__always)\n  public func getHybridVideoViewViewManagerSpec() -> any HybridVideoViewViewManagerSpec {\n    return __implementation\n  }\n\n  /**\n   * Casts this instance to a retained unsafe raw pointer.\n   * This acquires one additional strong reference on the object!\n   */\n  public func toUnsafe() -> UnsafeMutableRawPointer {\n    return Unmanaged.passRetained(self).toOpaque()\n  }\n\n  /**\n   * Casts an unsafe pointer to a `HybridVideoViewViewManagerSpec_cxx`.\n   * The pointer has to be a retained opaque `Unmanaged<HybridVideoViewViewManagerSpec_cxx>`.\n   * This removes one strong reference from the object!\n   */\n  public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridVideoViewViewManagerSpec_cxx {\n    return Unmanaged<HybridVideoViewViewManagerSpec_cxx>.fromOpaque(pointer).takeRetainedValue()\n  }\n\n  /**\n   * Gets (or creates) the C++ part of this Hybrid Object.\n   * The C++ part is a `std::shared_ptr<HybridVideoViewViewManagerSpec>`.\n   */\n  public func getCxxPart() -> bridge.std__shared_ptr_HybridVideoViewViewManagerSpec_ {\n    let cachedCxxPart = self.__cxxPart.lock()\n    if Bool(fromCxx: cachedCxxPart) {\n      return cachedCxxPart\n    } else {\n      let newCxxPart = bridge.create_std__shared_ptr_HybridVideoViewViewManagerSpec_(self.toUnsafe())\n      __cxxPart = bridge.weakify_std__shared_ptr_HybridVideoViewViewManagerSpec_(newCxxPart)\n      return newCxxPart\n    }\n  }\n\n  \n\n  /**\n   * Get the memory size of the Swift class (plus size of any other allocations)\n   * so the JS VM can properly track it and garbage-collect the JS object if needed.\n   */\n  @inline(__always)\n  public var memorySize: Int {\n    return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize\n  }\n\n  /**\n   * Compares this object with the given [other] object for reference equality.\n   */\n  @inline(__always)\n  public func equals(other: HybridVideoViewViewManagerSpec_cxx) -> Bool {\n    return self.__implementation === other.__implementation\n  }\n\n  /**\n   * Call dispose() on the Swift class.\n   * This _may_ be called manually from JS.\n   */\n  @inline(__always)\n  public func dispose() {\n    self.__implementation.dispose()\n  }\n\n  /**\n   * Call toString() on the Swift class.\n   */\n  @inline(__always)\n  public func toString() -> String {\n    return self.__implementation.toString()\n  }\n\n  // Properties\n  public final var player: bridge.std__optional_std__shared_ptr_HybridVideoPlayerSpec__ {\n    @inline(__always)\n    get {\n      return { () -> bridge.std__optional_std__shared_ptr_HybridVideoPlayerSpec__ in\n        if let __unwrappedValue = self.__implementation.player {\n          return bridge.create_std__optional_std__shared_ptr_HybridVideoPlayerSpec__({ () -> bridge.std__shared_ptr_HybridVideoPlayerSpec_ in\n            let __cxxWrapped = __unwrappedValue.getCxxWrapper()\n            return __cxxWrapped.getCxxPart()\n          }())\n        } else {\n          return .init()\n        }\n      }()\n    }\n    @inline(__always)\n    set {\n      self.__implementation.player = { () -> (any HybridVideoPlayerSpec)? in\n        if bridge.has_value_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(newValue) {\n          let __unwrapped = bridge.get_std__optional_std__shared_ptr_HybridVideoPlayerSpec__(newValue)\n          return { () -> any HybridVideoPlayerSpec in\n            let __unsafePointer = bridge.get_std__shared_ptr_HybridVideoPlayerSpec_(__unwrapped)\n            let __instance = HybridVideoPlayerSpec_cxx.fromUnsafe(__unsafePointer)\n            return __instance.getHybridVideoPlayerSpec()\n          }()\n        } else {\n          return nil\n        }\n      }()\n    }\n  }\n  \n  public final var controls: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.controls\n    }\n    @inline(__always)\n    set {\n      self.__implementation.controls = newValue\n    }\n  }\n  \n  public final var pictureInPicture: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.pictureInPicture\n    }\n    @inline(__always)\n    set {\n      self.__implementation.pictureInPicture = newValue\n    }\n  }\n  \n  public final var autoEnterPictureInPicture: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.autoEnterPictureInPicture\n    }\n    @inline(__always)\n    set {\n      self.__implementation.autoEnterPictureInPicture = newValue\n    }\n  }\n  \n  public final var resizeMode: Int32 {\n    @inline(__always)\n    get {\n      return self.__implementation.resizeMode.rawValue\n    }\n    @inline(__always)\n    set {\n      self.__implementation.resizeMode = margelo.nitro.video.ResizeMode(rawValue: newValue)!\n    }\n  }\n  \n  public final var keepScreenAwake: Bool {\n    @inline(__always)\n    get {\n      return self.__implementation.keepScreenAwake\n    }\n    @inline(__always)\n    set {\n      self.__implementation.keepScreenAwake = newValue\n    }\n  }\n  \n  public final var surfaceType: Int32 {\n    @inline(__always)\n    get {\n      return self.__implementation.surfaceType.rawValue\n    }\n    @inline(__always)\n    set {\n      self.__implementation.surfaceType = margelo.nitro.video.SurfaceType(rawValue: newValue)!\n    }\n  }\n\n  // Methods\n  @inline(__always)\n  public final func enterFullscreen() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.enterFullscreen()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func exitFullscreen() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.exitFullscreen()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func enterPictureInPicture() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.enterPictureInPicture()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func exitPictureInPicture() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.exitPictureInPicture()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func canEnterPictureInPicture() -> bridge.Result_bool_ {\n    do {\n      let __result = try self.__implementation.canEnterPictureInPicture()\n      let __resultCpp = __result\n      return bridge.create_Result_bool_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_bool_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnPictureInPictureChangeListener(listener: bridge.Func_void_bool) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnPictureInPictureChangeListener(listener: { () -> (Bool) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_bool(listener)\n        return { (__isInPictureInPicture: Bool) -> Void in\n          __wrappedFunction.call(__isInPictureInPicture)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addOnFullscreenChangeListener(listener: bridge.Func_void_bool) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addOnFullscreenChangeListener(listener: { () -> (Bool) -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void_bool(listener)\n        return { (__fullscreen: Bool) -> Void in\n          __wrappedFunction.call(__fullscreen)\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addWillEnterFullscreenListener(listener: bridge.Func_void) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addWillEnterFullscreenListener(listener: { () -> () -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void(listener)\n        return { () -> Void in\n          __wrappedFunction.call()\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addWillExitFullscreenListener(listener: bridge.Func_void) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addWillExitFullscreenListener(listener: { () -> () -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void(listener)\n        return { () -> Void in\n          __wrappedFunction.call()\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addWillEnterPictureInPictureListener(listener: bridge.Func_void) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addWillEnterPictureInPictureListener(listener: { () -> () -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void(listener)\n        return { () -> Void in\n          __wrappedFunction.call()\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func addWillExitPictureInPictureListener(listener: bridge.Func_void) -> bridge.Result_ListenerSubscription_ {\n    do {\n      let __result = try self.__implementation.addWillExitPictureInPictureListener(listener: { () -> () -> Void in\n        let __wrappedFunction = bridge.wrap_Func_void(listener)\n        return { () -> Void in\n          __wrappedFunction.call()\n        }\n      }())\n      let __resultCpp = __result\n      return bridge.create_Result_ListenerSubscription_(__resultCpp)\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_ListenerSubscription_(__exceptionPtr)\n    }\n  }\n  \n  @inline(__always)\n  public final func clearAllListeners() -> bridge.Result_void_ {\n    do {\n      try self.__implementation.clearAllListeners()\n      return bridge.create_Result_void_()\n    } catch (let __error) {\n      let __exceptionPtr = __error.toCpp()\n      return bridge.create_Result_void_(__exceptionPtr)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/IgnoreSilentSwitchMode.swift",
    "content": "///\n/// IgnoreSilentSwitchMode.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/**\n * Represents the JS union `IgnoreSilentSwitchMode`, backed by a C++ enum.\n */\npublic typealias IgnoreSilentSwitchMode = margelo.nitro.video.IgnoreSilentSwitchMode\n\npublic extension IgnoreSilentSwitchMode {\n  /**\n   * Get a IgnoreSilentSwitchMode for the given String value, or\n   * return `nil` if the given value was invalid/unknown.\n   */\n  init?(fromString string: String) {\n    switch string {\n      case \"auto\":\n        self = .auto\n      case \"ignore\":\n        self = .ignore\n      case \"obey\":\n        self = .obey\n      default:\n        return nil\n    }\n  }\n\n  /**\n   * Get the String value this IgnoreSilentSwitchMode represents.\n   */\n  var stringValue: String {\n    switch self {\n      case .auto:\n        return \"auto\"\n      case .ignore:\n        return \"ignore\"\n      case .obey:\n        return \"obey\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/ListenerSubscription.swift",
    "content": "///\n/// ListenerSubscription.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `ListenerSubscription`, backed by a C++ struct.\n */\npublic typealias ListenerSubscription = margelo.nitro.video.ListenerSubscription\n\npublic extension ListenerSubscription {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `ListenerSubscription`.\n   */\n  init(remove: @escaping () -> Void) {\n    self.init({ () -> bridge.Func_void in\n      let __closureWrapper = Func_void(remove)\n      return bridge.create_Func_void(__closureWrapper.toUnsafe())\n    }())\n  }\n\n  @inline(__always)\n  var remove: () -> Void {\n    return { () -> () -> Void in\n      let __wrappedFunction = bridge.wrap_Func_void(self.__remove)\n      return { () -> Void in\n        __wrappedFunction.call()\n      }\n    }()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/LivePlaybackParams.swift",
    "content": "///\n/// LivePlaybackParams.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `LivePlaybackParams`, backed by a C++ struct.\n */\npublic typealias LivePlaybackParams = margelo.nitro.video.LivePlaybackParams\n\npublic extension LivePlaybackParams {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `LivePlaybackParams`.\n   */\n  init(minPlaybackSpeed: Double?, maxPlaybackSpeed: Double?, maxOffsetMs: Double?, minOffsetMs: Double?, targetOffsetMs: Double?) {\n    self.init({ () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = minPlaybackSpeed {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = maxPlaybackSpeed {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = maxOffsetMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = minOffsetMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_double_ in\n      if let __unwrappedValue = targetOffsetMs {\n        return bridge.create_std__optional_double_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }())\n  }\n\n  @inline(__always)\n  var minPlaybackSpeed: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__minPlaybackSpeed) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__minPlaybackSpeed)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var maxPlaybackSpeed: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__maxPlaybackSpeed) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__maxPlaybackSpeed)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var maxOffsetMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__maxOffsetMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__maxOffsetMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var minOffsetMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__minOffsetMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__minOffsetMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var targetOffsetMs: Double? {\n    return { () -> Double? in\n      if bridge.has_value_std__optional_double_(self.__targetOffsetMs) {\n        let __unwrapped = bridge.get_std__optional_double_(self.__targetOffsetMs)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/MixAudioMode.swift",
    "content": "///\n/// MixAudioMode.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/**\n * Represents the JS union `MixAudioMode`, backed by a C++ enum.\n */\npublic typealias MixAudioMode = margelo.nitro.video.MixAudioMode\n\npublic extension MixAudioMode {\n  /**\n   * Get a MixAudioMode for the given String value, or\n   * return `nil` if the given value was invalid/unknown.\n   */\n  init?(fromString string: String) {\n    switch string {\n      case \"mixWithOthers\":\n        self = .mixwithothers\n      case \"doNotMix\":\n        self = .donotmix\n      case \"duckOthers\":\n        self = .duckothers\n      case \"auto\":\n        self = .auto\n      default:\n        return nil\n    }\n  }\n\n  /**\n   * Get the String value this MixAudioMode represents.\n   */\n  var stringValue: String {\n    switch self {\n      case .mixwithothers:\n        return \"mixWithOthers\"\n      case .donotmix:\n        return \"doNotMix\"\n      case .duckothers:\n        return \"duckOthers\"\n      case .auto:\n        return \"auto\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/NativeDrmParams.swift",
    "content": "///\n/// NativeDrmParams.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `NativeDrmParams`, backed by a C++ struct.\n */\npublic typealias NativeDrmParams = margelo.nitro.video.NativeDrmParams\n\npublic extension NativeDrmParams {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `NativeDrmParams`.\n   */\n  init(type: String?, licenseUrl: String?, certificateUrl: String?, contentId: String?, licenseHeaders: Dictionary<String, String>?, multiSession: Bool?, getLicense: ((_ payload: OnGetLicensePayload) -> Promise<Promise<String>>)?) {\n    self.init({ () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = type {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = licenseUrl {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = certificateUrl {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = contentId {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__unordered_map_std__string__std__string__ in\n      if let __unwrappedValue = licenseHeaders {\n        return bridge.create_std__optional_std__unordered_map_std__string__std__string__({ () -> bridge.std__unordered_map_std__string__std__string_ in\n          var __map = bridge.create_std__unordered_map_std__string__std__string_(__unwrappedValue.count)\n          for (__k, __v) in __unwrappedValue {\n            bridge.emplace_std__unordered_map_std__string__std__string_(&__map, std.string(__k), std.string(__v))\n          }\n          return __map\n        }())\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_bool_ in\n      if let __unwrappedValue = multiSession {\n        return bridge.create_std__optional_bool_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______ in\n      if let __unwrappedValue = getLicense {\n        return bridge.create_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______({ () -> bridge.Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload in\n          let __closureWrapper = Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__unwrappedValue)\n          return bridge.create_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__closureWrapper.toUnsafe())\n        }())\n      } else {\n        return .init()\n      }\n    }())\n  }\n\n  @inline(__always)\n  var type: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__type) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__type)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var licenseUrl: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__licenseUrl) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__licenseUrl)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var certificateUrl: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__certificateUrl) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__certificateUrl)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var contentId: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__contentId) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__contentId)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var licenseHeaders: Dictionary<String, String>? {\n    return { () -> Dictionary<String, String>? in\n      if bridge.has_value_std__optional_std__unordered_map_std__string__std__string__(self.__licenseHeaders) {\n        let __unwrapped = bridge.get_std__optional_std__unordered_map_std__string__std__string__(self.__licenseHeaders)\n        return { () -> Dictionary<String, String> in\n          var __dictionary = Dictionary<String, String>(minimumCapacity: __unwrapped.size())\n          let __keys = bridge.get_std__unordered_map_std__string__std__string__keys(__unwrapped)\n          for __key in __keys {\n            let __value = bridge.get_std__unordered_map_std__string__std__string__value(__unwrapped, __key)\n            __dictionary[String(__key)] = String(__value)\n          }\n          return __dictionary\n        }()\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var multiSession: Bool? {\n    return { () -> Bool? in\n      if bridge.has_value_std__optional_bool_(self.__multiSession) {\n        let __unwrapped = bridge.get_std__optional_bool_(self.__multiSession)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var getLicense: ((_ payload: OnGetLicensePayload) -> Promise<Promise<String>>)? {\n    return { () -> ((_ payload: OnGetLicensePayload) -> Promise<Promise<String>>)? in\n      if bridge.has_value_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(self.__getLicense) {\n        let __unwrapped = bridge.get_std__optional_std__function_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____const_OnGetLicensePayload_____payload______(self.__getLicense)\n        return { () -> (OnGetLicensePayload) -> Promise<Promise<String>> in\n          let __wrappedFunction = bridge.wrap_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string_____OnGetLicensePayload(__unwrapped)\n          return { (__payload: OnGetLicensePayload) -> Promise<Promise<String>> in\n            let __result = __wrappedFunction.call(__payload)\n            return { () -> Promise<Promise<String>> in\n              let __promise = Promise<Promise<String>>()\n              let __resolver = { (__result: Promise<String>) in\n                __promise.resolve(withResult: __result)\n              }\n              let __rejecter = { (__error: Error) in\n                __promise.reject(withError: __error)\n              }\n              let __resolverCpp = { () -> bridge.Func_void_std__shared_ptr_Promise_std__string__ in\n                let __closureWrapper = Func_void_std__shared_ptr_Promise_std__string__(__resolver)\n                return bridge.create_Func_void_std__shared_ptr_Promise_std__string__(__closureWrapper.toUnsafe())\n              }()\n              let __rejecterCpp = { () -> bridge.Func_void_std__exception_ptr in\n                let __closureWrapper = Func_void_std__exception_ptr(__rejecter)\n                return bridge.create_Func_void_std__exception_ptr(__closureWrapper.toUnsafe())\n              }()\n              let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_Promise_std__string____(__result)\n              __promiseHolder.addOnResolvedListener(__resolverCpp)\n              __promiseHolder.addOnRejectedListener(__rejecterCpp)\n              return __promise\n            }()\n          }\n        }()\n      } else {\n        return nil\n      }\n    }()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/NativeExternalSubtitle.swift",
    "content": "///\n/// NativeExternalSubtitle.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `NativeExternalSubtitle`, backed by a C++ struct.\n */\npublic typealias NativeExternalSubtitle = margelo.nitro.video.NativeExternalSubtitle\n\npublic extension NativeExternalSubtitle {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `NativeExternalSubtitle`.\n   */\n  init(uri: String, label: String, type: SubtitleType, language: String) {\n    self.init(std.string(uri), std.string(label), type, std.string(language))\n  }\n\n  @inline(__always)\n  var uri: String {\n    return String(self.__uri)\n  }\n  \n  @inline(__always)\n  var label: String {\n    return String(self.__label)\n  }\n  \n  @inline(__always)\n  var type: SubtitleType {\n    return self.__type\n  }\n  \n  @inline(__always)\n  var language: String {\n    return String(self.__language)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/NativeVideoConfig.swift",
    "content": "///\n/// NativeVideoConfig.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `NativeVideoConfig`, backed by a C++ struct.\n */\npublic typealias NativeVideoConfig = margelo.nitro.video.NativeVideoConfig\n\npublic extension NativeVideoConfig {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `NativeVideoConfig`.\n   */\n  init(uri: String, externalSubtitles: [NativeExternalSubtitle]?, drm: NativeDrmParams?, headers: Dictionary<String, String>?, bufferConfig: BufferConfig?, metadata: CustomVideoMetadata?, initializeOnCreation: Bool?) {\n    self.init(std.string(uri), { () -> bridge.std__optional_std__vector_NativeExternalSubtitle__ in\n      if let __unwrappedValue = externalSubtitles {\n        return bridge.create_std__optional_std__vector_NativeExternalSubtitle__({ () -> bridge.std__vector_NativeExternalSubtitle_ in\n          var __vector = bridge.create_std__vector_NativeExternalSubtitle_(__unwrappedValue.count)\n          for __item in __unwrappedValue {\n            __vector.push_back(__item)\n          }\n          return __vector\n        }())\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_NativeDrmParams_ in\n      if let __unwrappedValue = drm {\n        return bridge.create_std__optional_NativeDrmParams_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_std__unordered_map_std__string__std__string__ in\n      if let __unwrappedValue = headers {\n        return bridge.create_std__optional_std__unordered_map_std__string__std__string__({ () -> bridge.std__unordered_map_std__string__std__string_ in\n          var __map = bridge.create_std__unordered_map_std__string__std__string_(__unwrappedValue.count)\n          for (__k, __v) in __unwrappedValue {\n            bridge.emplace_std__unordered_map_std__string__std__string_(&__map, std.string(__k), std.string(__v))\n          }\n          return __map\n        }())\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_BufferConfig_ in\n      if let __unwrappedValue = bufferConfig {\n        return bridge.create_std__optional_BufferConfig_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_CustomVideoMetadata_ in\n      if let __unwrappedValue = metadata {\n        return bridge.create_std__optional_CustomVideoMetadata_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }(), { () -> bridge.std__optional_bool_ in\n      if let __unwrappedValue = initializeOnCreation {\n        return bridge.create_std__optional_bool_(__unwrappedValue)\n      } else {\n        return .init()\n      }\n    }())\n  }\n\n  @inline(__always)\n  var uri: String {\n    return String(self.__uri)\n  }\n  \n  @inline(__always)\n  var externalSubtitles: [NativeExternalSubtitle]? {\n    return { () -> [NativeExternalSubtitle]? in\n      if bridge.has_value_std__optional_std__vector_NativeExternalSubtitle__(self.__externalSubtitles) {\n        let __unwrapped = bridge.get_std__optional_std__vector_NativeExternalSubtitle__(self.__externalSubtitles)\n        return __unwrapped.map({ __item in __item })\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var drm: NativeDrmParams? {\n    return self.__drm.value\n  }\n  \n  @inline(__always)\n  var headers: Dictionary<String, String>? {\n    return { () -> Dictionary<String, String>? in\n      if bridge.has_value_std__optional_std__unordered_map_std__string__std__string__(self.__headers) {\n        let __unwrapped = bridge.get_std__optional_std__unordered_map_std__string__std__string__(self.__headers)\n        return { () -> Dictionary<String, String> in\n          var __dictionary = Dictionary<String, String>(minimumCapacity: __unwrapped.size())\n          let __keys = bridge.get_std__unordered_map_std__string__std__string__keys(__unwrapped)\n          for __key in __keys {\n            let __value = bridge.get_std__unordered_map_std__string__std__string__value(__unwrapped, __key)\n            __dictionary[String(__key)] = String(__value)\n          }\n          return __dictionary\n        }()\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var bufferConfig: BufferConfig? {\n    return self.__bufferConfig.value\n  }\n  \n  @inline(__always)\n  var metadata: CustomVideoMetadata? {\n    return self.__metadata.value\n  }\n  \n  @inline(__always)\n  var initializeOnCreation: Bool? {\n    return { () -> Bool? in\n      if bridge.has_value_std__optional_bool_(self.__initializeOnCreation) {\n        let __unwrapped = bridge.get_std__optional_bool_(self.__initializeOnCreation)\n        return __unwrapped\n      } else {\n        return nil\n      }\n    }()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/OnGetLicensePayload.swift",
    "content": "///\n/// OnGetLicensePayload.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `OnGetLicensePayload`, backed by a C++ struct.\n */\npublic typealias OnGetLicensePayload = margelo.nitro.video.OnGetLicensePayload\n\npublic extension OnGetLicensePayload {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `OnGetLicensePayload`.\n   */\n  init(contentId: String, licenseUrl: String, keyUrl: String, spc: String) {\n    self.init(std.string(contentId), std.string(licenseUrl), std.string(keyUrl), std.string(spc))\n  }\n\n  @inline(__always)\n  var contentId: String {\n    return String(self.__contentId)\n  }\n  \n  @inline(__always)\n  var licenseUrl: String {\n    return String(self.__licenseUrl)\n  }\n  \n  @inline(__always)\n  var keyUrl: String {\n    return String(self.__keyUrl)\n  }\n  \n  @inline(__always)\n  var spc: String {\n    return String(self.__spc)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/ResizeMode.swift",
    "content": "///\n/// ResizeMode.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/**\n * Represents the JS union `ResizeMode`, backed by a C++ enum.\n */\npublic typealias ResizeMode = margelo.nitro.video.ResizeMode\n\npublic extension ResizeMode {\n  /**\n   * Get a ResizeMode for the given String value, or\n   * return `nil` if the given value was invalid/unknown.\n   */\n  init?(fromString string: String) {\n    switch string {\n      case \"contain\":\n        self = .contain\n      case \"cover\":\n        self = .cover\n      case \"stretch\":\n        self = .stretch\n      case \"none\":\n        self = .none\n      default:\n        return nil\n    }\n  }\n\n  /**\n   * Get the String value this ResizeMode represents.\n   */\n  var stringValue: String {\n    switch self {\n      case .contain:\n        return \"contain\"\n      case .cover:\n        return \"cover\"\n      case .stretch:\n        return \"stretch\"\n      case .none:\n        return \"none\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Resolution.swift",
    "content": "///\n/// Resolution.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `Resolution`, backed by a C++ struct.\n */\npublic typealias Resolution = margelo.nitro.video.Resolution\n\npublic extension Resolution {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `Resolution`.\n   */\n  init(width: Double, height: Double) {\n    self.init(width, height)\n  }\n\n  @inline(__always)\n  var width: Double {\n    return self.__width\n  }\n  \n  @inline(__always)\n  var height: Double {\n    return self.__height\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/SourceType.swift",
    "content": "///\n/// SourceType.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/**\n * Represents the JS union `SourceType`, backed by a C++ enum.\n */\npublic typealias SourceType = margelo.nitro.video.SourceType\n\npublic extension SourceType {\n  /**\n   * Get a SourceType for the given String value, or\n   * return `nil` if the given value was invalid/unknown.\n   */\n  init?(fromString string: String) {\n    switch string {\n      case \"local\":\n        self = .local\n      case \"network\":\n        self = .network\n      default:\n        return nil\n    }\n  }\n\n  /**\n   * Get the String value this SourceType represents.\n   */\n  var stringValue: String {\n    switch self {\n      case .local:\n        return \"local\"\n      case .network:\n        return \"network\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/SubtitleType.swift",
    "content": "///\n/// SubtitleType.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/**\n * Represents the JS union `SubtitleType`, backed by a C++ enum.\n */\npublic typealias SubtitleType = margelo.nitro.video.SubtitleType\n\npublic extension SubtitleType {\n  /**\n   * Get a SubtitleType for the given String value, or\n   * return `nil` if the given value was invalid/unknown.\n   */\n  init?(fromString string: String) {\n    switch string {\n      case \"auto\":\n        self = .auto\n      case \"vtt\":\n        self = .vtt\n      case \"srt\":\n        self = .srt\n      case \"ssa\":\n        self = .ssa\n      case \"ass\":\n        self = .ass\n      default:\n        return nil\n    }\n  }\n\n  /**\n   * Get the String value this SubtitleType represents.\n   */\n  var stringValue: String {\n    switch self {\n      case .auto:\n        return \"auto\"\n      case .vtt:\n        return \"vtt\"\n      case .srt:\n        return \"srt\"\n      case .ssa:\n        return \"ssa\"\n      case .ass:\n        return \"ass\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/SurfaceType.swift",
    "content": "///\n/// SurfaceType.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/**\n * Represents the JS union `SurfaceType`, backed by a C++ enum.\n */\npublic typealias SurfaceType = margelo.nitro.video.SurfaceType\n\npublic extension SurfaceType {\n  /**\n   * Get a SurfaceType for the given String value, or\n   * return `nil` if the given value was invalid/unknown.\n   */\n  init?(fromString string: String) {\n    switch string {\n      case \"surface\":\n        self = .surface\n      case \"texture\":\n        self = .texture\n      default:\n        return nil\n    }\n  }\n\n  /**\n   * Get the String value this SurfaceType represents.\n   */\n  var stringValue: String {\n    switch self {\n      case .surface:\n        return \"surface\"\n      case .texture:\n        return \"texture\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/TextTrack.swift",
    "content": "///\n/// TextTrack.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `TextTrack`, backed by a C++ struct.\n */\npublic typealias TextTrack = margelo.nitro.video.TextTrack\n\npublic extension TextTrack {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `TextTrack`.\n   */\n  init(id: String, label: String, language: String?, selected: Bool) {\n    self.init(std.string(id), std.string(label), { () -> bridge.std__optional_std__string_ in\n      if let __unwrappedValue = language {\n        return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))\n      } else {\n        return .init()\n      }\n    }(), selected)\n  }\n\n  @inline(__always)\n  var id: String {\n    return String(self.__id)\n  }\n  \n  @inline(__always)\n  var label: String {\n    return String(self.__label)\n  }\n  \n  @inline(__always)\n  var language: String? {\n    return { () -> String? in\n      if bridge.has_value_std__optional_std__string_(self.__language) {\n        let __unwrapped = bridge.get_std__optional_std__string_(self.__language)\n        return String(__unwrapped)\n      } else {\n        return nil\n      }\n    }()\n  }\n  \n  @inline(__always)\n  var selected: Bool {\n    return self.__selected\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/TimedMetadata.swift",
    "content": "///\n/// TimedMetadata.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `TimedMetadata`, backed by a C++ struct.\n */\npublic typealias TimedMetadata = margelo.nitro.video.TimedMetadata\n\npublic extension TimedMetadata {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `TimedMetadata`.\n   */\n  init(metadata: [TimedMetadataObject]) {\n    self.init({ () -> bridge.std__vector_TimedMetadataObject_ in\n      var __vector = bridge.create_std__vector_TimedMetadataObject_(metadata.count)\n      for __item in metadata {\n        __vector.push_back(__item)\n      }\n      return __vector\n    }())\n  }\n\n  @inline(__always)\n  var metadata: [TimedMetadataObject] {\n    return self.__metadata.map({ __item in __item })\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/TimedMetadataObject.swift",
    "content": "///\n/// TimedMetadataObject.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `TimedMetadataObject`, backed by a C++ struct.\n */\npublic typealias TimedMetadataObject = margelo.nitro.video.TimedMetadataObject\n\npublic extension TimedMetadataObject {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `TimedMetadataObject`.\n   */\n  init(value: String, identifier: String) {\n    self.init(std.string(value), std.string(identifier))\n  }\n\n  @inline(__always)\n  var value: String {\n    return String(self.__value)\n  }\n  \n  @inline(__always)\n  var identifier: String {\n    return String(self.__identifier)\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Variant_NullType_TextTrack.swift",
    "content": "///\n/// Variant_NullType_TextTrack.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * An Swift enum with associated values representing a Variant/Union type.\n * JS type: `null | struct`\n */\n@frozen\npublic indirect enum Variant_NullType_TextTrack {\n  case first(NullType)\n  case second(TextTrack)\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/Variant_NullType__any_HybridVideoPlayerSourceSpec_.swift",
    "content": "///\n/// Variant_NullType__any_HybridVideoPlayerSourceSpec_.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * An Swift enum with associated values representing a Variant/Union type.\n * JS type: `null | hybrid-object`\n */\n@frozen\npublic indirect enum Variant_NullType__any_HybridVideoPlayerSourceSpec_ {\n  case first(NullType)\n  case second((any HybridVideoPlayerSourceSpec))\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/VideoInformation.swift",
    "content": "///\n/// VideoInformation.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `VideoInformation`, backed by a C++ struct.\n */\npublic typealias VideoInformation = margelo.nitro.video.VideoInformation\n\npublic extension VideoInformation {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `VideoInformation`.\n   */\n  init(bitrate: Double, width: Double, height: Double, duration: Double, fileSize: Int64, isHDR: Bool, isLive: Bool, orientation: VideoOrientation) {\n    self.init(bitrate, width, height, duration, fileSize, isHDR, isLive, orientation)\n  }\n\n  @inline(__always)\n  var bitrate: Double {\n    return self.__bitrate\n  }\n  \n  @inline(__always)\n  var width: Double {\n    return self.__width\n  }\n  \n  @inline(__always)\n  var height: Double {\n    return self.__height\n  }\n  \n  @inline(__always)\n  var duration: Double {\n    return self.__duration\n  }\n  \n  @inline(__always)\n  var fileSize: Int64 {\n    return self.__fileSize\n  }\n  \n  @inline(__always)\n  var isHDR: Bool {\n    return self.__isHDR\n  }\n  \n  @inline(__always)\n  var isLive: Bool {\n    return self.__isLive\n  }\n  \n  @inline(__always)\n  var orientation: VideoOrientation {\n    return self.__orientation\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/VideoOrientation.swift",
    "content": "///\n/// VideoOrientation.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/**\n * Represents the JS union `VideoOrientation`, backed by a C++ enum.\n */\npublic typealias VideoOrientation = margelo.nitro.video.VideoOrientation\n\npublic extension VideoOrientation {\n  /**\n   * Get a VideoOrientation for the given String value, or\n   * return `nil` if the given value was invalid/unknown.\n   */\n  init?(fromString string: String) {\n    switch string {\n      case \"portrait\":\n        self = .portrait\n      case \"landscape\":\n        self = .landscape\n      case \"portrait-upside-down\":\n        self = .portraitUpsideDown\n      case \"landscape-left\":\n        self = .landscapeLeft\n      case \"landscape-right\":\n        self = .landscapeRight\n      case \"square\":\n        self = .square\n      case \"unknown\":\n        self = .unknown\n      default:\n        return nil\n    }\n  }\n\n  /**\n   * Get the String value this VideoOrientation represents.\n   */\n  var stringValue: String {\n    switch self {\n      case .portrait:\n        return \"portrait\"\n      case .landscape:\n        return \"landscape\"\n      case .portraitUpsideDown:\n        return \"portrait-upside-down\"\n      case .landscapeLeft:\n        return \"landscape-left\"\n      case .landscapeRight:\n        return \"landscape-right\"\n      case .square:\n        return \"square\"\n      case .unknown:\n        return \"unknown\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/VideoPlayerStatus.swift",
    "content": "///\n/// VideoPlayerStatus.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n/**\n * Represents the JS union `VideoPlayerStatus`, backed by a C++ enum.\n */\npublic typealias VideoPlayerStatus = margelo.nitro.video.VideoPlayerStatus\n\npublic extension VideoPlayerStatus {\n  /**\n   * Get a VideoPlayerStatus for the given String value, or\n   * return `nil` if the given value was invalid/unknown.\n   */\n  init?(fromString string: String) {\n    switch string {\n      case \"idle\":\n        self = .idle\n      case \"loading\":\n        self = .loading\n      case \"readyToPlay\":\n        self = .readytoplay\n      case \"error\":\n        self = .error\n      default:\n        return nil\n    }\n  }\n\n  /**\n   * Get the String value this VideoPlayerStatus represents.\n   */\n  var stringValue: String {\n    switch self {\n      case .idle:\n        return \"idle\"\n      case .loading:\n        return \"loading\"\n      case .readytoplay:\n        return \"readyToPlay\"\n      case .error:\n        return \"error\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/onLoadData.swift",
    "content": "///\n/// onLoadData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `onLoadData`, backed by a C++ struct.\n */\npublic typealias onLoadData = margelo.nitro.video.onLoadData\n\npublic extension onLoadData {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `onLoadData`.\n   */\n  init(currentTime: Double, duration: Double, height: Double, width: Double, orientation: VideoOrientation) {\n    self.init(currentTime, duration, height, width, orientation)\n  }\n\n  @inline(__always)\n  var currentTime: Double {\n    return self.__currentTime\n  }\n  \n  @inline(__always)\n  var duration: Double {\n    return self.__duration\n  }\n  \n  @inline(__always)\n  var height: Double {\n    return self.__height\n  }\n  \n  @inline(__always)\n  var width: Double {\n    return self.__width\n  }\n  \n  @inline(__always)\n  var orientation: VideoOrientation {\n    return self.__orientation\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/onLoadStartData.swift",
    "content": "///\n/// onLoadStartData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `onLoadStartData`, backed by a C++ struct.\n */\npublic typealias onLoadStartData = margelo.nitro.video.onLoadStartData\n\npublic extension onLoadStartData {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `onLoadStartData`.\n   */\n  init(sourceType: SourceType, source: (any HybridVideoPlayerSourceSpec)) {\n    self.init(sourceType, { () -> bridge.std__shared_ptr_HybridVideoPlayerSourceSpec_ in\n      let __cxxWrapped = source.getCxxWrapper()\n      return __cxxWrapped.getCxxPart()\n    }())\n  }\n\n  @inline(__always)\n  var sourceType: SourceType {\n    return self.__sourceType\n  }\n  \n  @inline(__always)\n  var source: (any HybridVideoPlayerSourceSpec) {\n    return { () -> any HybridVideoPlayerSourceSpec in\n      let __unsafePointer = bridge.get_std__shared_ptr_HybridVideoPlayerSourceSpec_(self.__source)\n      let __instance = HybridVideoPlayerSourceSpec_cxx.fromUnsafe(__unsafePointer)\n      return __instance.getHybridVideoPlayerSourceSpec()\n    }()\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/onPlaybackStateChangeData.swift",
    "content": "///\n/// onPlaybackStateChangeData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `onPlaybackStateChangeData`, backed by a C++ struct.\n */\npublic typealias onPlaybackStateChangeData = margelo.nitro.video.onPlaybackStateChangeData\n\npublic extension onPlaybackStateChangeData {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `onPlaybackStateChangeData`.\n   */\n  init(isPlaying: Bool, isBuffering: Bool) {\n    self.init(isPlaying, isBuffering)\n  }\n\n  @inline(__always)\n  var isPlaying: Bool {\n    return self.__isPlaying\n  }\n  \n  @inline(__always)\n  var isBuffering: Bool {\n    return self.__isBuffering\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/onProgressData.swift",
    "content": "///\n/// onProgressData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `onProgressData`, backed by a C++ struct.\n */\npublic typealias onProgressData = margelo.nitro.video.onProgressData\n\npublic extension onProgressData {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `onProgressData`.\n   */\n  init(currentTime: Double, bufferDuration: Double) {\n    self.init(currentTime, bufferDuration)\n  }\n\n  @inline(__always)\n  var currentTime: Double {\n    return self.__currentTime\n  }\n  \n  @inline(__always)\n  var bufferDuration: Double {\n    return self.__bufferDuration\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/ios/swift/onVolumeChangeData.swift",
    "content": "///\n/// onVolumeChangeData.swift\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\nimport NitroModules\n\n/**\n * Represents an instance of `onVolumeChangeData`, backed by a C++ struct.\n */\npublic typealias onVolumeChangeData = margelo.nitro.video.onVolumeChangeData\n\npublic extension onVolumeChangeData {\n  private typealias bridge = margelo.nitro.video.bridge.swift\n\n  /**\n   * Create a new instance of `onVolumeChangeData`.\n   */\n  init(volume: Double, muted: Bool) {\n    self.init(volume, muted)\n  }\n\n  @inline(__always)\n  var volume: Double {\n    return self.__volume\n  }\n  \n  @inline(__always)\n  var muted: Bool {\n    return self.__muted\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/BandwidthData.hpp",
    "content": "///\n/// BandwidthData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (BandwidthData).\n   */\n  struct BandwidthData final {\n  public:\n    double bitrate     SWIFT_PRIVATE;\n    std::optional<double> width     SWIFT_PRIVATE;\n    std::optional<double> height     SWIFT_PRIVATE;\n\n  public:\n    BandwidthData() = default;\n    explicit BandwidthData(double bitrate, std::optional<double> width, std::optional<double> height): bitrate(bitrate), width(width), height(height) {}\n\n  public:\n    friend bool operator==(const BandwidthData& lhs, const BandwidthData& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ BandwidthData <> JS BandwidthData (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::BandwidthData> final {\n    static inline margelo::nitro::video::BandwidthData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::BandwidthData(\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bitrate\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"width\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"height\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::BandwidthData& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"bitrate\"), JSIConverter<double>::toJSI(runtime, arg.bitrate));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"width\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.width));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"height\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.height));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bitrate\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"width\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"height\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/BufferConfig.hpp",
    "content": "///\n/// BufferConfig.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `LivePlaybackParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct LivePlaybackParams; }\n// Forward declaration of `Resolution` to properly resolve imports.\nnamespace margelo::nitro::video { struct Resolution; }\n\n#include \"LivePlaybackParams.hpp\"\n#include <optional>\n#include \"Resolution.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (BufferConfig).\n   */\n  struct BufferConfig final {\n  public:\n    std::optional<LivePlaybackParams> livePlayback     SWIFT_PRIVATE;\n    std::optional<double> minBufferMs     SWIFT_PRIVATE;\n    std::optional<double> maxBufferMs     SWIFT_PRIVATE;\n    std::optional<double> bufferForPlaybackMs     SWIFT_PRIVATE;\n    std::optional<double> bufferForPlaybackAfterRebufferMs     SWIFT_PRIVATE;\n    std::optional<double> backBufferDurationMs     SWIFT_PRIVATE;\n    std::optional<double> preferredForwardBufferDurationMs     SWIFT_PRIVATE;\n    std::optional<double> preferredPeakBitRate     SWIFT_PRIVATE;\n    std::optional<Resolution> preferredMaximumResolution     SWIFT_PRIVATE;\n    std::optional<double> preferredPeakBitRateForExpensiveNetworks     SWIFT_PRIVATE;\n    std::optional<Resolution> preferredMaximumResolutionForExpensiveNetworks     SWIFT_PRIVATE;\n\n  public:\n    BufferConfig() = default;\n    explicit BufferConfig(std::optional<LivePlaybackParams> livePlayback, std::optional<double> minBufferMs, std::optional<double> maxBufferMs, std::optional<double> bufferForPlaybackMs, std::optional<double> bufferForPlaybackAfterRebufferMs, std::optional<double> backBufferDurationMs, std::optional<double> preferredForwardBufferDurationMs, std::optional<double> preferredPeakBitRate, std::optional<Resolution> preferredMaximumResolution, std::optional<double> preferredPeakBitRateForExpensiveNetworks, std::optional<Resolution> preferredMaximumResolutionForExpensiveNetworks): livePlayback(livePlayback), minBufferMs(minBufferMs), maxBufferMs(maxBufferMs), bufferForPlaybackMs(bufferForPlaybackMs), bufferForPlaybackAfterRebufferMs(bufferForPlaybackAfterRebufferMs), backBufferDurationMs(backBufferDurationMs), preferredForwardBufferDurationMs(preferredForwardBufferDurationMs), preferredPeakBitRate(preferredPeakBitRate), preferredMaximumResolution(preferredMaximumResolution), preferredPeakBitRateForExpensiveNetworks(preferredPeakBitRateForExpensiveNetworks), preferredMaximumResolutionForExpensiveNetworks(preferredMaximumResolutionForExpensiveNetworks) {}\n\n  public:\n    friend bool operator==(const BufferConfig& lhs, const BufferConfig& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ BufferConfig <> JS BufferConfig (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::BufferConfig> final {\n    static inline margelo::nitro::video::BufferConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::BufferConfig(\n        JSIConverter<std::optional<margelo::nitro::video::LivePlaybackParams>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"livePlayback\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"minBufferMs\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"maxBufferMs\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bufferForPlaybackMs\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bufferForPlaybackAfterRebufferMs\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"backBufferDurationMs\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredForwardBufferDurationMs\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredPeakBitRate\"))),\n        JSIConverter<std::optional<margelo::nitro::video::Resolution>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredMaximumResolution\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredPeakBitRateForExpensiveNetworks\"))),\n        JSIConverter<std::optional<margelo::nitro::video::Resolution>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredMaximumResolutionForExpensiveNetworks\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::BufferConfig& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"livePlayback\"), JSIConverter<std::optional<margelo::nitro::video::LivePlaybackParams>>::toJSI(runtime, arg.livePlayback));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"minBufferMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.minBufferMs));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"maxBufferMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.maxBufferMs));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"bufferForPlaybackMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.bufferForPlaybackMs));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"bufferForPlaybackAfterRebufferMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.bufferForPlaybackAfterRebufferMs));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"backBufferDurationMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.backBufferDurationMs));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"preferredForwardBufferDurationMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.preferredForwardBufferDurationMs));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"preferredPeakBitRate\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.preferredPeakBitRate));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"preferredMaximumResolution\"), JSIConverter<std::optional<margelo::nitro::video::Resolution>>::toJSI(runtime, arg.preferredMaximumResolution));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"preferredPeakBitRateForExpensiveNetworks\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.preferredPeakBitRateForExpensiveNetworks));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"preferredMaximumResolutionForExpensiveNetworks\"), JSIConverter<std::optional<margelo::nitro::video::Resolution>>::toJSI(runtime, arg.preferredMaximumResolutionForExpensiveNetworks));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::optional<margelo::nitro::video::LivePlaybackParams>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"livePlayback\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"minBufferMs\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"maxBufferMs\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bufferForPlaybackMs\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bufferForPlaybackAfterRebufferMs\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"backBufferDurationMs\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredForwardBufferDurationMs\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredPeakBitRate\")))) return false;\n      if (!JSIConverter<std::optional<margelo::nitro::video::Resolution>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredMaximumResolution\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredPeakBitRateForExpensiveNetworks\")))) return false;\n      if (!JSIConverter<std::optional<margelo::nitro::video::Resolution>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"preferredMaximumResolutionForExpensiveNetworks\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/CustomVideoMetadata.hpp",
    "content": "///\n/// CustomVideoMetadata.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n#include <string>\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (CustomVideoMetadata).\n   */\n  struct CustomVideoMetadata final {\n  public:\n    std::optional<std::string> title     SWIFT_PRIVATE;\n    std::optional<std::string> subtitle     SWIFT_PRIVATE;\n    std::optional<std::string> description     SWIFT_PRIVATE;\n    std::optional<std::string> artist     SWIFT_PRIVATE;\n    std::optional<std::string> imageUri     SWIFT_PRIVATE;\n\n  public:\n    CustomVideoMetadata() = default;\n    explicit CustomVideoMetadata(std::optional<std::string> title, std::optional<std::string> subtitle, std::optional<std::string> description, std::optional<std::string> artist, std::optional<std::string> imageUri): title(title), subtitle(subtitle), description(description), artist(artist), imageUri(imageUri) {}\n\n  public:\n    friend bool operator==(const CustomVideoMetadata& lhs, const CustomVideoMetadata& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ CustomVideoMetadata <> JS CustomVideoMetadata (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::CustomVideoMetadata> final {\n    static inline margelo::nitro::video::CustomVideoMetadata fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::CustomVideoMetadata(\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"title\"))),\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"subtitle\"))),\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"description\"))),\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"artist\"))),\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"imageUri\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::CustomVideoMetadata& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"title\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.title));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"subtitle\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.subtitle));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"description\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.description));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"artist\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.artist));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"imageUri\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.imageUri));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"title\")))) return false;\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"subtitle\")))) return false;\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"description\")))) return false;\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"artist\")))) return false;\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"imageUri\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.cpp",
    "content": "///\n/// HybridVideoPlayerEventEmitterSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerEventEmitterSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  void HybridVideoPlayerEventEmitterSpec::loadHybridMethods() {\n    // load base methods/properties\n    HybridObject::loadHybridMethods();\n    // load custom methods/properties\n    registerHybrids(this, [](Prototype& prototype) {\n      prototype.registerHybridMethod(\"addOnAudioBecomingNoisyListener\", &HybridVideoPlayerEventEmitterSpec::addOnAudioBecomingNoisyListener);\n      prototype.registerHybridMethod(\"addOnAudioFocusChangeListener\", &HybridVideoPlayerEventEmitterSpec::addOnAudioFocusChangeListener);\n      prototype.registerHybridMethod(\"addOnBandwidthUpdateListener\", &HybridVideoPlayerEventEmitterSpec::addOnBandwidthUpdateListener);\n      prototype.registerHybridMethod(\"addOnBufferListener\", &HybridVideoPlayerEventEmitterSpec::addOnBufferListener);\n      prototype.registerHybridMethod(\"addOnControlsVisibleChangeListener\", &HybridVideoPlayerEventEmitterSpec::addOnControlsVisibleChangeListener);\n      prototype.registerHybridMethod(\"addOnEndListener\", &HybridVideoPlayerEventEmitterSpec::addOnEndListener);\n      prototype.registerHybridMethod(\"addOnExternalPlaybackChangeListener\", &HybridVideoPlayerEventEmitterSpec::addOnExternalPlaybackChangeListener);\n      prototype.registerHybridMethod(\"addOnLoadListener\", &HybridVideoPlayerEventEmitterSpec::addOnLoadListener);\n      prototype.registerHybridMethod(\"addOnLoadStartListener\", &HybridVideoPlayerEventEmitterSpec::addOnLoadStartListener);\n      prototype.registerHybridMethod(\"addOnPlaybackStateChangeListener\", &HybridVideoPlayerEventEmitterSpec::addOnPlaybackStateChangeListener);\n      prototype.registerHybridMethod(\"addOnPlaybackRateChangeListener\", &HybridVideoPlayerEventEmitterSpec::addOnPlaybackRateChangeListener);\n      prototype.registerHybridMethod(\"addOnProgressListener\", &HybridVideoPlayerEventEmitterSpec::addOnProgressListener);\n      prototype.registerHybridMethod(\"addOnReadyToDisplayListener\", &HybridVideoPlayerEventEmitterSpec::addOnReadyToDisplayListener);\n      prototype.registerHybridMethod(\"addOnSeekListener\", &HybridVideoPlayerEventEmitterSpec::addOnSeekListener);\n      prototype.registerHybridMethod(\"addOnStatusChangeListener\", &HybridVideoPlayerEventEmitterSpec::addOnStatusChangeListener);\n      prototype.registerHybridMethod(\"addOnTimedMetadataListener\", &HybridVideoPlayerEventEmitterSpec::addOnTimedMetadataListener);\n      prototype.registerHybridMethod(\"addOnTextTrackDataChangedListener\", &HybridVideoPlayerEventEmitterSpec::addOnTextTrackDataChangedListener);\n      prototype.registerHybridMethod(\"addOnTrackChangeListener\", &HybridVideoPlayerEventEmitterSpec::addOnTrackChangeListener);\n      prototype.registerHybridMethod(\"addOnVolumeChangeListener\", &HybridVideoPlayerEventEmitterSpec::addOnVolumeChangeListener);\n      prototype.registerHybridMethod(\"clearAllListeners\", &HybridVideoPlayerEventEmitterSpec::clearAllListeners);\n    });\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerEventEmitterSpec.hpp",
    "content": "///\n/// HybridVideoPlayerEventEmitterSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/HybridObject.hpp>)\n#include <NitroModules/HybridObject.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `ListenerSubscription` to properly resolve imports.\nnamespace margelo::nitro::video { struct ListenerSubscription; }\n// Forward declaration of `BandwidthData` to properly resolve imports.\nnamespace margelo::nitro::video { struct BandwidthData; }\n// Forward declaration of `onLoadData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadData; }\n// Forward declaration of `onLoadStartData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onLoadStartData; }\n// Forward declaration of `onPlaybackStateChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onPlaybackStateChangeData; }\n// Forward declaration of `onProgressData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onProgressData; }\n// Forward declaration of `VideoPlayerStatus` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoPlayerStatus; }\n// Forward declaration of `TimedMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadata; }\n// Forward declaration of `TextTrack` to properly resolve imports.\nnamespace margelo::nitro::video { struct TextTrack; }\n// Forward declaration of `onVolumeChangeData` to properly resolve imports.\nnamespace margelo::nitro::video { struct onVolumeChangeData; }\n\n#include \"ListenerSubscription.hpp\"\n#include <functional>\n#include \"BandwidthData.hpp\"\n#include \"onLoadData.hpp\"\n#include \"onLoadStartData.hpp\"\n#include \"onPlaybackStateChangeData.hpp\"\n#include \"onProgressData.hpp\"\n#include \"VideoPlayerStatus.hpp\"\n#include \"TimedMetadata.hpp\"\n#include <string>\n#include <vector>\n#include <NitroModules/Null.hpp>\n#include \"TextTrack.hpp\"\n#include <variant>\n#include <optional>\n#include \"onVolumeChangeData.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace margelo::nitro;\n\n  /**\n   * An abstract base class for `VideoPlayerEventEmitter`\n   * Inherit this class to create instances of `HybridVideoPlayerEventEmitterSpec` in C++.\n   * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.\n   * @example\n   * ```cpp\n   * class HybridVideoPlayerEventEmitter: public HybridVideoPlayerEventEmitterSpec {\n   * public:\n   *   HybridVideoPlayerEventEmitter(...): HybridObject(TAG) { ... }\n   *   // ...\n   * };\n   * ```\n   */\n  class HybridVideoPlayerEventEmitterSpec: public virtual HybridObject {\n    public:\n      // Constructor\n      explicit HybridVideoPlayerEventEmitterSpec(): HybridObject(TAG) { }\n\n      // Destructor\n      ~HybridVideoPlayerEventEmitterSpec() override = default;\n\n    public:\n      // Properties\n      \n\n    public:\n      // Methods\n      virtual ListenerSubscription addOnAudioBecomingNoisyListener(const std::function<void()>& listener) = 0;\n      virtual ListenerSubscription addOnAudioFocusChangeListener(const std::function<void(bool /* hasAudioFocus */)>& listener) = 0;\n      virtual ListenerSubscription addOnBandwidthUpdateListener(const std::function<void(const BandwidthData& /* data */)>& listener) = 0;\n      virtual ListenerSubscription addOnBufferListener(const std::function<void(bool /* buffering */)>& listener) = 0;\n      virtual ListenerSubscription addOnControlsVisibleChangeListener(const std::function<void(bool /* visible */)>& listener) = 0;\n      virtual ListenerSubscription addOnEndListener(const std::function<void()>& listener) = 0;\n      virtual ListenerSubscription addOnExternalPlaybackChangeListener(const std::function<void(bool /* externalPlaybackActive */)>& listener) = 0;\n      virtual ListenerSubscription addOnLoadListener(const std::function<void(const onLoadData& /* data */)>& listener) = 0;\n      virtual ListenerSubscription addOnLoadStartListener(const std::function<void(const onLoadStartData& /* data */)>& listener) = 0;\n      virtual ListenerSubscription addOnPlaybackStateChangeListener(const std::function<void(const onPlaybackStateChangeData& /* data */)>& listener) = 0;\n      virtual ListenerSubscription addOnPlaybackRateChangeListener(const std::function<void(double /* rate */)>& listener) = 0;\n      virtual ListenerSubscription addOnProgressListener(const std::function<void(const onProgressData& /* data */)>& listener) = 0;\n      virtual ListenerSubscription addOnReadyToDisplayListener(const std::function<void()>& listener) = 0;\n      virtual ListenerSubscription addOnSeekListener(const std::function<void(double /* position */)>& listener) = 0;\n      virtual ListenerSubscription addOnStatusChangeListener(const std::function<void(VideoPlayerStatus /* status */)>& listener) = 0;\n      virtual ListenerSubscription addOnTimedMetadataListener(const std::function<void(const TimedMetadata& /* data */)>& listener) = 0;\n      virtual ListenerSubscription addOnTextTrackDataChangedListener(const std::function<void(const std::vector<std::string>& /* data */)>& listener) = 0;\n      virtual ListenerSubscription addOnTrackChangeListener(const std::function<void(const std::optional<std::variant<nitro::NullType, TextTrack>>& /* track */)>& listener) = 0;\n      virtual ListenerSubscription addOnVolumeChangeListener(const std::function<void(const onVolumeChangeData& /* data */)>& listener) = 0;\n      virtual void clearAllListeners() = 0;\n\n    protected:\n      // Hybrid Setup\n      void loadHybridMethods() override;\n\n    protected:\n      // Tag for logging\n      static constexpr auto TAG = \"VideoPlayerEventEmitter\";\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.cpp",
    "content": "///\n/// HybridVideoPlayerFactorySpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerFactorySpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  void HybridVideoPlayerFactorySpec::loadHybridMethods() {\n    // load base methods/properties\n    HybridObject::loadHybridMethods();\n    // load custom methods/properties\n    registerHybrids(this, [](Prototype& prototype) {\n      prototype.registerHybridMethod(\"createPlayer\", &HybridVideoPlayerFactorySpec::createPlayer);\n    });\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerFactorySpec.hpp",
    "content": "///\n/// HybridVideoPlayerFactorySpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/HybridObject.hpp>)\n#include <NitroModules/HybridObject.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSpec; }\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n\n#include <memory>\n#include \"HybridVideoPlayerSpec.hpp\"\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace margelo::nitro;\n\n  /**\n   * An abstract base class for `VideoPlayerFactory`\n   * Inherit this class to create instances of `HybridVideoPlayerFactorySpec` in C++.\n   * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.\n   * @example\n   * ```cpp\n   * class HybridVideoPlayerFactory: public HybridVideoPlayerFactorySpec {\n   * public:\n   *   HybridVideoPlayerFactory(...): HybridObject(TAG) { ... }\n   *   // ...\n   * };\n   * ```\n   */\n  class HybridVideoPlayerFactorySpec: public virtual HybridObject {\n    public:\n      // Constructor\n      explicit HybridVideoPlayerFactorySpec(): HybridObject(TAG) { }\n\n      // Destructor\n      ~HybridVideoPlayerFactorySpec() override = default;\n\n    public:\n      // Properties\n      \n\n    public:\n      // Methods\n      virtual std::shared_ptr<HybridVideoPlayerSpec> createPlayer(const std::shared_ptr<HybridVideoPlayerSourceSpec>& source) = 0;\n\n    protected:\n      // Hybrid Setup\n      void loadHybridMethods() override;\n\n    protected:\n      // Tag for logging\n      static constexpr auto TAG = \"VideoPlayerFactory\";\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.cpp",
    "content": "///\n/// HybridVideoPlayerSourceFactorySpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerSourceFactorySpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  void HybridVideoPlayerSourceFactorySpec::loadHybridMethods() {\n    // load base methods/properties\n    HybridObject::loadHybridMethods();\n    // load custom methods/properties\n    registerHybrids(this, [](Prototype& prototype) {\n      prototype.registerHybridMethod(\"fromUri\", &HybridVideoPlayerSourceFactorySpec::fromUri);\n      prototype.registerHybridMethod(\"fromVideoConfig\", &HybridVideoPlayerSourceFactorySpec::fromVideoConfig);\n    });\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerSourceFactorySpec.hpp",
    "content": "///\n/// HybridVideoPlayerSourceFactorySpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/HybridObject.hpp>)\n#include <NitroModules/HybridObject.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `NativeVideoConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeVideoConfig; }\n\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include <string>\n#include \"NativeVideoConfig.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace margelo::nitro;\n\n  /**\n   * An abstract base class for `VideoPlayerSourceFactory`\n   * Inherit this class to create instances of `HybridVideoPlayerSourceFactorySpec` in C++.\n   * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.\n   * @example\n   * ```cpp\n   * class HybridVideoPlayerSourceFactory: public HybridVideoPlayerSourceFactorySpec {\n   * public:\n   *   HybridVideoPlayerSourceFactory(...): HybridObject(TAG) { ... }\n   *   // ...\n   * };\n   * ```\n   */\n  class HybridVideoPlayerSourceFactorySpec: public virtual HybridObject {\n    public:\n      // Constructor\n      explicit HybridVideoPlayerSourceFactorySpec(): HybridObject(TAG) { }\n\n      // Destructor\n      ~HybridVideoPlayerSourceFactorySpec() override = default;\n\n    public:\n      // Properties\n      \n\n    public:\n      // Methods\n      virtual std::shared_ptr<HybridVideoPlayerSourceSpec> fromUri(const std::string& uri) = 0;\n      virtual std::shared_ptr<HybridVideoPlayerSourceSpec> fromVideoConfig(const NativeVideoConfig& config) = 0;\n\n    protected:\n      // Hybrid Setup\n      void loadHybridMethods() override;\n\n    protected:\n      // Tag for logging\n      static constexpr auto TAG = \"VideoPlayerSourceFactory\";\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.cpp",
    "content": "///\n/// HybridVideoPlayerSourceSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  void HybridVideoPlayerSourceSpec::loadHybridMethods() {\n    // load base methods/properties\n    HybridObject::loadHybridMethods();\n    // load custom methods/properties\n    registerHybrids(this, [](Prototype& prototype) {\n      prototype.registerHybridGetter(\"uri\", &HybridVideoPlayerSourceSpec::getUri);\n      prototype.registerHybridGetter(\"config\", &HybridVideoPlayerSourceSpec::getConfig);\n      prototype.registerHybridMethod(\"getAssetInformationAsync\", &HybridVideoPlayerSourceSpec::getAssetInformationAsync);\n    });\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerSourceSpec.hpp",
    "content": "///\n/// HybridVideoPlayerSourceSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/HybridObject.hpp>)\n#include <NitroModules/HybridObject.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `NativeVideoConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeVideoConfig; }\n// Forward declaration of `VideoInformation` to properly resolve imports.\nnamespace margelo::nitro::video { struct VideoInformation; }\n\n#include <string>\n#include \"NativeVideoConfig.hpp\"\n#include \"VideoInformation.hpp\"\n#include <NitroModules/Promise.hpp>\n\nnamespace margelo::nitro::video {\n\n  using namespace margelo::nitro;\n\n  /**\n   * An abstract base class for `VideoPlayerSource`\n   * Inherit this class to create instances of `HybridVideoPlayerSourceSpec` in C++.\n   * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.\n   * @example\n   * ```cpp\n   * class HybridVideoPlayerSource: public HybridVideoPlayerSourceSpec {\n   * public:\n   *   HybridVideoPlayerSource(...): HybridObject(TAG) { ... }\n   *   // ...\n   * };\n   * ```\n   */\n  class HybridVideoPlayerSourceSpec: public virtual HybridObject {\n    public:\n      // Constructor\n      explicit HybridVideoPlayerSourceSpec(): HybridObject(TAG) { }\n\n      // Destructor\n      ~HybridVideoPlayerSourceSpec() override = default;\n\n    public:\n      // Properties\n      virtual std::string getUri() = 0;\n      virtual NativeVideoConfig getConfig() = 0;\n\n    public:\n      // Methods\n      virtual std::shared_ptr<Promise<VideoInformation>> getAssetInformationAsync() = 0;\n\n    protected:\n      // Hybrid Setup\n      void loadHybridMethods() override;\n\n    protected:\n      // Tag for logging\n      static constexpr auto TAG = \"VideoPlayerSource\";\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerSpec.cpp",
    "content": "///\n/// HybridVideoPlayerSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoPlayerSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  void HybridVideoPlayerSpec::loadHybridMethods() {\n    // load base methods/properties\n    HybridObject::loadHybridMethods();\n    // load custom methods/properties\n    registerHybrids(this, [](Prototype& prototype) {\n      prototype.registerHybridGetter(\"source\", &HybridVideoPlayerSpec::getSource);\n      prototype.registerHybridGetter(\"eventEmitter\", &HybridVideoPlayerSpec::getEventEmitter);\n      prototype.registerHybridGetter(\"showNotificationControls\", &HybridVideoPlayerSpec::getShowNotificationControls);\n      prototype.registerHybridSetter(\"showNotificationControls\", &HybridVideoPlayerSpec::setShowNotificationControls);\n      prototype.registerHybridGetter(\"status\", &HybridVideoPlayerSpec::getStatus);\n      prototype.registerHybridGetter(\"duration\", &HybridVideoPlayerSpec::getDuration);\n      prototype.registerHybridGetter(\"volume\", &HybridVideoPlayerSpec::getVolume);\n      prototype.registerHybridSetter(\"volume\", &HybridVideoPlayerSpec::setVolume);\n      prototype.registerHybridGetter(\"currentTime\", &HybridVideoPlayerSpec::getCurrentTime);\n      prototype.registerHybridSetter(\"currentTime\", &HybridVideoPlayerSpec::setCurrentTime);\n      prototype.registerHybridGetter(\"muted\", &HybridVideoPlayerSpec::getMuted);\n      prototype.registerHybridSetter(\"muted\", &HybridVideoPlayerSpec::setMuted);\n      prototype.registerHybridGetter(\"loop\", &HybridVideoPlayerSpec::getLoop);\n      prototype.registerHybridSetter(\"loop\", &HybridVideoPlayerSpec::setLoop);\n      prototype.registerHybridGetter(\"rate\", &HybridVideoPlayerSpec::getRate);\n      prototype.registerHybridSetter(\"rate\", &HybridVideoPlayerSpec::setRate);\n      prototype.registerHybridGetter(\"mixAudioMode\", &HybridVideoPlayerSpec::getMixAudioMode);\n      prototype.registerHybridSetter(\"mixAudioMode\", &HybridVideoPlayerSpec::setMixAudioMode);\n      prototype.registerHybridGetter(\"ignoreSilentSwitchMode\", &HybridVideoPlayerSpec::getIgnoreSilentSwitchMode);\n      prototype.registerHybridSetter(\"ignoreSilentSwitchMode\", &HybridVideoPlayerSpec::setIgnoreSilentSwitchMode);\n      prototype.registerHybridGetter(\"playInBackground\", &HybridVideoPlayerSpec::getPlayInBackground);\n      prototype.registerHybridSetter(\"playInBackground\", &HybridVideoPlayerSpec::setPlayInBackground);\n      prototype.registerHybridGetter(\"playWhenInactive\", &HybridVideoPlayerSpec::getPlayWhenInactive);\n      prototype.registerHybridSetter(\"playWhenInactive\", &HybridVideoPlayerSpec::setPlayWhenInactive);\n      prototype.registerHybridGetter(\"isPlaying\", &HybridVideoPlayerSpec::getIsPlaying);\n      prototype.registerHybridGetter(\"selectedTrack\", &HybridVideoPlayerSpec::getSelectedTrack);\n      prototype.registerHybridMethod(\"replaceSourceAsync\", &HybridVideoPlayerSpec::replaceSourceAsync);\n      prototype.registerHybridMethod(\"getAvailableTextTracks\", &HybridVideoPlayerSpec::getAvailableTextTracks);\n      prototype.registerHybridMethod(\"selectTextTrack\", &HybridVideoPlayerSpec::selectTextTrack);\n      prototype.registerHybridMethod(\"release\", &HybridVideoPlayerSpec::release);\n      prototype.registerHybridMethod(\"initialize\", &HybridVideoPlayerSpec::initialize);\n      prototype.registerHybridMethod(\"preload\", &HybridVideoPlayerSpec::preload);\n      prototype.registerHybridMethod(\"play\", &HybridVideoPlayerSpec::play);\n      prototype.registerHybridMethod(\"pause\", &HybridVideoPlayerSpec::pause);\n      prototype.registerHybridMethod(\"seekBy\", &HybridVideoPlayerSpec::seekBy);\n      prototype.registerHybridMethod(\"seekTo\", &HybridVideoPlayerSpec::seekTo);\n    });\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoPlayerSpec.hpp",
    "content": "///\n/// HybridVideoPlayerSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/HybridObject.hpp>)\n#include <NitroModules/HybridObject.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n// Forward declaration of `HybridVideoPlayerEventEmitterSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerEventEmitterSpec; }\n// Forward declaration of `VideoPlayerStatus` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoPlayerStatus; }\n// Forward declaration of `MixAudioMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class MixAudioMode; }\n// Forward declaration of `IgnoreSilentSwitchMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class IgnoreSilentSwitchMode; }\n// Forward declaration of `TextTrack` to properly resolve imports.\nnamespace margelo::nitro::video { struct TextTrack; }\n\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n#include \"HybridVideoPlayerEventEmitterSpec.hpp\"\n#include \"VideoPlayerStatus.hpp\"\n#include \"MixAudioMode.hpp\"\n#include \"IgnoreSilentSwitchMode.hpp\"\n#include \"TextTrack.hpp\"\n#include <optional>\n#include <NitroModules/Promise.hpp>\n#include <NitroModules/Null.hpp>\n#include <variant>\n#include <vector>\n\nnamespace margelo::nitro::video {\n\n  using namespace margelo::nitro;\n\n  /**\n   * An abstract base class for `VideoPlayer`\n   * Inherit this class to create instances of `HybridVideoPlayerSpec` in C++.\n   * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.\n   * @example\n   * ```cpp\n   * class HybridVideoPlayer: public HybridVideoPlayerSpec {\n   * public:\n   *   HybridVideoPlayer(...): HybridObject(TAG) { ... }\n   *   // ...\n   * };\n   * ```\n   */\n  class HybridVideoPlayerSpec: public virtual HybridObject {\n    public:\n      // Constructor\n      explicit HybridVideoPlayerSpec(): HybridObject(TAG) { }\n\n      // Destructor\n      ~HybridVideoPlayerSpec() override = default;\n\n    public:\n      // Properties\n      virtual std::shared_ptr<HybridVideoPlayerSourceSpec> getSource() = 0;\n      virtual std::shared_ptr<HybridVideoPlayerEventEmitterSpec> getEventEmitter() = 0;\n      virtual bool getShowNotificationControls() = 0;\n      virtual void setShowNotificationControls(bool showNotificationControls) = 0;\n      virtual VideoPlayerStatus getStatus() = 0;\n      virtual double getDuration() = 0;\n      virtual double getVolume() = 0;\n      virtual void setVolume(double volume) = 0;\n      virtual double getCurrentTime() = 0;\n      virtual void setCurrentTime(double currentTime) = 0;\n      virtual bool getMuted() = 0;\n      virtual void setMuted(bool muted) = 0;\n      virtual bool getLoop() = 0;\n      virtual void setLoop(bool loop) = 0;\n      virtual double getRate() = 0;\n      virtual void setRate(double rate) = 0;\n      virtual MixAudioMode getMixAudioMode() = 0;\n      virtual void setMixAudioMode(MixAudioMode mixAudioMode) = 0;\n      virtual IgnoreSilentSwitchMode getIgnoreSilentSwitchMode() = 0;\n      virtual void setIgnoreSilentSwitchMode(IgnoreSilentSwitchMode ignoreSilentSwitchMode) = 0;\n      virtual bool getPlayInBackground() = 0;\n      virtual void setPlayInBackground(bool playInBackground) = 0;\n      virtual bool getPlayWhenInactive() = 0;\n      virtual void setPlayWhenInactive(bool playWhenInactive) = 0;\n      virtual bool getIsPlaying() = 0;\n      virtual std::optional<TextTrack> getSelectedTrack() = 0;\n\n    public:\n      // Methods\n      virtual std::shared_ptr<Promise<void>> replaceSourceAsync(const std::optional<std::variant<nitro::NullType, std::shared_ptr<HybridVideoPlayerSourceSpec>>>& source) = 0;\n      virtual std::vector<TextTrack> getAvailableTextTracks() = 0;\n      virtual void selectTextTrack(const std::optional<std::variant<nitro::NullType, TextTrack>>& textTrack) = 0;\n      virtual void release() = 0;\n      virtual std::shared_ptr<Promise<void>> initialize() = 0;\n      virtual std::shared_ptr<Promise<void>> preload() = 0;\n      virtual void play() = 0;\n      virtual void pause() = 0;\n      virtual void seekBy(double time) = 0;\n      virtual void seekTo(double time) = 0;\n\n    protected:\n      // Hybrid Setup\n      void loadHybridMethods() override;\n\n    protected:\n      // Tag for logging\n      static constexpr auto TAG = \"VideoPlayer\";\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.cpp",
    "content": "///\n/// HybridVideoViewViewManagerFactorySpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoViewViewManagerFactorySpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  void HybridVideoViewViewManagerFactorySpec::loadHybridMethods() {\n    // load base methods/properties\n    HybridObject::loadHybridMethods();\n    // load custom methods/properties\n    registerHybrids(this, [](Prototype& prototype) {\n      prototype.registerHybridMethod(\"createViewManager\", &HybridVideoViewViewManagerFactorySpec::createViewManager);\n    });\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoViewViewManagerFactorySpec.hpp",
    "content": "///\n/// HybridVideoViewViewManagerFactorySpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/HybridObject.hpp>)\n#include <NitroModules/HybridObject.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `HybridVideoViewViewManagerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoViewViewManagerSpec; }\n\n#include <memory>\n#include \"HybridVideoViewViewManagerSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  using namespace margelo::nitro;\n\n  /**\n   * An abstract base class for `VideoViewViewManagerFactory`\n   * Inherit this class to create instances of `HybridVideoViewViewManagerFactorySpec` in C++.\n   * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.\n   * @example\n   * ```cpp\n   * class HybridVideoViewViewManagerFactory: public HybridVideoViewViewManagerFactorySpec {\n   * public:\n   *   HybridVideoViewViewManagerFactory(...): HybridObject(TAG) { ... }\n   *   // ...\n   * };\n   * ```\n   */\n  class HybridVideoViewViewManagerFactorySpec: public virtual HybridObject {\n    public:\n      // Constructor\n      explicit HybridVideoViewViewManagerFactorySpec(): HybridObject(TAG) { }\n\n      // Destructor\n      ~HybridVideoViewViewManagerFactorySpec() override = default;\n\n    public:\n      // Properties\n      \n\n    public:\n      // Methods\n      virtual std::shared_ptr<HybridVideoViewViewManagerSpec> createViewManager(double nitroId) = 0;\n\n    protected:\n      // Hybrid Setup\n      void loadHybridMethods() override;\n\n    protected:\n      // Tag for logging\n      static constexpr auto TAG = \"VideoViewViewManagerFactory\";\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.cpp",
    "content": "///\n/// HybridVideoViewViewManagerSpec.cpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#include \"HybridVideoViewViewManagerSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  void HybridVideoViewViewManagerSpec::loadHybridMethods() {\n    // load base methods/properties\n    HybridObject::loadHybridMethods();\n    // load custom methods/properties\n    registerHybrids(this, [](Prototype& prototype) {\n      prototype.registerHybridGetter(\"player\", &HybridVideoViewViewManagerSpec::getPlayer);\n      prototype.registerHybridSetter(\"player\", &HybridVideoViewViewManagerSpec::setPlayer);\n      prototype.registerHybridGetter(\"controls\", &HybridVideoViewViewManagerSpec::getControls);\n      prototype.registerHybridSetter(\"controls\", &HybridVideoViewViewManagerSpec::setControls);\n      prototype.registerHybridGetter(\"pictureInPicture\", &HybridVideoViewViewManagerSpec::getPictureInPicture);\n      prototype.registerHybridSetter(\"pictureInPicture\", &HybridVideoViewViewManagerSpec::setPictureInPicture);\n      prototype.registerHybridGetter(\"autoEnterPictureInPicture\", &HybridVideoViewViewManagerSpec::getAutoEnterPictureInPicture);\n      prototype.registerHybridSetter(\"autoEnterPictureInPicture\", &HybridVideoViewViewManagerSpec::setAutoEnterPictureInPicture);\n      prototype.registerHybridGetter(\"resizeMode\", &HybridVideoViewViewManagerSpec::getResizeMode);\n      prototype.registerHybridSetter(\"resizeMode\", &HybridVideoViewViewManagerSpec::setResizeMode);\n      prototype.registerHybridGetter(\"keepScreenAwake\", &HybridVideoViewViewManagerSpec::getKeepScreenAwake);\n      prototype.registerHybridSetter(\"keepScreenAwake\", &HybridVideoViewViewManagerSpec::setKeepScreenAwake);\n      prototype.registerHybridGetter(\"surfaceType\", &HybridVideoViewViewManagerSpec::getSurfaceType);\n      prototype.registerHybridSetter(\"surfaceType\", &HybridVideoViewViewManagerSpec::setSurfaceType);\n      prototype.registerHybridMethod(\"enterFullscreen\", &HybridVideoViewViewManagerSpec::enterFullscreen);\n      prototype.registerHybridMethod(\"exitFullscreen\", &HybridVideoViewViewManagerSpec::exitFullscreen);\n      prototype.registerHybridMethod(\"enterPictureInPicture\", &HybridVideoViewViewManagerSpec::enterPictureInPicture);\n      prototype.registerHybridMethod(\"exitPictureInPicture\", &HybridVideoViewViewManagerSpec::exitPictureInPicture);\n      prototype.registerHybridMethod(\"canEnterPictureInPicture\", &HybridVideoViewViewManagerSpec::canEnterPictureInPicture);\n      prototype.registerHybridMethod(\"addOnPictureInPictureChangeListener\", &HybridVideoViewViewManagerSpec::addOnPictureInPictureChangeListener);\n      prototype.registerHybridMethod(\"addOnFullscreenChangeListener\", &HybridVideoViewViewManagerSpec::addOnFullscreenChangeListener);\n      prototype.registerHybridMethod(\"addWillEnterFullscreenListener\", &HybridVideoViewViewManagerSpec::addWillEnterFullscreenListener);\n      prototype.registerHybridMethod(\"addWillExitFullscreenListener\", &HybridVideoViewViewManagerSpec::addWillExitFullscreenListener);\n      prototype.registerHybridMethod(\"addWillEnterPictureInPictureListener\", &HybridVideoViewViewManagerSpec::addWillEnterPictureInPictureListener);\n      prototype.registerHybridMethod(\"addWillExitPictureInPictureListener\", &HybridVideoViewViewManagerSpec::addWillExitPictureInPictureListener);\n      prototype.registerHybridMethod(\"clearAllListeners\", &HybridVideoViewViewManagerSpec::clearAllListeners);\n    });\n  }\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/HybridVideoViewViewManagerSpec.hpp",
    "content": "///\n/// HybridVideoViewViewManagerSpec.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/HybridObject.hpp>)\n#include <NitroModules/HybridObject.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `HybridVideoPlayerSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSpec; }\n// Forward declaration of `ResizeMode` to properly resolve imports.\nnamespace margelo::nitro::video { enum class ResizeMode; }\n// Forward declaration of `SurfaceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SurfaceType; }\n// Forward declaration of `ListenerSubscription` to properly resolve imports.\nnamespace margelo::nitro::video { struct ListenerSubscription; }\n\n#include <memory>\n#include \"HybridVideoPlayerSpec.hpp\"\n#include <optional>\n#include \"ResizeMode.hpp\"\n#include \"SurfaceType.hpp\"\n#include \"ListenerSubscription.hpp\"\n#include <functional>\n\nnamespace margelo::nitro::video {\n\n  using namespace margelo::nitro;\n\n  /**\n   * An abstract base class for `VideoViewViewManager`\n   * Inherit this class to create instances of `HybridVideoViewViewManagerSpec` in C++.\n   * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.\n   * @example\n   * ```cpp\n   * class HybridVideoViewViewManager: public HybridVideoViewViewManagerSpec {\n   * public:\n   *   HybridVideoViewViewManager(...): HybridObject(TAG) { ... }\n   *   // ...\n   * };\n   * ```\n   */\n  class HybridVideoViewViewManagerSpec: public virtual HybridObject {\n    public:\n      // Constructor\n      explicit HybridVideoViewViewManagerSpec(): HybridObject(TAG) { }\n\n      // Destructor\n      ~HybridVideoViewViewManagerSpec() override = default;\n\n    public:\n      // Properties\n      virtual std::optional<std::shared_ptr<HybridVideoPlayerSpec>> getPlayer() = 0;\n      virtual void setPlayer(const std::optional<std::shared_ptr<HybridVideoPlayerSpec>>& player) = 0;\n      virtual bool getControls() = 0;\n      virtual void setControls(bool controls) = 0;\n      virtual bool getPictureInPicture() = 0;\n      virtual void setPictureInPicture(bool pictureInPicture) = 0;\n      virtual bool getAutoEnterPictureInPicture() = 0;\n      virtual void setAutoEnterPictureInPicture(bool autoEnterPictureInPicture) = 0;\n      virtual ResizeMode getResizeMode() = 0;\n      virtual void setResizeMode(ResizeMode resizeMode) = 0;\n      virtual bool getKeepScreenAwake() = 0;\n      virtual void setKeepScreenAwake(bool keepScreenAwake) = 0;\n      virtual SurfaceType getSurfaceType() = 0;\n      virtual void setSurfaceType(SurfaceType surfaceType) = 0;\n\n    public:\n      // Methods\n      virtual void enterFullscreen() = 0;\n      virtual void exitFullscreen() = 0;\n      virtual void enterPictureInPicture() = 0;\n      virtual void exitPictureInPicture() = 0;\n      virtual bool canEnterPictureInPicture() = 0;\n      virtual ListenerSubscription addOnPictureInPictureChangeListener(const std::function<void(bool /* isInPictureInPicture */)>& listener) = 0;\n      virtual ListenerSubscription addOnFullscreenChangeListener(const std::function<void(bool /* fullscreen */)>& listener) = 0;\n      virtual ListenerSubscription addWillEnterFullscreenListener(const std::function<void()>& listener) = 0;\n      virtual ListenerSubscription addWillExitFullscreenListener(const std::function<void()>& listener) = 0;\n      virtual ListenerSubscription addWillEnterPictureInPictureListener(const std::function<void()>& listener) = 0;\n      virtual ListenerSubscription addWillExitPictureInPictureListener(const std::function<void()>& listener) = 0;\n      virtual void clearAllListeners() = 0;\n\n    protected:\n      // Hybrid Setup\n      void loadHybridMethods() override;\n\n    protected:\n      // Tag for logging\n      static constexpr auto TAG = \"VideoViewViewManager\";\n  };\n\n} // namespace margelo::nitro::video\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/IgnoreSilentSwitchMode.hpp",
    "content": "///\n/// IgnoreSilentSwitchMode.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/NitroHash.hpp>)\n#include <NitroModules/NitroHash.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\nnamespace margelo::nitro::video {\n\n  /**\n   * An enum which can be represented as a JavaScript union (IgnoreSilentSwitchMode).\n   */\n  enum class IgnoreSilentSwitchMode {\n    AUTO      SWIFT_NAME(auto) = 0,\n    IGNORE      SWIFT_NAME(ignore) = 1,\n    OBEY      SWIFT_NAME(obey) = 2,\n  } CLOSED_ENUM;\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ IgnoreSilentSwitchMode <> JS IgnoreSilentSwitchMode (union)\n  template <>\n  struct JSIConverter<margelo::nitro::video::IgnoreSilentSwitchMode> final {\n    static inline margelo::nitro::video::IgnoreSilentSwitchMode fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"auto\"): return margelo::nitro::video::IgnoreSilentSwitchMode::AUTO;\n        case hashString(\"ignore\"): return margelo::nitro::video::IgnoreSilentSwitchMode::IGNORE;\n        case hashString(\"obey\"): return margelo::nitro::video::IgnoreSilentSwitchMode::OBEY;\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert \\\"\" + unionValue + \"\\\" to enum IgnoreSilentSwitchMode - invalid value!\");\n      }\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::IgnoreSilentSwitchMode arg) {\n      switch (arg) {\n        case margelo::nitro::video::IgnoreSilentSwitchMode::AUTO: return JSIConverter<std::string>::toJSI(runtime, \"auto\");\n        case margelo::nitro::video::IgnoreSilentSwitchMode::IGNORE: return JSIConverter<std::string>::toJSI(runtime, \"ignore\");\n        case margelo::nitro::video::IgnoreSilentSwitchMode::OBEY: return JSIConverter<std::string>::toJSI(runtime, \"obey\");\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert IgnoreSilentSwitchMode to JS - invalid value: \"\n                                    + std::to_string(static_cast<int>(arg)) + \"!\");\n      }\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isString()) {\n        return false;\n      }\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"auto\"):\n        case hashString(\"ignore\"):\n        case hashString(\"obey\"):\n          return true;\n        default:\n          return false;\n      }\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/ListenerSubscription.hpp",
    "content": "///\n/// ListenerSubscription.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n#include <functional>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (ListenerSubscription).\n   */\n  struct ListenerSubscription final {\n  public:\n    std::function<void()> remove     SWIFT_PRIVATE;\n\n  public:\n    ListenerSubscription() = default;\n    explicit ListenerSubscription(std::function<void()> remove): remove(remove) {}\n\n  public:\n    // ListenerSubscription is not equatable because these properties are not equatable: remove\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ ListenerSubscription <> JS ListenerSubscription (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::ListenerSubscription> final {\n    static inline margelo::nitro::video::ListenerSubscription fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::ListenerSubscription(\n        JSIConverter<std::function<void()>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"remove\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::ListenerSubscription& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"remove\"), JSIConverter<std::function<void()>>::toJSI(runtime, arg.remove));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::function<void()>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"remove\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/LivePlaybackParams.hpp",
    "content": "///\n/// LivePlaybackParams.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (LivePlaybackParams).\n   */\n  struct LivePlaybackParams final {\n  public:\n    std::optional<double> minPlaybackSpeed     SWIFT_PRIVATE;\n    std::optional<double> maxPlaybackSpeed     SWIFT_PRIVATE;\n    std::optional<double> maxOffsetMs     SWIFT_PRIVATE;\n    std::optional<double> minOffsetMs     SWIFT_PRIVATE;\n    std::optional<double> targetOffsetMs     SWIFT_PRIVATE;\n\n  public:\n    LivePlaybackParams() = default;\n    explicit LivePlaybackParams(std::optional<double> minPlaybackSpeed, std::optional<double> maxPlaybackSpeed, std::optional<double> maxOffsetMs, std::optional<double> minOffsetMs, std::optional<double> targetOffsetMs): minPlaybackSpeed(minPlaybackSpeed), maxPlaybackSpeed(maxPlaybackSpeed), maxOffsetMs(maxOffsetMs), minOffsetMs(minOffsetMs), targetOffsetMs(targetOffsetMs) {}\n\n  public:\n    friend bool operator==(const LivePlaybackParams& lhs, const LivePlaybackParams& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ LivePlaybackParams <> JS LivePlaybackParams (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::LivePlaybackParams> final {\n    static inline margelo::nitro::video::LivePlaybackParams fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::LivePlaybackParams(\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"minPlaybackSpeed\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"maxPlaybackSpeed\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"maxOffsetMs\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"minOffsetMs\"))),\n        JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"targetOffsetMs\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::LivePlaybackParams& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"minPlaybackSpeed\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.minPlaybackSpeed));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"maxPlaybackSpeed\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.maxPlaybackSpeed));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"maxOffsetMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.maxOffsetMs));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"minOffsetMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.minOffsetMs));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"targetOffsetMs\"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.targetOffsetMs));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"minPlaybackSpeed\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"maxPlaybackSpeed\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"maxOffsetMs\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"minOffsetMs\")))) return false;\n      if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"targetOffsetMs\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/MixAudioMode.hpp",
    "content": "///\n/// MixAudioMode.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/NitroHash.hpp>)\n#include <NitroModules/NitroHash.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\nnamespace margelo::nitro::video {\n\n  /**\n   * An enum which can be represented as a JavaScript union (MixAudioMode).\n   */\n  enum class MixAudioMode {\n    MIXWITHOTHERS      SWIFT_NAME(mixwithothers) = 0,\n    DONOTMIX      SWIFT_NAME(donotmix) = 1,\n    DUCKOTHERS      SWIFT_NAME(duckothers) = 2,\n    AUTO      SWIFT_NAME(auto) = 3,\n  } CLOSED_ENUM;\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ MixAudioMode <> JS MixAudioMode (union)\n  template <>\n  struct JSIConverter<margelo::nitro::video::MixAudioMode> final {\n    static inline margelo::nitro::video::MixAudioMode fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"mixWithOthers\"): return margelo::nitro::video::MixAudioMode::MIXWITHOTHERS;\n        case hashString(\"doNotMix\"): return margelo::nitro::video::MixAudioMode::DONOTMIX;\n        case hashString(\"duckOthers\"): return margelo::nitro::video::MixAudioMode::DUCKOTHERS;\n        case hashString(\"auto\"): return margelo::nitro::video::MixAudioMode::AUTO;\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert \\\"\" + unionValue + \"\\\" to enum MixAudioMode - invalid value!\");\n      }\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::MixAudioMode arg) {\n      switch (arg) {\n        case margelo::nitro::video::MixAudioMode::MIXWITHOTHERS: return JSIConverter<std::string>::toJSI(runtime, \"mixWithOthers\");\n        case margelo::nitro::video::MixAudioMode::DONOTMIX: return JSIConverter<std::string>::toJSI(runtime, \"doNotMix\");\n        case margelo::nitro::video::MixAudioMode::DUCKOTHERS: return JSIConverter<std::string>::toJSI(runtime, \"duckOthers\");\n        case margelo::nitro::video::MixAudioMode::AUTO: return JSIConverter<std::string>::toJSI(runtime, \"auto\");\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert MixAudioMode to JS - invalid value: \"\n                                    + std::to_string(static_cast<int>(arg)) + \"!\");\n      }\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isString()) {\n        return false;\n      }\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"mixWithOthers\"):\n        case hashString(\"doNotMix\"):\n        case hashString(\"duckOthers\"):\n        case hashString(\"auto\"):\n          return true;\n        default:\n          return false;\n      }\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/NativeDrmParams.hpp",
    "content": "///\n/// NativeDrmParams.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `OnGetLicensePayload` to properly resolve imports.\nnamespace margelo::nitro::video { struct OnGetLicensePayload; }\n\n#include <string>\n#include <optional>\n#include <unordered_map>\n#include <NitroModules/Promise.hpp>\n#include \"OnGetLicensePayload.hpp\"\n#include <functional>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (NativeDrmParams).\n   */\n  struct NativeDrmParams final {\n  public:\n    std::optional<std::string> type     SWIFT_PRIVATE;\n    std::optional<std::string> licenseUrl     SWIFT_PRIVATE;\n    std::optional<std::string> certificateUrl     SWIFT_PRIVATE;\n    std::optional<std::string> contentId     SWIFT_PRIVATE;\n    std::optional<std::unordered_map<std::string, std::string>> licenseHeaders     SWIFT_PRIVATE;\n    std::optional<bool> multiSession     SWIFT_PRIVATE;\n    std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>> getLicense     SWIFT_PRIVATE;\n\n  public:\n    NativeDrmParams() = default;\n    explicit NativeDrmParams(std::optional<std::string> type, std::optional<std::string> licenseUrl, std::optional<std::string> certificateUrl, std::optional<std::string> contentId, std::optional<std::unordered_map<std::string, std::string>> licenseHeaders, std::optional<bool> multiSession, std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const OnGetLicensePayload& /* payload */)>> getLicense): type(type), licenseUrl(licenseUrl), certificateUrl(certificateUrl), contentId(contentId), licenseHeaders(licenseHeaders), multiSession(multiSession), getLicense(getLicense) {}\n\n  public:\n    // NativeDrmParams is not equatable because these properties are not equatable: getLicense\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ NativeDrmParams <> JS NativeDrmParams (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::NativeDrmParams> final {\n    static inline margelo::nitro::video::NativeDrmParams fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::NativeDrmParams(\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"type\"))),\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"licenseUrl\"))),\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"certificateUrl\"))),\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"contentId\"))),\n        JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"licenseHeaders\"))),\n        JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"multiSession\"))),\n        JSIConverter<std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const margelo::nitro::video::OnGetLicensePayload&)>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"getLicense\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::NativeDrmParams& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"type\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.type));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"licenseUrl\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.licenseUrl));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"certificateUrl\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.certificateUrl));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"contentId\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.contentId));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"licenseHeaders\"), JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::toJSI(runtime, arg.licenseHeaders));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"multiSession\"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.multiSession));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"getLicense\"), JSIConverter<std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const margelo::nitro::video::OnGetLicensePayload&)>>>::toJSI(runtime, arg.getLicense));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"type\")))) return false;\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"licenseUrl\")))) return false;\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"certificateUrl\")))) return false;\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"contentId\")))) return false;\n      if (!JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"licenseHeaders\")))) return false;\n      if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"multiSession\")))) return false;\n      if (!JSIConverter<std::optional<std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::string>>>>(const margelo::nitro::video::OnGetLicensePayload&)>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"getLicense\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/NativeExternalSubtitle.hpp",
    "content": "///\n/// NativeExternalSubtitle.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `SubtitleType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SubtitleType; }\n\n#include <string>\n#include \"SubtitleType.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (NativeExternalSubtitle).\n   */\n  struct NativeExternalSubtitle final {\n  public:\n    std::string uri     SWIFT_PRIVATE;\n    std::string label     SWIFT_PRIVATE;\n    SubtitleType type     SWIFT_PRIVATE;\n    std::string language     SWIFT_PRIVATE;\n\n  public:\n    NativeExternalSubtitle() = default;\n    explicit NativeExternalSubtitle(std::string uri, std::string label, SubtitleType type, std::string language): uri(uri), label(label), type(type), language(language) {}\n\n  public:\n    friend bool operator==(const NativeExternalSubtitle& lhs, const NativeExternalSubtitle& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ NativeExternalSubtitle <> JS NativeExternalSubtitle (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::NativeExternalSubtitle> final {\n    static inline margelo::nitro::video::NativeExternalSubtitle fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::NativeExternalSubtitle(\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"uri\"))),\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"label\"))),\n        JSIConverter<margelo::nitro::video::SubtitleType>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"type\"))),\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"language\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::NativeExternalSubtitle& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"uri\"), JSIConverter<std::string>::toJSI(runtime, arg.uri));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"label\"), JSIConverter<std::string>::toJSI(runtime, arg.label));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"type\"), JSIConverter<margelo::nitro::video::SubtitleType>::toJSI(runtime, arg.type));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"language\"), JSIConverter<std::string>::toJSI(runtime, arg.language));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"uri\")))) return false;\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"label\")))) return false;\n      if (!JSIConverter<margelo::nitro::video::SubtitleType>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"type\")))) return false;\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"language\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/NativeVideoConfig.hpp",
    "content": "///\n/// NativeVideoConfig.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `NativeExternalSubtitle` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeExternalSubtitle; }\n// Forward declaration of `NativeDrmParams` to properly resolve imports.\nnamespace margelo::nitro::video { struct NativeDrmParams; }\n// Forward declaration of `BufferConfig` to properly resolve imports.\nnamespace margelo::nitro::video { struct BufferConfig; }\n// Forward declaration of `CustomVideoMetadata` to properly resolve imports.\nnamespace margelo::nitro::video { struct CustomVideoMetadata; }\n\n#include <string>\n#include \"NativeExternalSubtitle.hpp\"\n#include <vector>\n#include <optional>\n#include \"NativeDrmParams.hpp\"\n#include <unordered_map>\n#include \"BufferConfig.hpp\"\n#include \"CustomVideoMetadata.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (NativeVideoConfig).\n   */\n  struct NativeVideoConfig final {\n  public:\n    std::string uri     SWIFT_PRIVATE;\n    std::optional<std::vector<NativeExternalSubtitle>> externalSubtitles     SWIFT_PRIVATE;\n    std::optional<NativeDrmParams> drm     SWIFT_PRIVATE;\n    std::optional<std::unordered_map<std::string, std::string>> headers     SWIFT_PRIVATE;\n    std::optional<BufferConfig> bufferConfig     SWIFT_PRIVATE;\n    std::optional<CustomVideoMetadata> metadata     SWIFT_PRIVATE;\n    std::optional<bool> initializeOnCreation     SWIFT_PRIVATE;\n\n  public:\n    NativeVideoConfig() = default;\n    explicit NativeVideoConfig(std::string uri, std::optional<std::vector<NativeExternalSubtitle>> externalSubtitles, std::optional<NativeDrmParams> drm, std::optional<std::unordered_map<std::string, std::string>> headers, std::optional<BufferConfig> bufferConfig, std::optional<CustomVideoMetadata> metadata, std::optional<bool> initializeOnCreation): uri(uri), externalSubtitles(externalSubtitles), drm(drm), headers(headers), bufferConfig(bufferConfig), metadata(metadata), initializeOnCreation(initializeOnCreation) {}\n\n  public:\n    // NativeVideoConfig is not equatable because these properties are not equatable: drm\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ NativeVideoConfig <> JS NativeVideoConfig (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::NativeVideoConfig> final {\n    static inline margelo::nitro::video::NativeVideoConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::NativeVideoConfig(\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"uri\"))),\n        JSIConverter<std::optional<std::vector<margelo::nitro::video::NativeExternalSubtitle>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"externalSubtitles\"))),\n        JSIConverter<std::optional<margelo::nitro::video::NativeDrmParams>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"drm\"))),\n        JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"headers\"))),\n        JSIConverter<std::optional<margelo::nitro::video::BufferConfig>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bufferConfig\"))),\n        JSIConverter<std::optional<margelo::nitro::video::CustomVideoMetadata>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"metadata\"))),\n        JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"initializeOnCreation\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::NativeVideoConfig& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"uri\"), JSIConverter<std::string>::toJSI(runtime, arg.uri));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"externalSubtitles\"), JSIConverter<std::optional<std::vector<margelo::nitro::video::NativeExternalSubtitle>>>::toJSI(runtime, arg.externalSubtitles));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"drm\"), JSIConverter<std::optional<margelo::nitro::video::NativeDrmParams>>::toJSI(runtime, arg.drm));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"headers\"), JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::toJSI(runtime, arg.headers));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"bufferConfig\"), JSIConverter<std::optional<margelo::nitro::video::BufferConfig>>::toJSI(runtime, arg.bufferConfig));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"metadata\"), JSIConverter<std::optional<margelo::nitro::video::CustomVideoMetadata>>::toJSI(runtime, arg.metadata));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"initializeOnCreation\"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.initializeOnCreation));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"uri\")))) return false;\n      if (!JSIConverter<std::optional<std::vector<margelo::nitro::video::NativeExternalSubtitle>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"externalSubtitles\")))) return false;\n      if (!JSIConverter<std::optional<margelo::nitro::video::NativeDrmParams>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"drm\")))) return false;\n      if (!JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"headers\")))) return false;\n      if (!JSIConverter<std::optional<margelo::nitro::video::BufferConfig>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bufferConfig\")))) return false;\n      if (!JSIConverter<std::optional<margelo::nitro::video::CustomVideoMetadata>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"metadata\")))) return false;\n      if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"initializeOnCreation\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/OnGetLicensePayload.hpp",
    "content": "///\n/// OnGetLicensePayload.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (OnGetLicensePayload).\n   */\n  struct OnGetLicensePayload final {\n  public:\n    std::string contentId     SWIFT_PRIVATE;\n    std::string licenseUrl     SWIFT_PRIVATE;\n    std::string keyUrl     SWIFT_PRIVATE;\n    std::string spc     SWIFT_PRIVATE;\n\n  public:\n    OnGetLicensePayload() = default;\n    explicit OnGetLicensePayload(std::string contentId, std::string licenseUrl, std::string keyUrl, std::string spc): contentId(contentId), licenseUrl(licenseUrl), keyUrl(keyUrl), spc(spc) {}\n\n  public:\n    friend bool operator==(const OnGetLicensePayload& lhs, const OnGetLicensePayload& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ OnGetLicensePayload <> JS OnGetLicensePayload (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::OnGetLicensePayload> final {\n    static inline margelo::nitro::video::OnGetLicensePayload fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::OnGetLicensePayload(\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"contentId\"))),\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"licenseUrl\"))),\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"keyUrl\"))),\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"spc\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::OnGetLicensePayload& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"contentId\"), JSIConverter<std::string>::toJSI(runtime, arg.contentId));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"licenseUrl\"), JSIConverter<std::string>::toJSI(runtime, arg.licenseUrl));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"keyUrl\"), JSIConverter<std::string>::toJSI(runtime, arg.keyUrl));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"spc\"), JSIConverter<std::string>::toJSI(runtime, arg.spc));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"contentId\")))) return false;\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"licenseUrl\")))) return false;\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"keyUrl\")))) return false;\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"spc\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/ResizeMode.hpp",
    "content": "///\n/// ResizeMode.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/NitroHash.hpp>)\n#include <NitroModules/NitroHash.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\nnamespace margelo::nitro::video {\n\n  /**\n   * An enum which can be represented as a JavaScript union (ResizeMode).\n   */\n  enum class ResizeMode {\n    CONTAIN      SWIFT_NAME(contain) = 0,\n    COVER      SWIFT_NAME(cover) = 1,\n    STRETCH      SWIFT_NAME(stretch) = 2,\n    NONE      SWIFT_NAME(none) = 3,\n  } CLOSED_ENUM;\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ ResizeMode <> JS ResizeMode (union)\n  template <>\n  struct JSIConverter<margelo::nitro::video::ResizeMode> final {\n    static inline margelo::nitro::video::ResizeMode fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"contain\"): return margelo::nitro::video::ResizeMode::CONTAIN;\n        case hashString(\"cover\"): return margelo::nitro::video::ResizeMode::COVER;\n        case hashString(\"stretch\"): return margelo::nitro::video::ResizeMode::STRETCH;\n        case hashString(\"none\"): return margelo::nitro::video::ResizeMode::NONE;\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert \\\"\" + unionValue + \"\\\" to enum ResizeMode - invalid value!\");\n      }\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::ResizeMode arg) {\n      switch (arg) {\n        case margelo::nitro::video::ResizeMode::CONTAIN: return JSIConverter<std::string>::toJSI(runtime, \"contain\");\n        case margelo::nitro::video::ResizeMode::COVER: return JSIConverter<std::string>::toJSI(runtime, \"cover\");\n        case margelo::nitro::video::ResizeMode::STRETCH: return JSIConverter<std::string>::toJSI(runtime, \"stretch\");\n        case margelo::nitro::video::ResizeMode::NONE: return JSIConverter<std::string>::toJSI(runtime, \"none\");\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert ResizeMode to JS - invalid value: \"\n                                    + std::to_string(static_cast<int>(arg)) + \"!\");\n      }\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isString()) {\n        return false;\n      }\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"contain\"):\n        case hashString(\"cover\"):\n        case hashString(\"stretch\"):\n        case hashString(\"none\"):\n          return true;\n        default:\n          return false;\n      }\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/Resolution.hpp",
    "content": "///\n/// Resolution.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (Resolution).\n   */\n  struct Resolution final {\n  public:\n    double width     SWIFT_PRIVATE;\n    double height     SWIFT_PRIVATE;\n\n  public:\n    Resolution() = default;\n    explicit Resolution(double width, double height): width(width), height(height) {}\n\n  public:\n    friend bool operator==(const Resolution& lhs, const Resolution& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ Resolution <> JS Resolution (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::Resolution> final {\n    static inline margelo::nitro::video::Resolution fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::Resolution(\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"width\"))),\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"height\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::Resolution& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"width\"), JSIConverter<double>::toJSI(runtime, arg.width));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"height\"), JSIConverter<double>::toJSI(runtime, arg.height));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"width\")))) return false;\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"height\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/SourceType.hpp",
    "content": "///\n/// SourceType.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/NitroHash.hpp>)\n#include <NitroModules/NitroHash.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\nnamespace margelo::nitro::video {\n\n  /**\n   * An enum which can be represented as a JavaScript union (SourceType).\n   */\n  enum class SourceType {\n    LOCAL      SWIFT_NAME(local) = 0,\n    NETWORK      SWIFT_NAME(network) = 1,\n  } CLOSED_ENUM;\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ SourceType <> JS SourceType (union)\n  template <>\n  struct JSIConverter<margelo::nitro::video::SourceType> final {\n    static inline margelo::nitro::video::SourceType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"local\"): return margelo::nitro::video::SourceType::LOCAL;\n        case hashString(\"network\"): return margelo::nitro::video::SourceType::NETWORK;\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert \\\"\" + unionValue + \"\\\" to enum SourceType - invalid value!\");\n      }\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::SourceType arg) {\n      switch (arg) {\n        case margelo::nitro::video::SourceType::LOCAL: return JSIConverter<std::string>::toJSI(runtime, \"local\");\n        case margelo::nitro::video::SourceType::NETWORK: return JSIConverter<std::string>::toJSI(runtime, \"network\");\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert SourceType to JS - invalid value: \"\n                                    + std::to_string(static_cast<int>(arg)) + \"!\");\n      }\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isString()) {\n        return false;\n      }\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"local\"):\n        case hashString(\"network\"):\n          return true;\n        default:\n          return false;\n      }\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/SubtitleType.hpp",
    "content": "///\n/// SubtitleType.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/NitroHash.hpp>)\n#include <NitroModules/NitroHash.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\nnamespace margelo::nitro::video {\n\n  /**\n   * An enum which can be represented as a JavaScript union (SubtitleType).\n   */\n  enum class SubtitleType {\n    AUTO      SWIFT_NAME(auto) = 0,\n    VTT      SWIFT_NAME(vtt) = 1,\n    SRT      SWIFT_NAME(srt) = 2,\n    SSA      SWIFT_NAME(ssa) = 3,\n    ASS      SWIFT_NAME(ass) = 4,\n  } CLOSED_ENUM;\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ SubtitleType <> JS SubtitleType (union)\n  template <>\n  struct JSIConverter<margelo::nitro::video::SubtitleType> final {\n    static inline margelo::nitro::video::SubtitleType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"auto\"): return margelo::nitro::video::SubtitleType::AUTO;\n        case hashString(\"vtt\"): return margelo::nitro::video::SubtitleType::VTT;\n        case hashString(\"srt\"): return margelo::nitro::video::SubtitleType::SRT;\n        case hashString(\"ssa\"): return margelo::nitro::video::SubtitleType::SSA;\n        case hashString(\"ass\"): return margelo::nitro::video::SubtitleType::ASS;\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert \\\"\" + unionValue + \"\\\" to enum SubtitleType - invalid value!\");\n      }\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::SubtitleType arg) {\n      switch (arg) {\n        case margelo::nitro::video::SubtitleType::AUTO: return JSIConverter<std::string>::toJSI(runtime, \"auto\");\n        case margelo::nitro::video::SubtitleType::VTT: return JSIConverter<std::string>::toJSI(runtime, \"vtt\");\n        case margelo::nitro::video::SubtitleType::SRT: return JSIConverter<std::string>::toJSI(runtime, \"srt\");\n        case margelo::nitro::video::SubtitleType::SSA: return JSIConverter<std::string>::toJSI(runtime, \"ssa\");\n        case margelo::nitro::video::SubtitleType::ASS: return JSIConverter<std::string>::toJSI(runtime, \"ass\");\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert SubtitleType to JS - invalid value: \"\n                                    + std::to_string(static_cast<int>(arg)) + \"!\");\n      }\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isString()) {\n        return false;\n      }\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"auto\"):\n        case hashString(\"vtt\"):\n        case hashString(\"srt\"):\n        case hashString(\"ssa\"):\n        case hashString(\"ass\"):\n          return true;\n        default:\n          return false;\n      }\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/SurfaceType.hpp",
    "content": "///\n/// SurfaceType.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/NitroHash.hpp>)\n#include <NitroModules/NitroHash.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\nnamespace margelo::nitro::video {\n\n  /**\n   * An enum which can be represented as a JavaScript union (SurfaceType).\n   */\n  enum class SurfaceType {\n    SURFACE      SWIFT_NAME(surface) = 0,\n    TEXTURE      SWIFT_NAME(texture) = 1,\n  } CLOSED_ENUM;\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ SurfaceType <> JS SurfaceType (union)\n  template <>\n  struct JSIConverter<margelo::nitro::video::SurfaceType> final {\n    static inline margelo::nitro::video::SurfaceType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"surface\"): return margelo::nitro::video::SurfaceType::SURFACE;\n        case hashString(\"texture\"): return margelo::nitro::video::SurfaceType::TEXTURE;\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert \\\"\" + unionValue + \"\\\" to enum SurfaceType - invalid value!\");\n      }\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::SurfaceType arg) {\n      switch (arg) {\n        case margelo::nitro::video::SurfaceType::SURFACE: return JSIConverter<std::string>::toJSI(runtime, \"surface\");\n        case margelo::nitro::video::SurfaceType::TEXTURE: return JSIConverter<std::string>::toJSI(runtime, \"texture\");\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert SurfaceType to JS - invalid value: \"\n                                    + std::to_string(static_cast<int>(arg)) + \"!\");\n      }\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isString()) {\n        return false;\n      }\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"surface\"):\n        case hashString(\"texture\"):\n          return true;\n        default:\n          return false;\n      }\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/TextTrack.hpp",
    "content": "///\n/// TextTrack.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n#include <string>\n#include <optional>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (TextTrack).\n   */\n  struct TextTrack final {\n  public:\n    std::string id     SWIFT_PRIVATE;\n    std::string label     SWIFT_PRIVATE;\n    std::optional<std::string> language     SWIFT_PRIVATE;\n    bool selected     SWIFT_PRIVATE;\n\n  public:\n    TextTrack() = default;\n    explicit TextTrack(std::string id, std::string label, std::optional<std::string> language, bool selected): id(id), label(label), language(language), selected(selected) {}\n\n  public:\n    friend bool operator==(const TextTrack& lhs, const TextTrack& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ TextTrack <> JS TextTrack (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::TextTrack> final {\n    static inline margelo::nitro::video::TextTrack fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::TextTrack(\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"id\"))),\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"label\"))),\n        JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"language\"))),\n        JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"selected\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::TextTrack& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"id\"), JSIConverter<std::string>::toJSI(runtime, arg.id));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"label\"), JSIConverter<std::string>::toJSI(runtime, arg.label));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"language\"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.language));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"selected\"), JSIConverter<bool>::toJSI(runtime, arg.selected));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"id\")))) return false;\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"label\")))) return false;\n      if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"language\")))) return false;\n      if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"selected\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/TimedMetadata.hpp",
    "content": "///\n/// TimedMetadata.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `TimedMetadataObject` to properly resolve imports.\nnamespace margelo::nitro::video { struct TimedMetadataObject; }\n\n#include \"TimedMetadataObject.hpp\"\n#include <vector>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (TimedMetadata).\n   */\n  struct TimedMetadata final {\n  public:\n    std::vector<TimedMetadataObject> metadata     SWIFT_PRIVATE;\n\n  public:\n    TimedMetadata() = default;\n    explicit TimedMetadata(std::vector<TimedMetadataObject> metadata): metadata(metadata) {}\n\n  public:\n    friend bool operator==(const TimedMetadata& lhs, const TimedMetadata& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ TimedMetadata <> JS TimedMetadata (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::TimedMetadata> final {\n    static inline margelo::nitro::video::TimedMetadata fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::TimedMetadata(\n        JSIConverter<std::vector<margelo::nitro::video::TimedMetadataObject>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"metadata\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::TimedMetadata& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"metadata\"), JSIConverter<std::vector<margelo::nitro::video::TimedMetadataObject>>::toJSI(runtime, arg.metadata));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::vector<margelo::nitro::video::TimedMetadataObject>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"metadata\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/TimedMetadataObject.hpp",
    "content": "///\n/// TimedMetadataObject.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n#include <string>\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (TimedMetadataObject).\n   */\n  struct TimedMetadataObject final {\n  public:\n    std::string value     SWIFT_PRIVATE;\n    std::string identifier     SWIFT_PRIVATE;\n\n  public:\n    TimedMetadataObject() = default;\n    explicit TimedMetadataObject(std::string value, std::string identifier): value(value), identifier(identifier) {}\n\n  public:\n    friend bool operator==(const TimedMetadataObject& lhs, const TimedMetadataObject& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ TimedMetadataObject <> JS TimedMetadataObject (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::TimedMetadataObject> final {\n    static inline margelo::nitro::video::TimedMetadataObject fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::TimedMetadataObject(\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"value\"))),\n        JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"identifier\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::TimedMetadataObject& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"value\"), JSIConverter<std::string>::toJSI(runtime, arg.value));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"identifier\"), JSIConverter<std::string>::toJSI(runtime, arg.identifier));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"value\")))) return false;\n      if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"identifier\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/VideoInformation.hpp",
    "content": "///\n/// VideoInformation.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `VideoOrientation` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoOrientation; }\n\n#include \"VideoOrientation.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (VideoInformation).\n   */\n  struct VideoInformation final {\n  public:\n    double bitrate     SWIFT_PRIVATE;\n    double width     SWIFT_PRIVATE;\n    double height     SWIFT_PRIVATE;\n    double duration     SWIFT_PRIVATE;\n    int64_t fileSize     SWIFT_PRIVATE;\n    bool isHDR     SWIFT_PRIVATE;\n    bool isLive     SWIFT_PRIVATE;\n    VideoOrientation orientation     SWIFT_PRIVATE;\n\n  public:\n    VideoInformation() = default;\n    explicit VideoInformation(double bitrate, double width, double height, double duration, int64_t fileSize, bool isHDR, bool isLive, VideoOrientation orientation): bitrate(bitrate), width(width), height(height), duration(duration), fileSize(fileSize), isHDR(isHDR), isLive(isLive), orientation(orientation) {}\n\n  public:\n    friend bool operator==(const VideoInformation& lhs, const VideoInformation& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ VideoInformation <> JS VideoInformation (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::VideoInformation> final {\n    static inline margelo::nitro::video::VideoInformation fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::VideoInformation(\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bitrate\"))),\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"width\"))),\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"height\"))),\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"duration\"))),\n        JSIConverter<int64_t>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"fileSize\"))),\n        JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"isHDR\"))),\n        JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"isLive\"))),\n        JSIConverter<margelo::nitro::video::VideoOrientation>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"orientation\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::VideoInformation& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"bitrate\"), JSIConverter<double>::toJSI(runtime, arg.bitrate));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"width\"), JSIConverter<double>::toJSI(runtime, arg.width));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"height\"), JSIConverter<double>::toJSI(runtime, arg.height));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"duration\"), JSIConverter<double>::toJSI(runtime, arg.duration));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"fileSize\"), JSIConverter<int64_t>::toJSI(runtime, arg.fileSize));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"isHDR\"), JSIConverter<bool>::toJSI(runtime, arg.isHDR));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"isLive\"), JSIConverter<bool>::toJSI(runtime, arg.isLive));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"orientation\"), JSIConverter<margelo::nitro::video::VideoOrientation>::toJSI(runtime, arg.orientation));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bitrate\")))) return false;\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"width\")))) return false;\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"height\")))) return false;\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"duration\")))) return false;\n      if (!JSIConverter<int64_t>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"fileSize\")))) return false;\n      if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"isHDR\")))) return false;\n      if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"isLive\")))) return false;\n      if (!JSIConverter<margelo::nitro::video::VideoOrientation>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"orientation\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/VideoOrientation.hpp",
    "content": "///\n/// VideoOrientation.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/NitroHash.hpp>)\n#include <NitroModules/NitroHash.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\nnamespace margelo::nitro::video {\n\n  /**\n   * An enum which can be represented as a JavaScript union (VideoOrientation).\n   */\n  enum class VideoOrientation {\n    PORTRAIT      SWIFT_NAME(portrait) = 0,\n    LANDSCAPE      SWIFT_NAME(landscape) = 1,\n    PORTRAIT_UPSIDE_DOWN      SWIFT_NAME(portraitUpsideDown) = 2,\n    LANDSCAPE_LEFT      SWIFT_NAME(landscapeLeft) = 3,\n    LANDSCAPE_RIGHT      SWIFT_NAME(landscapeRight) = 4,\n    SQUARE      SWIFT_NAME(square) = 5,\n    UNKNOWN      SWIFT_NAME(unknown) = 6,\n  } CLOSED_ENUM;\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ VideoOrientation <> JS VideoOrientation (union)\n  template <>\n  struct JSIConverter<margelo::nitro::video::VideoOrientation> final {\n    static inline margelo::nitro::video::VideoOrientation fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"portrait\"): return margelo::nitro::video::VideoOrientation::PORTRAIT;\n        case hashString(\"landscape\"): return margelo::nitro::video::VideoOrientation::LANDSCAPE;\n        case hashString(\"portrait-upside-down\"): return margelo::nitro::video::VideoOrientation::PORTRAIT_UPSIDE_DOWN;\n        case hashString(\"landscape-left\"): return margelo::nitro::video::VideoOrientation::LANDSCAPE_LEFT;\n        case hashString(\"landscape-right\"): return margelo::nitro::video::VideoOrientation::LANDSCAPE_RIGHT;\n        case hashString(\"square\"): return margelo::nitro::video::VideoOrientation::SQUARE;\n        case hashString(\"unknown\"): return margelo::nitro::video::VideoOrientation::UNKNOWN;\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert \\\"\" + unionValue + \"\\\" to enum VideoOrientation - invalid value!\");\n      }\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::VideoOrientation arg) {\n      switch (arg) {\n        case margelo::nitro::video::VideoOrientation::PORTRAIT: return JSIConverter<std::string>::toJSI(runtime, \"portrait\");\n        case margelo::nitro::video::VideoOrientation::LANDSCAPE: return JSIConverter<std::string>::toJSI(runtime, \"landscape\");\n        case margelo::nitro::video::VideoOrientation::PORTRAIT_UPSIDE_DOWN: return JSIConverter<std::string>::toJSI(runtime, \"portrait-upside-down\");\n        case margelo::nitro::video::VideoOrientation::LANDSCAPE_LEFT: return JSIConverter<std::string>::toJSI(runtime, \"landscape-left\");\n        case margelo::nitro::video::VideoOrientation::LANDSCAPE_RIGHT: return JSIConverter<std::string>::toJSI(runtime, \"landscape-right\");\n        case margelo::nitro::video::VideoOrientation::SQUARE: return JSIConverter<std::string>::toJSI(runtime, \"square\");\n        case margelo::nitro::video::VideoOrientation::UNKNOWN: return JSIConverter<std::string>::toJSI(runtime, \"unknown\");\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert VideoOrientation to JS - invalid value: \"\n                                    + std::to_string(static_cast<int>(arg)) + \"!\");\n      }\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isString()) {\n        return false;\n      }\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"portrait\"):\n        case hashString(\"landscape\"):\n        case hashString(\"portrait-upside-down\"):\n        case hashString(\"landscape-left\"):\n        case hashString(\"landscape-right\"):\n        case hashString(\"square\"):\n        case hashString(\"unknown\"):\n          return true;\n        default:\n          return false;\n      }\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/VideoPlayerStatus.hpp",
    "content": "///\n/// VideoPlayerStatus.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/NitroHash.hpp>)\n#include <NitroModules/NitroHash.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\nnamespace margelo::nitro::video {\n\n  /**\n   * An enum which can be represented as a JavaScript union (VideoPlayerStatus).\n   */\n  enum class VideoPlayerStatus {\n    IDLE      SWIFT_NAME(idle) = 0,\n    LOADING      SWIFT_NAME(loading) = 1,\n    READYTOPLAY      SWIFT_NAME(readytoplay) = 2,\n    ERROR      SWIFT_NAME(error) = 3,\n  } CLOSED_ENUM;\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ VideoPlayerStatus <> JS VideoPlayerStatus (union)\n  template <>\n  struct JSIConverter<margelo::nitro::video::VideoPlayerStatus> final {\n    static inline margelo::nitro::video::VideoPlayerStatus fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"idle\"): return margelo::nitro::video::VideoPlayerStatus::IDLE;\n        case hashString(\"loading\"): return margelo::nitro::video::VideoPlayerStatus::LOADING;\n        case hashString(\"readyToPlay\"): return margelo::nitro::video::VideoPlayerStatus::READYTOPLAY;\n        case hashString(\"error\"): return margelo::nitro::video::VideoPlayerStatus::ERROR;\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert \\\"\" + unionValue + \"\\\" to enum VideoPlayerStatus - invalid value!\");\n      }\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::video::VideoPlayerStatus arg) {\n      switch (arg) {\n        case margelo::nitro::video::VideoPlayerStatus::IDLE: return JSIConverter<std::string>::toJSI(runtime, \"idle\");\n        case margelo::nitro::video::VideoPlayerStatus::LOADING: return JSIConverter<std::string>::toJSI(runtime, \"loading\");\n        case margelo::nitro::video::VideoPlayerStatus::READYTOPLAY: return JSIConverter<std::string>::toJSI(runtime, \"readyToPlay\");\n        case margelo::nitro::video::VideoPlayerStatus::ERROR: return JSIConverter<std::string>::toJSI(runtime, \"error\");\n        default: [[unlikely]]\n          throw std::invalid_argument(\"Cannot convert VideoPlayerStatus to JS - invalid value: \"\n                                    + std::to_string(static_cast<int>(arg)) + \"!\");\n      }\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isString()) {\n        return false;\n      }\n      std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);\n      switch (hashString(unionValue.c_str(), unionValue.size())) {\n        case hashString(\"idle\"):\n        case hashString(\"loading\"):\n        case hashString(\"readyToPlay\"):\n        case hashString(\"error\"):\n          return true;\n        default:\n          return false;\n      }\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/onLoadData.hpp",
    "content": "///\n/// onLoadData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `VideoOrientation` to properly resolve imports.\nnamespace margelo::nitro::video { enum class VideoOrientation; }\n\n#include \"VideoOrientation.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (onLoadData).\n   */\n  struct onLoadData final {\n  public:\n    double currentTime     SWIFT_PRIVATE;\n    double duration     SWIFT_PRIVATE;\n    double height     SWIFT_PRIVATE;\n    double width     SWIFT_PRIVATE;\n    VideoOrientation orientation     SWIFT_PRIVATE;\n\n  public:\n    onLoadData() = default;\n    explicit onLoadData(double currentTime, double duration, double height, double width, VideoOrientation orientation): currentTime(currentTime), duration(duration), height(height), width(width), orientation(orientation) {}\n\n  public:\n    friend bool operator==(const onLoadData& lhs, const onLoadData& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ onLoadData <> JS onLoadData (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::onLoadData> final {\n    static inline margelo::nitro::video::onLoadData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::onLoadData(\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"currentTime\"))),\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"duration\"))),\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"height\"))),\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"width\"))),\n        JSIConverter<margelo::nitro::video::VideoOrientation>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"orientation\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onLoadData& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"currentTime\"), JSIConverter<double>::toJSI(runtime, arg.currentTime));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"duration\"), JSIConverter<double>::toJSI(runtime, arg.duration));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"height\"), JSIConverter<double>::toJSI(runtime, arg.height));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"width\"), JSIConverter<double>::toJSI(runtime, arg.width));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"orientation\"), JSIConverter<margelo::nitro::video::VideoOrientation>::toJSI(runtime, arg.orientation));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"currentTime\")))) return false;\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"duration\")))) return false;\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"height\")))) return false;\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"width\")))) return false;\n      if (!JSIConverter<margelo::nitro::video::VideoOrientation>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"orientation\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/onLoadStartData.hpp",
    "content": "///\n/// onLoadStartData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n// Forward declaration of `SourceType` to properly resolve imports.\nnamespace margelo::nitro::video { enum class SourceType; }\n// Forward declaration of `HybridVideoPlayerSourceSpec` to properly resolve imports.\nnamespace margelo::nitro::video { class HybridVideoPlayerSourceSpec; }\n\n#include \"SourceType.hpp\"\n#include <memory>\n#include \"HybridVideoPlayerSourceSpec.hpp\"\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (onLoadStartData).\n   */\n  struct onLoadStartData final {\n  public:\n    SourceType sourceType     SWIFT_PRIVATE;\n    std::shared_ptr<HybridVideoPlayerSourceSpec> source     SWIFT_PRIVATE;\n\n  public:\n    onLoadStartData() = default;\n    explicit onLoadStartData(SourceType sourceType, std::shared_ptr<HybridVideoPlayerSourceSpec> source): sourceType(sourceType), source(source) {}\n\n  public:\n    friend bool operator==(const onLoadStartData& lhs, const onLoadStartData& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ onLoadStartData <> JS onLoadStartData (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::onLoadStartData> final {\n    static inline margelo::nitro::video::onLoadStartData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::onLoadStartData(\n        JSIConverter<margelo::nitro::video::SourceType>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"sourceType\"))),\n        JSIConverter<std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSourceSpec>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"source\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onLoadStartData& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"sourceType\"), JSIConverter<margelo::nitro::video::SourceType>::toJSI(runtime, arg.sourceType));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"source\"), JSIConverter<std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSourceSpec>>::toJSI(runtime, arg.source));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<margelo::nitro::video::SourceType>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"sourceType\")))) return false;\n      if (!JSIConverter<std::shared_ptr<margelo::nitro::video::HybridVideoPlayerSourceSpec>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"source\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/onPlaybackStateChangeData.hpp",
    "content": "///\n/// onPlaybackStateChangeData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (onPlaybackStateChangeData).\n   */\n  struct onPlaybackStateChangeData final {\n  public:\n    bool isPlaying     SWIFT_PRIVATE;\n    bool isBuffering     SWIFT_PRIVATE;\n\n  public:\n    onPlaybackStateChangeData() = default;\n    explicit onPlaybackStateChangeData(bool isPlaying, bool isBuffering): isPlaying(isPlaying), isBuffering(isBuffering) {}\n\n  public:\n    friend bool operator==(const onPlaybackStateChangeData& lhs, const onPlaybackStateChangeData& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ onPlaybackStateChangeData <> JS onPlaybackStateChangeData (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::onPlaybackStateChangeData> final {\n    static inline margelo::nitro::video::onPlaybackStateChangeData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::onPlaybackStateChangeData(\n        JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"isPlaying\"))),\n        JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"isBuffering\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onPlaybackStateChangeData& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"isPlaying\"), JSIConverter<bool>::toJSI(runtime, arg.isPlaying));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"isBuffering\"), JSIConverter<bool>::toJSI(runtime, arg.isBuffering));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"isPlaying\")))) return false;\n      if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"isBuffering\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/onProgressData.hpp",
    "content": "///\n/// onProgressData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (onProgressData).\n   */\n  struct onProgressData final {\n  public:\n    double currentTime     SWIFT_PRIVATE;\n    double bufferDuration     SWIFT_PRIVATE;\n\n  public:\n    onProgressData() = default;\n    explicit onProgressData(double currentTime, double bufferDuration): currentTime(currentTime), bufferDuration(bufferDuration) {}\n\n  public:\n    friend bool operator==(const onProgressData& lhs, const onProgressData& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ onProgressData <> JS onProgressData (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::onProgressData> final {\n    static inline margelo::nitro::video::onProgressData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::onProgressData(\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"currentTime\"))),\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bufferDuration\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onProgressData& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"currentTime\"), JSIConverter<double>::toJSI(runtime, arg.currentTime));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"bufferDuration\"), JSIConverter<double>::toJSI(runtime, arg.bufferDuration));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"currentTime\")))) return false;\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"bufferDuration\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/nitrogen/generated/shared/c++/onVolumeChangeData.hpp",
    "content": "///\n/// onVolumeChangeData.hpp\n/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.\n/// https://github.com/mrousavy/nitro\n/// Copyright © Marc Rousavy @ Margelo\n///\n\n#pragma once\n\n#if __has_include(<NitroModules/JSIConverter.hpp>)\n#include <NitroModules/JSIConverter.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/NitroDefines.hpp>)\n#include <NitroModules/NitroDefines.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/JSIHelpers.hpp>)\n#include <NitroModules/JSIHelpers.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n#if __has_include(<NitroModules/PropNameIDCache.hpp>)\n#include <NitroModules/PropNameIDCache.hpp>\n#else\n#error NitroModules cannot be found! Are you sure you installed NitroModules properly?\n#endif\n\n\n\n\n\nnamespace margelo::nitro::video {\n\n  /**\n   * A struct which can be represented as a JavaScript object (onVolumeChangeData).\n   */\n  struct onVolumeChangeData final {\n  public:\n    double volume     SWIFT_PRIVATE;\n    bool muted     SWIFT_PRIVATE;\n\n  public:\n    onVolumeChangeData() = default;\n    explicit onVolumeChangeData(double volume, bool muted): volume(volume), muted(muted) {}\n\n  public:\n    friend bool operator==(const onVolumeChangeData& lhs, const onVolumeChangeData& rhs) = default;\n  };\n\n} // namespace margelo::nitro::video\n\nnamespace margelo::nitro {\n\n  // C++ onVolumeChangeData <> JS onVolumeChangeData (object)\n  template <>\n  struct JSIConverter<margelo::nitro::video::onVolumeChangeData> final {\n    static inline margelo::nitro::video::onVolumeChangeData fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {\n      jsi::Object obj = arg.asObject(runtime);\n      return margelo::nitro::video::onVolumeChangeData(\n        JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"volume\"))),\n        JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"muted\")))\n      );\n    }\n    static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::video::onVolumeChangeData& arg) {\n      jsi::Object obj(runtime);\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"volume\"), JSIConverter<double>::toJSI(runtime, arg.volume));\n      obj.setProperty(runtime, PropNameIDCache::get(runtime, \"muted\"), JSIConverter<bool>::toJSI(runtime, arg.muted));\n      return obj;\n    }\n    static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {\n      if (!value.isObject()) {\n        return false;\n      }\n      jsi::Object obj = value.getObject(runtime);\n      if (!nitro::isPlainObject(runtime, obj)) {\n        return false;\n      }\n      if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"volume\")))) return false;\n      if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, \"muted\")))) return false;\n      return true;\n    }\n  };\n\n} // namespace margelo::nitro\n"
  },
  {
    "path": "packages/react-native-video/package.json",
    "content": "{\n  \"name\": \"react-native-video\",\n  \"version\": \"7.0.0-beta.8\",\n  \"description\": \"<Video /> Component for React Native\",\n  \"source\": \"./src/index.tsx\",\n  \"main\": \"./lib/commonjs/index.js\",\n  \"module\": \"./lib/module/index.js\",\n  \"types\": \"./lib/typescript/module/src/index.d.ts\",\n  \"react-native\": \"src/index\",\n  \"exports\": {\n    \".\": {\n      \"import\": {\n        \"types\": \"./lib/typescript/module/src/index.d.ts\",\n        \"default\": \"./lib/module/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./lib/typescript/commonjs/src/index.d.ts\",\n        \"default\": \"./lib/commonjs/index.js\"\n      }\n    },\n    \"./package.json\": \"./package.json\",\n    \"./app.plugin.js\": \"./app.plugin.js\"\n  },\n  \"files\": [\n    \"src\",\n    \"lib\",\n    \"android\",\n    \"ios\",\n    \"cpp\",\n    \"nitrogen\",\n    \"nitro.json\",\n    \"*.podspec\",\n    \"react-native.config.js\",\n    \"app.plugin.js\",\n    \"LICENSE\",\n    \"README.md\",\n    \"!ios/build\",\n    \"!android/build\",\n    \"!android/gradle\",\n    \"!android/gradlew\",\n    \"!android/gradlew.bat\",\n    \"!android/local.properties\",\n    \"!**/__tests__\",\n    \"!**/__fixtures__\",\n    \"!**/__mocks__\",\n    \"!**/.*\"\n  ],\n  \"scripts\": {\n    \"postinstall\": \"bun run build || exit 0;\",\n    \"typecheck\": \"tsc\",\n    \"lint\": \"eslint \\\"**/*.{js,ts,tsx}\\\"\",\n    \"clean\": \"del-cli android/build example/android/build example/android/app/build example/ios/build lib\",\n    \"prepare\": \"bun run build\",\n    \"build\": \"bob build\",\n    \"specs\": \"nitrogen\",\n    \"release\": \"release-it --preRelease beta --npm.tag=beta\"\n  },\n  \"keywords\": [\n    \"react-native\",\n    \"ios\",\n    \"android\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/TheWidlarzGroup/react-native-video.git\"\n  },\n  \"author\": \"TheWidlarzGroup <hi@thewidlarzgroup.com> (https://github.com/TheWidlarzGroup)\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/TheWidlarzGroup/react-native-video/issues\"\n  },\n  \"homepage\": \"https://github.com/TheWidlarzGroup/react-native-video#readme\",\n  \"publishConfig\": {\n    \"registry\": \"https://registry.npmjs.org/\"\n  },\n  \"devDependencies\": {\n    \"@expo/config-plugins\": \"^10.0.2\",\n    \"@types/react\": \"^18.2.44\",\n    \"del-cli\": \"^5.1.0\",\n    \"eslint\": \"^8.51.0\",\n    \"eslint-config-prettier\": \"^9.0.0\",\n    \"eslint-plugin-prettier\": \"^5.0.1\",\n    \"nitrogen\": \"0.35.0\",\n    \"prettier\": \"^3.0.3\",\n    \"react\": \"18.3.1\",\n    \"react-native\": \"^0.77.0\",\n    \"@react-native/eslint-config\": \"^0.77.0\",\n    \"react-native-builder-bob\": \"^0.40.0\",\n    \"react-native-nitro-modules\": \"0.35.0\",\n    \"typescript\": \"^5.2.2\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"*\",\n    \"react-native\": \"*\",\n    \"react-native-nitro-modules\": \">=0.35.0\"\n  },\n  \"release-it\": {\n    \"npm\": {\n      \"publish\": true\n    },\n    \"git\": false,\n    \"github\": {\n      \"release\": false\n    },\n    \"hooks\": {\n      \"before:init\": \"bun typecheck && bun lint\",\n      \"after:bump\": \"bun run build && cp ../../LICENSE ./LICENSE && cp ../../README.md ./README.md\"\n    }\n  },\n  \"react-native-builder-bob\": {\n    \"source\": \"src\",\n    \"output\": \"lib\",\n    \"targets\": [\n      [\n        \"commonjs\",\n        {\n          \"esm\": true\n        }\n      ],\n      [\n        \"module\",\n        {\n          \"esm\": true\n        }\n      ],\n      [\n        \"typescript\",\n        {\n          \"project\": \"tsconfig.build.json\",\n          \"tsc\": \"../../node_modules/.bin/tsc\"\n        }\n      ]\n    ]\n  },\n  \"codegenConfig\": {\n    \"name\": \"RNCVideoViewSpec\",\n    \"type\": \"components\",\n    \"jsSrcsDir\": \"src/spec/fabric\",\n    \"android\": {\n      \"javaPackageName\": \"com.twg.video.react\"\n    },\n    \"ios\": {\n      \"componentProvider\": {\n        \"RNCVideoView\": \"RCTVideoViewComponentView\"\n      }\n    }\n  },\n  \"create-react-native-library\": {\n    \"type\": \"view-legacy\",\n    \"languages\": \"kotlin-swift\",\n    \"version\": \"0.41.2\"\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/react-native.config.js",
    "content": "// https://github.com/react-native-community/cli/blob/main/docs/dependencies.md\n\nmodule.exports = {\n  dependency: {\n    platforms: {\n      /**\n       * @type {import('@react-native-community/cli-types').IOSDependencyParams}\n       */\n      ios: {},\n      /**\n       * @type {import('@react-native-community/cli-types').AndroidDependencyParams}\n       */\n      android: {\n        packageImportPath: \"import com.twg.video.react.VideoPackage;\",\n        componentDescriptors: [\"RNCVideoViewComponentDescriptor\"],\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "packages/react-native-video/src/core/VideoPlayer.ts",
    "content": "import { Platform } from 'react-native';\nimport { NitroModules } from 'react-native-nitro-modules';\nimport { type VideoPlayer as VideoPlayerImpl } from '../spec/nitro/VideoPlayer.nitro';\nimport type { VideoPlayerSource } from '../spec/nitro/VideoPlayerSource.nitro';\nimport type { IgnoreSilentSwitchMode } from './types/IgnoreSilentSwitchMode';\nimport type { MixAudioMode } from './types/MixAudioMode';\nimport type { TextTrack } from './types/TextTrack';\nimport type { NoAutocomplete } from './types/Utils';\nimport type { VideoConfig, VideoSource } from './types/VideoConfig';\nimport {\n  tryParseNativeVideoError,\n  VideoRuntimeError,\n} from './types/VideoError';\nimport type { VideoPlayerBase } from './types/VideoPlayerBase';\nimport type { VideoPlayerStatus } from './types/VideoPlayerStatus';\nimport { createPlayer } from './utils/playerFactory';\nimport { createSource } from './utils/sourceFactory';\nimport { VideoPlayerEvents } from './VideoPlayerEvents';\n\nclass VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {\n  private _player: VideoPlayerImpl | undefined;\n  private _releaseTimeout: ReturnType<typeof setTimeout> | undefined;\n\n  protected get player(): VideoPlayerImpl {\n    if (this._player === undefined) {\n      throw new VideoRuntimeError(\n        'player/released',\n        \"You can't access player after it's released\"\n      );\n    }\n\n    return this._player;\n  }\n\n  constructor(source: VideoSource | VideoConfig | VideoPlayerSource) {\n    const hybridSource = createSource(source);\n    const player = createPlayer(hybridSource);\n\n    // Initialize events\n    super(player.eventEmitter);\n    this._player = player;\n  }\n\n  /**\n   * Releases the player's native resources and releases native state.\n   * @internal\n   */\n  __destroy() {\n    if (this._player === undefined) return;\n\n    this.clearAllEvents();\n\n    try {\n      this.player.release();\n    } catch (error) {\n      // Best effort cleanup: teardown must never crash app unmount.\n      console.error('Failed to cleanup native player resources', error);\n    }\n\n    // We leave hybrid object to be cleaned up by garbage collector\n    // So we update memory size to ensure that memory is released\n    // when needed\n    this.updateMemorySize();\n\n    // We wait for 5s to let late events that were triggered before release to be processed\n    if (this._releaseTimeout !== undefined) {\n      clearTimeout(this._releaseTimeout);\n    }\n\n    this._releaseTimeout = setTimeout(() => {\n      this._player = undefined;\n      this._releaseTimeout = undefined;\n    }, 5000);\n  }\n\n  /**\n   * Returns the native (hybrid) player instance.\n   * Should not be used outside of the module.\n   * @internal\n   */\n  __getNativePlayer() {\n    return this.player;\n  }\n\n  /**\n   * Handles parsing native errors to VideoRuntimeError and calling onError if provided\n   * @internal\n   */\n  private throwError(error: unknown) {\n    const parsedError = tryParseNativeVideoError(error);\n\n    if (\n      parsedError instanceof VideoRuntimeError &&\n      this.triggerJSEvent('onError', parsedError as VideoRuntimeError)\n    ) {\n      // We don't throw errors if onError is provided\n      return;\n    }\n\n    throw parsedError;\n  }\n\n  /**\n   * Updates the memory size of the player and its source. Should be called after any operation that changes the memory size of the player or its source.\n   * @internal\n   */\n  private updateMemorySize() {\n    NitroModules.updateMemorySize(this.player);\n    NitroModules.updateMemorySize(this.player.source);\n  }\n\n  /**\n   * Wraps a promise to try parsing native errors to VideoRuntimeError\n   * @internal\n   */\n  private wrapPromise<T>(promise: Promise<T>) {\n    return new Promise<T>((resolve, reject) => {\n      promise.then(resolve).catch((error) => {\n        reject(this.throwError(error));\n      });\n    });\n  }\n\n  // Source\n  get source(): VideoPlayerSource {\n    return this.player.source;\n  }\n\n  // Status\n  get status(): VideoPlayerStatus {\n    return this.player.status;\n  }\n\n  // Duration\n  get duration(): number {\n    return this.player.duration;\n  }\n\n  // Volume\n  get volume(): number {\n    return this.player.volume;\n  }\n\n  set volume(value: number) {\n    this.player.volume = value;\n  }\n\n  // Current Time\n  get currentTime(): number {\n    return this.player.currentTime;\n  }\n\n  set currentTime(value: number) {\n    this.player.currentTime = value;\n  }\n\n  // Muted\n  get muted(): boolean {\n    return this.player.muted;\n  }\n\n  set muted(value: boolean) {\n    this.player.muted = value;\n  }\n\n  // Loop\n  get loop(): boolean {\n    return this.player.loop;\n  }\n\n  set loop(value: boolean) {\n    this.player.loop = value;\n  }\n\n  // Rate\n  get rate(): number {\n    return this.player.rate;\n  }\n\n  set rate(value: number) {\n    this.player.rate = value;\n  }\n\n  // Mix Audio Mode\n  get mixAudioMode(): MixAudioMode {\n    return this.player.mixAudioMode;\n  }\n\n  set mixAudioMode(value: MixAudioMode) {\n    this.player.mixAudioMode = value;\n  }\n\n  // Ignore Silent Switch Mode\n  get ignoreSilentSwitchMode(): IgnoreSilentSwitchMode {\n    return this.player.ignoreSilentSwitchMode;\n  }\n\n  set ignoreSilentSwitchMode(value: IgnoreSilentSwitchMode) {\n    if (__DEV__ && !['ios'].includes(Platform.OS)) {\n      console.warn(\n        'ignoreSilentSwitchMode is not supported on this platform, it wont have any effect'\n      );\n    }\n\n    this.player.ignoreSilentSwitchMode = value;\n  }\n\n  // Play In Background\n  get playInBackground(): boolean {\n    return this.player.playInBackground;\n  }\n\n  set playInBackground(value: boolean) {\n    this.player.playInBackground = value;\n  }\n\n  // Play When Inactive\n  get playWhenInactive(): boolean {\n    return this.player.playWhenInactive;\n  }\n\n  set playWhenInactive(value: boolean) {\n    this.player.playWhenInactive = value;\n  }\n\n  // Is Playing\n  get isPlaying(): boolean {\n    return this.player.isPlaying;\n  }\n\n  get showNotificationControls(): boolean {\n    return this.player.showNotificationControls;\n  }\n\n  set showNotificationControls(value: boolean) {\n    this.player.showNotificationControls = value;\n  }\n\n  async initialize(): Promise<void> {\n    await this.wrapPromise(this.player.initialize());\n\n    this.updateMemorySize();\n  }\n\n  async preload(): Promise<void> {\n    await this.wrapPromise(this.player.preload());\n\n    this.updateMemorySize();\n  }\n\n  /**\n   * Releases the player's native resources and releases native state.\n   * After calling this method, the player is no longer usable.\n   * Accessing any properties or methods of the player after calling this method will throw an error.\n   * If you want to clean player resource use `replaceSourceAsync` with `null` instead.\n   */\n  release(): void {\n    this.__destroy();\n  }\n\n  play(): void {\n    try {\n      this.player.play();\n    } catch (error) {\n      this.throwError(error);\n    }\n  }\n\n  pause(): void {\n    try {\n      this.player.pause();\n    } catch (error) {\n      this.throwError(error);\n    }\n  }\n\n  seekBy(time: number): void {\n    try {\n      this.player.seekBy(time);\n    } catch (error) {\n      this.throwError(error);\n    }\n  }\n\n  seekTo(time: number): void {\n    try {\n      this.player.seekTo(time);\n    } catch (error) {\n      this.throwError(error);\n    }\n  }\n\n  async replaceSourceAsync(\n    source: VideoSource | VideoConfig | NoAutocomplete<VideoPlayerSource> | null\n  ): Promise<void> {\n    this.updateMemorySize();\n\n    await this.wrapPromise(\n      this.player.replaceSourceAsync(\n        source === null ? null : createSource(source)\n      )\n    );\n\n    this.updateMemorySize();\n  }\n\n  // Text Track Management\n  getAvailableTextTracks(): TextTrack[] {\n    try {\n      return this.player.getAvailableTextTracks();\n    } catch (error) {\n      this.throwError(error);\n      return [];\n    }\n  }\n\n  selectTextTrack(textTrack: TextTrack | null): void {\n    try {\n      this.player.selectTextTrack(textTrack);\n    } catch (error) {\n      this.throwError(error);\n    }\n  }\n\n  // Selected Text Track\n  get selectedTrack(): TextTrack | undefined {\n    return this.player.selectedTrack;\n  }\n}\n\nexport { VideoPlayer };\n"
  },
  {
    "path": "packages/react-native-video/src/core/VideoPlayerEvents.ts",
    "content": "import type {\n  ListenerSubscription,\n  VideoPlayerEventEmitter,\n} from '../spec/nitro/VideoPlayerEventEmitter.nitro';\nimport {\n  ALL_PLAYER_EVENTS,\n  type JSVideoPlayerEvents,\n  type AllPlayerEvents as PlayerEvents,\n} from './types/Events';\n\nexport class VideoPlayerEvents {\n  protected eventEmitter: VideoPlayerEventEmitter;\n  protected jsEventListeners: Partial<\n    Record<keyof JSVideoPlayerEvents, Set<(..._params: any[]) => void>>\n  > = {};\n\n  protected readonly supportedEvents: (keyof PlayerEvents)[] =\n    ALL_PLAYER_EVENTS;\n\n  constructor(eventEmitter: VideoPlayerEventEmitter) {\n    this.eventEmitter = eventEmitter;\n  }\n\n  protected triggerJSEvent<Event extends keyof JSVideoPlayerEvents>(\n    event: Event,\n    ...params: Parameters<JSVideoPlayerEvents[Event]>\n  ): boolean {\n    if (!this.jsEventListeners[event]) return false;\n    this.jsEventListeners[event]?.forEach((fn) => fn(...params));\n    return true;\n  }\n\n  /**\n   * Adds a listener for a player event.\n   * @throw Error if the event is not supported.\n   * @param event - The event to add a listener for.\n   * @param callback - The callback to call when the event is triggered.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addEventListener<Event extends keyof PlayerEvents>(\n    event: Event,\n    callback: PlayerEvents[Event]\n  ): ListenerSubscription {\n    switch (event) {\n      // ----------------- JS Events -----------------\n      case 'onError':\n        this.jsEventListeners.onError ??= new Set();\n        this.jsEventListeners.onError.add(\n          callback as JSVideoPlayerEvents['onError']\n        );\n        return {\n          remove: () =>\n            this.jsEventListeners.onError?.delete(\n              callback as JSVideoPlayerEvents['onError']\n            ),\n        };\n      // ----------------- Native Events -----------------\n      case 'onAudioBecomingNoisy':\n        return this.eventEmitter.addOnAudioBecomingNoisyListener(\n          callback as PlayerEvents['onAudioBecomingNoisy']\n        );\n      case 'onAudioFocusChange':\n        return this.eventEmitter.addOnAudioFocusChangeListener(\n          callback as PlayerEvents['onAudioFocusChange']\n        );\n      case 'onBandwidthUpdate':\n        return this.eventEmitter.addOnBandwidthUpdateListener(\n          callback as PlayerEvents['onBandwidthUpdate']\n        );\n      case 'onBuffer':\n        return this.eventEmitter.addOnBufferListener(\n          callback as PlayerEvents['onBuffer']\n        );\n      case 'onControlsVisibleChange':\n        return this.eventEmitter.addOnControlsVisibleChangeListener(\n          callback as PlayerEvents['onControlsVisibleChange']\n        );\n      case 'onEnd':\n        return this.eventEmitter.addOnEndListener(\n          callback as PlayerEvents['onEnd']\n        );\n      case 'onExternalPlaybackChange':\n        return this.eventEmitter.addOnExternalPlaybackChangeListener(\n          callback as PlayerEvents['onExternalPlaybackChange']\n        );\n      case 'onLoad':\n        return this.eventEmitter.addOnLoadListener(\n          callback as PlayerEvents['onLoad']\n        );\n      case 'onLoadStart':\n        return this.eventEmitter.addOnLoadStartListener(\n          callback as PlayerEvents['onLoadStart']\n        );\n      case 'onPlaybackStateChange':\n        return this.eventEmitter.addOnPlaybackStateChangeListener(\n          callback as PlayerEvents['onPlaybackStateChange']\n        );\n      case 'onPlaybackRateChange':\n        return this.eventEmitter.addOnPlaybackRateChangeListener(\n          callback as PlayerEvents['onPlaybackRateChange']\n        );\n      case 'onProgress':\n        return this.eventEmitter.addOnProgressListener(\n          callback as PlayerEvents['onProgress']\n        );\n      case 'onReadyToDisplay':\n        return this.eventEmitter.addOnReadyToDisplayListener(\n          callback as PlayerEvents['onReadyToDisplay']\n        );\n      case 'onSeek':\n        return this.eventEmitter.addOnSeekListener(\n          callback as PlayerEvents['onSeek']\n        );\n      case 'onTimedMetadata':\n        return this.eventEmitter.addOnTimedMetadataListener(\n          callback as PlayerEvents['onTimedMetadata']\n        );\n      case 'onTextTrackDataChanged':\n        return this.eventEmitter.addOnTextTrackDataChangedListener(\n          callback as PlayerEvents['onTextTrackDataChanged']\n        );\n      case 'onTrackChange':\n        return this.eventEmitter.addOnTrackChangeListener(\n          callback as PlayerEvents['onTrackChange']\n        );\n      case 'onVolumeChange':\n        return this.eventEmitter.addOnVolumeChangeListener(\n          callback as PlayerEvents['onVolumeChange']\n        );\n      case 'onStatusChange':\n        return this.eventEmitter.addOnStatusChangeListener(\n          callback as PlayerEvents['onStatusChange']\n        );\n      default:\n        throw new Error(`[React Native Video] Unsupported event: ${event}`);\n    }\n  }\n\n  /**\n   * Clears all events from the event emitter.\n   */\n  clearAllEvents() {\n    this.jsEventListeners = {};\n    this.eventEmitter.clearAllListeners();\n  }\n}\n"
  },
  {
    "path": "packages/react-native-video/src/core/hooks/useEvent.ts",
    "content": "import { useEffect } from 'react';\nimport { VideoPlayer } from '../VideoPlayer';\nimport { type AllPlayerEvents } from '../types/Events';\n\n/**\n * Attaches an event listener to a `VideoPlayer` instance for a specified event.\n *\n * @param player - The player to attach the event to\n * @param event - The name of the event to attach the callback to\n * @param callback - The callback for the event\n */\nexport const useEvent = <T extends keyof AllPlayerEvents>(\n  player: VideoPlayer,\n  event: T,\n  callback: AllPlayerEvents[T]\n) => {\n  useEffect(() => {\n    const subscription = player.addEventListener(event, callback);\n\n    return () => {\n      subscription.remove();\n    };\n  }, [player, event, callback]);\n};\n"
  },
  {
    "path": "packages/react-native-video/src/core/hooks/useManagedInstance.ts",
    "content": "import {\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  type DependencyList,\n} from 'react';\n\n/**\n * @internal\n * A hook that helps to manage the lifecycle of a native instance in a React component.\n * It allows instance to be recreated when dependencies change, but not when the component is hot reloaded.\n *\n * @param config.factory - The factory function that creates the instance.\n * @param config.cleanup - The cleanup function that destroys the instance.\n * @param config.dependenciesEqualFn - The function that compares the dependencies.\n *\n * @param dependencies - The dependencies array.\n * @returns The managed instance.\n */\nexport const useManagedInstance = <T, D extends DependencyList[number]>(\n  config: {\n    factory: () => T;\n    cleanup: (object: T) => void;\n    dependenciesEqualFn?: (a: D, b?: D) => boolean;\n  },\n  dependencies: D[]\n): T => {\n  const { factory, cleanup, dependenciesEqualFn } = config;\n\n  const objectRef = useRef<T | null>(null);\n  const isFastRefresh = useRef(false);\n  const previousDependencies = useRef(dependencies);\n\n  // Wee need to force a \"re-render\" to recalculate the object\n  const [released, setReleased] = useState(false);\n\n  if (objectRef.current == null) {\n    objectRef.current = factory();\n  }\n\n  const object = useMemo(() => {\n    let newObject = objectRef.current;\n\n    const dependenciesChanged =\n      previousDependencies.current?.length === dependencies.length &&\n      dependencies.every(\n        (value, index) =>\n          dependenciesEqualFn?.(value, previousDependencies.current[index]) ??\n          value === previousDependencies.current[index]\n      );\n\n    if (!newObject || !dependenciesChanged || released) {\n      // Destroy the old object\n      if (objectRef.current) {\n        cleanup(objectRef.current);\n        objectRef.current = null;\n      }\n\n      // Create a new object\n      newObject = factory();\n      objectRef.current = newObject;\n      setReleased(false);\n\n      // Update the previous dependencies\n      previousDependencies.current = dependencies;\n    } else {\n      // If useMemo is re-evaluated, but dependencies are the same\n      // and object is still the same, we can assume that that\n      // the component is being hot reloaded\n      isFastRefresh.current = true;\n    }\n\n    return newObject;\n\n    // factory and cleanup are stable, so we don't need to re-evaluate\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [...dependencies, released]);\n\n  useEffect(() => {\n    isFastRefresh.current = false;\n\n    return () => {\n      if (!isFastRefresh.current && objectRef.current) {\n        cleanup(objectRef.current);\n        objectRef.current = null;\n        setReleased(true);\n      }\n    };\n\n    // factory and cleanup are stable, so we don't need to re-evaluate\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  return object;\n};\n"
  },
  {
    "path": "packages/react-native-video/src/core/hooks/useVideoPlayer.ts",
    "content": "import { useRef } from 'react';\nimport type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';\nimport type { NoAutocomplete } from '../types/Utils';\nimport type { VideoConfig, VideoSource } from '../types/VideoConfig';\nimport { isVideoPlayerSource } from '../utils/sourceFactory';\nimport { VideoPlayer } from '../VideoPlayer';\nimport { useManagedInstance } from './useManagedInstance';\n\nconst sourceEqual = <T extends VideoConfig | VideoSource | VideoPlayerSource>(\n  a: T,\n  b?: T\n) => {\n  if (isVideoPlayerSource(a) && isVideoPlayerSource(b)) {\n    return a.equals(b);\n  }\n\n  return JSON.stringify(a) === JSON.stringify(b);\n};\n\n/**\n * Creates a `VideoPlayer` instance and manages its lifecycle.\n *\n * if `initializeOnCreation` is true (default), the `setup` function will be called when the player is started loading source.\n * if `initializeOnCreation` is false, the `setup` function will be called when the player is created. changes made to player made before initializing will be overwritten when initializing.\n *\n * @param source - The source of the video to play\n * @param setup - A function to setup the player\n * @returns The `VideoPlayer` instance\n */\nexport const useVideoPlayer = (\n  source: VideoConfig | VideoSource | NoAutocomplete<VideoPlayerSource>,\n  setup?: (player: VideoPlayer) => void\n) => {\n  const setupCalled = useRef(false);\n\n  return useManagedInstance(\n    {\n      factory: () => {\n        const player = new VideoPlayer(source);\n\n        if (setup === undefined) {\n          return player;\n        }\n\n        if (player.source.config.initializeOnCreation !== false) {\n          // if source is small video, it can happen that onLoadStart is called before we set event from JS\n          // Thats why we adding event listener and calling setup once if player is loading or ready to play\n          // That way we ensure that setup is always called\n\n          const callSetupOnce = () => {\n            if (!setupCalled.current) {\n              setupCalled.current = true;\n              setup?.(player);\n            }\n          };\n\n          player.addEventListener('onLoadStart', callSetupOnce);\n          player.addEventListener('onStatusChange', callSetupOnce);\n        } else {\n          setup?.(player);\n        }\n\n        return player;\n      },\n      cleanup: (player) => {\n        player.__destroy();\n        setupCalled.current = false;\n      },\n      dependenciesEqualFn: sourceEqual,\n    },\n    [JSON.stringify(source)]\n  );\n};\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/BufferConfig.ts",
    "content": "export interface LivePlaybackParams {\n  /**\n   * Minimum playback speed for catching up to target live offset.\n   * @platform android\n   */\n  minPlaybackSpeed?: number;\n  /**\n   * Maximum playback speed for catching up to target live offset.\n   * @platform android\n   */\n  maxPlaybackSpeed?: number;\n  /**\n   * Maximum allowed live offset. The player won’t exceed this limit.\n   * @platform android\n   */\n  maxOffsetMs?: number;\n  /**\n   * Minimum allowed live offset. The player won’t go below this limit.\n   * @platform android\n   */\n  minOffsetMs?: number;\n  /**\n   * Target live offset. The player will try to maintain this offset.\n   * @platform android, ios, visionOS, tvOS\n   */\n  targetOffsetMs?: number;\n}\n\ninterface Resolution {\n  width: number;\n  height: number;\n}\n\nexport interface BufferConfig {\n  /**\n   * Configuration for live playback.\n   */\n  livePlayback?: LivePlaybackParams;\n\n  // -------- Android specific options --------\n\n  /**\n   * Minimum duration (ms) the player will attempt to keep buffered.\n   * @default 5000\n   * @platform android\n   */\n  minBufferMs?: number;\n  /**\n   * Maximum duration (ms) the player will attempt to keep buffered.\n   * @default 10000\n   * @platform android\n   */\n  maxBufferMs?: number;\n  /**\n   * Duration (ms) of media that must be buffered for playback to start or resume following a user action such as a seek.\n   * @default 1000\n   * @platform android\n   */\n  bufferForPlaybackMs?: number;\n  /**\n   * Duration (ms) of media that must be buffered for playback to resume after a rebuffer.\n   * @default 2000\n   * @platform android\n   */\n  bufferForPlaybackAfterRebufferMs?: number;\n  /**\n   * Duration (ms) of media that must be buffered before it can be played from the back buffer.\n   * @platform android\n   */\n  backBufferDurationMs?: number;\n\n  // -------- iOS specific options --------\n\n  /**\n   * The preferred duration (ms) of media that the player will attempt to retain in the buffer.\n   * @platform ios, visionOS, tvOS\n   */\n  preferredForwardBufferDurationMs?: number;\n  /**\n   * The desired limit, in bits per second, of network bandwidth used for loading the current item.\n   *\n   * You can use {@linkcode preferredPeakBitRateForExpensiveNetworks} to set a different bit rate when on an expensive network (e.g. cellular).\n   * @platform ios, visionOS, tvOS\n   */\n  preferredPeakBitRate?: number;\n  /**\n   * The preferred maximum resolution of the video.\n   *\n   * You can use {@linkcode preferredMaximumResolutionForExpensiveNetworks} to set a different resolution when on an expensive network (e.g. cellular).\n   * @platform ios, visionOS, tvOS\n   */\n  preferredMaximumResolution?: Resolution;\n  /**\n   * The desired limit, in bits per second, of network bandwidth used for loading the current item when on an expensive network (e.g. cellular).\n   * @platform ios, visionOS, tvOS\n   */\n  preferredPeakBitRateForExpensiveNetworks?: number;\n  /**\n   * The preferred maximum resolution of the video when on an expensive network (e.g. cellular).\n   * @platform ios, visionOS, tvOS\n   */\n  preferredMaximumResolutionForExpensiveNetworks?: Resolution;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/DrmParams.ts",
    "content": "/**\n * Headers type specifically for DRM license requests\n */\n\nexport interface DrmParams {\n  /**\n   * The license URL for the DRM license request.\n   * @platform Android, iOS, visionOS\n   */\n  licenseUrl?: string;\n  /**\n   * The certificate URL for the DRM license request.\n   * @platform iOS, visionOS\n   */\n  certificateUrl?: string;\n  /**\n   * The content ID for the DRM license request.\n   * @platform iOS, visionOS\n   */\n  contentId?: string;\n  /**\n   * The type of DRM to use.\n   * @platform Android, iOS, visionOS\n   */\n  type?: DRMType;\n  /**\n   * The headers to send with the DRM license request.\n   * @platform Android, iOS, visionOS\n   */\n  licenseHeaders?: Record<string, string>;\n  /**\n   * Whether to allow multiple sessions for the DRM license request.\n   * @platform Android\n   */\n  multiSession?: boolean;\n  /**\n   * A function to get the license for the DRM license request.\n   * @platform iOS\n   */\n  getLicense?: (payload: OnGetLicensePayload) => Promise<string>;\n}\n\ninterface OnGetLicensePayload {\n  /**\n   * The content ID for the DRM license request.\n   * This is typically a unique identifier for the content being played.\n   */\n  contentId: string;\n  /**\n   * The license URL for the DRM license request.\n   */\n  licenseUrl: string;\n  /**\n   * The key URL for the DRM license request.\n   * Typically starts with starting with skd:// or clearkey://\n   */\n  keyUrl: string;\n  /**\n   * The secure playback context (SPC) for the DRM license request.\n   * This is typically a base64-encoded string that contains information about the playback environment.\n   */\n  spc: string;\n}\n\ntype DRMType = 'widevine' | 'fairplay' | (string & {});\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/Events.ts",
    "content": "import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';\nimport type { TextTrack } from './TextTrack';\nimport type { VideoRuntimeError } from './VideoError';\nimport type { VideoOrientation } from './VideoOrientation';\nimport type { VideoPlayerStatus } from './VideoPlayerStatus';\n\nexport interface VideoPlayerEvents {\n  /**\n   * Called when the audio becomes noisy.\n   * @platform Android\n   */\n  onAudioBecomingNoisy: () => void;\n  /**\n   * Called when the audio focus changes.\n   * @param hasAudioFocus Whether the audio has focus.\n   * @platform Android\n   */\n  onAudioFocusChange: (hasAudioFocus: boolean) => void;\n  /**\n   * Called when the bandwidth of the video changes.\n   */\n  onBandwidthUpdate: (data: BandwidthData) => void;\n  /**\n   * Called when the video is buffering.\n   * @param buffering Whether the video is buffering.\n   */\n  onBuffer: (buffering: boolean) => void;\n  /**\n   * Called when the video view's controls visibility changes.\n   * @param visible Whether the video view's controls are visible.\n   */\n  onControlsVisibleChange: (visible: boolean) => void;\n  /**\n   * Called when the video ends.\n   */\n  onEnd: () => void;\n  /**\n   * Called when the external playback state changes.\n   * @param externalPlaybackActive Whether the external playback is active.\n   * @platform iOS\n   */\n  onExternalPlaybackChange: (externalPlaybackActive: boolean) => void;\n  /**\n   * Called when the video is loaded.\n   * @note onLoadStart -> initialize the player -> onLoad\n   */\n  onLoad: (data: onLoadData) => void;\n  /**\n   * Called when the video starts loading.\n   * @note onLoadStart -> initialize the player -> onLoad\n   */\n  onLoadStart: (data: onLoadStartData) => void;\n  /**\n   * Called when the player playback state changes.\n   */\n  onPlaybackStateChange: (data: onPlaybackStateChangeData) => void;\n  /**\n   * Called when the player playback rate changes.\n   */\n  onPlaybackRateChange: (rate: number) => void;\n  /**\n   * Called when the player progress changes.\n   */\n  onProgress: (data: onProgressData) => void;\n  /**\n   * Called when the video is ready to display.\n   */\n  onReadyToDisplay: () => void;\n  /**\n   * Called when the player seeks.\n   */\n  onSeek: (seekTime: number) => void;\n  /**\n   * Called when player receives timed metadata.\n   */\n  onTimedMetadata: (metadata: TimedMetadata) => void;\n  /**\n   * Called when the text track (currently displayed subtitle) data changes.\n   */\n  onTextTrackDataChanged: (texts: string[]) => void;\n  /**\n   * Called when the selected text track changes.\n   * @param track - The newly selected text track, or null if no track is selected\n   */\n  onTrackChange: (track: TextTrack | null) => void;\n  /**\n   * Called when the volume of the player changes.\n   */\n  onVolumeChange: (data: onVolumeChangeData) => void;\n  /**\n   * Called when the player status changes.\n   */\n  onStatusChange: (status: VideoPlayerStatus) => void;\n}\n\nexport interface JSVideoPlayerEvents {\n  onError: (error: VideoRuntimeError) => void;\n}\n\nexport type AllPlayerEvents = VideoPlayerEvents & JSVideoPlayerEvents;\n\nexport interface VideoViewEvents {\n  /**\n   * Called when the video view's picture in picture state changes.\n   * @param isInPictureInPicture Whether the video view is in picture in picture mode.\n   */\n  onPictureInPictureChange: (isInPictureInPicture: boolean) => void;\n  /**\n   * Called when the video view's fullscreen state changes.\n   * @param fullscreen Whether the video view is in fullscreen mode.\n   */\n  onFullscreenChange: (fullscreen: boolean) => void;\n  /**\n   * Called when the video view will enter fullscreen mode.\n   */\n  willEnterFullscreen: () => void;\n  /**\n   * Called when the video view will exit fullscreen mode.\n   */\n  willExitFullscreen: () => void;\n  /**\n   * Called when the video view will enter picture in picture mode.\n   */\n  willEnterPictureInPicture: () => void;\n  /**\n   * Called when the video view will exit picture in picture mode.\n   */\n  willExitPictureInPicture: () => void;\n}\n\nexport interface BandwidthData {\n  /**\n   * The bitrate of the video in bits per second.\n   */\n  bitrate: number;\n  /**\n   * The width of the video in pixels.\n   * @platform android\n   */\n  width?: number;\n  /**\n   * The height of the video in pixels.\n   * @platform Android\n   */\n  height?: number;\n}\n\nexport interface onLoadData {\n  /**\n   * The current time of the video in seconds.\n   */\n  currentTime: number;\n  /**\n   * The duration of the video in seconds.\n   * @note NaN if the duration is unknown.\n   */\n  duration: number;\n  /**\n   * The height of the video in pixels.\n   */\n  height: number;\n  /**\n   * The width of the video in pixels.\n   */\n  width: number;\n  /**\n   * The orientation of the video.\n   */\n  orientation: VideoOrientation;\n}\n\nexport type SourceType = 'local' | 'network';\n\nexport interface onLoadStartData {\n  /**\n   * The type of the source.\n   * @note `local` for local files, `network` for network sources.\n   */\n  sourceType: SourceType;\n  /**\n   * The source of the video.\n   */\n  source: VideoPlayerSource;\n}\n\nexport interface onPlaybackStateChangeData {\n  /**\n   * Whether the video is playing.\n   */\n  isPlaying: boolean;\n  /**\n   * Whether the video is buffering.\n   */\n  isBuffering: boolean;\n}\n\nexport interface onProgressData {\n  /**\n   * The current time of the video in seconds.\n   */\n  currentTime: number;\n  /**\n   * The time that player is able to play with only buffer.\n   */\n  bufferDuration: number;\n}\n\nexport type TimedMetadataObject = {\n  value: string;\n  identifier: string;\n};\n\nexport interface TimedMetadata {\n  /**\n   * The timed metadata of the video.\n   */\n  metadata: Array<TimedMetadataObject>;\n}\n\nexport interface onVolumeChangeData {\n  /**\n   * The volume of the player (0.0 = 0%, 1.0 = 100%).\n   */\n  volume: number;\n  /**\n   * Whether the player is muted.\n   */\n  muted: boolean;\n}\n\ntype CheckAllAndOnly<T, A extends readonly (keyof T)[]> =\n  // Missing keys?\n  Exclude<keyof T, A[number]> extends never\n    ? // Extra keys?\n      Exclude<A[number], keyof T> extends never\n      ? A\n      : ['Extra keys', Exclude<A[number], keyof T>]\n    : ['Missing keys', Exclude<keyof T, A[number]>];\n\nfunction allKeysOf<T>() {\n  return <A extends readonly (keyof T)[]>(...arr: A): CheckAllAndOnly<T, A> => {\n    return arr as CheckAllAndOnly<T, A>;\n  };\n}\n\nexport const ALL_PLAYER_EVENTS: (keyof AllPlayerEvents)[] =\n  allKeysOf<AllPlayerEvents>()(\n    'onAudioBecomingNoisy',\n    'onAudioFocusChange',\n    'onBandwidthUpdate',\n    'onBuffer',\n    'onControlsVisibleChange',\n    'onEnd',\n    'onError',\n    'onExternalPlaybackChange',\n    'onLoad',\n    'onLoadStart',\n    'onPlaybackStateChange',\n    'onPlaybackRateChange',\n    'onProgress',\n    'onReadyToDisplay',\n    'onSeek',\n    'onTimedMetadata',\n    'onTextTrackDataChanged',\n    'onTrackChange',\n    'onVolumeChange',\n    'onStatusChange'\n  );\n\nexport const ALL_VIEW_EVENTS: (keyof VideoViewEvents)[] =\n  allKeysOf<VideoViewEvents>()(\n    'onPictureInPictureChange',\n    'onFullscreenChange',\n    'willEnterFullscreen',\n    'willExitFullscreen',\n    'willEnterPictureInPicture',\n    'willExitPictureInPicture'\n  );\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/IgnoreSilentSwitchMode.ts",
    "content": "export type IgnoreSilentSwitchMode = 'auto' | 'ignore' | 'obey';\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/MixAudioMode.ts",
    "content": "export type MixAudioMode = 'mixWithOthers' | 'doNotMix' | 'duckOthers' | 'auto';\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/ResizeMode.ts",
    "content": "/**\n * Video resize modes that determine how video content is resized to fit the view\n *\n * - 'contain': Scale the video uniformly (maintain aspect ratio) so that it fits entirely within the view\n * - 'cover': Scale the video uniformly (maintain aspect ratio) so that it fills the entire view (may crop)\n * - 'stretch': Scale the video to fill the entire view without maintaining aspect ratio\n * - 'none': Do not resize the video - it will fallback to default behavior (contain)\n */\nexport type ResizeMode = 'contain' | 'cover' | 'stretch' | 'none';\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/TextTrack.ts",
    "content": "export interface TextTrack {\n  /**\n   * Unique identifier for the text track\n   */\n  id: string;\n\n  /**\n   * Display label for the text track\n   */\n  label: string;\n\n  /**\n   * Language code (ISO 639-1 or ISO 639-2)\n   * @example \"en\", \"es\", \"fr\"\n   */\n  language?: string;\n\n  /**\n   * Whether this track is currently selected\n   */\n  selected: boolean;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/Utils.ts",
    "content": "export type NoAutocomplete<T> = T & never;\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/VideoConfig.ts",
    "content": "import type { BufferConfig } from './BufferConfig';\nimport type { DrmParams } from './DrmParams';\n\nexport type VideoSource = number | string;\n\nexport type VideoConfig = {\n  /**\n   * The uri of the video.\n   * @example\n   * ```ts\n   * uri: 'https://example.com/video.mp4'\n   * // or\n   * uri: require('./assets/video.mp4')\n   * ```\n   */\n  uri: VideoSource;\n  /**\n   * The headers to be sent with the request.\n   */\n  headers?: Record<string, string>;\n  /**\n   * The DRM parameters to be used.\n   */\n  drm?: DrmParams;\n  /**\n   * The player buffer configuration.\n   */\n  bufferConfig?: BufferConfig;\n  /**\n   * The custom metadata to be associated with the video.\n   * This metadata can be used by the native player to show information about the video.\n   */\n  metadata?: CustomVideoMetadata;\n  /**\n   * The external subtitles to be used.\n   * @note on iOS, only WebVTT (.vtt) subtitles are supported (for HLS streams and MP4 files).\n   * @note on iOS, `label` can be overridden by player and there is no way to get around it.\n   * @example\n   * ```ts\n   * externalSubtitles: [\n   *   {\n   *     uri: 'https://example.com/subtitles_en.vtt',\n   *     label: 'English',\n   *     type: 'vtt',\n   *     language: 'en'\n   *   },\n   *   {\n   *     uri: 'https://example.com/subtitles_es.vtt',\n   *     label: 'Español',\n   *     type: 'vtt',\n   *     language: 'es'\n   *   }\n   * ]\n   * ```\n   */\n  externalSubtitles?: ExternalSubtitle[];\n  /**\n   * when the player is created, this flag will determine if native player should be initialized immediately.\n   * If set to true, the player will be initialized as soon as player is created\n   * If set to false, the player will need be initialized manually later\n   * @default true\n   */\n  initializeOnCreation?: boolean;\n};\n\n// @internal\nexport interface NativeVideoConfig extends VideoConfig {\n  // The uri should be resolved to string before creating the source\n  uri: string;\n  externalSubtitles?: NativeExternalSubtitle[];\n  drm?: NativeDrmParams;\n}\n\n/**\n * The type of the subtitle.\n * - `vtt` - WebVTT\n * - `srt` - SubRip\n * - `ssa` - SubStation Alpha\n * - `ass` - Advanced SubStation Alpha\n * - `auto` - Auto detect the subtitle type from the file extension\n *\n * @note `auto` is not available when uri have no extension.\n */\nexport type SubtitleType = 'vtt' | 'srt' | 'ssa' | 'ass' | 'auto';\n\ninterface ExternalSubtitleWithInferredType {\n  /**\n   * The uri of the subtitle.\n   * @note the uri must end with the subtitle type.\n   */\n  uri: `${string}.${SubtitleType}`;\n  /**\n   * The label for the subtitle.\n   */\n  label: string;\n  /**\n   * The type of the subtitle.\n   */\n  type?: SubtitleType;\n  /**\n   * The language code for the subtitle (ISO 639-1 or ISO 639-2).\n   * @example 'en', 'es', 'fr', 'de', 'zh-CN'\n   * @default 'und' (undefined)\n   */\n  language?: string;\n}\n\ninterface ExternalSubtitleWithCustomType {\n  /**\n   * The uri of the subtitle.\n   */\n  uri: string;\n  /**\n   * The label for the subtitle.\n   */\n  label: string;\n  /**\n   * The type of the subtitle.\n   */\n  type: Omit<SubtitleType, 'auto'>;\n  /**\n   * The language code for the subtitle (ISO 639-1 or ISO 639-2).\n   * @example 'en', 'es', 'fr', 'de', 'zh-CN'\n   * @default 'und' (undefined)\n   */\n  language?: string;\n}\n\nexport type ExternalSubtitle =\n  | ExternalSubtitleWithInferredType\n  | ExternalSubtitleWithCustomType;\n\ninterface NativeExternalSubtitle {\n  uri: string;\n  label: string;\n  type: SubtitleType;\n  language: string;\n}\n\ninterface NativeDrmParams extends DrmParams {\n  type?: string;\n}\n\ninterface CustomVideoMetadata {\n  title?: string;\n  subtitle?: string;\n  description?: string;\n  artist?: string;\n  imageUri?: string;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/VideoError.ts",
    "content": "export type LibraryError =\n  | 'library/deallocated'\n  | 'library/application-context-not-found';\n\nexport type PlayerError =\n  | 'player/released'\n  | 'player/not-initialized'\n  | 'player/asset-not-initialized'\n  | 'player/invalid-source';\n\nexport type SourceError =\n  | 'source/invalid-uri'\n  | 'source/missing-read-file-permission'\n  | 'source/file-does-not-exist'\n  | 'source/failed-to-initialize-asset'\n  | 'source/unsupported-content-type';\n\nexport type VideoViewError =\n  | 'view/not-found'\n  | 'view/deallocated'\n  | 'view/picture-in-picture-not-supported';\n\nexport type UnknownError = 'unknown/unknown';\n\nexport type VideoErrorCode =\n  | LibraryError\n  | PlayerError\n  | SourceError\n  | VideoViewError\n  | UnknownError;\n\nexport class VideoError<TCode extends VideoErrorCode> extends Error {\n  private readonly _code: TCode;\n  private readonly _message: string;\n  private readonly _stack?: string;\n\n  public get code(): TCode {\n    return this._code;\n  }\n  public get message(): string {\n    return this._message;\n  }\n\n  public get stack(): string | undefined {\n    return this._stack;\n  }\n\n  /**\n   * @internal\n   */\n  constructor(code: TCode, message: string, stack?: string) {\n    super(`[${code}]: ${message}`);\n    super.name = `[ReactNativeVideo] ${code}`;\n    super.message = message;\n    super.stack = stack;\n    this._code = code;\n    this._message = message;\n    this._stack = stack;\n  }\n\n  public toString(): string {\n    let string = `[${this.code}]: ${this.message}`;\n    return string;\n  }\n}\n\nexport class VideoComponentError extends VideoError<VideoViewError> {}\n\nexport class VideoRuntimeError extends VideoError<\n  LibraryError | PlayerError | SourceError | UnknownError\n> {}\n\n/**\n * Check if the message contains code and message\n */\nconst getCodeAndMessage = (\n  message: string\n): { code: string; message: string } | null => {\n  // (...){%@(match[1])::(match[2]);@%}(...)\n  const regex = /\\{%@([^:]+)::([^@]+)@%\\}/;\n  const match = message.match(regex);\n\n  if (\n    match &&\n    match.length === 3 &&\n    typeof match[1] === 'string' &&\n    typeof match[2] === 'string'\n  ) {\n    return {\n      code: match[1],\n      message: match[2],\n    };\n  }\n  return null;\n};\n\n/**\n * Check if the error has a stack property\n * If it does, it will try to parse the error message in the stack trace\n * and replace it with the proper code and message\n */\nconst maybeFixErrorStack = (error: object) => {\n  if ('stack' in error && typeof error.stack === 'string') {\n    const stack = error.stack;\n\n    // (...){%@(match[1])::(match[2]);@%}(...)\n    const regex = /\\{%@([^:]+)::([^@]+)@%\\}/;\n    const match = stack.match(regex);\n\n    if (\n      match &&\n      match.length === 3 &&\n      typeof match[1] === 'string' &&\n      typeof match[2] === 'string'\n    ) {\n      error.stack = error.stack.replace(regex, `[${match[1]}]: ${match[2]}`);\n    }\n  }\n};\n\nconst isVideoError = (\n  error: unknown\n): error is { code: string; message: string } =>\n  typeof error === 'object' &&\n  error != null &&\n  // @ts-expect-error error is still unknown\n  typeof error.message === 'string' &&\n  // @ts-expect-error error is still unknown\n  getCodeAndMessage(error.message) != null;\n\nconst hasStack = (error: unknown): error is { stack: string } =>\n  typeof error === 'object' &&\n  error != null &&\n  'stack' in error &&\n  typeof error.stack === 'string';\n\n/**\n * Tries to parse an error coming from native to a typed JS video error.\n * @param {VideoError} nativeError The native error instance. This is a JSON in the legacy native module architecture.\n * @returns A {@linkcode VideoRuntimeError} or {@linkcode VideoComponentError}, or the `nativeError` itself if it's not parsable\n * @method\n */\nexport const tryParseNativeVideoError = <T>(\n  nativeError: T\n): (VideoRuntimeError | VideoComponentError) | T => {\n  if (isVideoError(nativeError)) {\n    const result = getCodeAndMessage(nativeError.message);\n\n    if (result == null) {\n      return nativeError;\n    }\n\n    const { code, message } = result;\n\n    maybeFixErrorStack(nativeError);\n\n    if (code.startsWith('view')) {\n      return new VideoComponentError(\n        code as VideoViewError,\n        message,\n        hasStack(nativeError) ? nativeError.stack : undefined\n      );\n    }\n\n    return new VideoRuntimeError(\n      // @ts-expect-error the code is string, we narrow it down to TS union.\n      code,\n      message,\n      hasStack(nativeError) ? nativeError.stack : undefined\n    );\n  }\n\n  return nativeError;\n};\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/VideoInformation.ts",
    "content": "import type { Int64 } from 'react-native-nitro-modules';\nimport type { VideoOrientation } from './VideoOrientation';\n\nexport interface VideoInformation {\n  /**\n   * The bitrate of the video in kbps.\n   */\n  bitrate: number;\n\n  /**\n   * The width of the video in pixels.\n   */\n  width: number;\n\n  /**\n   * The height of the video in pixels.\n   */\n  height: number;\n\n  /**\n   * The duration of the video in seconds, or `-1` if not available.\n   */\n  duration: number;\n\n  /**\n   * The file size of the video in bytes, or `-1` if not available.\n   */\n  fileSize: Int64;\n\n  /**\n   * Whether the video is HDR.\n   */\n  isHDR: boolean;\n\n  /**\n   * Whether the video is live\n   */\n  isLive: boolean;\n\n  /**\n   * The orientation of the video.\n   * see {@link VideoOrientation}\n   */\n  orientation: VideoOrientation;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/VideoOrientation.ts",
    "content": "export type VideoOrientation =\n  | 'portrait'\n  | 'landscape'\n  | 'portrait-upside-down'\n  | 'landscape-left'\n  | 'landscape-right'\n  | 'square'\n  | 'unknown';\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/VideoPlayerBase.ts",
    "content": "import type { IgnoreSilentSwitchMode } from './IgnoreSilentSwitchMode';\nimport type { MixAudioMode } from './MixAudioMode';\nimport type { TextTrack } from './TextTrack';\nimport type { VideoPlayerSourceBase } from './VideoPlayerSourceBase';\nimport type { VideoPlayerStatus } from './VideoPlayerStatus';\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { VideoConfig } from './VideoConfig';\n\nexport interface VideoPlayerBase {\n  /**\n   * The source of the video.\n   * Source is immutable. To change the source, you need to call {@link replaceSourceAsync} method.\n   * see {@link VideoPlayerSourceBase}\n   */\n  readonly source: VideoPlayerSourceBase;\n\n  /**\n   * The status of the player.\n   * @param idle - The player is idle (source is not loaded)\n   * @param loading - The player is loading.\n   * @param readyToPlay - The player is ready to play (source is loaded).\n   * @param error - The player has an error.\n   */\n  readonly status: VideoPlayerStatus;\n\n  /**\n   * The current time of the video in seconds (1.0 = 1 sec).\n   * Returns NaN if the current time is not available.\n   */\n  readonly duration: number;\n\n  /**\n   * The volume of the video (0.0 = 0%, 1.0 = 100%).\n   * @note If the player is {@link muted}, the volume will be 0.0.\n   */\n  volume: number;\n\n  /**\n   * The duration of the video in seconds (1.0 = 1 sec).\n   * Returns NaN if the duration is not available.\n   */\n  currentTime: number;\n\n  /**\n   * Whether the player is muted.\n   */\n  muted: boolean;\n\n  /**\n   * Whether the player is looped.\n   */\n  loop: boolean;\n\n  /**\n   * Controls the speed at which the player should play.\n   * @note if rate is = 0, it will pause video.\n   */\n  rate: number;\n\n  /**\n   * Controls the audio mixing mode of the player.\n   *\n   * - `mixWithOthers` - Mix with other players.\n   * - `doNotMix` - Do not mix with other players.\n   * - `duckOthers` - Duck other players.\n   * - `auto` - uses default behavior for player.\n   *\n   * default is `auto`.\n   */\n  mixAudioMode: MixAudioMode;\n\n  /**\n   * Controls the silent switch mode of the player.\n   * @note This is only supported on iOS.\n   *\n   * - `auto` - uses default behavior for player.\n   * - `ignore` - ignore the silent switch.\n   * - `obey` - obey the silent switch.\n   */\n  ignoreSilentSwitchMode: IgnoreSilentSwitchMode;\n\n  /**\n   * Whether the player should play in background.\n   *\n   * - `true` - play in background.\n   * - `false` - pause in background (default).\n   *\n   * @note this can override {@link playWhenInactive}.\n   */\n  playInBackground: boolean;\n\n  /**\n   * Whether the player should play when the app is inactive (user opened control center).\n   *\n   * - `true` - play when the app is inactive.\n   * - `false` - pause when the app is inactive (default).\n   *\n   * @note this can be overridden by {@link playInBackground}.\n   * @note This is only supported on iOS.\n   */\n  playWhenInactive: boolean;\n\n  /**\n   * Whether the player is playing.\n   * @note This is a read-only property.\n   * @note To pause/resume the player, you need to use {@link play} and {@link pause} methods.\n   */\n  readonly isPlaying: boolean;\n\n  /**\n   * Manually initialize the player. You don't need to call this method manually, unless you set `initializeOnCreation` to false in {@link VideoConfig}\n   */\n  initialize(): Promise<void>;\n\n  /**\n   * Preload the video.\n   * This is useful to avoid delay when the user plays the video.\n   * Preloading too many videos can lead to memory issues or performance issues.\n   */\n  preload(): Promise<void>;\n\n  /**\n   * Start playback of player.\n   */\n  play(): void;\n\n  /**\n   * Pause playback of player.\n   */\n  pause(): void;\n\n  /**\n   * Seek by given time.\n   * If the time is negative, it will seek backward.\n   * time will be clamped if it is out of range (0 ~ {@link duration}).\n   * @param time - The time to seek from current time in seconds.\n   */\n  seekBy(time: number): void;\n\n  /**\n   * Seek to a specific time in the video.\n   * @param time - The time to seek to in seconds.\n   * @note This have same effect as {@link currentTime} setter.\n   * @note time will be clamped if it is out of range (0 ~ {@link duration}).\n   */\n  seekTo(time: number): void;\n\n  /**\n   * Replace the current source of the player.\n   * @param source - The new source of the video.\n   * @note If you want to clear the source, you can pass null.\n   * see {@link VideoPlayerSourceBase}\n   */\n  replaceSourceAsync(source: VideoPlayerSourceBase | null): Promise<void>;\n\n  /**\n   * Get all available text tracks for the current source.\n   * @returns Array of available text tracks\n   */\n  getAvailableTextTracks(): TextTrack[];\n\n  /**\n   * Select a text track to display.\n   * @param textTrack - Text track to select, or null to unselect current track\n   */\n  selectTextTrack(textTrack: TextTrack | null): void;\n\n  /**\n   * Get the currently selected text track.\n   * @returns The currently selected text track, or undefined if none is selected\n   */\n  readonly selectedTrack?: TextTrack;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/VideoPlayerSourceBase.ts",
    "content": "import type { NativeVideoConfig } from './VideoConfig';\nimport type { VideoInformation } from './VideoInformation';\n\nexport interface VideoPlayerSourceBase {\n  /**\n   * The URI of the asset.\n   */\n  readonly uri: string;\n\n  /**\n   * The config of the asset.\n   */\n  readonly config: NativeVideoConfig;\n\n  /**\n   * Get the information about the asset.\n   */\n  getAssetInformationAsync(): Promise<VideoInformation>;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/core/types/VideoPlayerStatus.ts",
    "content": "/**\n * The status of the player.\n * @param idle - The player is idle (source is not loaded)\n * @param loading - The player is loading (source is loading).\n * @param readyToPlay - The player is ready to play (source is loaded).\n * @param error - The player has an error (source is not loaded).\n */\nexport type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error';\n"
  },
  {
    "path": "packages/react-native-video/src/core/utils/playerFactory.ts",
    "content": "import { NitroModules } from 'react-native-nitro-modules';\nimport type {\n  VideoPlayer,\n  VideoPlayerFactory,\n} from '../../spec/nitro/VideoPlayer.nitro';\nimport type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';\nimport type { VideoConfig, VideoSource } from '../types/VideoConfig';\nimport { createSource, isVideoPlayerSource } from './sourceFactory';\nimport { tryParseNativeVideoError } from '../types/VideoError';\n\nconst VideoPlayerFactory =\n  NitroModules.createHybridObject<VideoPlayerFactory>('VideoPlayerFactory');\n\n/**\n * @internal\n * Creates a Native VideoPlayer instance.\n *\n * @param source - The source of the video to play\n * @returns The Native VideoPlayer instance\n */\nexport const createPlayer = (\n  source: VideoSource | VideoConfig | VideoPlayerSource\n): VideoPlayer => {\n  try {\n    if (isVideoPlayerSource(source)) {\n      return VideoPlayerFactory.createPlayer(source);\n    }\n\n    return VideoPlayerFactory.createPlayer(createSource(source));\n  } catch (error) {\n    throw tryParseNativeVideoError(error);\n  }\n};\n"
  },
  {
    "path": "packages/react-native-video/src/core/utils/sourceFactory.ts",
    "content": "import { Image, Platform } from 'react-native';\nimport { NitroModules } from 'react-native-nitro-modules';\nimport type {\n  VideoPlayerSource,\n  VideoPlayerSourceFactory,\n} from '../../spec/nitro/VideoPlayerSource.nitro';\nimport type {\n  ExternalSubtitle,\n  NativeVideoConfig,\n  SubtitleType,\n  VideoConfig,\n  VideoSource,\n} from '../types/VideoConfig';\nimport {\n  tryParseNativeVideoError,\n  VideoRuntimeError,\n} from '../types/VideoError';\n\nconst VideoPlayerSourceFactory =\n  NitroModules.createHybridObject<VideoPlayerSourceFactory>(\n    'VideoPlayerSourceFactory'\n  );\n\nexport const isVideoPlayerSource = (obj: any): obj is VideoPlayerSource => {\n  return (\n    obj && // obj is not null\n    typeof obj === 'object' && // obj is an object\n    'name' in obj && // obj has a name property\n    obj.name === 'VideoPlayerSource' // obj.name is 'VideoPlayerSource'\n  );\n};\n\n/**\n * Creates a `VideoPlayerSource` instance from a URI (string).\n *\n * @param uri - The URI of the video to play\n * @returns The `VideoPlayerSource` instance\n */\nexport const createSourceFromUri = (uri: string) => {\n  if (!uri || typeof uri !== 'string') {\n    throw new Error('RNV: Invalid source. The URI must be a non-empty string.');\n  }\n\n  try {\n    return VideoPlayerSourceFactory.fromUri(uri);\n  } catch (error) {\n    throw tryParseNativeVideoError(error);\n  }\n};\n\n/**\n * Creates a `VideoPlayerSource` instance from a `VideoConfig`.\n *\n * @note The `uri` property is required to be a string.\n *\n * @param config - The `VideoConfig` to create the `VideoPlayerSource` from\n * @returns The `VideoPlayerSource` instance\n */\nexport const createSourceFromVideoConfig = (\n  config: VideoConfig & { uri: string }\n) => {\n  if (!config.uri || typeof config.uri !== 'string') {\n    throw new VideoRuntimeError('source/invalid-uri', 'Invalid source URI');\n  }\n\n  if (config.externalSubtitles) {\n    config.externalSubtitles = parseExternalSubtitles(config.externalSubtitles);\n  }\n\n  // Ensure platform-based default for DRM type if DRM is provided without a type\n  if (config.drm && config.drm.type === undefined) {\n    const defaultDrmType = Platform.select({\n      android: 'widevine',\n      ios: 'fairplay',\n      default: undefined,\n    });\n\n    if (defaultDrmType) {\n      config.drm = {\n        ...config.drm,\n        type: defaultDrmType,\n      };\n    }\n  }\n\n  // Set default value for initializeOnCreation (true)\n  if (config.initializeOnCreation === undefined) {\n    config.initializeOnCreation = true;\n  }\n\n  try {\n    return VideoPlayerSourceFactory.fromVideoConfig(\n      config as NativeVideoConfig\n    );\n  } catch (error) {\n    throw tryParseNativeVideoError(error);\n  }\n};\n\n/**\n * Parses the external subtitles from the `ExternalSubtitle` to the `NativeExternalSubtitle` format.\n *\n * @param externalSubtitles - The external subtitles to parse\n * @returns The parsed external subtitles\n */\nconst parseExternalSubtitles = (\n  externalSubtitles: ExternalSubtitle[]\n): NativeVideoConfig['externalSubtitles'] => {\n  return externalSubtitles.map((subtitle) => ({\n    uri: subtitle.uri,\n    label: subtitle.label,\n    type: (subtitle.type ?? 'auto') as SubtitleType,\n    language: subtitle.language ?? 'und',\n  }));\n};\n\n/**\n * Creates a `VideoPlayerSource`\n *\n * @param source - The `VideoSource` to create the `VideoPlayerSource` from\n * @returns The `VideoPlayerSource` instance\n */\nexport const createSource = (\n  source: VideoSource | VideoConfig | VideoPlayerSource\n): VideoPlayerSource => {\n  // If source is a VideoPlayerSource, we can directly return it\n  if (isVideoPlayerSource(source)) {\n    return source;\n  }\n\n  // If source is a string, we can directly create the player\n  if (typeof source === 'string') {\n    return createSourceFromUri(source);\n  }\n\n  // If source is a number (asset), we need to resolve the asset source and create the player\n  if (typeof source === 'number') {\n    const resolvedSource = Image.resolveAssetSource(source);\n    if (!resolvedSource?.uri || typeof resolvedSource.uri !== 'string') {\n      throw new VideoRuntimeError('source/invalid-uri', 'Invalid source URI');\n    }\n    return createSourceFromUri(resolvedSource.uri);\n  }\n\n  // If source is an object (VideoConfig)\n  if (typeof source === 'object' && source !== null && 'uri' in source) {\n    if (typeof source.uri === 'string') {\n      return createSourceFromVideoConfig(\n        source as VideoConfig & { uri: string }\n      );\n    }\n\n    if (typeof source.uri === 'number') {\n      const resolvedSource = Image.resolveAssetSource(source.uri);\n      if (!resolvedSource?.uri || typeof resolvedSource.uri !== 'string') {\n        throw new VideoRuntimeError('source/invalid-uri', 'Invalid source URI');\n      }\n\n      const config = {\n        ...source,\n        uri: resolvedSource.uri,\n      };\n\n      return createSourceFromVideoConfig(config);\n    }\n\n    throw new VideoRuntimeError('source/invalid-uri', 'Invalid source URI');\n  }\n\n  throw new VideoRuntimeError('player/invalid-source', 'Invalid source');\n};\n"
  },
  {
    "path": "packages/react-native-video/src/core/video-view/NativeVideoView.tsx",
    "content": "import { Platform, UIManager } from 'react-native';\n\nimport VideoViewNativeComponent from '../../spec/fabric/VideoViewNativeComponent';\n\nconst LINKING_ERROR =\n  `The package 'react-native-video' doesn't seem to be linked. Make sure: \\n\\n` +\n  Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n  '- You rebuilt the app after installing the package\\n' +\n  '- You are not using Expo Go\\n';\n\nconst ComponentName = 'VideoView';\n\nexport const NativeVideoView =\n  UIManager.hasViewManagerConfig(ComponentName) != null\n    ? VideoViewNativeComponent\n    : () => {\n        throw new Error(LINKING_ERROR);\n      };\n"
  },
  {
    "path": "packages/react-native-video/src/core/video-view/VideoView.tsx",
    "content": "import * as React from 'react';\nimport type { ViewProps, ViewStyle } from 'react-native';\nimport { NitroModules } from 'react-native-nitro-modules';\nimport type { ListenerSubscription } from '../../spec/nitro/VideoPlayerEventEmitter.nitro';\nimport type {\n  SurfaceType,\n  VideoViewViewManager,\n  VideoViewViewManagerFactory,\n} from '../../spec/nitro/VideoViewViewManager.nitro';\nimport { type VideoViewEvents } from '../types/Events';\nimport type { ResizeMode } from '../types/ResizeMode';\nimport {\n  tryParseNativeVideoError,\n  VideoComponentError,\n  VideoError,\n} from '../types/VideoError';\nimport type { VideoPlayer } from '../VideoPlayer';\nimport { NativeVideoView } from './NativeVideoView';\n\nexport interface VideoViewProps extends Partial<VideoViewEvents>, ViewProps {\n  /**\n   * The player to play the video - {@link VideoPlayer}\n   */\n  player: VideoPlayer;\n  /**\n   * The style of the video view - {@link ViewStyle}\n   */\n  style?: ViewStyle;\n  /**\n   * Whether to show the controls. Defaults to false.\n   */\n  controls?: boolean;\n  /**\n   * Whether to enable & show the picture in picture button in native controls. Defaults to false.\n   */\n  pictureInPicture?: boolean;\n  /**\n   * Whether to automatically enter picture in picture mode when the video is playing. Defaults to false.\n   */\n  autoEnterPictureInPicture?: boolean;\n  /**\n   * How the video should be resized to fit the view. Defaults to 'none'.\n   * - 'contain': Scale the video uniformly (maintain aspect ratio) so that it fits entirely within the view\n   * - 'cover': Scale the video uniformly (maintain aspect ratio) so that it fills the entire view (may crop)\n   * - 'stretch': Scale the video to fill the entire view without maintaining aspect ratio\n   * - 'none': Do not resize the video\n   */\n  resizeMode?: ResizeMode;\n  /**\n   * Whether to keep the screen awake while the video view is mounted. Defaults to true.\n   */\n  keepScreenAwake?: boolean;\n\n  /**\n   * The type of underlying native view. Defaults to 'surface'.\n   * - 'surface': Uses a SurfaceView on Android. More performant, but cannot be animated or transformed.\n   * - 'texture': Uses a TextureView on Android. Less performant, but can be animated and transformed.\n   *\n   * Only applicable on Android\n   *\n   * @default 'surface'\n   * @platform android\n   */\n  surfaceType?: SurfaceType;\n}\n\nexport interface VideoViewRef {\n  /**\n   * Enter fullscreen mode\n   */\n  enterFullscreen: () => void;\n  /**\n   * Exit fullscreen mode\n   */\n  exitFullscreen: () => void;\n  /**\n   * Enter picture in picture mode\n   */\n  enterPictureInPicture: () => void;\n  /**\n   * Exit picture in picture mode\n   */\n  exitPictureInPicture: () => void;\n  /**\n   * Check if picture in picture mode is supported\n   * @returns true if picture in picture mode is supported, false otherwise\n   */\n  canEnterPictureInPicture: () => boolean;\n  /**\n   * Adds a listener for a view event.\n   * @param event - The event to add a listener for.\n   * @param callback - The callback to call when the event is triggered.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addEventListener: <Event extends keyof VideoViewEvents>(\n    event: Event,\n    callback: VideoViewEvents[Event]\n  ) => ListenerSubscription;\n}\n\nlet nitroIdCounter = 1;\nconst VideoViewViewManagerFactory =\n  NitroModules.createHybridObject<VideoViewViewManagerFactory>(\n    'VideoViewViewManagerFactory'\n  );\n\nconst wrapNativeViewManagerFunction = <T,>(\n  manager: VideoViewViewManager | null,\n  func: (manager: VideoViewViewManager) => T\n) => {\n  try {\n    if (manager === null) {\n      throw new VideoError('view/not-found', 'View manager not found');\n    }\n\n    return func(manager);\n  } catch (error) {\n    throw tryParseNativeVideoError(error);\n  }\n};\n\nconst updateProps = (manager: VideoViewViewManager, props: VideoViewProps) => {\n  manager.player = props.player.__getNativePlayer();\n  manager.controls = props.controls ?? false;\n  manager.pictureInPicture = props.pictureInPicture ?? false;\n  manager.autoEnterPictureInPicture = props.autoEnterPictureInPicture ?? false;\n  manager.resizeMode = props.resizeMode ?? 'none';\n  manager.keepScreenAwake = props.keepScreenAwake ?? true;\n  manager.surfaceType = props.surfaceType ?? 'surface';\n};\n\n/**\n * VideoView is a component that allows you to display a video from a {@link VideoPlayer}.\n *\n * @param player - The player to play the video - {@link VideoPlayer}\n * @param controls - Whether to show the controls. Defaults to false.\n * @param style - The style of the video view - {@link ViewStyle}\n * @param pictureInPicture - Whether to show the picture in picture button. Defaults to false.\n * @param autoEnterPictureInPicture - Whether to automatically enter picture in picture mode\n * when the video is playing. Defaults to false.\n * @param resizeMode - How the video should be resized to fit the view. Defaults to 'none'.\n */\nconst VideoView = React.forwardRef<VideoViewRef, VideoViewProps>(\n  (\n    {\n      player,\n      controls = false,\n      pictureInPicture = false,\n      autoEnterPictureInPicture = false,\n      resizeMode = 'none',\n      onPictureInPictureChange,\n      onFullscreenChange,\n      willEnterFullscreen,\n      willExitFullscreen,\n      willEnterPictureInPicture,\n      willExitPictureInPicture,\n      ...props\n    },\n    ref\n  ) => {\n    const nitroId = React.useMemo(() => nitroIdCounter++, []);\n    const nitroViewManager = React.useRef<VideoViewViewManager | null>(null);\n    const [isManagerReady, setIsManagerReady] = React.useState(false);\n\n    const setupViewManager = React.useCallback(\n      (id: number) => {\n        try {\n          if (nitroViewManager.current === null) {\n            nitroViewManager.current =\n              VideoViewViewManagerFactory.createViewManager(id);\n\n            // Should never happen\n            if (!nitroViewManager.current) {\n              throw new VideoError(\n                'view/not-found',\n                'Failed to create View Manager'\n              );\n            }\n          }\n\n          setIsManagerReady(true);\n        } catch (error) {\n          const parsedError = tryParseNativeVideoError(error);\n\n          if (\n            parsedError instanceof VideoComponentError &&\n            parsedError.code === 'view/not-found'\n          ) {\n            // The view was not found, did view get unmounted?\n            if (id === nitroId) {\n              // The id from native is same as the one we have,\n              // so the view was unmounted before native manager was able to find it\n\n              // On slow devices, when we quickly mount and unmount the view,\n              // the native manager may not have been able to find the view before the view was unmounted\n              // This should really never happen, but it's better to be safe than sorry\n\n              // We don't throw an error here, because it's not an actual error.\n              console.warn(\n                '[ReactNativeVideo] VideoView was unmounted before native manager was able to find it. It can happen when the view is quickly mounted and unmounted.'\n              );\n\n              return;\n            }\n          }\n\n          throw parsedError;\n        }\n      },\n      [nitroId]\n    );\n\n    const onNitroIdChange = React.useCallback(\n      (event: { nativeEvent: { nitroId: number } }) => {\n        setupViewManager(event.nativeEvent.nitroId);\n      },\n      [setupViewManager]\n    );\n\n    React.useImperativeHandle(\n      ref,\n      () => ({\n        enterFullscreen: () => {\n          wrapNativeViewManagerFunction(nitroViewManager.current, (manager) => {\n            manager.enterFullscreen();\n          });\n        },\n        exitFullscreen: () => {\n          wrapNativeViewManagerFunction(nitroViewManager.current, (manager) => {\n            manager.exitFullscreen();\n          });\n        },\n        enterPictureInPicture: () => {\n          wrapNativeViewManagerFunction(nitroViewManager.current, (manager) => {\n            manager.enterPictureInPicture();\n          });\n        },\n        exitPictureInPicture: () => {\n          wrapNativeViewManagerFunction(nitroViewManager.current, (manager) => {\n            manager.exitPictureInPicture();\n          });\n        },\n        canEnterPictureInPicture: () => {\n          return wrapNativeViewManagerFunction(\n            nitroViewManager.current,\n            (manager) => {\n              return manager.canEnterPictureInPicture();\n            }\n          );\n        },\n        addEventListener: <Event extends keyof VideoViewEvents>(\n          event: Event,\n          callback: VideoViewEvents[Event]\n        ): ListenerSubscription => {\n          return wrapNativeViewManagerFunction(\n            nitroViewManager.current,\n            (manager) => {\n              switch (event) {\n                case 'onPictureInPictureChange':\n                  return manager.addOnPictureInPictureChangeListener(\n                    callback as VideoViewEvents['onPictureInPictureChange']\n                  );\n                case 'onFullscreenChange':\n                  return manager.addOnFullscreenChangeListener(\n                    callback as VideoViewEvents['onFullscreenChange']\n                  );\n                case 'willEnterFullscreen':\n                  return manager.addWillEnterFullscreenListener(\n                    callback as VideoViewEvents['willEnterFullscreen']\n                  );\n                case 'willExitFullscreen':\n                  return manager.addWillExitFullscreenListener(\n                    callback as VideoViewEvents['willExitFullscreen']\n                  );\n                case 'willEnterPictureInPicture':\n                  return manager.addWillEnterPictureInPictureListener(\n                    callback as VideoViewEvents['willEnterPictureInPicture']\n                  );\n                case 'willExitPictureInPicture':\n                  return manager.addWillExitPictureInPictureListener(\n                    callback as VideoViewEvents['willExitPictureInPicture']\n                  );\n                default:\n                  throw new Error(\n                    `[React Native Video] Unsupported event: ${event}`\n                  );\n              }\n            }\n          );\n        },\n      }),\n      []\n    );\n\n    // Cleanup all listeners on unmount\n    React.useEffect(() => {\n      return () => {\n        if (nitroViewManager.current) {\n          nitroViewManager.current.clearAllListeners();\n          setIsManagerReady(false);\n        }\n      };\n    }, []);\n\n    // Register prop-based event callbacks as listeners\n    React.useEffect(() => {\n      if (!nitroViewManager.current) {\n        return;\n      }\n\n      const subscriptions: ListenerSubscription[] = [];\n\n      if (onPictureInPictureChange) {\n        subscriptions.push(\n          nitroViewManager.current.addOnPictureInPictureChangeListener(\n            onPictureInPictureChange\n          )\n        );\n      }\n      if (onFullscreenChange) {\n        subscriptions.push(\n          nitroViewManager.current.addOnFullscreenChangeListener(\n            onFullscreenChange\n          )\n        );\n      }\n      if (willEnterFullscreen) {\n        subscriptions.push(\n          nitroViewManager.current.addWillEnterFullscreenListener(\n            willEnterFullscreen\n          )\n        );\n      }\n      if (willExitFullscreen) {\n        subscriptions.push(\n          nitroViewManager.current.addWillExitFullscreenListener(\n            willExitFullscreen\n          )\n        );\n      }\n      if (willEnterPictureInPicture) {\n        subscriptions.push(\n          nitroViewManager.current.addWillEnterPictureInPictureListener(\n            willEnterPictureInPicture\n          )\n        );\n      }\n      if (willExitPictureInPicture) {\n        subscriptions.push(\n          nitroViewManager.current.addWillExitPictureInPictureListener(\n            willExitPictureInPicture\n          )\n        );\n      }\n\n      return () => {\n        subscriptions.forEach((sub) => sub.remove());\n      };\n    }, [\n      onPictureInPictureChange,\n      onFullscreenChange,\n      willEnterFullscreen,\n      willExitFullscreen,\n      willEnterPictureInPicture,\n      willExitPictureInPicture,\n      isManagerReady,\n    ]);\n\n    // Update non-event props\n    React.useEffect(() => {\n      if (!nitroViewManager.current) {\n        return;\n      }\n\n      // Updates props to native view\n      updateProps(nitroViewManager.current, {\n        ...props,\n        player: player,\n        controls: controls,\n        pictureInPicture: pictureInPicture,\n        autoEnterPictureInPicture: autoEnterPictureInPicture,\n        resizeMode: resizeMode,\n      });\n    }, [\n      player,\n      controls,\n      pictureInPicture,\n      autoEnterPictureInPicture,\n      resizeMode,\n      props,\n      isManagerReady,\n    ]);\n\n    return (\n      <NativeVideoView\n        nitroId={nitroId}\n        onNitroIdChange={onNitroIdChange}\n        {...props}\n      />\n    );\n  }\n);\n\nVideoView.displayName = 'VideoView';\n\nexport default React.memo(VideoView);\n"
  },
  {
    "path": "packages/react-native-video/src/expo-plugins/@types.ts",
    "content": "export type ConfigProps = {\n  /**\n   * Whether to use react-native-test-app compatible mode.\n   * @default false\n   */\n  reactNativeTestApp?: boolean;\n\n  /**\n   * Apply configs to be able to use Picture-in-picture on Android.\n   * @default false\n   */\n  enableAndroidPictureInPicture?: boolean;\n\n  /**\n   * Whether to enable background audio feature.\n   * @default false\n   */\n  enableBackgroundAudio?: boolean;\n\n  /**\n   * Android extensions for ExoPlayer - you can choose which extensions to include in order to reduce the size of the app.\n   * @default { useExoplayerDash: true, useExoplayerHls: true }\n   */\n  androidExtensions?: {\n    /**\n     * Whether to use ExoPlayer's Dash extension.\n     * @default true\n     */\n    useExoplayerDash?: boolean;\n\n    /**\n     * Whether to use ExoPlayer's HLS extension.\n     * @default true\n     */\n    useExoplayerHls?: boolean;\n  };\n};\n"
  },
  {
    "path": "packages/react-native-video/src/expo-plugins/getPackageInfo.ts",
    "content": "export function getPackageInfo(): { name: string; version: string } {\n  // src/expo-plugins/getPackageInfo.ts\n  try {\n    const packageJson = require('../../package.json');\n\n    return {\n      name: packageJson.name,\n      version: packageJson.version,\n    };\n  } catch (_) {}\n\n  // lib/commonjs/expo-plugins/getPackageInfo.js\n  try {\n    const packageJson = require('../../../package.json');\n\n    return {\n      name: packageJson.name,\n      version: packageJson.version,\n    };\n  } catch (_) {}\n\n  throw new Error('Failed to get (react-native-video) package info');\n}\n"
  },
  {
    "path": "packages/react-native-video/src/expo-plugins/withAndroidExtensions.ts",
    "content": "import { withGradleProperties, type ConfigPlugin } from '@expo/config-plugins';\nimport type { ConfigProps } from './@types';\n\n/**\n * Sets the Android extensions for ExoPlayer in `gradle.properties`.\n * You can choose which extensions to include in order to reduce the size of the app.\n */\nexport const withAndroidExtensions: ConfigPlugin<\n  ConfigProps['androidExtensions']\n> = (c, androidExtensions) => {\n  const keys = ['RNVideo_useExoplayerDash', 'RNVideo_useExoplayerHls'];\n\n  if (!androidExtensions) {\n    androidExtensions = {\n      useExoplayerDash: true,\n      useExoplayerHls: true,\n    };\n  }\n\n  return withGradleProperties(c, (config) => {\n    config.modResults = config.modResults.filter((item) => {\n      if (item.type === 'property' && keys.includes(item.key)) {\n        return false;\n      }\n      return true;\n    });\n\n    for (const key of keys) {\n      const valueKey = key.replace(\n        'RNVideo_',\n        ''\n      ) as keyof typeof androidExtensions;\n      const value = androidExtensions\n        ? (androidExtensions[valueKey] ?? false)\n        : false;\n\n      config.modResults.push({\n        type: 'property',\n        key,\n        value: value.toString(),\n      });\n    }\n\n    return config;\n  });\n};\n"
  },
  {
    "path": "packages/react-native-video/src/expo-plugins/withAndroidNotificationControls.ts",
    "content": "import {\n  AndroidConfig,\n  type ConfigPlugin,\n  withAndroidManifest,\n} from '@expo/config-plugins';\n\nexport const withAndroidNotificationControls: ConfigPlugin = (oldConfig) => {\n  return withAndroidManifest(oldConfig, (config) => {\n    const mainApplication = AndroidConfig.Manifest.getMainApplication(\n      config.modResults\n    );\n    if (!mainApplication) {\n      console.warn(\n        'AndroidManifest.xml is missing an <activity android:name=\".MainActivity\" /> element - skipping adding Notification Controls related config.'\n      );\n      return config;\n    }\n    mainApplication.service?.push({\n      '$': {\n        'android:name':\n          'com.twg.video.core.services.playback.VideoPlaybackService',\n        'android:exported': 'false',\n        'android:foregroundServiceType': 'mediaPlayback',\n      },\n      'intent-filter': [\n        {\n          action: [\n            {\n              $: {\n                'android:name': 'androidx.media3.session.MediaSessionService',\n              },\n            },\n          ],\n        },\n      ],\n    });\n    config.android?.permissions?.push(\n      'android.permission.FOREGROUND_SERVICE',\n      'android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK'\n    );\n    return config;\n  });\n};\n"
  },
  {
    "path": "packages/react-native-video/src/expo-plugins/withAndroidPictureInPicture.ts",
    "content": "import {\n  AndroidConfig,\n  withAndroidManifest,\n  type ConfigPlugin,\n} from '@expo/config-plugins';\n\nexport const withAndroidPictureInPicture: ConfigPlugin<boolean> = (\n  config,\n  enableAndroidPictureInPicture\n) => {\n  return withAndroidManifest(config, (_config) => {\n    if (!enableAndroidPictureInPicture) {\n      return _config;\n    }\n\n    const mainActivity = AndroidConfig.Manifest.getMainActivity(\n      _config.modResults\n    );\n\n    if (!mainActivity) {\n      console.warn(\n        'AndroidManifest.xml is missing an <activity android:name=\".MainActivity\" /> element - skipping adding Picture-In-Picture related config.'\n      );\n      return _config;\n    }\n\n    mainActivity.$['android:supportsPictureInPicture'] = 'true';\n\n    return _config;\n  });\n};\n"
  },
  {
    "path": "packages/react-native-video/src/expo-plugins/withBackgroundAudio.ts",
    "content": "import { withInfoPlist, type ConfigPlugin } from '@expo/config-plugins';\n\n/**\n * Sets `UIBackgroundModes` in `Info.plist` to enable background audio on Apple platforms.\n * This is required for audio to continue playing when the app is in the background.\n */\nexport const withBackgroundAudio: ConfigPlugin<boolean> = (\n  c,\n  enableBackgroundAudio\n) => {\n  return withInfoPlist(c, (config) => {\n    const modes = config.modResults.UIBackgroundModes || [];\n\n    if (enableBackgroundAudio) {\n      if (!modes.includes('audio')) {\n        config.modResults.UIBackgroundModes = [...modes, 'audio'];\n      }\n    } else {\n      config.modResults.UIBackgroundModes = modes.filter(\n        (mode: string) => mode !== 'audio'\n      );\n    }\n\n    return config;\n  });\n};\n"
  },
  {
    "path": "packages/react-native-video/src/expo-plugins/withReactNativeVideo.ts",
    "content": "import { type ConfigPlugin, createRunOncePlugin } from '@expo/config-plugins';\nimport type { ConfigProps } from './@types';\nimport { getPackageInfo } from './getPackageInfo';\nimport { withAndroidExtensions } from './withAndroidExtensions';\nimport { withAndroidPictureInPicture } from './withAndroidPictureInPicture';\nimport { withBackgroundAudio } from './withBackgroundAudio';\nimport { withAndroidNotificationControls } from './withAndroidNotificationControls';\n\nconst withRNVideo: ConfigPlugin<ConfigProps> = (config, props = {}) => {\n  if (props.enableAndroidPictureInPicture) {\n    config = withAndroidPictureInPicture(\n      config,\n      props.enableAndroidPictureInPicture\n    );\n  }\n\n  if (props.androidExtensions != null) {\n    config = withAndroidExtensions(config, props.androidExtensions);\n  }\n\n  if (props.enableBackgroundAudio) {\n    config = withBackgroundAudio(config, props.enableBackgroundAudio);\n  }\n\n  config = withAndroidNotificationControls(config);\n\n  return config;\n};\n\nconst { name, version } = getPackageInfo();\n\nexport default createRunOncePlugin(withRNVideo, name, version);\n"
  },
  {
    "path": "packages/react-native-video/src/expo-plugins/writeToPodfile.ts",
    "content": "import { mergeContents } from '@expo/config-plugins/build/utils/generateCode';\nimport fs from 'fs';\nimport path from 'path';\n\nexport const writeToPodfile = (\n  projectRoot: string,\n  key: string,\n  value: string,\n  testApp: boolean = false\n) => {\n  const podfilePath = path.join(projectRoot, 'ios', 'Podfile');\n  const podfileContent = fs.readFileSync(podfilePath, 'utf8');\n\n  if (podfileContent.includes(`$${key} =`)) {\n    console.warn(\n      `RNV - Podfile already contains a definition for \"$${key}\". Skipping...`\n    );\n    return;\n  }\n\n  if (testApp) {\n    mergeTestAppPodfile(podfileContent, podfilePath, key, value);\n  } else {\n    mergeExpoPodfile(podfileContent, podfilePath, key, value);\n  }\n};\n\nconst mergeTestAppPodfile = (\n  podfileContent: string,\n  podfilePath: string,\n  key: string,\n  value: string\n) => {\n  // We will try to inject the variable definition above the `use_test_app!` call in the Podfile.\n  const newPodfileContent = mergeContents({\n    tag: `rn-video-set-${key.toLowerCase()}`,\n    src: podfileContent,\n    newSrc: `$${key} = ${value}`,\n    anchor: /use_test_app!/,\n    offset: -1, // Insert the key-value pair just above the `use_test_app!` call.\n    comment: '#',\n  });\n\n  // Write to Podfile only if the merge was successful\n  if (newPodfileContent.didMerge) {\n    fs.writeFileSync(podfilePath, newPodfileContent.contents);\n  } else {\n    console.warn(\n      `RNV - Failed to write \"$${key} = ${value}\" to Test App Podfile`\n    );\n  }\n};\n\nconst mergeExpoPodfile = (\n  podfileContent: string,\n  podfilePath: string,\n  key: string,\n  value: string\n) => {\n  const newPodfileContent = mergeContents({\n    tag: `rn-video-set-${key.toLowerCase()}`,\n    src: podfileContent,\n    newSrc: `$${key} = ${value}`,\n    anchor: /platform :ios/,\n    offset: 0,\n    comment: '#',\n  });\n\n  if (newPodfileContent.didMerge) {\n    fs.writeFileSync(podfilePath, newPodfileContent.contents);\n  } else {\n    console.warn(`RNV - Failed to write \"$${key} = ${value}\" to Podfile`);\n  }\n};\n"
  },
  {
    "path": "packages/react-native-video/src/index.tsx",
    "content": "export { useEvent } from './core/hooks/useEvent';\nexport { useVideoPlayer } from './core/hooks/useVideoPlayer';\nexport * from './core/types/Events';\nexport type { IgnoreSilentSwitchMode } from './core/types/IgnoreSilentSwitchMode';\nexport type { MixAudioMode } from './core/types/MixAudioMode';\nexport type { ResizeMode } from './core/types/ResizeMode';\nexport type { TextTrack } from './core/types/TextTrack';\nexport type { VideoConfig, VideoSource } from './core/types/VideoConfig';\nexport {\n  type LibraryError,\n  type PlayerError,\n  type SourceError,\n  type UnknownError,\n  type VideoComponentError,\n  type VideoError,\n  type VideoErrorCode,\n  type VideoRuntimeError,\n  type VideoViewError,\n} from './core/types/VideoError';\nexport type { VideoPlayerStatus } from './core/types/VideoPlayerStatus';\nexport {\n  default as VideoView,\n  type VideoViewProps,\n  type VideoViewRef,\n} from './core/video-view/VideoView';\nexport { VideoPlayer } from './core/VideoPlayer';\n"
  },
  {
    "path": "packages/react-native-video/src/spec/fabric/VideoViewNativeComponent.ts",
    "content": "import type { ViewProps } from 'react-native';\nimport type {\n  DirectEventHandler,\n  Int32,\n} from 'react-native/Libraries/Types/CodegenTypes';\nimport codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';\n\ntype OnNitroIdChangeEvent = Readonly<{\n  nitroId: Int32;\n}>;\n\nexport interface ViewViewNativeProps extends ViewProps {\n  nitroId: Int32;\n  onNitroIdChange?: DirectEventHandler<OnNitroIdChangeEvent>;\n}\n\nexport default codegenNativeComponent<ViewViewNativeProps>('RNCVideoView');\n"
  },
  {
    "path": "packages/react-native-video/src/spec/nitro/VideoPlayer.nitro.ts",
    "content": "import type { HybridObject } from 'react-native-nitro-modules';\nimport type { TextTrack } from '../../core/types/TextTrack';\nimport type { VideoPlayerBase } from '../../core/types/VideoPlayerBase';\nimport type { VideoPlayerEventEmitter } from './VideoPlayerEventEmitter.nitro';\nimport type { VideoPlayerSource } from './VideoPlayerSource.nitro';\n\nexport interface VideoPlayer\n  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }>,\n    VideoPlayerBase {\n  // Override with (hybrid) VideoPlayerSource\n  readonly source: VideoPlayerSource;\n\n  // Holder of the video player events.\n  readonly eventEmitter: VideoPlayerEventEmitter;\n\n  /**\n   * Show playback controls in the notifications area\n   *\n   * @note on Android, this can be overridden by {@linkcode VideoPlayer.playInBackground}, as Android requires\n   * a foreground service to show notifications while the app is in the background.\n   *\n   * @default false\n   */\n  showNotificationControls: boolean;\n\n  /**\n   * Replace the current source of the player.\n   * @param source - The new source of the video.\n   * @note If you want to clear the source, you can pass null. It has the same effect as {@link release}.\n   * see {@link VideoPlayerSourceBase}\n   */\n  replaceSourceAsync(source: VideoPlayerSource | null): Promise<void>;\n\n  /**\n   * Get all available text tracks for the current source.\n   * @returns Array of available text tracks\n   */\n  getAvailableTextTracks(): TextTrack[];\n\n  /**\n   * Select a text track to display.\n   * @param textTrack - Text track to select, or null to unselect current track\n   */\n  selectTextTrack(textTrack: TextTrack | null): void;\n\n  /**\n   * Releases the player's native resources and releases native state.\n   */\n  release(): void;\n}\n\nexport interface VideoPlayerFactory\n  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {\n  createPlayer(source: VideoPlayerSource): VideoPlayer;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/spec/nitro/VideoPlayerEventEmitter.nitro.ts",
    "content": "import type { HybridObject } from 'react-native-nitro-modules';\nimport type {\n  BandwidthData,\n  onLoadData,\n  onLoadStartData,\n  onPlaybackStateChangeData,\n  onProgressData,\n  onVolumeChangeData,\n  TimedMetadata,\n} from '../../core/types/Events';\nimport type { TextTrack } from '../../core/types/TextTrack';\nimport type { VideoPlayerStatus } from '../../core/types/VideoPlayerStatus';\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { VideoPlayerEvents } from '../../core/types/Events';\n\nexport interface ListenerSubscription {\n  remove(): void;\n}\n\nexport interface VideoPlayerEventEmitter\n  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {\n  /**\n   * Adds a listener for the `onAudioBecomingNoisy` event.\n   * @see {@link VideoPlayerEvents.onAudioBecomingNoisy}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnAudioBecomingNoisyListener(listener: () => void): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onAudioFocusChange` event.\n   * @see {@link VideoPlayerEvents.onAudioFocusChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnAudioFocusChangeListener(\n    listener: (hasAudioFocus: boolean) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onBandwidthUpdate` event.\n   * @see {@link VideoPlayerEvents.onBandwidthUpdate}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnBandwidthUpdateListener(\n    listener: (data: BandwidthData) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onBuffer` event.\n   * @see {@link VideoPlayerEvents.onBuffer}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnBufferListener(\n    listener: (buffering: boolean) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onControlsVisibleChange` event.\n   * @see {@link VideoPlayerEvents.onControlsVisibleChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnControlsVisibleChangeListener(\n    listener: (visible: boolean) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onEnd` event.\n   * @see {@link VideoPlayerEvents.onEnd}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnEndListener(listener: () => void): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onExternalPlaybackChange` event.\n   * @see {@link VideoPlayerEvents.onExternalPlaybackChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnExternalPlaybackChangeListener(\n    listener: (externalPlaybackActive: boolean) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onLoad` event.\n   * @see {@link VideoPlayerEvents.onLoad}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnLoadListener(listener: (data: onLoadData) => void): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onLoadStart` event.\n   * @see {@link VideoPlayerEvents.onLoadStart}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnLoadStartListener(\n    listener: (data: onLoadStartData) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onPlaybackStateChange` event.\n   * @see {@link VideoPlayerEvents.onPlaybackStateChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnPlaybackStateChangeListener(\n    listener: (data: onPlaybackStateChangeData) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onPlaybackRateChange` event.\n   * @see {@link VideoPlayerEvents.onPlaybackRateChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnPlaybackRateChangeListener(\n    listener: (rate: number) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onProgress` event.\n   * @see {@link VideoPlayerEvents.onProgress}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnProgressListener(\n    listener: (data: onProgressData) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onReadyToDisplay` event.\n   * @see {@link VideoPlayerEvents.onReadyToDisplay}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnReadyToDisplayListener(listener: () => void): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onSeek` event.\n   * @see {@link VideoPlayerEvents.onSeek}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnSeekListener(listener: (position: number) => void): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onStatusChange` event.\n   * @see {@link VideoPlayerEvents.onStatusChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnStatusChangeListener(\n    listener: (status: VideoPlayerStatus) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onTimedMetadata` event.\n   * @see {@link VideoPlayerEvents.onTimedMetadata}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnTimedMetadataListener(\n    listener: (data: TimedMetadata) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onTextTrackDataChanged` event.\n   * @see {@link VideoPlayerEvents.onTextTrackDataChanged}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnTextTrackDataChangedListener(\n    listener: (data: string[]) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onTrackChange` event.\n   * @see {@link VideoPlayerEvents.onTrackChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnTrackChangeListener(\n    listener: (track: TextTrack | null) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onVolumeChange` event.\n   * @see {@link VideoPlayerEvents.onVolumeChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnVolumeChangeListener(\n    listener: (data: onVolumeChangeData) => void\n  ): ListenerSubscription;\n\n  /**\n   * Clears all listeners from the event emitter.\n   */\n  clearAllListeners(): void;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/spec/nitro/VideoPlayerSource.nitro.ts",
    "content": "import type { HybridObject } from 'react-native-nitro-modules';\nimport type { NativeVideoConfig } from '../../core/types/VideoConfig';\nimport type { VideoPlayerSourceBase } from '../../core/types/VideoPlayerSourceBase';\n\n/**\n * A source for a {@link VideoPlayer}.\n * Source cannot be changed after it is created. If you need to update the source, you need to create a new one.\n * It provides functions to get information about the asset.\n */\nexport interface VideoPlayerSource\n  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }>,\n    VideoPlayerSourceBase {}\n\nexport interface VideoPlayerSourceFactory\n  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {\n  fromUri(uri: string): VideoPlayerSource;\n  fromVideoConfig(config: NativeVideoConfig): VideoPlayerSource;\n}\n"
  },
  {
    "path": "packages/react-native-video/src/spec/nitro/VideoViewViewManager.nitro.ts",
    "content": "import type { HybridObject } from 'react-native-nitro-modules';\nimport type { ResizeMode } from '../../core/types/ResizeMode';\nimport type { VideoPlayer } from './VideoPlayer.nitro';\nimport type { ListenerSubscription } from './VideoPlayerEventEmitter.nitro';\n\nexport type SurfaceType = 'surface' | 'texture';\n\n// @internal\nexport interface VideoViewViewManager\n  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {\n  player?: VideoPlayer;\n  controls: boolean;\n  pictureInPicture: boolean;\n  autoEnterPictureInPicture: boolean;\n  resizeMode: ResizeMode;\n  enterFullscreen(): void;\n  exitFullscreen(): void;\n  enterPictureInPicture(): void;\n  exitPictureInPicture(): void;\n  canEnterPictureInPicture(): boolean;\n  keepScreenAwake: boolean;\n  surfaceType: SurfaceType;\n\n  // Event listeners\n\n  /**\n   * Adds a listener for the `onPictureInPictureChange` event.\n   * @see {@link VideoViewEvents.onPictureInPictureChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnPictureInPictureChangeListener(\n    listener: (isInPictureInPicture: boolean) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `onFullscreenChange` event.\n   * @see {@link VideoViewEvents.onFullscreenChange}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addOnFullscreenChangeListener(\n    listener: (fullscreen: boolean) => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `willEnterFullscreen` event.\n   * @see {@link VideoViewEvents.willEnterFullscreen}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addWillEnterFullscreenListener(listener: () => void): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `willExitFullscreen` event.\n   * @see {@link VideoViewEvents.willExitFullscreen}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addWillExitFullscreenListener(listener: () => void): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `willEnterPictureInPicture` event.\n   * @see {@link VideoViewEvents.willEnterPictureInPicture}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addWillEnterPictureInPictureListener(\n    listener: () => void\n  ): ListenerSubscription;\n\n  /**\n   * Adds a listener for the `willExitPictureInPicture` event.\n   * @see {@link VideoViewEvents.willExitPictureInPicture}\n   * @param listener - The listener to add.\n   * @returns A subscription object that can be used to remove the listener.\n   */\n  addWillExitPictureInPictureListener(\n    listener: () => void\n  ): ListenerSubscription;\n\n  /**\n   * Clears all listeners from the event emitter.\n   */\n  clearAllListeners(): void;\n}\n\n// @internal\nexport interface VideoViewViewManagerFactory\n  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {\n  createViewManager(nitroId: number): VideoViewViewManager;\n}\n"
  },
  {
    "path": "packages/react-native-video/tsconfig.build.json",
    "content": "{\n  \"extends\": \"./tsconfig\"\n}\n"
  },
  {
    "path": "packages/react-native-video/tsconfig.json",
    "content": "{\n  \"extends\": [\"../../config/tsconfig.json\"],\n  \"include\": [\"src\", \"./app.plugin.js\"],\n  \"compilerOptions\": {\n    \"rootDir\": \".\",\n    \"jsx\": \"react-jsx\",\n    \"stripInternal\": true\n  }\n}\n"
  },
  {
    "path": "scripts/release.sh",
    "content": "#!/bin/bash\n\nset -e\n\necho \"[React Native Video] Starting release process\"\necho \"[React Native Video] Options: $@\"\n\necho \"[React Native Video] Checking if we are in the correct directory\"\nif [ ! -d \"packages/react-native-video\" ]; then\n  echo \"[React Native Video] Error: Not in the correct directory\"\n  exit 1\nfi\n\n# Check if options include --skip react-native-video\nif [[ \" $@ \" =~ \" --skip \" ]] && [[ \" $@ \" =~ \" react-native-video \" ]]; then\n  echo \"[React Native Video] Skipping main package release\"\nelse\n  echo \"[React Native Video] Publishing main package\"\n  cd packages/react-native-video\n  bun run release $@\n  cd ../..\nfi\n\n# Check if options include --skip drm-plugin\nif [[ \" $@ \" =~ \" --skip \" ]] && [[ \" $@ \" =~ \" drm-plugin \" ]]; then\n  echo \"[DRM Plugin] Skipping drm plugin release\"\nelse\n  echo \"[DRM Plugin] Publishing drm plugin\"\n\n  cd packages/drm-plugin\n  bun run release $@\n  cd ../..\nfi\n\n# Check if options include --skip github\nif [[ \" $@ \" =~ \" --skip \" ]] && [[ \" $@ \" =~ \" github \" ]]; then\n  echo \"[React Native Video] Skipping GitHub release\"\nelse\n  echo \"[React Native Video] Making Github Release\"\n  bun run release:github $@\nfi\n\necho \"[React Native Video] Done\""
  }
]