signage: bring in from external repo
This is b28e6f07aa48f1e2f01eb37bffa180f97a7b03bd from
https://code.hackerspace.pl/q3k/love2d-signage/. We only keep code
commited by inf and q3k, and we're both now licensing this code under
the ISC license, as per COPYING in the root of hscloud.
Change-Id: Ibeee2e6923605e4b1a17a1d295867c056863ef59
Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/1335
Reviewed-by: informatic <informatic@hackerspace.pl>
Reviewed-by: q3k <q3k@hackerspace.pl>
diff --git a/hswaw/signage/core/node-manager.lua b/hswaw/signage/core/node-manager.lua
new file mode 100644
index 0000000..69af96b
--- /dev/null
+++ b/hswaw/signage/core/node-manager.lua
@@ -0,0 +1,114 @@
+local NodeManager = class('NodeManager', {
+ state = 'running',
+ stateTime = 0,
+ currentNode = nil,
+})
+
+function NodeManager:init(config)
+ self.config = config
+ self.nodes = {}
+ self.nodeConfs = {}
+
+ self.currentNode = nil
+
+ print('Initializing NodeManager')
+end
+
+function NodeManager:load()
+ self:configChanged()
+end
+
+function NodeManager:resize(w, h)
+ self.secondaryCanvas = love.graphics.newCanvas(w, h)
+end
+
+function NodeManager:configChanged()
+ local cnt = {}
+ local newNodes = {}
+ local newNodeConfs = {}
+
+ for _, c_ in ipairs(self.config.nodes) do
+ local nodeConfig = lume.clone(c_)
+ local hash = inspect(nodeConfig)
+ if cnt[hash] == nil then cnt[hash] = 0 end
+ cnt[hash] = cnt[hash] + 1
+ hash = hash .. '-' .. tostring(cnt[hash])
+
+ local nodeName = nodeConfig[1]
+ table.remove(nodeConfig, 1)
+
+ if self.nodeConfs[hash] then
+ print('Using existing node:', self.nodeConfs[hash], hash)
+ newNodes[#newNodes + 1] = self.nodeConfs[hash]
+ else
+ print('Creating new node.', nodeName, inspect(nodeConfig))
+ local status, err = pcall(function()
+ newNodes[#newNodes + 1] = require(nodeName)(nodeConfig)
+ end)
+ if err then
+ print("Error occured while loading", nodeName, err)
+ return
+ end
+ end
+
+ newNodeConfs[hash] = newNodes[#newNodes]
+ end
+
+ self.nodes = newNodes
+ self.nodeConfs = newNodeConfs
+end
+
+function NodeManager:render()
+ if not self.currentNode then self.currentNode = self.nodes[1] end
+ if not self.currentNode then return end
+
+ -- love.graphics.print('state: ' .. self.state .. '; counter: ' .. tostring(self.stateTime), 50, 50)
+
+ self.currentNode:render()
+
+ if self.state == 'transitioning' and self.currentNode ~= self.nextNode and self.nextNode then
+ self.secondaryCanvas:renderTo(function()
+ self.nextNode:render()
+ end)
+ love.graphics.setColor(1.0, 1.0, 1.0, 1.0 * (self.stateTime / self.config.transitionTime))
+ love.graphics.draw(self.secondaryCanvas, 0, 0)
+ end
+
+ love.graphics.setColor(1.0, 1.0, 1.0, 0.3)
+
+ if self.config.showProgress and self.state == 'running' then
+ local stateTime
+ stateTime = self.currentNode.displayTime or self.config.displayTime
+ local h = 5
+ love.graphics.rectangle("fill", 0, love.graphics.getHeight() - h, (self.stateTime / stateTime) * love.graphics.getWidth(), h)
+ end
+end
+
+function NodeManager:update(dt)
+ if not self.currentNode then self.currentNode = self.nodes[1] end
+ if not self.currentNode then return end
+
+ self.stateTime = self.stateTime + dt
+
+ if self.state == 'transitioning' and self.stateTime >= self.config.transitionTime then
+ self.stateTime = 0
+ self.state = 'running'
+ self.currentNode:afterExit()
+ -- self.currentNode, self.nextNode = self.nextNode, self.nodes[(lume.find(self.nodes, self.nextNode) or 1) % #self.nodes + 1]
+ self.currentNode = self.nextNode
+ self.currentNode:afterEnter()
+ elseif self.state == 'running' and self.stateTime >= (self.currentNode.displayTime or self.config.displayTime) then
+ self.stateTime = 0
+ self.state = 'transitioning'
+ self.currentNode:beforeExit()
+ self.nextNode = self.nodes[(lume.find(self.nodes, self.currentNode) or 1) % #self.nodes + 1]
+ self.nextNode:beforeEnter()
+ end
+
+ self.currentNode:update(dt)
+ if self.state == 'transitioning' and self.currentNode ~= self.nextNode and self.nextNode then
+ self.nextNode:update(dt)
+ end
+end
+
+return NodeManager
diff --git a/hswaw/signage/core/node.lua b/hswaw/signage/core/node.lua
new file mode 100644
index 0000000..42bba62
--- /dev/null
+++ b/hswaw/signage/core/node.lua
@@ -0,0 +1,16 @@
+local Node = class('Node', {})
+
+function Node:init(opts)
+ for i, n in pairs(opts) do
+ self[i] = n
+ end
+end
+
+function Node:update(dt) end
+
+function Node:beforeEnter() end
+function Node:afterEnter() end
+function Node:beforeExit() end
+function Node:afterExit() end
+
+return Node
diff --git a/hswaw/signage/core/thread-node.lua b/hswaw/signage/core/thread-node.lua
new file mode 100644
index 0000000..e8498dd
--- /dev/null
+++ b/hswaw/signage/core/thread-node.lua
@@ -0,0 +1,40 @@
+local ThreadNode = Node:extend('ThreadNode', {
+ threadFile = nil,
+ threadChannel = nil,
+ updateInterval = 5,
+ lastUpdate = 0,
+ state = nil,
+})
+
+function ThreadNode:update(dt)
+ if not self.state then self:checkUpdate() end
+end
+
+function ThreadNode:checkUpdate()
+ if self.threadFile and self.threadChannel then
+ if self.lastUpdate < love.timer.getTime() - self.updateInterval or
+ (not self.state and self.lastUpdate < love.timer.getTime() - 5) then
+ self.lastUpdate = love.timer.getTime()
+ print(self.threadChannel, "Updating...")
+
+ local updateThread = love.thread.newThread(self.threadFile)
+ updateThread:start()
+ end
+
+ local v = love.thread.getChannel(self.threadChannel):pop()
+ if v then
+ self:onUpdate(v)
+ end
+ end
+end
+
+function ThreadNode:afterExit()
+ print('exit')
+ self:checkUpdate()
+end
+
+function ThreadNode:onUpdate(v)
+ self.state = v
+end
+
+return ThreadNode