react-native-audio-api 0.5.7 → 0.6.0-rc.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/RNAudioAPI.podspec +1 -1
- package/android/CMakeLists.txt +6 -3
- package/android/build.gradle +1 -0
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +0 -20
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +0 -2
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +13 -0
- package/android/src/main/java/com/swmansion/audioapi/AudioManagerModule.kt +62 -0
- package/android/src/main/java/com/swmansion/audioapi/system/AudioFocusListener.kt +60 -0
- package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +294 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +279 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt +46 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +39 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionEventEmitter.kt +84 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +144 -0
- package/android/src/main/res/drawable/next.xml +9 -0
- package/android/src/main/res/drawable/pause.xml +9 -0
- package/android/src/main/res/drawable/play.xml +9 -0
- package/android/src/main/res/drawable/previous.xml +9 -0
- package/android/src/main/res/drawable/skip_backward_5.xml +9 -0
- package/android/src/main/res/drawable/skip_forward_5.xml +9 -0
- package/android/src/main/res/drawable/stop.xml +9 -0
- package/android/src/oldarch/NativeAudioManagerModuleSpec.java +99 -0
- package/app.plugin.js +1 -0
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -6
- package/common/cpp/audioapi/core/AudioContext.cpp +1 -12
- package/common/cpp/audioapi/core/AudioContext.h +0 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +1 -6
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +8 -4
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +1 -0
- package/common/cpp/audioapi/core/utils/AudioNodeDestructor.cpp +3 -3
- package/ios/audioapi/ios/AudioAPIModule.mm +2 -3
- package/ios/audioapi/ios/AudioManagerModule.h +18 -0
- package/ios/audioapi/ios/AudioManagerModule.mm +94 -0
- package/ios/audioapi/ios/core/AudioPlayer.h +4 -12
- package/ios/audioapi/ios/core/AudioPlayer.m +26 -108
- package/ios/audioapi/ios/core/IOSAudioPlayer.h +1 -3
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +4 -28
- package/ios/audioapi/ios/system/AudioEngine.h +23 -0
- package/ios/audioapi/ios/system/AudioEngine.mm +137 -0
- package/ios/audioapi/ios/system/AudioSessionManager.h +22 -0
- package/ios/audioapi/ios/system/AudioSessionManager.mm +183 -0
- package/ios/audioapi/ios/system/LockScreenManager.h +23 -0
- package/ios/audioapi/ios/system/LockScreenManager.mm +295 -0
- package/ios/audioapi/ios/system/NotificationManager.h +22 -0
- package/ios/audioapi/ios/system/NotificationManager.mm +173 -0
- package/lib/commonjs/api.js +197 -0
- package/lib/commonjs/api.js.map +1 -0
- package/lib/commonjs/api.web.js +219 -0
- package/lib/commonjs/api.web.js.map +1 -0
- package/lib/commonjs/core/AnalyserNode.js +71 -0
- package/lib/commonjs/core/AnalyserNode.js.map +1 -0
- package/lib/commonjs/core/AudioBuffer.js +44 -0
- package/lib/commonjs/core/AudioBuffer.js.map +1 -0
- package/lib/commonjs/core/AudioBufferSourceNode.js +68 -0
- package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -0
- package/lib/commonjs/core/AudioContext.js +29 -0
- package/lib/commonjs/core/AudioContext.js.map +1 -0
- package/lib/commonjs/core/AudioDestinationNode.js +11 -0
- package/lib/commonjs/core/AudioDestinationNode.js.map +1 -0
- package/lib/commonjs/core/AudioNode.js +30 -0
- package/lib/commonjs/core/AudioNode.js.map +1 -0
- package/lib/commonjs/core/AudioParam.js +82 -0
- package/lib/commonjs/core/AudioParam.js.map +1 -0
- package/lib/commonjs/core/AudioScheduledSourceNode.js +38 -0
- package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -0
- package/lib/commonjs/core/BaseAudioContext.js +80 -0
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -0
- package/lib/commonjs/core/BiquadFilterNode.js +33 -0
- package/lib/commonjs/core/BiquadFilterNode.js.map +1 -0
- package/lib/commonjs/core/GainNode.js +17 -0
- package/lib/commonjs/core/GainNode.js.map +1 -0
- package/lib/commonjs/core/OfflineAudioContext.js +63 -0
- package/lib/commonjs/core/OfflineAudioContext.js.map +1 -0
- package/lib/commonjs/core/OscillatorNode.js +32 -0
- package/lib/commonjs/core/OscillatorNode.js.map +1 -0
- package/lib/commonjs/core/PeriodicWave.js +15 -0
- package/lib/commonjs/core/PeriodicWave.js.map +1 -0
- package/lib/commonjs/core/StereoPannerNode.js +17 -0
- package/lib/commonjs/core/StereoPannerNode.js.map +1 -0
- package/lib/commonjs/errors/IndexSizeError.js +14 -0
- package/lib/commonjs/errors/IndexSizeError.js.map +1 -0
- package/lib/commonjs/errors/InvalidAccessError.js +14 -0
- package/lib/commonjs/errors/InvalidAccessError.js.map +1 -0
- package/lib/commonjs/errors/InvalidStateError.js +14 -0
- package/lib/commonjs/errors/InvalidStateError.js.map +1 -0
- package/lib/commonjs/errors/NotSupportedError.js +14 -0
- package/lib/commonjs/errors/NotSupportedError.js.map +1 -0
- package/lib/commonjs/errors/RangeError.js +14 -0
- package/lib/commonjs/errors/RangeError.js.map +1 -0
- package/lib/commonjs/errors/index.js +42 -0
- package/lib/commonjs/errors/index.js.map +1 -0
- package/lib/commonjs/index.js +17 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/interfaces.js +6 -0
- package/lib/commonjs/interfaces.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/plugin/withAudioAPI.js +62 -0
- package/lib/commonjs/plugin/withAudioAPI.js.map +1 -0
- package/lib/commonjs/specs/NativeAudioAPIModule.js +9 -0
- package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -0
- package/lib/commonjs/specs/NativeAudioManagerModule.js +33 -0
- package/lib/commonjs/specs/NativeAudioManagerModule.js.map +1 -0
- package/lib/commonjs/specs/index.js +27 -0
- package/lib/commonjs/specs/index.js.map +1 -0
- package/lib/commonjs/system/AudioManager.js +79 -0
- package/lib/commonjs/system/AudioManager.js.map +1 -0
- package/lib/commonjs/system/index.js +14 -0
- package/lib/commonjs/system/index.js.map +1 -0
- package/lib/commonjs/system/types.js +2 -0
- package/lib/commonjs/system/types.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils/index.js +10 -0
- package/lib/commonjs/utils/index.js.map +1 -0
- package/lib/commonjs/web-core/AnalyserNode.js +38 -0
- package/lib/commonjs/web-core/AnalyserNode.js.map +1 -0
- package/lib/commonjs/web-core/AudioBuffer.js +44 -0
- package/lib/commonjs/web-core/AudioBuffer.js.map +1 -0
- package/lib/commonjs/web-core/AudioBufferSourceNode.js +214 -0
- package/lib/commonjs/web-core/AudioBufferSourceNode.js.map +1 -0
- package/lib/commonjs/web-core/AudioContext.js +93 -0
- package/lib/commonjs/web-core/AudioContext.js.map +1 -0
- package/lib/commonjs/web-core/AudioDestinationNode.js +11 -0
- package/lib/commonjs/web-core/AudioDestinationNode.js.map +1 -0
- package/lib/commonjs/web-core/AudioNode.js +33 -0
- package/lib/commonjs/web-core/AudioNode.js.map +1 -0
- package/lib/commonjs/web-core/AudioParam.js +81 -0
- package/lib/commonjs/web-core/AudioParam.js.map +1 -0
- package/lib/commonjs/web-core/AudioScheduledSourceNode.js +41 -0
- package/lib/commonjs/web-core/AudioScheduledSourceNode.js.map +1 -0
- package/lib/commonjs/web-core/BaseAudioContext.js +2 -0
- package/lib/commonjs/web-core/BaseAudioContext.js.map +1 -0
- package/lib/commonjs/web-core/BiquadFilterNode.js +33 -0
- package/lib/commonjs/web-core/BiquadFilterNode.js.map +1 -0
- package/lib/commonjs/web-core/GainNode.js +17 -0
- package/lib/commonjs/web-core/GainNode.js.map +1 -0
- package/lib/commonjs/web-core/OfflineAudioContext.js +96 -0
- package/lib/commonjs/web-core/OfflineAudioContext.js.map +1 -0
- package/lib/commonjs/web-core/OscillatorNode.js +31 -0
- package/lib/commonjs/web-core/OscillatorNode.js.map +1 -0
- package/lib/commonjs/web-core/PeriodicWave.js +15 -0
- package/lib/commonjs/web-core/PeriodicWave.js.map +1 -0
- package/lib/commonjs/web-core/StereoPannerNode.js +17 -0
- package/lib/commonjs/web-core/StereoPannerNode.js.map +1 -0
- package/lib/commonjs/web-core/custom/LoadCustomWasm.js +37 -0
- package/lib/commonjs/web-core/custom/LoadCustomWasm.js.map +1 -0
- package/lib/commonjs/web-core/custom/index.js +14 -0
- package/lib/commonjs/web-core/custom/index.js.map +1 -0
- package/lib/commonjs/web-core/custom/signalsmithStretch/LICENSE.txt +21 -0
- package/lib/commonjs/web-core/custom/signalsmithStretch/README.md +46 -0
- package/lib/commonjs/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs +826 -0
- package/lib/commonjs/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs.map +1 -0
- package/lib/module/api.js +1 -0
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioContext.js +2 -1
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/plugin/withAudioAPI.js +58 -0
- package/lib/module/plugin/withAudioAPI.js.map +1 -0
- package/lib/module/specs/NativeAudioManagerModule.js +30 -0
- package/lib/module/specs/NativeAudioManagerModule.js.map +1 -0
- package/lib/module/specs/index.js +6 -0
- package/lib/module/specs/index.js.map +1 -0
- package/lib/module/system/AudioManager.js +75 -0
- package/lib/module/system/AudioManager.js.map +1 -0
- package/lib/module/system/index.js +4 -0
- package/lib/module/system/index.js.map +1 -0
- package/lib/module/system/types.js +2 -0
- package/lib/module/system/types.js.map +1 -0
- package/lib/typescript/api.d.ts +1 -0
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/plugin/withAudioAPI.d.ts +9 -0
- package/lib/typescript/plugin/withAudioAPI.d.ts.map +1 -0
- package/lib/typescript/specs/NativeAudioManagerModule.d.ts +14 -0
- package/lib/typescript/specs/NativeAudioManagerModule.d.ts.map +1 -0
- package/lib/typescript/specs/index.d.ts +4 -0
- package/lib/typescript/specs/index.d.ts.map +1 -0
- package/lib/typescript/system/AudioManager.d.ts +14 -0
- package/lib/typescript/system/AudioManager.d.ts.map +1 -0
- package/lib/typescript/system/index.d.ts +2 -0
- package/lib/typescript/system/index.d.ts.map +1 -0
- package/lib/typescript/system/types.d.ts +40 -0
- package/lib/typescript/system/types.d.ts.map +1 -0
- package/package.json +7 -4
- package/src/api.ts +1 -0
- package/src/core/AudioContext.ts +6 -1
- package/src/plugin/withAudioAPI.ts +90 -0
- package/src/specs/NativeAudioManagerModule.ts +48 -0
- package/src/specs/index.ts +6 -0
- package/src/system/AudioManager.ts +149 -0
- package/src/system/index.ts +1 -0
- package/src/system/types.ts +84 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#import <audioapi/ios/system/AudioEngine.h>
|
|
2
|
+
|
|
3
|
+
@implementation AudioEngine
|
|
4
|
+
|
|
5
|
+
static AudioEngine *_sharedInstance = nil;
|
|
6
|
+
|
|
7
|
+
+ (instancetype)sharedInstance
|
|
8
|
+
{
|
|
9
|
+
static dispatch_once_t onceToken;
|
|
10
|
+
dispatch_once(&onceToken, ^{
|
|
11
|
+
_sharedInstance = [[self alloc] initPrivate];
|
|
12
|
+
});
|
|
13
|
+
return _sharedInstance;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
- (instancetype)init
|
|
17
|
+
{
|
|
18
|
+
@throw [NSException exceptionWithName:@"Singleton" reason:@"Use +[AudioEngine sharedInstance]" userInfo:nil];
|
|
19
|
+
return nil;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
- (instancetype)initPrivate
|
|
23
|
+
{
|
|
24
|
+
if (self = [super init]) {
|
|
25
|
+
self.audioEngine = [[AVAudioEngine alloc] init];
|
|
26
|
+
self.audioEngine.mainMixerNode.outputVolume = 1;
|
|
27
|
+
self.sourceNodes = [[NSMutableDictionary alloc] init];
|
|
28
|
+
self.sourceFormats = [[NSMutableDictionary alloc] init];
|
|
29
|
+
}
|
|
30
|
+
return self;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
- (void)cleanup
|
|
34
|
+
{
|
|
35
|
+
NSLog(@"[AudioEngine] cleanup");
|
|
36
|
+
if ([self.audioEngine isRunning]) {
|
|
37
|
+
[self.audioEngine stop];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
self.audioEngine = nil;
|
|
41
|
+
self.sourceNodes = nil;
|
|
42
|
+
self.sourceFormats = nil;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
- (bool)rebuildAudioEngine
|
|
46
|
+
{
|
|
47
|
+
NSError *error = nil;
|
|
48
|
+
|
|
49
|
+
if ([self.audioEngine isRunning]) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (id sourceNodeId in self.sourceNodes) {
|
|
54
|
+
AVAudioSourceNode *sourceNode = [self.sourceNodes valueForKey:sourceNodeId];
|
|
55
|
+
AVAudioFormat *format = [self.sourceFormats valueForKey:sourceNodeId];
|
|
56
|
+
|
|
57
|
+
[self.audioEngine attachNode:sourceNode];
|
|
58
|
+
[self.audioEngine connect:sourceNode to:self.audioEngine.mainMixerNode format:format];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if ([self.audioEngine isRunning]) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (![self.audioEngine startAndReturnError:&error]) {
|
|
66
|
+
NSLog(@"Error while rebuilding audio engine: %@", [error debugDescription]);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
- (void)startEngine
|
|
74
|
+
{
|
|
75
|
+
NSLog(@"[AudioEngine] startEngine");
|
|
76
|
+
NSError *error = nil;
|
|
77
|
+
|
|
78
|
+
if ([self.audioEngine isRunning]) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
[self.audioEngine startAndReturnError:&error];
|
|
83
|
+
|
|
84
|
+
if (error != nil) {
|
|
85
|
+
NSLog(@"Error while starting the audio engine: %@", [error debugDescription]);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
- (void)stopEngine
|
|
90
|
+
{
|
|
91
|
+
NSLog(@"[AudioEngine] stopEngine");
|
|
92
|
+
if (![self.audioEngine isRunning]) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
[self.audioEngine pause];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
- (bool)isRunning
|
|
100
|
+
{
|
|
101
|
+
return [self.audioEngine isRunning];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
- (NSString *)attachSourceNode:(AVAudioSourceNode *)sourceNode format:(AVAudioFormat *)format
|
|
105
|
+
{
|
|
106
|
+
NSString *sourceNodeId = [[NSUUID UUID] UUIDString];
|
|
107
|
+
NSLog(@"[AudioEngine] attaching new source node with ID: %@", sourceNodeId);
|
|
108
|
+
|
|
109
|
+
[self.sourceNodes setValue:sourceNode forKey:sourceNodeId];
|
|
110
|
+
[self.sourceFormats setValue:format forKey:sourceNodeId];
|
|
111
|
+
|
|
112
|
+
[self.audioEngine attachNode:sourceNode];
|
|
113
|
+
[self.audioEngine connect:sourceNode to:self.audioEngine.mainMixerNode format:format];
|
|
114
|
+
|
|
115
|
+
if ([self.sourceNodes count] == 1) {
|
|
116
|
+
[self startEngine];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return sourceNodeId;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
- (void)detachSourceNodeWithId:(NSString *)sourceNodeId
|
|
123
|
+
{
|
|
124
|
+
NSLog(@"[AudioEngine] detaching source nde with ID: %@", sourceNodeId);
|
|
125
|
+
|
|
126
|
+
AVAudioSourceNode *sourceNode = [self.sourceNodes valueForKey:sourceNodeId];
|
|
127
|
+
[self.audioEngine detachNode:sourceNode];
|
|
128
|
+
|
|
129
|
+
[self.sourceNodes removeObjectForKey:sourceNodeId];
|
|
130
|
+
[self.sourceFormats removeObjectForKey:sourceNodeId];
|
|
131
|
+
|
|
132
|
+
if ([self.sourceNodes count] == 0) {
|
|
133
|
+
[self stopEngine];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <AVFoundation/AVFoundation.h>
|
|
4
|
+
#import <Foundation/Foundation.h>
|
|
5
|
+
|
|
6
|
+
@interface AudioSessionManager : NSObject
|
|
7
|
+
|
|
8
|
+
@property (nonatomic, weak) AVAudioSession *audioSession;
|
|
9
|
+
|
|
10
|
+
@property (nonatomic, assign) AVAudioSessionMode sessionMode;
|
|
11
|
+
@property (nonatomic, assign) AVAudioSessionCategory sessionCategory;
|
|
12
|
+
@property (nonatomic, assign) AVAudioSessionCategoryOptions sessionOptions;
|
|
13
|
+
|
|
14
|
+
+ (instancetype)sharedInstance;
|
|
15
|
+
- (void)cleanup;
|
|
16
|
+
- (bool)configureAudioSession;
|
|
17
|
+
|
|
18
|
+
- (NSNumber *)getDevicePreferredSampleRate;
|
|
19
|
+
- (void)setAudioSessionOptions:(NSString *)category mode:(NSString *)mode options:(NSArray *)options;
|
|
20
|
+
- (bool)setActive:(bool)active error:(NSError **)error;
|
|
21
|
+
|
|
22
|
+
@end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#import <audioapi/ios/system/AudioSessionManager.h>
|
|
2
|
+
|
|
3
|
+
@implementation AudioSessionManager
|
|
4
|
+
|
|
5
|
+
static AudioSessionManager *_sharedInstance = nil;
|
|
6
|
+
|
|
7
|
+
+ (instancetype)sharedInstance
|
|
8
|
+
{
|
|
9
|
+
static dispatch_once_t onceToken;
|
|
10
|
+
dispatch_once(&onceToken, ^{
|
|
11
|
+
_sharedInstance = [[self alloc] initPrivate];
|
|
12
|
+
});
|
|
13
|
+
return _sharedInstance;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
- (instancetype)init
|
|
17
|
+
{
|
|
18
|
+
@throw [NSException exceptionWithName:@"Singleton" reason:@"Use +[AudioSessionManager sharedInstance]" userInfo:nil];
|
|
19
|
+
return nil;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
- (instancetype)initPrivate
|
|
23
|
+
{
|
|
24
|
+
if (self = [super init]) {
|
|
25
|
+
self.audioSession = [AVAudioSession sharedInstance];
|
|
26
|
+
|
|
27
|
+
self.sessionCategory = AVAudioSessionCategoryPlayback;
|
|
28
|
+
self.sessionMode = AVAudioSessionModeDefault;
|
|
29
|
+
self.sessionOptions = AVAudioSessionCategoryOptionDuckOthers | AVAudioSessionCategoryOptionAllowBluetooth;
|
|
30
|
+
|
|
31
|
+
[self configureAudioSession];
|
|
32
|
+
}
|
|
33
|
+
return self;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
- (void)cleanup
|
|
37
|
+
{
|
|
38
|
+
NSLog(@"[AudioSessionManager] cleanup");
|
|
39
|
+
|
|
40
|
+
self.audioSession = nil;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
- (NSNumber *)getDevicePreferredSampleRate
|
|
44
|
+
{
|
|
45
|
+
return [NSNumber numberWithFloat:[self.audioSession sampleRate]];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
- (void)setAudioSessionOptions:(NSString *)category mode:(NSString *)mode options:(NSArray *)options
|
|
49
|
+
{
|
|
50
|
+
AVAudioSessionCategory sessionCategory = self.sessionCategory;
|
|
51
|
+
AVAudioSessionMode sessionMode = self.sessionMode;
|
|
52
|
+
AVAudioSessionCategoryOptions sessionOptions = 0;
|
|
53
|
+
|
|
54
|
+
if ([category isEqualToString:@"record"]) {
|
|
55
|
+
sessionCategory = AVAudioSessionCategoryRecord;
|
|
56
|
+
} else if ([category isEqualToString:@"ambient"]) {
|
|
57
|
+
sessionCategory = AVAudioSessionCategoryAmbient;
|
|
58
|
+
} else if ([category isEqualToString:@"playback"]) {
|
|
59
|
+
sessionCategory = AVAudioSessionCategoryPlayback;
|
|
60
|
+
} else if ([category isEqualToString:@"multiRoute"]) {
|
|
61
|
+
sessionCategory = AVAudioSessionCategoryMultiRoute;
|
|
62
|
+
} else if ([category isEqualToString:@"soloAmbient"]) {
|
|
63
|
+
sessionCategory = AVAudioSessionCategorySoloAmbient;
|
|
64
|
+
} else if ([category isEqualToString:@"playAndRecord"]) {
|
|
65
|
+
sessionCategory = AVAudioSessionCategoryPlayAndRecord;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if ([mode isEqualToString:@"default"]) {
|
|
69
|
+
sessionMode = AVAudioSessionModeDefault;
|
|
70
|
+
} else if ([mode isEqualToString:@"gameChat"]) {
|
|
71
|
+
sessionMode = AVAudioSessionModeGameChat;
|
|
72
|
+
} else if ([mode isEqualToString:@"videoChat"]) {
|
|
73
|
+
sessionMode = AVAudioSessionModeVideoChat;
|
|
74
|
+
} else if ([mode isEqualToString:@"voiceChat"]) {
|
|
75
|
+
sessionMode = AVAudioSessionModeVoiceChat;
|
|
76
|
+
} else if ([mode isEqualToString:@"measurement"]) {
|
|
77
|
+
sessionMode = AVAudioSessionModeMeasurement;
|
|
78
|
+
} else if ([mode isEqualToString:@"voicePrompt"]) {
|
|
79
|
+
sessionMode = AVAudioSessionModeVoicePrompt;
|
|
80
|
+
} else if ([mode isEqualToString:@"spokenAudio"]) {
|
|
81
|
+
sessionMode = AVAudioSessionModeSpokenAudio;
|
|
82
|
+
} else if ([mode isEqualToString:@"moviePlayback"]) {
|
|
83
|
+
sessionMode = AVAudioSessionModeMoviePlayback;
|
|
84
|
+
} else if ([mode isEqualToString:@"videoRecording"]) {
|
|
85
|
+
sessionMode = AVAudioSessionModeVideoRecording;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
for (NSString *option in options) {
|
|
89
|
+
if ([option isEqualToString:@"duckOthers"]) {
|
|
90
|
+
sessionOptions |= AVAudioSessionCategoryOptionDuckOthers;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if ([option isEqualToString:@"allowAirPlay"]) {
|
|
94
|
+
sessionOptions |= AVAudioSessionCategoryOptionAllowAirPlay;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if ([option isEqualToString:@"mixWithOthers"]) {
|
|
98
|
+
sessionOptions |= AVAudioSessionCategoryOptionMixWithOthers;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if ([option isEqualToString:@"allowBluetooth"]) {
|
|
102
|
+
sessionOptions |= AVAudioSessionCategoryOptionAllowBluetooth;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if ([option isEqualToString:@"defaultToSpeaker"]) {
|
|
106
|
+
sessionOptions |= AVAudioSessionCategoryOptionDefaultToSpeaker;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if ([option isEqualToString:@"allowBluetoothA2DP"]) {
|
|
110
|
+
sessionOptions |= AVAudioSessionCategoryOptionAllowBluetoothA2DP;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if ([option isEqualToString:@"overrideMutedMicrophoneInterruption"]) {
|
|
114
|
+
sessionOptions |= AVAudioSessionCategoryOptionOverrideMutedMicrophoneInterruption;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if ([option isEqualToString:@"interruptSpokenAudioAndMixWithOthers"]) {
|
|
118
|
+
sessionOptions |= AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
bool hasDirtySettings = false;
|
|
123
|
+
|
|
124
|
+
if (self.sessionCategory != sessionCategory) {
|
|
125
|
+
hasDirtySettings = true;
|
|
126
|
+
self.sessionCategory = sessionCategory;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (self.sessionMode != sessionMode) {
|
|
130
|
+
hasDirtySettings = true;
|
|
131
|
+
self.sessionMode = sessionMode;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (self.sessionOptions != sessionOptions) {
|
|
135
|
+
hasDirtySettings = true;
|
|
136
|
+
self.sessionOptions = sessionOptions;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (hasDirtySettings) {
|
|
140
|
+
[self configureAudioSession];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
- (bool)setActive:(bool)active error:(NSError **)error
|
|
145
|
+
{
|
|
146
|
+
return [self.audioSession setActive:active error:error];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
- (bool)configureAudioSession
|
|
150
|
+
{
|
|
151
|
+
NSLog(
|
|
152
|
+
@"[AudioSessionManager] configureAudioSession, category: %@, mode: %@, options: %lu",
|
|
153
|
+
self.sessionCategory,
|
|
154
|
+
self.sessionMode,
|
|
155
|
+
(unsigned long)self.sessionOptions);
|
|
156
|
+
|
|
157
|
+
NSError *error = nil;
|
|
158
|
+
|
|
159
|
+
[self.audioSession setPreferredIOBufferDuration:0.022 error:&error];
|
|
160
|
+
|
|
161
|
+
if (error != nil) {
|
|
162
|
+
NSLog(@"Error while setting preffered IO buffer duration: %@", [error debugDescription]);
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
[self.audioSession setCategory:self.sessionCategory mode:self.sessionMode options:self.sessionOptions error:&error];
|
|
167
|
+
|
|
168
|
+
if (error != nil) {
|
|
169
|
+
NSLog(@"Error while configuring audio session: %@", [error debugDescription]);
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
[self setActive:true error:&error];
|
|
174
|
+
|
|
175
|
+
if (error != nil) {
|
|
176
|
+
NSLog(@"Error while activating audio session: %@", [error debugDescription]);
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <AVFoundation/AVFoundation.h>
|
|
4
|
+
#import <Foundation/Foundation.h>
|
|
5
|
+
#import <MediaPlayer/MediaPlayer.h>
|
|
6
|
+
|
|
7
|
+
@class AudioManagerModule;
|
|
8
|
+
|
|
9
|
+
@interface LockScreenManager : NSObject
|
|
10
|
+
|
|
11
|
+
@property (nonatomic, weak) AudioManagerModule *audioManagerModule;
|
|
12
|
+
|
|
13
|
+
@property (nonatomic, weak) MPNowPlayingInfoCenter *playingInfoCenter;
|
|
14
|
+
@property (nonatomic, copy) NSString *artworkUrl;
|
|
15
|
+
|
|
16
|
+
+ (instancetype)sharedInstanceWithAudioManagerModule:(AudioManagerModule *)audioManagerModule;
|
|
17
|
+
- (void)cleanup;
|
|
18
|
+
|
|
19
|
+
- (void)setLockScreenInfo:(NSDictionary *)info;
|
|
20
|
+
- (void)resetLockScreenInfo;
|
|
21
|
+
- (void)enableRemoteCommand:(NSString *)name enabled:(BOOL)enabled;
|
|
22
|
+
|
|
23
|
+
@end
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#import <MediaPlayer/MediaPlayer.h>
|
|
2
|
+
#import <audioapi/ios/AudioManagerModule.h>
|
|
3
|
+
#import <audioapi/ios/system/LockScreenManager.h>
|
|
4
|
+
|
|
5
|
+
#define LOCK_SCREEN_INFO \
|
|
6
|
+
@{ \
|
|
7
|
+
@"album" : MPMediaItemPropertyAlbumTitle, \
|
|
8
|
+
@"artist" : MPMediaItemPropertyArtist, \
|
|
9
|
+
@"duration" : MPMediaItemPropertyPlaybackDuration, \
|
|
10
|
+
@"title" : MPMediaItemPropertyTitle, \
|
|
11
|
+
@"speed" : MPNowPlayingInfoPropertyPlaybackRate, \
|
|
12
|
+
@"elapsedTime" : MPNowPlayingInfoPropertyElapsedPlaybackTime, \
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@implementation LockScreenManager
|
|
16
|
+
|
|
17
|
+
static LockScreenManager *_sharedInstance = nil;
|
|
18
|
+
|
|
19
|
+
+ (instancetype)sharedInstanceWithAudioManagerModule:(AudioManagerModule *)audioManagerModule
|
|
20
|
+
{
|
|
21
|
+
static dispatch_once_t onceToken;
|
|
22
|
+
dispatch_once(&onceToken, ^{
|
|
23
|
+
_sharedInstance = [[self alloc] initPrivateWithAudioManagerModule:audioManagerModule];
|
|
24
|
+
});
|
|
25
|
+
return _sharedInstance;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
- (instancetype)init
|
|
29
|
+
{
|
|
30
|
+
@throw [NSException exceptionWithName:@"Singleton" reason:@"Use +[LockScreenManager sharedInstance]" userInfo:nil];
|
|
31
|
+
return nil;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
- (instancetype)initPrivateWithAudioManagerModule:(AudioManagerModule *)audioManagerModule
|
|
35
|
+
{
|
|
36
|
+
if (self = [super init]) {
|
|
37
|
+
self.audioManagerModule = audioManagerModule;
|
|
38
|
+
self.playingInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
|
|
39
|
+
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
|
|
40
|
+
}
|
|
41
|
+
return self;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
- (void)cleanup
|
|
45
|
+
{
|
|
46
|
+
NSLog(@"[LockScreenManager] cleanup");
|
|
47
|
+
[self resetLockScreenInfo];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
- (void)setLockScreenInfo:(NSDictionary *)info
|
|
51
|
+
{
|
|
52
|
+
// now playing info(lock screen info)
|
|
53
|
+
NSMutableDictionary *lockScreenInfoDict;
|
|
54
|
+
|
|
55
|
+
if (self.playingInfoCenter.nowPlayingInfo == nil) {
|
|
56
|
+
lockScreenInfoDict = [NSMutableDictionary dictionary];
|
|
57
|
+
} else {
|
|
58
|
+
lockScreenInfoDict = [[NSMutableDictionary alloc] initWithDictionary:self.playingInfoCenter.nowPlayingInfo];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
for (NSString *key in LOCK_SCREEN_INFO) {
|
|
62
|
+
if ([info objectForKey:key] != nil) {
|
|
63
|
+
[lockScreenInfoDict setValue:[info objectForKey:key] forKey:[LOCK_SCREEN_INFO objectForKey:key]];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
self.playingInfoCenter.nowPlayingInfo = lockScreenInfoDict;
|
|
68
|
+
|
|
69
|
+
// playback state
|
|
70
|
+
NSString *state = [info objectForKey:@"state"];
|
|
71
|
+
|
|
72
|
+
if (state != nil) {
|
|
73
|
+
if ([state isEqualToString:@"state_playing"]) {
|
|
74
|
+
self.playingInfoCenter.playbackState = MPNowPlayingPlaybackStatePlaying;
|
|
75
|
+
} else if ([state isEqualToString:@"state_paused"]) {
|
|
76
|
+
self.playingInfoCenter.playbackState = MPNowPlayingPlaybackStatePaused;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// artwork
|
|
81
|
+
NSString *artworkUrl = [self getArtworkUrl:[info objectForKey:@"artwork"]];
|
|
82
|
+
[self updateArtworkIfNeeded:artworkUrl];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
- (void)resetLockScreenInfo
|
|
86
|
+
{
|
|
87
|
+
self.playingInfoCenter.nowPlayingInfo = nil;
|
|
88
|
+
self.artworkUrl = nil;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
- (NSString *)getArtworkUrl:(NSString *)artwork
|
|
92
|
+
{
|
|
93
|
+
NSString *artworkUrl = nil;
|
|
94
|
+
|
|
95
|
+
if (artwork) {
|
|
96
|
+
if ([artwork isKindOfClass:[NSString class]]) {
|
|
97
|
+
artworkUrl = artwork;
|
|
98
|
+
} else if ([[artwork valueForKey:@"uri"] isKindOfClass:[NSString class]]) {
|
|
99
|
+
artworkUrl = [artwork valueForKey:@"uri"];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return artworkUrl;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)updateArtworkIfNeeded:(id)artworkUrl
|
|
107
|
+
{
|
|
108
|
+
if (artworkUrl == nil) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
MPNowPlayingInfoCenter *center = [MPNowPlayingInfoCenter defaultCenter];
|
|
113
|
+
if ([artworkUrl isEqualToString:self.artworkUrl] &&
|
|
114
|
+
[center.nowPlayingInfo objectForKey:MPMediaItemPropertyArtwork] != nil) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
self.artworkUrl = artworkUrl;
|
|
119
|
+
|
|
120
|
+
// Custom handling of artwork in another thread, will be loaded async
|
|
121
|
+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
|
122
|
+
UIImage *image = nil;
|
|
123
|
+
|
|
124
|
+
// check whether artwork path is present
|
|
125
|
+
if ([artworkUrl isEqual:@""]) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// artwork is url download from the interwebs
|
|
130
|
+
if ([artworkUrl hasPrefix:@"http://"] || [artworkUrl hasPrefix:@"https://"]) {
|
|
131
|
+
NSURL *imageURL = [NSURL URLWithString:artworkUrl];
|
|
132
|
+
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
|
|
133
|
+
image = [UIImage imageWithData:imageData];
|
|
134
|
+
} else {
|
|
135
|
+
NSString *localArtworkUrl = [artworkUrl stringByReplacingOccurrencesOfString:@"file://" withString:@""];
|
|
136
|
+
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:localArtworkUrl];
|
|
137
|
+
if (fileExists) {
|
|
138
|
+
image = [UIImage imageNamed:localArtworkUrl];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Check if image was available otherwise don't do anything
|
|
143
|
+
if (image == nil) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// check whether image is loaded
|
|
148
|
+
CGImageRef cgref = [image CGImage];
|
|
149
|
+
CIImage *cim = [image CIImage];
|
|
150
|
+
|
|
151
|
+
if (cim == nil && cgref == NULL) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
156
|
+
// Check if URL wasn't changed in the meantime
|
|
157
|
+
if (![artworkUrl isEqual:self.artworkUrl]) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
MPNowPlayingInfoCenter *center = [MPNowPlayingInfoCenter defaultCenter];
|
|
162
|
+
MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithBoundsSize:image.size
|
|
163
|
+
requestHandler:^UIImage *_Nonnull(CGSize size) {
|
|
164
|
+
return image;
|
|
165
|
+
}];
|
|
166
|
+
NSMutableDictionary *mediaDict = (center.nowPlayingInfo != nil)
|
|
167
|
+
? [[NSMutableDictionary alloc] initWithDictionary:center.nowPlayingInfo]
|
|
168
|
+
: [NSMutableDictionary dictionary];
|
|
169
|
+
[mediaDict setValue:artwork forKey:MPMediaItemPropertyArtwork];
|
|
170
|
+
center.nowPlayingInfo = mediaDict;
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
- (void)enableRemoteCommand:(NSString *)name enabled:(BOOL)enabled
|
|
176
|
+
{
|
|
177
|
+
MPRemoteCommandCenter *remoteCenter = [MPRemoteCommandCenter sharedCommandCenter];
|
|
178
|
+
|
|
179
|
+
if ([name isEqual:@"play"]) {
|
|
180
|
+
[self enableCommand:remoteCenter.playCommand withSelector:@selector(onPlay:) enabled:enabled];
|
|
181
|
+
} else if ([name isEqual:@"pause"]) {
|
|
182
|
+
[self enableCommand:remoteCenter.pauseCommand withSelector:@selector(onPause:) enabled:enabled];
|
|
183
|
+
} else if ([name isEqual:@"stop"]) {
|
|
184
|
+
[self enableCommand:remoteCenter.stopCommand withSelector:@selector(onStop:) enabled:enabled];
|
|
185
|
+
} else if ([name isEqual:@"togglePlayPause"]) {
|
|
186
|
+
[self enableCommand:remoteCenter.togglePlayPauseCommand withSelector:@selector(onTogglePlayPause:) enabled:enabled];
|
|
187
|
+
} else if ([name isEqual:@"changePlaybackRate"]) {
|
|
188
|
+
[self enableCommand:remoteCenter.changePlaybackRateCommand
|
|
189
|
+
withSelector:@selector(onChangePlaybackRate:)
|
|
190
|
+
enabled:enabled];
|
|
191
|
+
} else if ([name isEqual:@"nextTrack"]) {
|
|
192
|
+
[self enableCommand:remoteCenter.nextTrackCommand withSelector:@selector(onNextTrack:) enabled:enabled];
|
|
193
|
+
} else if ([name isEqual:@"previousTrack"]) {
|
|
194
|
+
[self enableCommand:remoteCenter.previousTrackCommand withSelector:@selector(onPreviousTrack:) enabled:enabled];
|
|
195
|
+
} else if ([name isEqual:@"skipForward"]) {
|
|
196
|
+
[self enableCommand:remoteCenter.skipForwardCommand withSelector:@selector(onSkipForward:) enabled:enabled];
|
|
197
|
+
} else if ([name isEqual:@"skipBackward"]) {
|
|
198
|
+
[self enableCommand:remoteCenter.skipBackwardCommand withSelector:@selector(onSkipBackward:) enabled:enabled];
|
|
199
|
+
} else if ([name isEqual:@"seekForward"]) {
|
|
200
|
+
[self enableCommand:remoteCenter.seekForwardCommand withSelector:@selector(onSeekForward:) enabled:enabled];
|
|
201
|
+
} else if ([name isEqual:@"seekBackward"]) {
|
|
202
|
+
[self enableCommand:remoteCenter.seekBackwardCommand withSelector:@selector(onSeekBackward:) enabled:enabled];
|
|
203
|
+
} else if ([name isEqual:@"changePlaybackPosition"]) {
|
|
204
|
+
[self enableCommand:remoteCenter.changePlaybackPositionCommand
|
|
205
|
+
withSelector:@selector(onChangePlaybackPosition:)
|
|
206
|
+
enabled:enabled];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
- (void)enableCommand:(MPRemoteCommand *)command withSelector:(SEL)selector enabled:(BOOL)enabled
|
|
211
|
+
{
|
|
212
|
+
[command removeTarget:self action:selector];
|
|
213
|
+
if (enabled) {
|
|
214
|
+
[command addTarget:self action:selector];
|
|
215
|
+
}
|
|
216
|
+
command.enabled = enabled;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
- (MPRemoteCommandHandlerStatus)onPlay:(MPRemoteCommandEvent *)event
|
|
220
|
+
{
|
|
221
|
+
[self.audioManagerModule sendEventWithName:@"onRemotePlay" body:@{}];
|
|
222
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
- (MPRemoteCommandHandlerStatus)onPause:(MPRemoteCommandEvent *)event
|
|
226
|
+
{
|
|
227
|
+
[self.audioManagerModule sendEventWithName:@"onRemotePause" body:@{}];
|
|
228
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
- (MPRemoteCommandHandlerStatus)onStop:(MPRemoteCommandEvent *)event
|
|
232
|
+
{
|
|
233
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteStop" body:@{}];
|
|
234
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
- (MPRemoteCommandHandlerStatus)onTogglePlayPause:(MPRemoteCommandEvent *)event
|
|
238
|
+
{
|
|
239
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteTogglePlayPause" body:@{}];
|
|
240
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
- (MPRemoteCommandHandlerStatus)onChangePlaybackRate:(MPChangePlaybackRateCommandEvent *)event
|
|
244
|
+
{
|
|
245
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteChangePlaybackRate"
|
|
246
|
+
body:@{@"value" : [NSNumber numberWithDouble:event.playbackRate]}];
|
|
247
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
- (MPRemoteCommandHandlerStatus)onNextTrack:(MPRemoteCommandEvent *)event
|
|
251
|
+
{
|
|
252
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteNextTrack" body:@{}];
|
|
253
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
- (MPRemoteCommandHandlerStatus)onPreviousTrack:(MPRemoteCommandEvent *)event
|
|
257
|
+
{
|
|
258
|
+
[self.audioManagerModule sendEventWithName:@"onRemotePreviousTrack" body:@{}];
|
|
259
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
- (MPRemoteCommandHandlerStatus)onSeekForward:(MPRemoteCommandEvent *)event
|
|
263
|
+
{
|
|
264
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteSeekForward" body:nil];
|
|
265
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
- (MPRemoteCommandHandlerStatus)onSeekBackward:(MPRemoteCommandEvent *)event
|
|
269
|
+
{
|
|
270
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteSeekBackward" body:@{}];
|
|
271
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
- (MPRemoteCommandHandlerStatus)onSkipForward:(MPSkipIntervalCommandEvent *)event
|
|
275
|
+
{
|
|
276
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteSkipForward"
|
|
277
|
+
body:@{@"value" : [NSNumber numberWithDouble:event.interval]}];
|
|
278
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
- (MPRemoteCommandHandlerStatus)onSkipBackward:(MPSkipIntervalCommandEvent *)event
|
|
282
|
+
{
|
|
283
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteSkipBackward"
|
|
284
|
+
body:@{@"value" : [NSNumber numberWithDouble:event.interval]}];
|
|
285
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
- (MPRemoteCommandHandlerStatus)onChangePlaybackPosition:(MPChangePlaybackPositionCommandEvent *)event
|
|
289
|
+
{
|
|
290
|
+
[self.audioManagerModule sendEventWithName:@"onRemoteChangePlaybackPosition"
|
|
291
|
+
body:@{@"value" : [NSNumber numberWithDouble:event.positionTime]}];
|
|
292
|
+
return MPRemoteCommandHandlerStatusSuccess;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <AVFoundation/AVFoundation.h>
|
|
4
|
+
#import <Foundation/Foundation.h>
|
|
5
|
+
|
|
6
|
+
@class AudioManagerModule;
|
|
7
|
+
|
|
8
|
+
@interface NotificationManager : NSObject
|
|
9
|
+
|
|
10
|
+
@property (nonatomic, weak) AudioManagerModule *audioManagerModule;
|
|
11
|
+
@property (nonatomic, weak) NSNotificationCenter *notificationCenter;
|
|
12
|
+
|
|
13
|
+
@property (nonatomic, assign) bool isInterrupted;
|
|
14
|
+
@property (nonatomic, assign) bool hadConfigurationChange;
|
|
15
|
+
@property (nonatomic, assign) BOOL audioInterruptionsObserved;
|
|
16
|
+
|
|
17
|
+
+ (instancetype)sharedInstanceWithAudioManagerModule:(AudioManagerModule *)audioManagerModule;
|
|
18
|
+
- (void)cleanup;
|
|
19
|
+
|
|
20
|
+
- (void)observeAudioInterruptions:(BOOL)enabled;
|
|
21
|
+
|
|
22
|
+
@end
|