UNPKG

react-native-sound

Version:

React Native module for playing sound clips on iOS, Android, and Windows

334 lines (287 loc) 7.49 kB
'use strict'; var ReactNative = require('react-native'); var RNSound = ReactNative.NativeModules.RNSound; var IsAndroid = RNSound.IsAndroid; var IsWindows = RNSound.IsWindows; var resolveAssetSource = require("react-native/Libraries/Image/resolveAssetSource"); var eventEmitter = new ReactNative.NativeEventEmitter(RNSound); var nextKey = 0; function isRelativePath(path) { return !/^(\/|http(s?)|asset|file)/.test(path); } function calculateRelativeVolume(volume, pan) { // calculates a lower volume relative to the pan value const relativeVolume = (volume * (1 - Math.abs(pan))); return Number(relativeVolume.toFixed(1)); } function setAndroidVolumes(sound) { // calculates the volumes for left and right channels if (sound._pan) { const relativeVolume = calculateRelativeVolume(sound._volume, sound._pan); if (sound._pan < 0) { // left is louder RNSound.setVolume(sound._key, sound._volume, relativeVolume); } else { // right is louder RNSound.setVolume(sound._key, relativeVolume, sound._volume); } } else { // no panning, same volume on both channels RNSound.setVolume(sound._key, sound._volume, sound._volume); } } function Sound(filename, basePath, onError, options) { var asset = resolveAssetSource(filename); if (asset) { this._filename = asset.uri; onError = basePath; } else { this._filename = basePath ? basePath + '/' + filename : filename; if (IsAndroid && !basePath && isRelativePath(filename)) { this._filename = filename.toLowerCase().replace(/\.[^.]+$/, ''); } } this.registerOnPlay = function() { if (this.onPlaySubscription != null) { console.warn('On Play change event listener is already registered'); return; } if (!IsWindows) { this.onPlaySubscription = eventEmitter.addListener( 'onPlayChange', (param) => { const { isPlaying, playerKey } = param; if (playerKey === this._key) { if (isPlaying) { this._playing = true; } else { this._playing = false; } } }, ); } } this._loaded = false; this._key = nextKey++; this._playing = false; this._duration = -1; this._numberOfChannels = -1; this._volume = 1; this._pan = 0; this._numberOfLoops = 0; this._speed = 1; this._pitch = 1; RNSound.prepare(this._filename, this._key, options || {}, (error, props) => { if (props) { if (typeof props.duration === 'number') { this._duration = props.duration; } if (typeof props.numberOfChannels === 'number') { this._numberOfChannels = props.numberOfChannels; } } if (error === null) { this._loaded = true; this.registerOnPlay(); } onError && onError(error, props); }); } Sound.prototype.isLoaded = function() { return this._loaded; }; Sound.prototype.play = function(onEnd) { if (this._loaded) { RNSound.play(this._key, (successfully) => onEnd && onEnd(successfully)); } else { onEnd && onEnd(false); } return this; }; Sound.prototype.pause = function(callback) { if (this._loaded) { RNSound.pause(this._key, () => { this._playing = false; callback && callback(); }); } return this; }; Sound.prototype.stop = function(callback) { if (this._loaded) { RNSound.stop(this._key, () => { this._playing = false; callback && callback(); }); } return this; }; Sound.prototype.reset = function() { if (this._loaded && IsAndroid) { RNSound.reset(this._key); this._playing = false; } return this; }; Sound.prototype.release = function() { if (this._loaded) { RNSound.release(this._key); this._loaded = false; if (!IsWindows) { if (this.onPlaySubscription != null) { this.onPlaySubscription.remove(); this.onPlaySubscription = null; } } } return this; }; Sound.prototype.getFilename = function() { return this._filename; }; Sound.prototype.getDuration = function() { return this._duration; }; Sound.prototype.getNumberOfChannels = function() { return this._numberOfChannels; }; Sound.prototype.getVolume = function() { return this._volume; }; Sound.prototype.getSpeed = function() { return this._speed; }; Sound.prototype.getPitch = function() { return this._pitch; }; Sound.prototype.setVolume = function(value) { this._volume = value; if (this._loaded) { if (IsAndroid) { setAndroidVolumes(this) } else { RNSound.setVolume(this._key, value); } } return this; }; Sound.prototype.setPan = function(value) { this._pan = value; if (this._loaded) { if (IsWindows) { throw new Error('#setPan not supported on windows'); } else if (IsAndroid) { setAndroidVolumes(this) } else { RNSound.setPan(this._key, value); } } return this; }; Sound.prototype.getSystemVolume = function(callback) { if(!IsWindows) { RNSound.getSystemVolume(callback); } return this; }; Sound.prototype.setSystemVolume = function(value) { if (IsAndroid) { RNSound.setSystemVolume(value); } return this; }; Sound.prototype.getPan = function() { return this._pan; }; Sound.prototype.getNumberOfLoops = function() { return this._numberOfLoops; }; Sound.prototype.setNumberOfLoops = function(value) { this._numberOfLoops = value; if (this._loaded) { if (IsAndroid || IsWindows) { RNSound.setLooping(this._key, !!value); } else { RNSound.setNumberOfLoops(this._key, value); } } return this; }; Sound.prototype.setSpeed = function(value) { this._speed = value; if (this._loaded) { if (!IsWindows) { RNSound.setSpeed(this._key, value); } } return this; }; Sound.prototype.setPitch = function(value) { this._pitch = value; if (this._loaded) { if (IsAndroid) { RNSound.setPitch(this._key, value); } } return this; }; Sound.prototype.getCurrentTime = function(callback) { if (this._loaded) { RNSound.getCurrentTime(this._key, callback); } }; Sound.prototype.setCurrentTime = function(value) { if (this._loaded) { RNSound.setCurrentTime(this._key, value); } return this; }; // android only Sound.prototype.setSpeakerphoneOn = function(value) { if (IsAndroid) { RNSound.setSpeakerphoneOn(this._key, value); } }; // ios only // This is deprecated. Call the static one instead. Sound.prototype.setCategory = function(value) { Sound.setCategory(value, false); } Sound.prototype.isPlaying = function() { return this._playing; } Sound.enable = function(enabled) { RNSound.enable(enabled); }; Sound.enableInSilenceMode = function(enabled) { if (!IsAndroid && !IsWindows) { RNSound.enableInSilenceMode(enabled); } }; Sound.setActive = function(value) { if (!IsAndroid && !IsWindows) { RNSound.setActive(value); } }; Sound.setCategory = function(value, mixWithOthers = false) { if (!IsWindows) { RNSound.setCategory(value, mixWithOthers); } }; Sound.setMode = function(value) { if (!IsAndroid && !IsWindows) { RNSound.setMode(value); } }; Sound.setSpeakerPhone = function(value) { if (!IsAndroid && !IsWindows) { RNSound.setSpeakerPhone(value) } } Sound.MAIN_BUNDLE = RNSound.MainBundlePath; Sound.DOCUMENT = RNSound.NSDocumentDirectory; Sound.LIBRARY = RNSound.NSLibraryDirectory; Sound.CACHES = RNSound.NSCachesDirectory; module.exports = Sound;