Skip to content

Commit f081ef8

Browse files
committed
Added Codable conformance
1 parent 00dabe2 commit f081ef8

File tree

8 files changed

+118
-33
lines changed

8 files changed

+118
-33
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ A robust multiplatform Swift library for working with SMPTE timecode supporting
4444
- Common math operations between timecodes: add, subtract, multiply, divide
4545
- Form a `Range` or `Stride` between two timecodes
4646
- Exhaustive unit tests ensuring accuracy
47+
- Conforms to `Codable`
4748

4849
## Installation
4950

Sources/TimecodeKit/FrameRate/FrameRate.swift

+21-21
Original file line numberDiff line numberDiff line change
@@ -12,113 +12,113 @@ extension Timecode {
1212

1313
// MARK: - FrameRate
1414

15-
public enum FrameRate: Int {
15+
public enum FrameRate: String, Codable {
1616

1717
/// 23.976 fps (aka 23.98)
1818
///
1919
/// Also known as 24p for HD video, sometimes rounded up to 23.98 fps. started out as the format for dealing with 24fps film in a NTSC post environment.
20-
case _23_976
20+
case _23_976 = "23.976"
2121

2222
/// 24 fps
2323
///
2424
/// (film, ATSC, 2k, 4k, 6k)
25-
case _24
25+
case _24 = "24"
2626

2727
/// 24.98 fps
2828
///
2929
/// This frame rate is commonly used to facilitate transfers between PAL and NTSC video and film sources. It is mostly used to compensate for some error.
30-
case _24_98
30+
case _24_98 = "24.98"
3131

3232
/// 25 fps
3333
///
3434
/// (PAL, used in Europe, Uruguay, Argentina, Australia), SECAM, DVB, ATSC)
35-
case _25
35+
case _25 = "25"
3636

3737
/// 29.97 fps (30p)
3838
///
3939
/// (NTSC American System (US, Canada, Mexico, Colombia, etc.), ATSC, PAL-M (Brazil))
4040
/// (30 / 1.001) frame/sec
41-
case _29_97
41+
case _29_97 = "29.97"
4242

4343
/// 29.97 drop fps
44-
case _29_97_drop
44+
case _29_97_drop = "29.97d"
4545

4646
/// 30 fps
4747
///
4848
/// (ATSC) This is the frame count of NTSC broadcast video. However, the actual frame rate or speed of the video format runs at 29.97 fps.
4949
///
5050
/// This timecode clock does not run in realtime. It is slightly slower by 0.1%.
5151
/// ie: 1:00:00:00:00 at 30 fps is approx 1:00:00:00;02 in 29.97df
52-
case _30
52+
case _30 = "30"
5353

5454
/// 30 drop fps:
5555
///
5656
/// The 30 fps drop-frame count is an adaptation that allows a timecode display running at 29.97 fps to actually show the clock-on-the-wall-time of the timeline by “dropping” or skipping specific frame numbers in order to “catch the clock up” to realtime.
57-
case _30_drop
57+
case _30_drop = "30d"
5858

5959
/// 47.952 (48p?)
6060
///
6161
/// Double 23.976 fps
62-
case _47_952
62+
case _47_952 = "47.952"
6363

6464
/// 48 fps
6565
///
6666
/// Double 24 fps
67-
case _48
67+
case _48 = "48"
6868

6969
/// 50 fps
7070
///
7171
/// Double 25 fps
72-
case _50
72+
case _50 = "50"
7373

7474
/// 59.94 fps
7575
///
7676
/// Double 29.97 fps
7777
///
7878
/// This video frame rate is supported by high definition cameras and is compatible with NTSC (29.97 fps).
79-
case _59_94
79+
case _59_94 = "59.94"
8080

8181
/// 59.94 drop fps
8282
///
8383
/// Double 29.97 drop fps
84-
case _59_94_drop
84+
case _59_94_drop = "59.94d"
8585

8686
/// 60 fps
8787
///
8888
/// Double 30 fps
8989
///
9090
/// This video frame rate is supported by many high definition cameras. However, the NTSC compatible 59.94 fps frame rate is much more common.
91-
case _60
91+
case _60 = "60"
9292

9393
/// 60 drop fps
9494
///
9595
/// Double 30 fps
96-
case _60_drop
96+
case _60_drop = "60d"
9797

9898
/// 100 fps
9999
///
100100
/// Double 50 fps / quadruple 25 fps
101-
case _100
101+
case _100 = "100"
102102

103103
/// 119.88 fps
104104
///
105105
/// Double 59.94 fps / quadruple 29.97 fps
106-
case _119_88
106+
case _119_88 = "119.88"
107107

108108
/// 119.88 drop fps
109109
///
110110
/// Double 59.94 drop fps / quadruple 29.97 drop fps
111-
case _119_88_drop
111+
case _119_88_drop = "119.88d"
112112

113113
/// 120 fps
114114
///
115115
/// Double 60 fps / quadruple 30 fps
116-
case _120
116+
case _120 = "120"
117117

118118
/// 120 drop fps
119119
///
120120
/// Double 60 fps drop / quadruple 30 fps drop
121-
case _120_drop
121+
case _120_drop = "120d"
122122

123123
}
124124

Sources/TimecodeKit/TimeValue/TimeValue.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import Foundation
1111
/// Primitive struct to represent real time.
1212
///
1313
/// In effort to retain precision, the value used when initializing will be stored unchanged, but can be accessed by either accessor. The backing value can be read as either `.seconds` or `.ms`. If the original format's property is get, the backing value will be returned unchanged. Otherwise it will be converted when needed when the properties are accessed.
14-
public struct TimeValue {
14+
public struct TimeValue: Codable {
1515

1616
// MARK: Data backing
1717

18-
private let msValue: Double?
18+
internal let msValue: Double?
1919

20-
private let secondsValue: Double?
20+
internal let secondsValue: Double?
2121

2222
// MARK: Public properties
2323

@@ -101,10 +101,10 @@ extension TimeValue: Comparable {
101101
extension TimeValue {
102102

103103
/// Enum describing units of time, as stored by `TimeValue`
104-
public enum UnitBacking {
104+
public enum UnitBacking: String, Codable {
105105

106-
case ms
107-
case seconds
106+
case ms = "ms"
107+
case seconds = "seconds"
108108

109109
}
110110

Sources/TimecodeKit/Timecode.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010

1111

1212
/// Object representing SMPTE timecode data with a variety of number- and string- based constructors, including helper functions to convert between them operators to perform math operations between them.
13-
public struct Timecode {
13+
public struct Timecode: Codable {
1414

1515
// MARK: - Immutable properties
1616

Sources/TimecodeKit/UpperLimit/UpperLimit.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import Foundation
1111
extension Timecode {
1212

1313
/// Enum describing the maximum timecode ceiling.
14-
public enum UpperLimit: Int {
14+
public enum UpperLimit: String, Codable {
1515

1616
/// Pro Tools' upper limit is "23:59:59:FF" which is 1 day (24 hours) in duration.
17-
case _24hours
17+
case _24hours = "24 hours"
1818

1919
/// Cubase's upper limit is "99 23:59:59:FF" which is 100 days in duration.
20-
case _100days
20+
case _100days = "100 days"
2121

2222
/// Internal use.
2323
internal var maxDays: Int {

Tests/TimecodeKit-Unit-Tests/Unit Tests/TimeValue/TimeValue Tests.swift

+37
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,41 @@ class TimeValue_UT_Tests: XCTestCase {
6262

6363
}
6464

65+
func testCodable() {
66+
67+
// set up JSON coders with default settings
68+
69+
let encoder = JSONEncoder()
70+
let decoder = JSONDecoder()
71+
72+
// set up a TimeValue object that has all non-defaults
73+
74+
let time = 50505050.123456789123456789
75+
76+
let ott1 = TimeValue(ms: time)
77+
78+
// encode
79+
80+
guard let encoded = try? encoder.encode(ott1)
81+
else {
82+
XCTFail("JSON encode failed.") ; return
83+
}
84+
85+
// decode
86+
87+
guard let decoded = try? decoder.decode(TimeValue.self, from: encoded)
88+
else {
89+
XCTFail("JSON decode failed.") ; return
90+
}
91+
92+
// compare original to reconstructed
93+
94+
XCTAssertEqual(ott1, decoded)
95+
96+
XCTAssertEqual(ott1.msValue, decoded.msValue)
97+
XCTAssertEqual(ott1.secondsValue, decoded.secondsValue)
98+
XCTAssertEqual(ott1.backing, decoded.backing)
99+
100+
}
101+
65102
}

Tests/TimecodeKit-Unit-Tests/Unit Tests/Timecode String Extensions Tests.swift

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ class Timecode_UT_Swift_Extensions_Tests: XCTestCase {
1414
override func setUp() { }
1515
override func tearDown() { }
1616

17-
1817
func testString_toTimeCode() {
1918

2019
XCTAssertEqual("01:05:20:14".toTimecode(at: ._23_976),

Tests/TimecodeKit-Unit-Tests/Unit Tests/Timecode Tests.swift

+49-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,54 @@ class Timecode_UT_Tests: XCTestCase {
1414
override func setUp() { }
1515
override func tearDown() { }
1616

17-
// no tests in this file
17+
func testCodable() {
18+
19+
// set up JSON coders with default settings
20+
21+
let encoder = JSONEncoder()
22+
let decoder = JSONDecoder()
23+
24+
Timecode.FrameRate.allCases.forEach {
25+
26+
// set up a timecode object that has all non-defaults
27+
28+
var tc = "1 12:34:56:11.85"
29+
.toTimecode(at: $0,
30+
limit: ._100days,
31+
subFramesDivisor: 100)!
32+
33+
tc.displaySubFrames = true
34+
35+
// encode
36+
37+
guard let encoded = try? encoder.encode(tc)
38+
else {
39+
XCTFail("JSON encode failed.") ; return
40+
}
41+
42+
// decode
43+
44+
guard let decoded = try? decoder.decode(Timecode.self, from: encoded)
45+
else {
46+
XCTFail("JSON decode failed.") ; return
47+
}
48+
49+
// compare original to reconstructed
50+
51+
XCTAssertEqual(tc, decoded)
52+
53+
XCTAssertEqual(tc.days, decoded.days)
54+
XCTAssertEqual(tc.hours, decoded.hours)
55+
XCTAssertEqual(tc.minutes, decoded.minutes)
56+
XCTAssertEqual(tc.seconds, decoded.seconds)
57+
XCTAssertEqual(tc.frames, decoded.frames)
58+
XCTAssertEqual(tc.frameRate, decoded.frameRate)
59+
XCTAssertEqual(tc.upperLimit, decoded.upperLimit)
60+
XCTAssertEqual(tc.subFramesDivisor, decoded.subFramesDivisor)
61+
XCTAssertEqual(tc.displaySubFrames, decoded.displaySubFrames)
62+
63+
}
64+
65+
}
1866

1967
}

0 commit comments

Comments
 (0)