class OSC::TCP::Client

Public Class Methods

new(host, port, handler=nil) click to toggle source
# File lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb, line 9
def initialize host, port, handler=nil
  @host = host
  @port = port
  @handler = handler
  @socket = TCPSocket.new host, port
  @sending_socket = OSC::TCP::SendingSocket.new @socket
end

Public Instance Methods

close() click to toggle source
# File lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb, line 17
def close
  @socket.close unless closed?
end
closed?() click to toggle source
# File lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb, line 21
def closed?
  @socket.closed?
end
response() click to toggle source
# File lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb, line 43
def response
  if received_messages = receive_raw
    received_messages.map do |message|
      OSCPacket.messages_from_network(message)
    end.flatten
  else
    nil
  end
end
send(msg) { |message| ... } click to toggle source

Send an OSC::Message and handle the response if one is given.

# File lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb, line 26
def send msg
  @sending_socket.send(msg)

  if block_given? || @handler
    messages = response
    if !messages.nil?
      messages.each do |message|
        if block_given?
          yield message
        else
          @handler.handle message
        end
      end
    end
  end
end
to_s() click to toggle source
# File lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb, line 53
def to_s
  "#<OSC::TCP::Client:#{ object_id } @host:#{ @host.inspect }, @port:#{ @port.inspect }, @handler:#{ @handler.to_s }>"
end

Private Instance Methods

receive_raw() click to toggle source
# File lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb, line 59
def receive_raw
  received = 0
  messages = []
  buffer   = []
  failed   = false
  received_any = false

  loop do
    begin
      # get a character from the socket, fail if nothing is available
      c = @socket.recv_nonblock(1)

      received_any = true

      case c
      when CHAR_END_ENC
        if received > 0
          # add SLIP encoded message to list
          messages << buffer.join

          # reset state and keep reading from the port until there's nothing left
          buffer.clear
          received = 0
          failed = false
        end
      when CHAR_ESC_ENC
        # get next character, blocking is okay
        c = @socket.recv(1)
        case c
        when CHAR_ESC_END_ENC
          c = CHAR_END_ENC
        when CHAR_ESC_ESC_ENC
          c = CHAR_ESC_ENC
        else
          received += 1
          buffer << c
        end
      else
        received += 1
        buffer << c
      end
    rescue Errno::EAGAIN, Errno::EWOULDBLOCK
      # If any messages have been received, assume sender is done sending.
      if failed || received_any
        break
      end

      # wait one second to see if the socket might become readable (and a
      # response forthcoming). normal usage is send + receive response, but
      # if app doesn't intend to respond we should eventually ignore it.

      IO.select([@socket], [], [], 0.2)
      failed = true
      retry
    end
  end

  if messages.size > 0
    messages
  else
    nil
  end
end