Skip to content
An Implementation of Open Sound Control in Crystal
Crystal
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
example
logo
spec
src
.editorconfig
.gitignore
.travis.yml
LICENSE
README.md
shard.yml

README.md

osc-crystal

Build Status

Open Sound Control implementation in Crystal.

This implementation is based on the The Open Sound Control 1.0 Specification and including some extensions (extra type-tag and dispatching).

Features

  • Encode/Decode OSC message
  • Support extra type-tags associated with the tyeps in Crystal
  • On receiving message, matching the address patterns and callback concurrently

Arguments and Type Tags

This supports basic type tags and some additional ones that be shown below:

OSC Type Tag Type in Crystal
i Int32
f Float32
s String
b OSC::Type::Blob(alias of Array(UIn8))
h Int64
d Float64
t Time
c Char
r OSC::Type::RGBA
m OSC::Type::Midi
T OSC::Type::True
F OSC::Type::False
N Nil
I OSC::Type::Inf

The type tags are determined by the type of each argument. See Usage.

Installation

  1. Add the dependency to your shard.yml:

    dependencies:
      osc-crystal:
        github: astellon/osc-crystal
  2. Run shards install

Usage

Getting started, let's send an OSC Message via UDP soket to localhost.

require "osc-crystal"

# make message
m1 = OSC::Message.new("/addr", 0_i32)

# set up UDP server/client
server = UDPSocket.new
server.bind "localhost", 8000

client = UDPSocket.new
client.connect "localhost", 8000

# send message
client.send m1

# receive massage
message, client_addr = server.receive

# decode from bytes
m2 = OSC::Message.new(message.bytes)

# get argumanent
m2.arg(0) # => 0

The type tags are determined by the type of each argument like:

m = OSC::Message.new(
      "/foo",
      0_i32,
      0_f32,
      "String",
      [0_u8, 0_u8, 0_u8, 0_u8],
      0_i64,
      0_f64,
      Time.utc,
      '0',
      OSC::Type::RGBA.new(0_u8, 0_u8, 0_u8, 0_u8),
      OSC::Type::Midi.new(0_u8, 0_u8, 0_u8, 0_u8),
      OSC::Type::True,
      OSC::Type::False,
      Nil,
      OSC::Type::Inf
    )

m.address # => "/foo"
m.tag     # => ifsbhdtcrmTFNI
m.arg(0)  # => 0

The best way to handle the messages is to use OSC::Server and OSC::Client. You can specify the address and the process that will be involked when the given socket receives OSC messages. Example:

require "socket"
require "osc-crystal"

# set up UDP server/client and wrap sockets with OSC classes
server = UDPSocket.new
server.bind "localhost", 8000
osc_server = OSC::Server.new(server)

client = UDPSocket.new
client.connect "localhost", 8000
osc_client = OSC::Client.new(client)

# initialize `OSC::Message`s
m1 = OSC::Message.new(
  "/*/*",
  1_i32
)

m2 = OSC::Message.new(
  "/*/hoge",
  1_i32
)

# add methods for specific address
osc_server.dispatch("/foo/hoge") do |m|
  puts "dispatched: /foo/hoge for #{m.address}"
end

osc_server.dispatch("/foo/fuga") do |m|
  puts "dispatched: /foo/fuga for #{m.address}"
end

# run the server concurrently (return immediately)
osc_server.run

# send messages
osc_client.send m1
# => dispatched: /foo/hoge for /*/*
#    dispatched: /foo/fuga for /*/*

osc_client.send m2
# => dispatched: /foo/hoge for /*/hoge

# Sleep a second
sleep(1)

client.close
server.close

Contributing

  1. Fork it (https://github.com/astellon/osc-crystal/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

You can’t perform that action at this time.