Skip to content

Commit c15034c

Browse files
authored
Merge pull request #85 from mansbernhardt/linux-support
Add Linux support for `SwiftTimecodeCore` target
2 parents 1cd1756 + 3f4c558 commit c15034c

16 files changed

Lines changed: 123 additions & 295 deletions

File tree

.github/workflows/build.yml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ on:
2525
- cron: '40 11 * * *' # once a day @ 11:40am UTC (4:40am PST)
2626

2727
env:
28-
SCHEME: "swift-timecode"
29-
WORKSPACEPATH: ".swiftpm/xcode/package.xcworkspace"
28+
SCHEME: swift-timecode
29+
WORKSPACEPATH: .swiftpm/xcode/package.xcworkspace
3030

3131
jobs:
3232
macOS:
@@ -105,3 +105,14 @@ jobs:
105105
ID: ${{ steps.sim-setup.outputs.id }}
106106
PLATFORM: ${{ steps.sim-setup.outputs.platform }}
107107
WORKSPACEPATH: ${{ steps.sim-setup.outputs.workspace-path }}
108+
109+
linux:
110+
name: Tests (Linux)
111+
runs-on: ubuntu-latest
112+
timeout-minutes: 20
113+
steps:
114+
- uses: actions/checkout@main
115+
- name: Build
116+
run: swift build
117+
- name: Unit Tests
118+
run: swift test

Package.swift

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,22 @@ let package = Package(
1212
],
1313
products: [
1414
.library(name: "SwiftTimecode", targets: ["SwiftTimecode"]),
15-
.library(name: "SwiftTimecodeCore", type: .static, targets: ["SwiftTimecodeCore"]),
16-
.library(name: "SwiftTimecodeAV", targets: ["SwiftTimecodeAV"]),
17-
.library(name: "SwiftTimecodeUI", targets: ["SwiftTimecodeUI"])
15+
.library(name: "SwiftTimecodeCore", type: .static, targets: ["SwiftTimecodeCore"])
1816
],
1917
dependencies: [
2018
// used only for Dev tests, not part of regular unit tests
2119
.package(url: "https://github.com/apple/swift-numerics", from: "1.1.1"),
22-
.package(url: "https://github.com/orchetect/swift-testing-extensions", from: "0.3.0"),
23-
.package(url: "https://github.com/orchetect/xctest-extensions", from: "2.0.0")
20+
.package(url: "https://github.com/orchetect/swift-testing-extensions", from: "0.2.4")
2421
],
2522
targets: [
2623
.target(
2724
name: "SwiftTimecode",
28-
dependencies: ["SwiftTimecodeCore", "SwiftTimecodeAV", "SwiftTimecodeUI"]
25+
dependencies: ["SwiftTimecodeCore"]
2926
),
3027
.target(
3128
name: "SwiftTimecodeCore",
3229
dependencies: []
3330
),
34-
.target(
35-
name: "SwiftTimecodeAV",
36-
dependencies: ["SwiftTimecodeCore"]
37-
),
38-
.target(
39-
name: "SwiftTimecodeUI",
40-
dependencies: ["SwiftTimecodeCore"],
41-
linkerSettings: [
42-
.linkedFramework("SwiftUI", .when(platforms: [.macOS, .macCatalyst, .iOS, .tvOS, .watchOS, .visionOS]))
43-
]
44-
),
4531
.testTarget(
4632
name: "SwiftTimecodeCoreTests",
4733
dependencies: [
@@ -50,39 +36,54 @@ let package = Package(
5036
.product(name: "TestingExtensions", package: "swift-testing-extensions"),
5137
]
5238
),
53-
.testTarget(
54-
name: "SwiftTimecodeAVTests",
55-
dependencies: [
56-
"SwiftTimecodeAV",
57-
.product(name: "TestingExtensions", package: "swift-testing-extensions"),
58-
],
59-
resources: [.copy("TestResource/Media Files")]
60-
),
61-
.testTarget(
62-
name: "SwiftTimecodeUITests",
63-
dependencies: [
64-
"SwiftTimecodeUI",
65-
.product(name: "TestingExtensions", package: "swift-testing-extensions"),
66-
],
67-
linkerSettings: [
68-
.linkedFramework("SwiftUI", .when(platforms: [.macOS, .macCatalyst, .iOS, .tvOS, .watchOS, .visionOS]))
69-
]
70-
),
71-
// dev tests
72-
// (not meant to be run as unit tests, but only to verify library's computational integrity
73-
// when making major changes to the library, as these tests require modification to be meaningful)
74-
.testTarget(
75-
name: "SwiftTimecodeDevTests",
76-
dependencies: [
77-
"SwiftTimecodeCore",
78-
"SwiftTimecodeAV",
79-
.product(name: "TestingExtensions", package: "swift-testing-extensions"),
80-
.product(name: "XCTestExtensions", package: "xctest-extensions")
81-
]
82-
)
8339
]
8440
)
8541

42+
#if canImport(Darwin)
43+
/// AV and UI targets are only compatible with Apple platforms.
44+
45+
package.products += [
46+
.library(name: "SwiftTimecodeAV", targets: ["SwiftTimecodeAV"]),
47+
.library(name: "SwiftTimecodeUI", targets: ["SwiftTimecodeUI"])
48+
]
49+
50+
package.targets.first(where: { $0.name == "SwiftTimecode" })?.dependencies += [
51+
"SwiftTimecodeAV", "SwiftTimecodeUI"
52+
]
53+
54+
package.targets += [
55+
.target(
56+
name: "SwiftTimecodeAV",
57+
dependencies: ["SwiftTimecodeCore"]
58+
),
59+
.target(
60+
name: "SwiftTimecodeUI",
61+
dependencies: ["SwiftTimecodeCore"],
62+
linkerSettings: [
63+
.linkedFramework("SwiftUI", .when(platforms: [.macOS, .macCatalyst, .iOS, .tvOS, .watchOS, .visionOS]))
64+
]
65+
),
66+
.testTarget(
67+
name: "SwiftTimecodeAVTests",
68+
dependencies: [
69+
"SwiftTimecodeAV",
70+
.product(name: "TestingExtensions", package: "swift-testing-extensions"),
71+
],
72+
resources: [.copy("TestResource/Media Files")]
73+
),
74+
.testTarget(
75+
name: "SwiftTimecodeUITests",
76+
dependencies: [
77+
"SwiftTimecodeUI",
78+
.product(name: "TestingExtensions", package: "swift-testing-extensions"),
79+
],
80+
linkerSettings: [
81+
.linkedFramework("SwiftUI", .when(platforms: [.macOS, .macCatalyst, .iOS, .tvOS, .watchOS, .visionOS]))
82+
]
83+
)
84+
]
85+
#endif
86+
8687
/// Conditionally opt-in to Swift DocC Plugin when an environment flag is present.
8788
if ProcessInfo.processInfo.environment["ENABLE_DOCC_PLUGIN"] != nil {
8889
package.dependencies += [

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Forchetect%2Fswift-timecode%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/orchetect/swift-timecode) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Forchetect%2Fswift-timecode%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/orchetect/swift-timecode) [![Xcode 16](https://img.shields.io/badge/Xcode-16-blue.svg?style=flat)](https://developer.apple.com/swift) [![License: MIT](http://img.shields.io/badge/License-MIT-lightgrey.svg?style=flat)](https://github.com/orchetect/swift-timecode/blob/main/LICENSE)
66

7-
The most robust, precise and complete Swift library for working with SMPTE/EBU timecode. Supports 23 industry-standard timecode frame rates with a suite of conversions, calculations and integrations with Apple AV frameworks.
7+
The most robust, precise and complete multi-platform Swift library for working with SMPTE/EBU timecode.
8+
9+
Supports 23 industry-standard timecode frame rates with a suite of conversions, calculations and integrations with Apple AV frameworks.
810

911
Timecode is a broadcast and post-production standard for addressing video frames. It is often used for video burn-in timecode (BITC), and display in a DAW (Digital Audio Workstation) or video playback/editing applications.
1012

1113
## Supported Timecode Frame Rates
1214

13-
The following timecode rates and formats are supported.
15+
The following timecode rates and formats are supported:
1416

1517
| Film / ATSC / HD | PAL / SECAM / DVB / ATSC | NTSC / ATSC / PAL-M | NTSC Non-Standard | ATSC / HD |
1618
| ---------------- | ------------------------ | ------------------- | ----------------- | --------- |
@@ -24,7 +26,7 @@ The following timecode rates and formats are supported.
2426

2527
## Supported Video Frame Rates
2628

27-
The following video frame rates are supported. (Video rates)
29+
The following video frame rates are supported:
2830

2931
| Film / HD | PAL | NTSC |
3032
| --------- | --------- | --------------- |
@@ -38,14 +40,13 @@ The following video frame rates are supported. (Video rates)
3840

3941
## Core Features
4042

41-
- Convert timecode between:
43+
- Convert timecode to/from:
4244
- timecode display string
4345
- total elapsed frame count
4446
- real wall-clock time
4547
- elapsed audio samples at any audio sample rate
4648
- rational time notation (such as `CMTime` or Final Cut Pro XML and AAF encoding)
4749
- feet + frames
48-
- Convert timecode and/or frame rate to a rational fraction, and vice-versa (including `CMTime`)
4950
- Support for Days as a timecode component (some DAWs including Cubase support > 24 hour timecode)
5051
- Support for Subframes
5152
- Math operations: add, subtract, multiply, divide
@@ -74,7 +75,7 @@ To add this package to a Swift package, add the dependency to your package and t
7475
```swift
7576
let package = Package(
7677
dependencies: [
77-
.package(url: "https://github.com/orchetect/swift-timecode", from: "3.0.0")
78+
.package(url: "https://github.com/orchetect/swift-timecode", from: "3.1.0")
7879
],
7980
targets: [
8081
.target(
@@ -88,6 +89,8 @@ let package = Package(
8889

8990
Import the entire library to use all features (core, AV, UI):
9091
```swift
92+
// on Apple platforms, imports Core/AV/UI.
93+
// on Linux, imports Core.
9194
import SwiftTimecode
9295
```
9396

Sources/SwiftTimecode/SwiftTimecode.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@
99
@_documentation(visibility: internal)
1010
@_exported import SwiftTimecodeCore
1111

12+
#if canImport(Darwin)
13+
1214
@_documentation(visibility: internal)
1315
@_exported import SwiftTimecodeAV
1416

1517
@_documentation(visibility: internal)
1618
@_exported import SwiftTimecodeUI
19+
20+
#endif

Sources/SwiftTimecodeCore/API Evolution/SwiftTimecodeCore-API-2.3.0.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Foundation
88

99
// MARK: API Changes in swift-timecode 2.3.0
1010

11+
#if canImport(UniformTypeIdentifiers) && canImport(CoreTransferable)
1112
@_documentation(visibility: internal)
1213
@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
1314
extension Timecode {
@@ -29,6 +30,7 @@ extension Timecode {
2930
try await self.init(from: itemProviders, propertiesForString: propertiesForTimecodeString)
3031
}
3132
}
33+
#endif
3234

3335
@_documentation(visibility: internal)
3436
extension String {

Sources/SwiftTimecodeCore/Timecode/Protocol Adoptions/Comparable.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// © 2020-2025 Steffan Andrews • Licensed under MIT License
55
//
66

7-
import Darwin
87
import Foundation
98

109
extension Timecode: Equatable {

Sources/SwiftTimecodeCore/Timecode/Protocol Adoptions/Strideable.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
// © 2020-2025 Steffan Andrews • Licensed under MIT License
55
//
66

7+
#if canImport(Darwin)
78
import Darwin
9+
#elseif canImport(Glibc)
10+
import Glibc
11+
#elseif canImport(Musl)
12+
import Musl
13+
#endif
814

915
extension Timecode: Strideable {
1016
public typealias Stride = Int

Sources/SwiftTimecodeCore/Timecode/Source/Timecode String.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@
66

77
import Foundation
88

9-
#if os(macOS)
10-
import AppKit
11-
#elseif os(iOS) || os(tvOS) || os(watchOS) || os(visionOS)
12-
import UIKit
13-
#endif
14-
159
// MARK: - FormattedTimecodeSource
1610

1711
extension String: _FormattedTimecodeSource {

Sources/SwiftTimecodeCore/Utilities/Outsourced/FloatingPoint and Darwin.swift

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010
/// ----------------------------------------------
1111

1212
#if canImport(Darwin)
13-
1413
import Darwin
14+
#elseif canImport(Glibc)
15+
import Glibc
16+
#elseif canImport(Musl)
17+
import Musl
18+
#endif
1519

1620
// MARK: - ceiling / floor
1721

@@ -20,14 +24,26 @@ extension FloatingPoint {
2024
/// (Functional convenience method)
2125
@_disfavoredOverload
2226
package var ceiling: Self {
27+
#if canImport(Darwin)
2328
Darwin.ceil(self)
29+
#elseif canImport(Glibc)
30+
Glibc.ceil(self)
31+
#elseif canImport(Musl)
32+
Musl.ceil(self)
33+
#endif
2434
}
2535

2636
/// Same as `floor()`
2737
/// (Functional convenience method)
2838
@_disfavoredOverload
2939
package var floor: Self {
40+
#if canImport(Darwin)
3041
Darwin.floor(self)
42+
#elseif canImport(Glibc)
43+
Glibc.floor(self)
44+
#elseif canImport(Musl)
45+
Musl.floor(self)
46+
#endif
3147
}
3248
}
3349

@@ -126,5 +142,3 @@ extension FloatingPoint {
126142
integralAndFraction.fraction
127143
}
128144
}
129-
130-
#endif

Sources/SwiftTimecodeCore/Utilities/Outsourced/NSAttributedString.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99
/// ----------------------------------------------
1010
/// ----------------------------------------------
1111

12-
#if canImport(Foundation)
12+
#if canImport(Darwin)
13+
import struct Foundation.NSRange
14+
import class Foundation.NSAttributedString
15+
import class Foundation.NSMutableAttributedString
1316

1417
#if os(macOS)
15-
import AppKit
18+
import class AppKit.NSMutableParagraphStyle
19+
import enum AppKit.NSTextAlignment
1620
#else
17-
import UIKit
21+
import class UIKit.NSMutableParagraphStyle
22+
import enum UIKit.NSTextAlignment
1823
#endif
1924

2025
extension NSAttributedString {

0 commit comments

Comments
 (0)