Code Monkey home page Code Monkey logo

oscine's Introduction

OSCine

OSCine is an easy to use yet robust Swift client and server implementation of Open Sound Control v1.1.

The motivations and goals for this package are:

  • Ease of use
  • No third-party dependencies
  • Close adherance to OSC v1.1 specification
  • Integrated TCP, UDP, and Multicast network support*
  • Integrated Bonjour advertisement and browsing support
  • Integrated OSLog support
  • SLIP support via Apple Network Protocol Framer

Future versions will likely support Swift 5.5 async operations.

ย * While OSCine has fully integrated network support, access to packet creation and parsing is available so that alternate transport libraries could be utilized if desired.

IMPORTANT: Multicast support on iOS/iPadOS 14 and later requires entitlements available only directly from Apple.

This package was initially created for my own uses as I found other Swift OSC packages lacking, primarily in their dependence upon third-party libraries. I am making this available via the included MIT style license in hopes others may find it useful. In particular I'm hoping this may be of interest to others attempting to implement Apple Netwok Protocol Framers. I found Apple documentation on framers to be seriously lacking and could find no open source examples. The included SLIP framer should be generally useful to anyone requiring SLIP support however it is likely more useful as an example of a 'data encoding' style protocol framer.

OSC

OSCine follows the OSC v1.1 specification closely and relies upon terminology from the OSC spec heavily throughout. If you are not familar with OSC and its paradigms it is strongly suggested that you review them before proceeding:

http://cnmat.org/OpenSoundControl/OSC-spec.html
http://opensoundcontrol.org/spec-1_0.html
http://opensoundcontrol.org/files/2009-NIME-OSC-1.1.pdf

Usage

Usage is intended to be as straightforward as possible assuming familiarity with OSC and its terminology. The representative examples below, and included test suite, should hopefully get you started. Further information and details can be found as Swift Documentation Comments in the code itself.

Client

let client = OSCClientUDP()
client.delegate = self //for connection state notifications - see OSCClientDelegate
client.connect(serviceName: "MyMixer", timeout: 10.0)

//after connection state change to: .ready

let bundle = OSCBundle(timeTag: OSCTimeTag.immediate,
                       bundleElements: [
                           OSCMessage(addressPattern: "/mixer/*/mute[0-9]", arguments: [.true]), 
                           OSCMessage(addressPattern: "/mixer/*/solo[0-9]", arguments: [.false]),
                           OSCMessage(addressPattern: "/mixer/*/fader[0-9]", arguments: [.float(0.0)]), 
                           OSCMessage(addressPattern: "/mixer/*/eq", arguments: [.float(0.0), .float(0.0), .float(0.0)]), 
                           OSCMessage(addressPattern: "/mixer/*/label", arguments: [.string("")]),
                       ])
try client.send(bundle)

Server

class MyMethod: OSCMethod {
    var addressPattern: OSCAddressPattern
    var requiredArguments: OSCArgumentTypeTagArray? = nil

    init(addressPattern: OSCAddressPattern, requiredArguments: OSCArgumentTypeTagArray? = nil) {
        self.addressPattern = addressPattern
        self.requiredArguments = requiredArguments
    }
    
    func handleMessage(_ message: OSCMessage, for match: OSCPatternMatchType, at timeTag: OSCTimeTag?) {
        print("Received message: \(message.addressPattern)",
              "with match: \(match)",
              "arguments: \(String(describing: message.arguments)),
              "time tag: \(String(describing: timeTag?.date))"")
    }
}

let server = OSCServerUDP()
server.delegate = self //for listener state notifications - see OSCServerDelegate
try server.register(methods: [MyMethod(addressPattern: "/mixer/main/mute1", requiredArguments: [.anyBoolean]), 
                              MyMethod(addressPattern: "/mixer/main/solo1", requiredArguments: [.anyBoolean]), 
                              MyMethod(addressPattern: "/mixer/main/fader1", requiredArguments: [.float, .optional(.float)]), 
                              MyMethod(addressPattern: "/mixer/main/eq", requiredArguments: [.anyNumber, .anyNumber, .anyNumber]), 
                              MyMethod(addressPattern: "/mixer/main/label"])
try server.listen(serviceName: "MyMixer")

Multicast

let mcast = OSCMulticast()
mcast.delegate = self //for group state notifications - see OSCMulticastDelegate
try mcast.joinGroup(on: "224.0.0.251", port: 12345)

//Register methods if you care to process or monitor messages sent to the group
try mcast.register(methods: [MyMethod(addressPattern: "/mixer/main/mute1", requiredArguments: [.anyBoolean]), 
                             MyMethod(addressPattern: "/mixer/main/solo1", requiredArguments: [.anyBoolean]), 
                             MyMethod(addressPattern: "/mixer/main/fader1", requiredArguments: [.float, .optional(.float)]), 
                             MyMethod(addressPattern: "/mixer/main/eq", requiredArguments: [.anyNumber, .anyNumber, .anyNumber]), 
                             MyMethod(addressPattern: "/mixer/main/label")

//after connection state change to: .ready

//Note that Messages sent to the group will also be delivered to any Methods you register on the Multicast instance.
let bundle = OSCBundle(timeTag: OSCTimeTag.immediate,
                       bundleElements: [
                            OSCMessage(addressPattern: "/mixer/*/mute[0-9]", arguments: [.true]), 
                            OSCMessage(addressPattern: "/mixer/*/solo[0-9]", arguments: [.false]),
                            OSCMessage(addressPattern: "/mixer/*/fader[0-9]", arguments: [.float(0.0)]), 
                            OSCMessage(addressPattern: "/mixer/*/eq", arguments: [.float(0.0), .float(0.0), .float(0.0)]), 
                            OSCMessage(addressPattern: "/mixer/*/label", arguments: [.string("")]),
                       ])
try mcast.send(bundle)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.