Table of Contents

Event API

The Event API provides a basic event system to allow your code to react to signals sent by the OS or other programs/libraries.

For example, this can be used to capture keys pressed, react if an external screen is attached or removed, or handle incoming network messages.

Overview

There are two main use cases for the event API:

In driver mode your program needs to register callbacks for events (using event.listen()) then it should exit to return execution to the primary program (usually the shell). In primary mode your program does not need to register events, it can handle them directly using event.pull().

Note: While it is technically possible to do both at the same time it is not recommended to do so. To make sure that events are received by all registered functions, they are consumed only after all functions have been called. So if you register your handler and pull at the same time, you would receive events twice.

Functions

snippet.lua
local allowedPlayers = {"Kubuxu", "Sangar", "Magik6k", "Vexatos"}
local function filter(name, ...)
  if name ~= "key_up" and name ~= "key_down" and name ~= "touch" then
    return false
  end
  local nick
  if name == "touch" then
    nick = select(3, ...)
  else
    nick = select(4, ...)
  end
  for _, allowed in ipairs(allowedPlayers) do
    if nick == allowed then
      return true
    end
  end
  return false
end
 
local e = {event.pullFiltered(filter)}  -- We are pulling key_up, key_down and click events for unlimited amount of time. The filter will ensure that only events caused by players in allowedPlayers are pulled.

Interrupts

Starting In OpenOS 1.6.4 and later, interrupts have been cleaned up. The following two methods are now obsolete

Interrupts are a type of messaging intended to close or stop a process. In OpenOS the computer.pullSignal(), and thus any wrapper, generates 2 types of events.

They are especially useful when event.pull*() is called without time limit and with a filter. In some cases this means that event.pull*() could be waiting indefinitely.

Basic event example

Typically user scripts care about one or two events, and don't care to handle the rest. It is good to handle “interrupted” for soft interrupts.

snippet.lua
while true do
  local id, _, x, y = event.pullMultiple("touch", "interrupted")
  if id == "interrupted" then
    print("soft interrupt, closing")
    break
  elseif id == "touch" then
    print("user clicked", x, y)
  end
end

General purpose event handler

Here is a clever solution for providing a general purpose event handler. In this example the primary functionality uses the event id returned by event.pull() as a key for a table of callbacks, using metamethods to handle undefined events. Note that event.pull puts the program on hold until there is an event available.

snippet.lua
local event = require "event" -- load event table and store the pointer to it in event
 
local char_space = string.byte(" ") -- numerical representation of the space char
local running = true -- state variable so the loop can terminate
 
function unknownEvent()
  -- do nothing if the event wasn't relevant
end
 
-- table that holds all event handlers
-- in case no match can be found returns the dummy function unknownEvent
local myEventHandlers = setmetatable({}, { __index = function() return unknownEvent end })
 
-- Example key-handler that simply sets running to false if the user hits space
function myEventHandlers.key_up(adress, char, code, playerName)
  if (char == char_space) then
    running = false
  end
end
 
-- The main event handler as function to separate eventID from the remaining arguments
function handleEvent(eventID, ...)
  if (eventID) then -- can be nil if no event was pulled for some time
    myEventHandlers[eventID](...) -- call the appropriate event handler with all remaining arguments
  end
end
 
-- main event loop which processes all events, or sleeps if there is nothing to do
while running do
  handleEvent(event.pull()) -- sleeps until an event is available, then process it
end

If you work in driver mode, you need to register the events instead, by either registering a global event handler like the one in the example above, or by registering each individual handler on its own. If you would write the example above to work in the background, the while running do loop would be replaced like this:

snippet.lua
event.listen("key_up", handleEvent) -- register handleEvent to be called on key_up then end the program

It would also be possible to register myEventHandlers.key_up directly, in which case it would receive an additional parameter (the event name) as the first parameter.

Contents