react-native-voximplant
Version:
VoxImplant Mobile SDK for embedding voice and video communication into React Native apps.
239 lines (224 loc) • 7.7 kB
JavaScript
/*
* Copyright (c) 2011-2020, Zingaya, Inc. All rights reserved.
*/
;
import {
NativeModules,
NativeEventEmitter,
} from 'react-native';
import AudioFileEventTypes from "./AudioFileEventTypes";
const AudioFileModule = NativeModules.RNVIAudioFileModule;
const EventEmitter = new NativeEventEmitter(AudioFileModule);
/**
* @memberof Voximplant.Hardware
* @class AudioFile
* @classdesc Class may be used to play audio files.
*/
export default class AudioFile {
/**
* @member {string} url - HTTP URL of the stream to play
* @memberOf Voximplant.Hardware.AudioFile
*/
url;
/**
* @member {boolean} looped - Indicate if the audio file should be played repeatedly or once
* @memberOf Voximplant.Hardware.AudioFile
*/
looped;
/**
* @member {string} url - Local audio file name
* @memberOf Voximplant.Hardware.AudioFile
*/
name;
/**
* @ignore
*/
constructor() {
this.listeners = {};
this.fileId = null;
this._audioFileStartedSubscriber = EventEmitter.addListener('VIAudioFileStarted', this._VIAudioFileStarted);
this._audioFileStoppedSubscriber = EventEmitter.addListener('VIAudioFileStopped', this._VIAudioFileStopped);
}
/**
* Initialize AudioFile instance to play local audio file.
*
* On android, the audio file must be located in resources "raw" folder.
*
* @param {string} name - Local audio file name
* @param {string} type - Local audio file type/format, for example ".mp3"
* @param {Voximplant.Hardware.AudioFileUsage} usage - Audio file usage mode. ANDROID ONLY.
* @return {Promise}
* @memberof Voximplant.Hardware.AudioFile
*/
initWithLocalFile(name, type, usage) {
return new Promise((resolve, reject) => {
this.name = name;
AudioFileModule.initWithFile({
name: name,
type: type,
usage: usage,
}, (fileId, error) => {
if (error) {
reject(error);
} else {
this.fileId = fileId;
resolve();
}
});
})
}
/**
* Initialize AudioFile to play a stream from a network.
*
* @param {string} url - HTTP URL of the stream to play
* @param {Voximplant.Hardware.AudioFileUsage} usage usage - Audio file usage mode. ANDROID ONLY.
* @return {Promise}
* @memberof Voximplant.Hardware.AudioFile
*/
loadFile(url, usage) {
return new Promise((resolve, reject) => {
this.url = url;
AudioFileModule.loadFile({
url: url,
usage: usage,
}, (fileId, error) => {
if (error) {
reject(error);
} else {
this.fileId = fileId;
resolve();
}
});
});
}
/**
* Start playing the audio file repeatedly or once.
* @param {boolean} looped - Indicate if the audio file should be played repeatedly or once
* @return {Promise<EventHandlers.AudioFileStarted>}
* @memberof Voximplant.Hardware.AudioFile
*/
play(looped) {
this.looped = looped;
return new Promise((resolve, reject) => {
let started = (event) => {
this.off(AudioFileEventTypes.Started, started);
console.log(`AudioFile: received event in start`);
if (event.result) {
resolve(event);
} else {
reject(event);
}
};
this.on(AudioFileEventTypes.Started, started);
AudioFileModule.play(this.fileId, looped);
});
}
/**
* Stop playing of the audio file.
*
* @return {Promise<EventHandlers.AudioFileStopped>}
* @memberof Voximplant.Hardware.AudioFile
*/
stop() {
return new Promise((resolve, reject) => {
let stopped = (event) => {
console.log(`AudioFile: received event in stop`);
this.off(AudioFileEventTypes.Stopped, stopped);
if (event.result) {
resolve(event);
} else {
reject(event);
}
};
this.on(AudioFileEventTypes.Stopped, stopped);
AudioFileModule.stop(this.fileId);
});
}
/**
* Release all resources allocated to play the audio file.
*
* Must be called even if the audio file was not played.
*
* @memberof Voximplant.Hardware.AudioFile
*/
releaseResources() {
if (this._audioFileStartedSubscriber) {
this._audioFileStartedSubscriber.remove();
delete this._audioFileStartedSubscriber;
}
if (this._audioFileStoppedSubscriber) {
this._audioFileStoppedSubscriber.remove();
delete this._audioFileStoppedSubscriber;
}
AudioFileModule.releaseResources(this.fileId);
}
/**
* Register a handler for the specified AudioFile event.
* One event can have more than one handler.
* Use the {@link Voximplant.Hardware.AudioFile#off} method to delete a handler.
* @param {Voximplant.Hardware.AudioFileEventTypes} event
* @param {function} handler
* @memberof Voximplant.Hardware.AudioFile
*/
on(event, handler) {
if (!handler || !(handler instanceof Function)) {
console.warn(`AudioFile: on: handler is not a Function`);
return;
}
if (Object.values(AudioFileEventTypes).indexOf(event) === -1) {
console.warn(`AudioFile: on: AudioFileEventTypes does not contain ${event} event`);
return;
}
if (!this.listeners[event]) {
this.listeners[event] = new Set();
}
this.listeners[event].add(handler);
}
/**
* Remove a handler for the specified AudioFile event.
* @param {Voximplant.Hardware.AudioFileEventTypes} event
* @param {function} handler - Handler function. If not specified, all handlers for the event will be removed.
* @memberof Voximplant.Hardware.AudioFile
*/
off(event, handler) {
if (!this.listeners[event]) {
return;
}
if (Object.values(AudioFileEventTypes).indexOf(event) === -1) {
console.warn(`AudioFile: off: AudioFileEventTypes does not contain ${event} event`);
return;
}
if (handler && handler instanceof Function) {
this.listeners[event].delete(handler);
} else {
this.listeners[event] = new Set();
}
}
/**
* @private
*/
_emit(event, ...args) {
const handlers = this.listeners[event];
if (handlers) {
for (const handler of handlers) {
handler(...args);
}
}
}
_VIAudioFileStarted = (event) => {
console.log(`AudioFile: received started event in general handler: ${event.fileId}`);
if (event.fileId === this.fileId) {
delete event.fileId;
event.audioFile = this;
this._emit(AudioFileEventTypes.Started, event);
}
};
_VIAudioFileStopped = (event) => {
console.log(`AudioFile: received stopped event in general handler: ${event.fileId}`);
if (event.fileId === this.fileId) {
delete event.fileId;
event.audioFile = this;
this._emit(AudioFileEventTypes.Stopped, event);
}
};
}