Skip to content

Commit 27f1b5e

Browse files
committed
Move AcoustID API to async/await for Swift 6 compatibility
This also removes the now defunct dependency DVR, bumps the iOS/tvOS version to 15 (macOS: 12) and declares Swift language mode 6
1 parent 0e5280e commit 27f1b5e

9 files changed

+98
-200
lines changed

Package.swift

+4-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
// swift-tools-version:5.8
1+
// swift-tools-version:6.0
22
import PackageDescription
33

44
let package = Package(
55
name: "ChromaSwift",
6-
platforms: [.macOS(.v10_15), .iOS(.v12), .tvOS(.v12)],
6+
platforms: [.macOS(.v12), .iOS(.v15), .tvOS(.v15)],
77
products: [.library(name: "ChromaSwift", targets: ["ChromaSwift"])],
8-
dependencies: [
9-
.package(url: "https://github.com/venmo/DVR", from: "2.1.0")
10-
],
118
targets: [
129
.target(
1310
name: "ChromaSwift",
@@ -69,8 +66,8 @@ let package = Package(
6966
),
7067
.testTarget(
7168
name: "ChromaSwiftTests",
72-
dependencies: ["ChromaSwift", "DVR"],
73-
resources: [.copy("Fixtures"), .copy("Audio")]
69+
dependencies: ["ChromaSwift"],
70+
resources: [.copy("Audio")]
7471
),
7572
.testTarget(
7673
name: "CChromaprintTests",

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ChromaSwift
22

33
![Platform](https://img.shields.io/badge/Platform-macOS%20%7C%20iOS%20%7C%20tvOS-inactive)
4-
[![Swift](https://img.shields.io/badge/Swift-5-orange)](https://swift.org/)
4+
[![Swift](https://img.shields.io/badge/Swift-6-orange)](https://swift.org/)
55
[![SPM](https://img.shields.io/badge/SPM-compatible-success)](https://swift.org/package-manager/)
66
[![Unit Tests](https://github.com/wallisch/ChromaSwift/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/wallisch/ChromaSwift/actions/workflows/unit_tests.yml)
77
[![codecov](https://codecov.io/gh/wallisch/ChromaSwift/branch/master/graph/badge.svg?token=Y9IMV4347N)](https://codecov.io/gh/wallisch/ChromaSwift)

Sources/ChromaSwift/AcoustID.swift

+32-35
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Foundation
66
public class AcoustID {
77
let lookupEndpoint = "https://api.acoustid.org/v2/lookup"
88

9-
let session: URLSession
9+
let session: URLSessionProtocol
1010
let apiKey: String
1111
let timeout: Double
1212

@@ -57,17 +57,17 @@ public class AcoustID {
5757
public let title: String?
5858
}
5959

60-
init(apiKey: String, timeout: Double, session: URLSession) {
60+
init(apiKey: String, timeout: Double, session: URLSessionProtocol) {
6161
self.session = session
6262
self.apiKey = apiKey
6363
self.timeout = timeout
6464
}
6565

6666
public convenience init(apiKey: String, timeout: Double = 3.0) {
67-
self.init(apiKey: apiKey, timeout: timeout, session: .shared)
67+
self.init(apiKey: apiKey, timeout: timeout, session: URLSession.shared)
6868
}
6969

70-
public func lookup(_ fingerprint: AudioFingerprint, completion: @escaping (Result<[APIResult], Error>) -> Void) {
70+
public func lookup(_ fingerprint: AudioFingerprint) async throws -> [APIResult] {
7171
let query = [
7272
URLQueryItem(name: "client", value: apiKey),
7373
URLQueryItem(name: "meta", value: "recordings+releasegroups+compress"),
@@ -78,41 +78,38 @@ public class AcoustID {
7878
lookupURLComponents.queryItems = query
7979

8080
guard let lookupURL = lookupURLComponents.url else {
81-
completion(.failure(Error.invalidURL))
82-
return
81+
throw Error.invalidURL
8382
}
8483
var request = URLRequest(url: lookupURL)
8584
request.timeoutInterval = timeout
8685

87-
session.dataTask(with: request) { (data, _, error) in
88-
if error != nil {
89-
completion(.failure(Error.networkFail))
90-
} else if let data = data {
91-
guard let decodedResponse = try? JSONDecoder().decode(APIResponse.self, from: data) else {
92-
completion(.failure(Error.parseFail))
93-
return
94-
}
95-
if let apiError = decodedResponse.error {
96-
switch apiError.code {
97-
case 3:
98-
completion(.failure(Error.invalidFingerprint))
99-
case 4:
100-
completion(.failure(Error.invalidApiKey))
101-
case 8:
102-
completion(.failure(Error.invalidDuration))
103-
case 14:
104-
completion(.failure(Error.tooManyRequests))
105-
default:
106-
completion(.failure(Error.apiFail))
107-
}
108-
return
109-
}
110-
guard let results = decodedResponse.results else {
111-
completion(.success([]))
112-
return
113-
}
114-
completion(.success(results))
86+
guard let (data, _) = try? await session.data(for: request) else {
87+
throw Error.networkFail
88+
}
89+
90+
guard let decodedResponse = try? JSONDecoder().decode(APIResponse.self, from: data) else {
91+
throw Error.parseFail
92+
}
93+
94+
if let apiError = decodedResponse.error {
95+
switch apiError.code {
96+
case 3:
97+
throw Error.invalidFingerprint
98+
case 4:
99+
throw Error.invalidApiKey
100+
case 8:
101+
throw Error.invalidDuration
102+
case 14:
103+
throw Error.tooManyRequests
104+
default:
105+
throw Error.apiFail
115106
}
116-
}.resume()
107+
}
108+
109+
guard let results = decodedResponse.results else {
110+
return []
111+
}
112+
113+
return results
117114
}
118115
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) 2024 Philipp Wallisch
2+
// Distributed under the MIT license, see the LICENSE file for details.
3+
4+
import Foundation
5+
6+
protocol URLSessionProtocol {
7+
func data(for request: URLRequest) async throws -> (Data, URLResponse)
8+
}
9+
10+
extension URLSession: URLSessionProtocol {}

0 commit comments

Comments
 (0)