diff --git a/.github/workflows/ios-demos.yml b/.github/workflows/ios-demos.yml index 3a34b47f..8ea26251 100644 --- a/.github/workflows/ios-demos.yml +++ b/.github/workflows/ios-demos.yml @@ -25,20 +25,9 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Set up Node.js LTS - uses: actions/setup-node@v3 - with: - node-version: lts/* - - name: Install Cocoapods run: gem install cocoapods - - name: Install AppCenter CLI - run: npm install -g appcenter-cli - - - name: Make build dir - run: mkdir ddp - - name: Run Cocoapods run: pod install diff --git a/binding/ios/Cobra-iOS.podspec b/binding/ios/Cobra-iOS.podspec index 1a585e37..e44195e3 100644 --- a/binding/ios/Cobra-iOS.podspec +++ b/binding/ios/Cobra-iOS.podspec @@ -1,10 +1,10 @@ Pod::Spec.new do |s| s.name = 'Cobra-iOS' s.module_name = 'Cobra' - s.version = '1.2.0' + s.version = '2.0.0' s.license = {:type => 'Apache 2.0'} s.summary = 'iOS binding for Picovoice\'s Cobra voice activity detection (VAD) engine.' - s.description = + s.description = <<-DESC Made in Vancouver, Canada by [Picovoice](https://picovoice.ai) @@ -12,7 +12,7 @@ Pod::Spec.new do |s| DESC s.homepage = 'https://github.com/Picovoice/cobra/tree/master/binding/ios' s.author = { 'Picovoice' => 'hello@picovoice.ai' } - s.source = { :git => "https://github.com/Picovoice/cobra.git", :tag => "Cobra-iOS-v1.2.0" } + s.source = { :git => "https://github.com/Picovoice/cobra.git", :tag => "Cobra-iOS-v2.0.0" } s.ios.deployment_target = '11.0' s.swift_version = '5.0' s.vendored_frameworks = 'lib/ios/PvCobra.xcframework' diff --git a/binding/ios/Cobra.swift b/binding/ios/Cobra.swift index 84184f9e..15dc6693 100644 --- a/binding/ios/Cobra.swift +++ b/binding/ios/Cobra.swift @@ -1,5 +1,5 @@ // -// Copyright 2021 Picovoice Inc. +// Copyright 2021-2023 Picovoice Inc. // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -27,15 +27,24 @@ public class Cobra { /// Cobra version string public static let version = String(cString: pv_cobra_version()) + private static var sdk = "ios" + + public static func setSdk(sdk: String) { + self.sdk = sdk + } + /// Constructor. /// /// - Parameters: /// - accessKey: AccessKey obtained from the Picovoice Console (https://console.picovoice.ai/) /// - Throws: CobraError public init(accessKey: String) throws { + pv_set_sdk(Cobra.sdk) + let status = pv_cobra_init(accessKey, &handle) if status != PV_STATUS_SUCCESS { - throw pvStatusToCobraError(status, "Cobra init failed") + let messageStack = try getMessageStack() + throw pvStatusToCobraError(status, "Cobra init failed", messageStack) } } @@ -60,6 +69,10 @@ public class Cobra { /// - Returns: Probability of voice activity. It is a floating-point number within [0, 1]. /// - Throws: CobraError public func process(pcm: [Int16]) throws -> Float32 { + if handle == nil { + throw CobraInvalidStateError("Unable to process - resources have been released") + } + if pcm.count != Cobra.frameLength { throw CobraInvalidArgumentError( "Frame of audio data must contain \(Cobra.frameLength) samples - given frame contained \(pcm.count)") @@ -68,39 +81,61 @@ public class Cobra { var result: Float32 = 0 let status = pv_cobra_process(self.handle, pcm, &result) if status != PV_STATUS_SUCCESS { - throw pvStatusToCobraError(status, "Cobra process failed") + let messageStack = try getMessageStack() + throw pvStatusToCobraError(status, "Cobra process failed", messageStack) } return result } - private func pvStatusToCobraError(_ status: pv_status_t, _ message: String) -> CobraError { + private func pvStatusToCobraError( + _ status: pv_status_t, + _ message: String, + _ messageStack: [String] = []) -> CobraError { switch status { case PV_STATUS_OUT_OF_MEMORY: - return CobraMemoryError(message) + return CobraMemoryError(message, messageStack) case PV_STATUS_IO_ERROR: - return CobraIOError(message) + return CobraIOError(message, messageStack) case PV_STATUS_INVALID_ARGUMENT: - return CobraInvalidArgumentError(message) + return CobraInvalidArgumentError(message, messageStack) case PV_STATUS_STOP_ITERATION: - return CobraStopIterationError(message) + return CobraStopIterationError(message, messageStack) case PV_STATUS_KEY_ERROR: - return CobraKeyError(message) + return CobraKeyError(message, messageStack) case PV_STATUS_INVALID_STATE: - return CobraInvalidStateError(message) + return CobraInvalidStateError(message, messageStack) case PV_STATUS_RUNTIME_ERROR: - return CobraRuntimeError(message) + return CobraRuntimeError(message, messageStack) case PV_STATUS_ACTIVATION_ERROR: - return CobraActivationError(message) + return CobraActivationError(message, messageStack) case PV_STATUS_ACTIVATION_LIMIT_REACHED: - return CobraActivationLimitError(message) + return CobraActivationLimitError(message, messageStack) case PV_STATUS_ACTIVATION_THROTTLED: - return CobraActivationThrottledError(message) + return CobraActivationThrottledError(message, messageStack) case PV_STATUS_ACTIVATION_REFUSED: - return CobraActivationRefusedError(message) + return CobraActivationRefusedError(message, messageStack) default: let pvStatusString = String(cString: pv_status_to_string(status)) - return CobraError("\(pvStatusString): \(message)") + return CobraError("\(pvStatusString): \(message)", messageStack) + } + } + + private func getMessageStack() throws -> [String] { + var messageStackRef: UnsafeMutablePointer?>? + var messageStackDepth: Int32 = 0 + let status = pv_get_error_stack(&messageStackRef, &messageStackDepth) + if status != PV_STATUS_SUCCESS { + throw pvStatusToCobraError(status, "Unable to get Cobra error state") } + + var messageStack: [String] = [] + for i in 0.. 1.2.0' + pod 'Cobra-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/cobra/v2.0-ios/binding/ios/Cobra-iOS.podspec' end target 'CobraAppTestUITests' do - pod 'Cobra-iOS', '~> 1.2.0' + pod 'Cobra-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/cobra/v2.0-ios/binding/ios/Cobra-iOS.podspec' end target 'PerformanceTest' do - pod 'Cobra-iOS', '~> 1.2.0' + pod 'Cobra-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/cobra/v2.0-ios/binding/ios/Cobra-iOS.podspec' end diff --git a/binding/ios/CobraAppTest/Podfile.lock b/binding/ios/CobraAppTest/Podfile.lock index 77e936cb..b4487f2c 100644 --- a/binding/ios/CobraAppTest/Podfile.lock +++ b/binding/ios/CobraAppTest/Podfile.lock @@ -1,16 +1,16 @@ PODS: - - Cobra-iOS (1.2.0) + - Cobra-iOS (2.0.0) DEPENDENCIES: - - Cobra-iOS (~> 1.2.0) + - Cobra-iOS (from `https://raw.githubusercontent.com/Picovoice/cobra/v2.0-ios/binding/ios/Cobra-iOS.podspec`) -SPEC REPOS: - trunk: - - Cobra-iOS +EXTERNAL SOURCES: + Cobra-iOS: + :podspec: https://raw.githubusercontent.com/Picovoice/cobra/v2.0-ios/binding/ios/Cobra-iOS.podspec SPEC CHECKSUMS: - Cobra-iOS: ff2e2622be1b37cc49935bb400938cb68cca6c18 + Cobra-iOS: c8d7f9052b9b783b9976243e3092c9b9087f63fc -PODFILE CHECKSUM: 350db7fdeda2f30994f4156e5d5c4048c8931cbb +PODFILE CHECKSUM: f2a9737621b3736541f8a3899eeff564bc95141a -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/binding/ios/CobraErrors.swift b/binding/ios/CobraErrors.swift index a47aa7a4..dde9ae44 100644 --- a/binding/ios/CobraErrors.swift +++ b/binding/ios/CobraErrors.swift @@ -1,5 +1,5 @@ // -// Copyright 2021 Picovoice Inc. +// Copyright 2021-2023 Picovoice Inc. // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -9,17 +9,28 @@ public class CobraError: LocalizedError { private let message: String + private let messageStack: [String] - public init (_ message: String) { + public init (_ message: String, _ messageStack: [String] = []) { self.message = message + self.messageStack = messageStack } public var errorDescription: String? { - return message + var messageString = message + if messageStack.count > 0 { + messageString += ":" + for i in 0.. 1.2.0' + pod 'Cobra-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/cobra/v2.0-ios/binding/ios/Cobra-iOS.podspec' pod 'ios-voice-processor', '~> 1.1.0' end diff --git a/demo/ios/CobraDemo/Podfile.lock b/demo/ios/CobraDemo/Podfile.lock index 2f5c70f5..1bcd1e21 100644 --- a/demo/ios/CobraDemo/Podfile.lock +++ b/demo/ios/CobraDemo/Podfile.lock @@ -1,20 +1,23 @@ PODS: - - Cobra-iOS (1.2.0) + - Cobra-iOS (2.0.0) - ios-voice-processor (1.1.0) DEPENDENCIES: - - Cobra-iOS (~> 1.2.0) + - Cobra-iOS (from `https://raw.githubusercontent.com/Picovoice/cobra/v2.0-ios/binding/ios/Cobra-iOS.podspec`) - ios-voice-processor (~> 1.1.0) SPEC REPOS: trunk: - - Cobra-iOS - ios-voice-processor +EXTERNAL SOURCES: + Cobra-iOS: + :podspec: https://raw.githubusercontent.com/Picovoice/cobra/v2.0-ios/binding/ios/Cobra-iOS.podspec + SPEC CHECKSUMS: - Cobra-iOS: ff2e2622be1b37cc49935bb400938cb68cca6c18 + Cobra-iOS: c8d7f9052b9b783b9976243e3092c9b9087f63fc ios-voice-processor: 8e32d7f980a06d392d128ef1cd19cf6ddcaca3c1 -PODFILE CHECKSUM: dcc8350eed61872fda34cda940969c6923f2c3e0 +PODFILE CHECKSUM: 4f296c7a7968d696777782481ce2f484ba88f7b4 COCOAPODS: 1.11.3