Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
334 changes: 334 additions & 0 deletions index.fc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
import {useState} from 'react';
import type {EmitterSubscription} from 'react-native';
import {
DeviceEventEmitter,
NativeEventEmitter,
NativeModules,
Platform,
} from 'react-native';
import {AudioSet, PlayBackType, RecordBackType, Status, pad} from './types';

const {RNAudioRecorderPlayer} = NativeModules;
export function AudioRecorderPlayerFC() {
const [isRecording, setIsRecording] = useState(false);
const [isPlaying, setIsPlaying] = useState(false);
const [hasPaused, setHasPaused] = useState(false);
const [hasPausedRecord, setHasPausedRecord] = useState(false);
const [isStopped, setIsStopped] = useState(false);
const [isFinished, setIsFinished] = useState(false);

const [recorderSubscription, setRecorderSubscription] =
useState<EmitterSubscription | null>(null);
const [playerSubscription, setPlayerSubscription] =
useState<EmitterSubscription | null>(null);
let _playerCallback: ((event: PlayBackType) => void) | null;

const mmss = (secs: number): string => {
let minutes = Math.floor(secs / 60);

secs = secs % 60;
minutes = minutes % 60;

return pad(minutes) + ':' + pad(secs);
};

const mmssss = (milisecs: number): string => {
const secs = Math.floor(milisecs / 1000);
const minutes = Math.floor(secs / 60);
const seconds = secs % 60;
const miliseconds = Math.floor((milisecs % 1000) / 10);

return pad(minutes) + ':' + pad(seconds) + ':' + pad(miliseconds);
};

/**
* Set listerner from native module for recorder.
* @returns {callBack((e: RecordBackType): void)}
*/

const addRecordBackListener = (
callback: (recordingMeta: RecordBackType) => void,
): void => {
if (Platform.OS === 'android') {
setRecorderSubscription(
DeviceEventEmitter.addListener('rn-recordback', callback),
);
} else {
const myModuleEvt = new NativeEventEmitter(RNAudioRecorderPlayer);
setRecorderSubscription(
myModuleEvt.addListener('rn-recordback', callback),
);
}
};

/**
* Remove listener for recorder.
* @returns {void}
*/
const removeRecordBackListener = (): void => {
if (recorderSubscription) {
recorderSubscription.remove();
setRecorderSubscription(null);
}
};

/**
* Set listener from native module for player.
* @returns {callBack((e: PlayBackType): void)}
*/
const addPlayBackListener = (
callback: (playbackMeta: PlayBackType) => void,
): void => {
_playerCallback = callback;
};

/**
* remove listener for player.
* @returns {void}
*/
const removePlayBackListener = (): void => {
_playerCallback = null;
};

/**
* start recording with param.
* @param {string} uri audio uri.
* @returns {Promise<string>}
*/
const startRecorder = async (
uri?: string,
audioSets?: AudioSet,
meteringEnabled?: boolean,
): Promise<string> => {
if (!isRecording) {
setIsRecording(true);

try {
return await RNAudioRecorderPlayer.startRecorder(
uri ?? 'DEFAULT',
audioSets,
meteringEnabled ?? false,
);
} catch (error: any) {
setIsRecording(false);
throw error;
}
}

return 'Already recording';
};

/**
* Pause recording.
* @returns {Promise<string>}
*/
const pauseRecorder = async (): Promise<string> => {
if (!hasPausedRecord) {
setHasPausedRecord(true);

return RNAudioRecorderPlayer.pauseRecorder();
}

return 'Already paused recording.';
};

/**
* Resume recording.
* @returns {Promise<string>}
*/
const resumeRecorder = async (): Promise<string> => {
if (hasPausedRecord) {
setHasPausedRecord(false);

return RNAudioRecorderPlayer.resumeRecorder();
}

return 'Currently recording.';
};

/**
* stop recording.
* @returns {Promise<string>}
*/
const stopRecorder = async (): Promise<string> => {
if (isRecording) {
setIsRecording(false);
setHasPausedRecord(false);
setIsStopped(true);
return RNAudioRecorderPlayer.stopRecorder();
}

return 'Already stopped';
};

/**
* Resume playing.
* @returns {Promise<string>}
*/
const resumePlayer = async (): Promise<string> => {
if (!isPlaying) {
return 'No audio playing';
}

if (hasPaused) {
setHasPaused(false);

return RNAudioRecorderPlayer.resumePlayer();
}

return 'Already playing';
};

const playerCallback = (event: PlayBackType): void => {
if (_playerCallback) {
_playerCallback(event);
}

if (event.isFinished) {
setIsFinished(true);
stopPlayer();
}
};

/**
* Start playing with param.
* @param {string} uri audio uri.
* @param {Record<string, string>} httpHeaders Set of http headers.
* @returns {Promise<string>}
*/
const startPlayer = async (
uri?: string,
httpHeaders?: Record<string, string>,
): Promise<string> => {
if (!uri) {
uri = 'DEFAULT';
}

if (!playerSubscription) {
if (Platform.OS === 'android') {
setPlayerSubscription(
DeviceEventEmitter.addListener('rn-playback', playerCallback),
);
} else {
const myModuleEvt = new NativeEventEmitter(RNAudioRecorderPlayer);

setPlayerSubscription(
myModuleEvt.addListener('rn-playback', playerCallback),
);
}
}

if (!isPlaying || hasPaused) {
setIsPlaying(true);
setHasPaused(false);

return RNAudioRecorderPlayer.startPlayer(uri, httpHeaders);
}
return `Playing out of sync: playing: ${isPlaying}, paused: ${hasPaused}, subscription: ${playerSubscription}`;
};

/**
* Stop playing.
* @returns {Promise<string>}
*/
const stopPlayer = async (): Promise<string> => {
if (isPlaying) {
setIsPlaying(false);
setHasPaused(false);

return RNAudioRecorderPlayer.stopPlayer();
}

return 'Already stopped playing';
};

/**
* Pause playing.
* @returns {Promise<string>}
*/
const pausePlayer = async (): Promise<string> => {
if (!isPlaying) {
return 'No audio playing';
}

if (!hasPaused) {
setHasPaused(true);

return RNAudioRecorderPlayer.pausePlayer();
}
return `Pausing out of sync: playing: ${isPlaying}, paused: ${hasPaused}`;
};

/**
* Seek to.
* @param {number} time position seek to in millisecond.
* @returns {Promise<string>}
*/
const seekToPlayer = async (time: number): Promise<string> => {
return RNAudioRecorderPlayer.seekToPlayer(time);
};

/**
* Set volume.
* @param {number} setVolume set volume.
* @returns {Promise<string>}
*/
const setVolume = async (volume: number): Promise<string> => {
if (volume < 0 || volume > 1) {
throw new Error('Value of volume should be between 0.0 to 1.0');
}

return RNAudioRecorderPlayer.setVolume(volume);
};

/**
* Set playback speed.
* @param {number} setPlaybackSpeed set playback speed.
* @returns {Promise<string>}
*/
const setPlaybackSpeed = async (playbackSpeed: number): Promise<string> => {
return RNAudioRecorderPlayer.setPlaybackSpeed(playbackSpeed);
};

/**
* Set subscription duration. Default is 0.5.
* @param {number} sec subscription callback duration in seconds.
* @returns {Promise<string>}
*/
const setSubscriptionDuration = async (sec: number): Promise<string> => {
return RNAudioRecorderPlayer.setSubscriptionDuration(sec);
};

const getStatus = (): Status => {
return {
isPlaying,
isRecording,
hasPaused,
hasPausedRecord,
isStopped,
isFinished,
};
};
return {
getStatus,
setSubscriptionDuration,
setPlaybackSpeed,
setVolume,
seekToPlayer,
pausePlayer,
stopPlayer,
mmssss,
mmss,
addRecordBackListener,
startPlayer,
playerCallback,
stopRecorder,
resumePlayer,
resumeRecorder,
pauseRecorder,
removePlayBackListener,
startRecorder,
addPlayBackListener,
removeRecordBackListener,
};
}
Loading