diff --git a/Rakefile b/Rakefile index 0fbcdc4..402ec06 100644 --- a/Rakefile +++ b/Rakefile @@ -15,8 +15,8 @@ $hoe = Hoe.spec 'scruby' do self.summary = %q{SuperCollider client for Ruby} self.rubyforge_name = self.name self.extra_deps = [ - ['maca-arguments','>= 0.6'], - ['maca-rosc', '>= 0.0.1'] + ['maca-arguments', '>= 0.6'], + ['aberant-osc-ruby','>= 0.1.5'] ] end diff --git a/lib/scruby.rb b/lib/scruby.rb index 8339846..720f828 100644 --- a/lib/scruby.rb +++ b/lib/scruby.rb @@ -18,14 +18,14 @@ require 'date' require 'rubygems' require 'arguments' -require 'rosc' +require 'osc-ruby' require 'eventmachine' require 'yaml' $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) module Scruby - VERSION = '0.2.6.4' + VERSION = '0.2.6.5' end require "scruby/core_ext/object" diff --git a/lib/scruby/group.rb b/lib/scruby/group.rb index 4f5d5bd..99de01d 100644 --- a/lib/scruby/group.rb +++ b/lib/scruby/group.rb @@ -2,17 +2,17 @@ module Scruby class Group < Node def free_all - send '/g_freeAll', self.node_id + send '/g_freeAll', self.id self end def deep_free - send '/g_deepFree', self.node_id + send '/g_deepFree', self.id self end def dump_tree post = false - send '/g_dumpTree', self.node_id, post + send '/g_dumpTree', self.id, post self end diff --git a/lib/scruby/server.rb b/lib/scruby/server.rb index 8c450fb..af752b3 100644 --- a/lib/scruby/server.rb +++ b/lib/scruby/server.rb @@ -3,50 +3,31 @@ module Scruby include OSC - class Message < OSC::Message - def initialize command, *args + class ::OSC::Message + def initialize address, *args args.peel! - args.collect! do |arg| + @address = address + @args = args.collect do |arg| case arg - when Array - Blob.new self.class.new(*arg).encode - when true - 1 - when false - 0 - when Symbol - arg.to_s + when Integer then OSCInt32.new arg + when Float then OSCFloat32.new arg + when String, Symbol then OSCString.new arg.to_s + when true then OSCInt32.new 1 + when false then OSCInt32.new 0 + when Array then OSCBlob.new self.class.new(*arg).encode + when OSCArgument then arg else - arg + raise TypeError.new("#{ arg } is not a valid Message argument.") end end - super command, type_tags(args), *args - end - - def type_tags *args - args.peel! - args.collect{ |arg| OSC::Packet.tag arg }.join end end - class UDPSender < OSC::UDPServer #:nodoc: - include Singleton - - alias :udp_send :send - def send command, host, port, *args - args = args.collect{ |arg| arg.kind_of?( Symbol ) ? arg.to_s : arg } - udp_send Message.new( command, *args ), 0, host, port - end - - def send_message message, host, port - udp_send message, 0, host, port - end - end - $UDP_Sender = UDPSender.instance - class Server attr_reader :host, :port, :path, :buffers, :control_buses, :audio_buses - DEFAULTS = { :buffers => 1024, :control_buses => 4096, :audio_buses => 128, :audio_outputs => 8, :audio_inputs => 8 }.freeze + DEFAULTS = { :buffers => 1024, :control_buses => 4096, :audio_buses => 128, :audio_outputs => 8, :audio_inputs => 8, + :host => 'localhost', :port => 57111, :path => '/Applications/SuperCollider/scsynth' + } # Initializes and registers a new Server instance and sets the host and port for it. # The server is a Ruby representation of scsynth which can be a local binary or a remote @@ -68,31 +49,34 @@ class Server # +buffers+ # Number of available sample buffers defaults to 1024 def initialize opts = {} - @host = opts.delete(:host) || 'localhost' - @port = opts.delete(:port) || 57111 - @path = opts.delete(:path) || '/Applications/SuperCollider/scsynth' @opts = DEFAULTS.dup.merge opts @buffers = [] @control_buses = [] @audio_buses = [] + @client = SimpleClient.new host, port Bus.audio self, @opts[:audio_outputs] # register hardware buses Bus.audio self, @opts[:audio_inputs] self.class.all << self end + + def host; @opts[:host]; end + def port; @opts[:port]; end + def path; @opts[:path]; end # Boots the local binary of the scsynth forking a process, it will rise a SCError if the scsynth # binary is not found in /Applications/SuperCollider/scsynth (default Mac OS path) or given path. # The default path can be overriden using Server.scsynt_path=('path') def boot - raise SCError.new('Scsynth not found in the given path') unless File.exists? @path + raise SCError.new('Scsynth not found in the given path') unless File.exists? path if running? - warn "Server on port #{ @port } allready running" + warn "Server on port #{ port } allready running" return self end ready = false + timeout = Time.now + 2 @thread = Thread.new do - IO.popen "cd #{ File.dirname @path }; ./#{ File.basename @path } -u #{ @port }" do |pipe| + IO.popen "cd #{ File.dirname path }; ./#{ File.basename path } -u #{ port }" do |pipe| loop do if response = pipe.gets puts response @@ -101,9 +85,9 @@ def boot end end end - sleep 0.01 until ready or !@thread.alive? - sleep 0.01 # just to be shure - send "/g_new", 1 + sleep 0.01 until ready or !@thread.alive? or Time.now > timeout + sleep 0.01 # just to be shure + send "/g_new", 1 # default group self end @@ -116,6 +100,7 @@ def stop send "/clearSched" send "/g_new", 1 end + alias :panic :stop # Sends the /quit OSC signal to the scsynth def quit @@ -126,13 +111,8 @@ def quit # Sends an OSC command or +Message+ to the scsyth server. # E.g. +server.send('/dumpOSC', 1)+ def send message, *args - case message - when Bundle, Message - $UDP_Sender.send_message message, @host, @port - else - $UDP_Sender.send message, @host, @port, *args - end - self + message = Message.new message, *args unless Packet === message + @client.send message end def send_bundle timestamp = nil, *messages @@ -141,7 +121,7 @@ def send_bundle timestamp = nil, *messages # Encodes and sends a SynthDef to the scsynth server def send_synth_def synth_def - send Bundle.new( nil, Message.new( '/d_recv', Blob.new(synth_def.encode), 0 ) ) + send Bundle.new( nil, Message.new( '/d_recv', OSCBlob.new(synth_def.encode), 0 ) ) end # Allocates either buffer or bus indices, should be consecutive diff --git a/scruby.gemspec b/scruby.gemspec index 1f7f485..4125920 100644 --- a/scruby.gemspec +++ b/scruby.gemspec @@ -2,11 +2,11 @@ Gem::Specification.new do |s| s.name = %q{scruby} - s.version = "0.2.6.4" + s.version = "0.2.6.5" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Macario Ortega"] - s.date = %q{2009-08-22} + s.date = %q{2009-08-24} s.default_executable = %q{livecode.rb} s.description = %q{} s.email = ["macarui@gmail.com"] @@ -27,16 +27,16 @@ Gem::Specification.new do |s| if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, [">= 0.6"]) - s.add_runtime_dependency(%q, [">= 0.0.1"]) + s.add_runtime_dependency(%q, [">= 0.1.5"]) s.add_development_dependency(%q, [">= 2.3.2"]) else s.add_dependency(%q, [">= 0.6"]) - s.add_dependency(%q, [">= 0.0.1"]) + s.add_dependency(%q, [">= 0.1.5"]) s.add_dependency(%q, [">= 2.3.2"]) end else s.add_dependency(%q, [">= 0.6"]) - s.add_dependency(%q, [">= 0.0.1"]) + s.add_dependency(%q, [">= 0.1.5"]) s.add_dependency(%q, [">= 2.3.2"]) end end diff --git a/spec/buffer_spec.rb b/spec/buffer_spec.rb index 66057ef..f493cfb 100644 --- a/spec/buffer_spec.rb +++ b/spec/buffer_spec.rb @@ -3,7 +3,7 @@ require 'date' require 'arguments' require 'tempfile' -require 'osc' +require 'osc-ruby' require "scruby/buffer" require "scruby/bus" require "scruby/server" diff --git a/spec/bus_spec.rb b/spec/bus_spec.rb index 13192df..859cb9b 100644 --- a/spec/bus_spec.rb +++ b/spec/bus_spec.rb @@ -1,7 +1,7 @@ require File.expand_path(File.dirname(__FILE__)) + "/helper" require 'tempfile' -require 'osc' +require 'osc-ruby' require "scruby/core_ext/numeric" require "scruby/bus" require "scruby/server" diff --git a/spec/group_spec.rb b/spec/group_spec.rb index 7401aef..2ae5272 100644 --- a/spec/group_spec.rb +++ b/spec/group_spec.rb @@ -5,7 +5,7 @@ require "scruby/node" require "scruby/group" require 'scruby/bus' -require 'osc' +require 'osc-ruby' require 'scruby/server' require File.join( File.expand_path(File.dirname(__FILE__)), "server") diff --git a/spec/node_spec.rb b/spec/node_spec.rb index a034835..6b77d82 100644 --- a/spec/node_spec.rb +++ b/spec/node_spec.rb @@ -3,7 +3,7 @@ require "scruby/core_ext/typed_array" require "scruby/node" require "scruby/bus" -require 'osc' +require 'osc-ruby' require 'scruby/server' require File.join( File.expand_path(File.dirname(__FILE__)), "server") diff --git a/spec/server_spec.rb b/spec/server_spec.rb index bb8f275..13f6e43 100644 --- a/spec/server_spec.rb +++ b/spec/server_spec.rb @@ -2,7 +2,7 @@ require 'arguments' require 'tempfile' -require 'osc' +require 'osc-ruby' require 'scruby/node' require 'scruby/core_ext/array' require 'scruby/core_ext/typed_array' @@ -38,7 +38,7 @@ def == other describe Message do it "should encode array as Message Blob" do m = Message.new "/b_allocRead", 1, "path", 1, -1, ["/b_query", 1] - p m.encode + m.encode.should == "/b_allocRead\000\000\000\000,isiib\000\000\000\000\000\001path\000\000\000\000\000\000\000\001\377\377\377\377\000\000\000\024/b_query\000\000\000\000,i\000\000\000\000\000\001" end end diff --git a/spec/synth_spec.rb b/spec/synth_spec.rb index 3c72abe..7216e56 100644 --- a/spec/synth_spec.rb +++ b/spec/synth_spec.rb @@ -1,6 +1,6 @@ require File.expand_path(File.dirname(__FILE__)) + "/helper" -require 'osc' +require 'osc-ruby' require "scruby/core_ext/typed_array" require "scruby/node" require "scruby/bus" @@ -13,6 +13,23 @@ describe Synth do + before :all do + Server.clear + @server = Server.new + @server.boot + @server.send "/dumpOSC", 3 + sleep 0.05 + end + + after :all do + @server.quit + sleep 1 + end + + before do + @server.flush + end + describe 'instantiation with node target' do before do Node.reset! @@ -31,71 +48,55 @@ end end - describe 'Server interaction' do - before :all do - Server.clear - @server = Server.new - @server.boot - @server.send "/dumpOSC", 3 + describe 'instantiaton messaging' do + it "should send /s_new message" do + synth = Synth.new :synth, :attack => 10 + sleep 0.05 + @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 0, 1, "attack", 10 \]} + end + + it "should send set message and return self" do + synth = Synth.new :synth, :attack => 10 + synth.set( :attack => 20 ).should be_a(Synth) sleep 0.05 + @server.output.should =~ %r{\[ "/n_set", #{ synth.id }, "attack", 20 \]} end + end - after :all do - @server.quit + describe 'Default Group' do + it "should send after message" do + synth = Synth.after nil, :synth, :attack => 10 + synth.should be_a(Synth) + sleep 0.05 + @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 3, 1, "attack", 10 \]} end - before do - @server.flush + it "should send before message" do + synth = Synth.before nil, :synth, :attack => 10 + synth.should be_a(Synth) + sleep 0.05 + @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 2, 1, "attack", 10 \]} end - it "should send /s_new message" do - synth = Synth.new :synth, :attack => 10 + it "should send head message" do + synth = Synth.head nil, :synth, :attack => 10 + synth.should be_a(Synth) sleep 0.05 @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 0, 1, "attack", 10 \]} end - it "should send set message and return self" do - synth = Synth.new :synth, :attack => 10 - synth.set( :attack => 20 ).should be_a(Synth) + it "should send tail message" do + synth = Synth.tail nil, :synth, :attack => 10 + synth.should be_a(Synth) sleep 0.05 - @server.output.should =~ %r{\[ "/n_set", #{ synth.id }, "attack", 20 \]} + @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 1, 1, "attack", 10 \]} end - describe 'Default Group' do - it "should send after message" do - synth = Synth.after nil, :synth, :attack => 10 - synth.should be_a(Synth) - sleep 0.05 - @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 3, 1, "attack", 10 \]} - end - - it "should send before message" do - synth = Synth.before nil, :synth, :attack => 10 - synth.should be_a(Synth) - sleep 0.05 - @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 2, 1, "attack", 10 \]} - end - - it "should send head message" do - synth = Synth.head nil, :synth, :attack => 10 - synth.should be_a(Synth) - sleep 0.05 - @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 0, 1, "attack", 10 \]} - end - - it "should send tail message" do - synth = Synth.tail nil, :synth, :attack => 10 - synth.should be_a(Synth) - sleep 0.05 - @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 1, 1, "attack", 10 \]} - end - - it "should send replace message" do - synth = Synth.replace nil, :synth, :attack => 10 - synth.should be_a(Synth) - sleep 0.05 - @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 4, 1, "attack", 10 \]} - end + it "should send replace message" do + synth = Synth.replace nil, :synth, :attack => 10 + synth.should be_a(Synth) + sleep 0.05 + @server.output.should =~ %r{\[ "/s_new", "#{ synth.name }", #{ synth.id }, 4, 1, "attack", 10 \]} end end