Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cb12b81
whitespace
aberant Aug 4, 2025
fb35670
fixing frozen string literal warnings
aberant Aug 4, 2025
29d45f8
enable frozen string literals in spec task
aberant Aug 5, 2025
9529509
moving int/float pack code to one spot and testing
aberant Sep 6, 2025
506882a
moving string/blob pack code to one spot and overall test improvements
aberant Sep 6, 2025
1d21f36
adding BinaryString and PaddedBinaryString to make encodings and padd…
aberant Sep 7, 2025
f709a9d
cleaning up old padding
aberant Sep 7, 2025
2d824af
simplifying OSC base type and naming it better
aberant Sep 7, 2025
a9f442e
whitespace
aberant Sep 7, 2025
951765a
removing unused argument
aberant Sep 7, 2025
4409664
modernize character check
aberant Sep 7, 2025
f1504dd
adding OSCNil type
aberant Sep 7, 2025
b2b1864
OSCPacket can now decode nil type
aberant Sep 7, 2025
25c0448
removing old comment
aberant Sep 7, 2025
538c3a2
updating requires statements in tests
aberant Sep 7, 2025
c8e17b2
slimming down spec_helper
aberant Sep 7, 2025
dcec6cd
updating requires in library
aberant Sep 7, 2025
6d4628a
Rename to make a CI badge
aberant Oct 26, 2025
24bf6d1
trying out a build status link in RDoc
aberant Oct 26, 2025
e61f528
lets see if this is just an image
aberant Oct 26, 2025
1eba616
got github action badge working
aberant Oct 26, 2025
e7d6480
README.rdoc: keeping this up to date
aberant Oct 26, 2025
b9c57a7
adding integration tests with python-osc
aberant Oct 26, 2025
5328dd6
moving socket require to better place
aberant Oct 26, 2025
2aa45f4
adding more nil, true, false support
aberant Oct 26, 2025
10114a1
learning how to use python-osc
aberant Oct 26, 2025
ecc4635
update readme
aberant Oct 26, 2025
eb660c8
adding bundle to from-ruby test
aberant Nov 16, 2025
458af8d
adding bundle to to-ruby test
aberant Nov 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: Ruby
name: Ruby Tests

on:
push:
Expand Down
15 changes: 6 additions & 9 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
= An OSC client for Ruby

{<img src="https://travis-ci.com/aberant/osc-ruby.svg?branch=master" alt="Build Status" />}[https://travis-ci.com/aberant/osc-ruby]
{rdoc-image:http://github.com/aberant/osc-ruby/actions/workflows/ruby.yml/badge.svg}[http://github.com/aberant/osc-ruby/actions/workflows/ruby.yml/]

http://opensoundcontrol.org/
http://opensoundcontrol.org

== Description

This OSC gem originally created by Tadayoshi Funaba has been updated for ruby 1.9 compatibility. I've made a point to make this code as expressive as possible and provide a test suite for confident hacking. It also should be flexible enough to support most crazy ideas.
This OSC gem originally created by Tadayoshi Funaba has been updated for modern ruby compatibility. I've made a point to make this code as expressive as possible and provide a test suite for confident hacking. It also should be flexible enough to support most non-conventional ideas.

Compatible with ruby 1.9, 2.* and jruby

== Install

sudo gem install osc-ruby
gem install osc-ruby

for the EMServer, you will need EventMachine

sudo gem install eventmachine
gem install eventmachine

== Event Machine Basic example

Expand Down Expand Up @@ -46,6 +45,4 @@ Originally created by...

Tadayoshi Funaba

http://www.funaba.org/en/

thx also to Toby Tripp, Brian McClain, Andreas Haller, James Hughes, Rapofran, and Daniel Dickison
With help from: Toby Tripp, Brian McClain, Andreas Haller, James Hughes, Rapofran, Daniel Dickison, Sam Aaron, and {others}[https://github.com/aberant/osc-ruby/graphs/contributors].
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ require "rake/testtask"
Rake::TestTask.new(:spec) do |t|
t.libs << "spec"
t.pattern = "spec/**/*_spec.rb"
t.ruby_opts = ['--enable=frozen-string-literal']
end

task :default => :spec
Expand Down
20 changes: 20 additions & 0 deletions integration-test/README.rdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
= Integration Tests
It's good to know if this library will work with other libraries. This is the code we use to gain some confidence osc-ruby works well with other OSC libraries.

== Python

We use {uv}[https://docs.astral.sh/uv/] to manage dependencies and run the python scripts.


=== From Ruby

We test osc-ruby sending to python-osc.

uv run ./integration-test/python/from-ruby/server.py
ruby ./integration-test/python/from-ruby/client.rb

=== To Ruby
We test osc-ruby receiving from python-osc.

ruby ./integration-test/python/to-ruby/server.rb
uv run ./integration-test/python/to-ruby/client.py
26 changes: 26 additions & 0 deletions integration-test/python/from-ruby/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require 'bundler/setup'

$:.unshift File.join( File.dirname( __FILE__ ), '..', '..', '..', 'lib')
require 'osc-ruby/client'
require 'osc-ruby/message'
require 'osc-ruby/bundle'

immediate = nil

client = OSC::Client.new('localhost', 3333)
int_msg = OSC::Message.new("/test", 42)
float_msg = OSC::Message.new("/test", OSC::OSCFloat32.new(3.14159))
string_msg = OSC::Message.new("/test", "Hello, World!")
nil_msg = OSC::Message.new("/test", nil)
true_msg = OSC::Message.new("/test", true)
false_msg = OSC::Message.new("/test", false)

client.send(int_msg)
client.send(float_msg)
client.send(string_msg)
client.send(nil_msg)
client.send(true_msg)
client.send(false_msg)

bundle = OSC::Bundle.new(immediate, int_msg, float_msg, string_msg, nil_msg, true_msg, false_msg)
client.send(bundle)
38 changes: 38 additions & 0 deletions integration-test/python/from-ruby/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "python-osc",
# ]
# ///


"""Example OSC server
Please run me via: `uv run integration-test/python/server.py`
This program listens to several addresses, and prints some information about
received packets.
"""
import argparse
import math

from pythonosc.dispatcher import Dispatcher
from pythonosc import osc_server

def print_osc(addr, *args):
print(f"addr: {addr} -- args: {args}")

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--ip",
default="127.0.0.1", help="The ip to listen on")
parser.add_argument("--port",
type=int, default=3333, help="The port to listen on")
args = parser.parse_args()

dispatcher = Dispatcher()
dispatcher.map("/*", print_osc)

server = osc_server.ThreadingOSCUDPServer(
(args.ip, args.port), dispatcher)

print("Serving on {}".format(server.server_address))
server.serve_forever()
50 changes: 50 additions & 0 deletions integration-test/python/to-ruby/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "python-osc",
# ]
# ///

from pythonosc.udp_client import SimpleUDPClient
from pythonosc import osc_message_builder as msg_builder
from pythonosc import osc_bundle_builder as bundle_builder

ip = "127.0.0.1"
port = 3333

client = SimpleUDPClient(ip, port)

client.send_message("/test", [123])
client.send_message("/test", [3.14])
builder = msg_builder.OscMessageBuilder(address="/test")
builder.add_arg(3.14159265358979, builder.ARG_TYPE_DOUBLE)
client.send(builder.build())
client.send_message("/test", ["Hello, World!"])
client.send_message("/test", [None])
client.send_message("/test", [True])
client.send_message("/test", [False])


bundle = bundle_builder.OscBundleBuilder(bundle_builder.IMMEDIATELY)
int_builder = msg_builder.OscMessageBuilder(address="/test")
int_builder.add_arg(123)
float_builder = msg_builder.OscMessageBuilder(address="/test")
float_builder.add_arg(3.14)
string_builder = msg_builder.OscMessageBuilder(address="/test")
string_builder.add_arg("Bundle")
nil_builder = msg_builder.OscMessageBuilder(address="/test")
nil_builder.add_arg(None)
true_builder = msg_builder.OscMessageBuilder(address="/test")
true_builder.add_arg(True)
false_builder = msg_builder.OscMessageBuilder(address="/test")
false_builder.add_arg(False)

bundle.add_content(int_builder.build())
bundle.add_content(float_builder.build())
bundle.add_content(string_builder.build())
bundle.add_content(nil_builder.build())
bundle.add_content(true_builder.build())
bundle.add_content(false_builder.build())

output = bundle.build()
client.send(output)
16 changes: 16 additions & 0 deletions integration-test/python/to-ruby/server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'bundler/setup'

$:.unshift File.join( File.dirname( __FILE__ ), '..', '..', '..', 'lib')
require 'osc-ruby'

require 'osc-ruby/server'

@server = OSC::Server.new( 3333 )

@server.add_method '/test' do | message |
puts "#{message.ip_address}:#{message.ip_port} -- #{message.address} -- #{message.to_a}"
puts message.encode.inspect
end


@server.run
1 change: 0 additions & 1 deletion lib/osc-ruby.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
require 'socket'
require 'thread'

# core extensions
Expand Down
2 changes: 2 additions & 0 deletions lib/osc-ruby/bundle.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'osc-ruby/osc_types'

module OSC
class Bundle
attr_accessor :timetag
Expand Down
2 changes: 2 additions & 0 deletions lib/osc-ruby/client.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'socket'

module OSC
class Client

Expand Down
2 changes: 2 additions & 0 deletions lib/osc-ruby/em_server.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
require 'eventmachine'
require 'osc-ruby/address_pattern'
require 'osc-ruby/osc_packet'

module OSC
Channel = EM::Channel.new
Expand Down
11 changes: 8 additions & 3 deletions lib/osc-ruby/message.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
require 'osc-ruby/osc_types'

module OSC
class Message
attr_accessor :address
attr_accessor :time
attr_accessor :ip_address
attr_accessor :ip_port

def self.new_with_time(address, time, tags=nil, *args)
message = new(address, tags, *args)
def self.new_with_time(address, time, *args)
message = new(address, *args)
message.time = time
message
end
Expand All @@ -20,7 +22,10 @@ def initialize(address, *args)
when Integer; @args << OSCInt32.new(arg)
when Float; @args << OSCFloat32.new(arg)
when String; @args << OSCString.new(arg)
when OSCArgument; @args << arg
when NilClass; @args << OSCNil.new()
when TrueClass; @args << OSCTrue.new()
when FalseClass; @args << OSCFalse.new()
when OSCType; @args << arg
end
end
end
Expand Down
26 changes: 0 additions & 26 deletions lib/osc-ruby/osc_argument.rb

This file was deleted.

24 changes: 14 additions & 10 deletions lib/osc-ruby/osc_packet.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require File.join(File.dirname( __FILE__ ), 'network_packet')
require 'ostruct'
require 'osc-ruby/message'
require 'osc-ruby/network_packet'
require 'osc-ruby/osc_types'

module OSC
class UnknownType < StandardError; end
Expand Down Expand Up @@ -40,19 +41,22 @@ def self.decode_simple_message(time, osc_packet)
address = osc_packet.get_string
args = osc_packet.get_arguments

Message.new_with_time(address, time, nil, *args)
Message.new_with_time(address, time, *args)
end

def initialize(string)
@packet = NetworkPacket.new(string)

@types = {
"i" => lambda{OSCInt32.new(get_int32)},
"f" => lambda{ OSCFloat32.new(get_float32)},
"d" => lambda{ OSCDouble64.new(get_double64)},
"s" => lambda{ OSCString.new(get_string)},
"b" => lambda{ OSCBlob.new(get_blob)}
}
"f" => lambda{OSCFloat32.new(get_float32)},
"d" => lambda{OSCDouble64.new(get_double64)},
"s" => lambda{OSCString.new(get_string)},
"b" => lambda{OSCBlob.new(get_blob)},
"N" => lambda{OSCNil.new()},
"T" => lambda{OSCTrue.new()},
"F" => lambda{OSCFalse.new()},
}
end

def get_bundle_messages
Expand All @@ -66,7 +70,7 @@ def get_bundle_messages
end

def get_string
result = ''
result = String.new
until ((c = @packet.getc) == string_delemeter)
result << c
end
Expand All @@ -90,7 +94,7 @@ def get_timestamp
end

def get_arguments
if (@packet.getc == ?,)
if (@packet.getc == ',')
tags = get_string
args = []

Expand Down
Loading