nosnia-audio-recorder 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -2
- package/android/src/main/java/com/nosniaaudiorecorder/NosniaAudioPlayerModule.kt +238 -0
- package/android/src/main/java/com/nosniaaudiorecorder/NosniaAudioRecorderModule.kt +204 -50
- package/android/src/main/java/com/nosniaaudiorecorder/NosniaAudioRecorderPackage.kt +12 -4
- package/ios/NosniaAudioPlayer.h +7 -0
- package/ios/NosniaAudioPlayer.mm +263 -0
- package/ios/NosniaAudioRecorder.mm +261 -44
- package/lib/module/AudioPlayer.js +176 -0
- package/lib/module/AudioPlayer.js.map +1 -0
- package/lib/module/NativeNosniaAudioPlayer.js +5 -0
- package/lib/module/NativeNosniaAudioPlayer.js.map +1 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/AudioPlayer.d.ts +76 -0
- package/lib/typescript/src/AudioPlayer.d.ts.map +1 -0
- package/lib/typescript/src/NativeNosniaAudioPlayer.d.ts +24 -0
- package/lib/typescript/src/NativeNosniaAudioPlayer.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +19 -7
- package/src/AudioPlayer.tsx +201 -0
- package/src/NativeNosniaAudioPlayer.ts +26 -0
- package/src/index.tsx +9 -0
|
@@ -97,60 +97,165 @@ RCT_EXPORT_MODULE(NosniaAudioRecorder)
|
|
|
97
97
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
98
98
|
reject:(RCTPromiseRejectBlock)reject {
|
|
99
99
|
@try {
|
|
100
|
-
|
|
100
|
+
// Safety check: options must not be nil
|
|
101
|
+
if (!options) {
|
|
102
|
+
reject(@"INVALID_OPTIONS", @"Options cannot be nil", nil);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Prevent concurrent recordings
|
|
107
|
+
if (_isRecording || _audioRecorder) {
|
|
101
108
|
reject(@"ALREADY_RECORDING", @"Recording is already in progress", nil);
|
|
102
109
|
return;
|
|
103
110
|
}
|
|
104
111
|
|
|
112
|
+
// Validate and generate filename
|
|
105
113
|
NSString *filename = options[@"filename"];
|
|
106
|
-
if (!filename) {
|
|
114
|
+
if (!filename || ![filename isKindOfClass:[NSString class]] || filename.length == 0) {
|
|
107
115
|
filename = [self generateFilename];
|
|
108
116
|
}
|
|
109
117
|
|
|
118
|
+
// Get and validate recording directory
|
|
110
119
|
NSString *recordingDir = [self getRecordingDirectory];
|
|
120
|
+
if (!recordingDir) {
|
|
121
|
+
reject(@"DIRECTORY_ERROR", @"Failed to get recording directory", nil);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
111
125
|
NSString *filePath = [recordingDir stringByAppendingPathComponent:filename];
|
|
126
|
+
if (!filePath) {
|
|
127
|
+
reject(@"PATH_ERROR", @"Invalid file path", nil);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Clean up existing file to prevent conflicts
|
|
132
|
+
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
133
|
+
[fileManager removeItemAtPath:filePath error:nil];
|
|
134
|
+
|
|
112
135
|
_recordingURL = [NSURL fileURLWithPath:filePath];
|
|
136
|
+
if (!_recordingURL) {
|
|
137
|
+
reject(@"URL_ERROR", @"Failed to create file URL", nil);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Validate and sanitize audio parameters
|
|
142
|
+
NSNumber *bitrate = options[@"bitrate"];
|
|
143
|
+
if (!bitrate || ![bitrate isKindOfClass:[NSNumber class]] || [bitrate integerValue] <= 0) {
|
|
144
|
+
bitrate = @(128000);
|
|
145
|
+
}
|
|
113
146
|
|
|
114
|
-
NSNumber *
|
|
115
|
-
|
|
116
|
-
|
|
147
|
+
NSNumber *channels = options[@"channels"];
|
|
148
|
+
if (!channels || ![channels isKindOfClass:[NSNumber class]]) {
|
|
149
|
+
channels = @(1);
|
|
150
|
+
} else {
|
|
151
|
+
NSInteger chCount = [channels integerValue];
|
|
152
|
+
if (chCount <= 0 || chCount > 2) channels = @(1);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
NSNumber *sampleRate = options[@"sampleRate"];
|
|
156
|
+
if (!sampleRate || ![sampleRate isKindOfClass:[NSNumber class]] || [sampleRate integerValue] <= 0) {
|
|
157
|
+
sampleRate = @(44100);
|
|
158
|
+
}
|
|
117
159
|
|
|
160
|
+
// Get audio session
|
|
118
161
|
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
error:&categoryError];
|
|
122
|
-
if (categoryError) {
|
|
123
|
-
reject(@"AUDIO_SESSION_ERROR", categoryError.description, categoryError);
|
|
162
|
+
if (!audioSession) {
|
|
163
|
+
reject(@"AUDIO_SESSION_ERROR", @"Failed to get audio session", nil);
|
|
124
164
|
return;
|
|
125
165
|
}
|
|
126
166
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
167
|
+
// Set audio category with device compatibility options
|
|
168
|
+
NSError *categoryError = nil;
|
|
169
|
+
BOOL categorySuccess = [audioSession setCategory:AVAudioSessionCategoryRecord
|
|
170
|
+
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker
|
|
171
|
+
error:&categoryError];
|
|
172
|
+
if (!categorySuccess || categoryError) {
|
|
173
|
+
NSString *msg = categoryError ? categoryError.description : @"Failed to set audio category";
|
|
174
|
+
reject(@"AUDIO_SESSION_ERROR", msg, categoryError);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
134
177
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
reject(@"INIT_RECORDER_ERROR", recorderError.description, recorderError);
|
|
178
|
+
// Activate audio session
|
|
179
|
+
NSError *activateError = nil;
|
|
180
|
+
BOOL activateSuccess = [audioSession setActive:YES error:&activateError];
|
|
181
|
+
if (!activateSuccess || activateError) {
|
|
182
|
+
NSString *msg = activateError ? activateError.description : @"Failed to activate audio session";
|
|
183
|
+
reject(@"AUDIO_SESSION_ERROR", msg, activateError);
|
|
142
184
|
return;
|
|
143
185
|
}
|
|
144
186
|
|
|
145
|
-
|
|
146
|
-
if (!
|
|
147
|
-
reject(@"
|
|
187
|
+
// Validate recording settings dictionary
|
|
188
|
+
if (!bitrate || !channels || !sampleRate) {
|
|
189
|
+
reject(@"INVALID_SETTINGS", @"Invalid recording settings", nil);
|
|
148
190
|
return;
|
|
149
191
|
}
|
|
150
192
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
193
|
+
// Create recording settings dictionary with safety checks
|
|
194
|
+
@try {
|
|
195
|
+
NSDictionary *recordingSettings = @{
|
|
196
|
+
AVFormatIDKey: @(kAudioFormatMPEG4AAC),
|
|
197
|
+
AVSampleRateKey: sampleRate,
|
|
198
|
+
AVNumberOfChannelsKey: channels,
|
|
199
|
+
AVEncoderBitRateKey: bitrate,
|
|
200
|
+
AVEncoderAudioQualityKey: @(AVAudioQualityMedium)
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Validate settings dictionary created successfully
|
|
204
|
+
if (!recordingSettings || recordingSettings.count == 0) {
|
|
205
|
+
reject(@"SETTINGS_ERROR", @"Failed to create recording settings", nil);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Validate all required keys are present
|
|
210
|
+
if (!recordingSettings[AVFormatIDKey] || !recordingSettings[AVSampleRateKey] ||
|
|
211
|
+
!recordingSettings[AVNumberOfChannelsKey] || !recordingSettings[AVEncoderBitRateKey]) {
|
|
212
|
+
reject(@"SETTINGS_ERROR", @"Incomplete recording settings", nil);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Initialize recorder with error handling
|
|
217
|
+
NSError *recorderError = nil;
|
|
218
|
+
_audioRecorder = [[AVAudioRecorder alloc] initWithURL:_recordingURL
|
|
219
|
+
settings:recordingSettings
|
|
220
|
+
error:&recorderError];
|
|
221
|
+
|
|
222
|
+
if (recorderError) {
|
|
223
|
+
NSString *msg = recorderError.description ?: @"Unknown recorder initialization error";
|
|
224
|
+
reject(@"INIT_RECORDER_ERROR", msg, recorderError);
|
|
225
|
+
_audioRecorder = nil;
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Validate recorder was created successfully
|
|
230
|
+
if (!_audioRecorder) {
|
|
231
|
+
reject(@"INIT_RECORDER_ERROR", @"AVAudioRecorder initialization returned nil", nil);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Set delegate and enable metering
|
|
236
|
+
_audioRecorder.delegate = self;
|
|
237
|
+
[_audioRecorder setMeteringEnabled:YES];
|
|
238
|
+
|
|
239
|
+
// Attempt to start recording
|
|
240
|
+
if (![_audioRecorder record]) {
|
|
241
|
+
NSString *errorMsg = @"Failed to start recording";
|
|
242
|
+
NSError *recErr = _audioRecorder.error;
|
|
243
|
+
if (recErr) {
|
|
244
|
+
errorMsg = [NSString stringWithFormat:@"%s (Error: %@)", errorMsg.UTF8String, recErr.description];
|
|
245
|
+
}
|
|
246
|
+
reject(@"START_RECORDING_ERROR", errorMsg, nil);
|
|
247
|
+
_audioRecorder = nil;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
_isRecording = YES;
|
|
252
|
+
[self startProgressTimer];
|
|
253
|
+
resolve(nil);
|
|
254
|
+
} @catch (NSException *innerException) {
|
|
255
|
+
reject(@"SETTINGS_ERROR", [NSString stringWithFormat:@"Exception creating settings: %@", innerException.reason], nil);
|
|
256
|
+
_audioRecorder = nil;
|
|
257
|
+
_isRecording = NO;
|
|
258
|
+
}
|
|
154
259
|
} @catch (NSException *exception) {
|
|
155
260
|
reject(@"START_RECORDING_ERROR", exception.reason, nil);
|
|
156
261
|
}
|
|
@@ -164,14 +269,42 @@ RCT_EXPORT_MODULE(NosniaAudioRecorder)
|
|
|
164
269
|
return;
|
|
165
270
|
}
|
|
166
271
|
|
|
272
|
+
// Stop timer and recorder
|
|
167
273
|
[self stopProgressTimer];
|
|
168
|
-
|
|
169
|
-
|
|
274
|
+
|
|
275
|
+
// Safely stop the recorder
|
|
276
|
+
if (_audioRecorder && [_audioRecorder isRecording]) {
|
|
277
|
+
[_audioRecorder stop];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Get file path before cleaning up recorder
|
|
281
|
+
NSString *filePath = nil;
|
|
282
|
+
if (_recordingURL) {
|
|
283
|
+
filePath = [_recordingURL path];
|
|
284
|
+
if (!filePath || filePath.length == 0) {
|
|
285
|
+
filePath = @"";
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Clean up recorder
|
|
290
|
+
_audioRecorder.delegate = nil;
|
|
170
291
|
_audioRecorder = nil;
|
|
171
292
|
_isRecording = NO;
|
|
293
|
+
_recordingURL = nil;
|
|
294
|
+
|
|
295
|
+
// Validate file exists before returning
|
|
296
|
+
if (filePath && filePath.length > 0) {
|
|
297
|
+
NSFileManager *fm = [NSFileManager defaultManager];
|
|
298
|
+
if ([fm fileExistsAtPath:filePath]) {
|
|
299
|
+
resolve(filePath);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
172
303
|
|
|
173
|
-
resolve(filePath);
|
|
304
|
+
resolve(filePath ?: @"");
|
|
174
305
|
} @catch (NSException *exception) {
|
|
306
|
+
_audioRecorder = nil;
|
|
307
|
+
_isRecording = NO;
|
|
175
308
|
reject(@"STOP_RECORDING_ERROR", exception.reason, nil);
|
|
176
309
|
}
|
|
177
310
|
}
|
|
@@ -184,7 +317,17 @@ RCT_EXPORT_MODULE(NosniaAudioRecorder)
|
|
|
184
317
|
return;
|
|
185
318
|
}
|
|
186
319
|
|
|
187
|
-
|
|
320
|
+
// Check if recorder supports pause
|
|
321
|
+
if (![_audioRecorder respondsToSelector:@selector(pause)]) {
|
|
322
|
+
reject(@"PAUSE_NOT_SUPPORTED", @"Pause is not supported", nil);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Safely pause
|
|
327
|
+
if ([_audioRecorder isRecording]) {
|
|
328
|
+
[_audioRecorder pause];
|
|
329
|
+
}
|
|
330
|
+
|
|
188
331
|
resolve(nil);
|
|
189
332
|
} @catch (NSException *exception) {
|
|
190
333
|
reject(@"PAUSE_ERROR", exception.reason, nil);
|
|
@@ -194,12 +337,29 @@ RCT_EXPORT_MODULE(NosniaAudioRecorder)
|
|
|
194
337
|
- (void)resumeRecording:(RCTPromiseResolveBlock)resolve
|
|
195
338
|
reject:(RCTPromiseRejectBlock)reject {
|
|
196
339
|
@try {
|
|
197
|
-
if (!_isRecording || !_audioRecorder
|
|
340
|
+
if (!_isRecording || !_audioRecorder) {
|
|
341
|
+
reject(@"NOT_RECORDING", @"No recording in progress", nil);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Check if recorder is currently recording (not paused)
|
|
346
|
+
if ([_audioRecorder isRecording]) {
|
|
198
347
|
reject(@"NOT_PAUSED", @"Recording is not paused", nil);
|
|
199
348
|
return;
|
|
200
349
|
}
|
|
201
350
|
|
|
202
|
-
|
|
351
|
+
// Check if recorder supports record method
|
|
352
|
+
if (![_audioRecorder respondsToSelector:@selector(record)]) {
|
|
353
|
+
reject(@"RECORD_NOT_SUPPORTED", @"Record is not supported", nil);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Resume recording
|
|
358
|
+
if (![_audioRecorder record]) {
|
|
359
|
+
reject(@"RESUME_ERROR", @"Failed to resume recording", nil);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
203
363
|
resolve(nil);
|
|
204
364
|
} @catch (NSException *exception) {
|
|
205
365
|
reject(@"RESUME_ERROR", exception.reason, nil);
|
|
@@ -209,21 +369,41 @@ RCT_EXPORT_MODULE(NosniaAudioRecorder)
|
|
|
209
369
|
- (void)cancelRecording:(RCTPromiseResolveBlock)resolve
|
|
210
370
|
reject:(RCTPromiseRejectBlock)reject {
|
|
211
371
|
@try {
|
|
372
|
+
// Stop progress timer first
|
|
212
373
|
[self stopProgressTimer];
|
|
213
374
|
|
|
375
|
+
// Safely stop recorder
|
|
214
376
|
if (_audioRecorder) {
|
|
215
|
-
[_audioRecorder
|
|
377
|
+
if ([_audioRecorder isRecording] || [_audioRecorder isPaused]) {
|
|
378
|
+
[_audioRecorder stop];
|
|
379
|
+
}
|
|
380
|
+
_audioRecorder.delegate = nil;
|
|
216
381
|
_audioRecorder = nil;
|
|
217
382
|
}
|
|
218
383
|
|
|
384
|
+
// Clean up recording file
|
|
219
385
|
if (_recordingURL) {
|
|
220
386
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
221
|
-
[
|
|
387
|
+
NSString *filePath = [_recordingURL path];
|
|
388
|
+
if (filePath && [fileManager fileExistsAtPath:filePath]) {
|
|
389
|
+
NSError *deleteError = nil;
|
|
390
|
+
[fileManager removeItemAtURL:_recordingURL error:&deleteError];
|
|
391
|
+
if (deleteError) {
|
|
392
|
+
// Log but don't fail - file cleanup is not critical
|
|
393
|
+
}
|
|
394
|
+
}
|
|
222
395
|
_recordingURL = nil;
|
|
223
396
|
}
|
|
224
397
|
|
|
225
398
|
_isRecording = NO;
|
|
226
399
|
resolve(nil);
|
|
400
|
+
} @catch (NSException *exception) {
|
|
401
|
+
_audioRecorder = nil;
|
|
402
|
+
_isRecording = NO;
|
|
403
|
+
reject(@"CANCEL_ERROR", exception.reason, nil);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
resolve(nil);
|
|
227
407
|
} @catch (NSException *exception) {
|
|
228
408
|
reject(@"CANCEL_ERROR", exception.reason, nil);
|
|
229
409
|
}
|
|
@@ -234,10 +414,23 @@ RCT_EXPORT_MODULE(NosniaAudioRecorder)
|
|
|
234
414
|
@try {
|
|
235
415
|
NSMutableDictionary *status = [NSMutableDictionary dictionary];
|
|
236
416
|
status[@"isRecording"] = @(_isRecording);
|
|
237
|
-
|
|
417
|
+
|
|
418
|
+
// Safely get duration
|
|
419
|
+
double duration = 0.0;
|
|
420
|
+
if (_audioRecorder) {
|
|
421
|
+
duration = _audioRecorder.currentTime;
|
|
422
|
+
if (duration < 0) duration = 0.0;
|
|
423
|
+
}
|
|
424
|
+
status[@"duration"] = @(duration * 1000);
|
|
425
|
+
|
|
426
|
+
// Safely get file path
|
|
238
427
|
if (_recordingURL) {
|
|
239
|
-
|
|
428
|
+
NSString *filePath = [_recordingURL path];
|
|
429
|
+
if (filePath) {
|
|
430
|
+
status[@"currentFilePath"] = filePath;
|
|
431
|
+
}
|
|
240
432
|
}
|
|
433
|
+
|
|
241
434
|
resolve(status);
|
|
242
435
|
} @catch (NSException *exception) {
|
|
243
436
|
reject(@"STATUS_ERROR", exception.reason, nil);
|
|
@@ -272,14 +465,38 @@ RCT_EXPORT_MODULE(NosniaAudioRecorder)
|
|
|
272
465
|
|
|
273
466
|
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder
|
|
274
467
|
successfully:(BOOL)flag {
|
|
275
|
-
|
|
276
|
-
|
|
468
|
+
@try {
|
|
469
|
+
if (!flag) {
|
|
470
|
+
// Recording failed - log but don't crash
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
_isRecording = NO;
|
|
474
|
+
[self stopProgressTimer];
|
|
475
|
+
|
|
476
|
+
// Clean up recorder reference
|
|
477
|
+
if (_audioRecorder == recorder) {
|
|
478
|
+
_audioRecorder = nil;
|
|
479
|
+
}
|
|
480
|
+
} @catch (NSException *exception) {
|
|
481
|
+
_audioRecorder = nil;
|
|
482
|
+
_isRecording = NO;
|
|
483
|
+
}
|
|
277
484
|
}
|
|
278
485
|
|
|
279
486
|
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder
|
|
280
487
|
error:(NSError *)error {
|
|
281
|
-
|
|
282
|
-
|
|
488
|
+
@try {
|
|
489
|
+
_isRecording = NO;
|
|
490
|
+
[self stopProgressTimer];
|
|
491
|
+
|
|
492
|
+
// Clean up recorder reference
|
|
493
|
+
if (_audioRecorder == recorder) {
|
|
494
|
+
_audioRecorder = nil;
|
|
495
|
+
}
|
|
496
|
+
} @catch (NSException *exception) {
|
|
497
|
+
_audioRecorder = nil;
|
|
498
|
+
_isRecording = NO;
|
|
499
|
+
}
|
|
283
500
|
}
|
|
284
501
|
|
|
285
502
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
4
|
+
import NativeModule from "./NativeNosniaAudioPlayer.js";
|
|
5
|
+
class AudioPlayer {
|
|
6
|
+
static instance = null;
|
|
7
|
+
progressListener = null;
|
|
8
|
+
completeListener = null;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.eventEmitter = new NativeEventEmitter(NativeModules.NosniaAudioPlayer);
|
|
11
|
+
}
|
|
12
|
+
static getInstance() {
|
|
13
|
+
if (!AudioPlayer.instance) {
|
|
14
|
+
AudioPlayer.instance = new AudioPlayer();
|
|
15
|
+
}
|
|
16
|
+
return AudioPlayer.instance;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Add a listener for playback progress updates
|
|
21
|
+
* @param callback Function called with playback progress (every 100ms during playback)
|
|
22
|
+
* @returns Function to remove the listener
|
|
23
|
+
*/
|
|
24
|
+
addPlaybackProgressListener(callback) {
|
|
25
|
+
if (this.progressListener) {
|
|
26
|
+
this.progressListener.remove();
|
|
27
|
+
}
|
|
28
|
+
this.progressListener = this.eventEmitter.addListener('onPlaybackProgress', data => callback(data));
|
|
29
|
+
return () => {
|
|
30
|
+
if (this.progressListener) {
|
|
31
|
+
this.progressListener.remove();
|
|
32
|
+
this.progressListener = null;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Remove the playback progress listener
|
|
39
|
+
*/
|
|
40
|
+
removePlaybackProgressListener() {
|
|
41
|
+
if (this.progressListener) {
|
|
42
|
+
this.progressListener.remove();
|
|
43
|
+
this.progressListener = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Add a listener for playback completion
|
|
49
|
+
* @param callback Function called when playback completes
|
|
50
|
+
* @returns Function to remove the listener
|
|
51
|
+
*/
|
|
52
|
+
addPlaybackCompleteListener(callback) {
|
|
53
|
+
if (this.completeListener) {
|
|
54
|
+
this.completeListener.remove();
|
|
55
|
+
}
|
|
56
|
+
this.completeListener = this.eventEmitter.addListener('onPlaybackComplete', callback);
|
|
57
|
+
return () => {
|
|
58
|
+
if (this.completeListener) {
|
|
59
|
+
this.completeListener.remove();
|
|
60
|
+
this.completeListener = null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Remove the playback complete listener
|
|
67
|
+
*/
|
|
68
|
+
removePlaybackCompleteListener() {
|
|
69
|
+
if (this.completeListener) {
|
|
70
|
+
this.completeListener.remove();
|
|
71
|
+
this.completeListener = null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Start playing audio from a file path
|
|
77
|
+
* @param options Configuration options (filePath, volume, loop)
|
|
78
|
+
* @returns Promise that resolves when playback starts
|
|
79
|
+
*/
|
|
80
|
+
async startPlaying(options) {
|
|
81
|
+
try {
|
|
82
|
+
const config = {
|
|
83
|
+
volume: 1.0,
|
|
84
|
+
loop: false,
|
|
85
|
+
...options
|
|
86
|
+
};
|
|
87
|
+
return await NativeModule.startPlaying(config);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error('Error starting playback:', error);
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Stop playing and reset player
|
|
96
|
+
* @returns Promise that resolves when playback stops
|
|
97
|
+
*/
|
|
98
|
+
async stopPlaying() {
|
|
99
|
+
try {
|
|
100
|
+
return await NativeModule.stopPlaying();
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error('Error stopping playback:', error);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Pause the current playback
|
|
109
|
+
* @returns Promise that resolves when playback is paused
|
|
110
|
+
*/
|
|
111
|
+
async pausePlaying() {
|
|
112
|
+
try {
|
|
113
|
+
return await NativeModule.pausePlaying();
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error('Error pausing playback:', error);
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Resume a paused playback
|
|
122
|
+
* @returns Promise that resolves when playback resumes
|
|
123
|
+
*/
|
|
124
|
+
async resumePlaying() {
|
|
125
|
+
try {
|
|
126
|
+
return await NativeModule.resumePlaying();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error('Error resuming playback:', error);
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Seek to a specific time in the audio
|
|
135
|
+
* @param time Time in seconds
|
|
136
|
+
* @returns Promise that resolves when seek completes
|
|
137
|
+
*/
|
|
138
|
+
async seekToTime(time) {
|
|
139
|
+
try {
|
|
140
|
+
return await NativeModule.seekToTime(time);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error('Error seeking:', error);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Set the playback volume
|
|
149
|
+
* @param volume Volume level (0.0 to 1.0)
|
|
150
|
+
* @returns Promise that resolves when volume is set
|
|
151
|
+
*/
|
|
152
|
+
async setVolume(volume) {
|
|
153
|
+
try {
|
|
154
|
+
const clampedVolume = Math.max(0, Math.min(1, volume));
|
|
155
|
+
return await NativeModule.setVolume(clampedVolume);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error('Error setting volume:', error);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get the current status of the player
|
|
164
|
+
* @returns Promise that resolves to the current player status
|
|
165
|
+
*/
|
|
166
|
+
async getStatus() {
|
|
167
|
+
try {
|
|
168
|
+
return await NativeModule.getPlayerStatus();
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error('Error getting player status:', error);
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export const NosniaAudioPlayer = AudioPlayer.getInstance();
|
|
176
|
+
//# sourceMappingURL=AudioPlayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","NativeModules","NativeModule","AudioPlayer","instance","progressListener","completeListener","constructor","eventEmitter","NosniaAudioPlayer","getInstance","addPlaybackProgressListener","callback","remove","addListener","data","removePlaybackProgressListener","addPlaybackCompleteListener","removePlaybackCompleteListener","startPlaying","options","config","volume","loop","error","console","stopPlaying","pausePlaying","resumePlaying","seekToTime","time","setVolume","clampedVolume","Math","max","min","getStatus","getPlayerStatus"],"sourceRoot":"..\\..\\src","sources":["AudioPlayer.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"..\\..\\src","sources":["NativeNosniaAudioPlayer.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAyBpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,mBAAmB,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeEventEmitter","NativeModules","NativeModule","AudioRecorder","instance","progressListener","constructor","eventEmitter","NosniaAudioRecorder","getInstance","addRecordingProgressListener","callback","remove","addListener","data","removeRecordingProgressListener","requestPermission","requestAudioPermission","error","console","checkPermission","checkAudioPermission","startRecording","options","hasPermission","Error","config","bitrate","channels","sampleRate","stopRecording","pauseRecording","resumeRecording","cancelRecording","getStatus","getRecorderStatus"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","NativeModules","NativeModule","AudioRecorder","instance","progressListener","constructor","eventEmitter","NosniaAudioRecorder","getInstance","addRecordingProgressListener","callback","remove","addListener","data","removeRecordingProgressListener","requestPermission","requestAudioPermission","error","console","checkPermission","checkAudioPermission","startRecording","options","hasPermission","Error","config","bitrate","channels","sampleRate","stopRecording","pauseRecording","resumeRecording","cancelRecording","getStatus","getRecorderStatus","NosniaAudioPlayer"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,kBAAkB,EAAEC,aAAa,QAAQ,cAAc;AAChE,OAAOC,YAAY,MAGZ,gCAA6B;AASpC,MAAMC,aAAa,CAAC;EAClB,OAAeC,QAAQ,GAAyB,IAAI;EAE5CC,gBAAgB,GAAQ,IAAI;EAE5BC,WAAWA,CAAA,EAAG;IACpB,IAAI,CAACC,YAAY,GAAG,IAAIP,kBAAkB,CACxCC,aAAa,CAACO,mBAChB,CAAC;EACH;EAEA,OAAOC,WAAWA,CAAA,EAAkB;IAClC,IAAI,CAACN,aAAa,CAACC,QAAQ,EAAE;MAC3BD,aAAa,CAACC,QAAQ,GAAG,IAAID,aAAa,CAAC,CAAC;IAC9C;IACA,OAAOA,aAAa,CAACC,QAAQ;EAC/B;;EAEA;AACF;AACA;AACA;AACA;EACEM,4BAA4BA,CAC1BC,QAAmC,EACvB;IACZ;IACA,IAAI,IAAI,CAACN,gBAAgB,EAAE;MACzB,IAAI,CAACA,gBAAgB,CAACO,MAAM,CAAC,CAAC;IAChC;IAEA,IAAI,CAACP,gBAAgB,GAAG,IAAI,CAACE,YAAY,CAACM,WAAW,CACnD,qBAAqB,EACpBC,IAAS,IAAKH,QAAQ,CAACG,IAAI,CAC9B,CAAC;IAED,OAAO,MAAM;MACX,IAAI,IAAI,CAACT,gBAAgB,EAAE;QACzB,IAAI,CAACA,gBAAgB,CAACO,MAAM,CAAC,CAAC;QAC9B,IAAI,CAACP,gBAAgB,GAAG,IAAI;MAC9B;IACF,CAAC;EACH;;EAEA;AACF;AACA;EACEU,+BAA+BA,CAAA,EAAS;IACtC,IAAI,IAAI,CAACV,gBAAgB,EAAE;MACzB,IAAI,CAACA,gBAAgB,CAACO,MAAM,CAAC,CAAC;MAC9B,IAAI,CAACP,gBAAgB,GAAG,IAAI;IAC9B;EACF;;EAEA;AACF;AACA;AACA;EACE,MAAMW,iBAAiBA,CAAA,EAAqB;IAC1C,IAAI;MACF,OAAO,MAAMd,YAAY,CAACe,sBAAsB,CAAC,CAAC;IACpD,CAAC,CAAC,OAAOC,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,oCAAoC,EAAEA,KAAK,CAAC;MAC1D,MAAMA,KAAK;IACb;EACF;;EAEA;AACF;AACA;AACA;EACE,MAAME,eAAeA,CAAA,EAAqB;IACxC,IAAI;MACF,OAAO,MAAMlB,YAAY,CAACmB,oBAAoB,CAAC,CAAC;IAClD,CAAC,CAAC,OAAOH,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,kCAAkC,EAAEA,KAAK,CAAC;MACxD,MAAMA,KAAK;IACb;EACF;;EAEA;AACF;AACA;AACA;AACA;EACE,MAAMI,cAAcA,CAACC,OAAyB,EAAiB;IAC7D,IAAI;MACF,MAAMC,aAAa,GAAG,MAAM,IAAI,CAACJ,eAAe,CAAC,CAAC;MAClD,IAAI,CAACI,aAAa,EAAE;QAClB,MAAM,IAAIC,KAAK,CACb,mEACF,CAAC;MACH;MAEA,MAAMC,MAAuB,GAAG;QAC9BC,OAAO,EAAE,MAAM;QAAE;QACjBC,QAAQ,EAAE,CAAC;QAAE;QACbC,UAAU,EAAE,KAAK;QAAE;QACnB,GAAGN;MACL,CAAC;MAED,OAAO,MAAMrB,YAAY,CAACoB,cAAc,CAACI,MAAM,CAAC;IAClD,CAAC,CAAC,OAAOR,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,2BAA2B,EAAEA,KAAK,CAAC;MACjD,MAAMA,KAAK;IACb;EACF;;EAEA;AACF;AACA;AACA;EACE,MAAMY,aAAaA,CAAA,EAAoB;IACrC,IAAI;MACF,OAAO,MAAM5B,YAAY,CAAC4B,aAAa,CAAC,CAAC;IAC3C,CAAC,CAAC,OAAOZ,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,2BAA2B,EAAEA,KAAK,CAAC;MACjD,MAAMA,KAAK;IACb;EACF;;EAEA;AACF;AACA;AACA;EACE,MAAMa,cAAcA,CAAA,EAAkB;IACpC,IAAI;MACF,OAAO,MAAM7B,YAAY,CAAC6B,cAAc,CAAC,CAAC;IAC5C,CAAC,CAAC,OAAOb,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,0BAA0B,EAAEA,KAAK,CAAC;MAChD,MAAMA,KAAK;IACb;EACF;;EAEA;AACF;AACA;AACA;EACE,MAAMc,eAAeA,CAAA,EAAkB;IACrC,IAAI;MACF,OAAO,MAAM9B,YAAY,CAAC8B,eAAe,CAAC,CAAC;IAC7C,CAAC,CAAC,OAAOd,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,2BAA2B,EAAEA,KAAK,CAAC;MACjD,MAAMA,KAAK;IACb;EACF;;EAEA;AACF;AACA;AACA;EACE,MAAMe,eAAeA,CAAA,EAAkB;IACrC,IAAI;MACF,OAAO,MAAM/B,YAAY,CAAC+B,eAAe,CAAC,CAAC;IAC7C,CAAC,CAAC,OAAOf,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,6BAA6B,EAAEA,KAAK,CAAC;MACnD,MAAMA,KAAK;IACb;EACF;;EAEA;AACF;AACA;AACA;EACE,MAAMgB,SAASA,CAAA,EAA4B;IACzC,IAAI;MACF,OAAO,MAAMhC,YAAY,CAACiC,iBAAiB,CAAC,CAAC;IAC/C,CAAC,CAAC,OAAOjB,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,gCAAgC,EAAEA,KAAK,CAAC;MACtD,MAAMA,KAAK;IACb;EACF;AACF;AAEA,OAAO,MAAMV,mBAAmB,GAAGL,aAAa,CAACM,WAAW,CAAC,CAAC;;AAE9D;AACA,SACE2B,iBAAiB,QAKZ,kBAAe","ignoreList":[]}
|