Skip to content

Commit bfb240e

Browse files
Merge pull request #6 from Krunal-K-SimformSolutions/feature/Add_cancel_support
Feature/add cancel support
2 parents 998ec6e + 1ec60a5 commit bfb240e

16 files changed

Lines changed: 214 additions & 112 deletions

android/src/main/java/com/reactnativeaudiowaveform/AudioRecorderWaveformViewManager.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class AudioRecorderWaveformViewManager(reactApplicationContext: ReactApplication
3434
const val COMMAND_RECORDER_PAUSE = 3
3535
const val COMMAND_RECORDER_RESUME = 4
3636
const val COMMAND_RECORDER_STOP = 5
37+
const val COMMAND_RECORDER_CANCEL = 6
3738

3839
const val TAG = "AudioRecorderWaveformView"
3940
}
@@ -51,6 +52,7 @@ class AudioRecorderWaveformViewManager(reactApplicationContext: ReactApplication
5152
.put("pause", COMMAND_RECORDER_PAUSE)
5253
.put("resume", COMMAND_RECORDER_RESUME)
5354
.put("stop", COMMAND_RECORDER_STOP)
55+
.put("cancel", COMMAND_RECORDER_CANCEL)
5456
.build()
5557
}
5658

@@ -85,6 +87,7 @@ class AudioRecorderWaveformViewManager(reactApplicationContext: ReactApplication
8587
COMMAND_RECORDER_PAUSE -> pauseRecording(root)
8688
COMMAND_RECORDER_RESUME -> resumeRecording(root)
8789
COMMAND_RECORDER_STOP -> stopRecording(root)
90+
COMMAND_RECORDER_CANCEL -> cancelRecording(root)
8891
else -> {}
8992
}
9093
}
@@ -278,4 +281,16 @@ class AudioRecorderWaveformViewManager(reactApplicationContext: ReactApplication
278281
dispatchJSEvent(OnErrorEvent(root.id, e))
279282
}
280283
}
284+
285+
private fun cancelRecording(@NonNull root: WaveformSeekBar) {
286+
DebugState.debug("cancelRecording")
287+
try {
288+
if(checkRecorderInit(root)) {
289+
recorder.cancelRecording()
290+
}
291+
} catch (e: Exception) {
292+
DebugState.error("cancelRecording", e)
293+
dispatchJSEvent(OnErrorEvent(root.id, e))
294+
}
295+
}
281296
}

android/src/main/java/com/reactnativeaudiowaveform/Recorder.kt

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Recorder private constructor(context: Context) {
2424
private val appContext = context
2525
private var withFFmpegMode = false
2626
private var withDebug = false
27+
private var withCancel = false
2728
private var withRefreshTimerMillis: Long = AudioConstants.SUBSCRIPTION_DURATION_IN_MILLISECONDS
2829

2930
private lateinit var recorder: AudioRecorder
@@ -56,59 +57,61 @@ class Recorder private constructor(context: Context) {
5657
this.convertConfig = convertConfig
5758

5859
this.source = when (sourceMode) {
59-
"noise" -> NoiseAudioSource(this.config)
60-
"auto" -> AutomaticGainAudioSource(this.config)
61-
else -> DefaultAudioSource(this.config)
62-
}
63-
return this
60+
"noise" -> NoiseAudioSource(this.config)
61+
"auto" -> AutomaticGainAudioSource(this.config)
62+
else -> DefaultAudioSource(this.config)
63+
}
64+
return this
6465
}
6566

6667
fun setSource(@NonNull filePath: String) {
67-
if(!this::recorder.isInitialized)
68-
throw Exception(Constant.NOT_INIT_RECORDER)
69-
70-
sourceFilePath = appContext.recordFile(filePath)
71-
72-
recorder.create(FFmpegRecordFinder::class.java) {
73-
this.ffmpegMode = withFFmpegMode
74-
this.destFile = sourceFilePath
75-
this.recordConfig = config
76-
this.audioSource = source
77-
this.refreshTimerMillis = withRefreshTimerMillis
78-
this.chunkAvailableCallback = onRawBuffer
79-
this.silentDetectedCallback = onSilentDetected
80-
this.timerCountCallback = onProgress
81-
this.debugMode = withDebug
82-
}
68+
if(!this::recorder.isInitialized)
69+
throw Exception(Constant.NOT_INIT_RECORDER)
70+
71+
withCancel = false
72+
sourceFilePath = appContext.recordFile(filePath)
73+
recorder.create(FFmpegRecordFinder::class.java) {
74+
this.ffmpegMode = withFFmpegMode
75+
this.destFile = sourceFilePath
76+
this.recordConfig = config
77+
this.audioSource = source
78+
this.refreshTimerMillis = withRefreshTimerMillis
79+
this.chunkAvailableCallback = onRawBuffer
80+
this.silentDetectedCallback = onSilentDetected
81+
this.timerCountCallback = onProgress
82+
this.debugMode = withDebug
83+
}
8384

84-
if (withFFmpegMode) {
85-
val ffmpegRecorder: FFmpegAudioRecorder =
86-
recorder.getAudioRecorder() as? FFmpegAudioRecorder ?: return
87-
ffmpegRecorder.setContext(appContext)
88-
ffmpegRecorder.setConvertConfig(convertConfig)
89-
ffmpegRecorder.setOnConvertStateChangeListener {
90-
onFFmpegState?.invoke(it)
91-
if (it == FFmpegConvertState.SUCCESS) {
92-
finishRecording()
93-
}
94-
}
85+
if (withFFmpegMode) {
86+
val ffmpegRecorder: FFmpegAudioRecorder =
87+
recorder.getAudioRecorder() as? FFmpegAudioRecorder ?: return
88+
ffmpegRecorder.setContext(appContext)
89+
ffmpegRecorder.setConvertConfig(convertConfig)
90+
ffmpegRecorder.setOnConvertStateChangeListener {
91+
onFFmpegState?.invoke(it)
92+
if (it == FFmpegConvertState.SUCCESS && !withCancel) {
93+
finishRecording()
94+
}
9595
}
96+
}
9697

97-
recorder.setOnRecordStateChangeListener { onRecordState?.invoke(it) }
98+
recorder.setOnRecordStateChangeListener { onRecordState?.invoke(it) }
9899
}
99100

100101
fun startRecording() {
101-
if(!this::recorder.isInitialized)
102-
throw Exception(Constant.NOT_INIT_RECORDER)
102+
if(!this::recorder.isInitialized)
103+
throw Exception(Constant.NOT_INIT_RECORDER)
103104

105+
withCancel = false
104106
if(!recorder.isRecording())
105107
recorder.startRecording()
106108
}
107109

108110
fun stopRecording() {
109-
if(!this::recorder.isInitialized)
110-
throw Exception(Constant.NOT_INIT_RECORDER)
111+
if(!this::recorder.isInitialized)
112+
throw Exception(Constant.NOT_INIT_RECORDER)
111113

114+
withCancel = false
112115
if(recorder.isRecording()) {
113116
recorder.stopRecording()
114117
if (!withFFmpegMode) {
@@ -118,21 +121,33 @@ class Recorder private constructor(context: Context) {
118121
}
119122

120123
fun resumeRecording() {
121-
if(!this::recorder.isInitialized)
122-
throw Exception(Constant.NOT_INIT_RECORDER)
124+
if(!this::recorder.isInitialized)
125+
throw Exception(Constant.NOT_INIT_RECORDER)
123126

127+
withCancel = false
124128
if(!recorder.isRecording())
125129
recorder.resumeRecording()
126130
}
127131

128132
fun pauseRecording() {
129-
if(!this::recorder.isInitialized)
130-
throw Exception(Constant.NOT_INIT_RECORDER)
133+
if(!this::recorder.isInitialized)
134+
throw Exception(Constant.NOT_INIT_RECORDER)
131135

136+
withCancel = false
132137
if(recorder.isRecording())
133138
recorder.pauseRecording()
134139
}
135140

141+
fun cancelRecording() {
142+
if(!this::recorder.isInitialized)
143+
throw Exception(Constant.NOT_INIT_RECORDER)
144+
145+
withCancel = true
146+
if(recorder.isRecording()) {
147+
recorder.stopRecording()
148+
}
149+
}
150+
136151
private fun finishRecording() {
137152
val recordMetadata = recorder.retrieveMetadata(sourceFilePath ?: File(""))
138153
onFinished?.invoke(sourceFilePath, recordMetadata)

example/ios/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ PODS:
185185
- React-cxxreact (= 0.63.4)
186186
- React-jsi (= 0.63.4)
187187
- React-jsinspector (0.63.4)
188-
- react-native-audio-waveform (0.1.0):
188+
- react-native-audio-waveform (1.0.1):
189189
- React-Core
190190
- React-RCTActionSheet (0.63.4):
191191
- React-Core/RCTActionSheetHeaders (= 0.63.4)
@@ -357,7 +357,7 @@ SPEC CHECKSUMS:
357357
React-jsi: a0418934cf48f25b485631deb27c64dc40fb4c31
358358
React-jsiexecutor: 93bd528844ad21dc07aab1c67cb10abae6df6949
359359
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
360-
react-native-audio-waveform: 0a678abd6fba6ce8c4b044ae9026c63e9b6df837
360+
react-native-audio-waveform: 94bd1cb921accc583b6316d0e5303792c3ceb75a
361361
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
362362
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
363363
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0

ios/AudioRecorderWaveformViewManager.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ @interface RCT_EXTERN_MODULE(AudioRecorderWaveformViewManager, RCTViewManager)
2929
RCT_EXTERN_METHOD(pause:(nonnull NSNumber *)reactTag viewId:(nonnull NSNumber *)viewId)
3030
RCT_EXTERN_METHOD(resume:(nonnull NSNumber *)reactTag viewId:(nonnull NSNumber *)viewId)
3131
RCT_EXTERN_METHOD(stop:(nonnull NSNumber *)reactTag viewId:(nonnull NSNumber *)viewId)
32+
RCT_EXTERN_METHOD(cancel:(nonnull NSNumber *)reactTag viewId:(nonnull NSNumber *)viewId)
3233

3334
@end

ios/AudioRecorderWaveformViewManager.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ class AudioRecorderWaveformViewManager: RCTViewManager {
4949
@objc private func handleRecorderStatusUpdate(_ notification: Notification) {
5050
let currentStatus = notification.userInfo![recordStateKey] as! RecordState
5151
DispatchQueue.main.async {
52+
self.handleTimerBasedOnRecorderState(state: currentStatus)
5253
if let onRecorderState = self.component?.onRecorderState {
5354
onRecorderState([recordStateKey: currentStatus.rawValue])
54-
self.handleTimerBasedOnRecorderState(state: currentStatus)
5555
}
5656
}
5757
}
@@ -81,6 +81,8 @@ class AudioRecorderWaveformViewManager: RCTViewManager {
8181
case .pause, .resume:
8282
self.pauseTimer()
8383
break
84+
case .canceled:
85+
self.resetTimer()
8486
}
8587
}
8688

@@ -159,6 +161,14 @@ class AudioRecorderWaveformViewManager: RCTViewManager {
159161
self.component?.reset()
160162
}
161163
}
164+
165+
@objc
166+
func cancel(_ reactTag: NSNumber, viewId: NSNumber) {
167+
AudioRecorder.sharedInstance.stopRecording()
168+
DispatchQueue.main.async {
169+
self.component?.reset()
170+
}
171+
}
162172
}
163173

164174
class AudioRecorderWaveformView : WaveformSeekBar {

ios/audio/recorder/AudioRecorder.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ class AudioRecorder {
4242

4343
func stopRecording() {
4444
DispatchQueue.main.async {
45-
print(self.audioRecorderManager.currentRecordPath!)
4645
self.audioRecorderManager.stopRecording()
4746

4847
}

ios/audio/recorder/AudioRecorderManager.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ class AudioRecorderManager: RCTEventEmitter {
261261
}
262262
}
263263

264-
func stopRecording() {
264+
func stopRecording(isCancel: Bool = false) {
265265
self.audioFile = nil
266266
self.audioEngine.inputNode.removeTap(onBus: 0)
267267
self.audioEngine.stop()
@@ -271,7 +271,11 @@ class AudioRecorderManager: RCTEventEmitter {
271271
print(error.localizedDescription)
272272
return
273273
}
274-
NotificationCenter.default.post(name: .recorderStateNotification, object: self, userInfo: [recordStateKey: RecordState.stop])
274+
if isCancel {
275+
NotificationCenter.default.post(name: .recorderStateNotification, object: self, userInfo: [recordStateKey: RecordState.stop])
276+
} else {
277+
NotificationCenter.default.post(name: .recorderStateNotification, object: self, userInfo: [recordStateKey: RecordState.canceled])
278+
}
275279

276280
}
277281

ios/audio/recorder/Extensions.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ enum RecordState : String {
1313
case stop = "STOP"
1414
case pause = "PAUSE"
1515
case resume = "RESUME"
16+
case canceled = "CANCELED"
1617
}
1718

1819
//Notification Center

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"name": "react-native-audio-waveform",
3-
"version": "0.1.0",
2+
"name": "rn-audio-waveform",
3+
"version": "1.0.1",
44
"description": "user waveform",
55
"main": "lib/commonjs/index",
66
"module": "lib/module/index",

src/player/AudioPlayerWaveformView.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
1+
import React, { forwardRef, useImperativeHandle } from 'react';
2+
import { StyleSheet, View } from 'react-native';
23
import styles from './AudioPlayerWaveformViewStyles';
34
import type {
45
AudioPlayerWaveformViewProps,
@@ -15,6 +16,8 @@ import {
1516
NativeAudioPlayerWaveformView,
1617
} from './AudioPlayerWaveformViewUtils';
1718

19+
const refView = React.createRef<View>();
20+
1821
function CustomAudioPlayerWaveformView(
1922
{
2023
style,
@@ -38,11 +41,16 @@ function CustomAudioPlayerWaveformView(
3841
}: AudioPlayerWaveformViewProps,
3942
ref: React.Ref<AudioPlayerWaveformHandleType>
4043
): React.ReactElement {
41-
const refView = useRef();
42-
4344
useImperativeHandle(ref, () => ({
44-
createPlayer: (withDebug: boolean = false, subscriptionDurationInMilliseconds: number) => {
45-
setUpPlayer(getViewId(refView), withDebug, subscriptionDurationInMilliseconds);
45+
createPlayer: (
46+
withDebug: boolean = false,
47+
subscriptionDurationInMilliseconds: number
48+
) => {
49+
setUpPlayer(
50+
getViewId(refView),
51+
withDebug,
52+
subscriptionDurationInMilliseconds
53+
);
4654
},
4755
setSource: (filePath: string, isAmplitudaMode?: boolean) => {
4856
setSource(getViewId(refView), filePath, isAmplitudaMode);
@@ -64,7 +72,7 @@ function CustomAudioPlayerWaveformView(
6472
return (
6573
<NativeAudioPlayerWaveformView
6674
ref={refView}
67-
style={[styles.defaultStyle, style]}
75+
style={StyleSheet.flatten([styles.defaultStyle, style])}
6876
progress={progress}
6977
maxProgress={maxProgress}
7078
visibleProgress={visibleProgress}
@@ -86,5 +94,6 @@ function CustomAudioPlayerWaveformView(
8694
);
8795
}
8896

89-
export const AudioPlayerWaveformView: React.ForwardRefExoticComponent<AudioPlayerWaveformViewProps> =
90-
forwardRef(CustomAudioPlayerWaveformView);
97+
export const AudioPlayerWaveformView = forwardRef(
98+
CustomAudioPlayerWaveformView
99+
);

0 commit comments

Comments
 (0)