osc-crystal

An Implementation of Open Sound Control in Crystal

osc-crystal

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

Repository

osc-crystal

Owner
Statistic
  • 5
  • 2
  • 2
  • 0
  • 0
  • over 2 years ago
  • March 16, 2019
License

MIT License

Links
Synced at

Fri, 22 Nov 2024 07:01:20 GMT

Languages