226 lines
5.9 KiB
Objective-C
226 lines
5.9 KiB
Objective-C
//
|
|
// TUICallingAudioPlayer.m
|
|
// TUICalling
|
|
//
|
|
// Created by gg on 2021/9/2.
|
|
//
|
|
|
|
#import "TUICallingAudioPlayer.h"
|
|
#import <AVFoundation/AVFoundation.h>
|
|
#import "TUICommonUtil.h"
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
@interface TUICallingAudioParam : NSObject
|
|
|
|
/// default is 0
|
|
@property (nonatomic, assign) NSTimeInterval startTime;
|
|
|
|
/// default is 10000
|
|
@property (nonatomic, assign) NSTimeInterval endTime;
|
|
|
|
/// default is NO
|
|
@property (nonatomic, assign) BOOL loop;
|
|
|
|
@end
|
|
|
|
@interface TUICallingAudioPlayer : NSObject <AVAudioPlayerDelegate>
|
|
|
|
+ (instancetype)sharedInstance;
|
|
|
|
- (BOOL)playAudio:(NSURL *)url;
|
|
|
|
- (BOOL)playAudio:(NSURL *)url params:(TUICallingAudioParam * _Nullable)param;
|
|
|
|
- (void)stopAudio;
|
|
|
|
#pragma mark - Private
|
|
@property (nonatomic, strong) CADisplayLink *displayLink;
|
|
@property (nonatomic, assign) NSTimeInterval startTime;
|
|
@property (nonatomic, assign) NSTimeInterval endTime;
|
|
@property (nonatomic, assign) BOOL loop;
|
|
@property (nonatomic, strong) AVAudioPlayer *player;
|
|
@end
|
|
|
|
NS_ASSUME_NONNULL_END
|
|
|
|
BOOL playAudioWithFilePath(NSString *filePath) {
|
|
TUICallingAudioParam *param = [[TUICallingAudioParam alloc] init];
|
|
NSURL *url = [NSURL fileURLWithPath:filePath];
|
|
if (!url) {
|
|
return NO;
|
|
}
|
|
param.startTime = 1.5;
|
|
param.loop = YES;
|
|
return [[TUICallingAudioPlayer sharedInstance] playAudio:url params:param];
|
|
}
|
|
|
|
BOOL playAudio(CallingAudioType type) {
|
|
NSBundle *bundle = [TUICommonUtil callingBundle];
|
|
TUICallingAudioParam *param = [[TUICallingAudioParam alloc] init];
|
|
switch (type) {
|
|
case CallingAudioTypeHangup: {
|
|
NSString *path = [[[bundle bundlePath] stringByAppendingPathComponent:@"AudioFile"] stringByAppendingPathComponent:@"phone_hangup.mp3"];
|
|
NSURL *url = [NSURL fileURLWithPath:path];
|
|
if (!url) {
|
|
return NO;
|
|
}
|
|
param.endTime = 2;
|
|
return [[TUICallingAudioPlayer sharedInstance] playAudio:url params:param];
|
|
} break;
|
|
case CallingAudioTypeCalled: {
|
|
NSString *path = [[[bundle bundlePath] stringByAppendingPathComponent:@"AudioFile"] stringByAppendingPathComponent:@"phone_ringing.flac"];
|
|
NSURL *url = [NSURL fileURLWithPath:path];
|
|
if (!url) {
|
|
return NO;
|
|
}
|
|
param.startTime = 1.5;
|
|
param.loop = YES;
|
|
return [[TUICallingAudioPlayer sharedInstance] playAudio:url params:param];
|
|
} break;
|
|
case CallingAudioTypeDial: {
|
|
NSString *path = [[[bundle bundlePath] stringByAppendingPathComponent:@"AudioFile"] stringByAppendingPathComponent:@"phone_dialing.m4a"];
|
|
NSURL *url = [NSURL fileURLWithPath:path];
|
|
if (!url) {
|
|
return NO;
|
|
}
|
|
param.startTime = 2;
|
|
param.loop = YES;
|
|
return [[TUICallingAudioPlayer sharedInstance] playAudio:url params:param];
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
void stopAudio(void) {
|
|
[[TUICallingAudioPlayer sharedInstance] stopAudio];
|
|
}
|
|
|
|
|
|
@implementation TUICallingAudioParam
|
|
- (instancetype)init {
|
|
if (self = [super init]) {
|
|
self.endTime = 10000;
|
|
self.startTime = 0;
|
|
self.loop = NO;
|
|
}
|
|
return self;
|
|
}
|
|
@end
|
|
|
|
@implementation TUICallingAudioPlayer
|
|
|
|
- (BOOL)playAudio:(NSURL *)url {
|
|
return [self playAudio:url params:nil];
|
|
}
|
|
|
|
- (BOOL)playAudio:(NSURL *)url params:(TUICallingAudioParam *)param {
|
|
if (self.player != nil) {
|
|
[self stopAudio];
|
|
}
|
|
NSError *error = nil;
|
|
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
|
|
if (error) {
|
|
return NO;
|
|
}
|
|
if (![self.player prepareToPlay]) {
|
|
return NO;
|
|
}
|
|
if (param != nil) {
|
|
self.startTime = param.startTime;
|
|
self.endTime = param.endTime;
|
|
self.loop = param.loop;
|
|
}
|
|
else {
|
|
self.startTime = 0;
|
|
self.endTime = 10000;
|
|
self.loop = NO;
|
|
}
|
|
self.player.currentTime = self.startTime;
|
|
self.player.delegate = self;
|
|
BOOL res = [self.player play];
|
|
if (self.endTime != 0 && res && self.endTime <= self.player.duration) {
|
|
[self startDisplayLink];
|
|
}
|
|
return res;
|
|
}
|
|
|
|
- (void)resetStatus {
|
|
self.loop = NO;
|
|
self.startTime = 0;
|
|
self.endTime = 10000;
|
|
[self invalidateDisplayLink];
|
|
}
|
|
|
|
- (void)stopAudio {
|
|
if (self.player == nil) {
|
|
return;
|
|
}
|
|
[self.player stop];
|
|
[self resetStatus];
|
|
self.player = nil;
|
|
}
|
|
|
|
- (void)startDisplayLink {
|
|
if (self.displayLink != nil) {
|
|
[self invalidateDisplayLink];
|
|
}
|
|
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkCallback:)];
|
|
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
}
|
|
|
|
- (void)invalidateDisplayLink {
|
|
if (self.displayLink == nil) {
|
|
return;
|
|
}
|
|
[self.displayLink invalidate];
|
|
self.displayLink = nil;
|
|
}
|
|
|
|
- (void)displayLinkCallback:(CADisplayLink *)displayLink {
|
|
if (self.player == nil || self.endTime <= 0 || !self.player.isPlaying) {
|
|
return;
|
|
}
|
|
if (self.player.currentTime >= self.endTime) {
|
|
if (self.loop) {
|
|
[self.player pause];
|
|
self.player.currentTime = self.startTime;
|
|
[self.player play];
|
|
}
|
|
else {
|
|
[self stopAudio];
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma mark - AVAudioPlayerDelegate
|
|
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
|
|
if (self.loop) {
|
|
player.currentTime = self.startTime;
|
|
[player play];
|
|
}
|
|
else {
|
|
[self stopAudio];
|
|
}
|
|
}
|
|
|
|
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error {
|
|
if (error) {
|
|
[self stopAudio];
|
|
}
|
|
}
|
|
|
|
#pragma mark - initialize
|
|
+ (instancetype)sharedInstance {
|
|
static TUICallingAudioPlayer *instance = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
instance = [[self alloc] init];
|
|
});
|
|
return instance;
|
|
}
|
|
|
|
@end
|