--- /dev/null
+//
+// Untitled.swift
+// DeepChordsSdk
+//
+// Created by liangshi on 2025/11/25.
+//
+
+import Foundation
+
+/// 判断可选类型是否为 nil
+func isNil(_ any: Any?) -> Bool {
+ switch any {
+ case .none: return true
+ case .some: return false
+ }
+}
+
+/// 判断可选类型是否有值
+func isValue(_ any: Any?) -> Bool {
+ return isNil(any) == false
+}
+
+/// for Array
+func isEmpty(_ value: [Any]?) -> Bool {
+ return isNil(value) || value!.count == 0
+}
+
+/// for Array
+func isNotEmpty(_ value: [Any]?) -> Bool {
+ return isEmpty(value) == false
+}
+
+/// for Dictionary
+func isEmpty(_ value: [AnyHashable: Any]?) -> Bool {
+ return isNil(value) || value!.count == 0
+}
+
+/// for Dictionary
+func isNotEmpty(_ value: [AnyHashable: Any]?) -> Bool {
+ return isEmpty(value) == false
+}
+
+/// for String
+func isEmpty(_ value: String?) -> Bool {
+ return isNil(value) || value!.count == 0
+}
+
+/// for String
+func isNotEmpty(_ value: String?) -> Bool {
+ return isEmpty(value) == false
+}
+
+public extension String {
+
+ /// 补足8位(长度为8的整数倍)
+ var binary: String {
+ let bytes = (Double(count) / 8.0).upInt
+ let offset = bytes * 8 - count
+ let prefix = Array(repeating: "0", count: offset).joined()
+ return prefix + self
+ }
+}
+
+public extension Double {
+ var upInt: Int { Int(ceil(self)) }
+}
+
+public extension Int {
+ private static let binaryPack = 0b11111111
+
+ /// convert to data with byte (max is 4294967295)
+ ///
+ /// 低位 --> 高位
+ var bytes: [UInt8] {
+ var mutatingSelf = self
+ var bytes = [UInt8(mutatingSelf & Self.binaryPack)]
+
+ var count = 1
+ mutatingSelf = mutatingSelf >> (count * 8)
+ while mutatingSelf > 0 {
+ bytes.append(UInt8(mutatingSelf & Self.binaryPack))
+ mutatingSelf = mutatingSelf >> (count * 8)
+ count = count + 1
+ }
+ return bytes
+ }
+
+ /// convert to data with 1 byte
+ var byte: UInt8 {
+ UInt8(self & Self.binaryPack)
+ }
+
+ /// convert to data with 2 byte
+ ///
+ /// 低位 --> 高位
+ var byte2: [UInt8] {
+ [
+ UInt8(self & Self.binaryPack),
+ UInt8(self >> 8 & Self.binaryPack)
+ ]
+ }
+
+ /// convert to data with 3 byte
+ ///
+ /// 低位 --> 高位
+ var byte3: [UInt8] {
+ [
+ UInt8(self & Self.binaryPack),
+ UInt8(self >> 8 & Self.binaryPack),
+ UInt8(self >> 16 & Self.binaryPack)
+ ]
+ }
+
+ /// convert to data with 4 byte
+ ///
+ /// 低位 --> 高位
+ var byte4: [UInt8] {
+ [
+ UInt8(self & Self.binaryPack),
+ UInt8(self >> 8 & Self.binaryPack),
+ UInt8(self >> 16 & Self.binaryPack),
+ UInt8(self >> 24 & Self.binaryPack)
+ ]
+ }
+}
+
+public extension BinaryInteger {
+
+ /// e.g. 0000100110010101
+ var binaryString: String {
+ .init(self, radix: 2).binary
+ }
+}
+
+public extension Array where Element == UInt8 {
+
+ var int: Int {
+ self
+ .map { Int($0) }
+ .enumerated()
+ .map { $1 << ($0 * 8) }
+ .reduce(0, { partialResult, value in
+ partialResult | value
+ })
+ }
+
+ var data: Data { Data(self) }
+}
+
+public extension Data {
+
+ func joined(format: String = "%02x", _ separator: String = "") -> String {
+ self
+ .map { String(format: format, $0) }
+ .joined(separator: separator)
+ }
+
+ func reversedJoined(format: String = "%02x", _ separator: String = "") -> String {
+ self
+ .map { String(format: format, $0) }
+ .reversed()
+ .joined(separator: separator)
+ }
+
+ var int: Int {
+ self
+ .map { Int($0) }
+ .enumerated()
+ .map { $1 << ($0 * 8) }
+ .reduce(0, { partialResult, value in
+ partialResult | value
+ })
+ }
+
+}
+
+public extension UInt8 {
+ var int: Int { Int(self) }
+}
+
+
+extension Data{
+ var float: Float {
+ var floatValue: Float = 0.0
+ let size = MemoryLayout<Float>.size
+ guard self.count >= size else { return 0 }
+
+ self.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) -> Void in
+ _ = memcpy(&floatValue, buffer.baseAddress!, size)
+ }
+
+ return floatValue
+ }
+}
--- /dev/null
+//
+// BleSender.swift
+// DeepChordsSdk
+//
+// Created by liangshi on 2025/11/25.
+//
+
+import Foundation
+
+class BleSender{
+ var completion: DCCompletionHandler!
+ var data = Data()
+
+ static var all: [BleSender] = []
+
+ init() {
+ Self.all.append(self)
+ startTimer()
+ }
+ var timer: Timer?
+ func startTimer() {
+ deinitTimer()
+
+ self.timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false, block: { [unowned self] _ in
+ deinitTimer()
+ self.completion?(.response.code(.timeout))
+ self.remove()
+ })
+ }
+
+ @discardableResult
+ func deinitTimer() ->Self{
+ guard let _ = self.timer else { return self}
+ self.timer?.invalidate()
+ self.timer = nil
+ // DCLogger.log("销毁定时器")
+ return self
+ }
+
+ /// 从缓存实例集合中移除该实例
+ func remove() {
+ Self.all.removeAll { $0 === self }
+ }
+
+ func isAnswer(_ receiveData:Data)->Bool{
+ if data.count < 3{
+ return false
+ }
+ if receiveData[1] == data[1] {
+ return true
+ }
+ return false
+ }
+
+ static func answer(_ data: Data) -> BleSender? {
+ if data.count < 3{
+ return nil
+ }
+ for item in Self.all {
+ if item.isAnswer(data) {
+ return item
+ }
+ }
+ return nil
+ }
+}
+
+public typealias DCCompletionHandler = (_ result: DCResponse) -> Void
+
+/// 状态码
+public enum DCCode: Int,CustomStringConvertible {
+
+ public var description: String{
+ return "MSCode(rawValue:\(rawValue), message:\(message))"
+ }
+
+ /// 操作成功
+ case success = 1000
+ /// 操作失败
+ case failure = 1001
+ /// 请求超时
+ case timeout = 1004
+ /// 未知错误
+ case unknow = 1005
+
+ var message:String{
+ switch self {
+ case .failure:
+ return "失败"
+ case .success:
+ return "成功"
+ case .timeout:
+ return "超时"
+ default:
+ return "未知错误"
+ }
+ }
+}
+
+public class DCResponse {
+ public private(set) var code: DCCode = .success
+ public private(set) var data: Data = Data()
+ static var response: DCResponse { DCResponse() }
+
+
+ var isSuccess:Bool{
+ return code == .success
+ }
+
+ public var description: String{
+ return code.description + "data = " + data.joined()
+ }
+
+ @discardableResult
+ func code(_ value: DCCode) -> Self {
+ code = value
+ return self
+ }
+
+ @discardableResult
+ func value(_ value: Data) -> Self {
+ self.data = value
+ return self
+ }
+}
--- /dev/null
+//
+// Untitled.swift
+// DeepChordsSdk
+//
+// Created by liangshi on 2025/11/25.
+//
+
+import Foundation
+import CoreBluetooth
+import StarburstSdk
+
+public class DCBleManager{
+ public static let serviceUUID = "AE30"
+ public static let writeUUID = "AE03"
+ public static let notifyUUID = "AE04"
+
+
+ public static let shared = DCBleManager()
+ private var connectPeripheral: CBPeripheral?
+ private var writeCha: CBCharacteristic?
+
+ func send(_ sender:BleSender){
+ if let connectPeripheral = connectPeripheral, let writeCha = writeCha {
+ DCLogger.debug("发",writeCha.uuid.uuidString,sender.data.joined())
+
+
+// if sender.data[1] == 0x10,sender.data[2] == 0x01 {
+// let text1 = "ba100101025b7b226964223a302c226e616d65223a22e69da8e5ae97e7baac2de4b880e6aca1e5b0b1e5a5bd20284c697665292e6d7033222c2273697a65223a343233323632342c22647572223a307d2c7b226964223a312c226e616d65223a22e5bca0e7b4abe8b1aa2de58fafe4b88de58fafe4bba52e6d7033222c2273697a65223a393635383835322c22647572223a307d2c7b226964223a322c226e616d65223a224245594f4e442de79c9fe79a84e788b1e4bda02e6d7033222c2273697a65223a31313031363533372c22647572223a307d2c7b226964223a332c226e616d65223a22472e452e4d2e20e98293e7b4abe6a38b2de69c89e5bf83e4baba2e6d7033222c2273697a65223a393630333832392c22647572223a307d2c7b226964223a342c226e616d65223a2248414e41e88f8ae6a293e4b9942de68891e4b88de698afe5a5b92e6d7033222c2273697a65223a373932343138312c22647572223a307d2c7b226964223a352c226e616d65223a2248414e412de5bf98e8aeb0e68891e887aae5b7b12e6d7033222c2273697a65223a393330343938342c22647572223a307d5da701d9"
+// sender.completion?(.response.code(.success).value(Data.dataWithHexString(text1)))
+// let text2 = "ba100102025b7b226964223a362c226e616d65223a224d722e3136e7bd97e99abde6b0b82de5a484e5a484e590bb2e6d7033222c2273697a65223a383533333836302c22647572223a307d2c7b226964223a372c226e616d65223a22536f6c65722de9a2a8e79a84e5ada3e7af802e6d7033222c2273697a65223a31303031333432352c22647572223a307d2c7b226964223a382c226e616d65223a225477696e732de6818be788b1e5a4a7e8bf87e5a4a92e6d7033222c2273697a65223a393039383039362c22647572223a307d2c7b226964223a392c226e616d65223a225477696e732de6a3aee5b7b4e79a87e5908e2e6d7033222c2273697a65223a373436323832322c22647572223a307d5d0e012c"
+// sender.completion?(.response.code(.success).value(Data.dataWithHexString(text2)))
+// }
+// else{
+ connectPeripheral.writeValue(sender.data, for: writeCha, type:.withoutResponse)
+// }
+ }
+ }
+ func sendToStarburst(_ data:Data){
+ var full = Data.dataWithHexString("BA0D")
+ full.append(data)
+ full.addCrc()
+ if let connectPeripheral = connectPeripheral, let writeCha = writeCha {
+// DCLogger.debug("发",writeCha.uuid.uuidString,full.joined())
+ connectPeripheral.writeValue(full, for: writeCha, type:.withoutResponse)
+ }
+ }
+}
+
+public extension DCBleManager{
+ func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
+ DCLogger.debug("蓝牙已连接 \(peripheral)")
+ connectPeripheral = peripheral
+ }
+
+ func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
+ DCLogger.debug("蓝牙已断开 \(peripheral)")
+ StarburstSdk.shared().bleDisConnected()
+ }
+//
+// func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
+// DCLogger.debug("发现服务成功")
+// for service in peripheral.services! {
+// DCLogger.debug("peripheral service: %@", service)
+// peripheral.discoverCharacteristics(nil, for: service)
+// }
+//
+// }
+ func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
+ if let list = service.characteristics{
+ DCLogger.debug("发现特征",list)
+ for char in list{
+ DCLogger.debug(char)
+ if char.uuid.uuidString == DCBleManager.notifyUUID {
+ peripheral.setNotifyValue(true, for: char)
+ }
+ if char.uuid.uuidString == DCBleManager.writeUUID {
+ writeCha = char
+
+ DCDevice.shared.handShake { success in
+ StarburstSdk.shared().bleConnected()
+ }
+ }
+ }
+ }
+ }
+
+ func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
+// DCLogger.debug("收 ",characteristic.uuid,characteristic.value?.joined() ?? "")
+ guard let data = characteristic.value else { return }
+ if data.count > 4 && data[0] == 0xBA {
+ if let sender = BleSender.answer(data) {
+ sender.completion?(.response.code(.success).value(data))
+ if data[1] == 0x10,data[2] == 0x01{
+ //音乐列表分包,解析的时候处理
+ }
+ else{
+ sender.deinitTimer()
+ sender.remove()
+ }
+ return
+ }
+ else if data[1] == 0x0D{
+ let subData = data.subdata(in: 2..<data.count - 3)
+ //DCLogger.debug("传给字节sdk",subData.joined())
+ StarburstSdk.shared().receiveBleData(subData)
+ }else{
+ receiveNoticeData(data)
+ }
+ }
+ else{
+ DCLogger.debug("收到异常数据!!!!!!!!!!!")
+ }
+ }
+}
+
+extension DCBleManager{
+ func receiveNoticeData(_ data:Data){
+ if data[1] == 0x10,data[2] == 0x06{
+ DCDevice.shared.receiveNotice(data)
+ }
+ else if data[1] == 0x0F,data[2] == 0x0B{
+ let type = data[3]
+ switch type{
+ case 0x01:
+ DCLogger.debug("打开AI对话")
+ case 0x02:
+ DCLogger.debug("关闭AI对话")
+// DCChat.shared.stopChat()
+ case 0x03:
+ DCLogger.debug("打开耳机录音")
+// DCBleRecord.shared.start(type: 0x00)
+ case 0x04:
+ DCLogger.debug("关闭耳机录音")
+// DCBleRecord.shared.stop()
+ default:
+ break
+ }
+ DCDevice.shared.eventCallback?(type)
+ DCDevice.shared.sendAiEventResponse(type)
+ }
+ }
+ static func contentData(_ data:Data)->Data{
+ if data.count > 4 && data[0] == 0xBA {
+ return data.subdata(in: 2..<data.count - 3)
+ }
+ return data
+ }
+}
--- /dev/null
+//
+// DCBleRecord.swift
+// Example
+//
+// Created by liangshi on 2025/12/9.
+//
+
+import StarburstSdk
+
+public class DCBleRecord {
+ public static let shared = DCBleRecord()
+ /// 语⾔编码,默认为普通话(zh-CN),auto_lang自动识别
+ public var fromLanguage:String = "zh-CN"
+ /// ⽬标语⾔编码,默认为英语(en-US),auto_lang自动识别
+ public var toLanguage:String = "en-US"
+ /// 是否翻译,默认false。如果为true翻译源语言和目标语言不能是同一种语言
+ public var isTranslate = false
+ /// 是否进⾏Tts,默认false
+ public var isTTs = false
+ /// 默认pcm ⽀持pcm / ogg_opus / mp3
+ public var ttsFormat = "mp3"
+ /// 识别回调
+ public var asrCallback:((String)->Void)?
+ /// 识别回调
+ public var translateCallback:((String)->Void)?
+ /// 识别回调
+ public var asrSplitCallback:((DCResponseModel)->Void)?
+ /// 识别回调
+ public var translateSplitCallback:((DCResponseModel)->Void)?
+ /// 翻译语音回调
+ public var translateDataCallback:((Data)->Void)?
+ /// 状态码回调
+ public var codeCallback:((Int)->Void)?
+ /// 录音文件回调
+ public var filePathCallBack:((String?)->Void)?
+ /// 设置录音文件路径
+ public var filePath:String?
+
+ var asrList : [(String,Int)] = []
+ var asrText = ""
+
+ var translateList : [(String,Int)] = []
+ var translateText = ""
+
+
+ init() {
+ setupRecord()
+ }
+
+ func setupRecord(){
+ // 通话录音声道数。1:单声道 ;2:⽴体声;默认单声道
+ StarburstConfig.shared().callRecordChannel = 1
+
+ let config = StarburstAsrConfig()
+ config.isTranslate = isTranslate
+ config.fromLanguage = fromLanguage
+ config.toLanguage = toLanguage
+ config.isTTs = isTTs
+ config.ttsFormat = ttsFormat
+
+ StarburstSdk.shared().setupDeviceRecord(with: filePath, asrConfig: config) { config in
+ DCLogger.debug("录音类型 \(config!.type == 0x00 ? "实时录音" : "通话录音")")
+ } recognizeText: { [weak self] model in
+ guard let self = self else {return}
+ guard let model = model else {return}
+
+ if let text = model.textResult,!text.isEmpty{
+ DCLogger.debug("asr = \(text)")
+ asrSplitCallback?(DCResponseModel(text: text, index: model.definiteIndex, definite: model.definite))
+ let msg = asrList.firstIndex (where: { (str,idx) in
+ return idx == model.definiteIndex;
+ })
+ if (msg == nil) {
+ asrList.append((text,model.definiteIndex))
+ } else {
+ asrList[msg!] = (text,model.definiteIndex)
+ }
+ asrText = asrList.compactMap({ (str,idx) in
+ return str
+ }).joined(separator: "\n")
+
+ asrCallback?(asrText)
+ }
+ if let translate = model.translateResult,let text = translate.text,!text.isEmpty{
+ DCLogger.debug("translate = \(text)")
+ translateSplitCallback?(DCResponseModel(text: text, index: Int(translate.definiteIndex), definite: translate.definite))
+ let msg = translateList.firstIndex (where: { (str,idx) in
+ return idx == translate.definiteIndex;
+ })
+ if (msg == nil) {
+ translateList.append((text,Int(translate.definiteIndex)))
+ } else {
+ translateList[msg!] = (text,Int(translate.definiteIndex))
+ }
+ translateText = translateList.compactMap({ (str,idx) in
+ return str
+ }).joined(separator: "\n")
+
+ translateCallback?(translateText)
+ }
+ if let ttsData = model.ttsResult?.streamPiece {
+ if let data = Data(base64Encoded: ttsData){
+ translateDataCallback?(data)
+ }
+ }
+ } stateChange: { [weak self] code in
+ DCLogger.debug("状态改变",code)
+ self?.codeCallback?(code.rawValue)
+ } finished: {[weak self] filePath in
+ DCLogger.debug("文件录音保存路径 \(filePath ?? "")")
+ self?.filePathCallBack?(filePath)
+ }
+ }
+
+ /// 0x00实时录音,0x0c通话录音
+ public func start(type:Int,recordPath:String?){
+
+ asrList = []
+ asrText = ""
+
+ translateList = []
+ translateText = ""
+ filePath = recordPath
+ DCLogger.debug("设置地址 \(filePath ?? "")")
+
+ setupRecord()
+ let config = StarburstBleAsrConfig()
+ config.type = type
+ StarburstSdk.shared().startDeviceRecord(config)
+
+ }
+ public func stop(){
+ StarburstSdk.shared().stopDeviceRecord()
+ }
+}
--- /dev/null
+//
+// DCCallRecord.swift
+// Example
+//
+// Created by liangshi on 2025/12/30.
+//
+
+import StarburstSdk
+
+public class DCCallRecord {
+ public static let shared = DCCallRecord()
+ /// 语⾔编码,默认为普通话(zh-CN),auto_lang自动识别
+ public var fromLanguage:String = "auto_lang"
+ /// ⽬标语⾔编码,默认为英语(en-US),auto_lang自动识别
+ public var toLanguage:String = "auto_lang"
+ /// 是否翻译,默认false。如果为true翻译源语言和目标语言不能是同一种语言
+ public var isTranslate = false
+ /// 是否进⾏Tts,默认false
+ public var isTTs = false
+ /// 默认pcm ⽀持pcm / ogg_opus / mp3
+ public var ttsFormat = "mp3"
+ /// 识别回调
+ public var asrCallback:((String)->Void)?
+ /// 对方识别回调
+ public var asrOtherCallback:((String)->Void)?
+
+ /// 状态码回调
+ public var codeCallback:((Int)->Void)?
+ /// 录音文件回调
+ public var filePathCallBack:((String?)->Void)?
+ /// opus回调
+ public var opusCallBack:((Data)->Void)?
+
+ var asrList : [(String,Int)] = []
+ var asrText = ""
+
+ var asrOtherList : [(String,Int)] = []
+ var asrOtherText = ""
+
+ init() {
+ setupRecord()
+ }
+
+ func setupRecord(){
+ // 通话录音声道数。1:单声道 ;2:⽴体声;默认单声道
+ StarburstConfig.shared().callRecordChannel = 2
+
+ let config = StarburstAsrConfig()
+ config.isTranslate = isTranslate
+ config.fromLanguage = fromLanguage
+ config.toLanguage = toLanguage
+ config.isTTs = isTTs
+ config.ttsFormat = ttsFormat
+
+ StarburstSdk.shared().setupDeviceRecord(with: nil, asrConfig: config) { config in
+ DCLogger.debug("录音类型 \(config!.type == 0x00 ? "实时录音" : "通话录音")")
+ } recognizeText: { [weak self] model in
+ guard let self = self else {return}
+ guard let model = model else {return}
+ DCLogger.debug(model.channel,"asr =",model.definiteIndex,model.textResult)
+ if let text = model.textResult,!text.isEmpty{
+
+ if model.channel == 1 {
+ //左耳
+ let msg = asrList.firstIndex (where: { (str,idx) in
+ return idx == model.definiteIndex;
+ })
+ if (msg == nil) {
+ asrList.append((text,model.definiteIndex))
+ } else {
+ asrList[msg!] = (text,model.definiteIndex)
+ }
+ asrText = asrList.compactMap({ (str,idx) in
+ return str
+ }).joined(separator: "\n")
+
+ asrCallback?(asrText)
+ }
+ else if model.channel == 2{
+ //右耳
+ let msg = asrOtherList.firstIndex (where: { (str,idx) in
+ return idx == model.definiteIndex;
+ })
+ if (msg == nil) {
+ asrOtherList.append((text,model.definiteIndex))
+ } else {
+ asrOtherList[msg!] = (text,model.definiteIndex)
+ }
+ asrOtherText = asrOtherList.compactMap({ (str,idx) in
+ return str
+ }).joined(separator: "\n")
+
+ asrOtherCallback?(asrOtherText)
+ }
+
+ }
+ } stateChange: { [weak self] code in
+ DCLogger.debug("状态改变",code)
+ self?.codeCallback?(code.rawValue)
+ } finished: {[weak self] filePath in
+ DCLogger.debug("文件录音保存路径 \(filePath ?? "")")
+ self?.filePathCallBack?(filePath)
+ }
+
+ //通话录音声道数。1:单声道 ;2:⽴体声;默认单声道
+ StarburstConfig.shared().callRecordChannel = 2
+ //收到sdk传过来的opus音频数据,传到OpusManager解码。解码过程是异步
+ StarburstSdk.shared().outputOpusData {[weak self] (config, opusData) in
+ DispatchQueue.global().async {
+ self?.opusCallBack?(opusData!)
+ }
+ }
+ }
+
+ public func inputPcm(data:Data){
+ StarburstSdk.shared().inputPcmData(data)
+ }
+
+ /// 0x00实时录音,0x0c通话录音
+ public func start(){
+
+ asrList = []
+ asrText = ""
+
+
+ asrOtherList = []
+ asrOtherText = ""
+
+ setupRecord()
+ let config = StarburstBleAsrConfig()
+ config.type = 0x0c
+ StarburstSdk.shared().startDeviceRecord(config)
+
+ }
+ public func stop(){
+ StarburstSdk.shared().stopDeviceRecord()
+ }
+}
--- /dev/null
+//
+// DCChat.swift
+// Example
+//
+// Created by liangshi on 2025/12/15.
+//
+
+import StarburstSdk
+
+public class DCRole{
+ /// 音色id
+ public var sid:String = ""
+ /// 名称
+ public var name:String = ""
+ /// 类型
+ public var type:String = ""
+ /// 角色
+ public var role:String = ""
+
+ public init(){
+
+ }
+
+ public init(sid: String, name: String, type: String, role: String) {
+ self.sid = sid
+ self.name = name
+ self.type = type
+ self.role = role
+ }
+}
+
+public class DCChat{
+ public static let shared = DCChat()
+ var speakerList = [DCRole]()
+ public var dialogId = 0
+ /// 识别回调
+ public var asrCallback:((String,Int)->Void)?
+ /// 回复回调
+ public var responseCallback:((String,Int)->Void)?
+ /// 对话语音回调
+ public var dataCallback:((Int,Data?,Bool,Int)->Void)?
+ /// 状态码回调
+ public var codeCallback:((Int)->Void)?
+ /// 结束对话回调
+ public var finishCallback:((String?)->Void)?
+
+ /// 智能体
+ public var role:DCRole?
+ /// 是否进⾏Tts,默认false
+ public var tts:Bool = true
+ /// 默认pcm。⽀持pcm / ogg_opus / mp3
+ public var ttsAudioFormat:String = "pcm"
+ /// 语⾔编码,默认为普通话(zh-CN)
+ public var language:String = "zh-CN"
+
+ init() {
+ setupChat()
+ }
+}
+extension DCChat{
+ public func getVcSpeekerList(finished:@escaping ([DCRole]?,Bool)->Void){
+ StarburstSdk.shared().getVcSpeekerList { (list, success) in
+ if success,let list = list {
+ var temp = [DCRole]()
+ for item in list {
+ let role = DCRole()
+ role.sid = item.sid
+ role.name = item.name
+ role.type = item.type
+ role.role = item.role
+ temp.append(role)
+ }
+ finished(temp,success)
+ }
+ else{
+ finished(nil,success)
+ }
+
+ }
+ }
+
+ func setupChat(){
+ let config = StarburstVoiceChatConfig()
+ config.tts = tts
+ config.ttsAudioFormat = ttsAudioFormat
+ if let speaker = role {
+ // config.role = "spongebob"
+ // config.ttsSpeakerType = "default"
+ // config.ttsSpeakerId = "BV063_streaming"
+ config.role = speaker.role
+ config.ttsSpeakerType = speaker.type
+ config.ttsSpeakerId = speaker.sid
+ }
+
+ StarburstSdk.shared().setupVoiceChat(with: config) { dialogId in
+ DCLogger.debug("开始对话 = \(dialogId)")
+ } textCallback: {[weak self] model in
+ guard let self = self else { return }
+ guard let textModel = model else { return }
+ self.dialogId = textModel.dialogId
+ DCLogger.debug("[recv] = \(textModel.dialogId),\(textModel.conversationFinish),\(textModel.sequence),\(textModel.textResult),\(textModel.responseText)")
+ if let text = textModel.textResult{
+ //DCLogger.debug("[send] = \(textModel.sequence),\(text)")
+ asrCallback?(text,self.dialogId)
+ }
+ else if let text = textModel.responseText{
+ //DCLogger.debug("[recv] = \(textModel.sequence),\(text)")
+ responseCallback?(text,self.dialogId)
+ }
+
+ } responseVoice: { [weak self] (dialogId,data, finish,sampleRate) in
+ guard let self = self else { return }
+ self.dialogId = dialogId
+ dataCallback?(dialogId,data,finish,sampleRate)
+ } stateChange: {[weak self] code in
+ DCLogger.debug("状态改变 \(code)")
+ self?.codeCallback?(code.rawValue)
+ } finished: {[weak self] filePath in
+ DCLogger.debug("结束对话")
+ self?.finishCallback?(filePath)
+ }
+ }
+
+ public func startChat(){
+ setupChat()
+ DCDevice.shared.startChat()
+ }
+ public func stopChat(){
+ StarburstSdk.shared().stopVoiceChat(self.dialogId)
+ }
+ public func startPlayTtsAudio(){
+ StarburstSdk.shared().startPlayTtsAudio(self.dialogId)
+ }
+ public func stopPlayTtsAudio(){
+ StarburstSdk.shared().stopPlayTtsAudio(self.dialogId)
+ }
+}
--- /dev/null
+//
+// Untitled.swift
+// Example
+//
+// Created by liangshi on 2025/12/29.
+//
+
+import StarburstSdk
+
+
+public class DCResponseModel {
+ public var text:String = ""
+ public var index:Int = 0
+ public var definite:Bool = false
+
+ init(text: String, index: Int, definite: Bool) {
+ self.text = text
+ self.index = index
+ self.definite = definite
+ }
+}
+
+public class DCChinse2En {
+ public static let shared = DCChinse2En()
+ /// 语⾔编码,默认为普通话(zh-CN),auto_lang自动识别
+ public var fromLanguage:String = "zh-CN"
+ /// ⽬标语⾔编码,默认为英语(en-US),auto_lang自动识别
+ public var toLanguage:String = "en-US"
+ /// 是否翻译,默认false。如果为true翻译源语言和目标语言不能是同一种语言
+ public var isTranslate = false
+ /// 是否进⾏Tts,默认false
+ public var isTTs = false
+ /// 默认pcm ⽀持pcm / ogg_opus / mp3
+ public var ttsFormat = "pcm"
+ /// 识别回调
+ public var asrCallback:((DCResponseModel)->Void)?
+ /// 翻译回调
+ public var translateCallback:((DCResponseModel)->Void)?
+ /// 翻译语音回调
+ public var translateDataCallback:((Data)->Void)?
+ /// 状态码回调
+ public var codeCallback:((Int)->Void)?
+ /// 打断
+ public var interruptionCallBack:(()->Void)?
+ /// 录音文件回调
+ public var filePathCallBack:((String?)->Void)?
+
+ var asrList : [(String,Int)] = []
+ var asrText = ""
+
+ var translateList : [(String,Int)] = []
+ var translateText = ""
+
+ public func start(){
+ let config = StarburstAsrConfig()
+ config.isTranslate = isTranslate
+ config.fromLanguage = fromLanguage
+ config.toLanguage = toLanguage
+ config.isTTs = isTTs
+ config.ttsFormat = ttsFormat
+ asrList = []
+ asrText = ""
+
+ translateList = []
+ translateText = ""
+
+ StarburstSdk.shared().startRecordAsr(config) {voiceData in
+ //DCLogger.debug("录音的音频流 = \(voiceData!)")
+ } recognizeText: {[weak self] model in
+ guard let self = self else {return}
+ guard let model = model else {return}
+
+ if let text = model.textResult,!text.isEmpty{
+// DCLogger.debug("asr = \(text)")
+ asrCallback?(DCResponseModel(text: text, index: model.definiteIndex, definite: model.definite))
+ }
+ if let translate = model.translateResult,let text = translate.text,!text.isEmpty{
+// DCLogger.debug("translate = \(text)")
+ translateCallback?(DCResponseModel(text: text, index: Int(translate.definiteIndex), definite: translate.definite))
+ }
+ if let ttsData = model.ttsResult?.streamPiece {
+ if let data = Data(base64Encoded: ttsData){
+ translateDataCallback?(data)
+ }
+ }
+ } stateChange: {[weak self] code in
+ DCLogger.debug("状态改变",code)
+ self?.codeCallback?(code.rawValue)
+ } interruption: { [weak self] in
+ self?.interruptionCallBack?()
+ }
+ }
+ public func stop(){
+ StarburstSdk.shared().stopRecordAsr {[weak self] filePath in
+ DCLogger.debug("文件录音保存路径 \(filePath ?? "")")
+ self?.filePathCallBack?(filePath)
+ }
+
+ }
+}
--- /dev/null
+//
+// DCDevice.swift
+// DeepChordsSdk
+//
+// Created by liangshi on 2025/11/25.
+//
+
+import Foundation
+
+public class DCDevice{
+ public static let shared = DCDevice()
+
+ /// ai事件回调
+ /// 0x01(打开AI对话)
+// 0x02(关闭AI对话)
+// 0x03(打开耳机录音)
+// 0x04(关闭耳机录音)
+ public var eventCallback:((UInt8)->Void)?
+
+ public var muiscPlayCallback:((UInt16,UInt16,UInt16)->Void)?
+
+ ///
+ func receiveNotice(_ data:Data){
+ if data[1] == 0x10,data[2] == 0x06{
+ let index = UInt16(data[3...4].int)
+ let pro = UInt16(data[5...6].int)
+ let total = UInt16(data[7...8].int)
+ DCLogger.debug("播放进度index = \(index),total = \(total),pro = \(pro)")
+ muiscPlayCallback?(index,total,pro)
+ }
+ }
+}
+ extension DCDevice{
+ public func handShake(finished:@escaping ((Bool)?)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x11
+ var data:UInt8 = 0x00
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = {[weak self] result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ finished(true)
+ }
+ else{
+ DCLogger.debug("握手失败")
+ finished(false)
+ self?.handShake(finished: finished)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ ///
+ ///
+ public func getBatery(finished:@escaping ((Int,Int)?)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x09
+ var data:UInt8 = 0x00
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let leftValue = result.data[3].int
+ let rightValue = result.data[5].int
+ DCLogger.debug(leftValue,rightValue)
+ finished((leftValue,rightValue))
+ }
+ else{
+ finished(nil)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func getSoftVersion(finished:@escaping (String?)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0A
+ var data:UInt8 = 0x00
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let data = result.data[2...6]
+ let text = String(data: data, encoding:.utf8)
+ DCLogger.debug(text ?? "")
+ finished((text))
+ }
+ else{
+ finished(nil)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func getHardVersion(finished:@escaping (String?)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0A
+ var data:UInt8 = 0x01
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let data = result.data[2...6]
+ let text = String(data: data, encoding:.utf8)
+ DCLogger.debug(text ?? "")
+ finished((text))
+ }
+ else{
+ finished(nil)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+
+ /// state 0关闭,1打开
+ public func findDevice(state:UInt8,finished:@escaping (Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0B
+ var data:UInt8 = state
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = result.data[2].int
+ DCLogger.debug(value)
+ finished(true)
+ }
+ else{
+ finished(false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+
+ /// type, 0x00(正常模式)
+ // 0x01(流行)
+ // 0x02(经典)
+ // 0x03(爵士)
+ // 0x04(摇滚)
+ // 0x05(自定义)
+ public func setEQ(type:UInt8,finished:@escaping (Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0C
+ var data:UInt8 = type
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = result.data[2].int
+ DCLogger.debug(value)
+ finished(value == 0)
+ }
+ else{
+ finished(false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ /// vaue,只有自定义才有,索引 0-9(对应10段EQ调节)(-12~12)
+ public func setCustomEQ(index:UInt8,value:Int,finished:@escaping (Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0C
+ var data:UInt8 = 0x06
+ var index:UInt8 = UInt8(index)
+ let int8Value: Int8 = Int8(value)
+ let valueData = withUnsafeBytes(of: int8Value) { Data($0) }
+
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&index, count: 1)
+ total.append(valueData)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = result.data[2].int
+ DCLogger.debug(value)
+ finished(value == 0)
+ }
+ else{
+ finished(false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func getEQ(finished:@escaping ((type:UInt8,value:[Int])?,Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0E
+ var data:UInt8 = 0x00
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let type = UInt8(result.data[2].int)
+ DCLogger.debug(type)
+ if type == 5 {
+ let data = result.data[3...12]
+ let int8Array = data.map { byte in
+ return Data([byte]).toInt8()
+ }
+ print(int8Array)
+ let list = int8Array.map{Int($0)}
+ finished((type,list),true)
+
+
+ }
+ else{
+ finished((type,[]),true)
+ }
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+}
+extension Data {
+ func toInt8() -> Int8 {
+ var int8Result: Int8 = 0
+ self.withUnsafeBytes {
+ int8Result = $0.load(as: Int8.self)
+ }
+ return int8Result
+ }
+}
+
+extension DCDevice{
+ //0x01(打开AI对话)
+// 0x02(关闭AI对话)
+// 0x03(打开耳机录音)
+// 0x04(关闭耳机录音)
+ func sendAiEventResponse(_ event:UInt8){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0F
+ var data:UInt8 = 0x0B
+ var content:UInt8 = event
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ }
+ DCBleManager.shared.send(sender)
+ sender.deinitTimer()//不需要回执
+ sender.remove()
+ }
+ func startChat(){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0F
+ var data:UInt8 = 0x0A
+ var content:UInt8 = 0x01
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ }
+ DCBleManager.shared.send(sender)
+ }
+ func stopChat(){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x0F
+ var data:UInt8 = 0x0A
+ var content:UInt8 = 0x00
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ }
+ DCBleManager.shared.send(sender)
+ }
+}
--- /dev/null
+//
+// LogManager.swift
+// Example
+//
+// Created by liangshi on 2025/11/24.
+//
+
+import Foundation
+
+/// 日记管理
+public class DCLogger {
+ static var isDebug: Bool = true
+
+ fileprivate static let shared = DCLogger()
+ private var fileHandle:FileHandle?
+ private init() {
+ let path = getPath()
+ fileHandle = FileHandle(forWritingAtPath: path)!
+ //fileHandle?.seekToEndOfFile()
+ }
+
+ fileprivate var dateString: String { Date().format(.full) }
+
+ public static var logs: [String] = []
+
+
+ private func getPath()->String{
+ let foldPath = NSHomeDirectory() + "/Documents/"
+ let fileManager = FileManager.default
+ if !fileManager.fileExists(atPath: foldPath) {
+ do {
+ try FileManager.default.createDirectory(atPath: foldPath, withIntermediateDirectories: true, attributes: nil)
+ } catch {
+ return ""
+ }
+ }
+ let path = foldPath + "Example_\(Date().format(.middle)).log"
+ if !FileManager.default.fileExists(atPath: path) {
+ FileManager.default.createFile(atPath: path, contents: nil, attributes: nil)
+
+ }
+ return path
+ }
+}
+
+extension DCLogger {
+ public static func debug(_ logs: Any..., line: Int = #line, separator: String = " ", terminator: String = "\n") {
+ objc_sync_enter(DCLogger.shared)
+ if DCLogger.isDebug {
+ print(DCLogger.shared.dateString, terminator: " [DeepChordsSdk-\(String(format: "%03d", line))]: ")
+ print(logs, separator: separator, terminator: terminator)
+ let logString = DCLogger.shared.dateString + " [DeepChordsSdk-\(String(format: "%03d", line))]: " + logs.map({ "\($0)" }).joined(separator: separator) + terminator
+ Self.logs.append(logString)
+ DCLogger.shared.saveLog(log: logString)
+ }
+ objc_sync_exit(DCLogger.shared)
+
+
+ }
+
+ private func saveLog(log:String){
+ fileHandle?.write(log.data(using: .utf8)!)
+ }
+}
--- /dev/null
+//
+// DCMusic.swift
+// Example
+//
+// Created by liangshi on 2025/12/17.
+//
+import Foundation
+
+public class DCMusic:Codable{
+ /// id
+ public var id:UInt16 = 0
+ /// 名字
+ public var name:String = ""
+ /// 大小
+ public var size:Int = 0
+ /// 时长
+ public var dur:Int = 0
+}
+
+extension DCDevice{
+
+ public func getTotalMusic(finished:@escaping (Int?)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x08
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = result.data[3...4].int
+ DCLogger.debug(value)
+ finished(value)
+ }
+ else{
+ finished(nil)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func getMusicList(size:UInt8,index:UInt16,finished:@escaping ([DCMusic]?,Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x01
+ var pageSize = size
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&pageSize, count: 1)
+ total.appendInt16(index)
+ total.addCrc()
+
+ var totalList = [DCMusic]()
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ //let data = DCBleManager.contentData(result.data)
+ if result.data.count <= 8{
+ sender.deinitTimer()
+ sender.remove()
+ finished(nil,false)
+ return
+ }
+
+ let index = result.data[3].int
+ let total = result.data[4].int
+ DCLogger.debug(total,index)
+ let data = result.data.subdata(in: 5..<result.data.count - 3)
+ let str = String(data: data, encoding: .utf8)
+ DCLogger.debug(str ?? "")
+ guard let list = JSON.decode([DCMusic].self, from: data) else {
+ sender.deinitTimer()
+ sender.remove()
+ finished(nil,false)
+ return
+ }
+ totalList += list
+
+ if index == total {
+ sender.deinitTimer()
+ sender.remove()
+ finished(totalList,true)
+ }
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+
+ // 0x00:顺序循环
+ // 0x01:随机
+ // 0x02:单曲
+ public func setMusicPlayMode(mode:UInt8,finished:@escaping (Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x02
+ var mode:UInt8 = mode
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&mode, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = result.data[2].int
+ DCLogger.debug(value)
+ finished(value == 0)
+ }
+ else{
+ finished(false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func getMusicPlayMode(finished:@escaping (UInt8?,Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x03
+ var content:UInt8 = 0x00
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt8(result.data[3].int)
+ DCLogger.debug(value)
+ finished(value,true)
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+
+ public func musicPlay(index:UInt16?,finished:@escaping (UInt16?,Bool)->Void){
+ if let index = index {
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x05
+
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.appendInt16(index)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt16(result.data[3...4].int)
+ DCLogger.debug(value)
+ finished(value,true)
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ else{
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x04
+ var content:UInt8 = 0x00
+
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt16(result.data[3...4].int)
+ DCLogger.debug(value)
+ finished(value,true)
+ }
+ else{
+ finished(nil,false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ }
+ public func musicPause(finished:@escaping (Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x04
+ var content:UInt8 = 0x01
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ finished(true)
+ }
+ else{
+ finished(false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+ public func musicDelete(list:[UInt16],finished:@escaping (Bool)->Void){
+ var head: UInt8 = 0xBA
+ var cmd: UInt8 = 0x10
+ var data:UInt8 = 0x07
+ var content:UInt8 = UInt8(list.count)
+ var total = Data()
+ total.append(&head, count: 1)
+ total.append(&cmd, count: 1)
+ total.append(&data, count: 1)
+ total.append(&content, count: 1)
+ for item in list {
+ total.appendInt16(item)
+ }
+ total.addCrc()
+
+ let sender = BleSender()
+ sender.data = total
+ sender.completion = { result in
+ DCLogger.debug("\(result.description)")
+ if result.isSuccess{
+ let value = UInt16(result.data[3].int)
+ DCLogger.debug(value)
+ finished(value == 0)
+ }
+ else{
+ finished(false)
+ }
+ }
+ DCBleManager.shared.send(sender)
+ }
+
+}
--- /dev/null
+//
+// DC.swift
+// Example
+//
+// Created by liangshi on 2025/12/9.
+//
+import StarburstSdk
+
+public class DCPhoneRecord {
+ public static let shared = DCPhoneRecord()
+ /// 语⾔编码,默认为普通话(zh-CN),auto_lang自动识别
+ public var fromLanguage:String = "zh-CN"
+ /// ⽬标语⾔编码,默认为英语(en-US),auto_lang自动识别
+ public var toLanguage:String = "en-US"
+ /// 是否翻译,默认false。如果为true翻译源语言和目标语言不能是同一种语言
+ public var isTranslate = false
+ /// 是否进⾏Tts,默认false
+ public var isTTs = false
+ /// 默认pcm ⽀持pcm / ogg_opus / mp3
+ public var ttsFormat = "pcm"
+ /// 识别回调
+ public var asrCallback:((String)->Void)?
+ /// 翻译回调
+ public var translateCallback:((String)->Void)?
+ /// 翻译语音回调
+ public var translateDataCallback:((Data)->Void)?
+ /// 状态码回调
+ public var codeCallback:((Int)->Void)?
+ /// 打断
+ public var interruptionCallBack:(()->Void)?
+ /// 录音文件回调
+ public var filePathCallBack:((String?)->Void)?
+
+ var asrList : [(String,Int)] = []
+ var asrText = ""
+
+ var translateList : [(String,Int)] = []
+ var translateText = ""
+
+ public func start(){
+ let config = StarburstAsrConfig()
+ config.isTranslate = isTranslate
+ config.fromLanguage = fromLanguage
+ config.toLanguage = toLanguage
+ config.isTTs = isTTs
+ config.ttsFormat = ttsFormat
+ asrList = []
+ asrText = ""
+
+ translateList = []
+ translateText = ""
+
+ StarburstSdk.shared().startRecordAsr(config) {voiceData in
+ //DCLogger.debug("录音的音频流 = \(voiceData!)")
+ } recognizeText: {[weak self] model in
+ guard let self = self else {return}
+ guard let model = model else {return}
+
+ if let text = model.textResult,!text.isEmpty{
+ DCLogger.debug("asr = \(text)")
+ let msg = asrList.firstIndex (where: { (str,idx) in
+ return idx == model.definiteIndex;
+ })
+ if (msg == nil) {
+ asrList.append((text,model.definiteIndex))
+ } else {
+ asrList[msg!] = (text,model.definiteIndex)
+ }
+ asrText = asrList.compactMap({ (str,idx) in
+ return str
+ }).joined(separator: "\n")
+
+ asrCallback?(asrText)
+ }
+ if let translate = model.translateResult,let text = translate.text,!text.isEmpty{
+ DCLogger.debug("translate = \(text)")
+ let msg = translateList.firstIndex (where: { (str,idx) in
+ return idx == translate.definiteIndex;
+ })
+ if (msg == nil) {
+ translateList.append((text,Int(translate.definiteIndex)))
+ } else {
+ translateList[msg!] = (text,Int(translate.definiteIndex))
+ }
+ translateText = translateList.compactMap({ (str,idx) in
+ return str
+ }).joined(separator: "\n")
+
+ translateCallback?(translateText)
+ }
+ if let ttsData = model.ttsResult?.streamPiece {
+ if let data = Data(base64Encoded: ttsData){
+ translateDataCallback?(data)
+ }
+ }
+ } stateChange: {[weak self] code in
+ DCLogger.debug("状态改变",code)
+ self?.codeCallback?(code.rawValue)
+ } interruption: { [weak self] in
+ self?.interruptionCallBack?()
+ }
+ }
+ public func stop(){
+ StarburstSdk.shared().stopRecordAsr {[weak self] filePath in
+ DCLogger.debug("文件录音保存路径 \(filePath ?? "")")
+ self?.filePathCallBack?(filePath)
+ }
+
+ }
+}
--- /dev/null
+//
+// Data.swift
+// Example
+//
+// Created by liangshi on 2025/11/24.
+//
+import Foundation
+
+extension Data {
+ static func dataWithHexString(_ hexStr: String) -> Data {
+ let hexStrWithoutSpaces = hexStr.replacingOccurrences(of: " ", with: "")
+ let lowercasedHexStr = hexStrWithoutSpaces.lowercased()
+ let len = lowercasedHexStr.count
+ if len == 0 {
+ return Data()
+ }
+
+ let utf16Chars = lowercasedHexStr.utf16
+
+ var result = Data()
+ var bytes: UInt8
+ var str = [CChar](repeating: 0, count: 3)
+ for i in 0..<len / 2 {
+ str[0] = CChar(utf16Chars[utf16Chars.index(utf16Chars.startIndex, offsetBy: 2 * i)])
+ str[1] = CChar(utf16Chars[utf16Chars.index(utf16Chars.startIndex, offsetBy: 2 * i + 1)])
+ bytes = UInt8(strtoul(str, nil, 16))
+ result.append(&bytes, count: 1)
+ }
+ return result
+ }
+
+ static func crc8(_ data: Data) -> UInt8 {
+ var crc: UInt8 = 0
+ for byte in data {
+ crc ^= byte
+ for _ in 0..<8 {
+ if crc & 0x01 != 0 {
+ crc = (crc >> 1) ^ 0x8C
+ } else {
+ crc >>= 1
+ }
+ }
+ }
+ return crc
+ }
+
+ mutating func addCrc(){
+ var len = UInt16(self.count - 2)
+ self.appendInt16(len)
+ var crc = Data.crc8(self)
+ self.append(&crc, count: 1)
+ }
+
+// mutating func addCrc(){
+// var list = self.map({ $0 })
+// var crc = chargestore_crc8(list, len: list.count)
+// self.append(&crc, count: 1)
+// }
+
+ mutating func appendInt16(_ value:UInt16){
+ var byte1 = UInt8(value & 0xFF)
+ var byte2 = UInt8((value >> 8) & 0xFF)
+ self.append(&byte1, count: 1)
+ self.append(&byte2, count: 1)
+
+ }
+}
+
+
+func chargestore_crc8(_ ptr: UnsafePointer<UInt8>, len: Int) -> UInt8 {
+ var crc: UInt8 = 0
+ var length = len
+ var currentPtr = ptr
+
+ while length > 0 {
+ crc ^= currentPtr.pointee
+ currentPtr = currentPtr.advanced(by: 1)
+ length -= 1
+
+ for _ in 0..<8 {
+ if crc & 0x01 != 0 {
+ crc = (crc >> 1) ^ 0x8C
+ } else {
+ crc >>= 1
+ }
+ }
+ }
+ return crc
+}
+
+class JSON {
+ /// JSON decode
+ static func decode<T: Decodable>(_ decodable: T.Type, from data: Data) -> T? {
+ do {
+ return try JSONDecoder().decode(decodable.self, from: data)
+ } catch { }
+ return nil
+ }
+
+ /// JSON decode
+ static func decode<T: Decodable>(_ decodable: T.Type, from jsonString: String) -> T? {
+ guard let data = jsonString.data(using: .utf8) else { return nil }
+ return decode(decodable, from: data)
+ }
+}
--- /dev/null
+//
+// Date.swift
+// Example
+//
+// Created by liangshi on 2025/11/24.
+//
+
+
+import Foundation
+
+// MARK: - Extension Date
+extension Date {
+
+ static let formatter = DateFormatter()
+
+ struct Format {
+
+ let rawValue: String
+ init(_ rawValue: String) {
+ self.rawValue = rawValue
+ }
+
+ /// e.g. 01:01:01
+ static let time: Format = .init("HH:mm:ss")
+
+ /// e.g. 01:01
+ static let shortTime: Format = .init("HH:mm")
+
+ /// e.g. 01-01
+ static let date: Format = .init("MM-dd")
+
+ /// e.g. 01月01日
+ static let date1: Format = .init("MM月dd日")
+
+ /// e.g. 2020-01-01
+ static let short: Format = .init("yyyy-MM-dd")
+
+
+ /// e.g. 2020年01月01日
+ static let short1: Format = .init("yyy年MM月dd日")
+
+ /// e.g. 2020-01-01 01:01
+ static let middle: Format = .init("yyyy-MM-dd HH:mm")
+
+ /// e.g. 2020年01月01日 01:01
+ static let middle1: Format = .init("yyy年MM月dd日 HH:mm")
+
+ /// e.g. 2020-01-01 01:01:01
+ static let long: Format = .init("yyyy-MM-dd HH:mm:ss")
+
+ /// e.g. 2020年01月01日 01:01:01
+ static let long1: Format = .init("yyyy年MM月dd日 HH:mm:ss")
+
+ /// e.g. 2020-01-01 01:01:01.088
+ static let full: Format = .init("yyyy-MM-dd HH:mm:ss.SSS")
+
+ /// e.g. 2020年01月01日 01:01:01.088
+ static let full1: Format = .init("yyyy年MM月dd日 HH:mm:ss.SSS")
+ static let full2: Format = .init("yyyy-MM-ddTHH:mm")
+ static let full3: Format = .init("yyyy-MM-dd HH:mm")
+ static let full4: Format = .init("yyyyMMdd00000000")
+ static let full5: Format = .init("yyyyMMddHHmmss")
+ static let full6: Format = .init("yyyyMMddHHmmssSSS")
+ }
+
+ /// 格式化成本地时间
+ func format(_ format: Date.Format = .middle) -> String {
+ Self.formatter.dateFormat = format.rawValue
+ return Self.formatter.string(from: self)
+ }
+
+ enum Unit {
+ case minute(Int)
+ case hour(Int)
+ case day(Int)
+
+ /// 转换成秒
+ var second: TimeInterval {
+ switch self {
+ case .minute(let minute): return 60.0 * Double(minute)
+ case .hour(let hour): return 60.0 * 60.0 * Double(hour)
+ case .day(let day): return 60.0 * 60.0 * 24.0 * Double(day)
+ }
+ }
+ }
+}
+
+let today: Date = .init()
+
+/// 本地化
+extension Date {
+ /// 星期几
+ enum Week: Int {
+ /// 星期日
+ case sun = 1
+ /// 星期一
+ case mon
+ /// 星期二
+ case tue
+ /// 星期三
+ case wed
+ /// 星期四
+ case thur
+ /// 星期五
+ case fri
+ /// 星期六
+ case sat
+ }
+
+ // /// 当天的第一秒
+ // var fromTimeInterval: TimeInterval {
+ // let today = format(.short)
+ // return today.timeIntervalSince1970(.short)
+ // }
+ //
+ // /// 当天最后一秒
+ // var toTimeInterval: TimeInterval { fromTimeInterval + Unit.day(1).second }
+
+ /// 哪一年
+ var year: Int { component(.year) }
+
+ /// 哪个月
+ var month: Int { component(.month) }
+
+ /// 当月的第几天
+ var day: Int { component(.day) }
+
+ /// 当月的第几天
+ var hour: Int { component(.hour)}
+
+ /// 当月的第几天
+ var minute: Int { component(.minute)}
+
+ /// 当月的第几天
+ var second: Int { component(.second)}
+
+ /// 当月的第几周
+ var weekOfMonth: Int { component(.weekOfMonth) }
+
+ /// 今年的第几周
+ var weekOfYear: Int { component(.weekOfYear) }
+
+ /// 星期几
+ var weekDay: Week { Week(rawValue: component(.weekday))! }
+
+ /// 假设当天是周五,表示本月的第几个周五
+ var weekdayOrdinal: Int { component(.weekdayOrdinal) }
+
+ private func component(_ component: Calendar.Component) -> Int {
+ return Calendar.autoupdatingCurrent.component(component, from: self)
+ }
+}
--- /dev/null
+//
+// DeepChords.swift
+// DeepChordsSdk
+//
+// Created by liangshi on 2025/11/25.
+//
+import Foundation
+import StarburstSdk
+public class DeepChordsAiSdk{
+ public static let shared = DeepChordsAiSdk()
+ public var authCallback: ((Int,String) -> Void)?
+ public var sdkLog:String{
+ return StarburstConfig.shared().logPath
+ }
+ public var isDebug:Bool = false{
+ didSet{
+ StarburstConfig.shared().isDebug = false
+ DCLogger.isDebug = isDebug
+ }
+ }
+
+
+ public func initSDK(){
+
+ StarburstConfig.shared().switch(to: .ble)
+ StarburstConfig.shared().appId = "prjzVnOEpKL1N"
+ StarburstConfig.shared().isDebug = false
+ //MARK: 配置缓存路径
+ StarburstConfig.shared().sdkFolder = NSTemporaryDirectory()
+// StarburstConfig.shared().sdkFolder = NSHomeDirectory() + "/Documents/DeepChordsSdk"
+ // 日志路径
+// StarburstConfig.shared().logPath = logPath()
+ StarburstConfig.shared().logPath = nil
+ //是否下发文字到耳机仓
+ StarburstConfig.shared().enableTextSyncToDevice = false
+ //主从耳机切换是否同步sdk信息到耳机
+ StarburstConfig.shared().enableEarbudsSwitchSync = true
+ //耳机仓表情下发开关
+ StarburstConfig.shared().enableEmotionSyncToDevice = false
+ //添加调试信息
+// StarburstConfig.shared().debugInfo = [
+// "x-use-ppe":"1",
+// "x-tt-env": "ppe_tischarge_test",
+// ]
+ // voicechat配置
+// StarburstConfig.shared().user_custom_prompt_init = "1.用户位置在上海市杨浦区。2.用户名称叫小明。"
+
+ StarburstSdk.shared().authCallback = {[weak self] (code,msg) in
+ self?.authCallback?(Int(code),msg ?? "")
+ }
+ //sdk发给蓝牙设备
+ StarburstSdk.shared().sendToBleCallback = {data in
+ guard let data = data else {return}
+ DCBleManager.shared.sendToStarburst(data)
+ }
+ StarburstSdk.shared().bleRecordStateCallback = {[weak self] state in
+
+ }
+ }
+
+ func logPath()->String{
+ let format = DateFormatter()
+ format.dateFormat = "yyyyMMddHHmmss"
+ let text = format.string(from: Date())
+ return NSHomeDirectory() + "/Documents/StarburstSdk_\(text).log"
+ }
+}
+
+extension DeepChordsAiSdk{
+ public func translate(text:String,from:String,to:String,finished:@escaping ((stream:String,finish:Bool)?)->Void){
+ let con = StarburstTslConfig()
+ con.fromLanguage = from
+ con.toLanguage = to
+
+ StarburstSdk.shared().translateByText(withSplit: text, config: con) { model in
+ guard let model = model else{return}
+ finished((model.llmResponse,model.complete))
+ } error: { error in
+ finished(nil)
+ }
+
+ }
+ public func sumary(text:String,finished:@escaping ((stream:String,finish:Bool)?)->Void){
+
+ StarburstSdk.shared().summaryByText(withSplit: text) { model in
+ guard let model = model else{return}
+ finished((model.llmResponse,model.complete))
+ } error: { error in
+ finished(nil)
+ }
+ }
+ public func cancelTranslateByTextWithSplit(){
+ StarburstSdk.shared().cancelTranslateByTextWithSplit()
+ }
+ public func cancelSummaryByTextWithSplit(){
+ StarburstSdk.shared().cancelSummaryByTextWithSplit()
+ }
+ public func getDeviceName()->String?{
+ let dn = StarburstSdk.shared().getDeviceName()
+ return dn
+ }
+}
--- /dev/null
+# ``DeepChordsSdk``
+
+<!--@START_MENU_TOKEN@-->Summary<!--@END_MENU_TOKEN@-->
+
+## Overview
+
+<!--@START_MENU_TOKEN@-->Text<!--@END_MENU_TOKEN@-->
+
+## Topics
+
+### <!--@START_MENU_TOKEN@-->Group<!--@END_MENU_TOKEN@-->
+
+- <!--@START_MENU_TOKEN@-->``Symbol``<!--@END_MENU_TOKEN@-->
\ No newline at end of file
--- /dev/null
+//
+// DeepChordsSdk.swift
+// DeepChordsSdk
+//
+// Created by lianzi on 2026/1/4.
+//
+
+import Foundation
+
--- /dev/null
+//
+// ReceiveManager.swift
+// DeepChordsSdk
+//
+// Created by liangshi on 2025/11/25.
+//
+import Foundation
+
+class ReceiveManager{
+
+
+ static func receiveData(_ data:Data){
+
+ }
+}
--- /dev/null
+//
+// Untitled.swift
+// Example
+//
+// Created by liangshi on 2025/12/29.
+//
+
--- /dev/null
+//
+// DeepChordsSdkTests.swift
+// DeepChordsSdkTests
+//
+// Created by lianzi on 2026/1/4.
+//
+
+import Testing
+@testable import DeepChordsSdk
+
+struct DeepChordsSdkTests {
+
+ @Test func example() async throws {
+ // Write your test here and use APIs like `#expect(...)` to check expected conditions.
+ }
+
+}
- DeviceKit (5.4.0)
- DGActivityIndicatorView (2.1.1)
- FDFullscreenPopGesture (1.1)
+ - FSPagerView (0.8.3)
- HandyJSON (5.0.2)
- HorizonCalendar (2.0.0)
- IQKeyboardCore (1.0.5)
- DeviceKit (~> 5.4.0)
- DGActivityIndicatorView
- FDFullscreenPopGesture
+ - FSPagerView
- HandyJSON
- HorizonCalendar
- IQKeyboardManagerSwift
- DeviceKit
- DGActivityIndicatorView
- FDFullscreenPopGesture
+ - FSPagerView
- HandyJSON
- HorizonCalendar
- IQKeyboardCore
DeviceKit: bd34bb1766d926c3cc5a5f6e3e9a6dd10148b805
DGActivityIndicatorView: ff2c76073d79692f724863c8dd38685866a03cb6
FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0
+ FSPagerView: 670405b2f18e2a87fa37f20b00de783e562c25a8
HandyJSON: 9e4e236f5d2dbefad5155a77417bbea438201c03
HorizonCalendar: 21e600058a8f4d407c79ef7848beda692c53a484
IQKeyboardCore: 28c8bf3bcd8ba5aa1570b318cbc4da94b861711e
YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
ZipArchive: e25a4373192673e3229ac8d6e9f64a3e5713c966
-PODFILE CHECKSUM: 170365f9acea11a62fa72e8f7904f6acb237a166
+PODFILE CHECKSUM: 8f9cd07b8bd8a2a7a6ddbfd0af6732a71e3766ec
COCOAPODS: 1.16.2
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>NSPrivacyTracking</key>
- <false/>
+ <key>NSPrivacyCollectedDataTypes</key>
+ <array/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
- <array>
- <dict>
- <key>NSPrivacyAccessedAPIType</key>
- <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
- <key>NSPrivacyAccessedAPITypeReasons</key>
- <array>
- <string>E174.1</string>
- </array>
- </dict>
- </array>
- <key>NSPrivacyCollectedDataTypes</key>
<array/>
+ <key>NSPrivacyTracking</key>
+ <false/>
</dict>
</plist>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>NSPrivacyTracking</key>
- <false/>
+ <key>NSPrivacyCollectedDataTypes</key>
+ <array/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
- <array>
- <dict>
- <key>NSPrivacyAccessedAPIType</key>
- <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
- <key>NSPrivacyAccessedAPITypeReasons</key>
- <array>
- <string>E174.1</string>
- </array>
- </dict>
- </array>
- <key>NSPrivacyCollectedDataTypes</key>
<array/>
+ <key>NSPrivacyTracking</key>
+ <false/>
</dict>
</plist>
objects = {
/* Begin PBXBuildFile section */
- 0D54E0612F0A5FDD00A80EE7 /* StarburstSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D54E0602F0A5FDD00A80EE7 /* StarburstSdk.framework */; };
- 3F7602F12EFA8BAB00588C18 /* DeepChordsSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F7602EA2EFA891200588C18 /* DeepChordsSdk.framework */; };
- 3F7602F22EFA8BAB00588C18 /* DeepChordsSdk.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3F7602EA2EFA891200588C18 /* DeepChordsSdk.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 0D54E4482F0A62F700A80EE7 /* DeepChordsSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D54E0EF2F0A61E600A80EE7 /* DeepChordsSdk.framework */; };
3F8F58292EBCA2B800FFC00B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */; };
+ 644D1BB5EDD3EA1D77C57786 /* Pods_DeepChordsSdk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 248D8B53B5A178ACA5867275 /* Pods_DeepChordsSdk.framework */; };
F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3862D5561144E20721225B96 /* Pods_ShenYin.framework */; };
/* End PBXBuildFile section */
+/* Begin PBXContainerItemProxy section */
+ 0D54E1022F0A61E600A80EE7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 3F887B942E38D8DC00C98658 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 0D54E0EE2F0A61E600A80EE7;
+ remoteInfo = DeepChordsSdk;
+ };
+/* End PBXContainerItemProxy section */
+
/* Begin PBXCopyFilesBuildPhase section */
- 3F79C6162E6055E500EC38B9 /* Embed Frameworks */ = {
+ 0D54E4462F0A62D900A80EE7 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
- 3F7602F22EFA8BAB00588C18 /* DeepChordsSdk.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
- 0D54E0602F0A5FDD00A80EE7 /* StarburstSdk.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = StarburstSdk.framework; sourceTree = "<group>"; };
+ 0D54E0EF2F0A61E600A80EE7 /* DeepChordsSdk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DeepChordsSdk.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 248D8B53B5A178ACA5867275 /* Pods_DeepChordsSdk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DeepChordsSdk.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3862D5561144E20721225B96 /* Pods_ShenYin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShenYin.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3F7602EA2EFA891200588C18 /* DeepChordsSdk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DeepChordsSdk.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3F887B9C2E38D8DC00C98658 /* ShenYin.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShenYin.app; sourceTree = BUILT_PRODUCTS_DIR; };
3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
+ 5A92F7DC2CB6E6E69D2AB23E /* Pods-DeepChordsSdk.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DeepChordsSdk.debug.xcconfig"; path = "Target Support Files/Pods-DeepChordsSdk/Pods-DeepChordsSdk.debug.xcconfig"; sourceTree = "<group>"; };
5F5DE5910965D53C2B3405B0 /* Pods-ShenYin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShenYin.debug.xcconfig"; path = "Target Support Files/Pods-ShenYin/Pods-ShenYin.debug.xcconfig"; sourceTree = "<group>"; };
CB933A7969ADF81D59503790 /* Pods-LingQi.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LingQi.debug.xcconfig"; path = "Target Support Files/Pods-LingQi/Pods-LingQi.debug.xcconfig"; sourceTree = "<group>"; };
CE98543C79FAAB6CEF4CBFCA /* Pods-LingQi.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LingQi.release.xcconfig"; path = "Target Support Files/Pods-LingQi/Pods-LingQi.release.xcconfig"; sourceTree = "<group>"; };
+ E7D3DF51BED56E93E4ED8102 /* Pods-DeepChordsSdk.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DeepChordsSdk.release.xcconfig"; path = "Target Support Files/Pods-DeepChordsSdk/Pods-DeepChordsSdk.release.xcconfig"; sourceTree = "<group>"; };
FBA7C30445BB0602D6B92F11 /* Pods-ShenYin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShenYin.release.xcconfig"; path = "Target Support Files/Pods-ShenYin/Pods-ShenYin.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
+/* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */
+ 0D54E4472F0A62D900A80EE7 /* Exceptions for "DeepChordsSdk" folder in "Embed Frameworks" build phase */ = {
+ isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet;
+ buildPhase = 0D54E4462F0A62D900A80EE7 /* Embed Frameworks */;
+ membershipExceptions = (
+ StarburstSdk.framework,
+ );
+ };
+/* End PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */
+
/* Begin PBXFileSystemSynchronizedRootGroup section */
+ 0D54E0F02F0A61E600A80EE7 /* DeepChordsSdk */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ exceptions = (
+ 0D54E4472F0A62D900A80EE7 /* Exceptions for "DeepChordsSdk" folder in "Embed Frameworks" build phase */,
+ );
+ path = DeepChordsSdk;
+ sourceTree = "<group>";
+ };
+ 0D54E0FF2F0A61E600A80EE7 /* DeepChordsSdkTests */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ exceptions = (
+ );
+ path = DeepChordsSdkTests;
+ sourceTree = "<group>";
+ };
3F887B9E2E38D8DC00C98658 /* ShenYin */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
+ 0D54E0EC2F0A61E600A80EE7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 644D1BB5EDD3EA1D77C57786 /* Pods_DeepChordsSdk.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
3F887B992E38D8DC00C98658 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 0D54E4482F0A62F700A80EE7 /* DeepChordsSdk.framework in Frameworks */,
F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */,
- 3F7602F12EFA8BAB00588C18 /* DeepChordsSdk.framework in Frameworks */,
- 0D54E0612F0A5FDD00A80EE7 /* StarburstSdk.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
CE98543C79FAAB6CEF4CBFCA /* Pods-LingQi.release.xcconfig */,
5F5DE5910965D53C2B3405B0 /* Pods-ShenYin.debug.xcconfig */,
FBA7C30445BB0602D6B92F11 /* Pods-ShenYin.release.xcconfig */,
+ 5A92F7DC2CB6E6E69D2AB23E /* Pods-DeepChordsSdk.debug.xcconfig */,
+ E7D3DF51BED56E93E4ED8102 /* Pods-DeepChordsSdk.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */,
3F887B9E2E38D8DC00C98658 /* ShenYin */,
3F8F68802EC1F25700FFC00B /* New Group */,
+ 0D54E0F02F0A61E600A80EE7 /* DeepChordsSdk */,
+ 0D54E0FF2F0A61E600A80EE7 /* DeepChordsSdkTests */,
3F887B9D2E38D8DC00C98658 /* Products */,
34A14A83ECF09370871C891F /* Pods */,
676B86A4BA2639E8694D56B4 /* Frameworks */,
- 0D54E0602F0A5FDD00A80EE7 /* StarburstSdk.framework */,
);
sourceTree = "<group>";
};
isa = PBXGroup;
children = (
3F887B9C2E38D8DC00C98658 /* ShenYin.app */,
+ 0D54E0EF2F0A61E600A80EE7 /* DeepChordsSdk.framework */,
);
name = Products;
sourceTree = "<group>";
children = (
3F7602EA2EFA891200588C18 /* DeepChordsSdk.framework */,
3862D5561144E20721225B96 /* Pods_ShenYin.framework */,
+ 248D8B53B5A178ACA5867275 /* Pods_DeepChordsSdk.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
+/* Begin PBXHeadersBuildPhase section */
+ 0D54E0EA2F0A61E600A80EE7 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
/* Begin PBXNativeTarget section */
+ 0D54E0EE2F0A61E600A80EE7 /* DeepChordsSdk */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 0D54E1042F0A61E600A80EE7 /* Build configuration list for PBXNativeTarget "DeepChordsSdk" */;
+ buildPhases = (
+ 4EDB33B100AD294830EAE06A /* [CP] Check Pods Manifest.lock */,
+ 0D54E0EA2F0A61E600A80EE7 /* Headers */,
+ 0D54E0EB2F0A61E600A80EE7 /* Sources */,
+ 0D54E0EC2F0A61E600A80EE7 /* Frameworks */,
+ 0D54E0ED2F0A61E600A80EE7 /* Resources */,
+ 0D54E4462F0A62D900A80EE7 /* Embed Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ fileSystemSynchronizedGroups = (
+ 0D54E0F02F0A61E600A80EE7 /* DeepChordsSdk */,
+ );
+ name = DeepChordsSdk;
+ productName = DeepChordsSdk;
+ productReference = 0D54E0EF2F0A61E600A80EE7 /* DeepChordsSdk.framework */;
+ productType = "com.apple.product-type.framework";
+ };
3F887B9B2E38D8DC00C98658 /* ShenYin */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3F887BAF2E38D8DD00C98658 /* Build configuration list for PBXNativeTarget "ShenYin" */;
3F887B992E38D8DC00C98658 /* Frameworks */,
3F887B9A2E38D8DC00C98658 /* Resources */,
5A934A35F54A5620CFD3C08A /* [CP] Embed Pods Frameworks */,
- 3F79C6162E6055E500EC38B9 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
+ 0D54E1032F0A61E600A80EE7 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
3F887B9E2E38D8DC00C98658 /* ShenYin */,
LastSwiftUpdateCheck = 1640;
LastUpgradeCheck = 1640;
TargetAttributes = {
+ 0D54E0EE2F0A61E600A80EE7 = {
+ CreatedOnToolsVersion = 16.4;
+ };
3F887B9B2E38D8DC00C98658 = {
CreatedOnToolsVersion = 16.4;
};
projectRoot = "";
targets = (
3F887B9B2E38D8DC00C98658 /* ShenYin */,
+ 0D54E0EE2F0A61E600A80EE7 /* DeepChordsSdk */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
+ 0D54E0ED2F0A61E600A80EE7 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
3F887B9A2E38D8DC00C98658 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
- 5A934A35F54A5620CFD3C08A /* [CP] Embed Pods Frameworks */ = {
+ 4EDB33B100AD294830EAE06A /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
);
- name = "[CP] Embed Pods Frameworks";
+ name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-DeepChordsSdk-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 5A934A35F54A5620CFD3C08A /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-ShenYin/Pods-ShenYin-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 0D54E0EB2F0A61E600A80EE7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
3F887B982E38D8DC00C98658 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
};
/* End PBXSourcesBuildPhase section */
+/* Begin PBXTargetDependency section */
+ 0D54E1032F0A61E600A80EE7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 0D54E0EE2F0A61E600A80EE7 /* DeepChordsSdk */;
+ targetProxy = 0D54E1022F0A61E600A80EE7 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
/* Begin XCBuildConfiguration section */
+ 0D54E1052F0A61E600A80EE7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 5A92F7DC2CB6E6E69D2AB23E /* Pods-DeepChordsSdk.debug.xcconfig */;
+ buildSettings = {
+ BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = G23X75CJ67;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_MODULE_VERIFIER = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/DeepChordsSdk",
+ );
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSHumanReadableCopyright = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MACH_O_TYPE = staticlib;
+ MARKETING_VERSION = 1.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
+ OTHER_LDFLAGS = (
+ "$(inherited)",
+ "-l\"icucore\"",
+ "-framework",
+ "\"CFNetwork\"",
+ "-framework",
+ "\"Security\"",
+ "-framework",
+ "\"SocketRocket\"",
+ "-ObjC",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = lianzi.DeepChordsSdk;
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SKIP_INSTALL = YES;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_INSTALL_MODULE = YES;
+ SWIFT_INSTALL_OBJC_HEADER = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ 0D54E1062F0A61E600A80EE7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = E7D3DF51BED56E93E4ED8102 /* Pods-DeepChordsSdk.release.xcconfig */;
+ buildSettings = {
+ BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = G23X75CJ67;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_MODULE_VERIFIER = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/DeepChordsSdk",
+ );
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSHumanReadableCopyright = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MACH_O_TYPE = staticlib;
+ MARKETING_VERSION = 1.0;
+ MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
+ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
+ OTHER_LDFLAGS = (
+ "$(inherited)",
+ "-l\"icucore\"",
+ "-framework",
+ "\"CFNetwork\"",
+ "-framework",
+ "\"Security\"",
+ "-framework",
+ "\"SocketRocket\"",
+ "-ObjC",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = lianzi.DeepChordsSdk;
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SKIP_INSTALL = YES;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_INSTALL_MODULE = YES;
+ SWIFT_INSTALL_OBJC_HEADER = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
3F887BB02E38D8DD00C98658 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 5F5DE5910965D53C2B3405B0 /* Pods-ShenYin.debug.xcconfig */;
"$(PROJECT_DIR)/ShenYin/SDKBleManager",
"$(PROJECT_DIR)/ShenYin/Ota",
"$(PROJECT_DIR)/ShenYin/Sdk/DcSdk/opus",
+ "$(PROJECT_DIR)/DeepChordsSdk",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShenYin/Info.plist;
"$(PROJECT_DIR)/ShenYin/SDKBleManager",
"$(PROJECT_DIR)/ShenYin/Ota",
"$(PROJECT_DIR)/ShenYin/Sdk/DcSdk/opus",
+ "$(PROJECT_DIR)/DeepChordsSdk",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShenYin/Info.plist;
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ 0D54E1042F0A61E600A80EE7 /* Build configuration list for PBXNativeTarget "DeepChordsSdk" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 0D54E1052F0A61E600A80EE7 /* Debug */,
+ 0D54E1062F0A61E600A80EE7 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
3F887B972E38D8DC00C98658 /* Build configuration list for PBXProject "ShenYin" */ = {
isa = XCConfigurationList;
buildConfigurations = (
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1640"
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES"
+ buildArchitectures = "Automatic">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "0D54E0EE2F0A61E600A80EE7"
+ BuildableName = "DeepChordsSdk.framework"
+ BlueprintName = "DeepChordsSdk"
+ ReferencedContainer = "container:ShenYin.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ shouldAutocreateTestPlan = "YES">
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Release"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "0D54E0EE2F0A61E600A80EE7"
+ BuildableName = "DeepChordsSdk.framework"
+ BlueprintName = "DeepChordsSdk"
+ ReferencedContainer = "container:ShenYin.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
+ <Testables>
+ <TestableReference
+ skipped = "NO"
+ parallelizable = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "0D54E0F82F0A61E600A80EE7"
+ BuildableName = "DeepChordsSdkTests.xctest"
+ BlueprintName = "DeepChordsSdkTests"
+ ReferencedContainer = "container:ShenYin.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
+ </Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
- <FileRef
- location = "container:../DeepChordsSdk_iOS/DeepChordsSdk/Example/Example.xcodeproj">
- </FileRef>
</Workspace>
import Foundation
import UIKit
-//import FSPagerView
+import FSPagerView
final class MineBannerView: BaseView {
private var dataArray = [BannerModel]()
- // private let pagerView = FSPagerView()
- // private let pageControl = FSPageControl()
+ private let pagerView = FSPagerView()
+ private let pageControl = FSPageControl()
public func config(list:[BannerModel]) {
self.dataArray = list
-// self.pageControl.numberOfPages = dataArray.count
-// self.pagerView.reloadData()
+ self.pageControl.numberOfPages = dataArray.count
+ self.pagerView.reloadData()
+ }
+
+ override func setupLayout() {
+ addSubview(pagerView)
+ addSubview(pageControl)
+
+ pagerView.snp.makeConstraints { (m) in
+ m.top.bottom.equalToSuperview()
+ m.left.right.equalToSuperview()
+ }
+ pageControl.snp.makeConstraints { (m) in
+ m.width.equalToSuperview()
+ m.height.equalTo(25)
+ m.bottom.equalToSuperview()
+ m.centerX.equalToSuperview()
+ }
+ }
+ override func setupViews() {
+ backgroundColor = .clear
+ clipsToBounds = true
+ pagerView.do { v in
+ v.dataSource = self
+ v.delegate = self
+ v.interitemSpacing = 18
+ v.bounces = false
+ v.isInfinite = true
+ v.automaticSlidingInterval = 4
+ v.itemSize = CGSize(width: kScreenWid - 36 , height: 126)
+ v.register(PictureViewCell.self, forCellWithReuseIdentifier: "PictureViewCell")
+ }
+
+ pageControl.do { v in
+ v.contentHorizontalAlignment = .center
+ v.hidesForSinglePage = true
+ v.setFillColor(UIColor.white.withAlphaComponent(0.4), for: .normal)
+ v.setFillColor(.white, for: .selected)
+ }
+ config(list: BannerCache.shared.get())
}
}
-// override func setupLayout() {
-// addSubview(pagerView)
-// addSubview(pageControl)
-//
-// pagerView.snp.makeConstraints { (m) in
-// m.top.bottom.equalToSuperview()
-// m.left.right.equalToSuperview()
-// }
-// pageControl.snp.makeConstraints { (m) in
-// m.width.equalToSuperview()
-// m.height.equalTo(25)
-// m.bottom.equalToSuperview()
-// m.centerX.equalToSuperview()
-// }
-// }
-// override func setupViews() {
-// backgroundColor = .clear
-// clipsToBounds = true
-// pagerView.do { v in
-// v.dataSource = self
-// v.delegate = self
-// v.interitemSpacing = 18
-// v.bounces = false
-// v.isInfinite = true
-// v.automaticSlidingInterval = 4
-// v.itemSize = CGSize(width: kScreenWid - 36 , height: 126)
-// v.register(PictureViewCell.self, forCellWithReuseIdentifier: "PictureViewCell")
-// }
-//
-// pageControl.do { v in
-// v.contentHorizontalAlignment = .center
-// v.hidesForSinglePage = true
-// v.setFillColor(UIColor.white.withAlphaComponent(0.4), for: .normal)
-// v.setFillColor(.white, for: .selected)
-// }
-// config(list: BannerCache.shared.get())
-// }
-//}
-//
-//extension MineBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
-// func numberOfItems(in pagerView: FSPagerView) -> Int {
-// return dataArray.count
-// }
-//
-// func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell {
-// let cell = pagerView.dequeueReusableCell(withReuseIdentifier: "PictureViewCell", at: index) as! PictureViewCell
-// let model = dataArray[index]
-// cell.picture.kf.setImage(with: model.cover.yc.asUrl)
-// return cell
-// }
-//
-// func pagerViewWillEndDragging(_ pagerView: FSPagerView, targetIndex: Int) {
-// self.pageControl.currentPage = targetIndex
-// }
-// func pagerViewDidEndScrollAnimation(_ pagerView: FSPagerView) {
-// self.pageControl.currentPage = pagerView.currentIndex
-// }
-//
-// func pagerView(_ pagerView: FSPagerView, didSelectItemAt index: Int){
-// let model = dataArray[index]
-//// if model.jumpType == 0 {
-//// if let url = model.jumpValue.fragmentUrl {
-//// let request = URLRequest(url: url)
-//// let params = BaseWebViewParams(request:request)
-//// let vc = BaseWebViewController(initData: params)
-//// UIViewController.yc.currentNav?.pushViewController(vc, animated: true)
-//// } //UIApplication.shared.canOpenURL(URL(string: ))
-//// }
-// HttpClient.request(.bannerClick(bannerId: model.id)) { (model:BannerModelRoot,res) in
-// }
-//
-// guard let url = model.url.yc.asUrl else{
-// return
-// }
-// UIApplication.shared.open(url)
-// }
-//}
-//
-//fileprivate class PictureViewCell: FSPagerViewCell {
-// let picture = UIImageView()
-//
-// override init(frame: CGRect) {
-// super.init(frame: frame)
-//
-// addSubview(picture)
-//
-// picture.snp.makeConstraints { (m) in
-// m.edges.equalToSuperview()
-// }
-//
-// picture.do { (v) in
-// v.yc.setCornerRadius(8)
+extension MineBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
+ func numberOfItems(in pagerView: FSPagerView) -> Int {
+ return dataArray.count
+ }
+
+ func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell {
+ let cell = pagerView.dequeueReusableCell(withReuseIdentifier: "PictureViewCell", at: index) as! PictureViewCell
+ let model = dataArray[index]
+ cell.picture.kf.setImage(with: model.cover.yc.asUrl)
+ return cell
+ }
+
+ func pagerViewWillEndDragging(_ pagerView: FSPagerView, targetIndex: Int) {
+ self.pageControl.currentPage = targetIndex
+ }
+ func pagerViewDidEndScrollAnimation(_ pagerView: FSPagerView) {
+ self.pageControl.currentPage = pagerView.currentIndex
+ }
+
+ func pagerView(_ pagerView: FSPagerView, didSelectItemAt index: Int){
+ let model = dataArray[index]
+// if model.jumpType == 0 {
+// if let url = model.jumpValue.fragmentUrl {
+// let request = URLRequest(url: url)
+// let params = BaseWebViewParams(request:request)
+// let vc = BaseWebViewController(initData: params)
+// UIViewController.yc.currentNav?.pushViewController(vc, animated: true)
+// } //UIApplication.shared.canOpenURL(URL(string: ))
// }
-//// picture.backgroundColor = .lightGray
-// }
-//
-// required init?(coder aDecoder: NSCoder) {
-// fatalError("init(coder:) has not been implemented")
-// }
-//}
+ HttpClient.request(.bannerClick(bannerId: model.id)) { (model:BannerModelRoot,res) in
+ }
+
+ guard let url = model.url.yc.asUrl else{
+ return
+ }
+ UIApplication.shared.open(url)
+ }
+}
+
+
+fileprivate class PictureViewCell: FSPagerViewCell {
+ let picture = UIImageView()
+
+ override init(frame: CGRect) {
+ super.init(frame: frame)
+
+ addSubview(picture)
+
+ picture.snp.makeConstraints { (m) in
+ m.edges.equalToSuperview()
+ }
+
+ picture.do { (v) in
+ v.yc.setCornerRadius(8)
+ }
+// picture.backgroundColor = .lightGray
+ }
+
+ required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+}
platform :ios, '13.0'
use_frameworks!
+target 'DeepChordsSdk' do
+ use_frameworks!
+ pod 'SocketRocket'
+end
workspace 'ShenYin'
project 'ShenYin.xcodeproj'
pod 'SVProgressHUD'#蒙版
pod 'MBProgressHUD'#蒙版
pod 'Kingfisher', '~> 6.0'#图片下载K
-# pod 'FSPagerView'
+ pod 'FSPagerView'
pod "TabPageViewController" #tabpage
pod 'JXSegmentedView'
pod 'JXPagingView/Paging'