nosnia-audio-recorder 0.9.14 → 0.9.17
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/android/src/main/java/com/nosniaaudiorecorder/NosniaAudioPlayerModule.kt +237 -237
- package/ios/NosniaAudioPlayer.h +6 -6
- package/ios/NosniaAudioPlayer.mm +254 -254
- package/ios/NosniaAudioRecorder.mm +28 -32
- package/ios/Pods/Pods.xcodeproj/xcuserdata/nosnia.xcuserdatad/xcschemes/xcschememanagement.plist +10 -0
- package/lib/module/AudioPlayer.js.map +1 -1
- package/lib/module/NativeNosniaAudioPlayer.js.map +1 -1
- package/lib/module/NativeNosniaAudioRecorder.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/package.json +174 -174
package/ios/NosniaAudioPlayer.mm
CHANGED
|
@@ -1,254 +1,254 @@
|
|
|
1
|
-
#import "NosniaAudioPlayer.h"
|
|
2
|
-
#import <AVFoundation/AVFoundation.h>
|
|
3
|
-
#import <React/RCTBridgeModule.h>
|
|
4
|
-
#import <React/RCTEventEmitter.h>
|
|
5
|
-
|
|
6
|
-
@interface NosniaAudioPlayer () <AVAudioPlayerDelegate>
|
|
7
|
-
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
|
|
8
|
-
@property (nonatomic, assign) BOOL isPlaying;
|
|
9
|
-
@property (nonatomic, strong) NSTimer *progressTimer;
|
|
10
|
-
@property (nonatomic, strong) NSString *currentFilePath;
|
|
11
|
-
@end
|
|
12
|
-
|
|
13
|
-
@implementation NosniaAudioPlayer {
|
|
14
|
-
AVAudioPlayer *_audioPlayer;
|
|
15
|
-
BOOL _isPlaying;
|
|
16
|
-
NSTimer *_progressTimer;
|
|
17
|
-
NSString *_currentFilePath;
|
|
18
|
-
BOOL _hasListeners;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
RCT_EXPORT_MODULE(NosniaAudioPlayer)
|
|
22
|
-
|
|
23
|
-
- (instancetype)init {
|
|
24
|
-
self = [super init];
|
|
25
|
-
if (self) {
|
|
26
|
-
_isPlaying = NO;
|
|
27
|
-
_hasListeners = NO;
|
|
28
|
-
}
|
|
29
|
-
return self;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
- (NSArray<NSString *> *)supportedEvents {
|
|
33
|
-
return @[@"onPlaybackProgress", @"onPlaybackComplete"];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
- (void)startObserving {
|
|
37
|
-
_hasListeners = YES;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
- (void)stopObserving {
|
|
41
|
-
_hasListeners = NO;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
- (void)startProgressTimer {
|
|
45
|
-
if (_progressTimer) {
|
|
46
|
-
[_progressTimer invalidate];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
_progressTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
|
|
50
|
-
repeats:YES
|
|
51
|
-
block:^(NSTimer * _Nonnull timer) {
|
|
52
|
-
if (self->_hasListeners && self->_audioPlayer && self->_isPlaying) {
|
|
53
|
-
NSTimeInterval currentTime = self->_audioPlayer.currentTime;
|
|
54
|
-
NSTimeInterval duration = self->_audioPlayer.duration;
|
|
55
|
-
[self sendEventWithName:@"onPlaybackProgress"
|
|
56
|
-
body:@{
|
|
57
|
-
@"currentTime": @(currentTime * 1000),
|
|
58
|
-
@"duration": @(duration * 1000),
|
|
59
|
-
@"isPlaying": @(self->_audioPlayer.isPlaying)
|
|
60
|
-
}];
|
|
61
|
-
}
|
|
62
|
-
}];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
- (void)stopProgressTimer {
|
|
66
|
-
if (_progressTimer) {
|
|
67
|
-
[_progressTimer invalidate];
|
|
68
|
-
_progressTimer = nil;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
- (void)startPlaying:(NSDictionary *)options
|
|
73
|
-
resolve:(RCTPromiseResolveBlock)resolve
|
|
74
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
75
|
-
@try {
|
|
76
|
-
NSString *filePath = options[@"filePath"];
|
|
77
|
-
if (!filePath) {
|
|
78
|
-
reject(@"INVALID_PATH", @"File path is required", nil);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
NSNumber *volume = options[@"volume"] ?: @(1.0);
|
|
83
|
-
NSNumber *loop = options[@"loop"] ?: @(NO);
|
|
84
|
-
|
|
85
|
-
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
|
|
86
|
-
NSError *error = nil;
|
|
87
|
-
|
|
88
|
-
// Setup audio session for playback
|
|
89
|
-
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
|
|
90
|
-
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
|
|
91
|
-
if (error) {
|
|
92
|
-
reject(@"AUDIO_SESSION_ERROR", error.description, error);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
[audioSession setActive:YES error:&error];
|
|
96
|
-
if (error) {
|
|
97
|
-
reject(@"AUDIO_SESSION_ERROR", error.description, error);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
|
|
102
|
-
if (error) {
|
|
103
|
-
reject(@"INIT_PLAYER_ERROR", error.description, error);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
_audioPlayer.delegate = self;
|
|
108
|
-
_audioPlayer.volume = [volume floatValue];
|
|
109
|
-
_audioPlayer.numberOfLoops = [loop boolValue] ? -1 : 0;
|
|
110
|
-
|
|
111
|
-
if (![_audioPlayer prepareToPlay]) {
|
|
112
|
-
reject(@"PREPARE_ERROR", @"Failed to prepare audio player", nil);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (![_audioPlayer play]) {
|
|
117
|
-
reject(@"START_PLAYING_ERROR", @"Failed to start playing", nil);
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
_isPlaying = YES;
|
|
122
|
-
_currentFilePath = filePath;
|
|
123
|
-
[self startProgressTimer];
|
|
124
|
-
resolve(nil);
|
|
125
|
-
} @catch (NSException *exception) {
|
|
126
|
-
reject(@"START_PLAYING_ERROR", exception.reason, nil);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
- (void)stopPlaying:(RCTPromiseResolveBlock)resolve
|
|
131
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
132
|
-
@try {
|
|
133
|
-
[self stopProgressTimer];
|
|
134
|
-
|
|
135
|
-
if (_audioPlayer) {
|
|
136
|
-
[_audioPlayer stop];
|
|
137
|
-
_audioPlayer = nil;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
_isPlaying = NO;
|
|
141
|
-
_currentFilePath = nil;
|
|
142
|
-
resolve(nil);
|
|
143
|
-
} @catch (NSException *exception) {
|
|
144
|
-
reject(@"STOP_PLAYING_ERROR", exception.reason, nil);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
- (void)pausePlaying:(RCTPromiseResolveBlock)resolve
|
|
149
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
150
|
-
@try {
|
|
151
|
-
if (!_isPlaying || !_audioPlayer) {
|
|
152
|
-
reject(@"NOT_PLAYING", @"No playback in progress", nil);
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
[_audioPlayer pause];
|
|
157
|
-
_isPlaying = NO;
|
|
158
|
-
resolve(nil);
|
|
159
|
-
} @catch (NSException *exception) {
|
|
160
|
-
reject(@"PAUSE_ERROR", exception.reason, nil);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
- (void)resumePlaying:(RCTPromiseResolveBlock)resolve
|
|
165
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
166
|
-
@try {
|
|
167
|
-
if (!_audioPlayer || _isPlaying) {
|
|
168
|
-
reject(@"NOT_PAUSED", @"Playback is not paused", nil);
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
[_audioPlayer play];
|
|
173
|
-
_isPlaying = YES;
|
|
174
|
-
resolve(nil);
|
|
175
|
-
} @catch (NSException *exception) {
|
|
176
|
-
reject(@"RESUME_ERROR", exception.reason, nil);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
- (void)seekToTime:(double)time
|
|
181
|
-
resolve:(RCTPromiseResolveBlock)resolve
|
|
182
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
183
|
-
@try {
|
|
184
|
-
if (!_audioPlayer) {
|
|
185
|
-
reject(@"NO_PLAYER", @"No audio player initialized", nil);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
_audioPlayer.currentTime = time;
|
|
190
|
-
resolve(nil);
|
|
191
|
-
} @catch (NSException *exception) {
|
|
192
|
-
reject(@"SEEK_ERROR", exception.reason, nil);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
- (void)setVolume:(double)volume
|
|
197
|
-
resolve:(RCTPromiseResolveBlock)resolve
|
|
198
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
199
|
-
@try {
|
|
200
|
-
if (!_audioPlayer) {
|
|
201
|
-
reject(@"NO_PLAYER", @"No audio player initialized", nil);
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
_audioPlayer.volume = volume;
|
|
206
|
-
resolve(nil);
|
|
207
|
-
} @catch (NSException *exception) {
|
|
208
|
-
reject(@"SET_VOLUME_ERROR", exception.reason, nil);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
- (void)getPlayerStatus:(RCTPromiseResolveBlock)resolve
|
|
213
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
214
|
-
@try {
|
|
215
|
-
NSMutableDictionary *status = [NSMutableDictionary dictionary];
|
|
216
|
-
status[@"isPlaying"] = @(_isPlaying);
|
|
217
|
-
|
|
218
|
-
if (_audioPlayer) {
|
|
219
|
-
status[@"duration"] = @(_audioPlayer.duration * 1000);
|
|
220
|
-
status[@"currentTime"] = @(_audioPlayer.currentTime * 1000);
|
|
221
|
-
} else {
|
|
222
|
-
status[@"duration"] = @(0);
|
|
223
|
-
status[@"currentTime"] = @(0);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
if (_currentFilePath) {
|
|
227
|
-
status[@"currentFilePath"] = _currentFilePath;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
resolve(status);
|
|
231
|
-
} @catch (NSException *exception) {
|
|
232
|
-
reject(@"STATUS_ERROR", exception.reason, nil);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
#pragma mark - AVAudioPlayerDelegate
|
|
237
|
-
|
|
238
|
-
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
|
|
239
|
-
successfully:(BOOL)flag {
|
|
240
|
-
_isPlaying = NO;
|
|
241
|
-
[self stopProgressTimer];
|
|
242
|
-
|
|
243
|
-
if (_hasListeners) {
|
|
244
|
-
[self sendEventWithName:@"onPlaybackComplete" body:@{}];
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player
|
|
249
|
-
error:(NSError *)error {
|
|
250
|
-
_isPlaying = NO;
|
|
251
|
-
[self stopProgressTimer];
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
@end
|
|
1
|
+
#import "NosniaAudioPlayer.h"
|
|
2
|
+
#import <AVFoundation/AVFoundation.h>
|
|
3
|
+
#import <React/RCTBridgeModule.h>
|
|
4
|
+
#import <React/RCTEventEmitter.h>
|
|
5
|
+
|
|
6
|
+
@interface NosniaAudioPlayer () <AVAudioPlayerDelegate>
|
|
7
|
+
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
|
|
8
|
+
@property (nonatomic, assign) BOOL isPlaying;
|
|
9
|
+
@property (nonatomic, strong) NSTimer *progressTimer;
|
|
10
|
+
@property (nonatomic, strong) NSString *currentFilePath;
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
@implementation NosniaAudioPlayer {
|
|
14
|
+
AVAudioPlayer *_audioPlayer;
|
|
15
|
+
BOOL _isPlaying;
|
|
16
|
+
NSTimer *_progressTimer;
|
|
17
|
+
NSString *_currentFilePath;
|
|
18
|
+
BOOL _hasListeners;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
RCT_EXPORT_MODULE(NosniaAudioPlayer)
|
|
22
|
+
|
|
23
|
+
- (instancetype)init {
|
|
24
|
+
self = [super init];
|
|
25
|
+
if (self) {
|
|
26
|
+
_isPlaying = NO;
|
|
27
|
+
_hasListeners = NO;
|
|
28
|
+
}
|
|
29
|
+
return self;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
- (NSArray<NSString *> *)supportedEvents {
|
|
33
|
+
return @[@"onPlaybackProgress", @"onPlaybackComplete"];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
- (void)startObserving {
|
|
37
|
+
_hasListeners = YES;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
- (void)stopObserving {
|
|
41
|
+
_hasListeners = NO;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
- (void)startProgressTimer {
|
|
45
|
+
if (_progressTimer) {
|
|
46
|
+
[_progressTimer invalidate];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
_progressTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
|
|
50
|
+
repeats:YES
|
|
51
|
+
block:^(NSTimer * _Nonnull timer) {
|
|
52
|
+
if (self->_hasListeners && self->_audioPlayer && self->_isPlaying) {
|
|
53
|
+
NSTimeInterval currentTime = self->_audioPlayer.currentTime;
|
|
54
|
+
NSTimeInterval duration = self->_audioPlayer.duration;
|
|
55
|
+
[self sendEventWithName:@"onPlaybackProgress"
|
|
56
|
+
body:@{
|
|
57
|
+
@"currentTime": @(currentTime * 1000),
|
|
58
|
+
@"duration": @(duration * 1000),
|
|
59
|
+
@"isPlaying": @(self->_audioPlayer.isPlaying)
|
|
60
|
+
}];
|
|
61
|
+
}
|
|
62
|
+
}];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
- (void)stopProgressTimer {
|
|
66
|
+
if (_progressTimer) {
|
|
67
|
+
[_progressTimer invalidate];
|
|
68
|
+
_progressTimer = nil;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
- (void)startPlaying:(NSDictionary *)options
|
|
73
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
74
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
75
|
+
@try {
|
|
76
|
+
NSString *filePath = options[@"filePath"];
|
|
77
|
+
if (!filePath) {
|
|
78
|
+
reject(@"INVALID_PATH", @"File path is required", nil);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
NSNumber *volume = options[@"volume"] ?: @(1.0);
|
|
83
|
+
NSNumber *loop = options[@"loop"] ?: @(NO);
|
|
84
|
+
|
|
85
|
+
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
|
|
86
|
+
NSError *error = nil;
|
|
87
|
+
|
|
88
|
+
// Setup audio session for playback
|
|
89
|
+
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
|
|
90
|
+
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
|
|
91
|
+
if (error) {
|
|
92
|
+
reject(@"AUDIO_SESSION_ERROR", error.description, error);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
[audioSession setActive:YES error:&error];
|
|
96
|
+
if (error) {
|
|
97
|
+
reject(@"AUDIO_SESSION_ERROR", error.description, error);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
|
|
102
|
+
if (error) {
|
|
103
|
+
reject(@"INIT_PLAYER_ERROR", error.description, error);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
_audioPlayer.delegate = self;
|
|
108
|
+
_audioPlayer.volume = [volume floatValue];
|
|
109
|
+
_audioPlayer.numberOfLoops = [loop boolValue] ? -1 : 0;
|
|
110
|
+
|
|
111
|
+
if (![_audioPlayer prepareToPlay]) {
|
|
112
|
+
reject(@"PREPARE_ERROR", @"Failed to prepare audio player", nil);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (![_audioPlayer play]) {
|
|
117
|
+
reject(@"START_PLAYING_ERROR", @"Failed to start playing", nil);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
_isPlaying = YES;
|
|
122
|
+
_currentFilePath = filePath;
|
|
123
|
+
[self startProgressTimer];
|
|
124
|
+
resolve(nil);
|
|
125
|
+
} @catch (NSException *exception) {
|
|
126
|
+
reject(@"START_PLAYING_ERROR", exception.reason, nil);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
- (void)stopPlaying:(RCTPromiseResolveBlock)resolve
|
|
131
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
132
|
+
@try {
|
|
133
|
+
[self stopProgressTimer];
|
|
134
|
+
|
|
135
|
+
if (_audioPlayer) {
|
|
136
|
+
[_audioPlayer stop];
|
|
137
|
+
_audioPlayer = nil;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
_isPlaying = NO;
|
|
141
|
+
_currentFilePath = nil;
|
|
142
|
+
resolve(nil);
|
|
143
|
+
} @catch (NSException *exception) {
|
|
144
|
+
reject(@"STOP_PLAYING_ERROR", exception.reason, nil);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
- (void)pausePlaying:(RCTPromiseResolveBlock)resolve
|
|
149
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
150
|
+
@try {
|
|
151
|
+
if (!_isPlaying || !_audioPlayer) {
|
|
152
|
+
reject(@"NOT_PLAYING", @"No playback in progress", nil);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
[_audioPlayer pause];
|
|
157
|
+
_isPlaying = NO;
|
|
158
|
+
resolve(nil);
|
|
159
|
+
} @catch (NSException *exception) {
|
|
160
|
+
reject(@"PAUSE_ERROR", exception.reason, nil);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
- (void)resumePlaying:(RCTPromiseResolveBlock)resolve
|
|
165
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
166
|
+
@try {
|
|
167
|
+
if (!_audioPlayer || _isPlaying) {
|
|
168
|
+
reject(@"NOT_PAUSED", @"Playback is not paused", nil);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
[_audioPlayer play];
|
|
173
|
+
_isPlaying = YES;
|
|
174
|
+
resolve(nil);
|
|
175
|
+
} @catch (NSException *exception) {
|
|
176
|
+
reject(@"RESUME_ERROR", exception.reason, nil);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
- (void)seekToTime:(double)time
|
|
181
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
182
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
183
|
+
@try {
|
|
184
|
+
if (!_audioPlayer) {
|
|
185
|
+
reject(@"NO_PLAYER", @"No audio player initialized", nil);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
_audioPlayer.currentTime = time;
|
|
190
|
+
resolve(nil);
|
|
191
|
+
} @catch (NSException *exception) {
|
|
192
|
+
reject(@"SEEK_ERROR", exception.reason, nil);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
- (void)setVolume:(double)volume
|
|
197
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
198
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
199
|
+
@try {
|
|
200
|
+
if (!_audioPlayer) {
|
|
201
|
+
reject(@"NO_PLAYER", @"No audio player initialized", nil);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
_audioPlayer.volume = volume;
|
|
206
|
+
resolve(nil);
|
|
207
|
+
} @catch (NSException *exception) {
|
|
208
|
+
reject(@"SET_VOLUME_ERROR", exception.reason, nil);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
- (void)getPlayerStatus:(RCTPromiseResolveBlock)resolve
|
|
213
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
214
|
+
@try {
|
|
215
|
+
NSMutableDictionary *status = [NSMutableDictionary dictionary];
|
|
216
|
+
status[@"isPlaying"] = @(_isPlaying);
|
|
217
|
+
|
|
218
|
+
if (_audioPlayer) {
|
|
219
|
+
status[@"duration"] = @(_audioPlayer.duration * 1000);
|
|
220
|
+
status[@"currentTime"] = @(_audioPlayer.currentTime * 1000);
|
|
221
|
+
} else {
|
|
222
|
+
status[@"duration"] = @(0);
|
|
223
|
+
status[@"currentTime"] = @(0);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (_currentFilePath) {
|
|
227
|
+
status[@"currentFilePath"] = _currentFilePath;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
resolve(status);
|
|
231
|
+
} @catch (NSException *exception) {
|
|
232
|
+
reject(@"STATUS_ERROR", exception.reason, nil);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
#pragma mark - AVAudioPlayerDelegate
|
|
237
|
+
|
|
238
|
+
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
|
|
239
|
+
successfully:(BOOL)flag {
|
|
240
|
+
_isPlaying = NO;
|
|
241
|
+
[self stopProgressTimer];
|
|
242
|
+
|
|
243
|
+
if (_hasListeners) {
|
|
244
|
+
[self sendEventWithName:@"onPlaybackComplete" body:@{}];
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player
|
|
249
|
+
error:(NSError *)error {
|
|
250
|
+
_isPlaying = NO;
|
|
251
|
+
[self stopProgressTimer];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@end
|