Skip to content

Commit 301d397

Browse files
KnowYourLinesRomualdPercereau
authored andcommitted
remove buggy url encoding
1 parent 74d2f90 commit 301d397

File tree

1 file changed

+385
-0
lines changed

1 file changed

+385
-0
lines changed

RNSound/RNSound.m

Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
#import "RNSound.h"
2+
3+
#if __has_include("RCTUtils.h")
4+
#import "RCTUtils.h"
5+
#else
6+
#import <React/RCTUtils.h>
7+
#endif
8+
9+
@implementation RNSound {
10+
NSMutableDictionary *_playerPool;
11+
NSMutableDictionary *_callbackPool;
12+
}
13+
14+
@synthesize _key = _key;
15+
16+
- (void)audioSessionChangeObserver:(NSNotification *)notification {
17+
NSDictionary *userInfo = notification.userInfo;
18+
AVAudioSessionRouteChangeReason audioSessionRouteChangeReason =
19+
[userInfo[@"AVAudioSessionRouteChangeReasonKey"] longValue];
20+
AVAudioSessionInterruptionType audioSessionInterruptionType =
21+
[userInfo[@"AVAudioSessionInterruptionTypeKey"] longValue];
22+
AVAudioPlayer *player = [self playerForKey:self._key];
23+
if (audioSessionInterruptionType == AVAudioSessionInterruptionTypeEnded) {
24+
if (player) {
25+
[player play];
26+
[self setOnPlay:YES forPlayerKey:self._key];
27+
}
28+
}
29+
else if (audioSessionRouteChangeReason ==
30+
AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
31+
if (player) {
32+
[player pause];
33+
[self setOnPlay:NO forPlayerKey:self._key];
34+
}
35+
}
36+
else if (audioSessionInterruptionType == AVAudioSessionInterruptionTypeBegan) {
37+
if (player) {
38+
[player pause];
39+
[self setOnPlay:NO forPlayerKey:self._key];
40+
}
41+
}
42+
}
43+
44+
- (NSMutableDictionary *)playerPool {
45+
if (!_playerPool) {
46+
_playerPool = [NSMutableDictionary new];
47+
}
48+
return _playerPool;
49+
}
50+
51+
- (NSMutableDictionary *)callbackPool {
52+
if (!_callbackPool) {
53+
_callbackPool = [NSMutableDictionary new];
54+
}
55+
return _callbackPool;
56+
}
57+
58+
- (AVAudioPlayer *)playerForKey:(nonnull NSNumber *)key {
59+
return [[self playerPool] objectForKey:key];
60+
}
61+
62+
- (NSNumber *)keyForPlayer:(nonnull AVAudioPlayer *)player {
63+
return [[[self playerPool] allKeysForObject:player] firstObject];
64+
}
65+
66+
- (RCTResponseSenderBlock)callbackForKey:(nonnull NSNumber *)key {
67+
return [[self callbackPool] objectForKey:key];
68+
}
69+
70+
- (NSString *)getDirectory:(int)directory {
71+
return [NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask,
72+
YES) firstObject];
73+
}
74+
75+
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
76+
successfully:(BOOL)flag {
77+
@synchronized(self) {
78+
NSNumber *key = [self keyForPlayer:player];
79+
if (key == nil)
80+
return;
81+
82+
[self setOnPlay:NO forPlayerKey:key];
83+
RCTResponseSenderBlock callback = [self callbackForKey:key];
84+
if (callback) {
85+
callback(
86+
[NSArray arrayWithObjects:[NSNumber numberWithBool:flag], nil]);
87+
[[self callbackPool] removeObjectForKey:key];
88+
}
89+
}
90+
}
91+
92+
RCT_EXPORT_MODULE();
93+
94+
- (NSArray<NSString *> *)supportedEvents {
95+
return [NSArray arrayWithObjects:@"onPlayChange", nil];
96+
}
97+
98+
- (NSDictionary *)constantsToExport {
99+
return [NSDictionary
100+
dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], @"IsAndroid",
101+
[[NSBundle mainBundle] bundlePath],
102+
@"MainBundlePath",
103+
[self getDirectory:NSDocumentDirectory],
104+
@"NSDocumentDirectory",
105+
[self getDirectory:NSLibraryDirectory],
106+
@"NSLibraryDirectory",
107+
[self getDirectory:NSCachesDirectory],
108+
@"NSCachesDirectory", nil];
109+
}
110+
111+
RCT_EXPORT_METHOD(enable : (BOOL)enabled) {
112+
AVAudioSession *session = [AVAudioSession sharedInstance];
113+
[session setCategory:AVAudioSessionCategoryAmbient error:nil];
114+
[session setActive:enabled error:nil];
115+
}
116+
117+
RCT_EXPORT_METHOD(setActive : (BOOL)active) {
118+
AVAudioSession *session = [AVAudioSession sharedInstance];
119+
[session setActive:active error:nil];
120+
}
121+
122+
RCT_EXPORT_METHOD(setMode : (NSString *)modeName) {
123+
AVAudioSession *session = [AVAudioSession sharedInstance];
124+
NSString *mode = nil;
125+
126+
if ([modeName isEqual:@"Default"]) {
127+
mode = AVAudioSessionModeDefault;
128+
} else if ([modeName isEqual:@"VoiceChat"]) {
129+
mode = AVAudioSessionModeVoiceChat;
130+
} else if ([modeName isEqual:@"VideoChat"]) {
131+
mode = AVAudioSessionModeVideoChat;
132+
} else if ([modeName isEqual:@"GameChat"]) {
133+
mode = AVAudioSessionModeGameChat;
134+
} else if ([modeName isEqual:@"VideoRecording"]) {
135+
mode = AVAudioSessionModeVideoRecording;
136+
} else if ([modeName isEqual:@"Measurement"]) {
137+
mode = AVAudioSessionModeMeasurement;
138+
} else if ([modeName isEqual:@"MoviePlayback"]) {
139+
mode = AVAudioSessionModeMoviePlayback;
140+
} else if ([modeName isEqual:@"SpokenAudio"]) {
141+
mode = AVAudioSessionModeSpokenAudio;
142+
}
143+
144+
if (mode) {
145+
[session setMode:mode error:nil];
146+
}
147+
}
148+
149+
RCT_EXPORT_METHOD(setCategory
150+
: (NSString *)categoryName mixWithOthers
151+
: (BOOL)mixWithOthers) {
152+
AVAudioSession *session = [AVAudioSession sharedInstance];
153+
NSString *category = nil;
154+
155+
if ([categoryName isEqual:@"Ambient"]) {
156+
category = AVAudioSessionCategoryAmbient;
157+
} else if ([categoryName isEqual:@"SoloAmbient"]) {
158+
category = AVAudioSessionCategorySoloAmbient;
159+
} else if ([categoryName isEqual:@"Playback"]) {
160+
category = AVAudioSessionCategoryPlayback;
161+
} else if ([categoryName isEqual:@"Record"]) {
162+
category = AVAudioSessionCategoryRecord;
163+
} else if ([categoryName isEqual:@"PlayAndRecord"]) {
164+
category = AVAudioSessionCategoryPlayAndRecord;
165+
}
166+
#if TARGET_OS_IOS
167+
else if ([categoryName isEqual:@"AudioProcessing"]) {
168+
category = AVAudioSessionCategoryAudioProcessing;
169+
}
170+
#endif
171+
else if ([categoryName isEqual:@"MultiRoute"]) {
172+
category = AVAudioSessionCategoryMultiRoute;
173+
}
174+
175+
if (category) {
176+
if (mixWithOthers) {
177+
[session setCategory:category
178+
withOptions:AVAudioSessionCategoryOptionMixWithOthers |
179+
AVAudioSessionCategoryOptionAllowBluetooth
180+
error:nil];
181+
} else {
182+
[session setCategory:category error:nil];
183+
}
184+
}
185+
}
186+
187+
RCT_EXPORT_METHOD(enableInSilenceMode : (BOOL)enabled) {
188+
AVAudioSession *session = [AVAudioSession sharedInstance];
189+
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
190+
[session setActive:enabled error:nil];
191+
}
192+
193+
RCT_EXPORT_METHOD(prepare
194+
: (NSString *)fileName withKey
195+
: (nonnull NSNumber *)key withOptions
196+
: (NSDictionary *)options withCallback
197+
: (RCTResponseSenderBlock)callback) {
198+
NSError *error;
199+
NSURL *fileNameUrl;
200+
AVAudioPlayer *player;
201+
202+
if ([fileName hasPrefix:@"http"]) {
203+
fileNameUrl = [NSURL URLWithString:fileName];
204+
NSData *data = [NSData dataWithContentsOfURL:fileNameUrl];
205+
player = [[AVAudioPlayer alloc] initWithData:data error:&error];
206+
} else if ([fileName hasPrefix:@"ipod-library://"]) {
207+
fileNameUrl = [NSURL URLWithString:fileName];
208+
player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileNameUrl
209+
error:&error];
210+
} else {
211+
fileNameUrl = [NSURL URLWithString:fileName];
212+
player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileNameUrl
213+
error:&error];
214+
}
215+
216+
if (player) {
217+
@synchronized(self) {
218+
player.delegate = self;
219+
player.enableRate = YES;
220+
[player prepareToPlay];
221+
[[self playerPool] setObject:player forKey:key];
222+
callback([NSArray
223+
arrayWithObjects:[NSNull null],
224+
[NSDictionary
225+
dictionaryWithObjectsAndKeys:
226+
[NSNumber
227+
numberWithDouble:player.duration],
228+
@"duration",
229+
[NSNumber numberWithUnsignedInteger:
230+
player.numberOfChannels],
231+
@"numberOfChannels", nil],
232+
nil]);
233+
}
234+
} else {
235+
callback([NSArray arrayWithObjects:RCTJSErrorFromNSError(error), nil]);
236+
}
237+
}
238+
239+
RCT_EXPORT_METHOD(play
240+
: (nonnull NSNumber *)key withCallback
241+
: (RCTResponseSenderBlock)callback) {
242+
[[AVAudioSession sharedInstance] setActive:YES error:nil];
243+
[[NSNotificationCenter defaultCenter]
244+
addObserver:self
245+
selector:@selector(audioSessionChangeObserver:)
246+
name:AVAudioSessionRouteChangeNotification
247+
object:[AVAudioSession sharedInstance]];
248+
[[NSNotificationCenter defaultCenter]
249+
addObserver:self
250+
selector:@selector(audioSessionChangeObserver:)
251+
name:AVAudioSessionInterruptionNotification
252+
object:[AVAudioSession sharedInstance]];
253+
self._key = key;
254+
AVAudioPlayer *player = [self playerForKey:key];
255+
if (player) {
256+
[[self callbackPool] setObject:[callback copy] forKey:key];
257+
[player play];
258+
[self setOnPlay:YES forPlayerKey:key];
259+
}
260+
}
261+
262+
RCT_EXPORT_METHOD(pause
263+
: (nonnull NSNumber *)key withCallback
264+
: (RCTResponseSenderBlock)callback) {
265+
AVAudioPlayer *player = [self playerForKey:key];
266+
if (player) {
267+
[player pause];
268+
callback([NSArray array]);
269+
}
270+
}
271+
272+
RCT_EXPORT_METHOD(stop
273+
: (nonnull NSNumber *)key withCallback
274+
: (RCTResponseSenderBlock)callback) {
275+
AVAudioPlayer *player = [self playerForKey:key];
276+
if (player) {
277+
[player stop];
278+
player.currentTime = 0;
279+
callback([NSArray array]);
280+
}
281+
}
282+
283+
RCT_EXPORT_METHOD(release : (nonnull NSNumber *)key) {
284+
@synchronized(self) {
285+
AVAudioPlayer *player = [self playerForKey:key];
286+
if (player) {
287+
[player stop];
288+
[[self callbackPool] removeObjectForKey:key];
289+
[[self playerPool] removeObjectForKey:key];
290+
NSNotificationCenter *notificationCenter =
291+
[NSNotificationCenter defaultCenter];
292+
[notificationCenter removeObserver:self];
293+
}
294+
}
295+
}
296+
297+
RCT_EXPORT_METHOD(setVolume
298+
: (nonnull NSNumber *)key withValue
299+
: (nonnull NSNumber *)value) {
300+
AVAudioPlayer *player = [self playerForKey:key];
301+
if (player) {
302+
player.volume = [value floatValue];
303+
}
304+
}
305+
306+
RCT_EXPORT_METHOD(getSystemVolume : (RCTResponseSenderBlock)callback) {
307+
AVAudioSession *session = [AVAudioSession sharedInstance];
308+
callback(@[ @(session.outputVolume) ]);
309+
}
310+
311+
RCT_EXPORT_METHOD(setPan
312+
: (nonnull NSNumber *)key withValue
313+
: (nonnull NSNumber *)value) {
314+
AVAudioPlayer *player = [self playerForKey:key];
315+
if (player) {
316+
player.pan = [value floatValue];
317+
}
318+
}
319+
320+
RCT_EXPORT_METHOD(setNumberOfLoops
321+
: (nonnull NSNumber *)key withValue
322+
: (nonnull NSNumber *)value) {
323+
AVAudioPlayer *player = [self playerForKey:key];
324+
if (player) {
325+
player.numberOfLoops = [value intValue];
326+
}
327+
}
328+
329+
RCT_EXPORT_METHOD(setSpeed
330+
: (nonnull NSNumber *)key withValue
331+
: (nonnull NSNumber *)value) {
332+
AVAudioPlayer *player = [self playerForKey:key];
333+
if (player) {
334+
player.rate = [value floatValue];
335+
}
336+
}
337+
338+
RCT_EXPORT_METHOD(setCurrentTime
339+
: (nonnull NSNumber *)key withValue
340+
: (nonnull NSNumber *)value) {
341+
AVAudioPlayer *player = [self playerForKey:key];
342+
if (player) {
343+
player.currentTime = [value doubleValue];
344+
}
345+
}
346+
347+
RCT_EXPORT_METHOD(getCurrentTime
348+
: (nonnull NSNumber *)key withCallback
349+
: (RCTResponseSenderBlock)callback) {
350+
AVAudioPlayer *player = [self playerForKey:key];
351+
if (player) {
352+
callback([NSArray
353+
arrayWithObjects:[NSNumber numberWithDouble:player.currentTime],
354+
[NSNumber numberWithBool:player.isPlaying], nil]);
355+
} else {
356+
callback([NSArray arrayWithObjects:[NSNumber numberWithInteger:-1],
357+
[NSNumber numberWithBool:NO], nil]);
358+
}
359+
}
360+
361+
RCT_EXPORT_METHOD(setSpeakerPhone : (BOOL)on) {
362+
AVAudioSession *session = [AVAudioSession sharedInstance];
363+
if (on) {
364+
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
365+
error:nil];
366+
} else {
367+
[session overrideOutputAudioPort:AVAudioSessionPortOverrideNone
368+
error:nil];
369+
}
370+
[session setActive:true error:nil];
371+
}
372+
373+
+ (BOOL)requiresMainQueueSetup {
374+
return YES;
375+
}
376+
- (void)setOnPlay:(BOOL)isPlaying forPlayerKey:(nonnull NSNumber *)playerKey {
377+
[self
378+
sendEventWithName:@"onPlayChange"
379+
body:[NSDictionary
380+
dictionaryWithObjectsAndKeys:
381+
[NSNumber
382+
numberWithBool:isPlaying ? YES : NO],
383+
@"isPlaying", playerKey, @"playerKey", nil]];
384+
}
385+
@end

0 commit comments

Comments
 (0)