Skip to content

Commit f6ded12

Browse files
committed
Remove CombineExt dependency
1 parent bcc7a2e commit f6ded12

File tree

21 files changed

+85
-119
lines changed

21 files changed

+85
-119
lines changed

Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

+4-13
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,13 @@
1010
"version" : "1.0.2"
1111
}
1212
},
13-
{
14-
"identity" : "combineext",
15-
"kind" : "remoteSourceControl",
16-
"location" : "https://github.com/CombineCommunity/CombineExt.git",
17-
"state" : {
18-
"revision" : "d7b896fa9ca8b47fa7bcde6b43ef9b70bf8c1f56",
19-
"version" : "1.8.1"
20-
}
21-
},
2213
{
2314
"identity" : "swift-concurrency-extras",
2415
"kind" : "remoteSourceControl",
2516
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
2617
"state" : {
27-
"revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71",
28-
"version" : "1.1.0"
18+
"revision" : "82a4ae7170d98d8538ec77238b7eb8e7199ef2e8",
19+
"version" : "1.3.1"
2920
}
3021
},
3122
{
@@ -42,8 +33,8 @@
4233
"kind" : "remoteSourceControl",
4334
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
4435
"state" : {
45-
"revision" : "357ca1e5dd31f613a1d43320870ebc219386a495",
46-
"version" : "1.2.2"
36+
"revision" : "a3f634d1a409c7979cabc0a71b3f26ffa9fc8af1",
37+
"version" : "1.4.3"
4738
}
4839
}
4940
],

Package.resolved

+15-24
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,17 @@
55
"kind" : "remoteSourceControl",
66
"location" : "https://github.com/pointfreeco/combine-schedulers",
77
"state" : {
8-
"revision" : "487a4d151e795a5e076a7e7aedcd13c2ebff6c31",
9-
"version" : "1.0.1"
10-
}
11-
},
12-
{
13-
"identity" : "combineext",
14-
"kind" : "remoteSourceControl",
15-
"location" : "https://github.com/CombineCommunity/CombineExt.git",
16-
"state" : {
17-
"revision" : "d7b896fa9ca8b47fa7bcde6b43ef9b70bf8c1f56",
18-
"version" : "1.8.1"
8+
"revision" : "9fa31f4403da54855f1e2aeaeff478f4f0e40b13",
9+
"version" : "1.0.2"
1910
}
2011
},
2112
{
2213
"identity" : "swift-concurrency-extras",
2314
"kind" : "remoteSourceControl",
2415
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
2516
"state" : {
26-
"revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71",
27-
"version" : "1.1.0"
28-
}
29-
},
30-
{
31-
"identity" : "swift-issue-reporting",
32-
"kind" : "remoteSourceControl",
33-
"location" : "https://github.com/pointfreeco/swift-issue-reporting",
34-
"state" : {
35-
"revision" : "c85092304cda8cb38d2d68454b29609a8013620b",
36-
"version" : "1.2.1"
17+
"revision" : "82a4ae7170d98d8538ec77238b7eb8e7199ef2e8",
18+
"version" : "1.3.1"
3719
}
3820
},
3921
{
@@ -59,8 +41,17 @@
5941
"kind" : "remoteSourceControl",
6042
"location" : "https://github.com/swiftlang/swift-syntax",
6143
"state" : {
62-
"revision" : "4c6cc0a3b9e8f14b3ae2307c5ccae4de6167ac2c",
63-
"version" : "600.0.0-prerelease-2024-06-12"
44+
"revision" : "0687f71944021d616d34d922343dcef086855920",
45+
"version" : "600.0.1"
46+
}
47+
},
48+
{
49+
"identity" : "xctest-dynamic-overlay",
50+
"kind" : "remoteSourceControl",
51+
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
52+
"state" : {
53+
"revision" : "a3f634d1a409c7979cabc0a71b3f26ffa9fc8af1",
54+
"version" : "1.4.3"
6455
}
6556
}
6657
],

Package.swift

+2-4
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@ let package = Package(
1717
dependencies: [
1818
.package(url: "https://github.com/mihai8804858/swift-snapshot-testing", branch: "main"),
1919
.package(url: "https://github.com/mihai8804858/swift-libass", .upToNextMajor(from: "1.0.0")),
20-
.package(url: "https://github.com/pointfreeco/combine-schedulers", .upToNextMajor(from: "1.0.0")),
21-
.package(url: "https://github.com/CombineCommunity/CombineExt.git", .upToNextMajor(from: "1.0.0"))
20+
.package(url: "https://github.com/pointfreeco/combine-schedulers", .upToNextMajor(from: "1.0.0"))
2221
],
2322
targets: [
2423
.target(
2524
name: "SwiftAssRenderer",
2625
dependencies: [
2726
.target(name: "SwiftAssBlend"),
2827
.product(name: "SwiftLibass", package: "swift-libass"),
29-
.product(name: "CombineSchedulers", package: "combine-schedulers"),
30-
.product(name: "CombineExt", package: "CombineExt")
28+
.product(name: "CombineSchedulers", package: "combine-schedulers")
3129
],
3230
path: "Sources/SwiftAssRenderer",
3331
resources: [

Sources/SwiftAssRenderer/Composition/AssVideoComposition.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import UIKit
33
#elseif canImport(AppKit)
44
import AppKit
55
#endif
6-
import AVFoundation
6+
@preconcurrency import AVFoundation
77
import CoreImage
88

99
@available(iOS 16.0, tvOS 16.0, visionOS 1.0, macCatalyst 16.0, macOS 13.0, *)
10-
final class AssVideoComposition {
10+
final class AssVideoComposition: Sendable {
1111
private let scale: CGFloat
1212
private let asset: AVAsset
1313
private let renderer: AssSubtitlesRenderer
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
import AVFoundation
22
import Combine
3-
import CombineExt
43

54
extension AVPlayer {
65
func periodicTimeObserver(interval: CMTime, queue: DispatchQueue = .main) -> AnyPublisher<CMTime, Never> {
7-
AnyPublisher<CMTime, Never>.create { [weak self] subscriber in
6+
Deferred { [weak self] in
87
guard let self else {
9-
subscriber.send(completion: .finished)
10-
return AnyCancellable {}
8+
return Empty(outputType: CMTime.self, failureType: Never.self)
9+
.eraseToAnyPublisher()
1110
}
12-
let observer = addPeriodicTimeObserver(forInterval: interval, queue: queue) { time in
13-
subscriber.send(time)
14-
}
15-
16-
return AnyCancellable { [weak self] in
17-
self?.removeTimeObserver(observer)
18-
}
19-
}
11+
let subject = PassthroughSubject<CMTime, Never>()
12+
let observer = addPeriodicTimeObserver(forInterval: interval, queue: queue) { subject.send($0) }
13+
return subject.handleEvents(
14+
receiveCompletion: { [weak self] _ in self?.removeTimeObserver(observer) },
15+
receiveCancel: { [weak self] in self?.removeTimeObserver(observer) }
16+
).eraseToAnyPublisher()
17+
}.eraseToAnyPublisher()
2018
}
2119
}

Sources/SwiftAssRenderer/Extensions/Bundle.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
protocol BundleType {
3+
protocol BundleType: Sendable {
44
func url(forResource name: String?, withExtension ext: String?) -> URL?
55
}
66

Sources/SwiftAssRenderer/Extensions/DispatchQueue.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Dispatch
22
import Foundation
33

4-
protocol DispatchQueueType {
4+
protocol DispatchQueueType: Sendable {
55
func executeAsync(_ work: @escaping () -> Void)
66
}
77

Sources/SwiftAssRenderer/Extensions/FileManager.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22

3-
protocol FileManagerType {
3+
protocol FileManagerType: Sendable {
44
var cachesDirectory: URL { get }
55

66
func fileExists(at path: URL) -> Bool
@@ -10,7 +10,7 @@ protocol FileManagerType {
1010
func createItem(at path: URL, contents: String, override: Bool) throws
1111
}
1212

13-
extension FileManager: FileManagerType {
13+
extension FileManager: FileManagerType, @retroactive @unchecked Sendable {
1414
var cachesDirectory: URL {
1515
if #available(iOS 16.0, tvOS 16.0, visionOS 1.0, macOS 13.0, *) {
1616
URL.cachesDirectory

Sources/SwiftAssRenderer/FontConfig/FontConfig.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
22

33
/// Which provider to use for character rendering and font management.
4-
public enum FontProvider: Equatable {
4+
public enum FontProvider: Equatable, Sendable {
55
/// Uses [fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/)
66
/// to manage the fonts and render the characters.
77
case fontConfig
@@ -10,7 +10,7 @@ public enum FontProvider: Equatable {
1010
case coreText
1111
}
1212

13-
protocol FontConfigType {
13+
protocol FontConfigType: Sendable {
1414
func configure(library: OpaquePointer, renderer: OpaquePointer) throws
1515
}
1616

Sources/SwiftAssRenderer/Loader/ContentsLoader.swift

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import Foundation
22
import Combine
3-
import CombineExt
43
import CombineSchedulers
54

6-
protocol ContentsLoaderType {
5+
protocol ContentsLoaderType: Sendable {
76
func loadContents(from url: URL) -> AnyPublisher<String?, Error>
87
}
98

@@ -31,16 +30,16 @@ struct ContentsLoader: ContentsLoaderType {
3130
}
3231

3332
private func loadLocalContents(from url: URL) -> AnyPublisher<String?, Error> {
34-
AnyPublisher<String?, Error>.create { subscriber in
35-
do {
36-
subscriber.send(try String(contentsOf: url))
37-
subscriber.send(completion: .finished)
38-
} catch {
39-
subscriber.send(completion: .failure(error))
33+
Deferred {
34+
Future { promise in
35+
do {
36+
promise(.success(try String(contentsOf: url)))
37+
} catch {
38+
promise(.failure(error))
39+
}
4040
}
41-
42-
return AnyCancellable {}
4341
}
42+
.eraseToAnyPublisher()
4443
}
4544

4645
private func loadRemoveContents(from url: URL) -> AnyPublisher<String?, Error> {

Sources/SwiftAssRenderer/Logger/Logger.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/// Log level.
2-
public enum LogLevel: Int {
2+
public enum LogLevel: Int, Sendable {
33
/// Only fatal errors that result in subtitles not being rendered.
44
case fatal = 0
55

@@ -20,7 +20,7 @@ public enum LogLevel: Int {
2020
}
2121

2222
/// Log output message and level.
23-
public struct LogMessage {
23+
public struct LogMessage: Sendable {
2424
/// Output message.
2525
public let message: String
2626

@@ -29,15 +29,15 @@ public struct LogMessage {
2929
}
3030

3131
/// Where the messages should be send to.
32-
public enum LogOutput {
32+
public enum LogOutput: Sendable {
3333
/// Print messages to console based on the provided log level.
3434
case console(LogLevel)
3535

3636
/// Send all messages to custom handler.
37-
case custom((LogMessage) -> Void)
37+
case custom(@Sendable (LogMessage) -> Void)
3838
}
3939

40-
protocol LoggerType {
40+
protocol LoggerType: Sendable {
4141
func configureLibrary(_ wrapper: LibraryWrapperType.Type, library: OpaquePointer)
4242
func log(message: LogMessage)
4343
}

Sources/SwiftAssRenderer/Pipeline/ImagePipelineType.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import CoreGraphics
22
import SwiftLibass
33

44
/// Pipeline that processed an `ASS_Image` into a ``ProcessedImage`` that can be drawn on the screen.
5-
public protocol ImagePipelineType {
5+
public protocol ImagePipelineType: Sendable {
66
func process(images: [ASS_Image], boundingRect: CGRect) -> ProcessedImage?
77
}

Sources/SwiftAssRenderer/Pipeline/ProcessedImage.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import CoreGraphics
22

33
/// Processed image bitmap and the rect where the image should be drawn in the subtitles canvas.
4-
public struct ProcessedImage: Equatable {
4+
public struct ProcessedImage: Equatable, Sendable {
55
public let image: CGImage
66
public let imageRect: CGRect
77

Sources/SwiftAssRenderer/Renderer/AssSubtitlesRenderer.swift

+12-14
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import Foundation
33
import SwiftLibass
44
import CombineSchedulers
55

6-
public typealias LibrarySetup = (_ library: OpaquePointer) -> Void
7-
public typealias RendererSetup = (_ library: OpaquePointer, _ renderer: OpaquePointer) -> Void
6+
public typealias LibrarySetup = @Sendable (_ library: OpaquePointer) -> Void
7+
public typealias RendererSetup = @Sendable (_ library: OpaquePointer, _ renderer: OpaquePointer) -> Void
88

99
/// ASS/SSA subtitles renderer. Manages the current ASS track,
1010
/// current time offset and current visible frame (``ProcessedImage``).
11-
public final class AssSubtitlesRenderer {
12-
public enum FrameRenderResult {
11+
public final class AssSubtitlesRenderer: Sendable {
12+
public enum FrameRenderResult: Sendable {
1313
case loaded(ProcessedImage)
1414
case unchanged
1515
case none
@@ -25,16 +25,14 @@ public final class AssSubtitlesRenderer {
2525
private let librarySetup: LibrarySetup?
2626
private let rendererSetup: RendererSetup?
2727

28-
private var library: OpaquePointer?
29-
private var renderer: OpaquePointer?
30-
31-
private var canvasSize: CGSize = .zero
32-
private var canvasScale: CGFloat = 1.0
33-
private var cancellables: Set<AnyCancellable> = []
34-
35-
private(set) var currentTrack: ASS_Track?
36-
private(set) var currentOffset: TimeInterval = 0
37-
private(set) var currentFrame = CurrentValueSubject<ProcessedImage?, Never>(nil)
28+
nonisolated(unsafe) private var library: OpaquePointer?
29+
nonisolated(unsafe) private var renderer: OpaquePointer?
30+
nonisolated(unsafe) private var canvasSize: CGSize = .zero
31+
nonisolated(unsafe) private var canvasScale: CGFloat = 1.0
32+
nonisolated(unsafe) private var cancellables: Set<AnyCancellable> = []
33+
nonisolated(unsafe) private(set) var currentTrack: ASS_Track?
34+
nonisolated(unsafe) private(set) var currentOffset: TimeInterval = 0
35+
nonisolated(unsafe) private(set) var currentFrame = CurrentValueSubject<ProcessedImage?, Never>(nil)
3836

3937
/// - Parameters:
4038
/// - fontConfig: Fonts configuration. Defines where the fonts and fonts cache is located,

Sources/SwiftAssRenderer/Wrapper/LibraryWrapper.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
2-
import SwiftLibass
2+
@preconcurrency import SwiftLibass
33

4-
struct LibraryRenderResult {
4+
struct LibraryRenderResult: Sendable {
55
let image: ASS_Image
66
let changed: Bool
77
}
@@ -15,7 +15,7 @@ extension FontProvider {
1515
}
1616
}
1717

18-
protocol LibraryWrapperType {
18+
protocol LibraryWrapperType: Sendable {
1919
static var libraryLogger: (Int, String) -> Void { get set }
2020
static func setLogCallback(_ library: OpaquePointer)
2121

0 commit comments

Comments
 (0)