summaryrefslogtreecommitdiff
path: root/indra/newview/scripts/lua/startup.lua
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/scripts/lua/startup.lua')
-rw-r--r--indra/newview/scripts/lua/startup.lua101
1 files changed, 101 insertions, 0 deletions
diff --git a/indra/newview/scripts/lua/startup.lua b/indra/newview/scripts/lua/startup.lua
new file mode 100644
index 0000000000..4311bb9a60
--- /dev/null
+++ b/indra/newview/scripts/lua/startup.lua
@@ -0,0 +1,101 @@
+-- query, wait for or mandate a particular viewer startup state
+
+-- During startup, the viewer steps through a sequence of numbered (and named)
+-- states. This can be used to detect when, for instance, the login screen is
+-- displayed, or when the viewer has finished logging in and is fully
+-- in-world.
+
+local fiber = require 'fiber'
+local leap = require 'leap'
+local inspect = require 'inspect'
+local function dbg(...) end
+-- local dbg = require 'printf'
+
+-- ---------------------------------------------------------------------------
+-- Get the list of startup states from the viewer.
+local bynum = leap.request('LLStartUp', {op='getStateTable'})['table']
+
+local byname = setmetatable(
+ {},
+ -- set metatable to throw an error if you look up invalid state name
+ {__index=function(t, k)
+ local v = t[k]
+ if v then
+ return v
+ end
+ error(string.format('startup module passed invalid state %q', k), 2)
+ end})
+
+-- derive byname as a lookup table to find the 0-based index for a given name
+for i, name in pairs(bynum) do
+ -- the viewer's states are 0-based, not 1-based like Lua indexes
+ byname[name] = i - 1
+end
+-- dbg('startup states: %s', inspect(byname))
+
+-- specialize a WaitFor to track the viewer's startup state
+local startup_pump = 'StartupState'
+local waitfor = leap.WaitFor:new(0, startup_pump)
+function waitfor:filter(pump, data)
+ if pump == self.name then
+ return data
+ end
+end
+
+function waitfor:process(data)
+ -- keep updating startup._state for interested parties
+ startup._state = data.str
+ dbg('startup updating state to %q', data.str)
+ -- now pass data along to base-class method to queue
+ leap.WaitFor.process(self, data)
+end
+
+-- listen for StartupState events
+leap.request(leap.cmdpump(),
+ {op='listen', source=startup_pump, listener='startup.lua', tweak=true})
+-- poke LLStartUp to make sure we get an event
+leap.send('LLStartUp', {op='postStartupState'})
+
+-- ---------------------------------------------------------------------------
+startup = {}
+
+-- wait for response from postStartupState
+while not startup._state do
+ dbg('startup.state() waiting for first StartupState event')
+ waitfor:wait()
+end
+
+-- return a list of all known startup states
+function startup.list()
+ return bynum
+end
+
+-- report whether state with string name 'left' is before string name 'right'
+function startup.before(left, right)
+ return byname[left] < byname[right]
+end
+
+-- report the viewer's current startup state
+function startup.state()
+ return startup._state
+end
+
+-- error if script is called before specified state string name
+function startup.ensure(state)
+ if startup.before(startup.state(), state) then
+ -- tell error() to pretend this error was thrown by our caller
+ error('must not be called before startup state ' .. state, 2)
+ end
+end
+
+-- block calling fiber until viewer has reached state with specified string name
+function startup.wait(state)
+ dbg('startup.wait(%q)', state)
+ while startup.before(startup.state(), state) do
+ local item = waitfor:wait()
+ dbg('startup.wait(%q) sees %s', state, item)
+ end
+end
+
+return startup
+