Logo + Raum-Schedule angefangen

This commit is contained in:
baldo 2015-09-08 23:41:50 +02:00
parent de72f31357
commit 9e8c31dbd1
26 changed files with 1202 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View file

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1280"
height="720"
viewBox="0 0 1280 720"
id="svg3363"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="logo.svg"
inkscape:export-filename="/home/baldo/projects/ffhh/ffnord-info-beamer/ffnord-con-2015-2/logo/logo.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs3365" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="606.70395"
inkscape:cy="189.53381"
inkscape:document-units="px"
inkscape:current-layer="g3425"
showgrid="false"
units="px"
inkscape:window-width="1278"
inkscape:window-height="1415"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="0" />
<metadata
id="metadata3368">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-332.36224)">
<g
id="g3413"
transform="matrix(0.95474973,0,0,0.95474973,31.067475,31.857036)">
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e44081;fill-opacity:1;fill-rule:nonzero;stroke:#dc0067;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 728.68638,350.92954 A 220.49287,220.49287 0 0 0 520.99106,498.10728 150.31792,150.31792 0 0 0 476.72349,491.27916 150.31792,150.31792 0 0 0 326.40513,641.59752 150.31792,150.31792 0 0 0 476.72349,791.91587 150.31792,150.31792 0 0 0 588.71763,741.58384 220.49287,220.49287 0 0 0 728.68638,791.91587 220.49287,220.49287 0 0 0 949.18052,571.42369 220.49287,220.49287 0 0 0 728.68638,350.92954 Z m 0,30.35352 A 190.13927,190.13927 0 0 1 918.827,571.42369 190.13927,190.13927 0 0 1 728.68638,761.56236 190.13927,190.13927 0 0 1 606.50083,717.07994 150.31792,150.31792 0 0 0 616.68442,695.5565 167.38731,167.38731 0 0 0 728.68638,738.81041 167.38731,167.38731 0 0 0 896.07505,571.42369 167.38731,167.38731 0 0 0 728.68638,404.03502 167.38731,167.38731 0 0 0 568.63364,522.92955 150.31792,150.31792 0 0 0 548.96567,509.9608 190.13927,190.13927 0 0 1 728.68638,381.28306 Z m 0,28.45703 a 161.68246,161.68246 0 0 1 161.68359,161.6836 161.68246,161.68246 0 0 1 -161.68359,161.68164 161.68246,161.68246 0 0 1 -109.74219,-43.22266 150.31792,150.31792 0 0 0 8.0957,-48.28515 150.31792,150.31792 0 0 0 -53.64062,-114.7168 161.68246,161.68246 0 0 1 155.28711,-117.14063 z m -251.96289,86.27735 a 145.57964,145.57964 0 0 1 42.82031,6.45117 220.49287,220.49287 0 0 0 -11.34961,68.95508 220.49287,220.49287 0 0 0 76.98828,167.05468 A 145.57964,145.57964 0 0 1 476.72349,787.17759 145.57964,145.57964 0 0 1 331.14341,641.59752 145.57964,145.57964 0 0 1 476.72349,496.01744 Z m 70.63671,18.33789 a 145.57964,145.57964 0 0 1 19.78711,13.41406 167.38731,167.38731 0 0 0 -5.84765,43.6543 167.38731,167.38731 0 0 0 51.62695,120.83203 145.57964,145.57964 0 0 1 -9.95117,21.59375 190.13927,190.13927 0 0 1 -64.42774,-142.42578 190.13927,190.13927 0 0 1 8.8125,-57.06836 z m 24.78711,17.42578 a 145.57964,145.57964 0 0 1 50.1543,109.81641 145.57964,145.57964 0 0 1 -7.19336,44.71093 161.68246,161.68246 0 0 1 -48.10351,-114.88476 161.68246,161.68246 0 0 1 5.14257,-39.64258 z"
id="circle5678" />
<polygon
style="fill:#ffc640;fill-opacity:1;stroke:#ffb400;stroke-width:0.1418799;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
points="31,56 37,50 31,44 26,44 30,48 22,48 22,52 30,52 26,56 "
transform="matrix(7.3084349,-6.920364e-8,-2.0120062e-8,6.9273802,224.1884,303.86994)"
id="polygon5543-0" />
<polygon
id="polygon5747"
transform="matrix(-13.127626,-1.2430561e-7,3.6140246e-8,12.443163,1116.7329,-46.888118)"
points="31,56 37,50 31,44 26,44 30,48 22,48 22,52 30,52 26,56 "
style="fill:#ffc640;fill-opacity:1;stroke:#ffb400;stroke-width:0.07898763;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<g
id="g3425"
transform="matrix(0.93158948,0,0,0.93158948,45.877567,41.852256)">
<text
sodipodi:linespacing="125%"
id="text4174"
y="954.60046"
x="394.6301"
style="font-style:normal;font-weight:normal;font-size:147.46354675px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#40b6e7;fill-opacity:1;stroke:#009ee0;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-family:Oswald;-inkscape-font-specification:'Oswald Ultra-Bold';fill:#40b6e7;fill-opacity:1;stroke:#009ee0;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;"
y="954.60046"
x="394.6301"
id="tspan4176"
sodipodi:role="line">FFNORD</tspan></text>
<g
id="g3418">
<text
sodipodi:linespacing="125%"
id="text4212"
y="1032.0195"
x="478.35355"
style="font-style:normal;font-weight:normal;font-size:82.68903351px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffc640;fill-opacity:1;stroke:#ffb400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;"
xml:space="preserve"><tspan
dx="0 0 0"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-family:Oswald;-inkscape-font-specification:'Oswald Ultra-Bold';fill:#ffc640;fill-opacity:1;stroke:#ffb400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;"
y="1032.0195"
x="478.35355"
id="tspan4214"
sodipodi:role="line">CON</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:82.68903351px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#e44081;fill-opacity:1;stroke:#dc0067;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;"
x="620.80359"
y="1032.0195"
id="text4274"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4276"
x="620.80359"
y="1032.0195"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-family:Oswald;-inkscape-font-specification:'Oswald Ultra-Bold';fill:#e44081;fill-opacity:1;stroke:#dc0067;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;"
dx="5.5911546">2015.2</tspan></text>
<polygon
style="fill:#ffc640;fill-opacity:1;stroke:#ffb400;stroke-width:0.18134066;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
points="30,48 22,48 22,52 30,52 26,56 31,56 37,50 31,44 26,44 "
transform="matrix(4.0051378,-4.0051379,3.796314,3.7963139,132.57633,923.99276)"
id="polygon5543" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

View file

@ -0,0 +1,8 @@
gl.setup(1280, 720)
background = resource.load_image("logo.png")
function node.render()
gl.clear(0.1, 0.1, 0.1, 1)
background:draw(0, 0, WIDTH, HEIGHT)
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View file

@ -1,6 +1,6 @@
gl.setup(1280, 720) gl.setup(1280, 720)
function node.render() function node.render()
resource.render_child("31c3"):draw(0, 0, 1280, 720) resource.render_child("room"):draw(0, 0, 1280, 720)
resource.render_child("29c3"):draw(0, 0, 1280, 720) -- resource.render_child("logo"):draw(0, 0, 1280, 720)
end end

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,14 @@
Room visualization used at 30c3.
This is almost the code that ran at 30c3. I had to remove the font used
as the font used at 30c3 cannot be redistributed. The replacement font
is "Roboto light". See http://www.fontsquirrel.com/license/roboto
Installation:
Nothing to do
Usage:
start info-beamer for this directory.
Then run ./service

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

View file

@ -0,0 +1,15 @@
{
"devices": {
"2429607372": "attraktor"
},
"rooms": {
"attraktor": {
"dect": "",
"translation": "",
"twitter": "#ffnord",
"irc": "#ffnord",
"texture": "marble",
"speed": 70
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,377 @@
-----------------------------------------------------------------------------
-- JSON4Lua: JSON encoding / decoding support for the Lua language.
-- json Module.
-- Author: Craig Mason-Jones
-- Homepage: http://json.luaforge.net/
-- Version: 0.9.40
-- This module is released under the MIT License (MIT).
-- Please see LICENCE.txt for details.
--
-- USAGE:
-- This module exposes two functions:
-- encode(o)
-- Returns the table / string / boolean / number / nil / json.null value as a JSON-encoded string.
-- decode(json_string)
-- Returns a Lua object populated with the data encoded in the JSON string json_string.
--
-- REQUIREMENTS:
-- compat-5.1 if using Lua 5.0
--
-- CHANGELOG
-- 0.9.20 Introduction of local Lua functions for private functions (removed _ function prefix).
-- Fixed Lua 5.1 compatibility issues.
-- Introduced json.null to have null values in associative arrays.
-- encode() performance improvement (more than 50%) through table.concat rather than ..
-- Introduced decode ability to ignore /**/ comments in the JSON string.
-- 0.9.10 Fix to array encoding / decoding to correctly manage nil/null values in arrays.
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Imports and dependencies
-----------------------------------------------------------------------------
local math = require('math')
local string = require("string")
local table = require("table")
local base = _G
-----------------------------------------------------------------------------
-- Module declaration
-----------------------------------------------------------------------------
module("json")
-- Public functions
-- Private functions
local decode_scanArray
local decode_scanComment
local decode_scanConstant
local decode_scanNumber
local decode_scanObject
local decode_scanString
local decode_scanWhitespace
local encodeString
local isArray
local isEncodable
-----------------------------------------------------------------------------
-- PUBLIC FUNCTIONS
-----------------------------------------------------------------------------
--- Encodes an arbitrary Lua object / variable.
-- @param v The Lua object / variable to be JSON encoded.
-- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode)
function encode (v)
-- Handle nil values
if v==nil then
return "null"
end
local vtype = base.type(v)
-- Handle strings
if vtype=='string' then
return '"' .. encodeString(v) .. '"' -- Need to handle encoding in string
end
-- Handle booleans
if vtype=='number' or vtype=='boolean' then
return base.tostring(v)
end
-- Handle tables
if vtype=='table' then
local rval = {}
-- Consider arrays separately
local bArray, maxCount = isArray(v)
if bArray then
for i = 1,maxCount do
table.insert(rval, encode(v[i]))
end
else -- An object, not an array
for i,j in base.pairs(v) do
if isEncodable(i) and isEncodable(j) then
table.insert(rval, '"' .. encodeString(i) .. '":' .. encode(j))
end
end
end
if bArray then
return '[' .. table.concat(rval,',') ..']'
else
return '{' .. table.concat(rval,',') .. '}'
end
end
-- Handle null values
if vtype=='function' and v==null then
return 'null'
end
base.assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. base.tostring(v))
end
--- Decodes a JSON string and returns the decoded value as a Lua data structure / value.
-- @param s The string to scan.
-- @param [startPos] Optional starting position where the JSON string is located. Defaults to 1.
-- @param Lua object, number The object that was scanned, as a Lua table / string / number / boolean or nil,
-- and the position of the first character after
-- the scanned JSON object.
function decode(s, startPos)
startPos = startPos and startPos or 1
startPos = decode_scanWhitespace(s,startPos)
base.assert(startPos<=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']')
local curChar = string.sub(s,startPos,startPos)
-- Object
if curChar=='{' then
return decode_scanObject(s,startPos)
end
-- Array
if curChar=='[' then
return decode_scanArray(s,startPos)
end
-- Number
if string.find("+-0123456789.e", curChar, 1, true) then
return decode_scanNumber(s,startPos)
end
-- String
if curChar==[["]] or curChar==[[']] then
return decode_scanString(s,startPos)
end
if string.sub(s,startPos,startPos+1)=='/*' then
return decode(s, decode_scanComment(s,startPos))
end
-- Otherwise, it must be a constant
return decode_scanConstant(s,startPos)
end
--- The null function allows one to specify a null value in an associative array (which is otherwise
-- discarded if you set the value with 'nil' in Lua. Simply set t = { first=json.null }
function null()
return null -- so json.null() will also return null ;-)
end
-----------------------------------------------------------------------------
-- Internal, PRIVATE functions.
-- Following a Python-like convention, I have prefixed all these 'PRIVATE'
-- functions with an underscore.
-----------------------------------------------------------------------------
--- Scans an array from JSON into a Lua object
-- startPos begins at the start of the array.
-- Returns the array and the next starting position
-- @param s The string being scanned.
-- @param startPos The starting position for the scan.
-- @return table, int The scanned array as a table, and the position of the next character to scan.
function decode_scanArray(s,startPos)
local array = {} -- The return value
local stringLen = string.len(s)
base.assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n'..s )
startPos = startPos + 1
-- Infinite loop for array elements
repeat
startPos = decode_scanWhitespace(s,startPos)
base.assert(startPos<=stringLen,'JSON String ended unexpectedly scanning array.')
local curChar = string.sub(s,startPos,startPos)
if (curChar==']') then
return array, startPos+1
end
if (curChar==',') then
startPos = decode_scanWhitespace(s,startPos+1)
end
base.assert(startPos<=stringLen, 'JSON String ended unexpectedly scanning array.')
object, startPos = decode(s,startPos)
table.insert(array,object)
until false
end
--- Scans a comment and discards the comment.
-- Returns the position of the next character following the comment.
-- @param string s The JSON string to scan.
-- @param int startPos The starting position of the comment
function decode_scanComment(s, startPos)
base.assert( string.sub(s,startPos,startPos+1)=='/*', "decode_scanComment called but comment does not start at position " .. startPos)
local endPos = string.find(s,'*/',startPos+2)
base.assert(endPos~=nil, "Unterminated comment in string at " .. startPos)
return endPos+2
end
--- Scans for given constants: true, false or null
-- Returns the appropriate Lua type, and the position of the next character to read.
-- @param s The string being scanned.
-- @param startPos The position in the string at which to start scanning.
-- @return object, int The object (true, false or nil) and the position at which the next character should be
-- scanned.
function decode_scanConstant(s, startPos)
local consts = { ["true"] = true, ["false"] = false, ["null"] = nil }
local constNames = {"true","false","null"}
for i,k in base.pairs(constNames) do
--print ("[" .. string.sub(s,startPos, startPos + string.len(k) -1) .."]", k)
if string.sub(s,startPos, startPos + string.len(k) -1 )==k then
return consts[k], startPos + string.len(k)
end
end
base.assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos)
end
--- Scans a number from the JSON encoded string.
-- (in fact, also is able to scan numeric +- eqns, which is not
-- in the JSON spec.)
-- Returns the number, and the position of the next character
-- after the number.
-- @param s The string being scanned.
-- @param startPos The position at which to start scanning.
-- @return number, int The extracted number and the position of the next character to scan.
function decode_scanNumber(s,startPos)
local endPos = startPos+1
local stringLen = string.len(s)
local acceptableChars = "+-0123456789.e"
while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true)
and endPos<=stringLen
) do
endPos = endPos + 1
end
local stringValue = 'return ' .. string.sub(s,startPos, endPos-1)
local stringEval = base.loadstring(stringValue)
base.assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos)
return stringEval(), endPos
end
--- Scans a JSON object into a Lua object.
-- startPos begins at the start of the object.
-- Returns the object and the next starting position.
-- @param s The string being scanned.
-- @param startPos The starting position of the scan.
-- @return table, int The scanned object as a table and the position of the next character to scan.
function decode_scanObject(s,startPos)
local object = {}
local stringLen = string.len(s)
local key, value
base.assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s)
startPos = startPos + 1
repeat
startPos = decode_scanWhitespace(s,startPos)
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly while scanning object.')
local curChar = string.sub(s,startPos,startPos)
if (curChar=='}') then
return object,startPos+1
end
if (curChar==',') then
startPos = decode_scanWhitespace(s,startPos+1)
end
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly scanning object.')
-- Scan the key
key, startPos = decode(s,startPos)
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
startPos = decode_scanWhitespace(s,startPos)
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
base.assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos)
startPos = decode_scanWhitespace(s,startPos+1)
base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
value, startPos = decode(s,startPos)
object[key]=value
until false -- infinite loop while key-value pairs are found
end
--- Scans a JSON string from the opening inverted comma or single quote to the
-- end of the string.
-- Returns the string extracted as a Lua string,
-- and the position of the next non-string character
-- (after the closing inverted comma or single quote).
-- @param s The string being scanned.
-- @param startPos The starting position of the scan.
-- @return string, int The extracted string as a Lua string, and the next character to parse.
function decode_scanString(s,startPos)
base.assert(startPos, 'decode_scanString(..) called without start position')
local startChar = string.sub(s,startPos,startPos)
base.assert(startChar==[[']] or startChar==[["]],'decode_scanString called for a non-string')
local escaped = false
local endPos = startPos + 1
local bEnded = false
local stringLen = string.len(s)
repeat
local curChar = string.sub(s,endPos,endPos)
-- Character escaping is only used to escape the string delimiters
if not escaped then
if curChar==[[\]] then
escaped = true
else
bEnded = curChar==startChar
end
else
-- If we're escaped, we accept the current character come what may
escaped = false
end
endPos = endPos + 1
base.assert(endPos <= stringLen+1, "String decoding failed: unterminated string at position " .. endPos)
until bEnded
local stringValue = 'return ' .. string.sub(s, startPos, endPos-1)
local stringEval = base.loadstring(stringValue)
base.assert(stringEval, 'Failed to load string [ ' .. stringValue .. '] in JSON4Lua.decode_scanString at position ' .. startPos .. ' : ' .. endPos)
return stringEval(), endPos
end
--- Scans a JSON string skipping all whitespace from the current start position.
-- Returns the position of the first non-whitespace character, or nil if the whole end of string is reached.
-- @param s The string being scanned
-- @param startPos The starting position where we should begin removing whitespace.
-- @return int The first position where non-whitespace was encountered, or string.len(s)+1 if the end of string
-- was reached.
function decode_scanWhitespace(s,startPos)
local whitespace=" \n\r\t"
local stringLen = string.len(s)
while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true) and startPos <= stringLen) do
startPos = startPos + 1
end
return startPos
end
--- Encodes a string to be JSON-compatible.
-- This just involves back-quoting inverted commas, back-quotes and newlines, I think ;-)
-- @param s The string to return as a JSON encoded (i.e. backquoted string)
-- @return The string appropriately escaped.
function encodeString(s)
s = string.gsub(s,'\\','\\\\')
s = string.gsub(s,'"','\\"')
s = string.gsub(s,"'","\\'")
s = string.gsub(s,'\n','\\n')
s = string.gsub(s,'\t','\\t')
return s
end
-- Determines whether the given Lua type is an array or a table / dictionary.
-- We consider any table an array if it has indexes 1..n for its n items, and no
-- other data in the table.
-- I think this method is currently a little 'flaky', but can't think of a good way around it yet...
-- @param t The table to evaluate as an array
-- @return boolean, number True if the table can be represented as an array, false otherwise. If true,
-- the second returned value is the maximum
-- number of indexed elements in the array.
function isArray(t)
-- Next we count all the elements, ensuring that any non-indexed elements are not-encodable
-- (with the possible exception of 'n')
local maxIndex = 0
for k,v in base.pairs(t) do
if (base.type(k)=='number' and math.floor(k)==k and 1<=k) then -- k,v is an indexed pair
if (not isEncodable(v)) then return false end -- All array elements must be encodable
maxIndex = math.max(maxIndex,k)
else
if (k=='n') then
if v ~= table.getn(t) then return false end -- False if n does not hold the number of elements
else -- Else of (k=='n')
if isEncodable(v) then return false end
end -- End of (k~='n')
end -- End of k,v not an indexed pair
end -- End of loop across all pairs
return true, maxIndex
end
--- Determines whether the given Lua object / table / variable can be JSON encoded. The only
-- types that are JSON encodable are: string, boolean, number, nil, table and json.null.
-- In this implementation, all other types are ignored.
-- @param o The object to examine.
-- @return boolean True if the object should be JSON encoded, false if it should be ignored.
function isEncodable(o)
local t = base.type(o)
return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null)
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="410"
height="210"
viewBox="0 0 410 210"
id="svg3363"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="logo.svg"
inkscape:export-filename="/home/baldo/projects/ffhh/ffnord-info-beamer/ffnord-con-2015-2/room/logo.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs3365" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="184.07151"
inkscape:cy="90.89919"
inkscape:document-units="px"
inkscape:current-layer="g3418"
showgrid="false"
units="px"
inkscape:window-width="2560"
inkscape:window-height="1417"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="0" />
<metadata
id="metadata3368">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-842.36224)">
<g
id="g3527"
transform="matrix(1.7382264,0,0,1.7382264,-46.776992,-857.16085)"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<text
sodipodi:linespacing="125%"
id="text4174"
y="1033.4785"
x="23.347813"
style="font-style:normal;font-weight:normal;font-size:67.51537323px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#40b6e7;fill-opacity:1;stroke:#009ee0;stroke-width:0.4578445;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-family:Oswald;-inkscape-font-specification:'Oswald Ultra-Bold';fill:#40b6e7;fill-opacity:1;stroke:#009ee0;stroke-width:0.4578445;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
y="1033.4785"
x="23.347813"
id="tspan4176"
sodipodi:role="line">FFNORD</tspan></text>
<g
transform="matrix(0.45784451,0,0,0.45784451,-157.33141,596.41996)"
id="g3418">
<text
sodipodi:linespacing="125%"
id="text4212"
y="1032.0195"
x="478.35355"
style="font-style:normal;font-weight:normal;font-size:82.68903351px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffc640;fill-opacity:1;stroke:#ffb400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;"
xml:space="preserve"><tspan
dx="0 0 0"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-family:Oswald;-inkscape-font-specification:'Oswald Ultra-Bold';fill:#ffc640;fill-opacity:1;stroke:#ffb400;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;"
y="1032.0195"
x="478.35355"
id="tspan4214"
sodipodi:role="line">CON</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:82.68903351px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#e44081;fill-opacity:1;stroke:#dc0067;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;"
x="620.80359"
y="1032.0195"
id="text4274"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4276"
x="620.80359"
y="1032.0195"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-family:Oswald;-inkscape-font-specification:'Oswald Ultra-Bold';fill:#e44081;fill-opacity:1;stroke:#dc0067;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;"
dx="5.5911546">2015.2</tspan></text>
<polygon
style="fill:#ffc640;fill-opacity:1;stroke:#ffb400;stroke-width:0.18134066;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
points="31,44 26,44 30,48 22,48 22,52 30,52 26,56 31,56 37,50 "
transform="matrix(4.0051378,-4.0051379,3.796314,3.7963139,132.57633,923.99276)"
id="polygon5543" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -0,0 +1,318 @@
gl.setup(1280, 720)
font = resource.load_font("Oswald-Medium.ttf")
node.alias("room")
local json = require "json"
-- Configure room here
local SAAL = "attraktor"
util.auto_loader(_G)
util.file_watch("schedule.json", function(content)
print("reloading schedule")
talks = json.decode(content)
end)
util.file_watch("config.json", function(content)
local config = json.decode(content)
if sys.get_env then
saal = config.devices[sys.get_env("SERIAL")]
end
if not saal then
print("using statically configured saal identifier")
saal = SAAL
end
print(saal)
rooms = config.rooms
room = config.rooms[saal]
end)
local base_time = N.base_time or 0
local current_talk
local all_talks = {}
local day = 0
function get_now()
return base_time + sys.now()
end
function check_next_talk()
local now = get_now()
local room_next = {}
for idx, talk in ipairs(talks) do
if rooms[talk.place] and not room_next[talk.place] and talk.unix + 25 * 60 > now then
room_next[talk.place] = talk
end
end
for room, talk in pairs(room_next) do
talk.lines = wrap(talk.title, 30)
end
if room_next[saal] then
current_talk = room_next[saal]
else
current_talk = nil
end
all_talks = {}
for room, talk in pairs(room_next) do
if current_talk and room ~= current_talk.place then
all_talks[#all_talks + 1] = talk
end
end
table.sort(all_talks, function(a, b)
if a.unix < b.unix then
return true
elseif a.unix > b.unix then
return false
else
return a.place < b.place
end
end)
end
function wrap(str, limit, indent, indent1)
limit = limit or 72
local here = 1
local wrapped = str:gsub("(%s+)()(%S+)()", function(sp, st, word, fi)
if fi-here > limit then
here = st
return "\n"..word
end
end)
local splitted = {}
for token in string.gmatch(wrapped, "[^\n]+") do
splitted[#splitted + 1] = token
end
return splitted
end
local clock = (function()
local base_time = N.base_time or 0
local function set(time)
base_time = tonumber(time) - sys.now()
end
util.data_mapper{
["clock/midnight"] = function(since_midnight)
set(since_midnight)
end;
}
local left = 0
local function get()
local time = (base_time + sys.now()) % 86400
return string.format("%d:%02d", math.floor(time / 3600), math.floor(time % 3600 / 60))
end
return {
get = get;
set = set;
}
end)()
check_next_talk()
util.data_mapper{
["clock/set"] = function(time)
base_time = tonumber(time) - sys.now()
N.base_time = base_time
check_next_talk()
print("UPDATED TIME", base_time)
end;
["clock/day"] = function(new_day)
print("DAY", new_day)
day = new_day
end;
}
function switcher(screens)
local current_idx = 1
local current = screens[current_idx]
local switch = sys.now() + current.time
local switched = sys.now()
local blend = 0.5
local function draw()
local now = sys.now()
local percent = ((now - switched) / (switch - switched)) * 3.14129 * 2 - 3.14129
progress:use{percent = percent}
white:draw(WIDTH-50, HEIGHT-50, WIDTH-10, HEIGHT-10)
progress:deactivate()
if now - switched < blend then
local delta = (switched - now) / blend
gl.pushMatrix()
gl.translate(WIDTH/2, 0)
gl.rotate(270-90 * delta, 0, 1, 0)
gl.translate(-WIDTH/2, 0)
current.draw()
gl.popMatrix()
elseif now < switch - blend then
current.draw(now - switched)
elseif now < switch then
local delta = 1 - (switch - now) / blend
gl.pushMatrix()
gl.translate(WIDTH/2, 0)
gl.rotate(90 * delta, 0, 1, 0)
gl.translate(-WIDTH/2, 0)
current.draw()
gl.popMatrix()
else
current_idx = current_idx + 1
if current_idx > #screens then
current_idx = 1
end
current = screens[current_idx]
switch = now + current.time
switched = now
end
end
return {
draw = draw;
}
end
content = switcher{
--[[ {
time = 10;
draw = function()
font:write(400, 200, "Other rooms", 80, 1,1,1,1)
white:draw(0, 300, WIDTH, 302, 0.6)
y = 320
local time_sep = false
if #all_talks > 0 then
for idx, talk in ipairs(all_talks) do
if not time_sep and talk.unix > get_now() then
if idx > 1 then
y = y + 5
white:draw(0, y, WIDTH, y+2, 0.6)
y = y + 20
end
time_sep = true
end
local alpha = 1
if not time_sep then
alpha = 0.3
end
font:write(30, y, talk.start, 50, 1,1,1,alpha)
font:write(190, y, talk.place, 50, 1,1,1,alpha)
font:write(400, y, talk.lines[math.floor((sys.now()/2) % #talk.lines)+1], 50, 1,1,1,alpha)
y = y + 60
end
else
font:write(400, 330, "No other talks.", 50, 1,1,1,1)
end
end
}, --]] {
time = 30;
draw = function()
if not current_talk then
redU(400, 200, "Next session...", 80, 1,1,1,1)
white:draw(0, 300, WIDTH, 302, 0.6)
redU(400, 330, "Nope. That's it.", 80)
else
local delta = current_talk.unix - get_now()
if delta > 0 then
redU(400, 200, "Next session", 80)
else
redU(400, 200, "This session", 80)
end
white:draw(0, 300, WIDTH, 302, 0.6)
blue(130, 330, current_talk.start, 50, 1,1,1,1)
if delta > 0 then
blue(130, 330 + 60, string.format("in %d min", math.floor(delta/60)+1), 50)
end
for idx, line in ipairs(current_talk.lines) do
if idx >= 5 then
break
end
yellow(400, 330 - 60 + 60 * idx, line, 50)
end
for i, speaker in ipairs(current_talk.speakers) do
blue(400, 510 + 50 * i, speaker, 50)
end
end
end
}, --[[ {
time = 10;
draw = function(t)
font:write(400, 200, "Room info", 80, 1,1,1,1)
white:draw(0, 300, WIDTH, 302, 0.6)
font:write(30, 320, "Audio", 50, 1,1,1,1)
font:write(400, 320, "Dial " .. room.dect, 50, 1,1,1,1)
font:write(30, 380, "Translation", 50, 1,1,1,1)
font:write(400, 380, "Dial " .. room.translation, 50, 1,1,1,1)
font:write(30, 480, "IRC", 50, 1,1,1,1)
font:write(400, 480, room.irc, 50, 1,1,1,1)
font:write(30, 540, "Twitter", 50, 1,1,1,1)
font:write(400, 540, room.twitter, 50, 1,1,1,1)
if t then
local banner = -4 + t
if banner > 0 and banner < 3.1412 then
local alpha = math.pow(math.sin(banner), 2)
local x = 400 - math.pow(banner / math.pi - 0.5, 5) * WIDTH * 2
font:write(x, 640, "http://info-beamer.org/", 30, 1,1,1,alpha)
end
end
end
}, --]]
}
function redU(x, y, text, size)
red(x, y, string.upper(text), size)
end
function red(x, y, text, size)
font:write(x, y, text, size, 0.894, 0.251, 0.506, 1)
end
function yellowU(x, y, text, size)
yellow(x, y, string.upper(text), size)
end
function yellow(x, y, text, size)
font:write(x, y, text, size, 1.0, 0.776, 0.251, 1)
end
function blueU(x, y, text, size)
blue(x, y, string.upper(text), size)
end
function blue(x, y, text, size)
font:write(x, y, text, size, 0.251, 0.714, 0.906, 1)
end
function node.render()
gl.clear(0.1, 0.1, 0.1, 1)
if base_time == 0 then
return
end
util.draw_correct(logo, 20, 20, 300, 120)
yellowU(310, 20, saal, 80)
blueU(730, 20, clock.get(), 80)
redU(WIDTH-300, 20, string.format("Day %d", day), 80)
local fov = math.atan2(HEIGHT, WIDTH*2) * 360 / math.pi
gl.perspective(fov, WIDTH/2, HEIGHT/2, -WIDTH,
WIDTH/2, HEIGHT/2, 0)
content.draw()
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View file

@ -0,0 +1,16 @@
uniform sampler2D Texture;
varying vec2 TexCoord;
uniform float percent;
void main() {
vec2 pos = TexCoord;
float angle = atan(pos.x - 0.5, pos.y - 0.5);
float dist = distance(pos, vec2(0.5, 0.5));
if (dist >= 0.5) {
gl_FragColor = vec4(0.0);
} else if (angle < percent) {
gl_FragColor = vec4(0.894, 0.251, 0.506, 1);
} else {
gl_FragColor = vec4(1.0, 0.776, 0.251, 1);
}
}

View file

@ -0,0 +1,121 @@
[
{
"duration": 60,
"lang": "de",
"place": "attraktor",
"speakers": [
],
"start": "9:30",
"title": "„Einlass“ und Frühstück",
"type": "talk",
"unix": 1441956600,
"unix_end": 1441960200
},
{
"duration": 30,
"lang": "de",
"place": "attraktor",
"speakers": [
],
"start": "11:00",
"title": "Eröffnungsplenum",
"type": "talk",
"unix": 1441962000,
"unix_end": 1441963800
},
{
"duration": 60,
"lang": "de",
"place": "attraktor",
"speakers": [
"t.b.a."
],
"start": "12:00",
"title": "Vortrags-Slot #1 mit folgender Diskussion und Kaffeepause",
"type": "talk",
"unix": 1441965600,
"unix_end": 1441969200
},
{
"duration": 60,
"lang": "de",
"place": "attraktor",
"speakers": [
"t.b.a."
],
"start": "14:00",
"title": "Vortrags-Slot #2 mit folgender Diskussion und Kaffeepause",
"type": "talk",
"unix": 1441972800,
"unix_end": 1441976400
},
{
"duration": 240,
"lang": "de",
"place": "attraktor",
"speakers": [
],
"start": "16:00",
"title": "Workshop und Hacking Time",
"type": "talk",
"unix": 1441980000,
"unix_end": 1441994400
},
{
"duration": 60,
"lang": "de",
"place": "attraktor",
"speakers": [
],
"start": "9:30",
"title": "„Einlass“ und Frühstück",
"type": "talk",
"unix": 1442043000,
"unix_end": 1442046600
},
{
"duration": 60,
"lang": "de",
"place": "attraktor",
"speakers": [
"t.b.a."
],
"start": "11:00",
"title": "Vortrags-Slot #3 mit folgender Diskussion und Kaffeepause",
"type": "talk",
"unix": 1442048400,
"unix_end": 1442052000
},
{
"duration": 150,
"lang": "de",
"place": "attraktor",
"speakers": [
],
"start": "13:00",
"title": "Workshop und Hacking Time",
"type": "talk",
"unix": 1442055600,
"unix_end": 1442064600
},
{
"duration": 30,
"lang": "de",
"place": "attraktor",
"speakers": [
],
"start": "16:00",
"title": "Abschlussplenum und Diskussion",
"type": "talk",
"unix": 1442066400,
"unix_end": 1442068200
}
]

55
ffnord-con-2015-2/room/service Executable file
View file

@ -0,0 +1,55 @@
#!/usr/bin/python
import sys
import time
import pytz
import socket
from calendar import timegm
from datetime import datetime, date
diff = None
# Fake time in UTC
diff = datetime(2015,9,11,8,30,00) - datetime.utcnow()
met = pytz.timezone("Europe/Berlin")
def current_time():
now = datetime.utcnow()
if diff:
now += diff
timestamp = timegm(now.timetuple()) + now.microsecond / 1000000.
now = now.replace(tzinfo=pytz.utc)
now = now.astimezone(met)
now = now.replace(tzinfo=None)
return now, timestamp
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def send(data):
sock.sendto(data, ('127.0.0.1', 4444))
print >>sys.stderr, "SENT >>> ", data
def send_clock(now, ts):
day = (now.date() - date(2015, 9, 11)).days
since_midnight = (
now -
now.replace(hour=0, minute=0, second=0, microsecond=0)
)
since_midnight = since_midnight.seconds + since_midnight.microseconds / 1000000.
send('room/clock/day:%d' % day)
send('room/clock/set:%f' % ts)
send('room/clock/midnight:%f' % since_midnight)
def main():
while 1:
now, ts = current_time()
if now.year < 2000:
print >>sys.stderr, "too soon"
time.sleep(1)
continue
send_clock(now, ts)
time.sleep(2)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,32 @@
uniform sampler2D Texture;
uniform sampler2D Grid;
uniform sampler2D Overlay;
varying vec2 TexCoord;
uniform float time;
const float segments = 9.0;
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
void main() {
vec2 pos = TexCoord;
vec2 coord = texture2D(Texture, pos).st;
coord.x = mod(coord.x + time, 1.0);
coord.y = coord.y + 0.0175;
coord += rand(pos) * 0.008;
vec3 col = texture2D(Overlay, coord).rgb;
float foo = floor(coord.y * segments);
col *= (foo / segments) * 0.6 + 0.4;
if (pos.y > 0.82) {
vec3 bar = texture2D(Overlay, pos).rgb;
col = col * 0.3 + bar * 0.4; //mix(col, bar, 0.3) * 0.8;
}
vec4 grid = texture2D(Grid, pos);
gl_FragColor = vec4(col, 1.0) + grid * 0.09;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B