From fb8c10876b6cc9ebe0a49521342292371ad8ce26 Mon Sep 17 00:00:00 2001 From: jm-github Date: Thu, 30 Oct 2014 16:02:30 +0000 Subject: [PATCH 01/31] 5 more effects Former-commit-id: e6a826299ad48143cb155e7113a34bd6d3b20246 --- effects/loop.json | 7 +++++++ effects/loop.py | 34 ++++++++++++++++++++++++++++++++++ effects/loop2.json | 7 +++++++ effects/loop2.py | 33 +++++++++++++++++++++++++++++++++ effects/random.json | 7 +++++++ effects/random.py | 25 +++++++++++++++++++++++++ effects/sparks-color.json | 7 +++++++ effects/sparks-color.py | 35 +++++++++++++++++++++++++++++++++++ effects/sparks.json | 7 +++++++ effects/sparks.py | 33 +++++++++++++++++++++++++++++++++ 10 files changed, 195 insertions(+) create mode 100644 effects/loop.json create mode 100644 effects/loop.py create mode 100644 effects/loop2.json create mode 100644 effects/loop2.py create mode 100644 effects/random.json create mode 100644 effects/random.py create mode 100644 effects/sparks-color.json create mode 100644 effects/sparks-color.py create mode 100644 effects/sparks.json create mode 100644 effects/sparks.py diff --git a/effects/loop.json b/effects/loop.json new file mode 100644 index 00000000..9415f8b1 --- /dev/null +++ b/effects/loop.json @@ -0,0 +1,7 @@ +{ + "name" : "Loop", + "script" : "loop.py", + "args" : + { + } +} diff --git a/effects/loop.py b/effects/loop.py new file mode 100644 index 00000000..93011e97 --- /dev/null +++ b/effects/loop.py @@ -0,0 +1,34 @@ +import hyperion +import time +import colorsys +import random + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0,0,0)) + +sleepTime = 0.002 + +runners = [ +{ "i":0, "pos":0, "c":0, "step":9 , "lvl":255}, +{ "i":1, "pos":0, "c":0, "step":8 , "lvl":255}, +{ "i":2, "pos":0, "c":0, "step":7 , "lvl":255}, +{ "i":0, "pos":0, "c":0, "step":6 , "lvl":0}, +{ "i":1, "pos":0, "c":0, "step":5 , "lvl":0}, +{ "i":2, "pos":0, "c":0, "step":4, "lvl":0}, +] + +# Start the write data loop +while not hyperion.abort(): + for r in runners: + if r["c"] == 0: + #ledData[r["pos"]*3+r["i"]] = 0 + r["c"] = r["step"] + r["pos"] = (r["pos"]+1)%hyperion.ledCount + ledData[r["pos"]*3+r["i"]] = int(r["lvl"]*(0.2+0.8*random.random())) + else: + r["c"] -= 1 + + hyperion.setColor(ledData) + time.sleep(sleepTime) diff --git a/effects/loop2.json b/effects/loop2.json new file mode 100644 index 00000000..77f2c438 --- /dev/null +++ b/effects/loop2.json @@ -0,0 +1,7 @@ +{ + "name" : "Loop2", + "script" : "loop2.py", + "args" : + { + } +} diff --git a/effects/loop2.py b/effects/loop2.py new file mode 100644 index 00000000..3498ac4e --- /dev/null +++ b/effects/loop2.py @@ -0,0 +1,33 @@ +import hyperion +import time +import colorsys +import random + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0,0,0)) + +sleepTime = 0.005 + +runners = [ +{ "pos":0, "step":4 , "lvl":255}, +{ "pos":1, "step":5 , "lvl":255}, +{ "pos":2, "step":6 , "lvl":255}, +{ "pos":0, "step":7 , "lvl":255}, +{ "pos":1, "step":8 , "lvl":255}, +{ "pos":2, "step":9, "lvl":255}, +] + +# Start the write data loop +count = 0 +while not hyperion.abort(): + count += 1 + for r in runners: + if count%r["step"] == 0: + ledData[r["pos"]] = 0 + r["pos"] = (r["pos"]+3)%(hyperion.ledCount*3) + ledData[r["pos"]] = r["lvl"] + + hyperion.setColor(ledData) + time.sleep(sleepTime) diff --git a/effects/random.json b/effects/random.json new file mode 100644 index 00000000..dc1d79ae --- /dev/null +++ b/effects/random.json @@ -0,0 +1,7 @@ +{ + "name" : "Random", + "script" : "random.py", + "args" : + { + } +} diff --git a/effects/random.py b/effects/random.py new file mode 100644 index 00000000..0f5406b1 --- /dev/null +++ b/effects/random.py @@ -0,0 +1,25 @@ +import hyperion +import time +import colorsys +import random + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0,0,0)) + +sleepTime = 0.001 + +# Start the write data loop +while not hyperion.abort(): + hyperion.setColor(ledData) + for i in range(hyperion.ledCount): + if random.randrange(10) == 1: + hue = random.random() + sat = 1.0 + val = random.random() + rgb = colorsys.hsv_to_rgb(hue, sat, val) + ledData[i*3 ] = int(255*rgb[0]) + ledData[i*3+1] = int(255*rgb[1]) + ledData[i*3+2] = int(255*rgb[2]) + time.sleep(sleepTime) diff --git a/effects/sparks-color.json b/effects/sparks-color.json new file mode 100644 index 00000000..1c3e8146 --- /dev/null +++ b/effects/sparks-color.json @@ -0,0 +1,7 @@ +{ + "name" : "Sparks color", + "script" : "sparks-color.py", + "args" : + { + } +} diff --git a/effects/sparks-color.py b/effects/sparks-color.py new file mode 100644 index 00000000..34b5acf5 --- /dev/null +++ b/effects/sparks-color.py @@ -0,0 +1,35 @@ +import hyperion +import time +import colorsys +import random + +# Get the parameters +rotationTime = float(hyperion.args.get('rotation-time', 3.0)) +brightness = float(hyperion.args.get('brightness', 1.0)) +saturation = float(hyperion.args.get('saturation', 1.0)) +reverse = bool(hyperion.args.get('reverse', False)) + +# Check parameters +rotationTime = max(0.1, rotationTime) +brightness = max(0.0, min(brightness, 1.0)) +saturation = max(0.0, min(saturation, 1.0)) + +# Initialize the led data +ledData = bytearray() + +sleepTime = 0.05 + +# Start the write data loop +while not hyperion.abort(): + ledData[:] = bytearray(3*hyperion.ledCount) + for i in range(hyperion.ledCount): + if random.random() < 0.005: + hue = random.random() + sat = 1 + val = 1 + rgb = colorsys.hsv_to_rgb(hue, sat, val) + ledData[i*3] = int(255*rgb[0]) + ledData[i*3+1] = int(255*rgb[1]) + ledData[i*3+2] = int(255*rgb[2]) + hyperion.setColor(ledData) + time.sleep(sleepTime) diff --git a/effects/sparks.json b/effects/sparks.json new file mode 100644 index 00000000..d4040309 --- /dev/null +++ b/effects/sparks.json @@ -0,0 +1,7 @@ +{ + "name" : "Sparks", + "script" : "sparks.py", + "args" : + { + } +} diff --git a/effects/sparks.py b/effects/sparks.py new file mode 100644 index 00000000..821719e2 --- /dev/null +++ b/effects/sparks.py @@ -0,0 +1,33 @@ +import hyperion +import time +import colorsys +import random + +# Get the parameters +rotationTime = float(hyperion.args.get('rotation-time', 3.0)) +brightness = float(hyperion.args.get('brightness', 1.0)) +saturation = float(hyperion.args.get('saturation', 1.0)) +reverse = bool(hyperion.args.get('reverse', False)) + +# Check parameters +rotationTime = max(0.1, rotationTime) +brightness = max(0.0, min(brightness, 1.0)) +saturation = max(0.0, min(saturation, 1.0)) + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0, 0, 0)) + +sleepTime = 0.05 + +# Start the write data loop +while not hyperion.abort(): + ledData[:] = bytearray(3*hyperion.ledCount) + for i in range(hyperion.ledCount): + if random.random() < 0.005: + ledData[i*3] = 255 + ledData[i*3+1] = 255 + ledData[i*3+2] = 255 + hyperion.setColor(ledData) + time.sleep(sleepTime) From 7dfe8ae8cf64dc892cdc8945ebac0454aacc5118 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 20 Jan 2016 14:45:17 +0100 Subject: [PATCH 02/31] all effects has same lineendings Former-commit-id: c2586f57ce03c20a7a1083a5d62c8ddde7359b84 --- effects/knight-rider.json | 20 ++++++++++---------- effects/loop.json | 14 +++++++------- effects/loop2.json | 14 +++++++------- effects/mood-blobs-blue.json | 24 ++++++++++++------------ effects/mood-blobs-green.json | 24 ++++++++++++------------ effects/mood-blobs-red.json | 24 ++++++++++++------------ effects/rainbow-mood.json | 20 ++++++++++---------- effects/rainbow-swirl-fast.json | 20 ++++++++++---------- effects/rainbow-swirl.json | 20 ++++++++++---------- effects/random.json | 14 +++++++------- effects/snake.json | 20 ++++++++++---------- effects/sparks-color.json | 14 +++++++------- effects/sparks.json | 14 +++++++------- effects/x-mas.json | 16 ++++++++-------- 14 files changed, 129 insertions(+), 129 deletions(-) diff --git a/effects/knight-rider.json b/effects/knight-rider.json index b4644387..9801d491 100644 --- a/effects/knight-rider.json +++ b/effects/knight-rider.json @@ -1,10 +1,10 @@ -{ - "name" : "Knight rider", - "script" : "knight-rider.py", - "args" : - { - "speed" : 1.0, - "fadeFactor" : 0.7, - "color" : [255,0,0] - } -} +{ + "name" : "Knight rider", + "script" : "knight-rider.py", + "args" : + { + "speed" : 1.0, + "fadeFactor" : 0.7, + "color" : [255,0,0] + } +} diff --git a/effects/loop.json b/effects/loop.json index 9415f8b1..c4e58803 100644 --- a/effects/loop.json +++ b/effects/loop.json @@ -1,7 +1,7 @@ -{ - "name" : "Loop", - "script" : "loop.py", - "args" : - { - } -} +{ + "name" : "Loop", + "script" : "loop.py", + "args" : + { + } +} diff --git a/effects/loop2.json b/effects/loop2.json index 77f2c438..ebedbe34 100644 --- a/effects/loop2.json +++ b/effects/loop2.json @@ -1,7 +1,7 @@ -{ - "name" : "Loop2", - "script" : "loop2.py", - "args" : - { - } -} +{ + "name" : "Loop2", + "script" : "loop2.py", + "args" : + { + } +} diff --git a/effects/mood-blobs-blue.json b/effects/mood-blobs-blue.json index 1aa188ab..32280b46 100644 --- a/effects/mood-blobs-blue.json +++ b/effects/mood-blobs-blue.json @@ -1,12 +1,12 @@ -{ - "name" : "Blue mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [0,0,255], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Blue mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [0,0,255], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/mood-blobs-green.json b/effects/mood-blobs-green.json index c0c104fe..aabd536c 100644 --- a/effects/mood-blobs-green.json +++ b/effects/mood-blobs-green.json @@ -1,12 +1,12 @@ -{ - "name" : "Green mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [0,255,0], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Green mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [0,255,0], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/mood-blobs-red.json b/effects/mood-blobs-red.json index 3272dded..ac47af53 100644 --- a/effects/mood-blobs-red.json +++ b/effects/mood-blobs-red.json @@ -1,12 +1,12 @@ -{ - "name" : "Red mood blobs", - "script" : "mood-blobs.py", - "args" : - { - "rotationTime" : 60.0, - "color" : [255,0,0], - "hueChange" : 60.0, - "blobs" : 5, - "reverse" : false - } -} +{ + "name" : "Red mood blobs", + "script" : "mood-blobs.py", + "args" : + { + "rotationTime" : 60.0, + "color" : [255,0,0], + "hueChange" : 60.0, + "blobs" : 5, + "reverse" : false + } +} diff --git a/effects/rainbow-mood.json b/effects/rainbow-mood.json index fe754287..c9208b60 100644 --- a/effects/rainbow-mood.json +++ b/effects/rainbow-mood.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow mood", - "script" : "rainbow-mood.py", - "args" : - { - "rotation-time" : 60.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow mood", + "script" : "rainbow-mood.py", + "args" : + { + "rotation-time" : 60.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/rainbow-swirl-fast.json b/effects/rainbow-swirl-fast.json index 19fec89c..88e8d79d 100644 --- a/effects/rainbow-swirl-fast.json +++ b/effects/rainbow-swirl-fast.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow swirl fast", - "script" : "rainbow-swirl.py", - "args" : - { - "rotation-time" : 3.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow swirl fast", + "script" : "rainbow-swirl.py", + "args" : + { + "rotation-time" : 3.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/rainbow-swirl.json b/effects/rainbow-swirl.json index 3f7b7243..43a80a8d 100644 --- a/effects/rainbow-swirl.json +++ b/effects/rainbow-swirl.json @@ -1,10 +1,10 @@ -{ - "name" : "Rainbow swirl", - "script" : "rainbow-swirl.py", - "args" : - { - "rotation-time" : 20.0, - "brightness" : 1.0, - "reverse" : false - } -} +{ + "name" : "Rainbow swirl", + "script" : "rainbow-swirl.py", + "args" : + { + "rotation-time" : 20.0, + "brightness" : 1.0, + "reverse" : false + } +} diff --git a/effects/random.json b/effects/random.json index dc1d79ae..3dbc26d4 100644 --- a/effects/random.json +++ b/effects/random.json @@ -1,7 +1,7 @@ -{ - "name" : "Random", - "script" : "random.py", - "args" : - { - } -} +{ + "name" : "Random", + "script" : "random.py", + "args" : + { + } +} diff --git a/effects/snake.json b/effects/snake.json index 2c7ba395..eb914c89 100644 --- a/effects/snake.json +++ b/effects/snake.json @@ -1,10 +1,10 @@ -{ - "name" : "Snake", - "script" : "snake.py", - "args" : - { - "rotation-time" : 10.0, - "color" : [255, 0, 0], - "percentage" : 25 - } -} +{ + "name" : "Snake", + "script" : "snake.py", + "args" : + { + "rotation-time" : 10.0, + "color" : [255, 0, 0], + "percentage" : 25 + } +} diff --git a/effects/sparks-color.json b/effects/sparks-color.json index 1c3e8146..641b7d8d 100644 --- a/effects/sparks-color.json +++ b/effects/sparks-color.json @@ -1,7 +1,7 @@ -{ - "name" : "Sparks color", - "script" : "sparks-color.py", - "args" : - { - } -} +{ + "name" : "Sparks color", + "script" : "sparks-color.py", + "args" : + { + } +} diff --git a/effects/sparks.json b/effects/sparks.json index d4040309..f00c01ae 100644 --- a/effects/sparks.json +++ b/effects/sparks.json @@ -1,7 +1,7 @@ -{ - "name" : "Sparks", - "script" : "sparks.py", - "args" : - { - } -} +{ + "name" : "Sparks", + "script" : "sparks.py", + "args" : + { + } +} diff --git a/effects/x-mas.json b/effects/x-mas.json index 72892a52..6c73b645 100644 --- a/effects/x-mas.json +++ b/effects/x-mas.json @@ -1,8 +1,8 @@ -{ - "name" : "X-Mas", - "script" : "x-mas.py", - "args" : - { - "sleepTime" : 0.75 - } -} +{ + "name" : "X-Mas", + "script" : "x-mas.py", + "args" : + { + "sleepTime" : 0.75 + } +} From de5b2849751537a334ab684d3d22591cc9ed8fd9 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 20 Jan 2016 22:36:21 +0100 Subject: [PATCH 03/31] modify effects - snake has a nice tail - random is not so fast anymore - merge sparks and sparks-color - make more params available in json files Former-commit-id: fc2a4f6f6ce2b44a35a75a9c0dbe36504b790be9 --- effects/random.json | 6 ++++-- effects/random.py | 18 +++++++----------- effects/snake.json | 8 ++++---- effects/snake.py | 2 +- effects/sparks-color.json | 11 +++++++++-- effects/sparks-color.py | 35 ----------------------------------- effects/sparks.json | 7 +++++++ effects/sparks.py | 32 ++++++++++++++++++-------------- 8 files changed, 50 insertions(+), 69 deletions(-) delete mode 100644 effects/sparks-color.py diff --git a/effects/random.json b/effects/random.json index 3dbc26d4..4a85b133 100644 --- a/effects/random.json +++ b/effects/random.json @@ -1,7 +1,9 @@ { - "name" : "Random", + "name" : "Random", "script" : "random.py", - "args" : + "args" : { + "speed" : 1.0, + "saturation" : 1.0 } } diff --git a/effects/random.py b/effects/random.py index 0f5406b1..63b56dca 100644 --- a/effects/random.py +++ b/effects/random.py @@ -1,24 +1,20 @@ -import hyperion -import time -import colorsys -import random +import hyperion, time, colorsys, random + +# get args +sleepTime = float(hyperion.args.get('speed', 1.0)) +saturation = float(hyperion.args.get('saturation', 1.0)) +ledData = bytearray() # Initialize the led data -ledData = bytearray() for i in range(hyperion.ledCount): ledData += bytearray((0,0,0)) -sleepTime = 0.001 - # Start the write data loop while not hyperion.abort(): hyperion.setColor(ledData) for i in range(hyperion.ledCount): if random.randrange(10) == 1: - hue = random.random() - sat = 1.0 - val = random.random() - rgb = colorsys.hsv_to_rgb(hue, sat, val) + rgb = colorsys.hsv_to_rgb(random.random(), saturation, random.random()) ledData[i*3 ] = int(255*rgb[0]) ledData[i*3+1] = int(255*rgb[1]) ledData[i*3+2] = int(255*rgb[2]) diff --git a/effects/snake.json b/effects/snake.json index eb914c89..d5a7674f 100644 --- a/effects/snake.json +++ b/effects/snake.json @@ -1,10 +1,10 @@ { - "name" : "Snake", + "name" : "Snake", "script" : "snake.py", "args" : { - "rotation-time" : 10.0, - "color" : [255, 0, 0], - "percentage" : 25 + "rotation-time" : 12.0, + "color" : [255, 0, 0], + "percentage" : 10 } } diff --git a/effects/snake.py b/effects/snake.py index 2ae5cb37..d8d16561 100644 --- a/effects/snake.py +++ b/effects/snake.py @@ -23,7 +23,7 @@ for i in range(hyperion.ledCount-snakeLeds): ledData += bytearray((0, 0, 0)) for i in range(1,snakeLeds+1): - rgb = colorsys.hsv_to_rgb(hsv[0], hsv[1], hsv[2]/i) + rgb = colorsys.hsv_to_rgb(hsv[0], hsv[1], hsv[2]*(snakeLeds-i)/snakeLeds) ledData += bytearray((int(rgb[0]*255), int(rgb[1]*255), int(rgb[2]*255))) # Calculate the sleep time and rotation increment diff --git a/effects/sparks-color.json b/effects/sparks-color.json index 641b7d8d..e4d3649e 100644 --- a/effects/sparks-color.json +++ b/effects/sparks-color.json @@ -1,7 +1,14 @@ { - "name" : "Sparks color", - "script" : "sparks-color.py", + "name" : "Sparks Color", + "script" : "sparks.py", "args" : { + "rotation-time" : 3.0, + "sleep-time" : 0.05, + "brightness" : 1.0, + "saturation" : 1.0, + "reverse" : false, + "color" : [255,255,255], + "random-color" : true } } diff --git a/effects/sparks-color.py b/effects/sparks-color.py deleted file mode 100644 index 34b5acf5..00000000 --- a/effects/sparks-color.py +++ /dev/null @@ -1,35 +0,0 @@ -import hyperion -import time -import colorsys -import random - -# Get the parameters -rotationTime = float(hyperion.args.get('rotation-time', 3.0)) -brightness = float(hyperion.args.get('brightness', 1.0)) -saturation = float(hyperion.args.get('saturation', 1.0)) -reverse = bool(hyperion.args.get('reverse', False)) - -# Check parameters -rotationTime = max(0.1, rotationTime) -brightness = max(0.0, min(brightness, 1.0)) -saturation = max(0.0, min(saturation, 1.0)) - -# Initialize the led data -ledData = bytearray() - -sleepTime = 0.05 - -# Start the write data loop -while not hyperion.abort(): - ledData[:] = bytearray(3*hyperion.ledCount) - for i in range(hyperion.ledCount): - if random.random() < 0.005: - hue = random.random() - sat = 1 - val = 1 - rgb = colorsys.hsv_to_rgb(hue, sat, val) - ledData[i*3] = int(255*rgb[0]) - ledData[i*3+1] = int(255*rgb[1]) - ledData[i*3+2] = int(255*rgb[2]) - hyperion.setColor(ledData) - time.sleep(sleepTime) diff --git a/effects/sparks.json b/effects/sparks.json index f00c01ae..0860987e 100644 --- a/effects/sparks.json +++ b/effects/sparks.json @@ -3,5 +3,12 @@ "script" : "sparks.py", "args" : { + "rotation-time" : 3.0, + "sleep-time" : 0.05, + "brightness" : 1.0, + "saturation" : 1.0, + "reverse" : false, + "color" : [255,255,255], + "random-color" : false } } diff --git a/effects/sparks.py b/effects/sparks.py index 821719e2..f215ba9a 100644 --- a/effects/sparks.py +++ b/effects/sparks.py @@ -1,33 +1,37 @@ -import hyperion -import time -import colorsys -import random +import hyperion, time, colorsys, random # Get the parameters rotationTime = float(hyperion.args.get('rotation-time', 3.0)) -brightness = float(hyperion.args.get('brightness', 1.0)) -saturation = float(hyperion.args.get('saturation', 1.0)) -reverse = bool(hyperion.args.get('reverse', False)) +sleepTime = float(hyperion.args.get('sleep-time', 0.05)) +brightness = float(hyperion.args.get('brightness', 1.0)) +saturation = float(hyperion.args.get('saturation', 1.0)) +reverse = bool(hyperion.args.get('reverse', False)) +color = list(hyperion.args.get('color', (255,255,255))) +randomColor = bool(hyperion.args.get('random-color', False)) # Check parameters rotationTime = max(0.1, rotationTime) -brightness = max(0.0, min(brightness, 1.0)) -saturation = max(0.0, min(saturation, 1.0)) +brightness = max(0.0, min(brightness, 1.0)) +saturation = max(0.0, min(saturation, 1.0)) # Initialize the led data ledData = bytearray() for i in range(hyperion.ledCount): ledData += bytearray((0, 0, 0)) -sleepTime = 0.05 - # Start the write data loop while not hyperion.abort(): ledData[:] = bytearray(3*hyperion.ledCount) for i in range(hyperion.ledCount): if random.random() < 0.005: - ledData[i*3] = 255 - ledData[i*3+1] = 255 - ledData[i*3+2] = 255 + + if randomColor: + rgb = colorsys.hsv_to_rgb(random.random(), 1, 1) + for n in range(3): + color[n] = int(rgb[n]*255) + + for n in range(3): + ledData[i*3+n] = color[n] + hyperion.setColor(ledData) time.sleep(sleepTime) From 2555c5071053c5f5112893d7bc11a525e234c0f3 Mon Sep 17 00:00:00 2001 From: redpanther Date: Sat, 23 Jan 2016 13:09:23 +0100 Subject: [PATCH 04/31] add shutdown effect: system shutdown is disabled by default. enable it in json (set false to true) the shutdown is abortable. simply select another effect before shutdown time reached this effect is made for linux and did not workl on windows without modifications Former-commit-id: 32f92246fbc87de576e4b1059dd319646917ec74 --- effects/shutdown.json | 11 ++++++++++ effects/shutdown.py | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 effects/shutdown.json create mode 100644 effects/shutdown.py diff --git a/effects/shutdown.json b/effects/shutdown.json new file mode 100644 index 00000000..7e09a13b --- /dev/null +++ b/effects/shutdown.json @@ -0,0 +1,11 @@ +{ + "name" : "System Shutdown", + "script" : "shutdown.py", + "args" : + { + "speed" : 1.2, + "alarm-color" : [255,0,0], + "post-color" : [255,174,11], + "shutdown-enabled" : false + } +} diff --git a/effects/shutdown.py b/effects/shutdown.py new file mode 100644 index 00000000..469443d0 --- /dev/null +++ b/effects/shutdown.py @@ -0,0 +1,51 @@ +import hyperion, time, colorsys, random, subprocess + +def setPixel(x,y,rgb): + global imageData, width + offset = y*width*3 + x*3 + if offset+2 < len(imageData): + imageData[offset] = rgb[0] + imageData[offset+1] = rgb[1] + imageData[offset+2] = rgb[2] + +# Initialize the led data and args +sleepTime = float(hyperion.args.get('speed', 1.0))*0.5 +alarmColor = hyperion.args.get('alarm-color', (255,0,0)) +postColor = hyperion.args.get('post-color', (255,174,11)) +off = bool(hyperion.args.get('shutdown-enabled', False)) +width = 12 +height = 10 + +imageData = bytearray(height * width * (0,0,0)) +imageDataBlack = bytearray(height * width * (0,0,0)) +imageDataRed = bytearray(height * width * alarmColor) + +# Start the write data loop +for i in range(6): + if hyperion.abort(): + off = False + break + if i % 2: + hyperion.setImage(width, height, imageDataRed) + else: + hyperion.setImage(width, height, imageDataBlack) + time.sleep(sleepTime) + +for y in range(height,0,-1): + if hyperion.abort(): + off = False + break + for x in range(width): + setPixel(x, y-1, alarmColor) + hyperion.setImage(width, height, imageData) + time.sleep(sleepTime) +time.sleep(1) + +for y in range(height): + for x in range(width): + setPixel(x, y, postColor) +hyperion.setImage(width, height, imageData) +time.sleep(2) + +if off and not hyperion.abort(): + subprocess.call("halt") From e7c7e05f88e18ade798a7278c01fee57ef5b7311 Mon Sep 17 00:00:00 2001 From: redpanther Date: Sun, 24 Jan 2016 08:10:36 +0100 Subject: [PATCH 05/31] add fading effect like in a cinema. sped start and end color are selectable in json file rename loop effects to more meaningfull names Former-commit-id: bed033e19d7cb38b0d5f11313a9f927ac8121194 --- effects/cinema-fade-in.json | 10 ++++++++ effects/cinema-fade-off.json | 10 ++++++++ effects/fade.py | 34 +++++++++++++++++++++++++++ effects/loop.json | 7 ------ effects/loop2.json | 7 ------ effects/loop2.py | 33 -------------------------- effects/running_dots.json | 10 ++++++++ effects/running_dots.py | 43 ++++++++++++++++++++++++++++++++++ effects/traces.json | 8 +++++++ effects/{loop.py => traces.py} | 8 +++---- 10 files changed, 119 insertions(+), 51 deletions(-) create mode 100644 effects/cinema-fade-in.json create mode 100644 effects/cinema-fade-off.json create mode 100644 effects/fade.py delete mode 100644 effects/loop.json delete mode 100644 effects/loop2.json delete mode 100644 effects/loop2.py create mode 100644 effects/running_dots.json create mode 100644 effects/running_dots.py create mode 100644 effects/traces.json rename effects/{loop.py => traces.py} (76%) diff --git a/effects/cinema-fade-in.json b/effects/cinema-fade-in.json new file mode 100644 index 00000000..2730c568 --- /dev/null +++ b/effects/cinema-fade-in.json @@ -0,0 +1,10 @@ +{ + "name" : "Cinema brighten lights", + "script" : "fade.py", + "args" : + { + "fade-time" : 5.0, + "color-start" : [ 136, 97, 7 ], + "color-end" : [ 238, 173, 47 ] + } +} diff --git a/effects/cinema-fade-off.json b/effects/cinema-fade-off.json new file mode 100644 index 00000000..7d7c20f8 --- /dev/null +++ b/effects/cinema-fade-off.json @@ -0,0 +1,10 @@ +{ + "name" : "Cinema dim lights", + "script" : "fade.py", + "args" : + { + "fade-time" : 5.0, + "color-start" : [ 238, 173, 47 ], + "color-end" : [ 136, 97, 7 ] + } +} diff --git a/effects/fade.py b/effects/fade.py new file mode 100644 index 00000000..950605d1 --- /dev/null +++ b/effects/fade.py @@ -0,0 +1,34 @@ +import hyperion, time + +def setColor(rgb): + hyperion.setColor( bytearray( hyperion.ledCount * rgb)) + +# Get the parameters +fadeTime = float(hyperion.args.get('fade-time', 5.0)) +colorStart = hyperion.args.get('color-start', (255,174,11)) +colorEnd = hyperion.args.get('color-end', (100,100,100)) + +color_step = ( + (colorEnd[0] - colorStart[0]) / 256.0, + (colorEnd[1] - colorStart[1]) / 256.0, + (colorEnd[2] - colorStart[2]) / 256.0 +) + +# fade color +for step in range(256): + if hyperion.abort(): + break + + setColor( ( + int( min(max(0, colorStart[0] + color_step[0]*step), 255) ), + int( min(max(0, colorStart[1] + color_step[1]*step), 255) ), + int( min(max(0, colorStart[2] + color_step[2]*step), 255) ) + ) ) + + time.sleep( fadeTime / 256 ) + +# maintain color until effect end +setColor(colorEnd) +while not hyperion.abort(): + time.sleep(1) + diff --git a/effects/loop.json b/effects/loop.json deleted file mode 100644 index c4e58803..00000000 --- a/effects/loop.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name" : "Loop", - "script" : "loop.py", - "args" : - { - } -} diff --git a/effects/loop2.json b/effects/loop2.json deleted file mode 100644 index ebedbe34..00000000 --- a/effects/loop2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name" : "Loop2", - "script" : "loop2.py", - "args" : - { - } -} diff --git a/effects/loop2.py b/effects/loop2.py deleted file mode 100644 index 3498ac4e..00000000 --- a/effects/loop2.py +++ /dev/null @@ -1,33 +0,0 @@ -import hyperion -import time -import colorsys -import random - -# Initialize the led data -ledData = bytearray() -for i in range(hyperion.ledCount): - ledData += bytearray((0,0,0)) - -sleepTime = 0.005 - -runners = [ -{ "pos":0, "step":4 , "lvl":255}, -{ "pos":1, "step":5 , "lvl":255}, -{ "pos":2, "step":6 , "lvl":255}, -{ "pos":0, "step":7 , "lvl":255}, -{ "pos":1, "step":8 , "lvl":255}, -{ "pos":2, "step":9, "lvl":255}, -] - -# Start the write data loop -count = 0 -while not hyperion.abort(): - count += 1 - for r in runners: - if count%r["step"] == 0: - ledData[r["pos"]] = 0 - r["pos"] = (r["pos"]+3)%(hyperion.ledCount*3) - ledData[r["pos"]] = r["lvl"] - - hyperion.setColor(ledData) - time.sleep(sleepTime) diff --git a/effects/running_dots.json b/effects/running_dots.json new file mode 100644 index 00000000..8accd451 --- /dev/null +++ b/effects/running_dots.json @@ -0,0 +1,10 @@ +{ + "name" : "Running dots", + "script" : "running_dots.py", + "args" : + { + "speed" : 1.5, + "whiteLevel" : 100, + "colorLevel" : 230 + } +} diff --git a/effects/running_dots.py b/effects/running_dots.py new file mode 100644 index 00000000..16d8d039 --- /dev/null +++ b/effects/running_dots.py @@ -0,0 +1,43 @@ +import hyperion, time, colorsys, random + +# get options from args +sleepTime = float(hyperion.args.get('speed', 1.5)) * 0.005 +whiteLevel = int(hyperion.args.get('whiteLevel', 0)) +lvl = int(hyperion.args.get('colorLevel', 220)) + +# check value +whiteLevel = min( whiteLevel, 254 ) +lvl = min( lvl, 255 ) + +if whiteLevel >= lvl: + lvl = 255 + +# Initialize the led data +ledData = bytearray() +for i in range(hyperion.ledCount): + ledData += bytearray((0,0,0)) + +runners = [ + { "pos":0, "step": 4, "lvl":lvl}, + { "pos":1, "step": 5, "lvl":lvl}, + { "pos":2, "step": 6, "lvl":lvl}, + { "pos":0, "step": 7, "lvl":lvl}, + { "pos":1, "step": 8, "lvl":lvl}, + { "pos":2, "step": 9, "lvl":lvl}, + #{ "pos":0, "step":10, "lvl":lvl}, + #{ "pos":1, "step":11, "lvl":lvl}, + #{ "pos":2, "step":12, "lvl":lvl}, +] + +# Start the write data loop +counter = 0 +while not hyperion.abort(): + counter += 1 + for r in runners: + if counter % r["step"] == 0: + ledData[r["pos"]] = whiteLevel + r["pos"] = (r["pos"]+3) % (hyperion.ledCount*3) + ledData[r["pos"]] = r["lvl"] + + hyperion.setColor(ledData) + time.sleep(sleepTime) diff --git a/effects/traces.json b/effects/traces.json new file mode 100644 index 00000000..a2bfdabb --- /dev/null +++ b/effects/traces.json @@ -0,0 +1,8 @@ +{ + "name" : "Color traces", + "script" : "traces.py", + "args" : + { + "speed" : 1.0 + } +} diff --git a/effects/loop.py b/effects/traces.py similarity index 76% rename from effects/loop.py rename to effects/traces.py index 93011e97..7f6a8dfe 100644 --- a/effects/loop.py +++ b/effects/traces.py @@ -8,15 +8,15 @@ ledData = bytearray() for i in range(hyperion.ledCount): ledData += bytearray((0,0,0)) -sleepTime = 0.002 +sleepTime = float(hyperion.args.get('speed', 1.0)) * 0.004 runners = [ { "i":0, "pos":0, "c":0, "step":9 , "lvl":255}, { "i":1, "pos":0, "c":0, "step":8 , "lvl":255}, { "i":2, "pos":0, "c":0, "step":7 , "lvl":255}, -{ "i":0, "pos":0, "c":0, "step":6 , "lvl":0}, -{ "i":1, "pos":0, "c":0, "step":5 , "lvl":0}, -{ "i":2, "pos":0, "c":0, "step":4, "lvl":0}, +{ "i":0, "pos":0, "c":0, "step":6 , "lvl":100}, +{ "i":1, "pos":0, "c":0, "step":5 , "lvl":100}, +{ "i":2, "pos":0, "c":0, "step":4, "lvl":100}, ] # Start the write data loop From 8732ffacf4a03690c27c142317b394aeb602864b Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 28 Jan 2016 05:50:32 +0100 Subject: [PATCH 06/31] simplify code of effect fade.py Former-commit-id: 3c7c633e764d14c9e11c6e145289894954695c65 --- effects/fade.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/effects/fade.py b/effects/fade.py index 950605d1..eb233a38 100644 --- a/effects/fade.py +++ b/effects/fade.py @@ -1,8 +1,5 @@ import hyperion, time -def setColor(rgb): - hyperion.setColor( bytearray( hyperion.ledCount * rgb)) - # Get the parameters fadeTime = float(hyperion.args.get('fade-time', 5.0)) colorStart = hyperion.args.get('color-start', (255,174,11)) @@ -15,20 +12,16 @@ color_step = ( ) # fade color +calcChannel = lambda i: min(max(int(colorStart[i] + color_step[i]*step),0),255) for step in range(256): if hyperion.abort(): break - setColor( ( - int( min(max(0, colorStart[0] + color_step[0]*step), 255) ), - int( min(max(0, colorStart[1] + color_step[1]*step), 255) ), - int( min(max(0, colorStart[2] + color_step[2]*step), 255) ) - ) ) - + hyperion.setColor( calcChannel(0),calcChannel(1),calcChannel(2) ) time.sleep( fadeTime / 256 ) # maintain color until effect end -setColor(colorEnd) +hyperion.setColor(colorEnd[0],colorEnd[1],colorEnd[2]) while not hyperion.abort(): time.sleep(1) From e5b802c01d928aeda2eb19056723faa4feeeb0f9 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 28 Jan 2016 06:12:28 +0100 Subject: [PATCH 07/31] simplify effects Former-commit-id: bbb8dc4c3852d0651eb2f4e9999e426db4a905d0 --- effects/shutdown.py | 8 +++----- effects/strobe.py | 12 +++--------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/effects/shutdown.py b/effects/shutdown.py index 469443d0..214af60e 100644 --- a/effects/shutdown.py +++ b/effects/shutdown.py @@ -1,4 +1,4 @@ -import hyperion, time, colorsys, random, subprocess +import hyperion, time, subprocess def setPixel(x,y,rgb): global imageData, width @@ -17,8 +17,6 @@ width = 12 height = 10 imageData = bytearray(height * width * (0,0,0)) -imageDataBlack = bytearray(height * width * (0,0,0)) -imageDataRed = bytearray(height * width * alarmColor) # Start the write data loop for i in range(6): @@ -26,9 +24,9 @@ for i in range(6): off = False break if i % 2: - hyperion.setImage(width, height, imageDataRed) + hyperion.setColor(alarmColor[0], alarmColor[1], alarmColor[2]) else: - hyperion.setImage(width, height, imageDataBlack) + hyperion.setColor(0, 0, 0) time.sleep(sleepTime) for y in range(height,0,-1): diff --git a/effects/strobe.py b/effects/strobe.py index 007e6133..39a3a558 100644 --- a/effects/strobe.py +++ b/effects/strobe.py @@ -1,6 +1,4 @@ -import hyperion -import time -import colorsys +import hyperion, time # Get the rotation time color = hyperion.args.get('color', (255,255,255)) @@ -12,13 +10,9 @@ frequency = min(100.0, frequency) # Compute the strobe interval sleepTime = 1.0 / frequency -# Initialize the led data -blackLedsData = bytearray(hyperion.ledCount * ( 0, 0, 0)) -whiteLedsData = bytearray(hyperion.ledCount * color) - # Start the write data loop while not hyperion.abort(): - hyperion.setColor(blackLedsData) + hyperion.setColor(0, 0, 0) time.sleep(sleepTime) - hyperion.setColor(whiteLedsData) + hyperion.setColor(color[0], color[1], color[2]) time.sleep(sleepTime) From 5dc59344c4553dd6e34b401b7b7afa986ee6a26b Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 8 Feb 2016 16:56:23 +0100 Subject: [PATCH 08/31] forward protobuf messages. configure (send proto messages to two other hyperiond): "protoServer" : { "port" : 19446, "forward" : [ "192.168.0.10:19445", "192.168.0.11:19445" ] }, Former-commit-id: 33af219cfce99609ca7245d662dc0f0561013bbd --- include/protoserver/ProtoConnection.h | 8 ++++---- include/protoserver/ProtoServer.h | 4 +++- libsrc/protoserver/ProtoClientConnection.cpp | 17 ++++++++++++++++- libsrc/protoserver/ProtoClientConnection.h | 8 +++++++- libsrc/protoserver/ProtoServer.cpp | 7 +++++-- src/hyperiond/hyperiond.cpp | 14 +++++++++++++- 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/include/protoserver/ProtoConnection.h b/include/protoserver/ProtoConnection.h index bb41e1b7..a61947fe 100644 --- a/include/protoserver/ProtoConnection.h +++ b/include/protoserver/ProtoConnection.h @@ -67,10 +67,6 @@ public: /// void clearAll(); -private: - /// Try to connect to the Hyperion host - void connectToHost(); - /// /// Send a command message and receive its reply /// @@ -78,6 +74,10 @@ private: /// void sendMessage(const proto::HyperionRequest & message); +private: + /// Try to connect to the Hyperion host + void connectToHost(); + /// /// Parse a reply message /// diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index dae57481..c18b38fb 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -6,6 +6,7 @@ // Qt includes #include #include +#include // Hyperion includes #include @@ -27,7 +28,7 @@ public: /// @param hyperion Hyperion instance /// @param port port number on which to start listening for connections /// - ProtoServer(Hyperion * hyperion, uint16_t port = 19445); + ProtoServer(Hyperion * hyperion, uint16_t port = 19445, QStringList * forwardClientList = new QStringList() ); ~ProtoServer(); /// @@ -56,4 +57,5 @@ private: /// List with open connections QSet _openConnections; + QStringList _forwardClients; }; diff --git a/libsrc/protoserver/ProtoClientConnection.cpp b/libsrc/protoserver/ProtoClientConnection.cpp index 165315f7..2f0cc8d3 100644 --- a/libsrc/protoserver/ProtoClientConnection.cpp +++ b/libsrc/protoserver/ProtoClientConnection.cpp @@ -20,7 +20,7 @@ // project includes #include "ProtoClientConnection.h" -ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion) : +ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion, QStringList forwardClientList) : QObject(), _socket(socket), _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()), @@ -30,11 +30,22 @@ ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hype // connect internal signals and slots connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); + + for (int i = 0; i < forwardClientList.size(); ++i) { + std::cout << "Proto forward to " << forwardClientList.at(i).toLocal8Bit().constData() << std::endl; + ProtoConnection* p = new ProtoConnection("127.0.0.1:19445"); + p->setSkipReply(true); + _proxy_connections << p; + } + } ProtoClientConnection::~ProtoClientConnection() { delete _socket; + + while (!_proxy_connections.isEmpty()) + delete _proxy_connections.takeFirst(); } void ProtoClientConnection::readData() @@ -81,6 +92,10 @@ void ProtoClientConnection::socketClosed() void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message) { + // forward messages + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->sendMessage(message); + switch (message.command()) { case proto::HyperionRequest::COLOR: diff --git a/libsrc/protoserver/ProtoClientConnection.h b/libsrc/protoserver/ProtoClientConnection.h index ec7d2e1c..a0c1186e 100644 --- a/libsrc/protoserver/ProtoClientConnection.h +++ b/libsrc/protoserver/ProtoClientConnection.h @@ -6,12 +6,14 @@ // Qt includes #include #include +#include // Hyperion includes #include // proto includes #include "message.pb.h" +#include "protoserver/ProtoConnection.h" class ImageProcessor; @@ -28,7 +30,7 @@ public: /// @param socket The Socket object for this connection /// @param hyperion The Hyperion server /// - ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion); + ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion, QStringList forwardClientList); /// /// Destructor @@ -123,4 +125,8 @@ private: /// The buffer used for reading data from the socket QByteArray _receiveBuffer; + + /// Hyperion proto connection object for forwarding + QList _proxy_connections; + }; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index a1afa30c..54d8611b 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -5,12 +5,15 @@ #include #include "ProtoClientConnection.h" -ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) : +ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port, QStringList * forwardClientList) : QObject(), _hyperion(hyperion), _server(), _openConnections() { + for (int i = 0; i < forwardClientList->size(); ++i) + _forwardClients << forwardClientList->at(i); + if (!_server.listen(QHostAddress::Any, port)) { throw std::runtime_error("Proto server could not bind to port"); @@ -39,7 +42,7 @@ void ProtoServer::newConnection() if (socket != nullptr) { std::cout << "New proto connection" << std::endl; - ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion); + ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion, _forwardClients); _openConnections.insert(connection); // register slot for cleaning up after the connection closed diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 032d44db..d96b345a 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -1,6 +1,7 @@ // C++ includes #include #include +#include // QT includes #include @@ -368,7 +369,18 @@ int main(int argc, char** argv) if (config.isMember("protoServer")) { const Json::Value & protoServerConfig = config["protoServer"]; - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt()); + QStringList forwardClientList; + + if ( ! protoServerConfig["forward"].isNull() && protoServerConfig["forward"].isArray() ) + { + for (const Json::Value& client : protoServerConfig["forward"]) + { + forwardClientList << client.asString().c_str(); + std::cout << client.asString() << std::endl; + } + } + + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt(), &forwardClientList ); std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; } #endif From b01b5eb005d51e7cf35de62a76b908e686d4e994 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 18:25:18 +0100 Subject: [PATCH 09/31] - prepare general way to send (proto) messages. currently only incomming protomessages are forwarded - begin impl. of json server Former-commit-id: 8f9237cd57ada1e84dc05e60b9ad723e47fd57b1 --- include/hyperion/Hyperion.h | 9 ++ include/hyperion/MessageForwarder.h | 31 +++++ include/protoserver/ProtoServer.h | 15 ++- libsrc/hyperion/CMakeLists.txt | 134 ++++++++++--------- libsrc/hyperion/Hyperion.cpp | 30 +++++ libsrc/hyperion/MessageForwarder.cpp | 34 +++++ libsrc/jsonserver/JsonClientConnection.cpp | 67 +++++++++- libsrc/jsonserver/JsonClientConnection.h | 6 + libsrc/protoserver/ProtoClientConnection.cpp | 16 +-- libsrc/protoserver/ProtoClientConnection.h | 7 +- libsrc/protoserver/ProtoServer.cpp | 29 +++- src/hyperiond/hyperiond.cpp | 13 +- 12 files changed, 287 insertions(+), 104 deletions(-) create mode 100644 include/hyperion/MessageForwarder.h create mode 100644 libsrc/hyperion/MessageForwarder.cpp diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index b6ed0946..811f0199 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -13,6 +13,7 @@ // Hyperion includes #include #include +#include // Effect engine includes #include @@ -125,6 +126,10 @@ public slots: /// Tell Hyperion that the transforms have changed and the leds need to be updated void transformsUpdated(); + /// Returns MessageForwarder Object + /// @return instance of message forwarder object + MessageForwarder * getForwarder(); + /// /// Clears the given priority channel. This will switch the led-colors to the colors of the next /// lower priority channel (or off if no more channels are set) @@ -168,6 +173,7 @@ public: static RgbChannelTransform * createRgbChannelTransform(const Json::Value& colorConfig); static LedDevice * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice * ledDevice); + static MessageForwarder * createMessageForwarder(const Json::Value & forwarderConfig); signals: /// Signal which is emitted when a priority channel is actively cleared @@ -201,6 +207,9 @@ private: /// Effect engine EffectEngine * _effectEngine; + // proto and json Message forwarder + MessageForwarder * _messageForwarder; + /// The timer for handling priority channel timeouts QTimer _timer; }; diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h new file mode 100644 index 00000000..467d0d35 --- /dev/null +++ b/include/hyperion/MessageForwarder.h @@ -0,0 +1,31 @@ +#pragma once + +// STL includes +#include +#include +#include +#include + +// QT includes +#include +#include + +// Utils includes +#include +class MessageForwarder +{ +public: + MessageForwarder(); + ~MessageForwarder(); + + void addJsonSlave(std::string slave); + void addProtoSlave(std::string slave); + void sendMessage(); + + QStringList getProtoSlaves(); + +private: + bool _running; + + QStringList _protoSlaves; +}; diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index c18b38fb..1d530caa 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -6,12 +6,19 @@ // Qt includes #include #include +#include #include // Hyperion includes #include +// forward decl class ProtoClientConnection; +class ProtoConnection; + +namespace proto { +class HyperionRequest; +} /// /// This class creates a TCP server which accepts connections wich can then send @@ -28,7 +35,7 @@ public: /// @param hyperion Hyperion instance /// @param port port number on which to start listening for connections /// - ProtoServer(Hyperion * hyperion, uint16_t port = 19445, QStringList * forwardClientList = new QStringList() ); + ProtoServer(Hyperion * hyperion, uint16_t port = 19445); ~ProtoServer(); /// @@ -48,6 +55,8 @@ private slots: /// void closedConnection(ProtoClientConnection * connection); + void newMessage(const proto::HyperionRequest * message); + private: /// Hyperion instance Hyperion * _hyperion; @@ -58,4 +67,8 @@ private: /// List with open connections QSet _openConnections; QStringList _forwardClients; + + /// Hyperion proto connection object for forwarding + QList _proxy_connections; + }; diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 1434f105..3a277a7e 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -1,66 +1,68 @@ - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) - -# Group the headers that go through the MOC compiler -SET(Hyperion_QT_HEADERS - ${CURRENT_HEADER_DIR}/Hyperion.h - - ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h -) - -SET(Hyperion_HEADERS - ${CURRENT_HEADER_DIR}/ImageProcessor.h - ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h - ${CURRENT_HEADER_DIR}/ImageToLedsMap.h - ${CURRENT_HEADER_DIR}/LedString.h - ${CURRENT_HEADER_DIR}/PriorityMuxer.h - - ${CURRENT_SOURCE_DIR}/MultiColorTransform.h -) - -SET(Hyperion_SOURCES - ${CURRENT_SOURCE_DIR}/Hyperion.cpp - ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp - ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp - ${CURRENT_SOURCE_DIR}/LedString.cpp - ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp - - ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp - ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp - ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp -) - -set(Hyperion_RESOURCES - ${CURRENT_SOURCE_DIR}/resource.qrc -) - -if(ENABLE_QT5) -QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) -QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") -else(ENABLE_QT5) -QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) -QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") -endif(ENABLE_QT5) - -add_library(hyperion - ${Hyperion_HEADERS} - ${Hyperion_QT_HEADERS} - ${Hyperion_HEADERS_MOC} - ${Hyperion_SOURCES} - ${Hyperion_RESOURCES_RCC} -) - -if(ENABLE_QT5) -qt5_use_modules(hyperion Widgets) -endif(ENABLE_QT5) - -target_link_libraries(hyperion - blackborder - hyperion-utils - leddevice - effectengine - serialport - ${QT_LIBRARIES} -) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) + +# Group the headers that go through the MOC compiler +SET(Hyperion_QT_HEADERS + ${CURRENT_HEADER_DIR}/Hyperion.h + ${CURRENT_HEADER_DIR}/MessageForwarder.h + + ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h +) + +SET(Hyperion_HEADERS + ${CURRENT_HEADER_DIR}/ImageProcessor.h + ${CURRENT_HEADER_DIR}/ImageProcessorFactory.h + ${CURRENT_HEADER_DIR}/ImageToLedsMap.h + ${CURRENT_HEADER_DIR}/LedString.h + ${CURRENT_HEADER_DIR}/PriorityMuxer.h + + ${CURRENT_SOURCE_DIR}/MultiColorTransform.h +) + +SET(Hyperion_SOURCES + ${CURRENT_SOURCE_DIR}/Hyperion.cpp + ${CURRENT_SOURCE_DIR}/ImageProcessor.cpp + ${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp + ${CURRENT_SOURCE_DIR}/LedString.cpp + ${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp + + ${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp + ${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp + ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp + ${CURRENT_SOURCE_DIR}/MessageForwarder.cpp +) + +set(Hyperion_RESOURCES + ${CURRENT_SOURCE_DIR}/resource.qrc +) + +if(ENABLE_QT5) +QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) +QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +else(ENABLE_QT5) +QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS}) +QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress") +endif(ENABLE_QT5) + +add_library(hyperion + ${Hyperion_HEADERS} + ${Hyperion_QT_HEADERS} + ${Hyperion_HEADERS_MOC} + ${Hyperion_SOURCES} + ${Hyperion_RESOURCES_RCC} +) + +if(ENABLE_QT5) +qt5_use_modules(hyperion Widgets) +endif(ENABLE_QT5) + +target_link_libraries(hyperion + blackborder + hyperion-utils + leddevice + effectengine + serialport + ${QT_LIBRARIES} +) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 37c77927..ed23fb30 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -267,12 +267,39 @@ LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig, } +MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarderConfig) +{ + MessageForwarder * forwarder = new MessageForwarder(); + if ( ! forwarderConfig.isNull() ) + { + if ( ! forwarderConfig["json"].isNull() && forwarderConfig["json"].isArray() ) + { + for (const Json::Value& addr : forwarderConfig["json"]) + forwarder->addJsonSlave(addr.asString()); + } + + if ( ! forwarderConfig["proto"].isNull() && forwarderConfig["proto"].isArray() ) + { + for (const Json::Value& addr : forwarderConfig["proto"]) + forwarder->addProtoSlave(addr.asString()); + } + } + + return forwarder; +} + +MessageForwarder * Hyperion::getForwarder() +{ + return _messageForwarder; +} + Hyperion::Hyperion(const Json::Value &jsonConfig) : _ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))), _muxer(_ledString.leds().size()), _raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])), _device(LedDeviceFactory::construct(jsonConfig["device"])), _effectEngine(nullptr), + _messageForwarder(createMessageForwarder(jsonConfig["forwarder"])), _timer() { if (!_raw2ledTransform->verifyTransforms()) @@ -314,6 +341,9 @@ Hyperion::~Hyperion() // delete the color transform delete _raw2ledTransform; + + // delete the message forwarder + delete _messageForwarder; } unsigned Hyperion::getLedCount() const diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp new file mode 100644 index 00000000..8da277e2 --- /dev/null +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -0,0 +1,34 @@ +#include + + +MessageForwarder::MessageForwarder() : +_running(false) +{ +} + +MessageForwarder::~MessageForwarder() +{ +} + + +void MessageForwarder::addJsonSlave(std::string slave) +{ + std::cout << slave << std::endl; +} + +void MessageForwarder::addProtoSlave(std::string slave) +{ + _protoSlaves << QString(slave.c_str()); +} + +void MessageForwarder::sendMessage() +{ + if ( ! _running ) + return; + +} + +QStringList MessageForwarder::getProtoSlaves() +{ + return _protoSlaves; +} diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 87fb7c1f..1b700b25 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -250,8 +250,22 @@ void JsonClientConnection::handleMessage(const std::string &messageString) handleNotImplemented(); } + +void JsonClientConnection::forwardJsonMessage(const Json::Value & message) +{ + QTcpSocket client; + client.connectToHost(QHostAddress("127.0.0.1"), 19444); + if ( client.waitForConnected(500) ) + { + sendMessage(message,&client); + client.close(); + } +} + void JsonClientConnection::handleColorCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -289,6 +303,8 @@ void JsonClientConnection::handleColorCommand(const Json::Value &message) void JsonClientConnection::handleImageCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -320,6 +336,8 @@ void JsonClientConnection::handleImageCommand(const Json::Value &message) void JsonClientConnection::handleEffectCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); int duration = message.get("duration", -1).asInt(); @@ -418,6 +436,8 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) void JsonClientConnection::handleClearCommand(const Json::Value &message) { + forwardJsonMessage(message); + // extract parameters int priority = message["priority"].asInt(); @@ -428,8 +448,10 @@ void JsonClientConnection::handleClearCommand(const Json::Value &message) sendSuccessReply(); } -void JsonClientConnection::handleClearallCommand(const Json::Value &) +void JsonClientConnection::handleClearallCommand(const Json::Value & message) { + forwardJsonMessage(message); + // clear priority _hyperion->clearall(); @@ -530,10 +552,51 @@ void JsonClientConnection::sendMessage(const Json::Value &message) response.append(serializedReply.c_str(), serializedReply.length()); - _socket->write(response.data(), response.length()); + _socket->write(response.data(), response.length()); } } + +void JsonClientConnection::sendMessage(const Json::Value & message, QTcpSocket * socket) +{ + // serialize message (FastWriter already appends a newline) + std::string serializedMessage = Json::FastWriter().write(message); + + // write message + socket->write(serializedMessage.c_str()); + if (!socket->waitForBytesWritten()) + { + //std::cout << "Error while writing data to host" << std::endl; + return; + } + + // read reply data + QByteArray serializedReply; + while (!serializedReply.contains('\n')) + { + // receive reply + if (!socket->waitForReadyRead()) + { + //std::cout << "Error while reading data from host" << std::endl; + return; + } + + serializedReply += socket->readAll(); + } + int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message + + // parse reply data + Json::Reader jsonReader; + Json::Value reply; + if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply)) + { + //std::cout << "Error while parsing reply: invalid json" << std::endl; + return; + } + +} + + void JsonClientConnection::sendSuccessReply() { // create reply diff --git a/libsrc/jsonserver/JsonClientConnection.h b/libsrc/jsonserver/JsonClientConnection.h index 6575388a..01db54b1 100644 --- a/libsrc/jsonserver/JsonClientConnection.h +++ b/libsrc/jsonserver/JsonClientConnection.h @@ -124,6 +124,7 @@ private: /// @param message The JSON message to send /// void sendMessage(const Json::Value & message); + void sendMessage(const Json::Value & message, QTcpSocket * socket); /// /// Send a standard reply indicating success @@ -147,6 +148,11 @@ private: /// void handleWebSocketFrame(); + /// + /// forward json message + /// + void forwardJsonMessage(const Json::Value & message); + private: /// /// Check if a JSON messag is valid according to a given JSON schema diff --git a/libsrc/protoserver/ProtoClientConnection.cpp b/libsrc/protoserver/ProtoClientConnection.cpp index 2f0cc8d3..d1f087cd 100644 --- a/libsrc/protoserver/ProtoClientConnection.cpp +++ b/libsrc/protoserver/ProtoClientConnection.cpp @@ -20,7 +20,7 @@ // project includes #include "ProtoClientConnection.h" -ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion, QStringList forwardClientList) : +ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion) : QObject(), _socket(socket), _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()), @@ -30,22 +30,11 @@ ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hype // connect internal signals and slots connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); - - for (int i = 0; i < forwardClientList.size(); ++i) { - std::cout << "Proto forward to " << forwardClientList.at(i).toLocal8Bit().constData() << std::endl; - ProtoConnection* p = new ProtoConnection("127.0.0.1:19445"); - p->setSkipReply(true); - _proxy_connections << p; - } - } ProtoClientConnection::~ProtoClientConnection() { delete _socket; - - while (!_proxy_connections.isEmpty()) - delete _proxy_connections.takeFirst(); } void ProtoClientConnection::readData() @@ -93,8 +82,7 @@ void ProtoClientConnection::socketClosed() void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message) { // forward messages - for (int i = 0; i < _proxy_connections.size(); ++i) - _proxy_connections.at(i)->sendMessage(message); + emit newMessage(&message); switch (message.command()) { diff --git a/libsrc/protoserver/ProtoClientConnection.h b/libsrc/protoserver/ProtoClientConnection.h index a0c1186e..c68f56e0 100644 --- a/libsrc/protoserver/ProtoClientConnection.h +++ b/libsrc/protoserver/ProtoClientConnection.h @@ -30,7 +30,7 @@ public: /// @param socket The Socket object for this connection /// @param hyperion The Hyperion server /// - ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion, QStringList forwardClientList); + ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion); /// /// Destructor @@ -43,6 +43,7 @@ signals: /// @param connection This connection object /// void connectionClosed(ProtoClientConnection * connection); + void newMessage(const proto::HyperionRequest * message); private slots: /// @@ -125,8 +126,4 @@ private: /// The buffer used for reading data from the socket QByteArray _receiveBuffer; - - /// Hyperion proto connection object for forwarding - QList _proxy_connections; - }; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index 54d8611b..a7c51ca8 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -2,17 +2,27 @@ #include // project includes +#include #include +#include "protoserver/ProtoConnection.h" #include "ProtoClientConnection.h" -ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port, QStringList * forwardClientList) : +ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) : QObject(), _hyperion(hyperion), _server(), _openConnections() { - for (int i = 0; i < forwardClientList->size(); ++i) - _forwardClients << forwardClientList->at(i); + + MessageForwarder * forwarder = hyperion->getForwarder(); + QStringList slaves = forwarder->getProtoSlaves(); + + for (int i = 0; i < slaves.size(); ++i) { + std::cout << "Proto forward to " << slaves.at(i).toLocal8Bit().constData() << std::endl; + ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); + p->setSkipReply(true); + _proxy_connections << p; + } if (!_server.listen(QHostAddress::Any, port)) { @@ -28,6 +38,9 @@ ProtoServer::~ProtoServer() foreach (ProtoClientConnection * connection, _openConnections) { delete connection; } + + while (!_proxy_connections.isEmpty()) + delete _proxy_connections.takeFirst(); } uint16_t ProtoServer::getPort() const @@ -42,14 +55,22 @@ void ProtoServer::newConnection() if (socket != nullptr) { std::cout << "New proto connection" << std::endl; - ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion, _forwardClients); + ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion); _openConnections.insert(connection); // register slot for cleaning up after the connection closed connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*))); + connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*))); + } } +void ProtoServer::newMessage(const proto::HyperionRequest * message) +{ + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->sendMessage(*message); +} + void ProtoServer::closedConnection(ProtoClientConnection *connection) { std::cout << "Proto connection closed" << std::endl; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index d96b345a..7bb5e60e 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -369,18 +369,7 @@ int main(int argc, char** argv) if (config.isMember("protoServer")) { const Json::Value & protoServerConfig = config["protoServer"]; - QStringList forwardClientList; - - if ( ! protoServerConfig["forward"].isNull() && protoServerConfig["forward"].isArray() ) - { - for (const Json::Value& client : protoServerConfig["forward"]) - { - forwardClientList << client.asString().c_str(); - std::cout << client.asString() << std::endl; - } - } - - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt(), &forwardClientList ); + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; } #endif From df91527557342e7925c57de81610b67485d3d9ce Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 20:53:03 +0100 Subject: [PATCH 10/31] implement json forwarder Former-commit-id: 5519118304bd5690e6b512481347579339e78ac9 --- include/hyperion/MessageForwarder.h | 13 ++++++++--- libsrc/hyperion/Hyperion.cpp | 6 ++++++ libsrc/hyperion/MessageForwarder.cpp | 25 ++++++++++++++++------ libsrc/jsonserver/JsonClientConnection.cpp | 14 ++++++++---- libsrc/protoserver/ProtoServer.cpp | 1 - 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 467d0d35..0a3c1b19 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -9,12 +9,19 @@ // QT includes #include #include +#include // Utils includes #include class MessageForwarder { public: + + struct JsonSlaveAddress { + QHostAddress addr; + quint16 port = 19444; + }; + MessageForwarder(); ~MessageForwarder(); @@ -23,9 +30,9 @@ public: void sendMessage(); QStringList getProtoSlaves(); + QList getJsonSlaves(); private: - bool _running; - - QStringList _protoSlaves; + QStringList _protoSlaves; + QList _jsonSlaves; }; diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index ed23fb30..2463ed15 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -275,13 +275,19 @@ MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarde if ( ! forwarderConfig["json"].isNull() && forwarderConfig["json"].isArray() ) { for (const Json::Value& addr : forwarderConfig["json"]) + { + std::cout << "Json forward to " << addr.asString() << std::endl; forwarder->addJsonSlave(addr.asString()); + } } if ( ! forwarderConfig["proto"].isNull() && forwarderConfig["proto"].isArray() ) { for (const Json::Value& addr : forwarderConfig["proto"]) + { + std::cout << "Proto forward to " << addr.asString() << std::endl; forwarder->addProtoSlave(addr.asString()); + } } } diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 8da277e2..be9c9825 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,8 +1,7 @@ #include -MessageForwarder::MessageForwarder() : -_running(false) +MessageForwarder::MessageForwarder() { } @@ -13,7 +12,19 @@ MessageForwarder::~MessageForwarder() void MessageForwarder::addJsonSlave(std::string slave) { - std::cout << slave << std::endl; + QStringList parts = QString(slave.c_str()).split(":"); + if (parts.size() != 2) + throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(slave.c_str()).toStdString()); + + bool ok; + quint16 port = parts[1].toUShort(&ok); + if (!ok) + throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString()); + + JsonSlaveAddress c; + c.addr = QHostAddress(parts[0]); + c.port = port; + _jsonSlaves << c; } void MessageForwarder::addProtoSlave(std::string slave) @@ -23,12 +34,14 @@ void MessageForwarder::addProtoSlave(std::string slave) void MessageForwarder::sendMessage() { - if ( ! _running ) - return; - } QStringList MessageForwarder::getProtoSlaves() { return _protoSlaves; } + +QList MessageForwarder::getJsonSlaves() +{ + return _jsonSlaves; +} diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 1b700b25..e4dbc096 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -16,6 +16,7 @@ // hyperion util includes #include #include +#include #include #include @@ -254,11 +255,16 @@ void JsonClientConnection::handleMessage(const std::string &messageString) void JsonClientConnection::forwardJsonMessage(const Json::Value & message) { QTcpSocket client; - client.connectToHost(QHostAddress("127.0.0.1"), 19444); - if ( client.waitForConnected(500) ) + QList list = _hyperion->getForwarder()->getJsonSlaves(); + + for ( int i=0; igetProtoSlaves(); for (int i = 0; i < slaves.size(); ++i) { - std::cout << "Proto forward to " << slaves.at(i).toLocal8Bit().constData() << std::endl; ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); p->setSkipReply(true); _proxy_connections << p; From 2b1ac785d16da8c4dba39c5adc2585e95bf2fe66 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 15 Feb 2016 21:21:56 +0100 Subject: [PATCH 11/31] add example configs Former-commit-id: 8176d915580bd0bd3d1604bcbf678f988e1d85d8 --- config/hyperion.config.json | 14 ++++++++++++++ config/hyperion_x86.config.json | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 0f8404a9..291086db 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -23,6 +23,20 @@ "colorOrder" : "rgb" }, + /// Configuration for message forwarding to other hyperions + /// protobuffer and json remote interface are forwarded to configured hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// + /// ** pay attention which port you use. use correct ports for protols ** + /// + /// * 'proto' : list of host in form of : + /// * 'json' : list of host in form of : +/// "forwarder" : +/// { +/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ], +/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ] +/// }, + /// Color manipulation configuration used to tune the output colors to specific surroundings. /// The configuration contains a list of color-transforms. Each transform contains the /// following fields: diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json index 4121c499..ec21a35b 100644 --- a/config/hyperion_x86.config.json +++ b/config/hyperion_x86.config.json @@ -19,6 +19,21 @@ "colorOrder" : "rgb" }, + /// Configuration for message forwarding to other hyperions + /// protobuffer and json remote interface are forwarded to configured hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// + /// ** pay attention which port you use. use correct ports for protols ** + /// + /// * 'proto' : list of host in form of : + /// * 'json' : list of host in form of : +/// "forwarder" : +/// { +/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ], +/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ] +/// }, + + /// Color manipulation configuration used to tune the output colors to specific surroundings. /// The configuration contains a list of color-transforms. Each transform contains the /// following fields: From 7f5b141f435efb4747ca57412dd2732a1cb09741 Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 14:16:59 +0100 Subject: [PATCH 12/31] forwarder: remove default init of port, could procude compile errors and it is not needed Former-commit-id: 08d7524a2cda53136ae8c72d5fdc1f95f51a23e7 --- include/hyperion/MessageForwarder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 0a3c1b19..9cc034fc 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -19,7 +19,7 @@ public: struct JsonSlaveAddress { QHostAddress addr; - quint16 port = 19444; + quint16 port; }; MessageForwarder(); From 738bafee994a266365d25b090ac3ede8c820d84e Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 14:59:31 +0100 Subject: [PATCH 13/31] forwarder: add missing include Former-commit-id: 58d07b73ff1ad321a9cfbf73895b438665ce3c14 --- libsrc/hyperion/MessageForwarder.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index be9c9825..1ae4bef6 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,3 +1,6 @@ +// STL includes +#include + #include From 629461b944a94c55c02736b9a8ab28f23ff51e1a Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 15:41:40 +0100 Subject: [PATCH 14/31] implement proto forwarding for hyperiond internal v4l2 grabber cleanup Former-commit-id: 669f139386633e3435cdc33639134819464afd4d --- include/grabber/V4L2Wrapper.h | 1 + include/hyperion/MessageForwarder.h | 1 - include/protoserver/ProtoServer.h | 7 +++ libsrc/grabber/v4l2/V4L2Wrapper.cpp | 3 ++ libsrc/hyperion/CMakeLists.txt | 2 +- libsrc/hyperion/MessageForwarder.cpp | 4 -- libsrc/protoserver/ProtoServer.cpp | 6 +++ src/hyperiond/hyperiond.cpp | 78 ++++++++++++++++------------ 8 files changed, 62 insertions(+), 40 deletions(-) diff --git a/include/grabber/V4L2Wrapper.h b/include/grabber/V4L2Wrapper.h index 2a9ece2c..2b8dc74a 100644 --- a/include/grabber/V4L2Wrapper.h +++ b/include/grabber/V4L2Wrapper.h @@ -44,6 +44,7 @@ public slots: signals: void emitColors(int priority, const std::vector &ledColors, const int timeout_ms); + void emitImage(int priority, const Image & image, const int timeout_ms); private slots: void newFrame(const Image & image); diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index 9cc034fc..c9c27fe5 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -27,7 +27,6 @@ public: void addJsonSlave(std::string slave); void addProtoSlave(std::string slave); - void sendMessage(); QStringList getProtoSlaves(); QList getJsonSlaves(); diff --git a/include/protoserver/ProtoServer.h b/include/protoserver/ProtoServer.h index 1d530caa..520848a9 100644 --- a/include/protoserver/ProtoServer.h +++ b/include/protoserver/ProtoServer.h @@ -12,6 +12,10 @@ // Hyperion includes #include +// hyperion includes +#include +#include + // forward decl class ProtoClientConnection; class ProtoConnection; @@ -43,6 +47,9 @@ public: /// uint16_t getPort() const; +public slots: + void sendImageToProtoSlaves(int priority, const Image & image, int duration_ms); + private slots: /// /// Slot which is called when a client tries to create a new connection diff --git a/libsrc/grabber/v4l2/V4L2Wrapper.cpp b/libsrc/grabber/v4l2/V4L2Wrapper.cpp index 76b16ab7..cbccf41b 100644 --- a/libsrc/grabber/v4l2/V4L2Wrapper.cpp +++ b/libsrc/grabber/v4l2/V4L2Wrapper.cpp @@ -94,6 +94,9 @@ void V4L2Wrapper::newFrame(const Image &image) // process the new image _processor->process(image, _ledColors); + // forward to other hyperions + emit emitImage(_priority, image, _timeout_ms); + // send colors to Hyperion emit emitColors(_priority, _ledColors, _timeout_ms); } diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 3a277a7e..ebd25254 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -6,7 +6,6 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion) # Group the headers that go through the MOC compiler SET(Hyperion_QT_HEADERS ${CURRENT_HEADER_DIR}/Hyperion.h - ${CURRENT_HEADER_DIR}/MessageForwarder.h ${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h ) @@ -19,6 +18,7 @@ SET(Hyperion_HEADERS ${CURRENT_HEADER_DIR}/PriorityMuxer.h ${CURRENT_SOURCE_DIR}/MultiColorTransform.h + ${CURRENT_HEADER_DIR}/MessageForwarder.h ) SET(Hyperion_SOURCES diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 1ae4bef6..09bcf685 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -35,10 +35,6 @@ void MessageForwarder::addProtoSlave(std::string slave) _protoSlaves << QString(slave.c_str()); } -void MessageForwarder::sendMessage() -{ -} - QStringList MessageForwarder::getProtoSlaves() { return _protoSlaves; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index ca1b6358..03c334d4 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -70,6 +70,12 @@ void ProtoServer::newMessage(const proto::HyperionRequest * message) _proxy_connections.at(i)->sendMessage(*message); } +void ProtoServer::sendImageToProtoSlaves(int priority, const Image & image, int duration_ms) +{ + for (int i = 0; i < _proxy_connections.size(); ++i) + _proxy_connections.at(i)->setImage(image, priority, duration_ms); +} + void ProtoServer::closedConnection(ProtoClientConnection *connection) { std::cout << "Proto connection closed" << std::endl; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 7bb5e60e..fe24762a 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -189,6 +189,39 @@ int main(int argc, char** argv) std::cout << "XBMC video checker created and started" << std::endl; } +// ---- network services ----- + + // Create Json server if configuration is present + JsonServer * jsonServer = nullptr; + if (config.isMember("jsonServer")) + { + const Json::Value & jsonServerConfig = config["jsonServer"]; + jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); + std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl; + } + +#ifdef ENABLE_PROTOBUF + // Create Proto server if configuration is present + ProtoServer * protoServer = nullptr; + if (config.isMember("protoServer")) + { + const Json::Value & protoServerConfig = config["protoServer"]; + protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); + std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; + } +#endif + + // Create Boblight server if configuration is present + BoblightServer * boblightServer = nullptr; + if (config.isMember("boblightServer")) + { + const Json::Value & boblightServerConfig = config["boblightServer"]; + boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt()); + std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl; + } + +// ---- grabber ----- + #ifdef ENABLE_DISPMANX // Construct and start the frame-grabber if the configuration is present DispmanxWrapper * dispmanx = nullptr; @@ -214,7 +247,7 @@ int main(int argc, char** argv) #if !defined(ENABLE_OSX) && !defined(ENABLE_FB) if (config.isMember("framegrabber")) { - std::cerr << "The dispmanx framegrabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The dispmanx framegrabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif @@ -246,14 +279,19 @@ int main(int argc, char** argv) grabberConfig.get("cropTop", 0).asInt(), grabberConfig.get("cropBottom", 0).asInt()); + #ifdef ENABLE_PROTOBUF + QObject::connect(v4l2Grabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + v4l2Grabber->start(); std::cout << "V4l2 grabber created and started" << std::endl; } #else if (config.isMember("grabber-v4l2")) { - std::cerr << "The v4l2 grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The v4l2 grabber can not be instantiated, because it has been left out from the build" << std::endl; } + #endif #ifdef ENABLE_AMLOGIC @@ -309,12 +347,12 @@ int main(int argc, char** argv) #else if (config.isMember("framebuffergrabber")) { - std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; } #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) else if (config.isMember("framegrabber")) { - std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The framebuffer grabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif @@ -344,44 +382,16 @@ int main(int argc, char** argv) #else if (config.isMember("osxgrabber")) { - std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The osx grabber can not be instantiated, because it has been left out from the build" << std::endl; } #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_FB) else if (config.isMember("framegrabber")) { - std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl; + std::cerr << "The osx grabber can not be instantiated, because it has been left out from the build" << std::endl; } #endif #endif - // Create Json server if configuration is present - JsonServer * jsonServer = nullptr; - if (config.isMember("jsonServer")) - { - const Json::Value & jsonServerConfig = config["jsonServer"]; - jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt()); - std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl; - } - -#ifdef ENABLE_PROTOBUF - // Create Proto server if configuration is present - ProtoServer * protoServer = nullptr; - if (config.isMember("protoServer")) - { - const Json::Value & protoServerConfig = config["protoServer"]; - protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() ); - std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl; - } -#endif - - // Create Boblight server if configuration is present - BoblightServer * boblightServer = nullptr; - if (config.isMember("boblightServer")) - { - const Json::Value & boblightServerConfig = config["boblightServer"]; - boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt()); - std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl; - } // run the application int rc = app.exec(); From 46c5a2ec051b68ea7d1c774062e04bb5d71c8b63 Mon Sep 17 00:00:00 2001 From: redpanther Date: Tue, 16 Feb 2016 15:56:20 +0100 Subject: [PATCH 15/31] use correct include for std::runtime_error Former-commit-id: a96b727cc0258fda9684f5df52084dd8d96068e3 --- libsrc/hyperion/MessageForwarder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/hyperion/MessageForwarder.cpp b/libsrc/hyperion/MessageForwarder.cpp index 09bcf685..2e277fc8 100644 --- a/libsrc/hyperion/MessageForwarder.cpp +++ b/libsrc/hyperion/MessageForwarder.cpp @@ -1,5 +1,5 @@ // STL includes -#include +#include #include From a9e8f0264a0b6a1262b99e59dfb0b6d4cd854488 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 17 Feb 2016 00:44:06 +0100 Subject: [PATCH 16/31] implement proto forwarding for osxgrabber and framebuffer. prepare forwarding in amlogic and dispmanx Former-commit-id: d67fc2b7fe8877e6eadf31a8c76e4a68110c6680 --- include/grabber/DispmanxWrapper.h | 3 +++ include/grabber/FramebufferWrapper.h | 3 +++ include/grabber/OsxWrapper.h | 3 +++ libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 4 +++- libsrc/grabber/framebuffer/FramebufferWrapper.cpp | 3 ++- libsrc/grabber/osx/OsxWrapper.cpp | 3 ++- libsrc/leddevice/LedDeviceFadeCandy.cpp | 2 +- src/hyperiond/hyperiond.cpp | 12 ++++++++++++ 8 files changed, 29 insertions(+), 4 deletions(-) diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index 4868c1a0..2df81340 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/include/grabber/FramebufferWrapper.h b/include/grabber/FramebufferWrapper.h index f633ae55..75252d24 100644 --- a/include/grabber/FramebufferWrapper.h +++ b/include/grabber/FramebufferWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/include/grabber/OsxWrapper.h b/include/grabber/OsxWrapper.h index 39ac1a7e..fa597c67 100644 --- a/include/grabber/OsxWrapper.h +++ b/include/grabber/OsxWrapper.h @@ -69,6 +69,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index c9d2b22c..84657fc8 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -51,10 +51,12 @@ void DispmanxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + //emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } + void DispmanxWrapper::stop() { // Stop the timer, effectivly stopping the process diff --git a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp index abc6400c..96506d55 100644 --- a/libsrc/grabber/framebuffer/FramebufferWrapper.cpp +++ b/libsrc/grabber/framebuffer/FramebufferWrapper.cpp @@ -46,8 +46,9 @@ void FramebufferWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } void FramebufferWrapper::stop() diff --git a/libsrc/grabber/osx/OsxWrapper.cpp b/libsrc/grabber/osx/OsxWrapper.cpp index 6d6f9a00..da8b039e 100644 --- a/libsrc/grabber/osx/OsxWrapper.cpp +++ b/libsrc/grabber/osx/OsxWrapper.cpp @@ -46,8 +46,9 @@ void OsxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - _processor->process(_image, _ledColors); + emit emitImage(_priority, _image, _timeout_ms); + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } void OsxWrapper::stop() diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index 685795a9..2e6a1411 100755 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -1,6 +1,6 @@ #include "LedDeviceFadeCandy.h" -static const unsigned MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds +static const signed MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds static const unsigned OPC_SET_PIXELS = 0; // OPC command codes static const unsigned OPC_HEADER_SIZE = 4; // OPC header size diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index fe24762a..b300aefc 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -240,6 +240,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(dispmanx, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + dispmanx->start(); std::cout << "Frame grabber created and started" << std::endl; } @@ -341,6 +345,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), fbGrabber, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(fbGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + fbGrabber->start(); std::cout << "Framebuffer grabber created and started" << std::endl; } @@ -375,6 +383,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), osxGrabber, SLOT(setGrabbingMode(GrabbingMode))); QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), osxGrabber, SLOT(setVideoMode(VideoMode))); } + + #ifdef ENABLE_PROTOBUF + QObject::connect(osxGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif osxGrabber->start(); std::cout << "OSX grabber created and started" << std::endl; From 0f17e031e85dc7359ce1a0cbb842b07d2b2aa82a Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 18 Feb 2016 10:32:38 +0100 Subject: [PATCH 17/31] basic loop connection detection. prevent if you configure forward to 127.0.0.1: and your server has the same port. But this doesn't protect if not forwarded to localhost "127.0.0.1". Loop connections across different hosts arn't detected too. Former-commit-id: 464a80708ebd11c0f7c83dc87a1afe0f10e0e078 --- libsrc/jsonserver/JsonServer.cpp | 8 ++++++++ libsrc/protoserver/ProtoServer.cpp | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/libsrc/jsonserver/JsonServer.cpp b/libsrc/jsonserver/JsonServer.cpp index 4efe855c..4cd7f411 100644 --- a/libsrc/jsonserver/JsonServer.cpp +++ b/libsrc/jsonserver/JsonServer.cpp @@ -16,6 +16,14 @@ JsonServer::JsonServer(Hyperion *hyperion, uint16_t port) : throw std::runtime_error("Json server could not bind to port"); } + QList list = _hyperion->getForwarder()->getJsonSlaves(); + for ( int i=0; igetProtoSlaves(); for (int i = 0; i < slaves.size(); ++i) { + if ( QString("127.0.0.1:%1").arg(port) == slaves.at(i) ) { + throw std::runtime_error("Loop between proto server and forwarder detected. Fix your config!"); + } + ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData()); p->setSkipReply(true); _proxy_connections << p; From 736d841567f3e482f2d8f9d2e00c6908be8b05e8 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 18 Feb 2016 23:32:42 +0100 Subject: [PATCH 18/31] update rpi bins Former-commit-id: 851c37754b2e9a020d9a82c90438db96988f472d --- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id index 44bbdc58..94286a16 100644 --- a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -1 +1 @@ -5c164e4ff52076a530461cdf6966943d52cd39df \ No newline at end of file +d6c2a97271d37ffb04fa2e1e9ce7812d5b132811 \ No newline at end of file From ec67caf24ed3d7d9f457190f294a92e12865a024 Mon Sep 17 00:00:00 2001 From: redpanther Date: Fri, 19 Feb 2016 13:31:08 +0100 Subject: [PATCH 19/31] add ability to convert an image to RGB color order forwarder: add flag to detect if forwarding is enabled Former-commit-id: c814651ec4973fe3b2bfca7c0370a0bac752f025 --- include/hyperion/MessageForwarder.h | 3 ++- include/utils/Image.h | 21 ++++++++++++++++++ libsrc/hyperion/MessageForwarder.cpp | 5 +++++ test/TestRgbImage.cpp | 32 ++++++++++++++++++++++------ 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/include/hyperion/MessageForwarder.h b/include/hyperion/MessageForwarder.h index c9c27fe5..a762ae41 100644 --- a/include/hyperion/MessageForwarder.h +++ b/include/hyperion/MessageForwarder.h @@ -27,7 +27,8 @@ public: void addJsonSlave(std::string slave); void addProtoSlave(std::string slave); - + + bool protoForwardingEnabled(); QStringList getProtoSlaves(); QList getJsonSlaves(); diff --git a/include/utils/Image.h b/include/utils/Image.h index 0a8ca31a..ece6155a 100644 --- a/include/utils/Image.h +++ b/include/utils/Image.h @@ -5,6 +5,8 @@ #include #include #include +#include + template class Image @@ -183,6 +185,25 @@ public: { return _pixels; } + + + /// + /// Convert image of any color order to a RGB image. + /// + /// @param[out] image The image that buffers the output + /// + void toRgb(Image& image) + { + image.resize(_width, _height); + const unsigned imageSize = _width * _height; + + for (unsigned idx=0; idx MessageForwarder::getJsonSlaves() { return _jsonSlaves; } + +bool MessageForwarder::protoForwardingEnabled() +{ + return ! _protoSlaves.empty(); +} diff --git a/test/TestRgbImage.cpp b/test/TestRgbImage.cpp index 374408f5..67773763 100644 --- a/test/TestRgbImage.cpp +++ b/test/TestRgbImage.cpp @@ -4,22 +4,42 @@ // Utils includes #include +#include #include +#include +#include int main() { std::cout << "Constructing image" << std::endl; - Image image(64, 64, ColorRgb::BLACK); + int width = 64; + int height = 64; + Image image_rgb(width, height, ColorRgb::BLACK); + Image image_bgr(image_rgb.width(), image_rgb.height(), ColorBgr::BLACK); std::cout << "Writing image" << std::endl; - for (unsigned y=0; y<64; ++y) + unsigned l = width * height; + + // BGR + for (unsigned i=0; i Date: Wed, 24 Feb 2016 00:24:46 +0100 Subject: [PATCH 20/31] Update CMakeLists.txt If you want to compile for OpenElec on Raspberry Pi, you must use Python 2.7 Former-commit-id: 813a997161461b90626359e2e23149f8fab59fbf --- libsrc/effectengine/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsrc/effectengine/CMakeLists.txt b/libsrc/effectengine/CMakeLists.txt index 619b691d..adb430e0 100644 --- a/libsrc/effectengine/CMakeLists.txt +++ b/libsrc/effectengine/CMakeLists.txt @@ -1,5 +1,7 @@ find_package(PythonLibs REQUIRED) +#OpenElec uses 2.7, if you want to compile for OpenElec require 2.7 +#find_package(PythonLibs 2.7 REQUIRED) # Include the python directory. Also include the parent (which is for example /usr/include) # which may be required when it is not includes by the (cross-) compiler by default. From 6bef43887bca62253c99413ac94fa3f936d040fd Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 14:34:19 +0100 Subject: [PATCH 21/31] implement dispmanx forwarding a a separate dispmanx wrapper implement forwarding for amlogic grabber Former-commit-id: 8a793d24bd083f9eca07c34ec3b222f0e54b4426 --- include/grabber/AmlogicWrapper.h | 6 ++ .../grabber}/DispmanxFrameGrabber.h | 0 include/grabber/DispmanxWrapper.h | 3 + libsrc/grabber/amlogic/AmlogicWrapper.cpp | 9 +- libsrc/grabber/dispmanx/CMakeLists.txt | 81 ++++++++-------- .../grabber/dispmanx/DispmanxFrameGrabber.cpp | 2 +- libsrc/grabber/dispmanx/DispmanxWrapper.cpp | 10 +- src/CMakeLists.txt | 5 + src/hyperion-dispmanx/CMakeLists.txt | 70 ++++++++++++++ src/hyperion-dispmanx/DispmanxWrapper.cpp | 38 ++++++++ src/hyperion-dispmanx/DispmanxWrapper.h | 42 +++++++++ src/hyperion-dispmanx/hyperion-dispmanx.cpp | 92 +++++++++++++++++++ 12 files changed, 314 insertions(+), 44 deletions(-) rename {libsrc/grabber/dispmanx => include/grabber}/DispmanxFrameGrabber.h (100%) create mode 100644 src/hyperion-dispmanx/CMakeLists.txt create mode 100644 src/hyperion-dispmanx/DispmanxWrapper.cpp create mode 100644 src/hyperion-dispmanx/DispmanxWrapper.h create mode 100644 src/hyperion-dispmanx/hyperion-dispmanx.cpp diff --git a/include/grabber/AmlogicWrapper.h b/include/grabber/AmlogicWrapper.h index 0ce70b80..c712b60e 100644 --- a/include/grabber/AmlogicWrapper.h +++ b/include/grabber/AmlogicWrapper.h @@ -68,6 +68,9 @@ public slots: /// void setVideoMode(const VideoMode videoMode); +signals: + void emitImage(int priority, const Image & image, const int timeout_ms); + private: /// The update rate [Hz] const int _updateInterval_ms; @@ -91,4 +94,7 @@ private: /// Pointer to Hyperion for writing led values Hyperion * _hyperion; + + // forwarding enabled + bool _forward; }; diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.h b/include/grabber/DispmanxFrameGrabber.h similarity index 100% rename from libsrc/grabber/dispmanx/DispmanxFrameGrabber.h rename to include/grabber/DispmanxFrameGrabber.h diff --git a/include/grabber/DispmanxWrapper.h b/include/grabber/DispmanxWrapper.h index 2df81340..e64adf47 100644 --- a/include/grabber/DispmanxWrapper.h +++ b/include/grabber/DispmanxWrapper.h @@ -94,4 +94,7 @@ private: /// Pointer to Hyperion for writing led values Hyperion * _hyperion; + + // forwarding enabled + bool _forward; }; diff --git a/libsrc/grabber/amlogic/AmlogicWrapper.cpp b/libsrc/grabber/amlogic/AmlogicWrapper.cpp index 1dca6764..b77f1612 100644 --- a/libsrc/grabber/amlogic/AmlogicWrapper.cpp +++ b/libsrc/grabber/amlogic/AmlogicWrapper.cpp @@ -26,6 +26,7 @@ AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeig // Configure the timer to generate events every n milliseconds _timer.setInterval(_updateInterval_ms); _timer.setSingleShot(false); + _forward = _hyperion->getForwarder()->protoForwardingEnabled(); _processor->setSize(grabWidth, grabHeight); @@ -55,8 +56,14 @@ void AmlogicWrapper::action() return; } - _processor->process(_image, _ledColors); + if ( _forward ) + { + Image image_rgb; + _image.toRgb(image_rgb); + emit emitImage(_priority, image_rgb, _timeout_ms); + } + _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); } diff --git a/libsrc/grabber/dispmanx/CMakeLists.txt b/libsrc/grabber/dispmanx/CMakeLists.txt index d4d64b72..27c1f11c 100644 --- a/libsrc/grabber/dispmanx/CMakeLists.txt +++ b/libsrc/grabber/dispmanx/CMakeLists.txt @@ -1,40 +1,41 @@ - -# Find the BCM-package (VC control) -find_package(BCM REQUIRED) -include_directories(${BCM_INCLUDE_DIRS}) - -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) - -# Group the headers that go through the MOC compiler -SET(DispmanxGrabberQT_HEADERS - ${CURRENT_HEADER_DIR}/DispmanxWrapper.h -) - -SET(DispmanxGrabberHEADERS - ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.h -) - -SET(DispmanxGrabberSOURCES - ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp - ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp -) - -if(ENABLE_QT5) -QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) -else(ENABLE_QT5) -QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) -endif(ENABLE_QT5) - -add_library(dispmanx-grabber - ${DispmanxGrabberHEADERS} - ${DispmanxGrabberQT_HEADERS} - ${DispmanxGrabberHEADERS_MOC} - ${DispmanxGrabberSOURCES} -) - -target_link_libraries(dispmanx-grabber - hyperion - ${QT_LIBRARIES} - ${BCM_LIBRARIES}) + +# Find the BCM-package (VC control) +find_package(BCM REQUIRED) +include_directories(${BCM_INCLUDE_DIRS}) + +# Define the current source locations +SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) +SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/dispmanx) + +# Group the headers that go through the MOC compiler +SET(DispmanxGrabberQT_HEADERS + ${CURRENT_HEADER_DIR}/DispmanxWrapper.h +) + +SET(DispmanxGrabberHEADERS + ${CURRENT_HEADER_DIR}/DispmanxFrameGrabber.h +) + +SET(DispmanxGrabberSOURCES + ${CURRENT_SOURCE_DIR}/DispmanxWrapper.cpp + ${CURRENT_SOURCE_DIR}/DispmanxFrameGrabber.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +else(ENABLE_QT5) + QT4_WRAP_CPP(DispmanxGrabberHEADERS_MOC ${DispmanxGrabberQT_HEADERS}) +endif(ENABLE_QT5) + +add_library(dispmanx-grabber + ${DispmanxGrabberHEADERS} + ${DispmanxGrabberQT_HEADERS} + ${DispmanxGrabberHEADERS_MOC} + ${DispmanxGrabberSOURCES} +) + +target_link_libraries(dispmanx-grabber + hyperion + ${QT_LIBRARIES} + ${BCM_LIBRARIES} +) diff --git a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp index 1f6516a4..53397acf 100644 --- a/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp +++ b/libsrc/grabber/dispmanx/DispmanxFrameGrabber.cpp @@ -4,7 +4,7 @@ #include // Local includes -#include "DispmanxFrameGrabber.h" +#include "grabber/DispmanxFrameGrabber.h" DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height) : _vc_display(0), diff --git a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp index 84657fc8..7868ce34 100644 --- a/libsrc/grabber/dispmanx/DispmanxWrapper.cpp +++ b/libsrc/grabber/dispmanx/DispmanxWrapper.cpp @@ -9,7 +9,7 @@ // Dispmanx grabber includes #include -#include "DispmanxFrameGrabber.h" +#include DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) : @@ -28,6 +28,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe _timer.setSingleShot(false); _processor->setSize(grabWidth, grabHeight); + _forward = _hyperion->getForwarder()->protoForwardingEnabled(); // Connect the QTimer to this QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(action())); @@ -51,7 +52,12 @@ void DispmanxWrapper::action() // Grab frame into the allocated image _frameGrabber->grabFrame(_image); - //emit emitImage(_priority, _image, _timeout_ms); + if ( _forward ) + { + Image image_rgb; + _image.toRgb(image_rgb); + emit emitImage(_priority, image_rgb, _timeout_ms); + } _processor->process(_image, _ledColors); _hyperion->setColors(_priority, _ledColors, _timeout_ms); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a291850..f55af750 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,4 +15,9 @@ if(ENABLE_PROTOBUF) if(ENABLE_X11) add_subdirectory(hyperion-x11) endif() + + if(ENABLE_DISPMANX) + add_subdirectory(hyperion-dispmanx) + endif() + endif() diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt new file mode 100644 index 00000000..4d48174e --- /dev/null +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -0,0 +1,70 @@ +# Configure minimum CMAKE version +cmake_minimum_required(VERSION 2.8) + +# Set the project name +project(hyperion-dispmanx) + +if(ENABLE_QT5) + find_package(Qt5Widgets REQUIRED) +else(ENABLE_QT5) + # find Qt4 + find_package(Qt4 REQUIRED QtCore QtGui QtNetwork ) +endif(ENABLE_QT5) + +# Find the BCM-package (VC control) +#find_package(BCM REQUIRED) +SET( BCM_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/dependencies/external/rapsi_vc ) +SET( BCM_LIBRARIES "" ) +ADD_DEFINITIONS ( -DDISPMANX_DUMMY ) + + + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver + ${QT_INCLUDES} + ${BCM_INCLUDE_DIRS} + ${PROTOBUF_INCLUDE_DIRS} +) + +set(Hyperion_Dispmanx_QT_HEADERS + DispmanxWrapper.h) + +set(Hyperion_Dispmanx_HEADERS +) + +set(Hyperion_Dispmanx_SOURCES + hyperion-dispmanx.cpp + DispmanxWrapper.cpp +) + +if(ENABLE_QT5) + QT5_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS}) +else(ENABLE_QT5) + QT4_WRAP_CPP(Hyperion_Dispmanx_HEADERS_MOC ${Hyperion_Dispmanx_QT_HEADERS}) +endif(ENABLE_QT5) + +add_executable( ${PROJECT_NAME} + ${Hyperion_Dispmanx_HEADERS} + ${Hyperion_Dispmanx_SOURCES} + ${Hyperion_Dispmanx_HEADERS_MOC} +) + +target_link_libraries( ${PROJECT_NAME} + getoptPlusPlus + blackborder + hyperion-utils + protoserver + dispmanx-grabber + ${Dispmanx_LIBRARIES} + pthread +) + +if(ENABLE_QT5) + qt5_use_modules(hyperion-dispmanx Widgets Core Gui Network) +else(ENABLE_QT5) + qt4_use_modules(hyperion-dispmanx + Core + Gui + Network + ) +endif(ENABLE_QT5) diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp new file mode 100644 index 00000000..b11830a7 --- /dev/null +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -0,0 +1,38 @@ + +// Hyperion-X11 includes +#include "DispmanxWrapper.h" + +DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : + _timer(this), + _grabber(grabWidth, grabHeight) +{ + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); + + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); +} + +const Image & DispmanxWrapper::getScreenshot() +{ + capture(); + return _screenshot_rgb; +} + +void DispmanxWrapper::start() +{ + _timer.start(); +} + +void DispmanxWrapper::stop() +{ + _timer.stop(); +} + +void DispmanxWrapper::capture() +{ + _grabber.grabFrame(_screenshot); + _screenshot.toRgb(_screenshot_rgb); + + emit sig_screenshot(_screenshot_rgb); +} diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h new file mode 100644 index 00000000..827a4d53 --- /dev/null +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -0,0 +1,42 @@ + +// QT includes +#include + +// Hyperion-Dispmanx includes +#include + +class DispmanxWrapper : public QObject +{ + Q_OBJECT +public: + DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + + const Image & getScreenshot(); + + /// + /// Starts the timed capturing of screenshots + /// + void start(); + + void stop(); + +signals: + void sig_screenshot(const Image & screenshot); + +private slots: + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot + /// signal. + /// + void capture(); + +private: + /// The QT timer to generate capture-publish events + QTimer _timer; + + /// The grabber for creating screenshots + DispmanxFrameGrabber _grabber; + Image _screenshot_rgb; + Image _screenshot; + +}; diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp new file mode 100644 index 00000000..c7d5fe0e --- /dev/null +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -0,0 +1,92 @@ + +// QT includes +#include +#include + +// getoptPlusPLus includes +#include + +#include "protoserver/ProtoConnectionWrapper.h" +#include "DispmanxWrapper.h" + +using namespace vlofgren; + +// save the image as screenshot +void saveScreenshot(const char * filename, const Image & image) +{ + // store as PNG + QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); + pngImage.save(filename); +} + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + try + { + // create the option parser and initialize all parameters + OptionsParser optionParser("Dispmanx capture application for Hyperion"); + ParameterSet & parameters = optionParser.getParameters(); + + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); + IntParameter & argWidth = parameters.add (0x0, "width", "The width of the grabbed frames [pixels]"); + IntParameter & argHeight = parameters.add (0x0, "height", "The height of the grabbed frames"); + + SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); + StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); + IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); + + // set defaults + argFps.setDefault(10); + argWidth.setDefault(64); + argHeight.setDefault(64); + argAddress.setDefault("127.0.0.1:19445"); + argPriority.setDefault(800); + + // parse all options + optionParser.parse(argc, const_cast(argv)); + + // check if we need to display the usage. exit if we do. + if (argHelp.isSet()) + { + optionParser.usage(); + return 0; + } + + // Create the dispmanx grabbing stuff + int grabInterval = 1000 / argFps.getValue(); + DispmanxWrapper dispmanxWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval); + + if (argScreenshot.isSet()) + { + // Capture a single screenshot and finish + const Image & screenshot = dispmanxWrapper.getScreenshot(); + saveScreenshot("screenshot.png", screenshot); + } + else + { + // Create the Proto-connection with hyperiond + ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + + // Connect the screen capturing to the proto processing + QObject::connect(&dispmanxWrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + + // Start the capturing + dispmanxWrapper.start(); + + // Start the application + app.exec(); + } + } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return -1; + } + + return 0; +} From 8fdf97e6934138b91e7e2950f1f2fb2c53a13842 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 14:42:25 +0100 Subject: [PATCH 22/31] prepare standalone amlogic grabber activate internal amlogic grabber forwarding Former-commit-id: 21dabf759935836eef556baeb8a27e362e95ae96 --- {libsrc/grabber/amlogic => include/grabber}/AmlogicGrabber.h | 0 libsrc/grabber/amlogic/AmlogicGrabber.cpp | 2 +- libsrc/grabber/amlogic/AmlogicWrapper.cpp | 2 +- libsrc/grabber/amlogic/CMakeLists.txt | 2 +- src/hyperion-aml/hyperion-aml.cpp | 2 +- src/hyperiond/hyperiond.cpp | 4 ++++ 6 files changed, 8 insertions(+), 4 deletions(-) rename {libsrc/grabber/amlogic => include/grabber}/AmlogicGrabber.h (100%) diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.h b/include/grabber/AmlogicGrabber.h similarity index 100% rename from libsrc/grabber/amlogic/AmlogicGrabber.h rename to include/grabber/AmlogicGrabber.h diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.cpp b/libsrc/grabber/amlogic/AmlogicGrabber.cpp index 8eaa9799..25153142 100644 --- a/libsrc/grabber/amlogic/AmlogicGrabber.cpp +++ b/libsrc/grabber/amlogic/AmlogicGrabber.cpp @@ -13,7 +13,7 @@ #include // Local includes -#include "AmlogicGrabber.h" +#include // Flags copied from 'include/linux/amlogic/amports/amvideocap.h' at https://github.com/codesnake/linux-amlogic #define AMVIDEOCAP_IOC_MAGIC 'V' diff --git a/libsrc/grabber/amlogic/AmlogicWrapper.cpp b/libsrc/grabber/amlogic/AmlogicWrapper.cpp index b77f1612..29022afe 100644 --- a/libsrc/grabber/amlogic/AmlogicWrapper.cpp +++ b/libsrc/grabber/amlogic/AmlogicWrapper.cpp @@ -9,7 +9,7 @@ // Amlogic grabber includes #include -#include "AmlogicGrabber.h" +#include AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, Hyperion * hyperion) : diff --git a/libsrc/grabber/amlogic/CMakeLists.txt b/libsrc/grabber/amlogic/CMakeLists.txt index be6cb97d..9ec98bfe 100644 --- a/libsrc/grabber/amlogic/CMakeLists.txt +++ b/libsrc/grabber/amlogic/CMakeLists.txt @@ -7,7 +7,7 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/amlogic) SET(AmlogicQT_HEADERS ${CURRENT_HEADER_DIR}/AmlogicWrapper.h) SET(AmlogicHEADERS - ${CURRENT_SOURCE_DIR}/AmlogicGrabber.h + ${CURRENT_HEADER_DIR}/AmlogicGrabber.h ) SET(AmlogicSOURCES diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index 13da6686..71bcd495 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -7,7 +7,7 @@ // getoptPlusPLus includes #include -#include "../../libsrc/grabber/amlogic/AmlogicGrabber.h" +#include using namespace vlofgren; diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index b300aefc..8af26879 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -316,6 +316,10 @@ int main(int argc, char** argv) QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), amlGrabber, SLOT(setVideoMode(VideoMode))); } + #ifdef ENABLE_PROTOBUF + QObject::connect(amlGrabber, SIGNAL(emitImage(int, const Image&, const int)), protoServer, SLOT(sendImageToProtoSlaves(int, const Image&, const int)) ); + #endif + amlGrabber->start(); std::cout << "AMLOGIC grabber created and started" << std::endl; } From 1b6b90df51b5c13ebefc1fe9315ba1596156c63c Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 15:09:07 +0100 Subject: [PATCH 23/31] bring back hyperion.tar.gz Former-commit-id: 2e507be1aca9e58076cafc38ca10e09a65cd3998 --- deploy/hyperion_rpi.tar.gz.REMOVED.git-id | 1 + 1 file changed, 1 insertion(+) create mode 100644 deploy/hyperion_rpi.tar.gz.REMOVED.git-id diff --git a/deploy/hyperion_rpi.tar.gz.REMOVED.git-id b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id new file mode 100644 index 00000000..f3692ead --- /dev/null +++ b/deploy/hyperion_rpi.tar.gz.REMOVED.git-id @@ -0,0 +1 @@ +5b0f057a8591d76be009018b302977faeec5159a \ No newline at end of file From 2c831c111021dde35f2ff0c3f94b38296f3fbb68 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 16:03:21 +0100 Subject: [PATCH 24/31] add standalone amlogic grabber fix standalone dispmanx grabber Former-commit-id: 5ace9bc90a6fe76f5a51ecef95d6e7119d1102db --- src/hyperion-aml/AmlogicWrapper.cpp | 38 ++++++++++++++++++ src/hyperion-aml/AmlogicWrapper.h | 43 +++++++++++++++++++++ src/hyperion-aml/CMakeLists.txt | 6 ++- src/hyperion-aml/hyperion-aml.cpp | 38 +++++++++++------- src/hyperion-dispmanx/CMakeLists.txt | 7 +--- src/hyperion-dispmanx/DispmanxWrapper.cpp | 2 +- src/hyperion-dispmanx/DispmanxWrapper.h | 40 +++++++++---------- src/hyperion-dispmanx/hyperion-dispmanx.cpp | 16 ++++---- 8 files changed, 138 insertions(+), 52 deletions(-) create mode 100644 src/hyperion-aml/AmlogicWrapper.cpp create mode 100644 src/hyperion-aml/AmlogicWrapper.h diff --git a/src/hyperion-aml/AmlogicWrapper.cpp b/src/hyperion-aml/AmlogicWrapper.cpp new file mode 100644 index 00000000..e4c1f7f1 --- /dev/null +++ b/src/hyperion-aml/AmlogicWrapper.cpp @@ -0,0 +1,38 @@ + +// Hyperion-AmLogic includes +#include "AmlogicWrapper.h" + +AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : + _timer(this), + _grabber(grabWidth, grabHeight) +{ + _timer.setSingleShot(false); + _timer.setInterval(updateRate_Hz); + + // Connect capturing to the timeout signal of the timer + connect(&_timer, SIGNAL(timeout()), this, SLOT(capture())); +} + +const Image & AmlogicWrapper::getScreenshot() +{ + capture(); + return _screenshot_rgb; +} + +void AmlogicWrapper::start() +{ + _timer.start(); +} + +void AmlogicWrapper::stop() +{ + _timer.stop(); +} + +void AmlogicWrapper::capture() +{ + _grabber.grabFrame(_screenshot); + _screenshot.toRgb(_screenshot_rgb); + + emit sig_screenshot(_screenshot_rgb); +} diff --git a/src/hyperion-aml/AmlogicWrapper.h b/src/hyperion-aml/AmlogicWrapper.h new file mode 100644 index 00000000..3f5b0bc8 --- /dev/null +++ b/src/hyperion-aml/AmlogicWrapper.h @@ -0,0 +1,43 @@ + +// QT includes +#include + +// Hyperion-Dispmanx includes +#include + +class AmlogicWrapper : public QObject +{ + Q_OBJECT +public: + AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + + const Image & getScreenshot(); + + /// + /// Starts the timed capturing of screenshots + /// + void start(); + + void stop(); + +signals: + void sig_screenshot(const Image & screenshot); + +private slots: + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot signal. + /// + void capture(); + +private: + /// The QT timer to generate capture-publish events + QTimer _timer; + + /// The grabber for creating screenshots + AmlogicGrabber _grabber; + + // image buffers + Image _screenshot_rgb; + Image _screenshot; + +}; diff --git a/src/hyperion-aml/CMakeLists.txt b/src/hyperion-aml/CMakeLists.txt index 5d45222a..cd27c046 100644 --- a/src/hyperion-aml/CMakeLists.txt +++ b/src/hyperion-aml/CMakeLists.txt @@ -14,6 +14,7 @@ include_directories( ) set(Hyperion_AML_QT_HEADERS + AmlogicWrapper.h ) set(Hyperion_AML_HEADERS @@ -21,12 +22,13 @@ set(Hyperion_AML_HEADERS set(Hyperion_AML_SOURCES hyperion-aml.cpp + AmlogicWrapper.cpp ) if(ENABLE_QT5) -QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) + QT5_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) else(ENABLE_QT5) -QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) + QT4_WRAP_CPP(Hyperion_AML_HEADERS_MOC ${Hyperion_AML_QT_HEADERS}) endif(ENABLE_QT5) add_executable(hyperion-amlogic diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index 71bcd495..cca5e688 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -7,16 +7,16 @@ // getoptPlusPLus includes #include -#include +#include +#include "AmlogicWrapper.h" using namespace vlofgren; // save the image as screenshot -void saveScreenshot(const char * filename, const Image & image) +void saveScreenshot(const char * filename, const Image & image) { // store as PNG QImage pngImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888); - pngImage = pngImage.rgbSwapped(); pngImage.save(filename); } @@ -30,16 +30,17 @@ int main(int argc, char ** argv) OptionsParser optionParser("X11 capture application for Hyperion"); ParameterSet & parameters = optionParser.getParameters(); - //IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); + IntParameter & argFps = parameters.add ('f', "framerate", "Capture frame rate [default=10]"); IntParameter & argWidth = parameters.add (0x0, "width", "Width of the captured image [default=128]"); IntParameter & argHeight = parameters.add (0x0, "height", "Height of the captured image [default=128]"); SwitchParameter<> & argScreenshot = parameters.add> (0x0, "screenshot", "Take a single screenshot, save it to file and quit"); StringParameter & argAddress = parameters.add ('a', "address", "Set the address of the hyperion server [default: 127.0.0.1:19445]"); IntParameter & argPriority = parameters.add ('p', "priority", "Use the provided priority channel (the lower the number, the higher the priority) [default: 800]"); - //SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); + SwitchParameter<> & argSkipReply = parameters.add> (0x0, "skip-reply", "Do not receive and check reply messages from Hyperion"); SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); // set defaults + argFps.setDefault(10); argWidth.setDefault(160); argHeight.setDefault(160); argAddress.setDefault("127.0.0.1:19445"); @@ -57,29 +58,36 @@ int main(int argc, char ** argv) int width = argWidth.getValue(); int height = argHeight.getValue(); - if (width < 160 || height < 60) + if (width < 160 || height < 160) { std::cout << "Minimum width and height is 160" << std::endl; width = std::max(160, width); height = std::max(160, height); } + + int grabInterval = 1000 / argFps.getValue(); + AmlogicWrapper amlWrapper(argWidth.getValue(),argHeight.getValue(),grabInterval); + if (argScreenshot.isSet()) { - - // Create the grabber - AmlogicGrabber amlGrabber(width, height); - // Capture a single screenshot and finish - Image screenshot; - amlGrabber.grabFrame(screenshot); + const Image & screenshot = amlWrapper.getScreenshot(); saveScreenshot("screenshot.png", screenshot); } else { - // TODO[TvdZ]: Implement the proto-client mechanisme - std::cerr << "The PROTO-interface has not been implemented yet" << std::endl; - } + // Create the Proto-connection with hyperiond + ProtoConnectionWrapper protoWrapper(argAddress.getValue(), argPriority.getValue(), 1000, argSkipReply.isSet()); + // Connect the screen capturing to the proto processing + QObject::connect(&amlWrapper, SIGNAL(sig_screenshot(const Image &)), &protoWrapper, SLOT(receiveImage(Image))); + + // Start the capturing + amlWrapper.start(); + + // Start the application + app.exec(); + } } catch (const std::runtime_error & e) { diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt index 4d48174e..130cb661 100644 --- a/src/hyperion-dispmanx/CMakeLists.txt +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -12,12 +12,7 @@ else(ENABLE_QT5) endif(ENABLE_QT5) # Find the BCM-package (VC control) -#find_package(BCM REQUIRED) -SET( BCM_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/dependencies/external/rapsi_vc ) -SET( BCM_LIBRARIES "" ) -ADD_DEFINITIONS ( -DDISPMANX_DUMMY ) - - +find_package(BCM REQUIRED) include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../../libsrc/protoserver diff --git a/src/hyperion-dispmanx/DispmanxWrapper.cpp b/src/hyperion-dispmanx/DispmanxWrapper.cpp index b11830a7..7d8702d2 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.cpp +++ b/src/hyperion-dispmanx/DispmanxWrapper.cpp @@ -1,5 +1,5 @@ -// Hyperion-X11 includes +// Hyperion-Dispmanx includes #include "DispmanxWrapper.h" DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz) : diff --git a/src/hyperion-dispmanx/DispmanxWrapper.h b/src/hyperion-dispmanx/DispmanxWrapper.h index 827a4d53..e8526b02 100644 --- a/src/hyperion-dispmanx/DispmanxWrapper.h +++ b/src/hyperion-dispmanx/DispmanxWrapper.h @@ -7,36 +7,36 @@ class DispmanxWrapper : public QObject { - Q_OBJECT + Q_OBJECT public: - DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); + DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz); - const Image & getScreenshot(); + const Image & getScreenshot(); - /// - /// Starts the timed capturing of screenshots - /// - void start(); + /// + /// Starts the timed capturing of screenshots + /// + void start(); - void stop(); + void stop(); signals: - void sig_screenshot(const Image & screenshot); + void sig_screenshot(const Image & screenshot); private slots: - /// - /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot - /// signal. - /// - void capture(); + /// + /// Performs a single screenshot capture and publishes the capture screenshot on the screenshot + /// signal. + /// + void capture(); private: - /// The QT timer to generate capture-publish events - QTimer _timer; + /// The QT timer to generate capture-publish events + QTimer _timer; - /// The grabber for creating screenshots - DispmanxFrameGrabber _grabber; - Image _screenshot_rgb; - Image _screenshot; + /// The grabber for creating screenshots + DispmanxFrameGrabber _grabber; + Image _screenshot_rgb; + Image _screenshot; }; diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp index c7d5fe0e..abf78c8c 100644 --- a/src/hyperion-dispmanx/hyperion-dispmanx.cpp +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -6,7 +6,7 @@ // getoptPlusPLus includes #include -#include "protoserver/ProtoConnectionWrapper.h" +#include #include "DispmanxWrapper.h" using namespace vlofgren; @@ -81,12 +81,12 @@ int main(int argc, char ** argv) app.exec(); } } - catch (const std::runtime_error & e) - { - // An error occured. Display error and quit - std::cerr << e.what() << std::endl; - return -1; - } + catch (const std::runtime_error & e) + { + // An error occured. Display error and quit + std::cerr << e.what() << std::endl; + return -1; + } - return 0; + return 0; } From 11af47d799a80bb31070f021c47b1d76b207c0c9 Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 23:30:50 +0100 Subject: [PATCH 25/31] make it compile on raspi Former-commit-id: 378b2ed1f605d060feb955819fb632424f21a218 --- test/dispmanx2png/dispmanx2png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dispmanx2png/dispmanx2png.cpp b/test/dispmanx2png/dispmanx2png.cpp index 1004b8ed..77dcb6b7 100644 --- a/test/dispmanx2png/dispmanx2png.cpp +++ b/test/dispmanx2png/dispmanx2png.cpp @@ -10,7 +10,7 @@ #include // Dispmanx grabber includes -#include +#include using namespace vlofgren; From 878538eb50f573658a21bad99a80db8e4e10662e Mon Sep 17 00:00:00 2001 From: redpanther Date: Wed, 24 Feb 2016 23:34:47 +0100 Subject: [PATCH 26/31] fix compile on raspi Former-commit-id: f526a9facebe8027f6bf50b1e54ab21bc1534faa --- test/dispmanx2png/dispmanx2png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dispmanx2png/dispmanx2png.cpp b/test/dispmanx2png/dispmanx2png.cpp index 1004b8ed..77dcb6b7 100644 --- a/test/dispmanx2png/dispmanx2png.cpp +++ b/test/dispmanx2png/dispmanx2png.cpp @@ -10,7 +10,7 @@ #include // Dispmanx grabber includes -#include +#include using namespace vlofgren; From ea89a85ddb87361ccd19ed520861f07f53713dc1 Mon Sep 17 00:00:00 2001 From: redpanther Date: Thu, 25 Feb 2016 15:21:25 +0100 Subject: [PATCH 27/31] make protoconnection to invalid host less blocking Former-commit-id: e7a89c87b15fbe9809ec63468b59ecc55c6d3e72 --- include/protoserver/ProtoConnection.h | 14 +++++++-- libsrc/protoserver/ProtoConnection.cpp | 40 +++++++++++++++++++++----- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/include/protoserver/ProtoConnection.h b/include/protoserver/ProtoConnection.h index a61947fe..7ecd8f36 100644 --- a/include/protoserver/ProtoConnection.h +++ b/include/protoserver/ProtoConnection.h @@ -7,6 +7,7 @@ #include #include #include +#include #include // hyperion util @@ -19,8 +20,11 @@ /// /// Connection class to setup an connection to the hyperion server and execute commands /// -class ProtoConnection +class ProtoConnection : public QObject { + +Q_OBJECT + public: /// /// Constructor @@ -74,10 +78,13 @@ public: /// void sendMessage(const proto::HyperionRequest & message); -private: +private slots: /// Try to connect to the Hyperion host void connectToHost(); + +private: + /// /// Parse a reply message /// @@ -99,4 +106,7 @@ private: /// Skip receiving reply messages from Hyperion if set bool _skipReply; + + QTimer _timer; + QAbstractSocket::SocketState _prevSocketState; }; diff --git a/libsrc/protoserver/ProtoConnection.cpp b/libsrc/protoserver/ProtoConnection.cpp index d7a6037e..5eb5e53c 100644 --- a/libsrc/protoserver/ProtoConnection.cpp +++ b/libsrc/protoserver/ProtoConnection.cpp @@ -9,7 +9,8 @@ ProtoConnection::ProtoConnection(const std::string & a) : _socket(), - _skipReply(false) + _skipReply(false), + _prevSocketState(QAbstractSocket::UnconnectedState) { QString address(a.c_str()); QStringList parts = address.split(":"); @@ -29,10 +30,18 @@ ProtoConnection::ProtoConnection(const std::string & a) : // try to connect to host std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; connectToHost(); + + // start the connection timer + _timer.setInterval(5000); + _timer.setSingleShot(false); + + connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) ); + _timer.start(); } ProtoConnection::~ProtoConnection() { + _timer.stop(); _socket.close(); } @@ -91,20 +100,37 @@ void ProtoConnection::clearAll() void ProtoConnection::connectToHost() { - _socket.connectToHost(_host, _port); - if (_socket.waitForConnected()) { - std::cout << "Connected to Hyperion host" << std::endl; + // try connection only when + if (_socket.state() == QAbstractSocket::UnconnectedState) + { + _socket.connectToHost(_host, _port); + //_socket.waitForConnected(1000); } } void ProtoConnection::sendMessage(const proto::HyperionRequest &message) { - if (_socket.state() == QAbstractSocket::UnconnectedState) + // print out connection message only when state is changed + if (_socket.state() != _prevSocketState ) { - std::cout << "Currently disconnected: trying to connect to host" << std::endl; - connectToHost(); + switch (_socket.state() ) + { + case QAbstractSocket::UnconnectedState: + std::cout << "No connection to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + + case QAbstractSocket::ConnectedState: + std::cout << "Connected to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + + default: + //std::cout << "Connecting to Hyperion: " << _host.toStdString() << ":" << _port << std::endl; + break; + } + _prevSocketState = _socket.state(); } + if (_socket.state() != QAbstractSocket::ConnectedState) { return; From f0c1e63fba17cfe99211202972cdb15ca0aed48d Mon Sep 17 00:00:00 2001 From: redpanther Date: Sat, 27 Feb 2016 18:06:04 +0100 Subject: [PATCH 28/31] update compile howto for making release binaries Former-commit-id: 5105b3f374221e573290c98990c55f0bd67ba849 --- CompileHowto.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CompileHowto.txt b/CompileHowto.txt index 621cf8fd..9f419709 100644 --- a/CompileHowto.txt +++ b/CompileHowto.txt @@ -24,11 +24,11 @@ mkdir "$HYPERION_DIR/build" cd "$HYPERION_DIR/build" # run cmake to generate make files on the raspberry pi -cmake .. +cmake -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # or if you are not compiling on the raspberry pi and need to disable the Dispmanx grabber and support for spi devices -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON .. +cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # as an alternative for the dispmanx grabber on non-rpi devices (e.g. cubox-i) you could try the framebuffer grabber -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON .. +cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. # for OSX build you need XCode, qt4 libraries and cmake. You can use macport (homebrew might work too) to install them sudo port install qt4-mac sudo port install cmake @@ -36,6 +36,12 @@ cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_V4L2=OFF -DENABLE_OSX=O # run make to build Hyperion make +# or if you have a system with more then 1 cpu core +make -j 4 +# "4" is the number of cpu cores (e.g. 4 on RPi2), this makes compile faster + +#after compile, to remove any stuff not needed for a release version. +strip bin/* # The binaries are build in "$HYPERION_DIR/build/bin". You could copy those to /usr/bin sudo cp ./bin/hyperion-remote /usr/bin/ From b63cdc1bcfc9d719061b104455fa8d377f90d919 Mon Sep 17 00:00:00 2001 From: redpanther Date: Mon, 29 Feb 2016 04:29:55 +0100 Subject: [PATCH 29/31] Revert "make it compile on raspi" This reverts commit 11af47d799a80bb31070f021c47b1d76b207c0c9 [formerly 378b2ed1f605d060feb955819fb632424f21a218]. Former-commit-id: 5343c8139825860e74243ecbbb67d9aae6697d63 --- test/dispmanx2png/dispmanx2png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dispmanx2png/dispmanx2png.cpp b/test/dispmanx2png/dispmanx2png.cpp index 77dcb6b7..1004b8ed 100644 --- a/test/dispmanx2png/dispmanx2png.cpp +++ b/test/dispmanx2png/dispmanx2png.cpp @@ -10,7 +10,7 @@ #include // Dispmanx grabber includes -#include +#include using namespace vlofgren; From 42e488c193be9394c0304eca2b85888438c7342c Mon Sep 17 00:00:00 2001 From: Serhan Date: Mon, 7 Mar 2016 12:10:30 +0100 Subject: [PATCH 30/31] Removed debug-build option Removed debug-build option Former-commit-id: ce88ca30ecf296617d6fe2d2b0e9d7f050d7d68a --- CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81479cb3..9c8e077a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,9 +91,6 @@ include_directories(${CMAKE_SOURCE_DIR}/include) # Prefer static linking over dynamic #set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so") -set(CMAKE_BUILD_TYPE "Debug") -#set(CMAKE_BUILD_TYPE "Release") - # enable C++11 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++11 -Wall") From 02d055b75c54ca1777e4000deced9fd9d3eda7ab Mon Sep 17 00:00:00 2001 From: brindosch Date: Tue, 8 Mar 2016 18:20:09 +0100 Subject: [PATCH 31/31] Add the service files and new hyperion conf Former-commit-id: 2083ce117791e6ad22037f91618af917fe99d40b --- bin/create_release.sh | 4 + bin/hyperion.init.sh | 11 +- bin/hyperion.initctl.sh | 17 ++ bin/hyperion.systemd.sh | 15 ++ bin/remove_hyperion.sh | 105 ++++++++++ config/hyperion.config.json | 372 ++++++++++++++++++------------------ 6 files changed, 341 insertions(+), 183 deletions(-) create mode 100644 bin/hyperion.initctl.sh create mode 100644 bin/hyperion.systemd.sh create mode 100644 bin/remove_hyperion.sh diff --git a/bin/create_release.sh b/bin/create_release.sh index d6b9bf66..c44fb5c5 100644 --- a/bin/create_release.sh +++ b/bin/create_release.sh @@ -24,6 +24,8 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names --ignore --transform "s:$repodir/effects/:hyperion/effects/:" \ --transform "s:$repodir/config/:hyperion/config/:" \ --transform "s:$repodir/bin/hyperion.init.sh:hyperion/init.d/hyperion.init.sh:" \ + --transform "s:$repodir/bin/hyperion.systemd.sh:hyperion/init.d/hyperion.systemd.sh:" \ + --transform "s:$repodir/bin/hyperion.initctl.sh:hyperion/init.d/hyperion.initctl.sh:" \ --transform "s://:/:g" \ "$builddir/bin/hyperiond" \ "$builddir/bin/hyperion-remote" \ @@ -32,5 +34,7 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names --ignore "$builddir/bin/dispmanx2png" \ "$repodir/effects/"* \ "$repodir/bin/hyperion.init.sh" \ + "$repodir/bin/hyperion.systemd.sh" \ + "$repodir/bin/hyperion.initctl.sh" \ "$repodir/config/hyperion.config.json" diff --git a/bin/hyperion.init.sh b/bin/hyperion.init.sh index d83bdb28..fbae0156 100644 --- a/bin/hyperion.init.sh +++ b/bin/hyperion.init.sh @@ -1,7 +1,16 @@ #!/bin/bash -# Hyperion daemon +# Hyperion daemon service # description: Hyperion daemon # processname: hyperiond +### BEGIN INIT INFO +# Provides: Hyperion +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Hyperion Ambilight init.d Service. +# Description: Hyperion Ambilight init.d Service. +### END INIT INFO DAEMON=hyperiond DAEMONOPTS="/etc/hyperion.config.json" diff --git a/bin/hyperion.initctl.sh b/bin/hyperion.initctl.sh new file mode 100644 index 00000000..e533b14a --- /dev/null +++ b/bin/hyperion.initctl.sh @@ -0,0 +1,17 @@ +## Hyperion daemon initctl script + +description "hyperion" +author "poljvd & tvdzwan" + +start on (runlevel [2345]) +stop on (runlevel [!2345]) + +respawn + +pre-start script +#comment out the following 2 lines for x32/64 +modprobe spidev +/usr/bin/gpio2spi +end script + +exec /usr/bin/hyperiond /etc/hyperion.config.json \ No newline at end of file diff --git a/bin/hyperion.systemd.sh b/bin/hyperion.systemd.sh new file mode 100644 index 00000000..005c0c14 --- /dev/null +++ b/bin/hyperion.systemd.sh @@ -0,0 +1,15 @@ +[Unit] +Description=Hyperion Systemd service + +[Service] +Type=simple +User=root +Group=root +UMask=007 +ExecStart=/opt/hyperion/bin/hyperiond /etc/hyperion.config.json +ExecReload=/bin/kill -HUP $MAINPID +Restart=on-failure +TimeoutStopSec=10 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/bin/remove_hyperion.sh b/bin/remove_hyperion.sh new file mode 100644 index 00000000..2b0c2788 --- /dev/null +++ b/bin/remove_hyperion.sh @@ -0,0 +1,105 @@ +#!/bin/sh +# Script to remove Hyperion and all services + +# Make sure /sbin is on the path (for service to find sub scripts) +PATH="/sbin:$PATH" + +#Check if HyperCon is logged in as root +if [ $(id -u) != 0 ] && [ "$1" = "HyperConRemove" ]; then + echo '---> Critical Error: Please connect as user "root" through HyperCon' + echo '---> We need admin privileges to remove your Hyperion! -> abort' + exit 1 +fi + +#Check, if script is running as root +if [ $(id -u) != 0 ]; then + echo '---> Critical Error: Please run the script as root (sudo sh ./remove_hyperion.sh)' + exit 1 +fi + +#Welcome message +echo '*******************************************************************************' +echo 'This script will remove Hyperion and itīs services' +echo '-----> Please BACKUP your hyperion.config.json if necessary <-----' +echo '*******************************************************************************' + +#Skip the prompt if HyperCon Remove +if [ "$1" = "" ]; then +#Prompt for confirmation to proceed +while true +do +echo -n "---> Do you really want to remove Hyperion and itīs services? (y or n) :" +read CONFIRM +case $CONFIRM in +y|Y|YES|yes|Yes) break ;; +n|N|no|NO|No) +echo "---> Aborting - you entered \"$CONFIRM\"" +exit +;; +*) echo "-> Please enter only y or n" +esac +done +echo "---> You entered \"$CONFIRM\". Remove Hyperion!" +fi +# Find out if we are on OpenElec +OS_OPENELEC=`grep -m1 -c OpenELEC /etc/issue` + +# check which init script we should use +USE_SYSTEMD=`grep -m1 -c systemd /proc/1/comm` +USE_INITCTL=`which /sbin/initctl | wc -l` +USE_SERVICE=`which /usr/sbin/service | wc -l` + +# Stop hyperion daemon if it is running +echo '---> Stop Hyperion, if necessary' +if [ $OS_OPENELEC -eq 1 ]; then + killall hyperiond 2>/dev/null +elif [ $USE_INITCTL -eq 1 ]; then + /sbin/initctl stop hyperion 2>/dev/null +elif [ $USE_SERVICE -eq 1 ]; then + /usr/sbin/service hyperion stop 2>/dev/null +elif [ $USE_SYSTEMD -eq 1 ]; then + service hyperion stop 2>/dev/null +fi + +#Disabling and delete service files +if [ $USE_INITCTL -eq 1 ]; then + echo '---> Delete and disable Hyperion initctl script' + rm -v /etc/init/hyperion 2>/dev/null + initctl reload-configuration +elif [ $OS_OPENELEC -eq 1 ]; then + # Remove Hyperion from OpenELEC autostart.sh + echo "---> Remove Hyperion from OpenELEC autostart.sh" + sed -i "/hyperiond/d" /storage/.config/autostart.sh 2>/dev/null +elif [ $USE_SYSTEMD -eq 1 ]; then + # Delete and disable Hyperion systemd script + echo '---> Delete and disable Hyperion systemd script' + systemctl disable hyperion.service + rm -v /etc/systemd/system/hyperion.service 2>/dev/null +elif [ $USE_SERVICE -eq 1 ]; then + # Delete and disable Hyperion init.d script + echo '---> Delete and disable Hyperion init.d script' + update-rc.d -f hyperion remove + rm /etc/init.d/hyperion 2>/dev/null +fi + +# Delete Hyperion binaries +if [ $OS_OPENELEC -eq 1 ]; then + # Remove OpenELEC Hyperion binaries and configs + echo '---> Remove the OpenELEC Hyperion binaries and hyperion.config.json' + rm -rv /storage/hyperion 2>/dev/null + rm -v /storage/.config/hyperion.config.json 2>/dev/null +else + #Remove binaries on all distributions/systems (not OpenELEC) + echo "---> Remove links to the binaries" + rm -v /usr/bin/hyperiond 2>/dev/null + rm -v /usr/bin/hyperion-remote 2>/dev/null + rm -v /usr/bin/hyperion-v4l2 2>/dev/null + rm -v /etc/hyperion.config.json 2>/dev/null + echo "---> Remove binaries" + rm -rv /opt/hyperion 2>/dev/null +fi +echo '*******************************************************************************' +echo 'Hyperion successful removed!' +echo '*******************************************************************************' +exit 0 + \ No newline at end of file diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 291086db..5bc313c3 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -4,39 +4,19 @@ { /// Device configuration contains the following fields: /// * 'name' : The user friendly name of the device (only used for display purposes) - /// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'ldp8806', - /// 'lpd6803', 'sedu', 'adalight', 'lightpack', 'philipshue', 'test' and 'none') - /// * 'output' : The output specification depends on selected device. This can for example be the - /// device specifier, device serial number, or the output file name - /// * 'rate' : The baudrate of the output to the device + /// * 'type' : The type of the device or leds (known types for now are + /// APA102, Adalight, AmbiLed, Atmo, Hyperion-USBASP-WS2801, Hyperion-USBASP-WS2812, Lightberry, Lightpack, LPD6803, LPD8806, Multi-Lightpack, P9813, Paintpack, PhilipsHUE, PiBlaster, SEDU, Test, ThinkerForge, TPM2, WS2801, WS2812b, None) + /// * [device type specific configuration] /// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.). - /// Specific of Philips Hue: - /// * 'username' : The name of user registred on the Philips Hue Bridge - /// * 'switchOffOnBlack' : Define if Hue light switch off when black is detected - /// * 'transitiontime' : Set the time of transition between color of Hue light "device" : { "name" : "MyPi", "type" : "ws2801", "output" : "/dev/spidev0.0", - "rate" : 250000, + "rate" : 1000000, "colorOrder" : "rgb" }, - /// Configuration for message forwarding to other hyperions - /// protobuffer and json remote interface are forwarded to configured hosts - /// 'proto' is mostly used for video streams and 'json' for effects - /// - /// ** pay attention which port you use. use correct ports for protols ** - /// - /// * 'proto' : list of host in form of : - /// * 'json' : list of host in form of : -/// "forwarder" : -/// { -/// "proto" : [ "127.0.0.1:19445","192.168.178.88:19445" ], -/// "json" : [ "127.0.0.1:19444","192.168.178.88:19444" ] -/// }, - /// Color manipulation configuration used to tune the output colors to specific surroundings. /// The configuration contains a list of color-transforms. Each transform contains the /// following fields: @@ -59,6 +39,7 @@ /// - 'type' The type of smoothing algorithm ('linear' or 'none') /// - 'time_ms' The time constant for smoothing algorithm in milliseconds /// - 'updateFrequency' The update frequency of the leds in Hz + /// - 'updateDelay' The delay of the output to leds (in periods of smoothing) "color" : { "transform" : @@ -96,13 +77,156 @@ ], "smoothing" : { - "type" : "none", + "type" : "linear", "time_ms" : 200, "updateFrequency" : 20.0000, "updateDelay" : 0 } }, + /// The black border configuration, contains the following items: + /// * enable : true if the detector should be activated + /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) + /// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) + /// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) + /// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency + /// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) + /// * mode : Border detection mode (values=default,classic,osd) + "blackborderdetector" : + { + "enable" : true, + "threshold" : 0.0, + "unknownFrameCnt" : 600, + "borderFrameCnt" : 50, + "maxInconsistentCnt" : 10, + "blurRemoveCnt" : 1, + "mode" : "default" + }, + + /// The configuration of the effect engine, contains the following items: + /// * paths : An array with absolute location(s) of directories with effects + /// * color : Set static color after boot -> set effect to "" (empty) and input the values [R,G,B] and set duration_ms NOT to 0 (use 1) instead + /// * effect : The effect selected as 'boot sequence' + /// * duration_ms : The duration of the selected effect (0=endless) + /// * priority : The priority of the selected effect/static color (default=0) + "effects" : + { + "paths" : + [ + "/opt/hyperion/effects" + ] + }, + + "bootsequence" : + { + "color" : [0,0,0], + "effect" : "Rainbow swirl fast", + "duration_ms" : 3000, + "priority" : 990 + }, + + /// The configuration of the Json/Proto forwarder. Forward messages to multiple instances of Hyperion on same and/or other hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// * proto : Proto server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19447"] or more instances to forward ["127.0.0.1:19447","192.168.0.24:19449"] + /// * json : Json server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19446"] or more instances to forward ["127.0.0.1:19446","192.168.0.24:19448"] + /// HINT: If you redirect to "127.0.0.1" (localhost) you could start a second hyperion with another device/led config! + /// Be sure your client(s) is/are listening on the configured ports. The second Hyperion (if used) also needs to be configured! (HyperCon -> External -> Json Server/Proto Server) +// "forwarder" : +// { +// "proto" : ["127.0.0.1:19447"], +// "json" : ["127.0.0.1:19446"] +// }, + + /// The configuration for the frame-grabber, contains the following items: + /// * width : The width of the grabbed frames [pixels] + /// * height : The height of the grabbed frames [pixels] + /// * frequency_Hz : The frequency of the frame grab [Hz] + "framegrabber" : + { + "width" : 80, + "height" : 45, + "frequency_Hz" : 10.0 + }, + + /// The configuration of the Kodi connection used to enable and disable the frame-grabber. Contains the following fields: + /// * xbmcAddress : The IP address of the Kodi-host + /// * xbmcTcpPort : The TCP-port of the Kodi-server + /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback + /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show + /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback + /// * grabMenu : Flag indicating that the frame-grabber is on(true) at the Kodi menu + /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when Kodi is on screensaver + /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing +// "xbmcVideoChecker" : +// { +// "xbmcAddress" : "127.0.0.1", +// "xbmcTcpPort" : 9090, +// "grabVideo" : true, +// "grabPictures" : true, +// "grabAudio" : true, +// "grabMenu" : false, +// "grabScreensaver" : true, +// "enable3DDetection" : true +// }, + + /// The configuration of the Json server which enables the json remote interface + /// * port : Port at which the json server is started + "jsonServer" : + { + "port" : 19444 + }, + + /// The configuration of the Proto server which enables the protobuffer remote interface + /// * port : Port at which the protobuffer server is started + "protoServer" : + { + "port" : 19445 + }, + + /// The configuration of the boblight server which enables the boblight remote interface + /// * port : Port at which the boblight server is started +// "boblightServer" : +// { +// "port" : 19333 +// }, + + /// Configuration for the embedded V4L2 grabber + /// * device : V4L2 Device to use [default="/dev/video0"] + /// * input : V4L2 input to use [default=0] + /// * standard : Video standard (no-change/PAL/NTSC) [default="no-change"] + /// * width : V4L2 width to set [default=-1] + /// * height : V4L2 height to set [default=-1] + /// * frameDecimation : Frame decimation factor [default=2] + /// * sizeDecimation : Size decimation factor [default=8] + /// * priority : Hyperion priority channel [default=800] + /// * mode : 3D mode to use 2D/3DSBS/3DTAB (note: no autodetection) [default="2D"] + /// * cropLeft : Cropping from the left [default=0] + /// * cropRight : Cropping from the right [default=0] + /// * cropTop : Cropping from the top [default=0] + /// * cropBottom : Cropping from the bottom [default=0] + /// * redSignalThreshold : Signal threshold for the red channel between 0.0 and 1.0 [default=0.0] + /// * greenSignalThreshold : Signal threshold for the green channel between 0.0 and 1.0 [default=0.0] + /// * blueSignalThreshold : Signal threshold for the blue channel between 0.0 and 1.0 [default=0.0] +// "grabber-v4l2" : +// { +// "device" : "/dev/video0", +// "input" : 0, +// "standard" : "no-change", +// "width" : -1, +// "height" : -1, +// "frameDecimation" : 2, +// "sizeDecimation" : 8, +// "priority" : 800, +// "mode" : "2D", +// "cropLeft" : 0, +// "cropRight" : 0, +// "cropTop" : 0, +// "cropBottom" : 0, +// "redSignalThreshold" : 0.0, +// "greenSignalThreshold" : 0.0, +// "blueSignalThreshold" : 0.0 +// }, + /// The configuration for each individual led. This contains the specification of the area /// averaged of an input image for each led to determine its color. Each item in the list /// contains the following fields: @@ -116,47 +240,47 @@ [ { "index" : 0, - "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, + "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 1, - "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, + "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 2, - "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, + "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 3, - "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, + "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 4, - "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, + "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 5, - "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, + "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 6, - "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, + "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 7, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, + "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { "index" : 8, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { @@ -196,271 +320,155 @@ }, { "index" : 16, - "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 17, "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 18, + "index" : 17, "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 19, + "index" : 18, "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 20, + "index" : 19, "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 21, + "index" : 20, "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 22, + "index" : 21, "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 23, + "index" : 22, "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 24, + "index" : 23, "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { - "index" : 25, + "index" : 24, "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, + { + "index" : 25, + "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, { "index" : 26, - "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, + "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 27, - "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, + "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 28, - "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, + "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 29, - "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, + "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 30, - "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, + "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 31, - "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, + "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } }, { "index" : 32, - "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 33, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } - }, - { - "index" : 34, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } }, { - "index" : 35, + "index" : 33, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } }, { - "index" : 36, + "index" : 34, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } }, { - "index" : 37, + "index" : 35, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } }, { - "index" : 38, + "index" : 36, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } }, { - "index" : 39, + "index" : 37, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } }, { - "index" : 40, + "index" : 38, "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } }, { - "index" : 41, - "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 42, + "index" : 39, "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 43, + "index" : 40, "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 44, + "index" : 41, "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 45, + "index" : 42, "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 46, + "index" : 43, "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 47, + "index" : 44, "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } }, { - "index" : 48, + "index" : 45, "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } - }, - { - "index" : 49, - "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, - "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } } ], - /// The black border configuration, contains the following items: - /// * enable : true if the detector should be activated - /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) - /// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) - optional - /// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) - optional - /// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency - optional - /// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) - optional - /// * mode : Border detection mode (values "default","classic","osd") - optional - - "blackborderdetector" : - { - "enable" : true, - "threshold" : 0.01, - "unknownFrameCnt": 600, - "borderFrameCnt" : 50, - "maxInconsistentCnt" : 10, - "blurRemoveCnt": 1, - "mode" : "default" - }, - - /// The configuration of the effect engine, contains the following items: - /// * paths : An array with absolute location(s) of directories with effects - /// * bootsequence : The effect selected as 'boot sequence' - /// * effect : name of the effect you want to start. Set to empty if no effect wanted - /// * color : switch to static color after effect is done - /// * duration_ms : duration of boot effect in ms. 0 means effect stays forever - /// * priority : priority of boot effect and static color - "effects" : - { - "paths" : - [ - "/opt/hyperion/effects" - ] - }, - - "bootsequence" : - { - "color" : [0,0,0], - "effect" : "Rainbow swirl fast", - "duration_ms" : 3000, - "priority" : 0 - }, - - /// The configuration for the frame-grabber, contains the following items: - /// * width : The width of the grabbed frames [pixels] - /// * height : The height of the grabbed frames [pixels] - /// * frequency_Hz : The frequency of the frame grab [Hz] - "framegrabber" : - { - "width" : 64, - "height" : 64, - "frequency_Hz" : 10.0 - }, - - /// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: - /// * xbmcAddress : The IP address of the XBMC-host - /// * xbmcTcpPort : The TCP-port of the XBMC-server - /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback - /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show - /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback - /// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu - /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when XBMC is on screensaver - /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing - "xbmcVideoChecker" : - { - "xbmcAddress" : "127.0.0.1", - "xbmcTcpPort" : 9090, - "grabVideo" : true, - "grabPictures" : true, - "grabAudio" : true, - "grabMenu" : false, - "grabScreensaver" : true, - "enable3DDetection" : true - }, - - /// The configuration of the Json server which enables the json remote interface - /// * port : Port at which the json server is started - "jsonServer" : - { - "port" : 19444 - }, - - /// The configuration of the Proto server which enables the protobuffer remote interface - /// * port : Port at which the protobuffer server is started - "protoServer" : - { - "port" : 19445 - }, - - /// The configuration of the boblight server which enables the boblight remote interface - /// * port : Port at which the boblight server is started -// "boblightServer" : -// { -// "port" : 19333 -// }, - "endOfJson" : "endOfJson" }