From cb1eb2ec3c446e37295497edd8dde645e516bf90 Mon Sep 17 00:00:00 2001 From: memory <496663675@qq.com> Date: Sun, 4 Jan 2026 17:44:06 +0800 Subject: [PATCH] =?utf8?q?=E9=AA=A8=E4=BC=A0=E5=AF=BCsdk=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- ShenYin/DeepChordsSdk/Any.swift | 194 ++++++++++ ShenYin/DeepChordsSdk/BleSender.swift | 125 +++++++ ShenYin/DeepChordsSdk/DCBleManager.swift | 148 ++++++++ ShenYin/DeepChordsSdk/DCBleRecord.swift | 135 +++++++ ShenYin/DeepChordsSdk/DCCallRecord.swift | 138 +++++++ ShenYin/DeepChordsSdk/DCChat.swift | 137 +++++++ ShenYin/DeepChordsSdk/DCChinse2En.swift | 100 +++++ ShenYin/DeepChordsSdk/DCDevice.swift | 343 ++++++++++++++++++ ShenYin/DeepChordsSdk/DCLogger.swift | 64 ++++ ShenYin/DeepChordsSdk/DCMusic.swift | 272 ++++++++++++++ ShenYin/DeepChordsSdk/DCPhoneRecord.swift | 110 ++++++ ShenYin/DeepChordsSdk/Data.swift | 105 ++++++ ShenYin/DeepChordsSdk/Date.swift | 152 ++++++++ ShenYin/DeepChordsSdk/DeepChordsAiSdk.swift | 102 ++++++ .../DeepChordsSdk.docc/DeepChordsSdk.md | 13 + ShenYin/DeepChordsSdk/DeepChordsSdk.swift | 9 + ShenYin/DeepChordsSdk/ReceiveManager.swift | 15 + .../Headers/AIGCErrorCode.h | 0 .../Headers/StarbaustVoiceChatModel.h | 0 .../Headers/StarburstAsrConfig.h | 0 .../Headers/StarburstAsrModel.h | 0 .../Headers/StarburstConfig.h | 0 .../Headers/StarburstFileAsrModel.h | 0 .../Headers/StarburstOffLineFile.h | 0 .../Headers/StarburstPhoneSdk.h | 0 .../Headers/StarburstSdk.h | 0 .../Headers/StarburstSdkManager.h | 0 .../Headers/StarburstStreamModel.h | 0 .../Headers/StarbusrtSpeaker.h | 0 .../Headers/StartburstDecoderConfig.h | 0 .../Headers/StartburstGlassChat.h | 0 .../Headers/StartburstGlassesSdk.h | 0 .../Headers/StartburstMixSdk.h | 0 .../Headers/TextToImageCallback.h | 0 .../Headers/TextToImageManager.h | 0 .../Headers/TextToSpeechCallback.h | 0 .../Headers/TextToSpeechManager.h | 0 .../StarburstSdk.framework/Info.plist | Bin .../Modules/module.modulemap | 0 .../PrivacyInfo.xcprivacy | 0 .../StarburstSdk.framework/StarburstSdk | Bin .../_CodeSignature/CodeDirectory | Bin .../_CodeSignature/CodeRequirements | Bin .../_CodeSignature/CodeRequirements-1 | Bin .../_CodeSignature/CodeResources | 0 .../_CodeSignature/CodeSignature | Bin ShenYin/DeepChordsSdk/Untitled.swift | 7 + .../DeepChordsSdkTests.swift | 17 + ShenYin/Podfile.lock | 6 +- ShenYin/Pods/Kingfisher/PrivacyInfo.xcprivacy | 17 +- .../Pods/MBProgressHUD/PrivacyInfo.xcprivacy | 17 +- ShenYin/ShenYin.xcodeproj/project.pbxproj | 272 +++++++++++++- .../xcschemes/DeepChordsSdk.xcscheme | 67 ++++ .../xcshareddata/xcschemes/ShenYin.xcscheme | 13 + .../contents.xcworkspacedata | 3 - .../ShenYin/UI/Mine/Root/MineBannerView.swift | 208 +++++------ ShenYin/podfile | 6 +- 57 files changed, 2646 insertions(+), 149 deletions(-) create mode 100644 ShenYin/DeepChordsSdk/Any.swift create mode 100644 ShenYin/DeepChordsSdk/BleSender.swift create mode 100644 ShenYin/DeepChordsSdk/DCBleManager.swift create mode 100644 ShenYin/DeepChordsSdk/DCBleRecord.swift create mode 100644 ShenYin/DeepChordsSdk/DCCallRecord.swift create mode 100644 ShenYin/DeepChordsSdk/DCChat.swift create mode 100644 ShenYin/DeepChordsSdk/DCChinse2En.swift create mode 100644 ShenYin/DeepChordsSdk/DCDevice.swift create mode 100644 ShenYin/DeepChordsSdk/DCLogger.swift create mode 100644 ShenYin/DeepChordsSdk/DCMusic.swift create mode 100644 ShenYin/DeepChordsSdk/DCPhoneRecord.swift create mode 100644 ShenYin/DeepChordsSdk/Data.swift create mode 100644 ShenYin/DeepChordsSdk/Date.swift create mode 100644 ShenYin/DeepChordsSdk/DeepChordsAiSdk.swift create mode 100644 ShenYin/DeepChordsSdk/DeepChordsSdk.docc/DeepChordsSdk.md create mode 100644 ShenYin/DeepChordsSdk/DeepChordsSdk.swift create mode 100644 ShenYin/DeepChordsSdk/ReceiveManager.swift rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/AIGCErrorCode.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarbaustVoiceChatModel.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstAsrConfig.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstAsrModel.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstConfig.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstFileAsrModel.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstOffLineFile.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstPhoneSdk.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstSdk.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstSdkManager.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarburstStreamModel.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StarbusrtSpeaker.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StartburstDecoderConfig.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StartburstGlassChat.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StartburstGlassesSdk.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/StartburstMixSdk.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/TextToImageCallback.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/TextToImageManager.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/TextToSpeechCallback.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Headers/TextToSpeechManager.h (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Info.plist (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/Modules/module.modulemap (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/PrivacyInfo.xcprivacy (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/StarburstSdk (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/_CodeSignature/CodeDirectory (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/_CodeSignature/CodeRequirements (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/_CodeSignature/CodeRequirements-1 (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/_CodeSignature/CodeResources (100%) rename ShenYin/{ => DeepChordsSdk}/StarburstSdk.framework/_CodeSignature/CodeSignature (100%) create mode 100644 ShenYin/DeepChordsSdk/Untitled.swift create mode 100644 ShenYin/DeepChordsSdkTests/DeepChordsSdkTests.swift create mode 100644 ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/DeepChordsSdk.xcscheme diff --git a/ShenYin/DeepChordsSdk/Any.swift b/ShenYin/DeepChordsSdk/Any.swift new file mode 100644 index 0000000..9ecfd13 --- /dev/null +++ b/ShenYin/DeepChordsSdk/Any.swift @@ -0,0 +1,194 @@ +// +// 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.size + guard self.count >= size else { return 0 } + + self.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) -> Void in + _ = memcpy(&floatValue, buffer.baseAddress!, size) + } + + return floatValue + } +} diff --git a/ShenYin/DeepChordsSdk/BleSender.swift b/ShenYin/DeepChordsSdk/BleSender.swift new file mode 100644 index 0000000..fbf60a6 --- /dev/null +++ b/ShenYin/DeepChordsSdk/BleSender.swift @@ -0,0 +1,125 @@ +// +// 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 + } +} diff --git a/ShenYin/DeepChordsSdk/DCBleManager.swift b/ShenYin/DeepChordsSdk/DCBleManager.swift new file mode 100644 index 0000000..21420f4 --- /dev/null +++ b/ShenYin/DeepChordsSdk/DCBleManager.swift @@ -0,0 +1,148 @@ +// +// 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{ + if data.count > 4 && data[0] == 0xBA { + return data.subdata(in: 2..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() + } +} diff --git a/ShenYin/DeepChordsSdk/DCCallRecord.swift b/ShenYin/DeepChordsSdk/DCCallRecord.swift new file mode 100644 index 0000000..b293dd0 --- /dev/null +++ b/ShenYin/DeepChordsSdk/DCCallRecord.swift @@ -0,0 +1,138 @@ +// +// 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() + } +} diff --git a/ShenYin/DeepChordsSdk/DCChat.swift b/ShenYin/DeepChordsSdk/DCChat.swift new file mode 100644 index 0000000..44db924 --- /dev/null +++ b/ShenYin/DeepChordsSdk/DCChat.swift @@ -0,0 +1,137 @@ +// +// 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) + } +} diff --git a/ShenYin/DeepChordsSdk/DCChinse2En.swift b/ShenYin/DeepChordsSdk/DCChinse2En.swift new file mode 100644 index 0000000..c6b114b --- /dev/null +++ b/ShenYin/DeepChordsSdk/DCChinse2En.swift @@ -0,0 +1,100 @@ +// +// 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) + } + + } +} diff --git a/ShenYin/DeepChordsSdk/DCDevice.swift b/ShenYin/DeepChordsSdk/DCDevice.swift new file mode 100644 index 0000000..9b557ed --- /dev/null +++ b/ShenYin/DeepChordsSdk/DCDevice.swift @@ -0,0 +1,343 @@ +// +// 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) + } +} diff --git a/ShenYin/DeepChordsSdk/DCLogger.swift b/ShenYin/DeepChordsSdk/DCLogger.swift new file mode 100644 index 0000000..c605936 --- /dev/null +++ b/ShenYin/DeepChordsSdk/DCLogger.swift @@ -0,0 +1,64 @@ +// +// 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)!) + } +} diff --git a/ShenYin/DeepChordsSdk/DCMusic.swift b/ShenYin/DeepChordsSdk/DCMusic.swift new file mode 100644 index 0000000..afc82d2 --- /dev/null +++ b/ShenYin/DeepChordsSdk/DCMusic.swift @@ -0,0 +1,272 @@ +// +// 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..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) + } + +} diff --git a/ShenYin/DeepChordsSdk/DCPhoneRecord.swift b/ShenYin/DeepChordsSdk/DCPhoneRecord.swift new file mode 100644 index 0000000..4046440 --- /dev/null +++ b/ShenYin/DeepChordsSdk/DCPhoneRecord.swift @@ -0,0 +1,110 @@ +// +// 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) + } + + } +} diff --git a/ShenYin/DeepChordsSdk/Data.swift b/ShenYin/DeepChordsSdk/Data.swift new file mode 100644 index 0000000..d59dcb4 --- /dev/null +++ b/ShenYin/DeepChordsSdk/Data.swift @@ -0,0 +1,105 @@ +// +// 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.. 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, 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(_ decodable: T.Type, from data: Data) -> T? { + do { + return try JSONDecoder().decode(decodable.self, from: data) + } catch { } + return nil + } + + /// JSON decode + static func decode(_ decodable: T.Type, from jsonString: String) -> T? { + guard let data = jsonString.data(using: .utf8) else { return nil } + return decode(decodable, from: data) + } +} diff --git a/ShenYin/DeepChordsSdk/Date.swift b/ShenYin/DeepChordsSdk/Date.swift new file mode 100644 index 0000000..3fd88f0 --- /dev/null +++ b/ShenYin/DeepChordsSdk/Date.swift @@ -0,0 +1,152 @@ +// +// 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) + } +} diff --git a/ShenYin/DeepChordsSdk/DeepChordsAiSdk.swift b/ShenYin/DeepChordsSdk/DeepChordsAiSdk.swift new file mode 100644 index 0000000..9aa91fc --- /dev/null +++ b/ShenYin/DeepChordsSdk/DeepChordsAiSdk.swift @@ -0,0 +1,102 @@ +// +// 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 + } +} diff --git a/ShenYin/DeepChordsSdk/DeepChordsSdk.docc/DeepChordsSdk.md b/ShenYin/DeepChordsSdk/DeepChordsSdk.docc/DeepChordsSdk.md new file mode 100644 index 0000000..c4554ad --- /dev/null +++ b/ShenYin/DeepChordsSdk/DeepChordsSdk.docc/DeepChordsSdk.md @@ -0,0 +1,13 @@ +# ``DeepChordsSdk`` + +Summary + +## Overview + +Text + +## Topics + +### Group + +- ``Symbol`` \ No newline at end of file diff --git a/ShenYin/DeepChordsSdk/DeepChordsSdk.swift b/ShenYin/DeepChordsSdk/DeepChordsSdk.swift new file mode 100644 index 0000000..1f8cd1f --- /dev/null +++ b/ShenYin/DeepChordsSdk/DeepChordsSdk.swift @@ -0,0 +1,9 @@ +// +// DeepChordsSdk.swift +// DeepChordsSdk +// +// Created by lianzi on 2026/1/4. +// + +import Foundation + diff --git a/ShenYin/DeepChordsSdk/ReceiveManager.swift b/ShenYin/DeepChordsSdk/ReceiveManager.swift new file mode 100644 index 0000000..e482cd6 --- /dev/null +++ b/ShenYin/DeepChordsSdk/ReceiveManager.swift @@ -0,0 +1,15 @@ +// +// ReceiveManager.swift +// DeepChordsSdk +// +// Created by liangshi on 2025/11/25. +// +import Foundation + +class ReceiveManager{ + + + static func receiveData(_ data:Data){ + + } +} diff --git a/ShenYin/StarburstSdk.framework/Headers/AIGCErrorCode.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/AIGCErrorCode.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/AIGCErrorCode.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/AIGCErrorCode.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarbaustVoiceChatModel.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarbaustVoiceChatModel.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarbaustVoiceChatModel.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarbaustVoiceChatModel.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstAsrConfig.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstAsrConfig.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstAsrConfig.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstAsrConfig.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstAsrModel.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstAsrModel.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstAsrModel.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstAsrModel.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstConfig.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstConfig.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstConfig.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstConfig.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstFileAsrModel.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstFileAsrModel.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstFileAsrModel.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstFileAsrModel.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstOffLineFile.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstOffLineFile.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstOffLineFile.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstOffLineFile.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstPhoneSdk.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstPhoneSdk.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstPhoneSdk.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstPhoneSdk.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstSdk.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstSdk.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstSdk.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstSdk.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstSdkManager.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstSdkManager.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstSdkManager.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstSdkManager.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarburstStreamModel.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstStreamModel.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarburstStreamModel.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarburstStreamModel.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StarbusrtSpeaker.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarbusrtSpeaker.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StarbusrtSpeaker.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StarbusrtSpeaker.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StartburstDecoderConfig.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StartburstDecoderConfig.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StartburstDecoderConfig.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StartburstDecoderConfig.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StartburstGlassChat.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StartburstGlassChat.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StartburstGlassChat.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StartburstGlassChat.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StartburstGlassesSdk.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StartburstGlassesSdk.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StartburstGlassesSdk.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StartburstGlassesSdk.h diff --git a/ShenYin/StarburstSdk.framework/Headers/StartburstMixSdk.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StartburstMixSdk.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/StartburstMixSdk.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/StartburstMixSdk.h diff --git a/ShenYin/StarburstSdk.framework/Headers/TextToImageCallback.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/TextToImageCallback.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/TextToImageCallback.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/TextToImageCallback.h diff --git a/ShenYin/StarburstSdk.framework/Headers/TextToImageManager.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/TextToImageManager.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/TextToImageManager.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/TextToImageManager.h diff --git a/ShenYin/StarburstSdk.framework/Headers/TextToSpeechCallback.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/TextToSpeechCallback.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/TextToSpeechCallback.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/TextToSpeechCallback.h diff --git a/ShenYin/StarburstSdk.framework/Headers/TextToSpeechManager.h b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/TextToSpeechManager.h similarity index 100% rename from ShenYin/StarburstSdk.framework/Headers/TextToSpeechManager.h rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Headers/TextToSpeechManager.h diff --git a/ShenYin/StarburstSdk.framework/Info.plist b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Info.plist similarity index 100% rename from ShenYin/StarburstSdk.framework/Info.plist rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Info.plist diff --git a/ShenYin/StarburstSdk.framework/Modules/module.modulemap b/ShenYin/DeepChordsSdk/StarburstSdk.framework/Modules/module.modulemap similarity index 100% rename from ShenYin/StarburstSdk.framework/Modules/module.modulemap rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/Modules/module.modulemap diff --git a/ShenYin/StarburstSdk.framework/PrivacyInfo.xcprivacy b/ShenYin/DeepChordsSdk/StarburstSdk.framework/PrivacyInfo.xcprivacy similarity index 100% rename from ShenYin/StarburstSdk.framework/PrivacyInfo.xcprivacy rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/PrivacyInfo.xcprivacy diff --git a/ShenYin/StarburstSdk.framework/StarburstSdk b/ShenYin/DeepChordsSdk/StarburstSdk.framework/StarburstSdk similarity index 100% rename from ShenYin/StarburstSdk.framework/StarburstSdk rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/StarburstSdk diff --git a/ShenYin/StarburstSdk.framework/_CodeSignature/CodeDirectory b/ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeDirectory similarity index 100% rename from ShenYin/StarburstSdk.framework/_CodeSignature/CodeDirectory rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeDirectory diff --git a/ShenYin/StarburstSdk.framework/_CodeSignature/CodeRequirements b/ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeRequirements similarity index 100% rename from ShenYin/StarburstSdk.framework/_CodeSignature/CodeRequirements rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeRequirements diff --git a/ShenYin/StarburstSdk.framework/_CodeSignature/CodeRequirements-1 b/ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeRequirements-1 similarity index 100% rename from ShenYin/StarburstSdk.framework/_CodeSignature/CodeRequirements-1 rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeRequirements-1 diff --git a/ShenYin/StarburstSdk.framework/_CodeSignature/CodeResources b/ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeResources similarity index 100% rename from ShenYin/StarburstSdk.framework/_CodeSignature/CodeResources rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeResources diff --git a/ShenYin/StarburstSdk.framework/_CodeSignature/CodeSignature b/ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeSignature similarity index 100% rename from ShenYin/StarburstSdk.framework/_CodeSignature/CodeSignature rename to ShenYin/DeepChordsSdk/StarburstSdk.framework/_CodeSignature/CodeSignature diff --git a/ShenYin/DeepChordsSdk/Untitled.swift b/ShenYin/DeepChordsSdk/Untitled.swift new file mode 100644 index 0000000..b0ff59a --- /dev/null +++ b/ShenYin/DeepChordsSdk/Untitled.swift @@ -0,0 +1,7 @@ +// +// Untitled.swift +// Example +// +// Created by liangshi on 2025/12/29. +// + diff --git a/ShenYin/DeepChordsSdkTests/DeepChordsSdkTests.swift b/ShenYin/DeepChordsSdkTests/DeepChordsSdkTests.swift new file mode 100644 index 0000000..6ec3507 --- /dev/null +++ b/ShenYin/DeepChordsSdkTests/DeepChordsSdkTests.swift @@ -0,0 +1,17 @@ +// +// 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. + } + +} diff --git a/ShenYin/Podfile.lock b/ShenYin/Podfile.lock index 4142efd..acd287b 100644 --- a/ShenYin/Podfile.lock +++ b/ShenYin/Podfile.lock @@ -3,6 +3,7 @@ PODS: - 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) @@ -73,6 +74,7 @@ DEPENDENCIES: - DeviceKit (~> 5.4.0) - DGActivityIndicatorView - FDFullscreenPopGesture + - FSPagerView - HandyJSON - HorizonCalendar - IQKeyboardManagerSwift @@ -99,6 +101,7 @@ SPEC REPOS: - DeviceKit - DGActivityIndicatorView - FDFullscreenPopGesture + - FSPagerView - HandyJSON - HorizonCalendar - IQKeyboardCore @@ -131,6 +134,7 @@ SPEC CHECKSUMS: DeviceKit: bd34bb1766d926c3cc5a5f6e3e9a6dd10148b805 DGActivityIndicatorView: ff2c76073d79692f724863c8dd38685866a03cb6 FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0 + FSPagerView: 670405b2f18e2a87fa37f20b00de783e562c25a8 HandyJSON: 9e4e236f5d2dbefad5155a77417bbea438201c03 HorizonCalendar: 21e600058a8f4d407c79ef7848beda692c53a484 IQKeyboardCore: 28c8bf3bcd8ba5aa1570b318cbc4da94b861711e @@ -158,6 +162,6 @@ SPEC CHECKSUMS: YYText: 5c461d709e24d55a182d1441c41dc639a18a4849 ZipArchive: e25a4373192673e3229ac8d6e9f64a3e5713c966 -PODFILE CHECKSUM: 170365f9acea11a62fa72e8f7904f6acb237a166 +PODFILE CHECKSUM: 8f9cd07b8bd8a2a7a6ddbfd0af6732a71e3766ec COCOAPODS: 1.16.2 diff --git a/ShenYin/Pods/Kingfisher/PrivacyInfo.xcprivacy b/ShenYin/Pods/Kingfisher/PrivacyInfo.xcprivacy index 148b97e..b951586 100644 --- a/ShenYin/Pods/Kingfisher/PrivacyInfo.xcprivacy +++ b/ShenYin/Pods/Kingfisher/PrivacyInfo.xcprivacy @@ -2,22 +2,13 @@ - NSPrivacyTracking - + NSPrivacyCollectedDataTypes + NSPrivacyTrackingDomains NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryDiskSpace - NSPrivacyAccessedAPITypeReasons - - E174.1 - - - - NSPrivacyCollectedDataTypes + NSPrivacyTracking + diff --git a/ShenYin/Pods/MBProgressHUD/PrivacyInfo.xcprivacy b/ShenYin/Pods/MBProgressHUD/PrivacyInfo.xcprivacy index 148b97e..b951586 100644 --- a/ShenYin/Pods/MBProgressHUD/PrivacyInfo.xcprivacy +++ b/ShenYin/Pods/MBProgressHUD/PrivacyInfo.xcprivacy @@ -2,22 +2,13 @@ - NSPrivacyTracking - + NSPrivacyCollectedDataTypes + NSPrivacyTrackingDomains NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryDiskSpace - NSPrivacyAccessedAPITypeReasons - - E174.1 - - - - NSPrivacyCollectedDataTypes + NSPrivacyTracking + diff --git a/ShenYin/ShenYin.xcodeproj/project.pbxproj b/ShenYin/ShenYin.xcodeproj/project.pbxproj index 17f2faf..67f4f6d 100644 --- a/ShenYin/ShenYin.xcodeproj/project.pbxproj +++ b/ShenYin/ShenYin.xcodeproj/project.pbxproj @@ -7,21 +7,29 @@ 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; @@ -29,14 +37,17 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0D54E0602F0A5FDD00A80EE7 /* StarburstSdk.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = StarburstSdk.framework; sourceTree = ""; }; + 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 = ""; }; + 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 = ""; }; 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 = ""; }; 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 = ""; }; 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 = ""; }; + 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 = ""; }; 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 = ""; }; /* End PBXFileReference section */ @@ -64,7 +75,32 @@ }; /* 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 = ""; + }; + 0D54E0FF2F0A61E600A80EE7 /* DeepChordsSdkTests */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + ); + path = DeepChordsSdkTests; + sourceTree = ""; + }; 3F887B9E2E38D8DC00C98658 /* ShenYin */ = { isa = PBXFileSystemSynchronizedRootGroup; exceptions = ( @@ -76,13 +112,20 @@ /* 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; }; @@ -96,6 +139,8 @@ 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 = ""; @@ -106,10 +151,11 @@ 3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */, 3F887B9E2E38D8DC00C98658 /* ShenYin */, 3F8F68802EC1F25700FFC00B /* New Group */, + 0D54E0F02F0A61E600A80EE7 /* DeepChordsSdk */, + 0D54E0FF2F0A61E600A80EE7 /* DeepChordsSdkTests */, 3F887B9D2E38D8DC00C98658 /* Products */, 34A14A83ECF09370871C891F /* Pods */, 676B86A4BA2639E8694D56B4 /* Frameworks */, - 0D54E0602F0A5FDD00A80EE7 /* StarburstSdk.framework */, ); sourceTree = ""; }; @@ -117,6 +163,7 @@ isa = PBXGroup; children = ( 3F887B9C2E38D8DC00C98658 /* ShenYin.app */, + 0D54E0EF2F0A61E600A80EE7 /* DeepChordsSdk.framework */, ); name = Products; sourceTree = ""; @@ -133,13 +180,47 @@ children = ( 3F7602EA2EFA891200588C18 /* DeepChordsSdk.framework */, 3862D5561144E20721225B96 /* Pods_ShenYin.framework */, + 248D8B53B5A178ACA5867275 /* Pods_DeepChordsSdk.framework */, ); name = Frameworks; sourceTree = ""; }; /* 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" */; @@ -149,11 +230,11 @@ 3F887B992E38D8DC00C98658 /* Frameworks */, 3F887B9A2E38D8DC00C98658 /* Resources */, 5A934A35F54A5620CFD3C08A /* [CP] Embed Pods Frameworks */, - 3F79C6162E6055E500EC38B9 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( + 0D54E1032F0A61E600A80EE7 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 3F887B9E2E38D8DC00C98658 /* ShenYin */, @@ -173,6 +254,9 @@ LastSwiftUpdateCheck = 1640; LastUpgradeCheck = 1640; TargetAttributes = { + 0D54E0EE2F0A61E600A80EE7 = { + CreatedOnToolsVersion = 16.4; + }; 3F887B9B2E38D8DC00C98658 = { CreatedOnToolsVersion = 16.4; }; @@ -193,11 +277,19 @@ 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; @@ -209,21 +301,39 @@ /* 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; @@ -255,6 +365,13 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 0D54E0EB2F0A61E600A80EE7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 3F887B982E38D8DC00C98658 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -264,7 +381,123 @@ }; /* 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 */; @@ -283,6 +516,7 @@ "$(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; @@ -340,6 +574,7 @@ "$(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; @@ -504,6 +739,15 @@ /* 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 = ( diff --git a/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/DeepChordsSdk.xcscheme b/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/DeepChordsSdk.xcscheme new file mode 100644 index 0000000..c27ba03 --- /dev/null +++ b/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/DeepChordsSdk.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/ShenYin.xcscheme b/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/ShenYin.xcscheme index 7b6a0f6..f5114f2 100644 --- a/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/ShenYin.xcscheme +++ b/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/ShenYin.xcscheme @@ -29,6 +29,19 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES" shouldAutocreateTestPlan = "YES"> + + + + + + - - diff --git a/ShenYin/ShenYin/UI/Mine/Root/MineBannerView.swift b/ShenYin/ShenYin/UI/Mine/Root/MineBannerView.swift index 90e1243..7f5eeff 100644 --- a/ShenYin/ShenYin/UI/Mine/Root/MineBannerView.swift +++ b/ShenYin/ShenYin/UI/Mine/Root/MineBannerView.swift @@ -8,118 +8,118 @@ 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") + } +} diff --git a/ShenYin/podfile b/ShenYin/podfile index 8ffa418..bffe192 100644 --- a/ShenYin/podfile +++ b/ShenYin/podfile @@ -2,6 +2,10 @@ source "https://gitee.com/mirrors/CocoaPods-Specs.git" platform :ios, '13.0' use_frameworks! +target 'DeepChordsSdk' do + use_frameworks! + pod 'SocketRocket' +end workspace 'ShenYin' project 'ShenYin.xcodeproj' @@ -20,7 +24,7 @@ target 'ShenYin' do pod 'SVProgressHUD'#蒙版 pod 'MBProgressHUD'#蒙版 pod 'Kingfisher', '~> 6.0'#图片下载K -# pod 'FSPagerView' + pod 'FSPagerView' pod "TabPageViewController" #tabpage pod 'JXSegmentedView' pod 'JXPagingView/Paging' -- 2.17.1