WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 0a57a42

Browse files
authored
Merge pull request #52 from orchetect/2.0.0
OSCKit 2.0.0
2 parents 9476d5d + df8d4c0 commit 0a57a42

File tree

124 files changed

+5326
-4180
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+5326
-4180
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,7 @@ jobs:
4040
run: xcodebuild build -workspace ".swiftpm/xcode/package.xcworkspace" -scheme "$SCHEME" -destination "generic/platform=macOS" | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]}
4141
- name: Unit Tests
4242
run: xcodebuild test -workspace ".swiftpm/xcode/package.xcworkspace" -scheme "$SCHEME" -destination "platform=macOS" | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]}
43-
44-
macOS-swift6:
45-
name: macOS (Swift 6.0)
46-
runs-on: macos-latest
47-
steps:
48-
- uses: actions/checkout@main
49-
- uses: maxim-lobanov/setup-xcode@v1
50-
with:
51-
xcode-version: latest-stable
52-
- name: Set Package to Swift 6.0
53-
run: swift package tools-version --set "6.0"
54-
- name: Build
55-
run: xcodebuild build -workspace ".swiftpm/xcode/package.xcworkspace" -scheme "$SCHEME" -destination "generic/platform=macOS" | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]}
56-
- name: Unit Tests
57-
run: xcodebuild test -workspace ".swiftpm/xcode/package.xcworkspace" -scheme "$SCHEME" -destination "platform=macOS" | xcbeautify --renderer github-actions && exit ${PIPESTATUS[0]}
58-
43+
5944
macCatalyst:
6045
name: macCatalyst
6146
runs-on: macos-latest

Examples/Custom Type/Custom OSC Type/CustomType.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import OSCKitCore
99

1010
// NOTE:
1111
// In this basic example, we've chosen to use the underlying OSC Type "blob", which is essentially raw data, as our
12-
// underlying data storage chunk within an OSC message, since our object conforms to Codable and it's easily converted
12+
// underlying data storage chunk within an OSC message, since our type conforms to Codable and it's easily converted
1313
// to/from Data.
1414
//
1515
// Since we've chosen to use JSONEncoder, and JSON is technically text (string) block, we could have also chosen
@@ -33,16 +33,18 @@ extension CustomType: OSCValueCodable {
3333
// uses an OSC Type Tag that already exists.
3434
// For a reference of existing OSC Type Tags, see the OSC 1.0 spec online.
3535
static let oscTag: Character = "j"
36-
// atomic indicates that the tag is static and will never change based on its data content
37-
static let oscTagIdentity: OSCValueTagIdentity = .atomic(oscTag)
36+
37+
// establishes that the tag is static and will never change based on its data payload
38+
static let oscTagIdentity: OSCValueTagIdentity = .tag(oscTag)
3839
}
3940

4041
extension CustomType: OSCValueEncodable {
41-
public typealias OSCValueEncodingBlock = OSCValueAtomicEncoder<OSCEncoded>
42-
static let oscEncoding = OSCValueEncodingBlock { value in
42+
static let oscEncoding = OSCValueStaticTagEncoder<Self> { value throws(OSCEncodeError) in
4343
// Encode our Codable type instance into raw data
4444
let encoder = JSONEncoder()
45-
let jsonData = try encoder.encode(value)
45+
let jsonData: Data
46+
do { jsonData = try encoder.encode(value) }
47+
catch { throw .valueEncodingError(error.localizedDescription) }
4648

4749
// OSCValueEncodingBlock makes it our responsibility to make sure OSB blob (data) is encoded correctly,
4850
// including a 4-byte big-endian Int32 length header and trailing null-byte padding to an alignment of 4 bytes.
@@ -53,16 +55,17 @@ extension CustomType: OSCValueEncodable {
5355
}
5456

5557
extension CustomType: OSCValueDecodable {
56-
public typealias OSCValueDecodingBlock = OSCValueAtomicDecoder<OSCDecoded>
57-
static let oscDecoding = OSCValueDecodingBlock { dataReader in
58+
static let oscDecoding = OSCValueStaticTagDecoder<Self> { dataReader throws(OSCDecodeError) in
5859
let decoder = JSONDecoder()
5960

6061
// Gets entire data chunk from the OSC blob, stripping the length bytes and null padding suffix
6162
// and returning the actual data content
6263
let data = try dataReader.readBlob()
6364

6465
// Decode into a new instance of our Codable type
65-
let decoded = try decoder.decode(CustomType.self, from: data)
66+
let decoded: CustomType
67+
do { decoded = try decoder.decode(CustomType.self, from: data) }
68+
catch { throw .valueDecodingError(error.localizedDescription) }
6669
return decoded
6770
}
6871
}

Examples/Custom Type/Custom OSC Type/OSCManager.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Foundation
88
import OSCKit
99

1010
/// OSC lifecycle and send/receive manager.
11-
final class OSCManager: ObservableObject, Sendable {
11+
@MainActor final class OSCManager: ObservableObject {
1212
private let client = OSCUDPClient()
1313
private let server = OSCUDPServer(port: 8000)
1414

@@ -29,13 +29,15 @@ extension OSCManager {
2929
/// Call this once on app launch.
3030
func start() {
3131
// setup client
32-
do { try client.start() } catch { print(error) }
32+
do { try client.start() } catch { print(error.localizedDescription) }
3333

3434
// setup server
3535
server.setReceiveHandler { [weak self] message, timeTag, host, port in
36-
self?.handle(message: message, timeTag: timeTag, host: host, port: port)
36+
Task { @MainActor in
37+
self?.handle(message: message, timeTag: timeTag, host: host, port: port)
38+
}
3739
}
38-
do { try server.start() } catch { print(error) }
40+
do { try server.start() } catch { print(error.localizedDescription) }
3941
}
4042

4143
func stop() {
@@ -66,11 +68,11 @@ extension OSCManager {
6668
// MARK: - Send
6769

6870
extension OSCManager {
69-
func send(_ message: OSCMessage, to host: String, port: UInt16) {
71+
func send(_ packet: OSCPacket, to host: String, port: UInt16) {
7072
do {
71-
try client.send(message, to: host, port: port)
73+
try client.send(packet, to: host, port: port)
7274
} catch {
73-
print(error)
75+
print(error.localizedDescription)
7476
}
7577
}
7678
}

Examples/Method Blocks/OSC Method Blocks/ContentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct ContentView: View {
2828
sendTestOSCMessageCWithOptionalValue()
2929
}
3030

31-
Button("Send Test OSC Message C With No Optional Value") {
31+
Button("Send Test OSC Message C With Missing Optional Value") {
3232
sendTestOSCMessageCWithNoOptionalValue()
3333
}
3434
}

Examples/Method Blocks/OSC Method Blocks/OSCManager.swift

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

1010
/// OSC lifecycle and send/receive manager.
11-
final class OSCManager: ObservableObject, Sendable {
11+
@MainActor final class OSCManager: ObservableObject {
1212
private let client = OSCUDPClient()
1313
private let server = OSCUDPServer(port: 8000)
1414
private let receiver = OSCReceiver()
@@ -24,17 +24,15 @@ extension OSCManager {
2424
/// Call once at app startup.
2525
func start() {
2626
// setup client
27-
do { try client.start() } catch { print(error) }
27+
do { try client.start() } catch { print(error.localizedDescription) }
2828

2929
// setup server
3030
server.setReceiveHandler { [weak self] message, timeTag, host, port in
31-
do {
32-
try self?.receiver.handle(message: message, timeTag: timeTag, host: host, port: port)
33-
} catch {
34-
print(error)
31+
Task {
32+
await self?.receiver.handle(message: message, timeTag: timeTag, host: host, port: port)
3533
}
3634
}
37-
do { try server.start() } catch { print(error) }
35+
do { try server.start() } catch { print(error.localizedDescription) }
3836
}
3937

4038
func stop() {
@@ -54,7 +52,7 @@ extension OSCManager {
5452
do {
5553
try client.send(message, to: host, port: port)
5654
} catch {
57-
print(error)
55+
print(error.localizedDescription)
5856
}
5957
}
6058
}

Examples/Method Blocks/OSC Method Blocks/OSCReceiver.swift

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,34 @@ final class OSCReceiver: Sendable {
1414
private let addressSpace = OSCAddressSpace()
1515

1616
public init() {
17-
// Register local OSC method and supply a closure block
18-
addressSpace.register(localAddress: "/methodA") { values, host, port in
17+
Task { await setup() }
18+
}
19+
20+
private func setup() async {
21+
// A) Register local OSC method and supply a closure block
22+
await addressSpace.register(localAddress: "/methodA") { values, host, port in
1923
guard let str = try? values.masked(String.self) else { return }
2024
print("Received methodA from \(host) port \(port) with value: \"\(str)\"")
2125
}
2226

23-
// Register local OSC method and supply a closure block
24-
addressSpace.register(localAddress: "/some/address/methodB") { values, host, port in
27+
// B) Register local OSC method and supply a closure block
28+
await addressSpace.register(localAddress: "/some/address/methodB") { values, host, port in
2529
guard let (str, int) = try? values.masked(String.self, Int.self) else { return }
2630
print("Received methodB from \(host) port \(port) with values: [\"\(str)\", \(int)]")
2731
}
2832

2933
// Instead of supplying a closure, it's also possible to forward to a function:
3034

31-
// Option 1: weak reference (recommended):
32-
addressSpace.register(
35+
// C) Option 1: weak reference (recommended):
36+
await addressSpace.register(
3337
localAddress: "/some/address/methodC",
3438
block: { [weak self] values, host, port in
3539
self?.handleMethodC(values: values, host: host, port: port)
3640
}
3741
)
3842

39-
// Option 2: strong reference (discouraged):
40-
// addressSpace.register(
43+
// C) Option 2: strong reference (discouraged):
44+
// await addressSpace.register(
4145
// localAddress: "/some/address/methodC",
4246
// block: handleMethodC
4347
// )
@@ -48,9 +52,9 @@ final class OSCReceiver: Sendable {
4852
print("Received methodC from \(host) port \(port) with values: [\"\(str)\", \(dbl as Any)]")
4953
}
5054

51-
public func handle(message: OSCMessage, timeTag: OSCTimeTag, host: String, port: UInt16) throws {
55+
public func handle(message: OSCMessage, timeTag: OSCTimeTag, host: String, port: UInt16) async {
5256
// Execute closures for matching methods, and returns the matching method IDs
53-
let methodIDs = addressSpace.dispatch(message: message, host: host, port: port)
57+
let methodIDs = await addressSpace.dispatch(message: message, host: host, port: port)
5458

5559
// If no IDs are returned, it means that the OSC message address pattern did not match any
5660
// that were registered

Examples/Method IDs/OSC Method IDs/ContentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct ContentView: View {
2828
sendTestOSCMessageCWithOptionalValue()
2929
}
3030

31-
Button("Send Test OSC Message C With No Optional Value") {
31+
Button("Send Test OSC Message C With Missing Optional Value") {
3232
sendTestOSCMessageCWithNoOptionalValue()
3333
}
3434
}

Examples/Method IDs/OSC Method IDs/OSCManager.swift

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,37 @@ import Foundation
88
import OSCKit
99

1010
/// OSC lifecycle and send/receive manager.
11-
final class OSCManager: ObservableObject, Sendable {
11+
@MainActor final class OSCManager: ObservableObject {
1212
private let client = OSCUDPClient()
1313
private let server = OSCUDPServer(port: 8000)
14-
private let receiver = OSCReceiver()
14+
private var receiver: OSCReceiver?
1515

1616
init() {
17-
start()
17+
Task { await start() }
1818
}
1919
}
2020

2121
// MARK: - Lifecycle
2222

2323
extension OSCManager {
2424
/// Call once at app startup.
25-
func start() {
25+
func start() async {
2626
// setup client
27-
do { try client.start() } catch { print(error) }
27+
do { try client.start() } catch { print(error.localizedDescription) }
28+
29+
receiver = await OSCReceiver()
2830

2931
// setup server
3032
server.setReceiveHandler { [weak self] message, timeTag, host, port in
31-
do {
32-
try self?.receiver.handle(message: message, timeTag: timeTag, host: host, port: port)
33-
} catch {
34-
print(error)
33+
Task {
34+
do {
35+
try await self?.receiver?.handle(message: message, timeTag: timeTag, host: host, port: port)
36+
} catch {
37+
print(error.localizedDescription)
38+
}
3539
}
3640
}
37-
do { try server.start() } catch { print(error) }
41+
do { try server.start() } catch { print(error.localizedDescription) }
3842
}
3943

4044
func stop() {
@@ -50,7 +54,7 @@ extension OSCManager {
5054
do {
5155
try client.send(message, to: host, port: port)
5256
} catch {
53-
print(error)
57+
print(error.localizedDescription)
5458
}
5559
}
5660
}

Examples/Method IDs/OSC Method IDs/OSCReceiver.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ final class OSCReceiver: Sendable {
1717
private let idMethodB: OSCAddressSpace.MethodID
1818
private let idMethodC: OSCAddressSpace.MethodID
1919

20-
public init() {
20+
public init() async {
2121
// register local OSC methods and store the ID tokens once before receiving OSC messages
22-
idMethodA = addressSpace.register(localAddress: "/methodA")
23-
idMethodB = addressSpace.register(localAddress: "/some/address/methodB")
24-
idMethodC = addressSpace.register(localAddress: "/some/address/methodC")
22+
idMethodA = await addressSpace.register(localAddress: "/methodA")
23+
idMethodB = await addressSpace.register(localAddress: "/some/address/methodB")
24+
idMethodC = await addressSpace.register(localAddress: "/some/address/methodC")
2525
}
2626

27-
public func handle(message: OSCMessage, timeTag: OSCTimeTag, host: String, port: UInt16) throws {
28-
let ids = addressSpace.methods(matching: message.addressPattern)
27+
public func handle(message: OSCMessage, timeTag: OSCTimeTag, host: String, port: UInt16) async throws {
28+
let ids = await addressSpace.methods(matching: message.addressPattern)
2929

3030
guard !ids.isEmpty else {
3131
// No matches against any registered local OSC addresses.

Examples/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# OSCKit Examples
22

3-
These example projects are provided to demonstrate using OSCKit.
3+
These example projects are provided to demonstrate using OSCKit on Apple platforms.
44

55
They will build for all platforms including macOS, iOS, tvOS and visionOS, and can be run in device simulators.
66

77
## Build Note
88

9-
If Xcode builds but the app does not run, it may be because Xcode is defaulting to the wrong Scheme. Ensure the example app's Scheme is selected then try again.
9+
> [!TIP]
10+
>
11+
> If Xcode builds but the app does not run, it may be because Xcode is defaulting to the wrong Scheme. Ensure the example app's Scheme is selected then try again.

0 commit comments

Comments
 (0)