Difference between revisions of "Gideros LOSC"

From GiderosMobile
(Created page with "__TOC__ === LOSC === OSC 1.0 implementation for lua. Github: '''https://github.com/davidgranstrom/losc''' '''License''': * MIT License '''Features''': * implements the compl...")
 
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
__TOC__
 
__TOC__
=== LOSC ===
+
=== OSC ===
 +
OpenSoundControl: '''https://ccrma.stanford.edu/groups/osc/index.html'''
 +
 
 +
From '''''Wikipedia''''', the free encyclopedia
 +
 
 +
'''Open Sound Control (OSC) is a protocol for networking sound synthesizers, computers, and other multimedia devices for purposes such as musical performance or show control. OSC's advantages include interoperability, accuracy, flexibility and enhanced organization and documentation. Its disadvantages include inefficient coding of information, increased load on embedded processors, and lack of standardized messages/interoperability. The first specification was released in March 2002.'''
 +
 
 +
==== LOSC ====
 
OSC 1.0 implementation for lua. Github: '''https://github.com/davidgranstrom/losc'''
 
OSC 1.0 implementation for lua. Github: '''https://github.com/davidgranstrom/losc'''
  
Line 14: Line 21:
 
* scheduled bundle evaluation (plugin dependent)
 
* scheduled bundle evaluation (plugin dependent)
  
==== OSC ====
+
=== Gideros LOSC ===
OpenSoundControl: '''https://ccrma.stanford.edu/groups/osc/index.html'''
+
You can download the Gideros LOSC bundle here: '''[[Media:Losc.zip]]''' ('''tip''': right click and Save Link As).
 +
 
 +
To use LOSC in your project, copy the Gideros LOSC bundle in your project '''assets''' folder.
  
From '''''Wikipedia''''', the free encyclopedia
+
For documentation regarding LOSC you can refer to this link: '''https://davidgranstrom.github.io/losc/index.html'''
  
'''Open Sound Control (OSC) is a protocol for networking sound synthesizers, computers, and other multimedia devices for purposes such as musical performance or show control. OSC's advantages include interoperability, accuracy, flexibility and enhanced organization and documentation. Its disadvantages include inefficient coding of information, increased load on embedded processors, and lack of standardized messages/interoperability. The first specification was released in March 2002.'''
+
@'''keszegh''' initiated LOSC thread on Gideros forum here: '''https://forum.gideros.rocks/discussion/4975/how-can-i-communicate-with-other-apps-using-osc/p1'''
  
=== Gideros LOSC ===
+
There is also plenty of comments in each LOSC files, feel free to read them.
The Gideros Unite framework allows a host (server) and clients to connect over a Local Area Network. Some demo code:
 
  
'''Get all connected devices'''
+
==== Example 1 ====
 +
A simple example of a server and a client.
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
-- we can get all devices that are connected to our network
+
example="client"
local devices = {}
+
--example="server"
serverlink:addEventListener("device", function(e)
+
 
print(e.data.id, e.data.ip, e.data.host)
+
local losc = require"losc"
devices[e.data.id] = {}
+
local plugin = require"losc.plugins.udp-socket"
devices[e.data.id].ip = e.data.ip
+
local Packet = require"losc.packet"
devices[e.data.id].name = e.data.host
+
 
end)
+
if example=="client" then
 +
-----------------
 +
-- Simple client.
 +
-- Uses the udp-socket plugin.
 +
local udp = plugin.new {sendAddr = "localhost", sendPort = 9000}
 +
local osc = losc.new {plugin = udp}
 +
 
 +
local message = losc.new_message {
 +
address = "/foo/bar",
 +
types = "ifsb",
 +
123, 1.2345, "hi", "blobdata",
 +
}
 +
 
 +
osc:send(message)
  
serverlink:getDevices()
+
stage:addEventListener(Event.KEY_DOWN, function(e)
 +
if e.keyCode == KeyCode.M then
 +
osc:send(message)
 +
end
 +
end)
 +
end
  
-- add some methods, that could be called by other clients or server through network
 
-- draw something
 
serverlink:addMethod("draw", self.drawLine, self)
 
-- end drawing
 
serverlink:addMethod("end", self.stopDrawing, self)
 
-- clear drawing
 
serverlink:addMethod("clear", self.reset, self)
 
  
-- then you can call this methods when needed
+
if example=="server" then
serverlink:callMethod("clear")
+
-----------------
serverlink:callMethod("draw", someX, someY)
+
-- Simple server.
 +
-- Uses the udp-socket plugin.
 +
local udp = plugin.new {
 +
recvAddr = "localhost",
 +
recvPort = 9000,
 +
ignore_late = true, -- ignore late bundles
 +
non_blocking = true, -- do not block on :open(), :poll() handles processing
 +
}
 +
local osc = losc.new {plugin = udp}
  
-- or call method of specific device using its id
+
local function print_data(data)
serverlink:callMethodOf("clear", 112233)
+
local msg = data.message
serverlink:callMethodOf("draw", someX, someY, 112233)
+
print("address: " .. msg.address, "timestamp: " .. data.timestamp)
 +
for index, argument in ipairs(msg) do
 +
print("index: " .. index, "arg: " .. argument)
 +
end
 +
end
 +
local function print_message(msg)
 +
local text = TextField.new(nil, msg.address)
 +
stage:addChild(text)
 +
text:setPosition(math.random(400), math.random(400))
 +
print("address: " .. msg.address, "time: "..plugin:now():timestamp(plugin.precision))
 +
for index, argument in ipairs(msg) do
 +
print("index: " .. index, "arg: " .. argument)
 +
end
 +
end
  
-- and when game is finished
+
osc:add_handler("/foo/bar", function(data)
serverlink:close()
+
print_data(data)
</syntaxhighlight>
+
end)
 +
osc:add_handler("/foo/bar2", function(data)
 +
print_data(data)
 +
end)
  
'''Server example code'''
+
osc:open() -- non blocking call :)
<syntaxhighlight lang="lua">
+
isopened=true
function onAccept(e)
 
-- auto accept client with provided id
 
serverlink:accept(e.data.id)
 
end
 
  
-- create a server instance
+
function onEnterFrame()
serverlink = Server.new({username = 'myServer'})
+
local status, data = osc:poll()
-- add event to monitor when new client wants to join
+
if status and data then
serverlink:addEventListener('newClient', onAccept)
+
local message = Packet.unpack(data)
-- start broadcasting to discover devices
+
print_message(message)
serverlink:startBroadcast()
+
end
 +
end
 +
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
  
-- and then before entering game logic
+
stage:addEventListener(Event.KEY_DOWN, function(e)
-- if we are ready to play stop broadcasting
+
if e.keyCode == KeyCode.S then
serverlink:stopBroadcast()
+
if not isopened then
-- and start only listening to clients
+
print("server opened")
serverlink:startListening()
+
osc:open()
 +
isopened = true
 +
end
 +
elseif e.keyCode == KeyCode.P then
 +
if isopened then
 +
print("server closed")
 +
isopened = false
 +
osc:close()
 +
end
 +
end
 +
end)
 +
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
'''Client example code'''
+
This as a Gideros project: '''[[Media:Loscdemo.zip]]''' ('''tip''': right click and Save Link As).
<syntaxhighlight lang="lua">
+
 
function onJoin(e)
+
To test the '''LOSC''' protocol:
-- auto connect to server with provided id
+
* uncomment ''example="server"''
serverlink:connect(e.data.id)
+
* and comment ''example="client"''
end
+
* compile the server as an executable then launch it
 +
* in Gideros:
 +
* uncomment ''example="client"''
 +
* and comment ''example="server"''
 +
* run the client in Gideros Player
 +
* the communication should be established between the server and the client
  
-- create client instance
+
==== Example 2 ====
serverlink = Client.new({username = 'IAmAClient'})
+
Drag your mouse on the clients to draw Pixels on the server.
-- create event to monitor when new server starts broadcasting
 
serverlink:addEventListener('newServer', onJoin)
 
  
-- event to listen if server accepted our connection
+
[[File:Losc_demo4_ss.png]]
serverlink:addEventListener('onAccepted', function()
 
print('server accepted our connection')
 
end)
 
</syntaxhighlight>
 
  
'''Game logic example''' (the game logic is the same for server and clients)
+
'''client.lua'''
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
-- we can get all devices that are connected to our network
+
print("----")
local devices = {}
+
print("LOSC GIDEROS DEMO")
serverlink:addEventListener('device', function(e)
+
print("LOSC CLIENT")
print(e.data.id, e.data.ip, e.data.host)
+
print("")
devices[e.data.id] = {}
 
devices[e.data.id].ip = e.data.ip
 
devices[e.data.id].name = e.data.host
 
end)
 
serverlink:getDevices()
 
  
-- add some methods, that could be called by other clients or server through network
+
local losc = require "losc"
-- draw something
+
local plugin = require "losc.plugins.udp-socket"
serverlink:addMethod('draw', self.drawLine, self)
 
-- end drawing
 
serverlink:addMethod('end', self.stopDrawing, self)
 
-- clear drawing
 
serverlink:addMethod('clear', self.reset, self)
 
  
-- then you can call these methods when needed
+
-- simple client, uses the udp-socket plugin
serverlink:callMethod('clear')
+
local udp = plugin.new { sendAddr="localhost", sendPort=9000, }
serverlink:callMethod('draw', someX, someY)
+
local osc = losc.new { plugin=udp, }
  
-- or call method of specific device using its id
+
-- send message
serverlink:callMethodOf('clear', 112233)
+
local message
serverlink:callMethodOf('draw', someX, someY, 112233)
+
local mousex, mousey = 0, 0
 +
stage:addEventListener(Event.MOUSE_MOVE, function(e)
 +
mousex, mousey = e.x, e.y
 +
message = losc.new_message {
 +
address="/foo/bar2", -- "/foo/bar"
 +
types="ii", -- "ifsb"
 +
mousex, mousey, -- 123, 1.2345, "hi", "blobdata"
 +
}
 +
osc:send(message)
 +
end)
 +
</syntaxhighlight>
  
-- when game is finished
+
'''server.lua'''
serverlink:close()
+
<syntaxhighlight lang="lua">
</syntaxhighlight>
+
print("----")
 +
print("LOSC GIDEROS DEMO")
 +
print("LOSC SERVER")
 +
print("")
  
=== Using the Gideros Unite Framework ===
+
local losc = require "losc"
ar2rsawseen 2012/07/25 Gideros Mobile, '''updated 2023/12/13 (V2)'''
+
local plugin = require "losc.plugins.udp-socket"
 +
local packet = require "losc.packet"
  
<youtube>https://www.youtube.com/watch?v=WBFLSz34I4I</youtube>
+
-- simple server, uses the udp-socket plugin
 +
local udp = plugin.new {
 +
recvAddr="localhost",
 +
recvPort=9000,
 +
ignore_late=true, -- true, false, ignore late bundles
 +
non_blocking=true, -- true, false, do not block on :open(), :poll() handles processing
 +
}
 +
local osc = losc.new { plugin=udp }
  
Gideros Unite framework provides a way to implement Multiplayer games:
+
-- a pixel list
* using LuaSocket to establish socket connections and create server/client instances
+
local pixels = {}
* device discovery over Local Area Network
 
* call methods on devices through the network
 
* protocols: '''tcp''', '''udp''' or both. Binding some method to tcp if reliability is needed, and others to udp for faster data processing
 
  
You can download the Gideros Unite Framework here: '''[[Media:Unite.zip|Unite.zip]]'''
+
-- open server
 +
osc:open() -- non blocking call :)
 +
print("server opened")
 +
local isopened = true
  
And a Gideros project: '''[[Media:DrawTogetherV2.zip|DrawTogetherV2.zip]]'''
+
-- listeners
 +
local function process_message(msg)
 +
local pixel = Pixel.new(math.random(0xffff00), 1, 32, 32)
 +
pixel:setAnchorPoint(0.5, 0.5)
 +
pixel:setPosition(msg[1] or 0, msg[2] or 0)
 +
pixels[#pixels+1] = pixel
 +
stage:addChild(pixel)
 +
end
 +
stage:addEventListener(Event.ENTER_FRAME, function(e)
 +
local status, data = osc:poll()
 +
if status and data then
 +
local message = packet.unpack(data)
 +
process_message(message)
 +
end
 +
for i = #pixels, 1, -1 do
 +
local pposx, pposy = pixels[i]:getPosition()
 +
pposy += 2
 +
pixels[i]:setPosition(pposx, pposy)
 +
if pposy > 200 then
 +
stage:removeChild(pixels[i])
 +
pixels[i] = nil
 +
table.remove(pixels, i)
 +
end
 +
end
 +
end)
 +
stage:addEventListener(Event.KEY_DOWN, function(e)
 +
isopened = not isopened
 +
if isopened then
 +
osc:open() -- non blocking call :)
 +
print("server opened")
 +
else
 +
osc:close()
 +
print("server closed")
 +
end
 +
end)
 +
</syntaxhighlight>
  
=== Standard scenario ===
+
This as a Gideros project: '''[[Media:Loscdemo4.zip]]''' ('''tip''': right click and Save Link As).
This is a standard scenario that can be created using Gideros Unite framework:
 
# Server starts broadcasting or skip to step 5, if all clients know server IP address
 
# Client's start listening to servers
 
# Client receives broadcast message from server, newServer event is initiated
 
# Client autoconnects to server or user manually (by pushing button) connects to specific server
 
# Server receives newClient event
 
# Server accepts client automatically or user manually (by pushing button) accepts specific client
 
# Client receives onAccept event
 
# Implement your game logic here, where both clients and server can call methods on all devices or on one specific device in the network
 
# When one of the clients becomes unreachable, all clients and server get onClientClose event
 
# When server becomes unreachable, all clients get onServerClose event
 
# When you are finished, close client or server using close method, which stops all timers, closes all connections and destroys instance
 
  
=== Framework ===
 
*1 [[Unite Server Method list]]
 
*2 [[Unite Client Method list]]
 
*3 [[Unite Server Event list]]
 
*4 [[Unite Client Event list]]
 
  
{{Unite Framework}}
+
'''[[Multiplayer]]'''
 +
{{GIDEROS IMPORTANT LINKS}}

Latest revision as of 20:54, 8 December 2024

OSC

OpenSoundControl: https://ccrma.stanford.edu/groups/osc/index.html

From Wikipedia, the free encyclopedia
Open Sound Control (OSC) is a protocol for networking sound synthesizers, computers, and other multimedia devices for purposes such as musical performance or show control. OSC's advantages include interoperability, accuracy, flexibility and enhanced organization and documentation. Its disadvantages include inefficient coding of information, increased load on embedded processors, and lack of standardized messages/interoperability. The first specification was released in March 2002.

LOSC

OSC 1.0 implementation for lua. Github: https://github.com/davidgranstrom/losc

License:

  • MIT License

Features:

  • implements the complete OSC 1.0 specification
  • pure lua implementation, no platform dependent libraries
  • support for extended OSC types
  • plugin system for transport layers
  • address pattern matching
  • scheduled bundle evaluation (plugin dependent)

Gideros LOSC

You can download the Gideros LOSC bundle here: Media:Losc.zip (tip: right click and Save Link As).

To use LOSC in your project, copy the Gideros LOSC bundle in your project assets folder.

For documentation regarding LOSC you can refer to this link: https://davidgranstrom.github.io/losc/index.html

@keszegh initiated LOSC thread on Gideros forum here: https://forum.gideros.rocks/discussion/4975/how-can-i-communicate-with-other-apps-using-osc/p1

There is also plenty of comments in each LOSC files, feel free to read them.

Example 1

A simple example of a server and a client.

example="client"
--example="server"

local losc = require"losc"
local plugin = require"losc.plugins.udp-socket"
local Packet = require"losc.packet"

if example=="client" then
	-----------------
	-- Simple client.
	-- Uses the udp-socket plugin.
	local udp = plugin.new {sendAddr = "localhost", sendPort = 9000}
	local osc = losc.new {plugin = udp}

	local message = losc.new_message {
		address = "/foo/bar",
		types = "ifsb",
		123, 1.2345, "hi", "blobdata",
	}

	osc:send(message)

	stage:addEventListener(Event.KEY_DOWN, function(e)
		if e.keyCode == KeyCode.M then
			osc:send(message)
		end
	end)
end


if example=="server" then
	-----------------
	-- Simple server.
	-- Uses the udp-socket plugin.
	local udp = plugin.new {
		recvAddr = "localhost",
		recvPort = 9000,
		ignore_late = true, -- ignore late bundles
		non_blocking = true, -- do not block on :open(), :poll() handles processing
	}
	local osc = losc.new {plugin = udp}

	local function print_data(data)
		local msg = data.message
		print("address: " .. msg.address, "timestamp: " .. data.timestamp)
		for index, argument in ipairs(msg) do
			print("index: " .. index, "arg: " .. argument)
		end
	end
	local function print_message(msg)
		local text = TextField.new(nil, msg.address)
		stage:addChild(text)
		text:setPosition(math.random(400), math.random(400))
		print("address: " .. msg.address, "time: "..plugin:now():timestamp(plugin.precision))
		for index, argument in ipairs(msg) do
			print("index: " .. index, "arg: " .. argument)
		end
	end

	osc:add_handler("/foo/bar", function(data)
		print_data(data)
	end)
	osc:add_handler("/foo/bar2", function(data)
		print_data(data)
	end)

	osc:open() -- non blocking call :)
	isopened=true

	function onEnterFrame()
		local status, data = osc:poll()
		if status and data then
			local message = Packet.unpack(data)
			print_message(message)
		end
	end
	stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)

	stage:addEventListener(Event.KEY_DOWN, function(e)
		if e.keyCode == KeyCode.S then
			if not isopened then
				print("server opened")
				osc:open()
				isopened = true
			end
		elseif e.keyCode == KeyCode.P then
			if isopened then
				print("server closed")
				isopened = false
				osc:close()
			end
		end
	end)
end

This as a Gideros project: Media:Loscdemo.zip (tip: right click and Save Link As).

To test the LOSC protocol:

  • uncomment example="server"
  • and comment example="client"
  • compile the server as an executable then launch it
  • in Gideros:
  • uncomment example="client"
  • and comment example="server"
  • run the client in Gideros Player
  • the communication should be established between the server and the client

Example 2

Drag your mouse on the clients to draw Pixels on the server.

Losc demo4 ss.png

client.lua

print("----")
print("LOSC GIDEROS DEMO")
print("LOSC CLIENT")
print("")

local losc = require "losc"
local plugin = require "losc.plugins.udp-socket"

-- simple client, uses the udp-socket plugin
local udp = plugin.new { sendAddr="localhost", sendPort=9000, }
local osc = losc.new { plugin=udp, }

-- send message
local message
local mousex, mousey = 0, 0
stage:addEventListener(Event.MOUSE_MOVE, function(e)
	mousex, mousey = e.x, e.y
	message = losc.new_message {
		address="/foo/bar2", -- "/foo/bar"
		types="ii", -- "ifsb"
		mousex, mousey, -- 123, 1.2345, "hi", "blobdata"
	}
	osc:send(message)
end)

server.lua

print("----")
print("LOSC GIDEROS DEMO")
print("LOSC SERVER")
print("")

local losc = require "losc"
local plugin = require "losc.plugins.udp-socket"
local packet = require "losc.packet"

-- simple server, uses the udp-socket plugin
local udp = plugin.new {
	recvAddr="localhost",
	recvPort=9000,
	ignore_late=true, -- true, false, ignore late bundles
	non_blocking=true, -- true, false, do not block on :open(), :poll() handles processing
}
local osc = losc.new { plugin=udp }

-- a pixel list
local pixels = {}

-- open server
osc:open() -- non blocking call :)
print("server opened")
local isopened = true

-- listeners
local function process_message(msg)
	local pixel = Pixel.new(math.random(0xffff00), 1, 32, 32)
	pixel:setAnchorPoint(0.5, 0.5)
	pixel:setPosition(msg[1] or 0, msg[2] or 0)
	pixels[#pixels+1] = pixel
	stage:addChild(pixel)
end
stage:addEventListener(Event.ENTER_FRAME, function(e)
	local status, data = osc:poll()
	if status and data then
		local message = packet.unpack(data)
		process_message(message)
	end
	for i = #pixels, 1, -1 do
		local pposx, pposy = pixels[i]:getPosition()
		pposy += 2
		pixels[i]:setPosition(pposx, pposy)
		if pposy > 200 then
			stage:removeChild(pixels[i])
			pixels[i] = nil
			table.remove(pixels, i)
		end
	end
end)
stage:addEventListener(Event.KEY_DOWN, function(e)
	isopened = not isopened
	if isopened then
		osc:open() -- non blocking call :)
		print("server opened")
	else
		osc:close()
		print("server closed")
	end
end)

This as a Gideros project: Media:Loscdemo4.zip (tip: right click and Save Link As).


Multiplayer