Contents

============================================================================

Renoise Socket API Reference

This reference describes the built-in socket support for Lua scripts in Renoise. Sockets can be used to send/receive data over process boundaries, or exchange data across computers in a network (Internet). The socket API in Renoise has server support (which can respond to multiple connected clients) and client support (send/receive data to/from a server).

Right now UDP and TCP protocols are supported. The class interfaces for UDP and TCP sockets behave exactly the same. That is, they don't depend on the protocol, so both are easily interchangeable when needed.

Please read the INTRODUCTION first to get an overview about the complete API, and scripting for Renoise in general...

Overview

The socket server interface in Renoise is asynchronous (callback based), which means server calls never block or wait, but are served in the background. As soon a connection is established or messages arrive, a set of specified callbacks are invoked to respond to messages.

Socket clients in Renoise do block with timeouts to receive messages, and assume that you only expect a response from a server after having sent something to it (i.e.: GET HTTP). To constantly poll a connection to a server, for example in idle timers, specify a timeout of 0 in "receive(message, 0)". This will only check if there are any pending messages from the server and read them. If there are no pending messages it will not block or timeout.

Error Handling

All socket functions which can fail, will return an error string as an optional second return value. They do not call Lua's error() handler, so you can decide yourself how to deal with expected errors like connection timeouts, connection failures, and so on. This also means you don't have to "pcall" socket functions to handle such "expected" errors.

Logic errors (setting invalid addresses, using disconnected sockets, passing invalid timeouts, and so on) will fire Lua's runtime error (abort your scripts and spit out an error). If you get such an error, then this usually means you did something wrong: fed or used the sockets in a way that does not make sense. Never "pcall" such errors, fix the problem instead.

Examples

For examples on how to use sockets, have a look at the corresponding "CodeSnippets" file.

==============================================================================

Socket

renoise.Socket

Constants

renoise.Socket.PROTOCOL_TCP
renoise.Socket.PROTOCOL_UDP

Creating Socket Servers

Creates a connected UPD or TCP server object. Use "localhost" to use your system's default network address. Protocol can be renoise.Socket.PROTOCOL_TCP or renoise.Socket.PROTOCOL_UDP (by default TCP). When instantiation and connection succeed, a valid server object is returned, otherwise "socket_error" is set and the server object is nil. Using the create function with no server_address allows you to create a server which allows connections to any address (for example localhost and some IP)

renoise.Socket.create_server( [server_address, ] server_port [, protocol]) ->
  [server (SocketServer or nil), socket_error (string or nil)]

Creating Socket Clients

Create a connected UPD or TCP client. Protocol can be renoise.Socket.PROTOCOL_TCP or renoise.Socket.PROTOCOL_UDP (by default TCP) Timeout is the time to wait until the connection is established (1000 ms by default). When instantiation and connection succeed, a valid client object is returned, otherwise "socket_error" is set and the client object is nil

renoise.Socket.create_client(server_address, server_port [, protocol] [, timeout]) ->
  [client (SocketClient or nil), socket_error (string or nil)]

renoise.Socket.SocketBase

SocketBase is the base class for socket clients and servers. All SocketBase properties and functions are available for servers and clients.

Properties

Returns true when the socket object is valid and connected. Sockets can manually be closed (see socket:close()). Client sockets can also actively be closed/refused by the server. In this case the client:receive() calls will fail and return an error.

socket.is_open -> [boolean]

The socket's resolved local address (for example "127.0.0.1" when a socket is bound to "localhost")

socket.local_address -> [string]

The socket's local port number, as specified when instantiated.

socket.local_port -> [number]

Functions

Closes the socket connection and releases all resources. This will make the socket useless, so any properties, calls to the socket will result in errors. Can be useful to explicitly release a connection without waiting for the dead object to be garbage collected, or if you want to actively refuse a connection.

socket:close()

renoise.Socket.SocketClient (inherits from SocketBase)

A SocketClient can connect to other socket servers and send and receive data from them on request. Connections to a server can not change, they are specified when constructing a client. You can not reconnect a client; create a new client instance instead.

Properties

Address of the socket's peer, the socket address this client is connected to.

socket_client.peer_address -> [string]

Port of the socket's peer, the socket this client is connected to.

socket_client.peer_port -> [number]

Functions

Send a message string (or OSC messages or bundles) to the connected server. When sending fails, "success" return value will be false and "error_message" is set, describing the error in a human readable format. NB: when using TCP instead of UDP as protocol for OSC messages, !no! SLIP encoding and no size prefixing of the passed OSC data will be done here. So, when necessary, do this manually by your own please.

socket_client:send(message) ->
  [success (boolean), error_message (string or nil)]

Receive a message string from the the connected server with the given timeout in milliseconds. Mode can be one of "line", "all" or a number > 0, like Lua's io.read. \param timeout can be 0, which is useful for receive("*all"). This will only check and read pending data from the sockets queue.

When receiving fails or times-out, the returned message will be nil and error_message is set. The error message is "timeout" on timeouts, "disconnected" when the server actively refused/disconnected your client. Any other errors are system dependent, and should only be used for display purposes.

Once you get an error from receive, and this error is not a "timeout", the socket will already be closed and thus must be recreated in order to retry communication with the server. Any attempt to use a closed socket will fire a runtime error.

socket_client:receive(mode, timeout_ms) ->
  [message (string or nil), error_message (string or nil)]

renoise.Socket.SocketServer (inherits from SocketBase)

A SocketServer handles one or more clients in the background, interacts only with callbacks from connected clients. This background polling can be start and stop on request.

Properties

Returns true while the server is running (the server is up and running)

server_socket.is_running -> [boolean]

Functions

Start running the server by specifying a class or table which defines the callback functions for the server (see "callbacks" below for more info).

server_socket:run(notifier_table_or_call)

Stop a running server.

server_socket:stop()

Suspends the calling thread by the given timeout, and calls the server's callback methods as soon as something has happened in the server while waiting. Should be avoided whenever possible.

server_socket:wait(timeout_ms)

Callbacks

All callback properties are optional. So you can, for example, skip specifying "socket_accepted" if you have no use for this.

Notifier table example:

notifier_table = {
  socket_error = function(error_message)
    -- An error happened in the servers background thread.
  end,
 
  socket_accepted = function(socket)
     -- FOR TCP CONNECTIONS ONLY: called as soon as a new client
     -- connected to your server. The passed socket is a ready to use socket
     -- object, representing a connection to the new socket.
  end,
 
  socket_message = function(socket, message)
    -- A message was received from a client: The passed socket is a ready
    -- to use connection for TCP connections. For UDP, a "dummy" socket is
    -- passed, which can only be used to query the peer address and port
    -- -> socket.port and socket.address
  end
}

Notifier class example:
Note: You must pass an instance of a class, like server_socket:run(MyNotifier())

class "MyNotifier"
 
  MyNotifier::__init()
    -- could pass a server ref or something else here, or simply do nothing
  end
 
  function MyNotifier:socket_error(error_message)
    -- An error happened in the servers background thread.
  end
 
  function MyNotifier:socket_accepted(socket)
    -- FOR TCP CONNECTIONS ONLY: called as soon as a new client
    -- connected to your server. The passed socket is a ready to use socket
    -- object, representing a connection to the new socket.
  end
 
  function MyNotifier:socket_message(socket, message)
    -- A message was received from a client: The passed socket is a ready
    -- to use connection for TCP connections. For UDP, a "dummy" socket is
    -- passed, which can only be used to query the peer address and port
    -- -> socket.port and socket.address
  end