[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"[BUG]\"\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Platform (please complete the following information):**\n - OS: [e.g. iOS or Android]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/workflows/npm-publish.yml",
    "content": "# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created\n# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages\n\nname: Publish NPM Package\n\non:\n  workflow_dispatch:\n  release:\n    types: [created]\n\njobs:\n  publish-npm:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 16\n          registry-url: https://registry.npmjs.org/\n      - run: npm publish\n        env:\n          NODE_AUTH_TOKEN: ${{secrets.NPM_ACCESS_TOKEN}}\n"
  },
  {
    "path": ".gitignore",
    "content": "*.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n## Build generated\nbuild/\nDerivedData/\n\n## Various settings\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata/\n\n## Other\n*.moved-aside\n*.xccheckout\n*.xcscmblueprint\n\n## Obj-C/Swift specific\n*.hmap\n*.ipa\n*.dSYM.zip\n*.dSYM\n\n# CocoaPods\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# Pods/\n\n# Carthage\n#\n# Add this line if you want to avoid checking in source code from Carthage dependencies.\n# Carthage/Checkouts\n\nCarthage/Build\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/#source-control\n\nfastlane/report.xml\nfastlane/Preview.html\nfastlane/screenshots\nfastlane/test_output\n\n# Code Injection\n#\n# After new code Injection tools there's a generated folder /iOSInjectionProject\n# https://github.com/johnno1962/injectionforxcode\n\niOSInjectionProject/\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"tabWidth\": 4,\n  \"semi\": false,\n  \"singleQuote\": true\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Johnson Su\n\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-sound-player\n\n> ⚠️ **This package is no longer actively maintained.** For new projects, I recommend using other libraries such as [react-native-track-player](https://github.com/doublesymmetry/react-native-track-player) which provides more comprehensive audio playback features and active community support.\n\nPlay audio files, stream audio from URL, using ReactNative.\n\n## Installation\n\n### 1. `yarn` or `npm`\n\n```\n    // yarn\n    yarn add react-native-sound-player\n    // or npm\n    npm install --save react-native-sound-player\n```\n\n### 2. Link\n\nFor RN >= 0.60 you can skip this step.\n\n```\n    react-native link react-native-sound-player\n```\n\n## Usage\n\n### Play sound with file name and type\n\n1. Add sound files to iOS/Android.\n\n- On iOS, drag and drop sound file into project in Xcode. Remember to check **\"Copy items if needed\"** option and **\"Add to targets\"**.\n- On Android, put sound files in `{project_root}/android/app/src/main/res/raw/`. Just create the folder if it doesn't exist.\n- When using playAsset() you only need to copy the file to the projects root directory or a subfolder like assets\n\n2. Import the library and call the `playSoundFile(fileName, fileType)` function:\n\n```javascript\nimport SoundPlayer from \"react-native-sound-player\";\n\ntry {\n  // play the file tone.mp3\n  SoundPlayer.playSoundFile(\"tone\", \"mp3\");\n  // or play from url\n  SoundPlayer.playUrl(\"https://example.com/music.mp3\");\n  // or play file from folder\n  SoundPlayer.playAsset(require(\"./assets/tone.mp3\"));\n} catch (e) {\n  console.log(`cannot play the sound file`, e);\n}\n```\n\n> Please note that the device can still go to sleep (screen goes off) while audio is playing.\n> When this happens, the audio will stop playing.\n> To prevent this, you can use something like [react-native-keep-awake](https://github.com/corbt/react-native-keep-awake).\n> Or alternatively, for iOS, you can add a Background Mode of `Audio, AirPlay, and Picture in Picture` in XCode. To do this, select your application from Targets, then click on `Signing & Capabilities` and add `Background Modes`. once the options for it appear on your `Signing & Capabilities` page select the checkbox with `Audio, AirPlay, and Picture in Picture`. This will allow the application to continue playing audio when the app is in the background and even when the device is locked.\n\n## Functions\n\n### `playSoundFile(fileName: string, fileType: string)`\n\nPlay the sound file named `fileName` with file type `fileType`.\n\n### `playSoundFileWithDelay(fileName: string, fileType: string, delay: number)` - iOS Only\n\nPlay the sound file named `fileName` with file type `fileType` after a a delay of `delay` in _seconds_ from the current device time.\n\n### `loadSoundFile(fileName: string, fileType: string)`\n\nLoad the sound file named `fileName` with file type `fileType`, without playing it.\nThis is useful when you want to play a large file, which can be slow to mount,\nand have precise control on when the sound is played. This can also be used in\ncombination with `getInfo()` to get audio file `duration` without playing it.\nYou should subscribe to the `onFinishedLoading` event to get notified when the\nfile is loaded.\n\n### `playUrl(url: string)`\n\nPlay the audio from url. Supported formats are:\n\n- [AVPlayer (iOS)](https://stackoverflow.com/questions/21879981/avfoundation-avplayer-supported-formats-no-vob-or-mpg-containers)\n- [MediaPlayer (Android)](https://developer.android.com/guide/topics/media/media-formats)\n\n### `loadUrl(url: string)`\n\nLoad the audio from the given `url` without playing it. You can then play the audio\nby calling `play()`. This might be useful when you find the delay between calling\n`playUrl()` and the sound actually starts playing is too much.\n\n### `playAsset(asset: number)`\n\nPlay the audio from an asset, to get the asset number use `require('./assets/tone.mp3')`.\n\nSupported formats see `playUrl()` function.\n\n### `loadAsset(asset: number)`\n\nLoad the audio from an asset like above but without playing it. You can then play the audio by calling `play()`. This might be useful when you find the delay between calling `playAsset()` and the sound actually starts playing is too much.\n\n### `addEventListener(callback: (object: ResultObject) => SubscriptionObject)`\n\nSubscribe to any event. Returns a subscription object. Subscriptions created by this function cannot be removed by calling `unmount()`. You **NEED** to call `yourSubscriptionObject.remove()` when you no longer need this event listener or whenever your component unmounts.\n\nSupported events are:\n\n1. `FinishedLoading`\n2. `FinishedPlaying`\n3. `FinishedLoadingURL`\n4. `FinishedLoadingFile`\n\n```javascript\n  // Example\n  ...\n  // Create instance variable(s) to store your subscriptions in your class\n  _onFinishedPlayingSubscription = null\n  _onFinishedLoadingSubscription = null\n  _onFinishedLoadingFileSubscription = null\n  _onFinishedLoadingURLSubscription = null\n\n  // Subscribe to event(s) you want when component mounted\n  componentDidMount() {\n    _onFinishedPlayingSubscription = SoundPlayer.addEventListener('FinishedPlaying', ({ success }) => {\n      console.log('finished playing', success)\n    })\n    _onFinishedLoadingSubscription = SoundPlayer.addEventListener('FinishedLoading', ({ success }) => {\n      console.log('finished loading', success)\n    })\n    _onFinishedLoadingFileSubscription = SoundPlayer.addEventListener('FinishedLoadingFile', ({ success, name, type }) => {\n      console.log('finished loading file', success, name, type)\n    })\n    _onFinishedLoadingURLSubscription = SoundPlayer.addEventListener('FinishedLoadingURL', ({ success, url }) => {\n      console.log('finished loading url', success, url)\n    })\n  }\n\n  // Remove all the subscriptions when component will unmount\n  componentWillUnmount() {\n    _onFinishedPlayingSubscription.remove()\n    _onFinishedLoadingSubscription.remove()\n    _onFinishedLoadingURLSubscription.remove()\n    _onFinishedLoadingFileSubscription.remove()\n  }\n  ...\n```\n\n### `onFinishedPlaying(callback: (success: boolean) => any)`\n\nSubscribe to the \"finished playing\" event. The `callback` function is called whenever a file is finished playing. **This function will be deprecated soon, please use `addEventListener` above**.\n\n### `onFinishedLoading(callback: (success: boolean) => any)`\n\nSubscribe to the \"finished loading\" event. The `callback` function is called whenever a file is finished loading, i.e. the file is ready to be `play()`, `resume()`, `getInfo()`, etc. **This function will be deprecated soon, please use `addEventListener` above**.\n\n### `unmount()`\n\nUnsubscribe the \"finished playing\" and \"finished loading\" event. **This function will be deprecated soon, please use `addEventListener` and remove your own listener by calling `yourSubscriptionObject.remove()`**.\n\n### `play()`\n\nPlay the loaded sound file. This function is the same as `resume()`.\n\n### `pause()`\n\nPause the currently playing file.\n\n### `resume()`\n\nResume from pause and continue playing the same file. This function is the same as `play()`.\n\n### `stop()`\n\nStop playing, call `playSound(fileName: string, fileType: string)` to start playing again.\n\n### `seek(seconds: number)`\n\nSeek to `seconds` of the currently playing file.\n\n### `setSpeaker(on: boolean)`\n\nOverwrite default audio output to speaker, which forces `playUrl()` function to play from speaker.\n\n### `setMixAudio(on: boolean)`\n\nOnly available on iOS. If you set this option, your audio will be mixed with audio playing in background apps, such as the Music app.\n\n### `setVolume(volume: number)`\n\nSet the volume of the current player. This does not change the volume of the device.\n\n### `setNumberOfLoops(loops: number)`\n\n**iOS**: Set the number of loops. A negative value will loop indefinitely until the `stop()` command is called.\n\n**Android**: 0 will play the sound once. Any other number will loop indefinitely until the `stop()` command is called.\n\n### `getInfo() => Promise<{currentTime: number, duration: number}>`\n\nGet the `currentTime` and `duration` of the currently mounted audio media. This function returns a promise which resolves to an Object containing `currentTime` and `duration` properties.\n\n```javascript\n// Example\n...\n  playSong() {\n    try {\n      SoundPlayer.playSoundFile('engagementParty', 'm4a')\n    } catch (e) {\n      alert('Cannot play the file')\n      console.log('cannot play the song file', e)\n    }\n  }\n\n  async getInfo() { // You need the keyword `async`\n    try {\n      const info = await SoundPlayer.getInfo() // Also, you need to await this because it is async\n      console.log('getInfo', info) // {duration: 12.416, currentTime: 7.691}\n    } catch (e) {\n      console.log('There is no song playing', e)\n    }\n  }\n\n  onPressPlayButton() {\n    this.playSong()\n    this.getInfo()\n  }\n\n...\n```\n"
  },
  {
    "path": "RNSoundPlayer.podspec",
    "content": "require 'json'\npackage = JSON.parse(File.read(File.join(__dir__, \"package.json\")))\n\nPod::Spec.new do |s|\n\n  s.name           = \"RNSoundPlayer\"\n  s.version        = package['version']\n  s.summary        = package[\"description\"]\n  s.homepage       = \"https://github.com/johnsonsu/react-native-sound-player\"\n  s.license        = package[\"license\"]\n  s.author         = { \"Johnson Su\" => \"johnsonsu@johnsonsu.com\" }\n  s.platforms      = { :ios => \"9.0\", :tvos => \"9.0\" }\n  s.source         = { :git => \"https://github.com/johnsonsu/react-native-sound-player.git\", :tag => s.version }\n  s.source_files   = 'ios/**/*.{h,m}'\n  s.preserve_paths = \"package.json\", \"LICENSE\"\n  s.dependency 'React-Core'\n\nend\n"
  },
  {
    "path": "android/build.gradle",
    "content": "\napply plugin: 'com.android.library'\n\ndef DEFAULT_COMPILE_SDK_VERSION = 31\ndef DEFAULT_BUILD_TOOLS_VERSION = '31.0.3'\ndef DEFAULT_MIN_SDK_VERSION = 16\ndef DEFAULT_TARGET_SDK_VERSION = 31\n\ndef safeExtGet(prop, fallback) {\n    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback\n}\n\nandroid {\n    compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)\n    buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)\n\n    defaultConfig {\n        minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION)\n        targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)\n        versionCode 1\n        versionName \"1.0\"\n        ndk {\n            abiFilters \"armeabi-v7a\", \"x86\"\n        }\n    }\n    lintOptions {\n       warning 'InvalidPackage'\n    }\n}\n\ndependencies {\n    implementation 'com.facebook.react:react-native:+'\n}\n\n"
  },
  {
    "path": "android/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.johnsonsu.rnsoundplayer\">\n</manifest>\n"
  },
  {
    "path": "android/src/main/java/com/johnsonsu/rnsoundplayer/RNSoundPlayerModule.java",
    "content": "package com.johnsonsu.rnsoundplayer;\n\nimport android.content.Context;\nimport android.media.AudioManager;\nimport android.media.MediaPlayer;\nimport android.media.MediaPlayer.OnCompletionListener;\nimport android.media.MediaPlayer.OnPreparedListener;\nimport android.net.Uri;\n\nimport java.io.File;\n\nimport java.io.IOException;\nimport javax.annotation.Nullable;\n\nimport com.facebook.react.bridge.ReactApplicationContext;\nimport com.facebook.react.bridge.ReactContextBaseJavaModule;\nimport com.facebook.react.bridge.ReactMethod;\nimport com.facebook.react.bridge.Callback;\nimport com.facebook.react.bridge.ReactContext;\nimport com.facebook.react.modules.core.DeviceEventManagerModule;\nimport com.facebook.react.bridge.WritableMap;\nimport com.facebook.react.bridge.Arguments;\nimport com.facebook.react.bridge.Promise;\nimport com.facebook.react.bridge.LifecycleEventListener;\n\n\npublic class RNSoundPlayerModule extends ReactContextBaseJavaModule implements LifecycleEventListener {\n\n  public final static String EVENT_SETUP_ERROR = \"OnSetupError\";\n  public final static String EVENT_FINISHED_PLAYING = \"FinishedPlaying\";\n  public final static String EVENT_FINISHED_LOADING = \"FinishedLoading\";\n  public final static String EVENT_FINISHED_LOADING_FILE = \"FinishedLoadingFile\";\n  public final static String EVENT_FINISHED_LOADING_URL = \"FinishedLoadingURL\";\n\n  private final ReactApplicationContext reactContext;\n  private MediaPlayer mediaPlayer;\n  private float volume;\n  private AudioManager audioManager;\n\n  public RNSoundPlayerModule(ReactApplicationContext reactContext) {\n    super(reactContext);\n    this.reactContext = reactContext;\n    this.volume = 1.0f;\n    this.audioManager = (AudioManager) this.reactContext.getSystemService(Context.AUDIO_SERVICE);\n    reactContext.addLifecycleEventListener(this);\n  }\n\n  @Override\n  public String getName() {\n    return \"RNSoundPlayer\";\n  }\n\n  @ReactMethod\n  public void setSpeaker(Boolean on) {\n    audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);\n    audioManager.setSpeakerphoneOn(on);\n  }\n\n  @Override\n  public void onHostResume() {\n  }\n\n  @Override\n  public void onHostPause() {\n  }\n\n  @Override\n  public void onHostDestroy() {\n\n    this.stop();\n    if (mediaPlayer != null) {\n      mediaPlayer.release();\n      mediaPlayer = null;\n    }\n  }\n\n  @ReactMethod\n  public void playSoundFile(String name, String type) throws IOException {\n    mountSoundFile(name, type);\n    this.resume();\n  }\n\n  @ReactMethod\n  public void loadSoundFile(String name, String type) throws IOException {\n    mountSoundFile(name, type);\n  }\n\n  @ReactMethod\n  public void playUrl(String url) throws IOException {\n    prepareUrl(url);\n    this.resume();\n  }\n\n  @ReactMethod\n  public void loadUrl(String url) throws IOException {\n    prepareUrl(url);\n  }\n\n  @ReactMethod\n  public void pause() throws IllegalStateException {\n    if (this.mediaPlayer != null) {\n      this.mediaPlayer.pause();\n    }\n  }\n\n  @ReactMethod\n  public void resume() throws IOException, IllegalStateException {\n    if (this.mediaPlayer != null) {\n      this.setVolume(this.volume);\n      this.mediaPlayer.start();\n    }\n  }\n\n  @ReactMethod\n  public void stop() throws IllegalStateException {\n    if (this.mediaPlayer != null) {\n      this.mediaPlayer.stop();\n    }\n  }\n\n  @ReactMethod\n  public void seek(float seconds) throws IllegalStateException {\n    if (this.mediaPlayer != null) {\n      this.mediaPlayer.seekTo((int) seconds * 1000);\n    }\n  }\n\n  @ReactMethod\n  public void setVolume(float volume) throws IOException {\n    this.volume = volume;\n    if (this.mediaPlayer != null) {\n      this.mediaPlayer.setVolume(volume, volume);\n    }\n  }\n\n  @ReactMethod\n  public void setNumberOfLoops(int noOfLooping){\n    // The expected boolean value\n    Boolean looping;\n    if (noOfLooping == 0) {\n      looping = false;\n    }\n    else {\n      looping = true;\n    }\n\n    if (this.mediaPlayer != null) {\n      this.mediaPlayer.setLooping(looping);\n    }\n  }\n\n  @ReactMethod\n  public void getInfo(\n          Promise promise) {\n    if (this.mediaPlayer == null) {\n      promise.resolve(null);\n      return;\n    }\n    WritableMap map = Arguments.createMap();\n    map.putDouble(\"currentTime\", this.mediaPlayer.getCurrentPosition() / 1000.0);\n    map.putDouble(\"duration\", this.mediaPlayer.getDuration() / 1000.0);\n    promise.resolve(map);\n  }\n\n  @ReactMethod\n  public void addListener(String eventName) {\n    // Set up any upstream listeners or background tasks as necessary\n  }\n\n  @ReactMethod\n  public void removeListeners(Integer count) {\n    // Remove upstream listeners, stop unnecessary background tasks\n  }\n\n  private void sendEvent(ReactApplicationContext reactContext,\n                         String eventName,\n                         @Nullable WritableMap params) {\n    reactContext\n            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)\n            .emit(eventName, params);\n  }\n\n  private void mountSoundFile(String name, String type) throws IOException {\n    try {\n      Uri uri;\n      int soundResID = getReactApplicationContext().getResources().getIdentifier(name, \"raw\", getReactApplicationContext().getPackageName());\n\n      if (soundResID > 0) {\n        uri = Uri.parse(\"android.resource://\" + getReactApplicationContext().getPackageName() + \"/raw/\" + name);\n      } else {\n        uri = this.getUriFromFile(name, type);\n      }\n\n      if (this.mediaPlayer == null) {\n        this.mediaPlayer = initializeMediaPlayer(uri);\n      } else {\n        this.mediaPlayer.reset();\n        this.mediaPlayer.setDataSource(getCurrentActivity(), uri);\n        this.mediaPlayer.prepare();\n      }\n      sendMountFileSuccessEvents(name, type);\n    } catch (IOException e) {\n      sendErrorEvent(e);\n    }\n  }\n\n  private Uri getUriFromFile(String name, String type) {\n    String folder = getReactApplicationContext().getFilesDir().getAbsolutePath();\n    String file = (!type.isEmpty()) ? name + \".\" + type : name;\n\n    // http://blog.weston-fl.com/android-mediaplayer-prepare-throws-status0x1-error1-2147483648\n    // this helps avoid a common error state when mounting the file\n    File ref = new File(folder + \"/\" + file);\n\n    if (ref.exists()) {\n      ref.setReadable(true, false);\n    }\n\n    return Uri.parse(\"file://\" + folder + \"/\" + file);\n  }\n\n  private void prepareUrl(final String url) throws IOException {\n    try {\n      if (this.mediaPlayer == null) {\n        Uri uri = Uri.parse(url);\n        this.mediaPlayer = initializeMediaPlayer(uri);\n        this.mediaPlayer.setOnPreparedListener(\n                new OnPreparedListener() {\n                  @Override\n                  public void onPrepared(MediaPlayer mediaPlayer) {\n                    WritableMap onFinishedLoadingURLParams = Arguments.createMap();\n                    onFinishedLoadingURLParams.putBoolean(\"success\", true);\n                    onFinishedLoadingURLParams.putString(\"url\", url);\n                    sendEvent(getReactApplicationContext(), EVENT_FINISHED_LOADING_URL, onFinishedLoadingURLParams);\n                  }\n                }\n        );\n      } else {\n        Uri uri = Uri.parse(url);\n        this.mediaPlayer.reset();\n        this.mediaPlayer.setDataSource(getCurrentActivity(), uri);\n        this.mediaPlayer.prepare();\n      }\n      WritableMap params = Arguments.createMap();\n      params.putBoolean(\"success\", true);\n      sendEvent(getReactApplicationContext(), EVENT_FINISHED_LOADING, params);\n    } catch (IOException e) {\n      WritableMap errorParams = Arguments.createMap();\n      errorParams.putString(\"error\", e.getMessage());\n      sendEvent(getReactApplicationContext(), EVENT_SETUP_ERROR, errorParams);\n    }\n  }\n\n  private MediaPlayer initializeMediaPlayer(Uri uri) throws IOException {\n    MediaPlayer mediaPlayer = MediaPlayer.create(getCurrentActivity(), uri);\n\n    if (mediaPlayer == null) {\n      throw new IOException(\"Failed to initialize MediaPlayer for URI: \" + uri.toString());\n    }\n\n    mediaPlayer.setOnCompletionListener(\n            new OnCompletionListener() {\n              @Override\n              public void onCompletion(MediaPlayer arg0) {\n                WritableMap params = Arguments.createMap();\n                params.putBoolean(\"success\", true);\n                sendEvent(getReactApplicationContext(), EVENT_FINISHED_PLAYING, params);\n              }\n            }\n    );\n\n    return mediaPlayer;\n  }\n\n  private void sendMountFileSuccessEvents(String name, String type) {\n    WritableMap params = Arguments.createMap();\n    params.putBoolean(\"success\", true);\n    sendEvent(reactContext, EVENT_FINISHED_LOADING, params);\n\n    WritableMap onFinishedLoadingFileParams = Arguments.createMap();\n    onFinishedLoadingFileParams.putBoolean(\"success\", true);\n    onFinishedLoadingFileParams.putString(\"name\", name);\n    onFinishedLoadingFileParams.putString(\"type\", type);\n    sendEvent(reactContext, EVENT_FINISHED_LOADING_FILE, onFinishedLoadingFileParams);\n  }\n\n\n  private void sendErrorEvent(IOException e) {\n    WritableMap errorParams = Arguments.createMap();\n    errorParams.putString(\"error\", e.getMessage());\n    sendEvent(reactContext, EVENT_SETUP_ERROR, errorParams);\n  }\n}\n"
  },
  {
    "path": "android/src/main/java/com/johnsonsu/rnsoundplayer/RNSoundPlayerPackage.java",
    "content": "package com.johnsonsu.rnsoundplayer;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.facebook.react.ReactPackage;\nimport com.facebook.react.bridge.NativeModule;\nimport com.facebook.react.bridge.ReactApplicationContext;\nimport com.facebook.react.uimanager.ViewManager;\nimport com.facebook.react.bridge.JavaScriptModule;\n\npublic class RNSoundPlayerPackage implements ReactPackage {\n    @Override\n    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {\n      return Arrays.<NativeModule>asList(new RNSoundPlayerModule(reactContext));\n    }\n\n    @Override\n    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {\n      return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "index.d.ts",
    "content": "declare module \"react-native-sound-player\" {\n  import { EmitterSubscription } from \"react-native\";\n\n  export type SoundPlayerEvent =\n    | \"OnSetupError\"\n    | \"FinishedLoading\"\n    | \"FinishedPlaying\"\n    | \"FinishedLoadingURL\"\n    | \"FinishedLoadingFile\";\n\n  export type SoundPlayerEventData = {\n    success?: boolean;\n    url?: string;\n    name?: string;\n    type?: string;\n  };\n\n  interface SoundPlayerType {\n    playSoundFile: (name: string, type: string) => void;\n    playSoundFileWithDelay: (name: string, type: string, delay: number) => void;\n    loadSoundFile: (name: string, type: string) => void;\n    playUrl: (url: string) => void;\n    loadUrl: (url: string) => void;\n    playAsset: (asset: number) => void;\n    loadAsset: (asset: number) => void;\n    /** @deprecated  please use addEventListener*/\n    onFinishedPlaying: (callback: (success: boolean) => unknown) => void;\n    /** @deprecated  please use addEventListener*/\n    onFinishedLoading: (callback: (success: boolean) => unknown) => void;\n    /** Subscribe to any event. Returns a subscription object. Subscriptions created by this function cannot be removed by calling unmount(). You NEED to call yourSubscriptionObject.remove() when you no longer need this event listener or whenever your component unmounts. */\n    addEventListener: (\n      eventName: SoundPlayerEvent,\n      callback: (data: SoundPlayerEventData) => void\n    ) => EmitterSubscription;\n    /** Play the loaded sound file. This function is the same as `resume`. */\n    play: () => void;\n    /** Pause the currently playing file. */\n    pause: () => void;\n    /** Resume from pause and continue playing the same file. This function is the same as `play`. */\n    resume: () => void;\n    /** Stop playing, call `playSound` to start playing again. */\n    stop: () => void;\n    /** Seek to seconds of the currently playing file. */\n    seek: (seconds: number) => void;\n    /** Set the volume of the current player. This does not change the volume of the device. */\n    setVolume: (volume: number) => void;\n    /** Only available on iOS. Overwrite default audio output to speaker, which forces playUrl() function to play from speaker. */\n    setSpeaker: (on: boolean) => void;\n    /** Only available on iOS. If you set this option, your audio will be mixed with audio playing in background apps, such as the Music app. */\n    setMixAudio: (on: boolean) => void;\n    /** iOS: 0 means to play the sound once, a positive number specifies the number of times to return to the start and play again, a negative number indicates an indefinite loop. Android: 0 means to play the sound once, other numbers indicate an indefinite loop. */\n    setNumberOfLoops: (loops: number) => void;\n    /** Get the currentTime and duration of the currently mounted audio media. This function returns a promise which resolves to an Object containing currentTime and duration properties. */\n    getInfo: () => Promise<{ currentTime: number; duration: number }>;\n    /** @deprecated Please use addEventListener and remove your own listener by calling yourSubscriptionObject.remove(). */\n    unmount: () => void;\n  }\n\n  const SoundPlayer: SoundPlayerType;\n\n  export default SoundPlayer;\n}\n"
  },
  {
    "path": "index.js",
    "content": "/**\n * @flow\n */\n\"use strict\";\n\nimport { NativeModules, NativeEventEmitter, Platform } from \"react-native\";\nimport resolveAsset from 'react-native/Libraries/Image/resolveAssetSource';\nconst { RNSoundPlayer } = NativeModules;\n\nconst _soundPlayerEmitter = new NativeEventEmitter(RNSoundPlayer);\nlet _finishedPlayingListener = null;\nlet _finishedLoadingListener = null;\n\nexport default {\n  playSoundFile: (name: string, type: string) => {\n    RNSoundPlayer.playSoundFile(name, type);\n  },\n\n  playSoundFileWithDelay: (name: string, type: string, delay: number) => {\n    RNSoundPlayer.playSoundFileWithDelay(name, type, delay);\n  },\n\n  loadSoundFile: (name: string, type: string) => {\n    RNSoundPlayer.loadSoundFile(name, type);\n  },\n\n  setNumberOfLoops: (loops: number) => {\n    RNSoundPlayer.setNumberOfLoops(loops);\n  },\n\n  playUrl: (url: string) => {\n    RNSoundPlayer.playUrl(url);\n  },\n\n  loadUrl: (url: string) => {\n    RNSoundPlayer.loadUrl(url);\n  },\n  \n  playAsset: async (asset: number) => {\n    if (!(__DEV__) && Platform.OS === \"android\") {\n      RNSoundPlayer.playSoundFile(resolveAsset(asset).uri, '');\n    } else {\n      RNSoundPlayer.playUrl(resolveAsset(asset).uri); \n    } \n  },\n  \n  loadAsset: (asset: number) => {\n    if (!(__DEV__) && Platform.OS === \"android\") {\n      RNSoundPlayer.loadSoundFile(resolveAsset(asset).uri, '');\n    } else {\n      RNSoundPlayer.loadUrl(resolveAsset(asset).uri); \n    }\n  },\n\n  onFinishedPlaying: (callback: (success: boolean) => any) => {\n    if (_finishedPlayingListener) {\n      _finishedPlayingListener.remove();\n      _finishedPlayingListener = undefined;\n    }\n\n    _finishedPlayingListener = _soundPlayerEmitter.addListener(\n        \"FinishedPlaying\",\n        callback\n    );\n  },\n\n  onFinishedLoading: (callback: (success: boolean) => any) => {\n    if (_finishedLoadingListener) {\n      _finishedLoadingListener.remove();\n      _finishedLoadingListener = undefined;\n    }\n\n    _finishedLoadingListener = _soundPlayerEmitter.addListener(\n      \"FinishedLoading\",\n      callback\n    );\n  },\n\n  addEventListener: (\n    eventName:\n      | \"OnSetupError\"\n      | \"FinishedLoading\"\n      | \"FinishedPlaying\"\n      | \"FinishedLoadingURL\"\n      | \"FinishedLoadingFile\",\n    callback: Function\n  ) => _soundPlayerEmitter.addListener(eventName, callback),\n\n  play: () => {\n    // play and resume has the exact same implementation natively\n    RNSoundPlayer.resume();\n  },\n\n  pause: () => {\n    RNSoundPlayer.pause();\n  },\n\n  resume: () => {\n    RNSoundPlayer.resume();\n  },\n\n  stop: () => {\n    RNSoundPlayer.stop();\n  },\n\n  seek: (seconds: number) => {\n    RNSoundPlayer.seek(seconds);\n  },\n\n  setVolume: (volume: number) => {\n    RNSoundPlayer.setVolume(volume);\n  },\n\n  setSpeaker: (on: boolean) => {\n    RNSoundPlayer.setSpeaker(on);\n  },\n\n  setMixAudio: (on: boolean) => {\n    if (Platform.OS === \"android\") {\n      console.log(\"setMixAudio is not implemented on Android\");\n    } else {\n      RNSoundPlayer.setMixAudio(on);\n    }\n  },\n\n  getInfo: async () => RNSoundPlayer.getInfo(),\n\n  unmount: () => {\n    if (_finishedPlayingListener) {\n      _finishedPlayingListener.remove();\n      _finishedPlayingListener = undefined;\n    }\n\n    if (_finishedLoadingListener) {\n      _finishedLoadingListener.remove();\n      _finishedLoadingListener = undefined;\n    }\n  },\n};\n"
  },
  {
    "path": "ios/RNSoundPlayer.h",
    "content": "//\n//  RNSoundPlayer\n//\n//  Created by Johnson Su on 2018-07-10.\n//\n\n#import <React/RCTBridgeModule.h>\n#import <AVFoundation/AVFoundation.h>\n#import <React/RCTEventEmitter.h>\n\n@interface RNSoundPlayer : RCTEventEmitter <RCTBridgeModule, AVAudioPlayerDelegate>\n@property (nonatomic, strong) AVAudioPlayer *player;\n@property (nonatomic, strong) AVPlayer *avPlayer;\n@property (nonatomic) int loopCount;\n@end\n"
  },
  {
    "path": "ios/RNSoundPlayer.m",
    "content": "//\n//  RNSoundPlayer\n//\n//  Created by Johnson Su on 2018-07-10.\n//\n\n#import \"RNSoundPlayer.h\"\n#import <AVFoundation/AVFoundation.h>\n\n@implementation RNSoundPlayer\n{\n    bool hasListeners;\n}\n\nstatic NSString *const EVENT_SETUP_ERROR = @\"OnSetupError\";\nstatic NSString *const EVENT_FINISHED_LOADING = @\"FinishedLoading\";\nstatic NSString *const EVENT_FINISHED_LOADING_FILE = @\"FinishedLoadingFile\";\nstatic NSString *const EVENT_FINISHED_LOADING_URL = @\"FinishedLoadingURL\";\nstatic NSString *const EVENT_FINISHED_PLAYING = @\"FinishedPlaying\";\n\nRCT_EXPORT_MODULE();\n\n@synthesize bridge = _bridge;\n\n+ (BOOL)requiresMainQueueSetup {\n    return YES;\n}\n\n- (instancetype)init {\n    self = [super init];\n    if (self) {\n        self.loopCount = 0;\n        [[NSNotificationCenter defaultCenter] addObserver:self\n                                                 selector:@selector(itemDidFinishPlaying:)\n                                                     name:AVPlayerItemDidPlayToEndTimeNotification\n                                                   object:nil];\n    }\n    return self;\n}\n\n- (void)dealloc {\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (NSArray<NSString *> *)supportedEvents {\n    return @[EVENT_FINISHED_PLAYING, EVENT_FINISHED_LOADING, EVENT_FINISHED_LOADING_URL, EVENT_FINISHED_LOADING_FILE, EVENT_SETUP_ERROR];\n}\n\n-(void)startObserving {\n    hasListeners = YES;\n}\n\n-(void)stopObserving {\n    hasListeners = NO;\n}\n\nRCT_EXPORT_METHOD(playUrl:(NSString *)url) {\n    [self prepareUrl:url];\n    if (self.avPlayer) {\n        [self.avPlayer play];\n    }\n}\n\nRCT_EXPORT_METHOD(loadUrl:(NSString *)url) {\n    [self prepareUrl:url];\n}\n\nRCT_EXPORT_METHOD(playSoundFile:(NSString *)name ofType:(NSString *)type) {\n    [self mountSoundFile:name ofType:type];\n    if (self.player) {\n        [self.player play];\n    }\n}\n\nRCT_EXPORT_METHOD(playSoundFileWithDelay:(NSString *)name ofType:(NSString *)type delay:(double)delay) {\n    [self mountSoundFile:name ofType:type];\n    if (self.player) {\n        [self.player playAtTime:(self.player.deviceCurrentTime + delay)];\n    }\n}\n\nRCT_EXPORT_METHOD(loadSoundFile:(NSString *)name ofType:(NSString *)type) {\n    [self mountSoundFile:name ofType:type];\n}\n\nRCT_EXPORT_METHOD(pause) {\n    if (self.player != nil) {\n        [self.player pause];\n    }\n    if (self.avPlayer != nil) {\n        [self.avPlayer pause];\n    }\n}\n\nRCT_EXPORT_METHOD(resume) {\n    if (self.player != nil) {\n        [self.player play];\n    }\n    if (self.avPlayer != nil) {\n        [self.avPlayer play];\n    }\n}\n\nRCT_EXPORT_METHOD(stop) {\n    if (self.player != nil) {\n        [self.player stop];\n    }\n    if (self.avPlayer != nil) {\n        [self.avPlayer pause];\n        [self.avPlayer seekToTime:kCMTimeZero];\n    }\n}\n\nRCT_EXPORT_METHOD(seek:(float)seconds) {\n    if (self.player != nil) {\n        self.player.currentTime = seconds;\n    }\n    if (self.avPlayer != nil) {\n        [self.avPlayer seekToTime:CMTimeMakeWithSeconds(seconds, NSEC_PER_SEC)];\n    }\n}\n\n#if !TARGET_OS_TV\nRCT_EXPORT_METHOD(setSpeaker:(BOOL)on) {\n    AVAudioSession *session = [AVAudioSession sharedInstance];\n    NSError *error = nil;\n    if (on) {\n        [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];\n        [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];\n    } else {\n        [session setCategory:AVAudioSessionCategoryPlayback error:&error];\n        [session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error];\n    }\n    [session setActive:YES error:&error];\n    if (error) {\n        [self sendErrorEvent:error];\n    }\n}\n#endif\n\nRCT_EXPORT_METHOD(setMixAudio:(BOOL)on) {\n    AVAudioSession *session = [AVAudioSession sharedInstance];\n    NSError *error = nil;\n    if (on) {\n        [session setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];\n    } else {\n        [session setCategory:AVAudioSessionCategoryPlayback withOptions:0 error:&error];\n    }\n    [session setActive:YES error:&error];\n    if (error) {\n        [self sendErrorEvent:error];\n    }\n}\n\nRCT_EXPORT_METHOD(setVolume:(float)volume) {\n    if (self.player != nil) {\n        [self.player setVolume:volume];\n    }\n    if (self.avPlayer != nil) {\n        [self.avPlayer setVolume:volume];\n    }\n}\n\nRCT_EXPORT_METHOD(setNumberOfLoops:(NSInteger)loopCount) {\n    self.loopCount = loopCount;\n    if (self.player != nil) {\n        [self.player setNumberOfLoops:loopCount];\n    }\n}\n\nRCT_REMAP_METHOD(getInfo,\n                 getInfoWithResolver:(RCTPromiseResolveBlock)resolve\n                 rejecter:(RCTPromiseRejectBlock)reject) {\n    if (self.player != nil) {\n        NSDictionary *data = @{\n            @\"currentTime\": [NSNumber numberWithDouble:[self.player currentTime]],\n            @\"duration\": [NSNumber numberWithDouble:[self.player duration]]\n        };\n        resolve(data);\n    } else if (self.avPlayer != nil) {\n        CMTime currentTime = [[self.avPlayer currentItem] currentTime];\n        CMTime duration = [[[self.avPlayer currentItem] asset] duration];\n        NSDictionary *data = @{\n            @\"currentTime\": [NSNumber numberWithFloat:CMTimeGetSeconds(currentTime)],\n            @\"duration\": [NSNumber numberWithFloat:CMTimeGetSeconds(duration)]\n        };\n        resolve(data);\n    } else {\n        resolve(nil);\n    }\n}\n\n- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {\n    if (hasListeners) {\n        [self sendEventWithName:EVENT_FINISHED_PLAYING body:@{@\"success\": [NSNumber numberWithBool:flag]}];\n    }\n}\n\n- (void)itemDidFinishPlaying:(NSNotification *)notification {\n    if (hasListeners) {\n        [self sendEventWithName:EVENT_FINISHED_PLAYING body:@{@\"success\": [NSNumber numberWithBool:YES]}];\n    }\n}\n\n- (void)mountSoundFile:(NSString *)name ofType:(NSString *)type {\n    if (self.avPlayer) {\n        self.avPlayer = nil;\n    }\n\n    NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:name ofType:type];\n\n    if (soundFilePath == nil) {\n        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);\n        NSString *documentsDirectory = [paths objectAtIndex:0];\n        soundFilePath = [NSString stringWithFormat:@\"%@.%@\", [documentsDirectory stringByAppendingPathComponent:name], type];\n    }\n\n    NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];\n    NSError *error = nil;\n    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:&error];\n    if (error) {\n        [self sendErrorEvent:error];\n        return;\n    }\n    [self.player setDelegate:self];\n    [self.player setNumberOfLoops:self.loopCount];\n    [self.player prepareToPlay];\n    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];\n    if (error) {\n        [self sendErrorEvent:error];\n        return;\n    }\n    if (hasListeners) {\n        [self sendEventWithName:EVENT_FINISHED_LOADING body:@{@\"success\": [NSNumber numberWithBool:YES]}];\n        [self sendEventWithName:EVENT_FINISHED_LOADING_FILE body:@{@\"success\": [NSNumber numberWithBool:YES], @\"name\": name, @\"type\": type}];\n    }\n}\n\n- (void)prepareUrl:(NSString *)url {\n    if (self.player) {\n        self.player = nil;\n    }\n    NSURL *soundURL = [NSURL URLWithString:url];\n    self.avPlayer = [[AVPlayer alloc] initWithURL:soundURL];\n    [self.avPlayer.currentItem addObserver:self forKeyPath:@\"status\" options:0 context:nil];\n}\n\n- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {\n    if (object == self.avPlayer.currentItem && [keyPath isEqualToString:@\"status\"] && hasListeners) {\n        if (self.avPlayer.currentItem.status == AVPlayerItemStatusReadyToPlay) {\n            [self sendEventWithName:EVENT_FINISHED_LOADING body:@{@\"success\": [NSNumber numberWithBool:YES]}];\n            NSURL *url = [(AVURLAsset *)self.avPlayer.currentItem.asset URL];\n            [self sendEventWithName:EVENT_FINISHED_LOADING_URL body:@{@\"success\": [NSNumber numberWithBool:YES], @\"url\": [url absoluteString]}];\n        } else if (self.avPlayer.currentItem.status == AVPlayerItemStatusFailed) {\n            [self sendErrorEvent:self.avPlayer.currentItem.error];\n        }\n    }\n}\n\n- (void)sendErrorEvent:(NSError *)error {\n\tif (hasListeners) {\n\t    [self sendEventWithName:EVENT_SETUP_ERROR body:@{@\"error\": [error localizedDescription]}];\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ios/RNSoundPlayer.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t13BE3DEE1AC21097009241FE /* RNSoundPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* RNSoundPlayer.m */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t58B511D91A9E6C8500147676 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"include/$(PRODUCT_NAME)\";\n\t\t\tdstSubfolderSpec = 16;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t134814201AA4EA6300B7C361 /* libRNSoundPlayer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNSoundPlayer.a; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t13BE3DEC1AC21097009241FE /* RNSoundPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSoundPlayer.h; sourceTree = \"<group>\"; };\n\t\t13BE3DED1AC21097009241FE /* RNSoundPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSoundPlayer.m; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t58B511D81A9E6C8500147676 /* 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/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t134814211AA4EA7D00B7C361 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t134814201AA4EA6300B7C361 /* libRNSoundPlayer.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t58B511D21A9E6C8500147676 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t13BE3DEC1AC21097009241FE /* RNSoundPlayer.h */,\n\t\t\t\t13BE3DED1AC21097009241FE /* RNSoundPlayer.m */,\n\t\t\t\t134814211AA4EA7D00B7C361 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t58B511DA1A9E6C8500147676 /* RNSoundPlayer */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget \"RNSoundPlayer\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t58B511D71A9E6C8500147676 /* Sources */,\n\t\t\t\t58B511D81A9E6C8500147676 /* Frameworks */,\n\t\t\t\t58B511D91A9E6C8500147676 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = RNSoundPlayer;\n\t\t\tproductName = RCTDataManager;\n\t\t\tproductReference = 134814201AA4EA6300B7C361 /* libRNSoundPlayer.a */;\n\t\t\tproductType = \"com.apple.product-type.library.static\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t58B511D31A9E6C8500147676 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0610;\n\t\t\t\tORGANIZATIONNAME = Facebook;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t58B511DA1A9E6C8500147676 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.1.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject \"RNSoundPlayer\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 58B511D21A9E6C8500147676;\n\t\t\tproductRefGroup = 58B511D21A9E6C8500147676;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t58B511DA1A9E6C8500147676 /* RNSoundPlayer */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t58B511D71A9E6C8500147676 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t13BE3DEE1AC21097009241FE /* RNSoundPlayer.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t58B511ED1A9E6C8500147676 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\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_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = 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_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\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 = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t58B511EE1A9E6C8500147676 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\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_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = 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_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\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\tGCC_C_LANGUAGE_STANDARD = gnu99;\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 = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t58B511F01A9E6C8500147676 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,\n\t\t\t\t\t\"$(SRCROOT)/../../React/**\",\n\t\t\t\t\t\"$(SRCROOT)/../../node_modules/react-native/React/**\",\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tOTHER_LDFLAGS = \"-ObjC\";\n\t\t\t\tPRODUCT_NAME = RNSoundPlayer;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t58B511F11A9E6C8500147676 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,\n\t\t\t\t\t\"$(SRCROOT)/../../React/**\",\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tOTHER_LDFLAGS = \"-ObjC\";\n\t\t\t\tPRODUCT_NAME = RNSoundPlayer;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t58B511D61A9E6C8500147676 /* Build configuration list for PBXProject \"RNSoundPlayer\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t58B511ED1A9E6C8500147676 /* Debug */,\n\t\t\t\t58B511EE1A9E6C8500147676 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget \"RNSoundPlayer\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t58B511F01A9E6C8500147676 /* Debug */,\n\t\t\t\t58B511F11A9E6C8500147676 /* 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 = 58B511D31A9E6C8500147676 /* Project object */;\n}\n"
  },
  {
    "path": "ios/RNSoundPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-native-sound-player\",\n  \"version\": \"0.14.5\",\n  \"description\": \"Play or stream audio files in ReactNative on iOS/Android\",\n  \"main\": \"index.js\",\n  \"types\": \"index.d.ts\",\n  \"keywords\": [\n    \"reactnative\",\n    \"react-native\",\n    \"sound\",\n    \"player\",\n    \"audio\",\n    \"streaming\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/johnsonsu/react-native-sound-player.git\"\n  },\n  \"author\": {\n    \"name\": \"Johnson Su\",\n    \"email\": \"johnsonsu@johnsonsu.com\"\n  },\n  \"prettier\": {\n    \"trailingComma\": \"es5\",\n    \"tabWidth\": 2,\n    \"semi\": true,\n    \"singleQuote\": false\n  },\n  \"license\": \"MIT\"\n}\n"
  }
]