237 lines
9.7 KiB
Swift
237 lines
9.7 KiB
Swift
//
|
|
// SystemSoundPlayer.swift
|
|
// DDAudioPlayerKit_Private
|
|
//
|
|
// Created by 中道 on 2023/8/31.
|
|
//
|
|
|
|
import Foundation
|
|
import AVFoundation
|
|
//import DDLogKit_Private
|
|
|
|
public let DDAS = DDAudioService.default
|
|
|
|
open class DDAudioService {
|
|
public static let `default` = DDAudioService()
|
|
private var items : [DDAudioServiceItem] = []
|
|
|
|
public func playSoundWithVibrate(audioUrl:URL,name:String,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
|
let item = DDAudioServiceItem(name: name)
|
|
items.append(item)
|
|
item.playSoundWithVibrate(audioUrl: audioUrl,numberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
|
}
|
|
|
|
public func playSound(audioUrl:URL,name:String,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
|
let item = DDAudioServiceItem(name: name)
|
|
items.append(item)
|
|
item.playSound(audioUrl: audioUrl,numberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
|
}
|
|
|
|
public func playVibrate(name:String,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
|
let item = DDAudioServiceItem(name: name)
|
|
items.append(item)
|
|
item.playVibrate(numberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
|
}
|
|
|
|
public func stopSoundWithVibrate(name:String) {
|
|
if items.contains(where: { item in
|
|
item.name == name
|
|
}) == true {
|
|
if let index = items.firstIndex(where: { item in
|
|
item.name == name
|
|
}) {
|
|
let item = items[index]
|
|
item.stopSoundWithVibrate {[weak self] in
|
|
self?.items.remove(at: index)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public func stopSound(name:String) {
|
|
if items.contains(where: { item in
|
|
item.name == name
|
|
}) == true {
|
|
if let index = items.firstIndex(where: { item in
|
|
item.name == name
|
|
}) {
|
|
let item = items[index]
|
|
item.stopSound {[weak self] in
|
|
self?.items.remove(at: index)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public func stopVibrate(name:String) {
|
|
if items.contains(where: { item in
|
|
item.name == name
|
|
}) == true {
|
|
if let index = items.firstIndex(where: { item in
|
|
item.name == name
|
|
}) {
|
|
let item = items[index]
|
|
item.stopVibrate {[weak self] in
|
|
self?.items.remove(at: index)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
open class DDAudioServiceItem {
|
|
fileprivate var name : String
|
|
private var audioSoundID : SystemSoundID = 0
|
|
private var vibrateSoundID : SystemSoundID = 0
|
|
private var endSound : Bool = false
|
|
private var endVibrate : Bool = false
|
|
private var stopSoundCompletionHander : (() -> Void)?
|
|
private var stopVibrateCompletionHander : (() -> Void)?
|
|
|
|
init(name:String) {
|
|
self.name = name
|
|
}
|
|
|
|
public func playSoundWithVibrate(audioUrl:URL,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0, eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
|
playVibrate(numberOfLoops: -1)
|
|
playSound(audioUrl: audioUrl,numberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock) {[weak self] in
|
|
self?.stopVibrate {
|
|
if endCompletionBlock != nil {
|
|
endCompletionBlock!()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public func stopSoundWithVibrate(completionHander:@escaping (() -> Void)) {
|
|
stopSound {[weak self] in
|
|
self?.stopVibrate {
|
|
completionHander()
|
|
}
|
|
}
|
|
}
|
|
|
|
public func playSound(audioUrl:URL,numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
|
|
|
var audioSoundID:SystemSoundID = 0
|
|
AudioServicesCreateSystemSoundID(audioUrl as CFURL, &audioSoundID)
|
|
self.audioSoundID = audioSoundID
|
|
DispatchQueue.global().async {[weak self] in
|
|
self?.playSound(audioSoundID: audioSoundID,leftNumberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
|
}
|
|
}
|
|
|
|
private func playSound(audioSoundID:SystemSoundID,leftNumberOfLoops:Int,timeInterval:TimeInterval,eachLoopCompletionBlock: (() -> Void)?, endCompletionBlock: (() -> Void)?) {
|
|
var changeLeftNumberOfLoops = leftNumberOfLoops
|
|
AudioServicesPlaySystemSoundWithCompletion(audioSoundID) {[weak self] in
|
|
// 每次loop后回调
|
|
if eachLoopCompletionBlock != nil {
|
|
eachLoopCompletionBlock!()
|
|
}
|
|
|
|
// 当前的剩余为0就结束
|
|
changeLeftNumberOfLoops-=1
|
|
if changeLeftNumberOfLoops == 0 || self?.endSound == true {
|
|
// 结束播放
|
|
AudioServicesDisposeSystemSoundID(audioSoundID)
|
|
// DDLog(message: "name = \(self?.name ?? "")的sound播放结束")
|
|
|
|
// 清除数据
|
|
self?.audioSoundID = 0
|
|
self?.endSound = false
|
|
|
|
// stop后回调
|
|
if self?.stopSoundCompletionHander != nil {
|
|
self?.stopSoundCompletionHander!()
|
|
}else if endCompletionBlock != nil {
|
|
// play所有loops后回调
|
|
endCompletionBlock!()
|
|
}
|
|
}else{
|
|
DispatchQueue.global().asyncAfter(deadline: .now() + timeInterval, execute: {
|
|
self?.playSound(audioSoundID: audioSoundID, leftNumberOfLoops: changeLeftNumberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
public func stopSound(completionHandler:@escaping (() -> Void)) {
|
|
stopSoundCompletionHander = completionHandler
|
|
|
|
// 先尝试关闭
|
|
let status = AudioServicesDisposeSystemSoundID(audioSoundID)
|
|
// DDLog(message: "sound dispose status = \(status)")
|
|
if status != 0 {
|
|
// 假如没有关闭成功的话会来到结束
|
|
endSound = true
|
|
}else {
|
|
audioSoundID = 0
|
|
// DDLog(message: "name = \(name)的sound播放结束")
|
|
completionHandler()
|
|
}
|
|
}
|
|
|
|
|
|
public func playVibrate(numberOfLoops:Int = 1,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)? = nil,endCompletionBlock: (() -> Void)? = nil) {
|
|
self.endVibrate = false
|
|
|
|
var vibrateSoundID : SystemSoundID = 0
|
|
vibrateSoundID = kSystemSoundID_Vibrate
|
|
self.vibrateSoundID = vibrateSoundID
|
|
DispatchQueue.global().async {[weak self] in
|
|
self?.playVibrate(vibrateSoundID: vibrateSoundID, leftNumberOfLoops: numberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
|
}
|
|
}
|
|
|
|
private func playVibrate(vibrateSoundID:SystemSoundID,leftNumberOfLoops:Int,timeInterval:TimeInterval = 0,eachLoopCompletionBlock: (() -> Void)?, endCompletionBlock: (() -> Void)?) {
|
|
var changeLeftNumberOfLoops = leftNumberOfLoops
|
|
AudioServicesPlayAlertSoundWithCompletion(vibrateSoundID) {[weak self] in
|
|
// 每次loop后回调
|
|
if eachLoopCompletionBlock != nil {
|
|
eachLoopCompletionBlock!()
|
|
}
|
|
|
|
// 当前的剩余为0就结束
|
|
changeLeftNumberOfLoops-=1
|
|
if changeLeftNumberOfLoops == 0 || self?.endVibrate == true {
|
|
// 结束
|
|
AudioServicesDisposeSystemSoundID(vibrateSoundID)
|
|
// DDLog(message: "name = \(self?.name ?? "")的vibrate播放结束")
|
|
|
|
// 清除数据
|
|
self?.vibrateSoundID = 0
|
|
self?.endVibrate = false
|
|
|
|
// stop后的回调
|
|
if self?.stopVibrateCompletionHander != nil {
|
|
self?.stopVibrateCompletionHander!()
|
|
}else if endCompletionBlock != nil {
|
|
// play完所有loops后回调
|
|
endCompletionBlock!()
|
|
}
|
|
}else{
|
|
DispatchQueue.global().asyncAfter(deadline: .now() + timeInterval, execute: {
|
|
self?.playVibrate(vibrateSoundID: vibrateSoundID, leftNumberOfLoops: changeLeftNumberOfLoops,timeInterval: timeInterval,eachLoopCompletionBlock: eachLoopCompletionBlock,endCompletionBlock: endCompletionBlock)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
public func stopVibrate(completionHandler:@escaping (() -> Void)) {
|
|
stopVibrateCompletionHander = completionHandler
|
|
|
|
// 先尝试关闭
|
|
let status = AudioServicesDisposeSystemSoundID(vibrateSoundID)
|
|
// DDLog(message: "vibrate dispose status = \(status)")
|
|
if status != 0 {
|
|
// 假如没有关闭成功的话会来到结束
|
|
endVibrate = true
|
|
}else{
|
|
vibrateSoundID = 0
|
|
// DDLog(message: "name = \(name)的vibrate播放结束")
|
|
completionHandler()
|
|
}
|
|
}
|
|
|
|
}
|