Skip to content

Commit

Permalink
Re-structured docs for docc combined documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
orchetect committed Oct 16, 2024
1 parent fca3dff commit ceea1f2
Show file tree
Hide file tree
Showing 37 changed files with 226 additions and 131 deletions.
9 changes: 8 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// swift-tools-version: 5.9
// (be sure to update the .swift-version file when this Swift version changes)

import Foundation
import PackageDescription

let package = Package(
Expand All @@ -22,7 +23,7 @@ let package = Package(
dependencies: [
// used only for Dev tests, not part of regular unit tests
// .package(url: "https://github.com/orchetect/XCTestUtils", from: "1.0.3")
],
] + doccPluginDependency(),
targets: [
// umbrella target
.target(
Expand Down Expand Up @@ -82,3 +83,9 @@ let package = Package(
)
]
)

func doccPluginDependency() -> [Package.Dependency] {
ProcessInfo.processInfo.environment["ENABLE_DOCC_PLUGIN"] != nil
? [.package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.4.3")]
: []
}
29 changes: 29 additions & 0 deletions Sources/TimecodeKit/Documentation.docc/Documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ``TimecodeKit``

Value types, AV methods and UI components for representing and working with SMPTE/EBU timecode.

![TimecodeKit](timecodekit-banner.png)

For core types, math, and conversions see **TimecodeKitCore** documentation.

For AVFoundation methods, see **TimecodeKitAV** documentation.

For UI components, see **TimecodeKitUI** documentation.

## Topics

### Welcome

- <doc:Getting-Started>
- <doc:TimecodeKit-2-Migration-Guide>

### Modules

- <doc:TimecodeKikCore>
- <doc:TimecodeKikCoreAV>
- <doc:TimecodeKikCoreUI>

### Formats Addendum

- <doc:LTC-Linear-Timecode>
- <doc:MTC-MIDI-Timecode>
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@

Documentation and guides to get the most out of TimecodeKit.

Add the library to your app project or Swift package, and import it.
## Import

All modules in the library can be imported to your app project or Swift package using an umbrella import.

```swift
import TimecodeKit
```

If only certain modules are needed, they may instead be imported individually.

The library provides UI components that may also be imported if desired.

```swift
import TimecodeKitCore
import TimecodeKitAV
import TimecodeKitUI
```

The documentation page for ``Timecode`` provides a quick overview of how to form timecode and convert to/from various other time values.
## Using TimecodeKit

The documentation page for ``TimecodeKitCore/Timecode`` provides a quick overview of how to form timecode and convert to/from various other time values.

Example projects are located in the Examples folder to demonstrate usage of the library.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ MIDI Timecode is a device synchronization protocol that encodes SPMTE timecode u
TimecodeKit does not implement MTC encoding or decoding directly.

Instead, [MIDIKit](https://github.com/orchetect/MIDIKit) (an open-source Swift MIDI I/O package for all Apple platforms) implements MTC encoding/decoding.
It imports TimecodeKit as a dependency and uses ``Timecode`` and ``TimecodeFrameRate`` as data structures.
It imports TimecodeKit as a dependency and uses ``TimecodeKitCore/Timecode`` and ``TimecodeKitCore/TimecodeFrameRate`` as data structures.

## References

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ Timecode(.string("01:00:00:00"), at: .fps24, by: .allowingInvalid)

## Timecode String Value

- The `stringValue` property is now the ``Timecode/stringValue(format:)`` method.
- The Timecode struct no longer stores string formatting properties. Instead, formatting options are now optionally passed when calling ``Timecode/stringValue(format:)``.
- The `stringValue` property is now the ``TimecodeKitCore/Timecode/stringValue(format:)`` method.
- The Timecode struct no longer stores string formatting properties. Instead, formatting options are now optionally passed when calling ``TimecodeKitCore/Timecode/stringValue(format:)``.

```swift
// 1.x API
Expand Down Expand Up @@ -106,7 +106,7 @@ let timecode = try Timecode(
)
```

Timecode metadata can now also be constructed and passed using a new ``Timecode/Properties-swift.struct`` struct. It contains:
Timecode metadata can now also be constructed and passed using a new ``TimecodeKitCore/Timecode/Properties-swift.struct`` struct. It contains:

- `frameRate`
- `subFramesBase`
Expand Down Expand Up @@ -168,17 +168,17 @@ try "01:00:00:00".toTimecode(at: ._24)

Some enum cases have been renamed to conform to lowerCamelCase and replace underscore prefixes.

- ``TimecodeFrameRate`` cases have been renamed.
- ``TimecodeKitCore/TimecodeFrameRate`` cases have been renamed.
- `._24` is now `.fps24` and so on
- ``VideoFrameRate`` cases have been renamed.
- ``TimecodeKitCore/VideoFrameRate`` cases have been renamed.
- `._24p` is now `.fps24p` and so on
- ``Timecode/UpperLimit-swift.enum`` cases have been renamed.
- ``TimecodeKitCore/Timecode/UpperLimit-swift.enum`` cases have been renamed.
- `._24hours` is now `.max24Hours`
- `._100days` is now `.max100Days`
- ``Timecode/SubFramesBase-swift.enum`` cases have been renamed.
- ``TimecodeKitCore/Timecode/SubFramesBase-swift.enum`` cases have been renamed.
- `._80SubFrames` is now `.max80SubFrames`
- `._100SubFrames` is now `.max100SubFrames`
- ``TimecodeFrameRate/CompatibleGroup-swift.enum`` cases have been renamed.
- ``TimecodeKitCore/TimecodeFrameRate/CompatibleGroup-swift.enum`` cases have been renamed.
- `.NTSC` is now `.ntscColor`
- `.NTSC_drop` is now `.ntscDrop`
- `.ATSC` is now `.whole`
Expand Down
5 changes: 5 additions & 0 deletions Sources/TimecodeKit/TimecodeKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

// Welcome to TimecodeKit :)

@_documentation(visibility: internal)
@_exported import TimecodeKitCore

@_documentation(visibility: internal)
@_exported import TimecodeKitAV

@_documentation(visibility: internal)
@_exported import TimecodeKitUI
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extension AVAsset {
/// that may be contained in the asset. If `nil`, drop-frame information is contained in the
/// asset is used, defaulting to `false`.
///
/// - Throws: ``Timecode/MediaParseError``
/// - Throws: ``TimecodeKitAV/TimecodeKitCore/Timecode/MediaParseError``
@_disfavoredOverload
public func timecodeFrameRate(drop: Bool? = nil) async throws -> TimecodeFrameRate {
// a timecode track does not contain frame rate information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extension AVAsset {
/// Passing a value to `frameRate` will override frame rate detection.
/// Passing `nil` will detect frame rate from the asset's contents if possible.
///
/// - Throws: ``Timecode/MediaParseError``
/// - Throws: ``TimecodeKitCore/Timecode/MediaParseError``
@_disfavoredOverload
public func startTimecode(
at frameRate: TimecodeFrameRate? = nil,
Expand All @@ -44,7 +44,7 @@ extension AVAsset {
/// Passing a value to `frameRate` will override frame rate detection.
/// Passing `nil` will detect frame rate from the asset's contents if possible.
///
/// - Throws: ``Timecode/MediaParseError`` or ``Timecode/ValidationError``
/// - Throws: ``TimecodeKitAV/TimecodeKitCore/Timecode/MediaParseError`` or `Timecode.ValidationError`
@_disfavoredOverload
public func endTimecode(
at frameRate: TimecodeFrameRate? = nil,
Expand Down Expand Up @@ -76,7 +76,7 @@ extension AVAsset {
/// Passing a value to `frameRate` will override frame rate detection.
/// Passing `nil` will detect frame rate from the asset's contents if possible.
///
/// - Throws: ``Timecode/MediaParseError`` or ``Timecode/ValidationError``
/// - Throws: ``TimecodeKitAV/TimecodeKitCore/Timecode/MediaParseError`` or `Timecode.ValidationError`
@_disfavoredOverload
public func durationTimecode(
at frameRate: TimecodeFrameRate? = nil,
Expand All @@ -102,7 +102,7 @@ extension AVAsset {
/// Passing a value to `frameRate` will override frame rate detection.
/// Passing `nil` will detect frame rate from the asset's contents if possible.
///
/// - Throws: ``Timecode/MediaParseError``
/// - Throws: ``TimecodeKitAV/TimecodeKitCore/Timecode/MediaParseError``
@_disfavoredOverload
public func timecodes(
at frameRate: TimecodeFrameRate? = nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ extension AVMutableMovie {
/// Add a timecode track containing one sample (start timecode).
/// Existing timecode track(s) are left unaltered.
/// If `duration` is omitted, the video's duration will be used.
///
/// > IMPORTANT:
/// >
/// > This method will indiscriminately add a timecode track, even if one is already present in the movie. It is not
/// > recommended to have more than one timecode track in a movie, and movie player applications in most cases may
/// > only observe the first one found, as multiple timecode tracks is considered undefined.
/// >
/// > In most scenarios, using ``replaceTimecodeTrack(startTimecode:duration:extensions:fileType:)`` is preferable.
@discardableResult
public func addTimecodeTrack(
startTimecode: Timecode,
Expand Down Expand Up @@ -170,6 +178,7 @@ extension Timecode {
/// Returns a new Core Media format description based on the timecode `frameRate`.
///
/// - Throws: Core Media error.
@_documentation(visibility: internal)
public func cmFormatDescription(
extensions: CMFormatDescription.Extensions? = nil
) throws -> CMTimeCodeFormatDescription {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ extension AVAssetTrack {
/// Passing a value to `frameRate` will override frame rate detection.
/// Passing `nil` will detect frame rate from the asset's contents if possible.
///
/// - Throws: ``Timecode/MediaParseError`` or ``Timecode/ValidationError``
/// - Throws: ``TimecodeKitCore/Timecode/MediaParseError`` or `Timecode.ValidationError`
@_disfavoredOverload
public func durationTimecode(
at frameRate: TimecodeFrameRate? = nil,
Expand Down Expand Up @@ -56,7 +56,7 @@ extension AVAssetTrack {
/// Passing a value to `frameRate` will override frame rate detection.
/// Passing `nil` will detect frame rate from the asset's contents if possible.
///
/// - Throws: ``Timecode/MediaParseError``
/// - Throws: ``TimecodeKitCore/Timecode/MediaParseError``
@_disfavoredOverload
func timecodeRange(
at frameRate: TimecodeFrameRate? = nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,44 +36,6 @@ extension AVAssetTrack {
}
}

extension CMTimeRange {
/// Returns the time range as a timecode range.
///
/// Throws an error if the range is invalid or if one or both of the times cannot be converted
/// to valid timecode.
///
/// - Throws: ``Timecode/MediaParseError``
public func timecodeRange(
at frameRate: TimecodeFrameRate,
base: Timecode.SubFramesBase = .default(),
limit: Timecode.UpperLimit = .max24Hours
) throws -> ClosedRange<Timecode> {
let properties = Timecode.Properties(rate: frameRate, base: base, limit: limit)
return try timecodeRange(using: properties)
}

/// Returns the time range as a timecode range.
///
/// Throws an error if the range is invalid or if one or both of the times cannot be converted
/// to valid timecode.
///
/// - Throws: ``Timecode/MediaParseError``
public func timecodeRange(
using properties: Timecode.Properties
) throws -> ClosedRange<Timecode> {
guard isValid, start <= end else {
throw Timecode.MediaParseError.unknownTimecode
}

let timecodes = try [start, end]
.map {
try Timecode(.cmTime($0), using: properties)
}

return timecodes[0] ... timecodes[1]
}
}

#if !os(tvOS) // AVMediaDataStorage not available on tvOS

@available(macOS 10.11, iOS 13.0, watchOS 6, *)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ try await exportSession.export(to: url, as: .mov)

## Topics

### AVAsset Extensions
### AVAsset Methods

- ``AVFoundation/AVAsset/startTimecode(at:base:limit:)``
- ``AVFoundation/AVAsset/durationTimecode(at:base:limit:)``
Expand All @@ -86,11 +86,16 @@ try await exportSession.export(to: url, as: .mov)
- ``AVFoundation/AVAsset/videoFrameRate(interlaced:)``
- ``AVFoundation/AVAsset/isVideoInterlaced``

### AVAssetTrack Extensions
### AVAssetTrack Methods

- ``AVFoundation/AVAssetTrack/durationTimecode(at:limit:base:)``

### AVMutableMovie Extensions
### AVMutableMovie Methods

- ``AVFoundation/AVMutableMovie/addTimecodeTrack(startTimecode:duration:extensions:fileType:)``
- ``AVFoundation/AVMutableMovie/replaceTimecodeTrack(startTimecode:duration:extensions:fileType:)``

### Errors

- ``TimecodeKitCore/Timecode/MediaParseError``
- ``TimecodeKitCore/Timecode/MediaWriteError``
16 changes: 16 additions & 0 deletions Sources/TimecodeKitAV/Documentation.docc/Documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# ``TimecodeKitAV``

AVFoundation methods for reading and writing timecode tracks to movie files.

![TimecodeKit](timecodekit-banner.png)


## Topics

### AVAsset

- <doc:AVAsset-Timecode-Track>

### VideoFrameRate Initializers

- ``TimecodeKitCore/VideoFrameRate/init(asset:interlaced:)``
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Timecode Errors.swift
// TimecodeKit • https://github.com/orchetect/TimecodeKit
// © 2020-2024 Steffan Andrews • Licensed under MIT License
//

extension Timecode {
public enum MediaParseError: Error {
case missingOrNonStandardFrameRate
case unknownTimecode
case internalError
case noData
}

public enum MediaWriteError: Error {
case internalError
}
}
1 change: 1 addition & 0 deletions Sources/TimecodeKitAV/TimecodeKitAV.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@

// Welcome to TimecodeKit :)

@_documentation(visibility: internal)
@_exported import TimecodeKitCore
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import AVFoundation
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
extension VideoFrameRate {
/// Initialize from embedded frame rate information in an `AVAsset`.
public init(asset: AVAsset) async throws {
self = try await asset.videoFrameRate()
public init(asset: AVAsset, interlaced: Bool? = nil) async throws {
self = try await asset.videoFrameRate(interlaced: interlaced)
}
}

Expand Down
Loading

0 comments on commit ceea1f2

Please sign in to comment.