Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions assets/webconfig/content/remote.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@ <h3 class="page-header"><i class="fa fa-wifi fa-fw"></i><span data-i18n="main_me
<span class="input-group-addon" id="remote_input_reseff" title="Repeat Effect" style="cursor:pointer"><i class="fa fa-repeat"></i></span>
</td>
</tr>
<tr style="display:none">
<td style="vertical-align:middle"><label for="remote_input_img" >Picture:</label></td>
<td><input id="remote_input_img" type="file" accept="image/*" /></td>
<tr>
<td style="vertical-align:middle"><label for="remote_input_img" data-i18n="remote_effects_label_picture" >Picture:</label></td>
<td class="input-group custom-file">
<input class="form-control" id="remote_input_img" type="file" accept="image/*" />
<span class="input-group-addon" id="remote_input_repimg" title="Repeat Image" style="cursor:pointer"><i class="fa fa-repeat"></i></span>
</td>
</tr>
<tr>
<td style="vertical-align:middle"><label for="remote_duration" data-i18n="remote_input_duration"></label></td>
Expand Down
1 change: 1 addition & 0 deletions assets/webconfig/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@
"remote_color_button_reset": "Farbe/Effekt zurücksetzen",
"remote_color_label_color": "Farbe:",
"remote_effects_label_effects": "Effekt:",
"remote_effects_label_picture" : "Bild:",
"remote_adjustment_label": "Farbanpassung",
"remote_adjustment_intro": "Verändere live Farbe/Helligkeit/Kompensation. $1",
"remote_videoMode_label": "Video Modus",
Expand Down
1 change: 1 addition & 0 deletions assets/webconfig/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@
"remote_color_button_reset" : "Reset Color/Effect",
"remote_color_label_color" : "Color:",
"remote_effects_label_effects" : "Effect:",
"remote_effects_label_picture" : "Picture:",
"remote_adjustment_label" : "Color adjustment",
"remote_adjustment_intro" : "Modifiy color/brightness/compensation during runtime. $1",
"remote_videoMode_label" : "Video mode",
Expand Down
11 changes: 11 additions & 0 deletions assets/webconfig/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ <h3>Hyperion Web Configuration requires Javascript. Please enable Javascript in
<!-- /.navbar-header -->

<ul class="nav navbar-top-links navbar-right">
<!-- Browser built in capture stream - streamer.js -->
<li class="dropdown" id="btn_streamer" style="display:none">
<!-- Hidden helpers -->
<canvas style="display:none" id="streamcanvas"></canvas>
<video style="display:none" id="streamvideo" autoplay></video>
<a>
<i id="btn_streamer_icon" class="fa fa-video-camera fa-fw"></i>
</a>
</li>
<!-- instance switcher -->
<li class="dropdown" id="btn_hypinstanceswitch" style="display:none">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-exchange fa-fw"></i> <i class="fa fa-caret-down"></i>
Expand Down Expand Up @@ -311,6 +321,7 @@ <h4 data-i18n="dashboard_alert_message_disabled_t"></h4>

<script src="js/content_index.js"></script>
<script src="js/settings.js"></script>
<script src="js/streamer.js"></script>
<script src="js/wizard.js"></script>

<!--gijgo dialog-->
Expand Down
27 changes: 22 additions & 5 deletions assets/webconfig/js/content_remote.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ $(document).ready(function() {
var mappingList = window.serverSchema.properties.color.properties.imageToLedMappingType.enum;
var duration = 0;
var rgb = {r:255,g:0,b:0};
var lastImgData = "";
var lastFileName= "";

//create html
createTable('ssthead', 'sstbody', 'sstcont');
Expand Down Expand Up @@ -115,7 +117,7 @@ $(document).ready(function() {

if(priority > 254)
continue;
if(priority < 254 && (compId == "EFFECT" || compId == "COLOR") )
if(priority < 254 && (compId == "EFFECT" || compId == "COLOR" || compId == "IMAGE") )
clearAll = true;

if (visible)
Expand All @@ -139,6 +141,9 @@ $(document).ready(function() {
case "COLOR":
owner = $.i18n('remote_color_label_color')+' '+'<div style="width:18px; height:18px; border-radius:20px; margin-bottom:-4px; border:1px grey solid; background-color: rgb('+value+'); display:inline-block" title="RGB: ('+value+')"></div>';
break;
case "IMAGE":
owner = $.i18n('remote_effects_label_picture')+' '+owner;
break;
case "GRABBER":
owner = $.i18n('general_comp_GRABBER')+': ('+owner+')';
break;
Expand All @@ -161,7 +166,7 @@ $(document).ready(function() {

var btn = '<button id="srcBtn'+i+'" type="button" '+btn_state+' class="btn btn-'+btn_type+' btn_input_selection" onclick="requestSetSource('+priority+');">'+btn_text+'</button>';

if((compId == "EFFECT" || compId == "COLOR") && priority < 254)
if((compId == "EFFECT" || compId == "COLOR" || compId == "IMAGE") && priority < 254)
btn += '<button type="button" class="btn btn-sm btn-danger" style="margin-left:10px;" onclick="requestPriorityClear('+priority+');"><i class="fa fa-close"></button>';

if(btn_type != 'default')
Expand Down Expand Up @@ -301,7 +306,9 @@ $(document).ready(function() {

$("#reset_color").off().on("click", function(){
requestPriorityClear();
lastImgData = "";
$("#effect_select").val("__none__");
$("#remote_input_img").val("");
});

$("#remote_duration").off().on("change", function(){
Expand All @@ -320,10 +327,20 @@ $(document).ready(function() {
sendEffect();
});

$("#remote_input_repimg").off().on("click", function(){
if(lastImgData != "")
requestSetImage(lastImgData, duration, lastFileName);
});

$("#remote_input_img").change(function(){
readImg(this, function(src,width,height){
console.log(src,width,height)
requestSetImage(src,width,height,duration)
readImg(this, function(src,fileName){
lastFileName = fileName;
if(src.includes(","))
lastImgData = src.split(",")[1];
else
lastImgData = src;

requestSetImage(lastImgData, duration, lastFileName);
});
});

Expand Down
10 changes: 5 additions & 5 deletions assets/webconfig/js/hyperion.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,19 @@ function initWebSocket()
{
var error = response.hasOwnProperty("error")? response.error : "unknown";
$(window.hyperion).trigger({type:"error",reason:error});
console.log("[window.websocket::onmessage] "+error)
console.log("[window.websocket::onmessage] ",error)
}
}
catch(exception_error)
{
$(window.hyperion).trigger({type:"error",reason:exception_error});
console.log("[window.websocket::onmessage] "+exception_error)
console.log("[window.websocket::onmessage] ",exception_error)
}
};

window.websocket.onerror = function (error) {
$(window.hyperion).trigger({type:"error",reason:error});
console.log("[window.websocket::onerror] "+error)
console.log("[window.websocket::onerror] ",error)
};
}
}
Expand Down Expand Up @@ -290,9 +290,9 @@ function requestSetColor(r,g,b,duration)
sendToHyperion("color", "", '"color":['+r+','+g+','+b+'], "priority":'+window.webPrio+',"duration":'+validateDuration(duration)+',"origin":"'+window.webOrigin+'"');
}

function requestSetImage(data,width,height,duration)
function requestSetImage(data,duration,name)
{
sendToHyperion("image", "", '"imagedata":"'+data+'", "imagewidth":'+width+',"imageheight":'+height+', "priority":'+window.webPrio+',"duration":'+validateDuration(duration)+'');
sendToHyperion("image", "", '"imagedata":"'+data+'", "priority":'+window.webPrio+',"duration":'+validateDuration(duration)+', "format":"auto", "origin":"'+window.webOrigin+'", "name":"'+name+'"');
}

function requestSetComponentState(comp, state)
Expand Down
111 changes: 111 additions & 0 deletions assets/webconfig/js/streamer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
$(document).ready( function() {

// check if browser supports streaming
if(window.navigator.mediaDevices && window.navigator.mediaDevices.getDisplayMedia){
$("#btn_streamer").toggle()
}

// variables
var streamActive = false;
var screenshotTimer = "";
var screenshotIntervalTimeMs = 100;
var streamImageHeight = 0;
var streamImageWidth = 0;
const videoElem = document.getElementById("streamvideo");
const canvasElem = document.getElementById("streamcanvas");

// Options for getDisplayMedia()
var displayMediaOptions = {
video: {
cursor: "never",
width: 170,
height: 100,
frameRate: 15
},
audio: false
};


async function startCapture() {
streamActive = true;

try {
var stream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
videoElem.srcObject = stream;

// get the active track of the stream
const track = stream.getVideoTracks()[0];

// listen for track ending, fires when user aborts through browser
track.onended = function(event) {
stopCapture();
};

// wait for video ready
videoElem.addEventListener('loadedmetadata', (e) => {
window.setTimeout(() => (
onCapabilitiesReady(track.getSettings())
), 500);
});
} catch(err) {
stopCapture();
console.error("Error: " + err);
}
}

function onCapabilitiesReady(settings) {
// extract real width/height
streamImageWidth = settings.width;
streamImageHeight = settings.height;

// start screenshotTimer
updateScrTimer(false);

// we are sending
$("#btn_streamer_icon").addClass("text-danger");
}

function stopCapture(evt) {
streamActive = false;
$("#btn_streamer_icon").removeClass("text-danger");

updateScrTimer(true);
// sometimes it's null on abort
if(videoElem.srcObject){
let tracks = videoElem.srcObject.getTracks();

tracks.forEach(track => track.stop());
videoElem.srcObject = null;
}
}

function takePicture(){
var context = canvasElem.getContext('2d');
canvasElem.width = streamImageWidth;
canvasElem.height = streamImageHeight;
context.drawImage(videoElem, 0, 0, streamImageWidth, streamImageHeight);

var data = canvasElem.toDataURL('image/png').split(",")[1];
requestSetImage(data, 2, "Streaming");
}

// start or update screenshot timer
function updateScrTimer(stop){
clearInterval(screenshotTimer)

if(stop === false){
screenshotTimer = setInterval(() => (
takePicture()
), screenshotIntervalTimeMs);
}
}

$("#btn_streamer").off().on("click",function(e){
if(!$("#btn_streamer_icon").hasClass("text-danger") && !streamActive){
startCapture();
} else {
stopCapture();
}
});

});
6 changes: 3 additions & 3 deletions assets/webconfig/js/ui_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,11 @@ function readImg(input,cb)
{
if (input.files && input.files[0]) {
var reader = new FileReader();
// inject fileName property
reader.fileName = input.files[0].name

reader.onload = function (e) {
var i = new Image();
i.src = e.target.result;
cb(i.src,i.width,i.height);
cb(e.target.result, e.target.fileName);
}
reader.readAsDataURL(input.files[0]);
}
Expand Down
14 changes: 12 additions & 2 deletions libsrc/api/JSONRPC_schema/schema-image.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,27 @@
},
"imagewidth": {
"type" : "integer",
"required": true,
"minimum": 0
},
"imageheight": {
"type" : "integer",
"required": true,
"minimum": 0
},
"imagedata": {
"type": "string",
"required": true
},
"format": {
"type": "string",
"enum" : ["auto"]
},
"scale": {
"type": "integer",
"minimum" : 25,
"maximum" : 2000
},
"name": {
"type": "string"
}
},
"additionalProperties": false
Expand Down
Loading