diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..919434a
--- /dev/null
+++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/Examples/iOS/OSCTest/OSCTest.xcodeproj/project.pbxproj b/Examples/iOS/OSCTest/OSCTest.xcodeproj/project.pbxproj
index 9e0a000..a7ba1f9 100644
--- a/Examples/iOS/OSCTest/OSCTest.xcodeproj/project.pbxproj
+++ b/Examples/iOS/OSCTest/OSCTest.xcodeproj/project.pbxproj
@@ -316,7 +316,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = M4VH59A389;
+ DEVELOPMENT_TEAM = FNLF39495D;
INFOPLIST_FILE = "$(SRCROOT)/OSCTest/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -334,7 +334,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = M4VH59A389;
+ DEVELOPMENT_TEAM = FNLF39495D;
INFOPLIST_FILE = "$(SRCROOT)/OSCTest/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
diff --git a/Examples/macOS/OSCMonitor/OSCMonitor.xcodeproj/project.pbxproj b/Examples/macOS/OSCMonitor/OSCMonitor.xcodeproj/project.pbxproj
index 51270d1..97ff1bb 100644
--- a/Examples/macOS/OSCMonitor/OSCMonitor.xcodeproj/project.pbxproj
+++ b/Examples/macOS/OSCMonitor/OSCMonitor.xcodeproj/project.pbxproj
@@ -108,6 +108,8 @@
dependencies = (
);
name = OSCMonitor;
+ packageProductDependencies = (
+ );
productName = OSCMonitor;
productReference = 033827B21D3999590065A3A7 /* OSCMonitor.app */;
productType = "com.apple.product-type.application";
@@ -124,7 +126,7 @@
TargetAttributes = {
033827B11D3999590065A3A7 = {
CreatedOnToolsVersion = 8.0;
- DevelopmentTeam = 638F7EDPVY;
+ DevelopmentTeam = FNLF39495D;
DevelopmentTeamName = "Devin Roth (Personal Team)";
LastSwiftMigration = 0910;
ProvisioningStyle = Automatic;
@@ -133,13 +135,15 @@
};
buildConfigurationList = 033827AD1D3999590065A3A7 /* Build configuration list for PBXProject "OSCMonitor" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 033827A91D3999590065A3A7;
+ packageReferences = (
+ );
productRefGroup = 033827B31D3999590065A3A7 /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -298,6 +302,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = FNLF39495D;
INFOPLIST_FILE = OSCMonitor/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.14;
@@ -314,6 +319,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = FNLF39495D;
INFOPLIST_FILE = OSCMonitor/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.14;
diff --git a/Examples/macOS/OSCMonitor/OSCMonitor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/macOS/OSCMonitor/OSCMonitor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/Examples/macOS/OSCMonitor/OSCMonitor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/Framework/SwiftOSC/Addresses/OSCAddressPattern.swift b/Framework/SwiftOSC/Addresses/OSCAddressPattern.swift
index d760983..2cf8a80 100644
--- a/Framework/SwiftOSC/Addresses/OSCAddressPattern.swift
+++ b/Framework/SwiftOSC/Addresses/OSCAddressPattern.swift
@@ -180,20 +180,24 @@ public struct OSCAddressPattern {
// Returns True if the address matches the address pattern.
public func matches(_ address: OSCAddress)->Bool{
- if address.string.range(of: self.regex, options: .regularExpression) == nil {
- return false
- } else {
- return true
+ var maches = true
+ autoreleasepool {
+ if address.string.range(of: self.regex, options: .regularExpression) == nil {
+ maches = false
+ }
}
+ return maches
}
// Returns True if the address is along the path of the address pattern
public func matches(path: OSCAddress)->Bool{
- if path.string.range(of: self.regexPath, options: .regularExpression) == nil {
- return false
- } else {
- return true
+ var maches = true
+ autoreleasepool {
+ if path.string.range(of: self.regexPath, options: .regularExpression) == nil {
+ maches = false
+ }
}
+ return maches
}
}
diff --git a/Framework/SwiftOSC/Network/OSCClient.swift b/Framework/SwiftOSC/Network/OSCClient.swift
index 6287434..33cca78 100644
--- a/Framework/SwiftOSC/Network/OSCClient.swift
+++ b/Framework/SwiftOSC/Network/OSCClient.swift
@@ -10,39 +10,39 @@ import Foundation
import Network
public class OSCClient {
-
- var connection: NWConnection?
+
+ public var connection: NWConnection? // Access Control: changed 'var connection: NWConnection?' to public.
var queue: DispatchQueue
-
- var host: NWEndpoint.Host
- var port: NWEndpoint.Port
-
+
+ public private(set) var host: NWEndpoint.Host
+ public private(set) var port: NWEndpoint.Port
+
public init?(host: String, port: Int) {
-
+
// check if string is empty
if host == "" {
-
+
NSLog("Invalid Hostname: No empty strings allowed.")
return nil
-
+
}
- if port > 65535 && port >= 0{
+ if port > 65535 || port <= 0 {
NSLog("Invalid Port: Out of range.")
return nil
}
-
+
self.host = NWEndpoint.Host(host)
self.port = NWEndpoint.Port(integerLiteral: UInt16(port))
-
+
queue = DispatchQueue(label: "SwiftOSC Client")
setupConnection()
}
-
+
func setupConnection(){
-
+
// create the connection
connection = NWConnection(host: host, port: port, using: .udp)
-
+
// setup state update handler
connection?.stateUpdateHandler = { [weak self] (newState) in
switch newState {
@@ -53,22 +53,27 @@ public class OSCClient {
NSLog("SWiftOSC Client is restarting.")
self?.setupConnection()
case .cancelled:
+ NSLog("SWiftOSC Client cancelled.")
break
case .waiting(let error):
NSLog("SwiftOSC Client waiting with error \(error)")
case .preparing:
+ NSLog("SWiftOSC Client is preparing.")
break
case .setup:
+ NSLog("SWiftOSC Client is setting up.")
break
+ @unknown default:
+ fatalError()
}
}
-
+
// start the connection
connection?.start(queue: queue)
}
-
+
public func send(_ element: OSCElement){
-
+
let data = element.oscData
connection?.send(content: data, completion: .contentProcessed({ (error) in
if let error = error {
@@ -80,7 +85,7 @@ public class OSCClient {
// destroy connection and listener
connection?.forceCancel()
-
+
// setup new listener
setupConnection()
}
diff --git a/Framework/SwiftOSC/Network/OSCDelegate.swift b/Framework/SwiftOSC/Network/OSCDelegate.swift
index bcb9bf2..75d7db5 100644
--- a/Framework/SwiftOSC/Network/OSCDelegate.swift
+++ b/Framework/SwiftOSC/Network/OSCDelegate.swift
@@ -8,7 +8,7 @@
import Foundation
-public protocol OSCDelegate {
+public protocol OSCDelegate: AnyObject {
func didReceive(_ data: Data)
func didReceive(_ bundle: OSCBundle)
func didReceive(_ message: OSCMessage)
diff --git a/Framework/SwiftOSC/Network/OSCServer.swift b/Framework/SwiftOSC/Network/OSCServer.swift
index 1d1de0d..9c59c9a 100644
--- a/Framework/SwiftOSC/Network/OSCServer.swift
+++ b/Framework/SwiftOSC/Network/OSCServer.swift
@@ -11,56 +11,80 @@ import Network
public class OSCServer {
- public var delegate: OSCDelegate?
+ public weak var delegate: OSCDelegate?
- var listener: NWListener?
- var port: NWEndpoint.Port
+ public var listener: NWListener?
+ public private(set) var port: NWEndpoint.Port
+ public private(set) var name: String?
+ public private(set) var domain: String?
var queue: DispatchQueue
- var connection: NWConnection?
+ public var connection: NWConnection?
- public init?(port: Int) {
+ var bonjour: Bool = false
+
+ public init?(port: Int, bonjourName: String? = nil, domain: String? = nil) {
+
+ self.domain = domain
// check port range
- if port > 65535 && port >= 0{
+ if port > 65535 || port <= 0 {
NSLog("Invalid Port: Out of range.")
return nil
}
+ if let bonjourName = bonjourName {
+ bonjour = true
+ self.name = bonjourName
+ }
self.port = NWEndpoint.Port(integerLiteral: UInt16(port))
- queue = DispatchQueue(label: "SwiftOSC Server")
+ queue = DispatchQueue(label: "SwiftOSC Server") // or .main
setupListener()
}
func setupListener() {
+
+ // advertise Bonjour
+ let udpOption = NWProtocolUDP.Options()
+ let params = NWParameters(dtls: nil, udp: udpOption)
+ //if bonjour { params.includePeerToPeer = true }
+
// create the listener
- listener = try! NWListener(using: .udp, on: port)
+ listener = try! NWListener(using: params, on: port)
+
+ // Bonjour service
+ if bonjour { listener?.service = NWListener.Service(name: name,
+ type: "_osc._udp",
+ domain: domain)
+ }
// handle incoming connections server will only respond to the latest connection
listener?.newConnectionHandler = { [weak self] (newConnection) in
+ guard let self = self else { print("SwiftOSC Server newConnectionHandler error"); return }
+ NSLog("\(self.name ?? "SwiftOSC server"): New Connection from \(String(describing: newConnection))")
- NSLog("New Connection from \(String(describing: newConnection))")
-
- // cancel previous connection
- if self?.connection != nil {
- NSLog("Cancelling connection: \(String(describing: newConnection))")
- self?.connection?.cancel()
+ // cancel previous connection // check if it's own port
+ if self.connection != nil {
+ NSLog("\(self.name ?? "SwiftOSC server"): Cancelling connection: \(String(describing: newConnection))")
+ self.connection?.cancel()
}
- self?.connection = newConnection
- self?.connection?.start(queue: (self?.queue)!)
- self?.receive()
+ self.connection = newConnection
+ self.connection?.start(queue: (self.queue))
+ self.receive()
}
-
+
// Handle listener state changes
listener?.stateUpdateHandler = { [weak self] (newState) in
+ guard let self = self else { print("SwiftOSC Server stateUpdateHandler error"); return }
switch newState {
case .ready:
- NSLog("Listening on port \(String(describing: self?.listener?.port))")
+ NSLog("\(self.name ?? "SwiftOSC server"): Listening on port \(String(describing: self.listener?.port)), delegate: \(String(describing: self.delegate))")
case .failed(let error):
- NSLog("Listener failed with error \(error)")
+ NSLog("\(self.name ?? "SwiftOSC server"): Listener failed with error \(error)")
+ self.restart()
case .cancelled:
- NSLog("Listener cancelled")
+ NSLog("\(self.name ?? "SwiftOSC server"): Listener cancelled")
default:
break
}
@@ -74,7 +98,7 @@ public class OSCServer {
func receive() {
connection?.receiveMessage { [weak self] (content, context, isCompleted, error) in
if let data = content {
- data.printHexString()
+ // data.printHexString()
self?.decodePacket(data)
}
@@ -86,13 +110,14 @@ public class OSCServer {
func decodePacket(_ data: Data){
- DispatchQueue.main.async {
- self.delegate?.didReceive(data)
+ DispatchQueue.main.async { [weak self] in
+ guard let strongSelf = self else { return }
+ strongSelf.delegate?.didReceive(data)
}
if data[0] == 0x2f { // check if first character is "/"
if let message = decodeMessage(data){
- print(message)
+ // print(message)
self.sendToDelegate(message)
}
@@ -118,23 +143,25 @@ public class OSCServer {
let length = Int(bundleData.subdata(in: Range(0...3)).toInt32())
let nextData = bundleData.subdata(in: 4.. OSCMessage {
+ let customMessage: OSCMessage = OSCMessage(OSCAddressPattern("/OSCError")!)
+ customMessage.add(String("SwiftOSCServer \(name ?? String(describing: self.listener?.port)) OSC exception_ *** dirty fix 'type end found nil' *** (TotalMix bundle data with missing type end)"))
+ return customMessage
+ }
+ let customMessage = buildCustomMessage()
+ NSLog("SwiftOSCServer exception_ *** dirty fix 'type end found nil' ***")
+ return customMessage }
let type = messageData.subdata(in: 1.. 2.0'
+````
+
+### [Swift Package Manager](https://swift.org/package-manager/)
+
+```swift
+dependencies: [
+ .package(url: "https://github.com/soundflix/SwiftOSC.git", from: "2.0")
+]
```
-OR
+Alternatively, you can add the package [directly via Xcode](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app).
+
+OR install locally:
### Step 1
@@ -22,7 +34,7 @@ Clone or download repository from Github.
### Step 2
-Open SwiftOSC.xcworkspace and build SwiftOSC frameworks.
+Open SwiftOSC.xcworkspace and build SwiftOSC frameworks.
### Step 3
@@ -47,7 +59,7 @@ var server = OSCServer(port: 8080)
Setup server delegate to handle incoming OSC Data
```swift
class OSCHandler: OSCServerDelegate {
-
+
func didReceive(_ message: OSCMessage){
if let integer = message.arguments[0] as? Int {
print("Received int \(integer)")
@@ -93,7 +105,7 @@ client.send(message)
```
## Known Issues
- OSCClient loses connection following returning from being in the background. Call client.restart() in this situation.\
-
+
## About