mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
effects included in hyperiond binary as qtResource (#237)
* implement effects included in hyperiond binary * cleanup * remove install of effects dir. People who wants to develop effects has to copy them from github effect params for initial effects can be changed in config permanently and other effect params can be changed via json (currently only temporarily) * fix schema of fadecandy webui fix display of specific led options * add leddevice write support * cleanup * webui: tune hue code * when use json effect definition from putsiede hyperiond but want to use py script from inside hyperiond use ad a : e.g. fade.py needs a fade.py near the json file, but :fade.py is taken from resource inside hyperiond * add ability to di * add abiloty to diable effcts via hyperion config * use effect name instead of script in active effects and prio register * finally solve open file handle during effect is playing. Now script is read before, then file closed and then t is run by python * fix some webui things - led config tabs - inital loading screen optimize qrc file generation fix compile warning in hyperion.cpp * cleanup * more cleanup
This commit is contained in:
parent
d097995a74
commit
adfe2a4b23
@ -45,29 +45,24 @@
|
|||||||
<div id="menu_controller" class="tab-pane fade in active" style="padding-top:10px">
|
<div id="menu_controller" class="tab-pane fade in active" style="padding-top:10px">
|
||||||
<div class="panel panel-primary">
|
<div class="panel panel-primary">
|
||||||
<div class="panel-heading form-group" style="font-size:90%;white-space:nowrap;">
|
<div class="panel-heading form-group" style="font-size:90%;white-space:nowrap;">
|
||||||
<button id='btn_submit' class="btn btn-success" style="float:right">Save Settings</button>
|
<button id='btn_submit_controller' class="btn btn-success" style="float:right">Save Settings</button>
|
||||||
<label for="leddevices">Controller Type</label>
|
<label for="leddevices">Controller Type</label>
|
||||||
<select id="leddevices" class="form-control" style="color:black;width:auto;margin-left:10px;display:inline-block" />
|
<select id="leddevices" class="form-control" style="color:black;width:auto;margin-left:10px;display:inline-block" />
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
|
||||||
<div id="ledDeviceOptions">
|
|
||||||
<div id='editor_container'></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="panel-body">
|
||||||
|
<div id="ledDeviceOptions"> <div id='editor_container'></div> </div>
|
||||||
|
|
||||||
<div id="huebridge" class="container-fluid" style="display:none">
|
<div id="huebridge" class="container-fluid" style="display:none">
|
||||||
<hr/>
|
<hr/>
|
||||||
<button data-toggle="collapse" class="btn btn-success" data-target="#huebridge_content">Hue Bridge Setup Helper</button>
|
<button data-toggle="collapse" class="btn btn-success" data-target="#huebridge_content">Hue Bridge Setup Helper</button>
|
||||||
|
|
||||||
|
|
||||||
<div id="huebridge_content" class="collapse">
|
<div id="huebridge_content" class="collapse">
|
||||||
<!-- <div class="col-lg-12"> -->
|
<div class="introd" style="margin-top:20px;margin-bottom:20px">
|
||||||
<!-- <h1 class="page-header" lang="en" data-lang-token="main_menu_huebridge_token">Hue Bridge</h1> -->
|
With this Setup Helper you can get a new User for your Hue Bridge and you can see your Lights with the IDs for Hyperion Configuration.
|
||||||
With this Setup Helper you can get a new User for your Hue Bridge and you can see your Lights with the IDs for Hyperion Configuration.<br />
|
If you already have a working User you will see it below. But you can always create a new one as well.
|
||||||
If you already have a working User you will see it below. But you can always create a new one as well. <br />
|
<b>Remember:</b> This is only a helper. You have to copy and paste them in your config above.
|
||||||
<b>Remember:</b> This is only a helper. You have to copy and paste them in your config above. <br/ >
|
</div>
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
|
|
||||||
<span id="ip_alert" style="display:none; color:red; font-weight: bold;" lang="en" data-lang-token="hue_failure_ip_token">Please check your IP Address.</span>
|
<span id="ip_alert" style="display:none; color:red; font-weight: bold;" lang="en" data-lang-token="hue_failure_ip_token">Please check your IP Address.</span>
|
||||||
<span id="abortConnection" style="display:none; color:red; font-weight: bold;" lang="en" data-lang-token="hue_failure_connection_token">Connection Timeout. Please press the button in time.</span><br />
|
<span id="abortConnection" style="display:none; color:red; font-weight: bold;" lang="en" data-lang-token="hue_failure_connection_token">Connection Timeout. Please press the button in time.</span><br />
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -75,16 +70,12 @@
|
|||||||
<input type="text" class="form-control" id="ip">
|
<input type="text" class="form-control" id="ip">
|
||||||
<label for="user" lang="en" data-lang-token="hue_label_username">Hue Bridge Username:</label>
|
<label for="user" lang="en" data-lang-token="hue_label_username">Hue Bridge Username:</label>
|
||||||
<input type="text" class="form-control" id="user" disabled>
|
<input type="text" class="form-control" id="user" disabled>
|
||||||
<br />
|
<div id="hue_lights" class="row"></div>
|
||||||
<div id="hue_lights" class="row" />
|
|
||||||
<button type="button" class="btn btn-success" id="create_user"> <i class="fa fa-floppy-o"></i><span lang="en" data-lang-token="hue_button_create_user_token"> Create User</span></button>
|
<button type="button" class="btn btn-success" id="create_user"> <i class="fa fa-floppy-o"></i><span lang="en" data-lang-token="hue_button_create_user_token"> Create User</span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -48,3 +48,16 @@ table.borderless td,table.borderless th{border: none !important;}
|
|||||||
/*Config introduction*/
|
/*Config introduction*/
|
||||||
.introd{padding-left:14px;border-left:5px solid #0088cc;}
|
.introd{padding-left:14px;border-left:5px solid #0088cc;}
|
||||||
.introd h4{line-height:25px;}
|
.introd h4{line-height:25px;}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
background-image: url('/img/hyperion/hyperionlogo.png');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
background-color: rgba(1, 1, 1, 0.7);
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index:99999;
|
||||||
|
}
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<div id="loading_overlay"></div>
|
||||||
|
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
$(document).ready( function() {
|
$(document).ready( function() {
|
||||||
|
$("#loading_overlay").addClass("overlay");
|
||||||
loadContentTo("#container_connection_lost","connection_lost");
|
loadContentTo("#container_connection_lost","connection_lost");
|
||||||
initWebSocket();
|
initWebSocket();
|
||||||
bindNavToContent("#load_dashboard","dashboard",true);
|
bindNavToContent("#load_dashboard","dashboard",true);
|
||||||
@ -51,6 +52,7 @@ $(document).ready( function() {
|
|||||||
$('#versioninforesult').html('<div lang="en" data-lang-token="dashboard_message_infobox_updatesuccess" style="margin:0px;" class="alert alert-success">You run the latest version of Hyperion.</div>');
|
$('#versioninforesult').html('<div lang="en" data-lang-token="dashboard_message_infobox_updatesuccess" style="margin:0px;" class="alert alert-success">You run the latest version of Hyperion.</div>');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
$("#loading_overlay").removeClass("overlay");
|
||||||
}); // end cmd-serverinfo
|
}); // end cmd-serverinfo
|
||||||
|
|
||||||
$(hyperion).one("cmd-config-getschema", function(event) {
|
$(hyperion).one("cmd-config-getschema", function(event) {
|
||||||
|
@ -108,18 +108,17 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
$('#leds_cfg_nav a[data-toggle="tab"]').off().on('shown.bs.tab', function (e) {
|
$('#leds_cfg_nav a[data-toggle="tab"]').off().on('shown.bs.tab', function (e) {
|
||||||
var target = $(e.target).attr("href") // activated tab
|
var target = $(e.target).attr("href") // activated tab
|
||||||
if (target == "#menu_gencfg" && !ledsCustomCfgInitialized)
|
if (target == "#menu_gencfg" && !ledsCustomCfgInitialized)
|
||||||
{
|
{
|
||||||
ledsCustomCfgInitialized = true;
|
ledsCustomCfgInitialized = true;
|
||||||
// $("#ledconfig").linedtextarea();
|
|
||||||
// $(window).resize(function(){
|
|
||||||
// $("#ledconfig").trigger("resize");
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
var grabber_conf_editor = null;
|
||||||
$("#leddevices").off().on("change", function(event) {
|
$("#leddevices").off().on("change", function(event) {
|
||||||
generalOptions = parsedConfSchemaJSON.properties.device;
|
generalOptions = parsedConfSchemaJSON.properties.device;
|
||||||
specificOptions = parsedConfSchemaJSON.properties.alldevices[$(this).val()];
|
specificOptions = parsedConfSchemaJSON.properties.alldevices[$(this).val()];
|
||||||
@ -128,7 +127,7 @@ $(document).ready(function() {
|
|||||||
$('#editor_container').html("");
|
$('#editor_container').html("");
|
||||||
var element = document.getElementById('editor_container');
|
var element = document.getElementById('editor_container');
|
||||||
|
|
||||||
var grabber_conf_editor = new JSONEditor(element,{
|
grabber_conf_editor = new JSONEditor(element,{
|
||||||
theme: 'bootstrap3',
|
theme: 'bootstrap3',
|
||||||
iconlib: "fontawesome4",
|
iconlib: "fontawesome4",
|
||||||
disable_collapse: 'true',
|
disable_collapse: 'true',
|
||||||
@ -157,10 +156,11 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
if (isCurrentDevice)
|
if (isCurrentDevice)
|
||||||
{
|
{
|
||||||
for(var key in parsedConfJSON.device){
|
specificOptions_val = grabber_conf_editor.getEditor("root.specificOptions").getValue()
|
||||||
if (key in specificOptions.properties)
|
for(var key in grabber_conf_editor.getEditor("root.specificOptions").getValue()){
|
||||||
values_specific[key] = parsedConfJSON.device[key];
|
values_specific[key] = (key in parsedConfJSON.device) ? parsedConfJSON.device[key] : specificOptions_val[key];
|
||||||
};
|
};
|
||||||
|
|
||||||
grabber_conf_editor.getEditor("root.specificOptions").setValue( values_specific );
|
grabber_conf_editor.getEditor("root.specificOptions").setValue( values_specific );
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -188,5 +188,30 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
$("#btn_submit_controller").off().on("click", function(event) {
|
||||||
|
if (grabber_conf_editor==null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ledDevice = $("#leddevices").val();
|
||||||
|
result = {device:{}};
|
||||||
|
|
||||||
|
general = grabber_conf_editor.getEditor("root.generalOptions").getValue();
|
||||||
|
specific = grabber_conf_editor.getEditor("root.specificOptions").getValue();
|
||||||
|
for(var key in general){
|
||||||
|
result.device[key] = general[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var key in specific){
|
||||||
|
result.device[key] = specific[key];
|
||||||
|
}
|
||||||
|
result.device.type=ledDevice;
|
||||||
|
requestWriteConfig(result)
|
||||||
|
});
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
requestServerConfig();
|
requestServerConfig();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ var watchdog = 0;
|
|||||||
//
|
//
|
||||||
function cron()
|
function cron()
|
||||||
{
|
{
|
||||||
if ( watchdog > 3)
|
if ( watchdog > 2)
|
||||||
{
|
{
|
||||||
var interval_id = window.setInterval("", 9999); // Get a reference to the last
|
var interval_id = window.setInterval("", 9999); // Get a reference to the last
|
||||||
for (var i = 1; i < interval_id; i++)
|
for (var i = 1; i < interval_id; i++)
|
||||||
|
@ -1,609 +0,0 @@
|
|||||||
@font-face {
|
|
||||||
font-family: 'fontello';
|
|
||||||
src: url('../res/fontello.ttf') format('truetype'), url('../res/fontello.woff') format('woff');
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
color: #A6B4B4;
|
|
||||||
background-color: #2C2C2C;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-text-size-adjust: none;
|
|
||||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
|
||||||
font-family: 'Lucida Grande', Helvetica, Arial, Roboto, serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-webkit-flex-wrap: nowrap;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
|
|
||||||
background-color: #2C2C2C;
|
|
||||||
min-width: 320px;
|
|
||||||
min-height: 460px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.work {
|
|
||||||
-webkit-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
border-top: 1px solid #919F9F;
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-justify-content: space-around;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .button {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
position: relative;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.touchrect {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
font-family: "fontello";
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .button .icon {
|
|
||||||
font-size: 25px;
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .button .title {
|
|
||||||
font-size: 12px;
|
|
||||||
margin-top: 8px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .button:active,
|
|
||||||
.footer .button.selected {
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 400%;
|
|
||||||
display: flex;
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-transition: left 0.5s ease-in-out;
|
|
||||||
transition: left 0.5s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contentarea {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
-ms-overflow-y: auto;
|
|
||||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
|
||||||
position: relative;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
|
|
||||||
#color {
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#colorpicker {
|
|
||||||
position: relative;
|
|
||||||
-webkit-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#colorwheelbg {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pointer {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
position: absolute;
|
|
||||||
border: 2px solid #FFFFFF;
|
|
||||||
border-radius: 15px;
|
|
||||||
left: calc(50% - 15px);
|
|
||||||
top: calc(50% - 15px);
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal {
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
li .delete_icon {
|
|
||||||
font-family: "fontello";
|
|
||||||
font-size: 20px;
|
|
||||||
color: red;
|
|
||||||
height: 40px;
|
|
||||||
width: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
li .edit_icon {
|
|
||||||
font-family: "fontello";
|
|
||||||
font-size: 20px;
|
|
||||||
height: 40px;
|
|
||||||
width: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.locked .edit_icon,
|
|
||||||
.locked .delete_icon {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
li .titlebox {
|
|
||||||
-webkit-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebox label {
|
|
||||||
display: block;
|
|
||||||
line-height: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebox label.title {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebox label.subtitle {
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
li:not(:last-child) {
|
|
||||||
border-bottom: 1px solid #919F9F;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
li {
|
|
||||||
border-bottom: 1px solid #919F9F;
|
|
||||||
}
|
|
||||||
|
|
||||||
li input[type=range] {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#transform li {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#transform .icon {
|
|
||||||
width: 40px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group,
|
|
||||||
.grouplist {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grouplist .header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
border-bottom: 1px solid gray;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 15px;
|
|
||||||
font-size: 16px;
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-justify-content: space-between;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group ul,
|
|
||||||
.grouplist ul {
|
|
||||||
overflow-y: hidden;
|
|
||||||
-webkit-transition: all 0.5s ease-in-out;
|
|
||||||
transition: all 0.5s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group[collapsed=true] ul {
|
|
||||||
max-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group li label {
|
|
||||||
margin: 4px 0 0 50px;
|
|
||||||
display: block;
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group > .header {
|
|
||||||
border-bottom: 1px solid gray;
|
|
||||||
padding: 3px 0 3px 10px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group > .header label {
|
|
||||||
display: block;
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group > .header label:first-child {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group > .header label:last-child {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group > .header label:first-child:after {
|
|
||||||
font-family: "fontello";
|
|
||||||
content: '\e808';
|
|
||||||
font-size: 20px;
|
|
||||||
transition: all 0.5s ease-in-out;
|
|
||||||
-webkit-transform-origin: 50% 33%;
|
|
||||||
-webkit-transform: rotateZ(180deg);
|
|
||||||
transform-origin: 50% 33%;
|
|
||||||
transform: rotateZ(180deg);
|
|
||||||
-ms-transform-origin: 50% 33%;
|
|
||||||
-ms-transform: rotateZ(180deg);
|
|
||||||
position: absolute;
|
|
||||||
right: 24px;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grouplist .header .callout {
|
|
||||||
font-family: "fontello";
|
|
||||||
font-size: 20px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grouplist .header .callout:active {
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group[collapsed=true] > .header label:first-child:after {
|
|
||||||
-webkit-transform: rotateZ(0deg);
|
|
||||||
-ms-transform: rotateZ(0deg);
|
|
||||||
transform: rotateZ(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper .value {
|
|
||||||
width: 40px;
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
color: #FFFFFF;
|
|
||||||
margin: auto 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#transform .group .slider {
|
|
||||||
-webkit-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider {
|
|
||||||
position: relative;
|
|
||||||
margin-left: 20px;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider .track {
|
|
||||||
border-radius: 4px;
|
|
||||||
height: 4px;
|
|
||||||
border: 1px solid #BDC3C7;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider .thumb {
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-radius: 10px;
|
|
||||||
height: 20px;
|
|
||||||
width: 20px;
|
|
||||||
border: 2px solid #BDC3C7;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
position: absolute;
|
|
||||||
top: -8px;
|
|
||||||
margin-left: -10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper .icon {
|
|
||||||
display: block;
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.red .icon {
|
|
||||||
color: #FF0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.green .icon {
|
|
||||||
color: #00FF00;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blue .icon {
|
|
||||||
color: #0000FF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.msg {
|
|
||||||
position: relative;
|
|
||||||
margin: auto;
|
|
||||||
padding: 5px 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
|
||||||
background-color: #D70000;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status {
|
|
||||||
background-color: #00A200;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper_msg {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 5px;
|
|
||||||
width: 100%;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: flex;
|
|
||||||
visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
-webkit-transition: opacity 0.2s linear;
|
|
||||||
transition: opacity 0.2s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.invisible {
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputline {
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-justify-content: space-between;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 6px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings .inputline input {
|
|
||||||
background: none;
|
|
||||||
border: 1px solid rgba(100, 100, 100, 0.4);
|
|
||||||
height: 100%;
|
|
||||||
color: white;
|
|
||||||
text-align: right;
|
|
||||||
font-size: inherit;
|
|
||||||
-webkit-user-select: text;
|
|
||||||
-moz-user-select: text;
|
|
||||||
-ms-user-select: text;
|
|
||||||
user-select: text;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings .inputline input:focus {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line {
|
|
||||||
width: 100%;
|
|
||||||
position: relative;
|
|
||||||
padding: 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin: auto 10px;
|
|
||||||
border: 1px #A6B4B4 solid;
|
|
||||||
background: none;
|
|
||||||
color: #A6B4B4;
|
|
||||||
padding: 6px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:active {
|
|
||||||
border: 1px #FFFFFF solid;
|
|
||||||
background-color: transparent;
|
|
||||||
color: #FFFFFF;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner {
|
|
||||||
height: 20px;
|
|
||||||
width: 20px;
|
|
||||||
display: inline-flex;
|
|
||||||
display: -webkit-inline-flex;
|
|
||||||
-webkit-animation: rotation .8s infinite linear;
|
|
||||||
animation: rotation .8s infinite linear;
|
|
||||||
border: 6px inset #D7D7D7;
|
|
||||||
border-radius: 50%;
|
|
||||||
float: right;
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes rotation {
|
|
||||||
from {
|
|
||||||
-ms-transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
-ms-transform: rotate(359deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes rotation {
|
|
||||||
from {
|
|
||||||
-webkit-transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
-webkit-transform: rotate(359deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes rotation {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(359deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
li.selected {
|
|
||||||
background-color: rgba(100, 100, 100, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
#effects li {
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
font-size: 16px;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#color #buttonctrl {
|
|
||||||
display: -webkit-flex;
|
|
||||||
-webkit-justify-content: space-between;
|
|
||||||
-webkit-align-items: flex-end;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: flex-end;
|
|
||||||
margin: 10px auto 35px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#color #buttonctrl > .icon {
|
|
||||||
font-size: 27px;
|
|
||||||
line-height: 100%;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#color #buttonctrl > .icon:active {
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
#color .slider {
|
|
||||||
position: relative;
|
|
||||||
width: 70%;
|
|
||||||
margin: 10px auto;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#color .slider .track {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-image: -webkit-linear-gradient(left, #000000 0%, #FFFFFF 100%);
|
|
||||||
background-image: linear-gradient(to right, #000000 0%, #FFFFFF 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
#color .slider .thumb {
|
|
||||||
background: transparent;
|
|
||||||
border: 3px solid rgba(255, 255, 255, 1.0);
|
|
||||||
width: 14px;
|
|
||||||
border-radius: 4px;
|
|
||||||
height: 28px;
|
|
||||||
position: absolute;
|
|
||||||
top: -4px;
|
|
||||||
margin-left: -7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#color .value {
|
|
||||||
outline: none;
|
|
||||||
border: 1px solid white;
|
|
||||||
font-family: Monaco, monospace;
|
|
||||||
text-align: center;
|
|
||||||
background: transparent;
|
|
||||||
width: 100px;
|
|
||||||
color: white;
|
|
||||||
font-size: 16px;
|
|
||||||
display: block;
|
|
||||||
-webkit-user-select: text;
|
|
||||||
-moz-user-select: text;
|
|
||||||
-ms-user-select: text;
|
|
||||||
user-select: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox::before {
|
|
||||||
display: table-cell;
|
|
||||||
font-family: "fontello";
|
|
||||||
content: '\e803';
|
|
||||||
height: 40px;
|
|
||||||
width: 40px;
|
|
||||||
font-size: 20px;
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected .checkbox::before {
|
|
||||||
content: '\e802';
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html manifest="manifest.appcache">
|
|
||||||
<head>
|
|
||||||
<title>Hyperion remote control</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<meta name="format-detection" content="telephone=no"/>
|
|
||||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width"/>
|
|
||||||
<link href="css/index.css" rel="stylesheet">
|
|
||||||
<link rel="apple-touch-icon" href="res/icon_128.png">
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app">
|
|
||||||
<div class="work">
|
|
||||||
<div class="container">
|
|
||||||
<div id="color" class="contentarea">
|
|
||||||
<div id="colorpicker">
|
|
||||||
<img id="colorwheelbg" src="res/colorwheel.png" width="auto" height="90%"/>
|
|
||||||
<div id="pointer"></div>
|
|
||||||
<div class="touchrect"></div>
|
|
||||||
</div>
|
|
||||||
<div class="slider" id="brightness">
|
|
||||||
<div class="track"></div>
|
|
||||||
<div class="thumb"></div>
|
|
||||||
</div>
|
|
||||||
<div id="buttonctrl">
|
|
||||||
<div class="icon" id="clear_button"></div>
|
|
||||||
<input type="text" class="value" autocomplete="off" autocorrect="off" autocapitalize="off"/>
|
|
||||||
<div class="icon" id="clearall_button"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="effects" class="contentarea">
|
|
||||||
<label class="info">Need server connection to fetch list.</label>
|
|
||||||
<ul></ul>
|
|
||||||
</div>
|
|
||||||
<div id="transform" class="contentarea">
|
|
||||||
<label class="info">Need server connection to fetch list.</label>
|
|
||||||
<div class="values"></div>
|
|
||||||
</div>
|
|
||||||
<div id="settings" class="contentarea">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
<div class="button selected" id="colorButton" data-area="color">
|
|
||||||
<div class="icon"></div>
|
|
||||||
<div class="title">Color</div>
|
|
||||||
<div class="touchrect"></div>
|
|
||||||
</div>
|
|
||||||
<div class="button" id="effectsButton" data-area="effects">
|
|
||||||
<div class="icon"></div>
|
|
||||||
<div class="title">Effects</div>
|
|
||||||
<div class="touchrect"></div>
|
|
||||||
</div>
|
|
||||||
<div class="button" id="thresholdButton" data-area="transform">
|
|
||||||
<div class="icon"></div>
|
|
||||||
<div class="title">Transform</div>
|
|
||||||
<div class="touchrect"></div>
|
|
||||||
</div>
|
|
||||||
<div class="button" id="settingsButton" data-area="settings">
|
|
||||||
<div class="icon">n</div>
|
|
||||||
<div class="title">Settings</div>
|
|
||||||
<div class="touchrect"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script src="js/vendor/require.js" data-main="js/app/main"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,37 +0,0 @@
|
|||||||
/*global define, chrome */
|
|
||||||
define(['api/LocalStorage'], function (LocalStorage) {
|
|
||||||
'use strict';
|
|
||||||
return LocalStorage.subclass(/** @lends ChromeLocalStorage.prototype */{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ChromeLocalStorage
|
|
||||||
* @classdesc Chrome's persistent storage
|
|
||||||
* @constructs
|
|
||||||
* @extends LocalStorage
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
},
|
|
||||||
|
|
||||||
get: function () {
|
|
||||||
chrome.storage.local.get('data', function (entry) {
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
this.emit('error', chrome.runtime.lastError.message);
|
|
||||||
} else {
|
|
||||||
this.emit('got', entry.data);
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
set: function (data) {
|
|
||||||
var entry = {};
|
|
||||||
entry.data = data;
|
|
||||||
chrome.storage.local.set(entry, function () {
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
this.emit('error', chrome.runtime.lastError.message);
|
|
||||||
} else {
|
|
||||||
this.emit('set');
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,57 +0,0 @@
|
|||||||
/*global chrome */
|
|
||||||
define(['api/Network'], function (Network) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
return Network.subclass(/** @lends ChromeNetwork.prototype */{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ChromeNetwork
|
|
||||||
* @extends Network
|
|
||||||
* @classdesc Network functions for chrome apps
|
|
||||||
* @constructs
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @overrides
|
|
||||||
* @param onSuccess
|
|
||||||
* @param onError
|
|
||||||
*/
|
|
||||||
getLocalInterfaces: function (onSuccess, onError) {
|
|
||||||
var ips = [];
|
|
||||||
|
|
||||||
chrome.system.network.getNetworkInterfaces(function (networkInterfaces) {
|
|
||||||
var i;
|
|
||||||
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
if (onError) {
|
|
||||||
onError('Could not get network interfaces');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < networkInterfaces.length; i++) {
|
|
||||||
// check only ipv4
|
|
||||||
if (networkInterfaces[i].address.indexOf('.') === -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ips.push(networkInterfaces[i].address);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess(ips);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @overrides
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
|
||||||
canDetectLocalAddress: function () {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
});
|
|
@ -1,307 +0,0 @@
|
|||||||
/*global chrome */
|
|
||||||
define(['lib/stapes', 'api/Socket', 'utils/Tools'], function (Stapes, Socket, tools) {
|
|
||||||
'use strict';
|
|
||||||
return Socket.subclass(/** @lends ChromeTcpSocket.prototype */{
|
|
||||||
DEBUG: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
handle: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {function}
|
|
||||||
*/
|
|
||||||
currentResponseCallback: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {function}
|
|
||||||
*/
|
|
||||||
currentErrorCallback: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporary buffer for incoming data
|
|
||||||
* @type {Uint8Array}
|
|
||||||
*/
|
|
||||||
inputBuffer: null,
|
|
||||||
inputBufferIndex: 0,
|
|
||||||
readBufferTimerId: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ChromeTcpSocket
|
|
||||||
* @extends Socket
|
|
||||||
* @constructs
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
this.inputBuffer = new Uint8Array(4096);
|
|
||||||
this.inputBufferIndex = 0;
|
|
||||||
|
|
||||||
chrome.sockets.tcp.onReceive.addListener(this.onDataReceived.bind(this));
|
|
||||||
chrome.sockets.tcp.onReceiveError.addListener(this.onError.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
create: function (onSuccess, onError) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Creating socket...');
|
|
||||||
}
|
|
||||||
chrome.sockets.tcp.create({bufferSize: 4096}, function (createInfo) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket created: ' + createInfo.socketId);
|
|
||||||
}
|
|
||||||
this.handle = createInfo.socketId;
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
isConnected: function (resultCallback) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Checking if socket is connected...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.handle) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultCallback) {
|
|
||||||
resultCallback(false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.sockets.tcp.getInfo(this.handle, function (socketInfo) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket connected: ' + socketInfo.connected);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socketInfo.connected) {
|
|
||||||
if (resultCallback) {
|
|
||||||
resultCallback(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (resultCallback) {
|
|
||||||
resultCallback(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
connect: function (server, onSuccess, onError) {
|
|
||||||
var timeoutHandle;
|
|
||||||
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Connecting to peer ' + server.address + ':' + server.port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.handle) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('Socket handle is invalid');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME for some reason chrome blocks if peer is not reachable
|
|
||||||
timeoutHandle = setTimeout(function () {
|
|
||||||
chrome.sockets.tcp.getInfo(this.handle, function (socketInfo) {
|
|
||||||
if (!socketInfo.connected) {
|
|
||||||
// let the consumer decide if to close or not?
|
|
||||||
// this.close();
|
|
||||||
onError('Could not connect to ' + server.address + ':' + server.port);
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
}.bind(this), 500);
|
|
||||||
|
|
||||||
chrome.sockets.tcp.connect(this.handle, server.address, server.port, function (result) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Connect result: ' + result);
|
|
||||||
}
|
|
||||||
clearTimeout(timeoutHandle);
|
|
||||||
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
if (onError) {
|
|
||||||
onError('Could not connect to ' + server.address + ':' + server.port);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result !== 0) {
|
|
||||||
if (onError) {
|
|
||||||
onError('Could not connect to ' + server.address + ':' + server.port);
|
|
||||||
}
|
|
||||||
} else if (onSuccess) {
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
close: function (onSuccess, onError) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Closing socket...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.handle) {
|
|
||||||
chrome.sockets.tcp.close(this.handle, function () {
|
|
||||||
this.handle = null;
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('Socket handle is invalid');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
write: function (data, onSuccess, onError) {
|
|
||||||
var dataToSend = null, dataType = typeof (data);
|
|
||||||
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] writing to socket...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.handle) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('Socket handle is invalid');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isConnected(function (connected) {
|
|
||||||
if (connected) {
|
|
||||||
if (dataType === 'string') {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('> ' + data);
|
|
||||||
}
|
|
||||||
dataToSend = tools.str2ab(data);
|
|
||||||
} else {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('> ' + tools.ab2hexstr(data));
|
|
||||||
}
|
|
||||||
dataToSend = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.sockets.tcp.send(this.handle, tools.a2ab(dataToSend), function (sendInfo) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket write result: ' + sendInfo.resultCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sendInfo.resultCode !== 0) {
|
|
||||||
onError('Socket write error: ' + sendInfo.resultCode);
|
|
||||||
} else if (onSuccess) {
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
if (onError) {
|
|
||||||
onError('No connection to peer');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
read: function (onSuccess, onError) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] reading from socket...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.handle) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('Socket handle is invalid');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isConnected(function (connected) {
|
|
||||||
if (!connected) {
|
|
||||||
this.currentResponseCallback = null;
|
|
||||||
this.currentErrorCallback = null;
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('No connection to peer');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
if (onSuccess) {
|
|
||||||
this.currentResponseCallback = onSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
this.currentErrorCallback = onError;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data receiption callback
|
|
||||||
* @private
|
|
||||||
* @param info
|
|
||||||
*/
|
|
||||||
onDataReceived: function (info) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] received data...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.socketId === this.handle && info.data) {
|
|
||||||
if (this.readBufferTimerId) {
|
|
||||||
clearTimeout(this.readBufferTimerId);
|
|
||||||
}
|
|
||||||
if (this.readTimeoutTimerId) {
|
|
||||||
clearTimeout(this.readTimeoutTimerId);
|
|
||||||
this.readTimeoutTimerId = null;
|
|
||||||
}
|
|
||||||
this.inputBuffer.set(new Uint8Array(info.data), this.inputBufferIndex);
|
|
||||||
this.inputBufferIndex += info.data.byteLength;
|
|
||||||
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('< ' + tools.ab2hexstr(info.data));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.currentResponseCallback) {
|
|
||||||
this.readBufferTimerId = setTimeout(function () {
|
|
||||||
this.currentResponseCallback(this.inputBuffer.subarray(0, this.inputBufferIndex));
|
|
||||||
this.inputBufferIndex = 0;
|
|
||||||
this.currentResponseCallback = null;
|
|
||||||
}.bind(this), 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error callback
|
|
||||||
* @private
|
|
||||||
* @param info
|
|
||||||
*/
|
|
||||||
onError: function (info) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[ERROR]: ' + info.resultCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.socketId === this.handle) {
|
|
||||||
if (this.currentErrorCallback) {
|
|
||||||
this.currentErrorCallback(info.resultCode);
|
|
||||||
this.currentErrorCallback = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
});
|
|
@ -1,49 +0,0 @@
|
|||||||
/*global define */
|
|
||||||
define(['lib/stapes'], function (Stapes) {
|
|
||||||
'use strict';
|
|
||||||
return Stapes.subclass(/** @lends LocalStorage.prototype */{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LocalStorage
|
|
||||||
* @classdesc LocalStorage handler using HTML5 localStorage
|
|
||||||
* @constructs
|
|
||||||
*
|
|
||||||
* @fires got
|
|
||||||
* @fires error
|
|
||||||
* @fires set
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets stored data
|
|
||||||
*/
|
|
||||||
get: function () {
|
|
||||||
var data;
|
|
||||||
|
|
||||||
if (!window.localStorage) {
|
|
||||||
this.emit('error', 'Local Storage not supported');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localStorage.data) {
|
|
||||||
data = JSON.parse(localStorage.data);
|
|
||||||
this.emit('got', data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores settings
|
|
||||||
* @param {object} data - Data object to store
|
|
||||||
*/
|
|
||||||
set: function (data) {
|
|
||||||
if (!window.localStorage) {
|
|
||||||
this.emit('error', 'Local Storage not supported');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.data = JSON.stringify(data);
|
|
||||||
this.emit('set');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,57 +0,0 @@
|
|||||||
/*global define */
|
|
||||||
define(['lib/stapes'], function (Stapes) {
|
|
||||||
'use strict';
|
|
||||||
return Stapes.subclass(/** @lends Network.prototype */{
|
|
||||||
detectTimerId: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Network
|
|
||||||
* @classdesc Empty network functions handler
|
|
||||||
* @constructs
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of known local interfaces (ipv4)
|
|
||||||
* @param {function(string[])} [onSuccess] - Callback to call on success
|
|
||||||
* @param {function(error:string)} [onError] - Callback to call on error
|
|
||||||
*/
|
|
||||||
getLocalInterfaces: function (onSuccess, onError) {
|
|
||||||
var ips = [], RTCPeerConnection;
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/de/docs/Web/API/RTCPeerConnection
|
|
||||||
RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;
|
|
||||||
|
|
||||||
var rtc = new RTCPeerConnection({iceServers: []});
|
|
||||||
rtc.onicecandidate = function (event) {
|
|
||||||
var parts;
|
|
||||||
|
|
||||||
if (this.detectTimerId) {
|
|
||||||
clearTimeout(this.detectTimerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.candidate) {
|
|
||||||
parts = event.candidate.candidate.split(' ');
|
|
||||||
if (ips.indexOf(parts[4]) === -1) {
|
|
||||||
console.log(event.candidate);
|
|
||||||
ips.push(parts[4]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.detectTimerId = setTimeout(function () {
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess(ips);
|
|
||||||
}
|
|
||||||
}, 200);
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
rtc.createDataChannel('');
|
|
||||||
rtc.createOffer(rtc.setLocalDescription.bind(rtc), onError);
|
|
||||||
},
|
|
||||||
|
|
||||||
canDetectLocalAddress: function () {
|
|
||||||
return window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
});
|
|
@ -1,68 +0,0 @@
|
|||||||
/*global define */
|
|
||||||
define(['lib/stapes'], function (Stapes) {
|
|
||||||
'use strict';
|
|
||||||
return Stapes.subclass(/** @lends Socket.prototype */{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Socket
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the socket
|
|
||||||
* @param onSuccess
|
|
||||||
* @param onError
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
create: function (onSuccess, onError) {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a connection is opened.
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
isConnected: function () {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to another peer
|
|
||||||
* @param {Object} peer Port object
|
|
||||||
* @param {function} [onSuccess] Callback to call on success
|
|
||||||
* @param {function(error:string)} [onError] Callback to call on error
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
connect: function (peer, onSuccess, onError) {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the current connection
|
|
||||||
* @param {function} [onSuccess] Callback to call on success
|
|
||||||
* @param {function(error:string)} [onError] Callback to call on error
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
close: function (onSuccess, onError) {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read data from the socket
|
|
||||||
* @param {function} [onSuccess] Callback to call on success
|
|
||||||
* @param {function(error:string)} [onError] Callback to call on error
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
read: function (onSuccess, onError) {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes data to the socket
|
|
||||||
* @param {string | Array} data Data to send.
|
|
||||||
* @param {function} [onSuccess] Callback to call if data was sent successfully
|
|
||||||
* @param {function(error:string)} [onError] Callback to call on error
|
|
||||||
* @abstract
|
|
||||||
*/
|
|
||||||
write: function (data, onSuccess, onError) {
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
});
|
|
@ -1,229 +0,0 @@
|
|||||||
define(['lib/stapes', 'api/Socket', 'utils/Tools'], function (Stapes, Socket, tools) {
|
|
||||||
'use strict';
|
|
||||||
return Socket.subclass(/** @lends WebSocket.prototype */{
|
|
||||||
DEBUG: false,
|
|
||||||
|
|
||||||
handle: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {function}
|
|
||||||
*/
|
|
||||||
currentResponseCallback: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {function}
|
|
||||||
*/
|
|
||||||
currentErrorCallback: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporary buffer for incoming data
|
|
||||||
* @type {Uint8Array}
|
|
||||||
*/
|
|
||||||
inputBuffer: null,
|
|
||||||
inputBufferIndex: 0,
|
|
||||||
readBufferTimerId: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class WebSocket
|
|
||||||
* @extends Socket
|
|
||||||
* @constructs
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
this.inputBuffer = new Uint8Array(4096);
|
|
||||||
this.inputBufferIndex = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
create: function (onSuccess, onError) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Creating socket...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isConnected: function (resultCallback) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Checking if socket is connected...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.handle) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultCallback) {
|
|
||||||
resultCallback(false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultCallback) {
|
|
||||||
if (this.handle.readyState === WebSocket.OPEN) {
|
|
||||||
resultCallback(true);
|
|
||||||
} else {
|
|
||||||
resultCallback(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
connect: function (server, onSuccess, onError) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Connecting to peer ' + server.address + ':' + server.port);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentErrorCallback = onError;
|
|
||||||
|
|
||||||
this.handle = new WebSocket('ws://' + server.address + ':' + server.port);
|
|
||||||
this.handle.onmessage = this.onDataReceived.bind(this);
|
|
||||||
this.handle.onclose = function () {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('onClose');
|
|
||||||
}
|
|
||||||
}.bind(this);
|
|
||||||
this.handle.onerror = function () {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[ERROR]: ');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.currentErrorCallback) {
|
|
||||||
this.currentErrorCallback('WebSocket error');
|
|
||||||
this.currentErrorCallback = null;
|
|
||||||
}
|
|
||||||
}.bind(this);
|
|
||||||
this.handle.onopen = function () {
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
close: function (onSuccess, onError) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Closing socket...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.handle) {
|
|
||||||
this.handle.close();
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('Socket handle is invalid');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
write: function (data, onSuccess, onError) {
|
|
||||||
var dataToSend = null, dataType = typeof (data);
|
|
||||||
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] writing to socket...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.handle) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] Socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('Socket handle is invalid');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isConnected(function (connected) {
|
|
||||||
if (connected) {
|
|
||||||
if (dataType === 'string') {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('> ' + data);
|
|
||||||
}
|
|
||||||
//dataToSend = tools.str2ab(data);
|
|
||||||
dataToSend = data;
|
|
||||||
} else {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('> ' + tools.ab2hexstr(data));
|
|
||||||
}
|
|
||||||
dataToSend = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentErrorCallback = onError;
|
|
||||||
this.handle.send(dataToSend);
|
|
||||||
|
|
||||||
if (onSuccess) {
|
|
||||||
onSuccess();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (onError) {
|
|
||||||
onError('No connection to peer');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
read: function (onSuccess, onError) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] reading from socket...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.handle) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] socket not created');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('Socket handle is invalid');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isConnected(function (connected) {
|
|
||||||
if (!connected) {
|
|
||||||
this.currentResponseCallback = null;
|
|
||||||
this.currentErrorCallback = null;
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
onError('No connection to peer');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
if (onSuccess) {
|
|
||||||
this.currentResponseCallback = onSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onError) {
|
|
||||||
this.currentErrorCallback = onError;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data receiption callback
|
|
||||||
* @private
|
|
||||||
* @param event
|
|
||||||
*/
|
|
||||||
onDataReceived: function (event) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('[DEBUG] received data...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.handle && event.data) {
|
|
||||||
if (this.DEBUG) {
|
|
||||||
console.log('< ' + event.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.currentResponseCallback) {
|
|
||||||
this.currentResponseCallback(tools.str2ab(event.data));
|
|
||||||
this.currentResponseCallback = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
});
|
|
@ -1,534 +0,0 @@
|
|||||||
/*global define */
|
|
||||||
define([
|
|
||||||
'lib/stapes', 'views/MainView', 'models/Settings', 'views/SettingsView', 'views/EffectsView', 'views/TransformView', 'data/ServerControl', 'api/Socket', 'api/Network'
|
|
||||||
], function (Stapes, MainView, Settings, SettingsView, EffectsView, TransformView, ServerControl, Socket, Network) {
|
|
||||||
'use strict';
|
|
||||||
var network = new Network();
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends AppController.prototype */{
|
|
||||||
/**
|
|
||||||
* @type MainView
|
|
||||||
*/
|
|
||||||
mainView: null,
|
|
||||||
/**
|
|
||||||
* @type SettingsView
|
|
||||||
*/
|
|
||||||
settingsView: null,
|
|
||||||
/**
|
|
||||||
* @type EffectsView
|
|
||||||
*/
|
|
||||||
effectsView: null,
|
|
||||||
/**
|
|
||||||
* @type TransformView
|
|
||||||
*/
|
|
||||||
transformView: null,
|
|
||||||
/**
|
|
||||||
* @type Settings
|
|
||||||
*/
|
|
||||||
settings: null,
|
|
||||||
/**
|
|
||||||
* @type ServerControl
|
|
||||||
*/
|
|
||||||
serverControl: null,
|
|
||||||
color: {
|
|
||||||
r: 25,
|
|
||||||
g: 25,
|
|
||||||
b: 25
|
|
||||||
},
|
|
||||||
effects: [],
|
|
||||||
transform: {},
|
|
||||||
selectedServer: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class AppController
|
|
||||||
* @constructs
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
this.mainView = new MainView();
|
|
||||||
this.settingsView = new SettingsView();
|
|
||||||
this.effectsView = new EffectsView();
|
|
||||||
this.transformView = new TransformView();
|
|
||||||
|
|
||||||
this.settings = new Settings();
|
|
||||||
|
|
||||||
this.bindEventHandlers();
|
|
||||||
this.mainView.setColor(this.color);
|
|
||||||
|
|
||||||
if (!network.canDetectLocalAddress()) {
|
|
||||||
this.settingsView.enableDetectButton(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do initialization
|
|
||||||
*/
|
|
||||||
init: function () {
|
|
||||||
this.settings.load();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
bindEventHandlers: function () {
|
|
||||||
this.settings.on({
|
|
||||||
'loaded': function () {
|
|
||||||
var i;
|
|
||||||
|
|
||||||
for (i = 0; i < this.settings.servers.length; i++) {
|
|
||||||
if (this.settings.servers[i].selected) {
|
|
||||||
this.selectedServer = this.settings.servers[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.settingsView.fillServerList(this.settings.servers);
|
|
||||||
|
|
||||||
if (!this.selectedServer) {
|
|
||||||
this.gotoArea('settings');
|
|
||||||
} else {
|
|
||||||
this.connectToServer(this.selectedServer);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'error': function (message) {
|
|
||||||
this.showError(message);
|
|
||||||
},
|
|
||||||
'serverAdded': function (server) {
|
|
||||||
var i;
|
|
||||||
for (i = 0; i < this.settings.servers.length; i++) {
|
|
||||||
if (this.settings.servers[i].selected) {
|
|
||||||
this.selectedServer = this.settings.servers[i];
|
|
||||||
this.connectToServer(server);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.settingsView.fillServerList(this.settings.servers);
|
|
||||||
},
|
|
||||||
'serverChanged': function (server) {
|
|
||||||
var i;
|
|
||||||
for (i = 0; i < this.settings.servers.length; i++) {
|
|
||||||
if (this.settings.servers[i].selected) {
|
|
||||||
this.selectedServer = this.settings.servers[i];
|
|
||||||
this.connectToServer(server);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.settingsView.fillServerList(this.settings.servers);
|
|
||||||
this.connectToServer(server);
|
|
||||||
},
|
|
||||||
'serverRemoved': function () {
|
|
||||||
var i, removedSelected = true;
|
|
||||||
this.settingsView.fillServerList(this.settings.servers);
|
|
||||||
|
|
||||||
for (i = 0; i < this.settings.servers.length; i++) {
|
|
||||||
if (this.settings.servers[i].selected) {
|
|
||||||
removedSelected = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (removedSelected) {
|
|
||||||
this.selectedServer = null;
|
|
||||||
if (this.serverControl) {
|
|
||||||
this.serverControl.disconnect();
|
|
||||||
}
|
|
||||||
this.effectsView.clear();
|
|
||||||
this.transformView.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.mainView.on({
|
|
||||||
'barClick': function (id) {
|
|
||||||
if (id !== 'settings') {
|
|
||||||
if (!this.selectedServer) {
|
|
||||||
this.showError('No server selected');
|
|
||||||
} else if (!this.serverControl) {
|
|
||||||
this.connectToServer(this.selectedServer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.gotoArea(id);
|
|
||||||
},
|
|
||||||
'colorChange': function (color) {
|
|
||||||
this.color = color;
|
|
||||||
|
|
||||||
if (!this.selectedServer) {
|
|
||||||
this.showError('No server selected');
|
|
||||||
} else if (!this.serverControl) {
|
|
||||||
this.connectToServer(this.selectedServer, function () {
|
|
||||||
this.serverControl.setColor(color, this.selectedServer.duration);
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
this.serverControl.setColor(color, this.selectedServer.duration);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'clear': function () {
|
|
||||||
if (!this.selectedServer) {
|
|
||||||
this.showError('No server selected');
|
|
||||||
} else if (!this.serverControl) {
|
|
||||||
this.connectToServer(this.selectedServer, function () {
|
|
||||||
this.serverControl.clear();
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
this.serverControl.clear();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'clearall': function () {
|
|
||||||
if (!this.selectedServer) {
|
|
||||||
this.showError('No server selected');
|
|
||||||
} else if (!this.serverControl) {
|
|
||||||
this.connectToServer(this.selectedServer, function () {
|
|
||||||
this.serverControl.clearall();
|
|
||||||
this.mainView.setColor({r: 0, g: 0, b: 0});
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
this.serverControl.clearall();
|
|
||||||
this.mainView.setColor({r: 0, g: 0, b: 0});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.settingsView.on({
|
|
||||||
'serverAdded': function (server) {
|
|
||||||
if (server.address && server.port) {
|
|
||||||
server.priority = server.priority || 50;
|
|
||||||
this.settings.addServer(server);
|
|
||||||
this.lockSettingsView(false);
|
|
||||||
} else {
|
|
||||||
this.showError('Invalid server data');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'serverAddCanceled': function () {
|
|
||||||
this.lockSettingsView(false);
|
|
||||||
this.settingsView.fillServerList(this.settings.servers);
|
|
||||||
},
|
|
||||||
'serverEditCanceled': function () {
|
|
||||||
this.lockSettingsView(false);
|
|
||||||
this.settingsView.fillServerList(this.settings.servers);
|
|
||||||
},
|
|
||||||
'serverSelected': function (index) {
|
|
||||||
this.lockSettingsView(false);
|
|
||||||
this.settings.setSelectedServer(index);
|
|
||||||
},
|
|
||||||
'serverRemoved': function (index) {
|
|
||||||
this.settings.removeServer(index);
|
|
||||||
},
|
|
||||||
'serverChanged': function (data) {
|
|
||||||
if (data.server.address && data.server.port) {
|
|
||||||
data.server.priority = data.server.priority || 50;
|
|
||||||
this.settings.updateServer(data.index, data.server);
|
|
||||||
this.lockSettingsView(false);
|
|
||||||
} else {
|
|
||||||
this.showError('Invalid server data');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'editServer': function (index) {
|
|
||||||
var server = this.settings.servers[index];
|
|
||||||
this.settingsView.editServer({index: index, server: server});
|
|
||||||
},
|
|
||||||
'durationChanged': function (value) {
|
|
||||||
this.settings.duration = value;
|
|
||||||
this.settings.save();
|
|
||||||
},
|
|
||||||
'detect': function () {
|
|
||||||
this.lockSettingsView(true);
|
|
||||||
this.settingsView.showWaiting(true);
|
|
||||||
this.searchForServer(function (server) {
|
|
||||||
this.settings.addServer(server);
|
|
||||||
}.bind(this), function () {
|
|
||||||
this.lockSettingsView(false);
|
|
||||||
this.settingsView.showWaiting(false);
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.effectsView.on({
|
|
||||||
'effectSelected': function (effectId) {
|
|
||||||
if (!this.serverControl) {
|
|
||||||
this.connectToServer(this.selectedServer, function () {
|
|
||||||
this.serverControl.runEffect(this.effects[parseInt(effectId)]);
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
this.serverControl.runEffect(this.effects[parseInt(effectId)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.transformView.on({
|
|
||||||
'gamma': function (data) {
|
|
||||||
if (data.r) {
|
|
||||||
this.transform.gamma[0] = data.r;
|
|
||||||
} else if (data.g) {
|
|
||||||
this.transform.gamma[1] = data.g;
|
|
||||||
} else if (data.b) {
|
|
||||||
this.transform.gamma[2] = data.b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.serverControl) {
|
|
||||||
this.serverControl.setTransform(this.transform);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'whitelevel': function (data) {
|
|
||||||
if (data.r) {
|
|
||||||
this.transform.whitelevel[0] = data.r;
|
|
||||||
} else if (data.g) {
|
|
||||||
this.transform.whitelevel[1] = data.g;
|
|
||||||
} else if (data.b) {
|
|
||||||
this.transform.whitelevel[2] = data.b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.serverControl) {
|
|
||||||
this.serverControl.setTransform(this.transform);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'blacklevel': function (data) {
|
|
||||||
if (data.r) {
|
|
||||||
this.transform.blacklevel[0] = data.r;
|
|
||||||
} else if (data.g) {
|
|
||||||
this.transform.blacklevel[1] = data.g;
|
|
||||||
} else if (data.b) {
|
|
||||||
this.transform.blacklevel[2] = data.b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.serverControl) {
|
|
||||||
this.serverControl.setTransform(this.transform);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'threshold': function (data) {
|
|
||||||
if (data.r) {
|
|
||||||
this.transform.threshold[0] = data.r;
|
|
||||||
} else if (data.g) {
|
|
||||||
this.transform.threshold[1] = data.g;
|
|
||||||
} else if (data.b) {
|
|
||||||
this.transform.threshold[2] = data.b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.serverControl) {
|
|
||||||
this.serverControl.setTransform(this.transform);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'hsv': function (data) {
|
|
||||||
if (data.valueGain) {
|
|
||||||
this.transform.valueGain = data.valueGain;
|
|
||||||
} else if (data.saturationGain) {
|
|
||||||
this.transform.saturationGain = data.saturationGain;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.serverControl) {
|
|
||||||
this.serverControl.setTransform(this.transform);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param id
|
|
||||||
*/
|
|
||||||
gotoArea: function (id) {
|
|
||||||
this.mainView.scrollToArea(id);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param server
|
|
||||||
*/
|
|
||||||
connectToServer: function (server, onConnected) {
|
|
||||||
if (this.serverControl) {
|
|
||||||
if (this.serverControl.isConnecting()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.serverControl.off();
|
|
||||||
this.serverControl.disconnect();
|
|
||||||
this.transformView.clear();
|
|
||||||
this.effectsView.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.serverControl = new ServerControl(server, Socket);
|
|
||||||
this.serverControl.on({
|
|
||||||
connected: function () {
|
|
||||||
this.serverControl.getServerInfo();
|
|
||||||
},
|
|
||||||
serverInfo: function (info) {
|
|
||||||
var index;
|
|
||||||
if (!this.selectedServer.name || this.selectedServer.name.length === 0) {
|
|
||||||
this.selectedServer.name = info.hostname;
|
|
||||||
index = this.settings.indexOfServer(this.selectedServer);
|
|
||||||
this.settings.updateServer(index, this.selectedServer);
|
|
||||||
this.settingsView.fillServerList(this.settings.servers);
|
|
||||||
}
|
|
||||||
this.effects = info.effects;
|
|
||||||
this.transform = info.transform[0];
|
|
||||||
this.updateView();
|
|
||||||
this.showStatus('Connected to ' + this.selectedServer.name);
|
|
||||||
if (onConnected) {
|
|
||||||
onConnected();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function (message) {
|
|
||||||
this.serverControl = null;
|
|
||||||
this.showError(message);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
this.serverControl.connect();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
updateView: function () {
|
|
||||||
var i, effects = [];
|
|
||||||
if (this.effects) {
|
|
||||||
for (i = 0; i < this.effects.length; i++) {
|
|
||||||
effects.push({id: i, name: this.effects[i].name});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.effectsView.clear();
|
|
||||||
this.effectsView.fillList(effects);
|
|
||||||
|
|
||||||
this.transformView.clear();
|
|
||||||
this.transformView.fillList(this.transform);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the error text
|
|
||||||
* @param {string} error - Error message
|
|
||||||
*/
|
|
||||||
showError: function (error) {
|
|
||||||
this.mainView.showError(error);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows a message
|
|
||||||
* @param {string} message - Text to show
|
|
||||||
*/
|
|
||||||
showStatus: function (message) {
|
|
||||||
this.mainView.showStatus(message);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param lock
|
|
||||||
*/
|
|
||||||
lockSettingsView: function (lock) {
|
|
||||||
if (network.canDetectLocalAddress()) {
|
|
||||||
this.settingsView.enableDetectButton(!lock);
|
|
||||||
}
|
|
||||||
this.settingsView.lockList(lock);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param onFound
|
|
||||||
* @param onEnd
|
|
||||||
*/
|
|
||||||
searchForServer: function (onFound, onEnd) {
|
|
||||||
network.getLocalInterfaces(function (ips) {
|
|
||||||
if (ips.length === 0) {
|
|
||||||
onEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkInterface (localInterfaceAddress, ciOnFinished) {
|
|
||||||
var index, ipParts, addr;
|
|
||||||
|
|
||||||
index = 1;
|
|
||||||
ipParts = localInterfaceAddress.split('.');
|
|
||||||
ipParts[3] = index;
|
|
||||||
addr = ipParts.join('.');
|
|
||||||
|
|
||||||
function checkAddressRange (startAddress, count, carOnFinished) {
|
|
||||||
var ipParts, i, addr, cbCounter = 0, last;
|
|
||||||
|
|
||||||
function checkAddress (address, port, caOnFinished) {
|
|
||||||
var server = new ServerControl({'address': address, 'port': port}, Socket);
|
|
||||||
server.on({
|
|
||||||
'error': function () {
|
|
||||||
server.disconnect();
|
|
||||||
caOnFinished();
|
|
||||||
},
|
|
||||||
'connected': function () {
|
|
||||||
server.getServerInfo();
|
|
||||||
},
|
|
||||||
'serverInfo': function (result) {
|
|
||||||
var serverInfo = {
|
|
||||||
'address': address,
|
|
||||||
'port': port,
|
|
||||||
'priority': 50
|
|
||||||
};
|
|
||||||
server.disconnect();
|
|
||||||
|
|
||||||
if (result.hostname) {
|
|
||||||
serverInfo.name = result.hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
caOnFinished(serverInfo);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
server.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkAddressDoneCb (serverInfo) {
|
|
||||||
var ipParts, nextAddr;
|
|
||||||
|
|
||||||
if (serverInfo && onFound) {
|
|
||||||
onFound(serverInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
cbCounter++;
|
|
||||||
if (cbCounter === count) {
|
|
||||||
ipParts = startAddress.split('.');
|
|
||||||
ipParts[3] = parseInt(ipParts[3]) + count;
|
|
||||||
nextAddr = ipParts.join('.');
|
|
||||||
carOnFinished(nextAddr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ipParts = startAddress.split('.');
|
|
||||||
last = parseInt(ipParts[3]);
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
ipParts[3] = last + i;
|
|
||||||
addr = ipParts.join('.');
|
|
||||||
|
|
||||||
checkAddress(addr, 19444, checkAddressDoneCb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkAddressRangeCb (nextAddr) {
|
|
||||||
var ipParts, count = 64, lastPart;
|
|
||||||
|
|
||||||
ipParts = nextAddr.split('.');
|
|
||||||
lastPart = parseInt(ipParts[3]);
|
|
||||||
if (lastPart === 255) {
|
|
||||||
ciOnFinished();
|
|
||||||
return;
|
|
||||||
} else if (lastPart + 64 > 254) {
|
|
||||||
count = 255 - lastPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkAddressRange(nextAddr, count, checkAddressRangeCb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do search in chunks because the dispatcher used in the ios socket plugin can handle only 64 threads
|
|
||||||
checkAddressRange(addr, 64, checkAddressRangeCb);
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkInterfaceCb () {
|
|
||||||
if (ips.length === 0) {
|
|
||||||
onEnd();
|
|
||||||
} else {
|
|
||||||
checkInterface(ips.pop(), checkInterfaceCb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkInterface(ips.pop(), checkInterfaceCb);
|
|
||||||
|
|
||||||
}.bind(this), function (error) {
|
|
||||||
this.showError(error);
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,201 +0,0 @@
|
|||||||
/*global define */
|
|
||||||
define(['lib/stapes', 'utils/Tools'], function (Stapes, tools) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends ServerControl.prototype */{
|
|
||||||
/** @type Socket */
|
|
||||||
socket: null,
|
|
||||||
server: null,
|
|
||||||
connecting: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ServerControl
|
|
||||||
* @classdesc Interface for the hyperion server control. All commands are sent directly to hyperion's server.
|
|
||||||
* @constructs
|
|
||||||
* @param {object} server - Hyperion server parameter
|
|
||||||
* @param {string} server.address - Server address
|
|
||||||
* @param {number} server.port - Hyperion server port
|
|
||||||
* @param {function} Socket - constructor of the socket to use for communication
|
|
||||||
*
|
|
||||||
* @fires connected
|
|
||||||
* @fires error
|
|
||||||
* @fires serverInfo
|
|
||||||
* @fires cmdSent
|
|
||||||
*/
|
|
||||||
constructor: function (server, Socket) {
|
|
||||||
this.server = server;
|
|
||||||
this.socket = new Socket();
|
|
||||||
this.connecting = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to connect to the server
|
|
||||||
*/
|
|
||||||
connect: function () {
|
|
||||||
if (!this.server) {
|
|
||||||
this.emit('error', 'Missing server info');
|
|
||||||
} else {
|
|
||||||
this.connecting = true;
|
|
||||||
this.socket.create(function () {
|
|
||||||
this.socket.connect(this.server, function () {
|
|
||||||
this.emit('connected');
|
|
||||||
this.connecting = false;
|
|
||||||
}.bind(this), function (error) {
|
|
||||||
this.socket.close();
|
|
||||||
this.emit('error', error);
|
|
||||||
this.connecting = false;
|
|
||||||
}.bind(this));
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect from the server
|
|
||||||
*/
|
|
||||||
disconnect: function () {
|
|
||||||
this.socket.close();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the color command to the server
|
|
||||||
* @param {object} color - Color to set
|
|
||||||
* @param {number} color.r - Red value
|
|
||||||
* @param {number} color.g - Green value
|
|
||||||
* @param {number} color.b - Blue value
|
|
||||||
* @param {number} duration - Duration in seconds
|
|
||||||
*/
|
|
||||||
setColor: function (color, duration) {
|
|
||||||
var intColor, cmd;
|
|
||||||
|
|
||||||
intColor = [
|
|
||||||
Math.floor(color.r), Math.floor(color.g), Math.floor(color.b)
|
|
||||||
];
|
|
||||||
cmd = {
|
|
||||||
command: 'color',
|
|
||||||
color: intColor,
|
|
||||||
priority: this.server.priority
|
|
||||||
};
|
|
||||||
|
|
||||||
if (duration) {
|
|
||||||
cmd.duration = duration * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sendCommand(cmd);
|
|
||||||
},
|
|
||||||
|
|
||||||
clear: function () {
|
|
||||||
var cmd = {
|
|
||||||
command: 'clear',
|
|
||||||
priority: this.server.priority
|
|
||||||
};
|
|
||||||
this.sendCommand(cmd);
|
|
||||||
},
|
|
||||||
|
|
||||||
clearall: function () {
|
|
||||||
var cmd = {
|
|
||||||
command: 'clearall'
|
|
||||||
};
|
|
||||||
this.sendCommand(cmd);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a command to rund specified effect
|
|
||||||
* @param {object} effect - Effect object
|
|
||||||
*/
|
|
||||||
runEffect: function (effect) {
|
|
||||||
var cmd;
|
|
||||||
|
|
||||||
if (!effect) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = {
|
|
||||||
command: 'effect',
|
|
||||||
effect: {
|
|
||||||
name: effect.name,
|
|
||||||
args: effect.args
|
|
||||||
},
|
|
||||||
priority: this.server.priority
|
|
||||||
};
|
|
||||||
this.sendCommand(cmd);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a command for color transformation
|
|
||||||
* @param {object} transform
|
|
||||||
*/
|
|
||||||
setTransform: function (transform) {
|
|
||||||
var cmd;
|
|
||||||
|
|
||||||
if (!transform) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = {
|
|
||||||
'command': 'transform',
|
|
||||||
'transform': transform
|
|
||||||
};
|
|
||||||
|
|
||||||
this.sendCommand(cmd);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param command
|
|
||||||
*/
|
|
||||||
sendCommand: function (command) {
|
|
||||||
var data;
|
|
||||||
|
|
||||||
if (!command) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof command === 'string') {
|
|
||||||
data = command;
|
|
||||||
} else {
|
|
||||||
data = JSON.stringify(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.socket.isConnected(function (connected) {
|
|
||||||
if (connected) {
|
|
||||||
this.socket.write(data + '\n', function () {
|
|
||||||
this.emit('cmdSent', command);
|
|
||||||
}.bind(this), function (error) {
|
|
||||||
this.emit('error', error);
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
this.emit('error', 'No server connection');
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the information about the hyperion server
|
|
||||||
*/
|
|
||||||
getServerInfo: function () {
|
|
||||||
var cmd = {command: 'serverinfo'};
|
|
||||||
|
|
||||||
this.socket.isConnected(function (connected) {
|
|
||||||
if (connected) {
|
|
||||||
this.socket.write(JSON.stringify(cmd) + '\n', function () {
|
|
||||||
this.socket.read(function (result) {
|
|
||||||
var dataobj, str = tools.ab2str(result);
|
|
||||||
dataobj = JSON.parse(str);
|
|
||||||
this.emit('serverInfo', dataobj.info);
|
|
||||||
}.bind(this), function (error) {
|
|
||||||
this.emit('error', error);
|
|
||||||
}.bind(this));
|
|
||||||
}.bind(this), function (error) {
|
|
||||||
this.emit('error', error);
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
this.emit('error', 'No server connection');
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
isConnecting: function () {
|
|
||||||
return this.connecting;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,150 +0,0 @@
|
|||||||
/*global require, requirejs */
|
|
||||||
|
|
||||||
requirejs.config({
|
|
||||||
baseUrl: 'js/app',
|
|
||||||
paths: {
|
|
||||||
'lib': '../vendor'
|
|
||||||
},
|
|
||||||
map: {
|
|
||||||
'controllers/AppController': {
|
|
||||||
'api/Socket': 'api/WebSocket'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.addPointerDownHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.addEventListener('touchstart', handler, false);
|
|
||||||
dom.addEventListener('mousedown', handler, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.removePointerDownHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.removeEventListener('touchstart', handler, false);
|
|
||||||
dom.removeEventListener('mousedown', handler, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.addPointerUpHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.addEventListener('touchend', handler, false);
|
|
||||||
dom.addEventListener('mouseup', handler, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.removePointerUpHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.removeEventListener('touchend', handler, false);
|
|
||||||
dom.removeEventListener('mouseup', handler, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.addPointerMoveHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.addEventListener('touchmove', handler, false);
|
|
||||||
dom.addEventListener('mousemove', handler, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.removePointerMoveHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.removeEventListener('touchmove', handler, false);
|
|
||||||
dom.removeEventListener('mousemove', handler, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.addClickHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
var toFire = false;
|
|
||||||
|
|
||||||
dom.addEventListener('touchstart', function (event) {
|
|
||||||
if (event.touches.length > 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
toFire = true;
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('touchmove', function () {
|
|
||||||
toFire = false;
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('touchend', function (event) {
|
|
||||||
var focused;
|
|
||||||
if (toFire) {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
|
|
||||||
focused = document.querySelector(':focus');
|
|
||||||
|
|
||||||
if (focused && event.target !== focused) {
|
|
||||||
focused.blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.target.tagName !== 'INPUT') {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('click', function () {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
}, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
function checkInstallFirefoxOS() {
|
|
||||||
'use strict';
|
|
||||||
var manifest_url, installCheck;
|
|
||||||
|
|
||||||
manifest_url = [location.protocol, '//', location.host, location.pathname.replace('index.html',''), 'manifest.webapp'].join('');
|
|
||||||
installCheck = navigator.mozApps.checkInstalled(manifest_url);
|
|
||||||
|
|
||||||
installCheck.onerror = function() {
|
|
||||||
alert('Error calling checkInstalled: ' + installCheck.error.name);
|
|
||||||
};
|
|
||||||
|
|
||||||
installCheck.onsuccess = function() {
|
|
||||||
var installLoc;
|
|
||||||
if(!installCheck.result) {
|
|
||||||
if (confirm('Do you want to install hyperion remote contorl on your device?')) {
|
|
||||||
installLoc = navigator.mozApps.install(manifest_url);
|
|
||||||
installLoc.onsuccess = function(data) {
|
|
||||||
};
|
|
||||||
installLoc.onerror = function() {
|
|
||||||
alert(installLoc.error.name);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
require(['controllers/AppController'], function (AppController) {
|
|
||||||
'use strict';
|
|
||||||
var app = new AppController();
|
|
||||||
app.init();
|
|
||||||
if (navigator.mozApps && navigator.userAgent.indexOf('Mozilla/5.0 (Mobile;') !== -1) {
|
|
||||||
checkInstallFirefoxOS();
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,108 +0,0 @@
|
|||||||
/*global require, requirejs */
|
|
||||||
|
|
||||||
requirejs.config({
|
|
||||||
baseUrl: '../js/app',
|
|
||||||
paths: {
|
|
||||||
'lib': '../vendor'
|
|
||||||
},
|
|
||||||
map: {
|
|
||||||
'controllers/AppController': {
|
|
||||||
'api/Socket': 'api/ChromeTcpSocket',
|
|
||||||
'api/Network': 'api/ChromeNetwork'
|
|
||||||
},
|
|
||||||
'models/Settings': {
|
|
||||||
'api/LocalStorage': 'api/ChromeLocalStorage'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.addPointerDownHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.addEventListener('touchstart', function (event) {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
event.preventDefault();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('mousedown', function () {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
}, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.addPointerUpHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.addEventListener('touchend', function (event) {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
event.preventDefault();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('mouseup', function () {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
}, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.addPointerMoveHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
dom.addEventListener('touchmove', function (event) {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
event.preventDefault();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('mousemove', function () {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
}, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {HTMLElement} dom
|
|
||||||
* @param {function} handler
|
|
||||||
*/
|
|
||||||
window.addClickHandler = function (dom, handler) {
|
|
||||||
'use strict';
|
|
||||||
var toFire = false;
|
|
||||||
|
|
||||||
dom.addEventListener('touchstart', function (event) {
|
|
||||||
if (event.touches.length > 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
toFire = true;
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('touchmove', function () {
|
|
||||||
toFire = false;
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('touchend', function (event) {
|
|
||||||
if (toFire) {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
if (event.target.tagName !== 'INPUT') {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
dom.addEventListener('click', function () {
|
|
||||||
handler.apply(this, arguments);
|
|
||||||
}, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
require(['controllers/AppController'], function (AppController) {
|
|
||||||
'use strict';
|
|
||||||
var app = new AppController();
|
|
||||||
app.init();
|
|
||||||
});
|
|
@ -1,124 +0,0 @@
|
|||||||
/*global define */
|
|
||||||
define(['lib/stapes', 'api/LocalStorage'], function (Stapes, LocalStorage) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends Settings.prototype */{
|
|
||||||
storage: null, servers: [],
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Settings
|
|
||||||
* @classdesc Local application settings
|
|
||||||
* @constructs
|
|
||||||
* @fires saved
|
|
||||||
* @fires loaded
|
|
||||||
* @fires error
|
|
||||||
* @fires serverAdded
|
|
||||||
* @fires serverChanged
|
|
||||||
* @fires serverRemoved
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
this.storage = new LocalStorage();
|
|
||||||
this.storage.on({
|
|
||||||
error: function (message) {
|
|
||||||
this.emit('error', message);
|
|
||||||
}, got: function (settings) {
|
|
||||||
if (settings) {
|
|
||||||
this.servers = settings.servers || [];
|
|
||||||
}
|
|
||||||
this.emit('loaded');
|
|
||||||
}, set: function () {
|
|
||||||
this.emit('saved');
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save current settings
|
|
||||||
*/
|
|
||||||
save: function () {
|
|
||||||
this.storage.set({
|
|
||||||
servers: this.servers
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads persistent settings
|
|
||||||
*/
|
|
||||||
load: function () {
|
|
||||||
this.storage.get();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a server definition
|
|
||||||
* @param {object} server - Server information
|
|
||||||
*/
|
|
||||||
addServer: function (server) {
|
|
||||||
if (this.indexOfServer(server) === -1) {
|
|
||||||
if (this.servers.length === 0) {
|
|
||||||
server.selected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.servers.push(server);
|
|
||||||
this.save();
|
|
||||||
this.emit('serverAdded', server);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a server as a default server
|
|
||||||
* @param {number} index - Index of the server in the server list to set as default one
|
|
||||||
*/
|
|
||||||
setSelectedServer: function (index) {
|
|
||||||
var i;
|
|
||||||
for (i = 0; i < this.servers.length; i++) {
|
|
||||||
delete this.servers[i].selected;
|
|
||||||
}
|
|
||||||
this.servers[index].selected = true;
|
|
||||||
this.save();
|
|
||||||
this.emit('serverChanged', this.servers[index]);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a server from the list
|
|
||||||
* @param {number} index - Index of the server in the list to remove
|
|
||||||
*/
|
|
||||||
removeServer: function (index) {
|
|
||||||
this.servers.splice(index, 1);
|
|
||||||
this.save();
|
|
||||||
this.emit('serverRemoved');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update server information
|
|
||||||
* @param {number} index - Index of the server to update
|
|
||||||
* @param {object} server - New server information
|
|
||||||
*/
|
|
||||||
updateServer: function (index, server) {
|
|
||||||
if (index >= 0 && index < this.servers.length) {
|
|
||||||
this.servers[index] = server;
|
|
||||||
this.save();
|
|
||||||
this.emit('serverChanged', server);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the server in the list.
|
|
||||||
* @param {object} server - Server to search index for
|
|
||||||
* @returns {number} - Index of the server in the list. -1 if server not found
|
|
||||||
*/
|
|
||||||
indexOfServer: function (server) {
|
|
||||||
var i, tmp;
|
|
||||||
|
|
||||||
for (i = 0; i < this.servers.length; i++) {
|
|
||||||
tmp = this.servers[i];
|
|
||||||
|
|
||||||
if (tmp.port === server.port && tmp.address === server.address) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,56 +0,0 @@
|
|||||||
define([], function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Convert a string to ArrayBuffer
|
|
||||||
* @param {string} str String to convert
|
|
||||||
* @returns {ArrayBuffer} Result
|
|
||||||
*/
|
|
||||||
str2ab: function (str) {
|
|
||||||
var i, buf = new ArrayBuffer(str.length), bufView = new Uint8Array(buf);
|
|
||||||
for (i = 0; i < str.length; i++) {
|
|
||||||
bufView[i] = str.charCodeAt(i);
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert an array to ArrayBuffer
|
|
||||||
* @param array
|
|
||||||
* @returns {ArrayBuffer} Result
|
|
||||||
*/
|
|
||||||
a2ab: function (array) {
|
|
||||||
return new Uint8Array(array).buffer;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert ArrayBuffer to string
|
|
||||||
* @param {ArrayBuffer} buffer Buffer to convert
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
ab2hexstr: function (buffer) {
|
|
||||||
var i, str = '', ua = new Uint8Array(buffer);
|
|
||||||
for (i = 0; i < ua.length; i++) {
|
|
||||||
str += this.b2hexstr(ua[i]);
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert byte to hexstr.
|
|
||||||
* @param {number} byte Byte to convert
|
|
||||||
*/
|
|
||||||
b2hexstr: function (byte) {
|
|
||||||
return ('00' + byte.toString(16)).substr(-2);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ArrayBuffer} buffer
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
ab2str: function (buffer) {
|
|
||||||
return String.fromCharCode.apply(null, new Uint8Array(buffer));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,64 +0,0 @@
|
|||||||
/**
|
|
||||||
* hyperion remote
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
define(['lib/stapes'], function (Stapes) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends EffectsView.prototype */{
|
|
||||||
/**
|
|
||||||
* @class EffectsView
|
|
||||||
* @constructs
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
this.bindEventHandlers();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
bindEventHandlers: function () {
|
|
||||||
window.addClickHandler(document.querySelector('#effects ul'), function (event) {
|
|
||||||
var selected = event.target.parentNode.querySelector('.selected');
|
|
||||||
if (selected) {
|
|
||||||
selected.classList.remove('selected');
|
|
||||||
}
|
|
||||||
event.target.classList.add('selected');
|
|
||||||
this.emit('effectSelected', event.target.dataset.id);
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the list
|
|
||||||
*/
|
|
||||||
clear: function () {
|
|
||||||
document.querySelector('#effects ul').innerHTML = '';
|
|
||||||
document.querySelector('#effects .info').classList.add('hidden');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill the list
|
|
||||||
* @param {object} effects - Object containing effect information
|
|
||||||
*/
|
|
||||||
fillList: function (effects) {
|
|
||||||
var dom, el, i;
|
|
||||||
|
|
||||||
dom = document.createDocumentFragment();
|
|
||||||
|
|
||||||
for (i = 0; i < effects.length; i++) {
|
|
||||||
el = document.createElement('li');
|
|
||||||
el.innerHTML = effects[i].name;
|
|
||||||
el.dataset.id = effects[i].id;
|
|
||||||
dom.appendChild(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.querySelector('#effects ul').appendChild(dom);
|
|
||||||
|
|
||||||
if (effects.length === 0) {
|
|
||||||
document.querySelector('#effects .info').classList.remove('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,402 +0,0 @@
|
|||||||
define([
|
|
||||||
'lib/stapes',
|
|
||||||
'lib/tinycolor',
|
|
||||||
'utils/Tools',
|
|
||||||
'views/Slider'
|
|
||||||
], function (Stapes, Tinycolor, tools, Slider) {
|
|
||||||
'use strict';
|
|
||||||
var timer;
|
|
||||||
|
|
||||||
function showMessageField (text, type) {
|
|
||||||
var dom, wrapper;
|
|
||||||
|
|
||||||
dom = document.querySelector('.work .msg');
|
|
||||||
|
|
||||||
if (!dom) {
|
|
||||||
dom = document.createElement('div');
|
|
||||||
dom.classList.add('msg');
|
|
||||||
dom.classList.add(type);
|
|
||||||
wrapper = document.createElement('div');
|
|
||||||
wrapper.classList.add('wrapper_msg');
|
|
||||||
wrapper.classList.add('invisible');
|
|
||||||
wrapper.appendChild(dom);
|
|
||||||
|
|
||||||
document.querySelector('.work').appendChild(wrapper);
|
|
||||||
setTimeout(function () {
|
|
||||||
wrapper.classList.remove('invisible');
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dom.classList.contains(type)) {
|
|
||||||
dom.className = 'msg';
|
|
||||||
dom.classList.add(type);
|
|
||||||
}
|
|
||||||
dom.innerHTML = text;
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
timer = setTimeout(function () {
|
|
||||||
var error = document.querySelector('.work .wrapper_msg');
|
|
||||||
if (error) {
|
|
||||||
error.parentNode.removeChild(error);
|
|
||||||
}
|
|
||||||
}, 1600);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends MainView.prototype*/{
|
|
||||||
pointer: null,
|
|
||||||
colorpicker: null,
|
|
||||||
slider: null,
|
|
||||||
sliderinput: null,
|
|
||||||
cpradius: 0,
|
|
||||||
cpcenter: 0,
|
|
||||||
drag: false,
|
|
||||||
color: null,
|
|
||||||
brightness: 1.0,
|
|
||||||
inputbox: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class MainView
|
|
||||||
* @construct
|
|
||||||
* @fires barClick
|
|
||||||
* @fires colorChange
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
var ev;
|
|
||||||
this.pointer = document.querySelector('#colorpicker #pointer');
|
|
||||||
this.colorpicker = document.querySelector('#colorpicker #colorwheelbg');
|
|
||||||
this.slider = new Slider({
|
|
||||||
element: document.getElementById('brightness'),
|
|
||||||
min: 0,
|
|
||||||
max: 1,
|
|
||||||
step: 0.02,
|
|
||||||
value: 1
|
|
||||||
});
|
|
||||||
this.inputbox = document.querySelector('#color input.value');
|
|
||||||
|
|
||||||
this.cpradius = this.colorpicker.offsetWidth / 2;
|
|
||||||
this.cpcenter = this.colorpicker.offsetLeft + this.cpradius;
|
|
||||||
|
|
||||||
this.bindEventHandlers();
|
|
||||||
|
|
||||||
ev = document.createEvent('Event');
|
|
||||||
ev.initEvent('resize', true, true);
|
|
||||||
window.dispatchEvent(ev);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
bindEventHandlers: function () {
|
|
||||||
var cptouchrect;
|
|
||||||
|
|
||||||
window.addEventListener('resize', function () {
|
|
||||||
var attrW, attrH, side, w = this.colorpicker.parentNode.clientWidth, h = this.colorpicker.parentNode.clientHeight;
|
|
||||||
|
|
||||||
attrW = this.colorpicker.getAttribute('width');
|
|
||||||
attrH = this.colorpicker.getAttribute('height');
|
|
||||||
side = attrW === 'auto' ? attrH : attrW;
|
|
||||||
if (w > h) {
|
|
||||||
if (attrH !== side) {
|
|
||||||
this.colorpicker.setAttribute('height', side);
|
|
||||||
this.colorpicker.setAttribute('width', 'auto');
|
|
||||||
}
|
|
||||||
} else if (attrW !== side) {
|
|
||||||
this.colorpicker.setAttribute('height', 'auto');
|
|
||||||
this.colorpicker.setAttribute('width', side);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cpradius = this.colorpicker.offsetWidth / 2;
|
|
||||||
this.cpcenter = this.colorpicker.offsetLeft + this.cpradius;
|
|
||||||
if (this.color) {
|
|
||||||
this.updatePointer();
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
window.addClickHandler(document.querySelector('.footer'), function (event) {
|
|
||||||
this.emit('barClick', event.target.parentNode.dataset.area);
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
|
|
||||||
this.slider.on('changeValue', function (value) {
|
|
||||||
this.brightness = value.value;
|
|
||||||
this.updateInput();
|
|
||||||
this.fireColorEvent();
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.inputbox.addEventListener('input', function (event) {
|
|
||||||
var bright, rgb = new Tinycolor(event.target.value).toRgb();
|
|
||||||
|
|
||||||
if (rgb.r === 0 && rgb.g === 0 && rgb.b === 0) {
|
|
||||||
this.brightness = 0;
|
|
||||||
this.color = new Tinycolor({
|
|
||||||
r: 0xff,
|
|
||||||
g: 0xff,
|
|
||||||
b: 0xff
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
bright = Math.max(rgb.r, rgb.g, rgb.b) / 256;
|
|
||||||
rgb.r = Math.round(rgb.r / bright);
|
|
||||||
rgb.g = Math.round(rgb.g / bright);
|
|
||||||
rgb.b = Math.round(rgb.b / bright);
|
|
||||||
this.brightness = bright;
|
|
||||||
this.color = new Tinycolor(rgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fireColorEvent();
|
|
||||||
this.updatePointer();
|
|
||||||
this.updateSlider();
|
|
||||||
}.bind(this), false);
|
|
||||||
|
|
||||||
this.inputbox.addEventListener('keydown', function (event) {
|
|
||||||
switch (event.keyCode) {
|
|
||||||
case 8:
|
|
||||||
case 9:
|
|
||||||
case 16:
|
|
||||||
case 37:
|
|
||||||
case 38:
|
|
||||||
case 39:
|
|
||||||
case 40:
|
|
||||||
case 46:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (event.target.value.length >= 6 && (event.target.selectionEnd - event.target.selectionStart) === 0) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
} else if (event.keyCode < 48 || event.keyCode > 71) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
cptouchrect = document.querySelector('#colorpicker .touchrect');
|
|
||||||
window.addPointerDownHandler(cptouchrect, function (event) {
|
|
||||||
this.leaveInput();
|
|
||||||
this.drag = true;
|
|
||||||
this.handleEvent(event);
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
window.addPointerMoveHandler(cptouchrect, function (event) {
|
|
||||||
if (this.drag) {
|
|
||||||
this.handleEvent(event);
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
window.addPointerUpHandler(cptouchrect, function () {
|
|
||||||
this.drag = false;
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
window.addClickHandler(document.querySelector('#clear_button'), function () {
|
|
||||||
this.emit('clear');
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
window.addClickHandler(document.querySelector('#clearall_button'), function () {
|
|
||||||
this.emit('clearall');
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param event
|
|
||||||
*/
|
|
||||||
handleEvent: function (event) {
|
|
||||||
var point, x, y;
|
|
||||||
|
|
||||||
if (event.touches) {
|
|
||||||
x = event.touches[0].clientX;
|
|
||||||
y = event.touches[0].clientY;
|
|
||||||
} else {
|
|
||||||
x = event.clientX;
|
|
||||||
y = event.clientY;
|
|
||||||
}
|
|
||||||
point = this.getCirclePoint(x, y);
|
|
||||||
this.color = this.getColorFromPoint(point);
|
|
||||||
|
|
||||||
this.updatePointer();
|
|
||||||
this.updateSlider();
|
|
||||||
this.updateInput();
|
|
||||||
|
|
||||||
this.fireColorEvent();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param {number} x
|
|
||||||
* @param {number} y
|
|
||||||
* @returns {{x: number, y: number}}
|
|
||||||
*/
|
|
||||||
getCirclePoint: function (x, y) {
|
|
||||||
var p = {
|
|
||||||
x: x,
|
|
||||||
y: y
|
|
||||||
}, c = {
|
|
||||||
x: this.colorpicker.offsetLeft + this.cpradius,
|
|
||||||
y: this.colorpicker.offsetTop + this.cpradius
|
|
||||||
}, n;
|
|
||||||
|
|
||||||
n = Math.sqrt(Math.pow((x - c.x), 2) + Math.pow((y - c.y), 2));
|
|
||||||
|
|
||||||
if (n > this.cpradius) {
|
|
||||||
p.x = (c.x) + this.cpradius * ((x - c.x) / n);
|
|
||||||
p.y = (c.y) + this.cpradius * ((y - c.y) / n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param {{x: number, y: number}} p
|
|
||||||
* @returns {Tinycolor}
|
|
||||||
*/
|
|
||||||
getColorFromPoint: function (p) {
|
|
||||||
var h, t, s, x, y;
|
|
||||||
x = p.x - this.colorpicker.offsetLeft - this.cpradius;
|
|
||||||
y = this.cpradius - p.y + this.colorpicker.offsetTop;
|
|
||||||
t = Math.atan2(y, x);
|
|
||||||
h = (t * (180 / Math.PI) + 360) % 360;
|
|
||||||
s = Math.min(Math.sqrt(x * x + y * y) / this.cpradius, 1);
|
|
||||||
|
|
||||||
return new Tinycolor({
|
|
||||||
h: h,
|
|
||||||
s: s,
|
|
||||||
v: 1
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param color
|
|
||||||
* @returns {{x: number, y: number}}
|
|
||||||
*/
|
|
||||||
getPointFromColor: function (color) {
|
|
||||||
var t, x, y, p = {};
|
|
||||||
|
|
||||||
t = color.h * (Math.PI / 180);
|
|
||||||
y = Math.sin(t) * this.cpradius * color.s;
|
|
||||||
x = Math.cos(t) * this.cpradius * color.s;
|
|
||||||
|
|
||||||
p.x = Math.round(x + this.colorpicker.offsetLeft + this.cpradius);
|
|
||||||
p.y = Math.round(this.cpradius - y + this.colorpicker.offsetTop);
|
|
||||||
|
|
||||||
return p;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
fireColorEvent: function () {
|
|
||||||
var rgb = this.color.toRgb();
|
|
||||||
rgb.r = Math.round(rgb.r * this.brightness);
|
|
||||||
rgb.g = Math.round(rgb.g * this.brightness);
|
|
||||||
rgb.b = Math.round(rgb.b * this.brightness);
|
|
||||||
this.emit('colorChange', rgb);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param rgb
|
|
||||||
*/
|
|
||||||
setColor: function (rgb) {
|
|
||||||
var bright;
|
|
||||||
|
|
||||||
if (rgb.r === 0 && rgb.g === 0 && rgb.b === 0) {
|
|
||||||
this.brightness = 0;
|
|
||||||
this.color = new Tinycolor({
|
|
||||||
r: 0xff,
|
|
||||||
g: 0xff,
|
|
||||||
b: 0xff
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
bright = Math.max(rgb.r, rgb.g, rgb.b) / 256;
|
|
||||||
rgb.r = Math.round(rgb.r / bright);
|
|
||||||
rgb.g = Math.round(rgb.g / bright);
|
|
||||||
rgb.b = Math.round(rgb.b / bright);
|
|
||||||
this.brightness = bright;
|
|
||||||
this.color = new Tinycolor(rgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updatePointer();
|
|
||||||
this.updateSlider();
|
|
||||||
this.updateInput();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
updateSlider: function () {
|
|
||||||
this.slider.setValue(this.brightness);
|
|
||||||
this.slider.dom.style.backgroundImage = '-webkit-linear-gradient(left, #000000 0%, ' + this.color.toHexString() + ' 100%)';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
updatePointer: function () {
|
|
||||||
var point = this.getPointFromColor(this.color.toHsv());
|
|
||||||
|
|
||||||
this.pointer.style.left = (point.x - this.pointer.offsetWidth / 2) + 'px';
|
|
||||||
this.pointer.style.top = (point.y - this.pointer.offsetHeight / 2) + 'px';
|
|
||||||
this.pointer.style.backgroundColor = this.color.toHexString();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
updateInput: function () {
|
|
||||||
var rgb = this.color.toRgb();
|
|
||||||
rgb.r = Math.round(rgb.r * this.brightness);
|
|
||||||
rgb.g = Math.round(rgb.g * this.brightness);
|
|
||||||
rgb.b = Math.round(rgb.b * this.brightness);
|
|
||||||
|
|
||||||
this.inputbox.value = this.inputbox.style.backgroundColor = (
|
|
||||||
'#'
|
|
||||||
+ tools.b2hexstr(rgb.r)
|
|
||||||
+ tools.b2hexstr(rgb.g)
|
|
||||||
+ tools.b2hexstr(rgb.b)
|
|
||||||
);
|
|
||||||
this.inputbox.style.color = (rgb.r + rgb.g + rgb.b) < 384 ? '#fff' : '#000';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scroll to the specific tab content
|
|
||||||
* @param {string} id - Id of the tab to scroll to
|
|
||||||
*/
|
|
||||||
scrollToArea: function (id) {
|
|
||||||
var area, index;
|
|
||||||
document.querySelector('.footer .selected').classList.remove('selected');
|
|
||||||
document.querySelector('.footer .button[data-area =' + id + ']').classList.add('selected');
|
|
||||||
|
|
||||||
area = document.getElementById(id);
|
|
||||||
index = area.offsetLeft / area.clientWidth;
|
|
||||||
area.parentNode.style.left = (-index * 100) + '%';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows a status message
|
|
||||||
* @param {string} message - Text to show
|
|
||||||
*/
|
|
||||||
showStatus: function (message) {
|
|
||||||
showMessageField(message, 'status');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the error text
|
|
||||||
* @param {string} error - Error message
|
|
||||||
*/
|
|
||||||
showError: function (error) {
|
|
||||||
showMessageField(error, 'error');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
leaveInput: function () {
|
|
||||||
this.inputbox.blur();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,199 +0,0 @@
|
|||||||
define(['lib/stapes'], function (Stapes) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param params
|
|
||||||
* @returns {HTMLElement}
|
|
||||||
*/
|
|
||||||
function buildDom (params) {
|
|
||||||
var dom, label, ul, li, i, header;
|
|
||||||
|
|
||||||
dom = document.createElement('div');
|
|
||||||
dom.classList.add('grouplist');
|
|
||||||
dom.id = params.id;
|
|
||||||
|
|
||||||
header = document.createElement('div');
|
|
||||||
header.classList.add('header');
|
|
||||||
dom.appendChild(header);
|
|
||||||
label = document.createElement('div');
|
|
||||||
label.innerHTML = params.label;
|
|
||||||
label.classList.add('title');
|
|
||||||
header.appendChild(label);
|
|
||||||
label = document.createElement('div');
|
|
||||||
label.innerHTML = '';
|
|
||||||
label.classList.add('callout');
|
|
||||||
header.appendChild(label);
|
|
||||||
|
|
||||||
ul = document.createElement('ul');
|
|
||||||
dom.appendChild(ul);
|
|
||||||
if (params.list) {
|
|
||||||
for (i = 0; i < params.list.length; i++) {
|
|
||||||
li = createLine(params.list[i]);
|
|
||||||
ul.appendChild(li);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dom;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createLine (params) {
|
|
||||||
var dom, el, horiz, box, touch;
|
|
||||||
|
|
||||||
dom = document.createDocumentFragment();
|
|
||||||
|
|
||||||
horiz = document.createElement('div');
|
|
||||||
horiz.classList.add('horizontal');
|
|
||||||
dom.appendChild(horiz);
|
|
||||||
|
|
||||||
touch = document.createElement('div');
|
|
||||||
touch.classList.add('horizontal');
|
|
||||||
horiz.appendChild(touch);
|
|
||||||
|
|
||||||
el = document.createElement('div');
|
|
||||||
el.classList.add('checkbox');
|
|
||||||
touch.appendChild(el);
|
|
||||||
|
|
||||||
box = document.createElement('div');
|
|
||||||
box.classList.add('titlebox');
|
|
||||||
touch.appendChild(box);
|
|
||||||
|
|
||||||
el = document.createElement('label');
|
|
||||||
el.classList.add('title');
|
|
||||||
el.innerHTML = params.title || '';
|
|
||||||
box.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('label');
|
|
||||||
el.classList.add('subtitle');
|
|
||||||
el.innerHTML = params.subtitle;
|
|
||||||
box.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('div');
|
|
||||||
el.classList.add('touchrect');
|
|
||||||
touch.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('div');
|
|
||||||
el.classList.add('edit_icon');
|
|
||||||
el.innerHTML = '';
|
|
||||||
horiz.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('div');
|
|
||||||
el.classList.add('delete_icon');
|
|
||||||
el.innerHTML = '';
|
|
||||||
horiz.appendChild(el);
|
|
||||||
|
|
||||||
return dom;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends ServerList.prototype */{
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {HTMLElement}
|
|
||||||
*/
|
|
||||||
dom: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class ServerList
|
|
||||||
* @constructs
|
|
||||||
* @param {object} params - List parameter
|
|
||||||
* @param {string} params.id - List id
|
|
||||||
* @param {string} params.label - List title
|
|
||||||
* @param {{title: string, subtitle: string, c}[]} [params.list] - List elements
|
|
||||||
*
|
|
||||||
* @fires add
|
|
||||||
* @fires remove
|
|
||||||
* @fires select
|
|
||||||
* @fires edit
|
|
||||||
*/
|
|
||||||
constructor: function (params) {
|
|
||||||
this.dom = buildDom(params || {});
|
|
||||||
this.bindEventHandlers();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
bindEventHandlers: function () {
|
|
||||||
window.addClickHandler(this.dom.querySelector('.callout'), function () {
|
|
||||||
this.emit('add');
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
window.addClickHandler(this.dom.querySelector('ul'), function (event) {
|
|
||||||
if (event.target.classList.contains('delete_icon')) {
|
|
||||||
this.emit('remove', event.target.parentNode.parentNode.id);
|
|
||||||
} else if (event.target.classList.contains('edit_icon')) {
|
|
||||||
this.emit('edit', event.target.parentNode.parentNode.id);
|
|
||||||
} else if (event.target.classList.contains('touchrect')) {
|
|
||||||
this.emit('select', event.target.parentNode.parentNode.parentNode.id);
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the DOM of the list
|
|
||||||
* @returns {HTMLElement}
|
|
||||||
*/
|
|
||||||
getDom: function () {
|
|
||||||
return this.dom;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a line
|
|
||||||
* @param id
|
|
||||||
* @param selected
|
|
||||||
* @param element
|
|
||||||
*/
|
|
||||||
append: function (id, selected, element) {
|
|
||||||
var li = document.createElement('li');
|
|
||||||
li.id = id;
|
|
||||||
if (selected) {
|
|
||||||
li.classList.add('selected');
|
|
||||||
}
|
|
||||||
li.appendChild(element);
|
|
||||||
this.dom.querySelector('ul').appendChild(li);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace a line
|
|
||||||
* @param index
|
|
||||||
* @param element
|
|
||||||
*/
|
|
||||||
replace: function (index, element) {
|
|
||||||
var child = this.dom.querySelector('ul li:nth-child(' + (index + 1) + ')'), li;
|
|
||||||
if (child) {
|
|
||||||
li = document.createElement('li');
|
|
||||||
li.appendChild(element);
|
|
||||||
this.dom.querySelector('ul').replaceChild(li, child);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a line
|
|
||||||
* @param lineParam
|
|
||||||
*/
|
|
||||||
addLine: function (lineParam) {
|
|
||||||
var line = createLine(lineParam);
|
|
||||||
this.append(lineParam.id, lineParam.selected, line);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the list
|
|
||||||
*/
|
|
||||||
clear: function () {
|
|
||||||
this.dom.querySelector('ul').innerHTML = '';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide or show the Add button in the header
|
|
||||||
* @param {boolean} show - True to show, false to hide
|
|
||||||
*/
|
|
||||||
showAddButton: function (show) {
|
|
||||||
if (show) {
|
|
||||||
this.dom.querySelector('.callout').classList.remove('invisible');
|
|
||||||
} else {
|
|
||||||
this.dom.querySelector('.callout').classList.add('invisible');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,259 +0,0 @@
|
|||||||
define(['lib/stapes', 'views/ServerList'], function (Stapes, ServerList) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function createLabelInputLine (params) {
|
|
||||||
var dom, el;
|
|
||||||
|
|
||||||
dom = document.createElement('div');
|
|
||||||
dom.classList.add('inputline');
|
|
||||||
dom.id = params.id;
|
|
||||||
|
|
||||||
el = document.createElement('label');
|
|
||||||
el.innerHTML = params.label;
|
|
||||||
dom.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('input');
|
|
||||||
if (typeof params.value === 'number') {
|
|
||||||
el.type = 'number';
|
|
||||||
}
|
|
||||||
el.value = params.value || '';
|
|
||||||
el.autocomplete='off';
|
|
||||||
el.autocorrect='off';
|
|
||||||
el.autocapitalize='off';
|
|
||||||
dom.appendChild(el);
|
|
||||||
|
|
||||||
return dom;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createButtonLine (params) {
|
|
||||||
var dom, el;
|
|
||||||
|
|
||||||
dom = document.createElement('div');
|
|
||||||
dom.classList.add('inputline');
|
|
||||||
|
|
||||||
el = document.createElement('button');
|
|
||||||
el.innerHTML = params.label;
|
|
||||||
el.classList.add('OK');
|
|
||||||
dom.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('button');
|
|
||||||
el.innerHTML = 'Cancel';
|
|
||||||
el.classList.add('CANCEL');
|
|
||||||
dom.appendChild(el);
|
|
||||||
|
|
||||||
return dom;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createDetectLine () {
|
|
||||||
var dom, el;
|
|
||||||
|
|
||||||
dom = document.createElement('div');
|
|
||||||
dom.classList.add('line');
|
|
||||||
|
|
||||||
el = document.createElement('button');
|
|
||||||
el.id = 'detect_button';
|
|
||||||
el.innerHTML = 'Detect';
|
|
||||||
dom.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('div');
|
|
||||||
el.classList.add('spinner');
|
|
||||||
el.classList.add('hidden');
|
|
||||||
dom.appendChild(el);
|
|
||||||
|
|
||||||
return dom;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends SettingsView.prototype */{
|
|
||||||
dom: null,
|
|
||||||
serverList: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class SettingsView
|
|
||||||
* @classdesc View for the settings
|
|
||||||
* @constructs
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
var list = [], el;
|
|
||||||
|
|
||||||
this.dom = document.querySelector('#settings');
|
|
||||||
|
|
||||||
this.serverList = new ServerList({
|
|
||||||
id: 'serverList',
|
|
||||||
label: 'Server',
|
|
||||||
list: list
|
|
||||||
});
|
|
||||||
|
|
||||||
this.serverList.on({
|
|
||||||
add: function () {
|
|
||||||
var line, box;
|
|
||||||
|
|
||||||
this.enableDetectButton(false);
|
|
||||||
this.lockList(true);
|
|
||||||
|
|
||||||
box = document.createDocumentFragment();
|
|
||||||
|
|
||||||
line = createLabelInputLine({id: 'name', label: 'Name:'});
|
|
||||||
box.appendChild(line);
|
|
||||||
line = createLabelInputLine({id: 'address', label: 'Address:'});
|
|
||||||
box.appendChild(line);
|
|
||||||
line = createLabelInputLine({id: 'port', label: 'Port:', value: 19444});
|
|
||||||
box.appendChild(line);
|
|
||||||
line = createLabelInputLine({id: 'priority', label: 'Priority:', value: 50});
|
|
||||||
box.appendChild(line);
|
|
||||||
line = createLabelInputLine({id: 'duration', label: 'Duration (sec):', value: 0});
|
|
||||||
box.appendChild(line);
|
|
||||||
|
|
||||||
line = createButtonLine({label: 'Add'});
|
|
||||||
|
|
||||||
window.addClickHandler(line.firstChild, function (event) {
|
|
||||||
var server = {}, i, inputs = event.target.parentNode.parentNode.querySelectorAll('input');
|
|
||||||
|
|
||||||
for (i = 0; i < inputs.length; i++) {
|
|
||||||
server[inputs[i].parentNode.id] = inputs[i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
server.port = parseInt(server.port);
|
|
||||||
server.priority = parseInt(server.priority);
|
|
||||||
server.duration = parseInt(server.duration);
|
|
||||||
|
|
||||||
this.emit('serverAdded', server);
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
window.addClickHandler(line.lastChild, function () {
|
|
||||||
this.emit('serverAddCanceled');
|
|
||||||
}.bind(this));
|
|
||||||
box.appendChild(line);
|
|
||||||
this.serverList.append(null, false, box);
|
|
||||||
},
|
|
||||||
select: function (id) {
|
|
||||||
if (!this.dom.classList.contains('locked')) {
|
|
||||||
this.emit('serverSelected', parseInt(id.replace('server_', '')));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
remove: function (id) {
|
|
||||||
this.emit('serverRemoved', parseInt(id.replace('server_', '')));
|
|
||||||
},
|
|
||||||
edit: function (id) {
|
|
||||||
this.emit('editServer', parseInt(id.replace('server_', '')));
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.dom.appendChild(this.serverList.getDom());
|
|
||||||
|
|
||||||
el = createDetectLine();
|
|
||||||
|
|
||||||
window.addClickHandler(el.querySelector('button'), function () {
|
|
||||||
this.emit('detect');
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
this.dom.appendChild(el);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills the list of known servers
|
|
||||||
* @param {Array} servers
|
|
||||||
*/
|
|
||||||
fillServerList: function (servers) {
|
|
||||||
var i, server, params;
|
|
||||||
this.serverList.clear();
|
|
||||||
for (i = 0; i < servers.length; i++) {
|
|
||||||
server = servers[i];
|
|
||||||
params = {id: 'server_' + i, title: server.name, subtitle: server.address + ':' + server.port};
|
|
||||||
if (server.selected) {
|
|
||||||
params.selected = true;
|
|
||||||
}
|
|
||||||
this.serverList.addLine(params);
|
|
||||||
}
|
|
||||||
this.serverList.showAddButton(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows or hides the spinner as progress indicator
|
|
||||||
* @param {boolean} show True to show, false to hide
|
|
||||||
*/
|
|
||||||
showWaiting: function (show) {
|
|
||||||
if (show) {
|
|
||||||
this.dom.querySelector('.spinner').classList.remove('hidden');
|
|
||||||
} else {
|
|
||||||
this.dom.querySelector('.spinner').classList.add('hidden');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables or disables the detect button
|
|
||||||
* @param {Boolean} enabled True to enable, false to disable
|
|
||||||
*/
|
|
||||||
enableDetectButton: function (enabled) {
|
|
||||||
if (enabled) {
|
|
||||||
this.dom.querySelector('#detect_button').classList.remove('hidden');
|
|
||||||
} else {
|
|
||||||
this.dom.querySelector('#detect_button').classList.add('hidden');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locks the list for editing/deleting
|
|
||||||
* @param {Boolean} lock True to lock, false to unlock
|
|
||||||
*/
|
|
||||||
lockList: function (lock) {
|
|
||||||
if (!lock) {
|
|
||||||
this.dom.classList.remove('locked');
|
|
||||||
this.serverList.showAddButton(true);
|
|
||||||
} else {
|
|
||||||
this.dom.classList.add('locked');
|
|
||||||
this.serverList.showAddButton(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
editServer: function (serverInfo) {
|
|
||||||
var line, box;
|
|
||||||
|
|
||||||
this.lockList(true);
|
|
||||||
this.enableDetectButton(false);
|
|
||||||
|
|
||||||
box = document.createDocumentFragment();
|
|
||||||
|
|
||||||
line = createLabelInputLine({id: 'name', label: 'Name:', value: serverInfo.server.name});
|
|
||||||
box.appendChild(line);
|
|
||||||
line = createLabelInputLine({id: 'address', label: 'Address:', value: serverInfo.server.address});
|
|
||||||
box.appendChild(line);
|
|
||||||
line = createLabelInputLine({id: 'port', label: 'Port:', value: serverInfo.server.port});
|
|
||||||
box.appendChild(line);
|
|
||||||
line = createLabelInputLine({id: 'priority', label: 'Priority:', value: serverInfo.server.priority});
|
|
||||||
box.appendChild(line);
|
|
||||||
line = createLabelInputLine({id: 'duration', label: 'Duration (sec):', value: serverInfo.server.duration});
|
|
||||||
box.appendChild(line);
|
|
||||||
|
|
||||||
line = createButtonLine({label: 'Done'});
|
|
||||||
|
|
||||||
window.addClickHandler(line.querySelector('button.OK'), function (event) {
|
|
||||||
var server = {}, i, inputs = event.target.parentNode.parentNode.querySelectorAll('input');
|
|
||||||
|
|
||||||
for (i = 0; i < inputs.length; i++) {
|
|
||||||
server[inputs[i].parentNode.id] = inputs[i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
server.port = parseInt(server.port);
|
|
||||||
server.priority = parseInt(server.priority);
|
|
||||||
server.duration = parseInt(server.duration);
|
|
||||||
if (serverInfo.server.selected) {
|
|
||||||
server.selected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('serverChanged', {index: serverInfo.index, server: server});
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
window.addClickHandler(line.querySelector('button.CANCEL'), function () {
|
|
||||||
this.emit('serverEditCanceled');
|
|
||||||
}.bind(this));
|
|
||||||
box.appendChild(line);
|
|
||||||
|
|
||||||
window.addClickHandler(box.querySelector('input'), function (event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.serverList.replace(serverInfo.index, box);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
|||||||
define(['lib/stapes'], function (Stapes) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function syncView (slider) {
|
|
||||||
var left = (slider.value - slider.min) * 100 / (slider.max - slider.min);
|
|
||||||
slider.dom.lastElementChild.style.left = left + '%';
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleEvent(event, slider) {
|
|
||||||
var x, left, ratio, value, steppedValue;
|
|
||||||
if (event.touches) {
|
|
||||||
x = event.touches[0].clientX;
|
|
||||||
} else {
|
|
||||||
x = event.clientX;
|
|
||||||
}
|
|
||||||
|
|
||||||
left = x - slider.dom.getBoundingClientRect().left;
|
|
||||||
ratio = left / slider.dom.offsetWidth;
|
|
||||||
value = (slider.max - slider.min) * ratio;
|
|
||||||
|
|
||||||
steppedValue = (value - slider.min) % slider.step;
|
|
||||||
if (steppedValue <= slider.step / 2) {
|
|
||||||
value = value - steppedValue;
|
|
||||||
} else {
|
|
||||||
value = value + (slider.step - steppedValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
value = Math.max(value, slider.min);
|
|
||||||
value = Math.min(value, slider.max);
|
|
||||||
slider.value = value;
|
|
||||||
slider.emit('changeValue', {
|
|
||||||
'value': value,
|
|
||||||
'target': slider.dom
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends Slider.prototype */{
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Element}
|
|
||||||
*/
|
|
||||||
dom: null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Number}
|
|
||||||
*/
|
|
||||||
min: 0,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Number}
|
|
||||||
*/
|
|
||||||
max: 100,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Number}
|
|
||||||
*/
|
|
||||||
value: 0,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @type {Number}
|
|
||||||
*/
|
|
||||||
step: 1,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Slider
|
|
||||||
* @constructs
|
|
||||||
* @fires change
|
|
||||||
*/
|
|
||||||
constructor: function (params) {
|
|
||||||
this.dom = params.element;
|
|
||||||
this.setValue(params.value);
|
|
||||||
this.setMin(params.min);
|
|
||||||
this.setMax(params.max);
|
|
||||||
this.setStep(params.step);
|
|
||||||
|
|
||||||
this.bindEventHandlers();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
bindEventHandlers: function () {
|
|
||||||
var that = this;
|
|
||||||
|
|
||||||
function pointerMoveEventHandler(event) {
|
|
||||||
if (that.drag) {
|
|
||||||
handleEvent(event, that);
|
|
||||||
syncView(that);
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function pointerUpEventHandler() {
|
|
||||||
that.drag = false;
|
|
||||||
syncView(that);
|
|
||||||
window.removePointerMoveHandler(document, pointerMoveEventHandler);
|
|
||||||
window.removePointerUpHandler(document, pointerUpEventHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addPointerDownHandler(this.dom, function (event) {
|
|
||||||
this.drag = true;
|
|
||||||
handleEvent(event, this);
|
|
||||||
syncView(this);
|
|
||||||
window.addPointerMoveHandler(document, pointerMoveEventHandler);
|
|
||||||
window.addPointerUpHandler(document, pointerUpEventHandler);
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
setValue: function(value) {
|
|
||||||
this.value = value || 0;
|
|
||||||
syncView(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
setMin: function(value) {
|
|
||||||
this.min = value || 0;
|
|
||||||
syncView(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
setMax: function(value) {
|
|
||||||
this.max = value || 100;
|
|
||||||
syncView(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
setStep: function(value) {
|
|
||||||
this.step = value || 1;
|
|
||||||
syncView(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,375 +0,0 @@
|
|||||||
/**
|
|
||||||
* hyperion remote
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
define([
|
|
||||||
'lib/stapes',
|
|
||||||
'views/Slider'
|
|
||||||
], function (Stapes, Slider) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function onHeaderClick (event) {
|
|
||||||
var list = event.target.parentNode.parentNode.querySelector('ul');
|
|
||||||
|
|
||||||
if (list.clientHeight === 0) {
|
|
||||||
list.style.maxHeight = list.scrollHeight + 'px';
|
|
||||||
event.target.parentNode.parentNode.setAttribute('collapsed', 'false');
|
|
||||||
} else {
|
|
||||||
list.style.maxHeight = 0;
|
|
||||||
event.target.parentNode.parentNode.setAttribute('collapsed', 'true');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createLine (id, type, icon, caption, value, min, max) {
|
|
||||||
var dom, el, el2, label, wrapper;
|
|
||||||
|
|
||||||
dom = document.createElement('li');
|
|
||||||
dom.className = type;
|
|
||||||
|
|
||||||
label = document.createElement('label');
|
|
||||||
label.innerHTML = caption;
|
|
||||||
dom.appendChild(label);
|
|
||||||
|
|
||||||
wrapper = document.createElement('div');
|
|
||||||
wrapper.classList.add('wrapper');
|
|
||||||
wrapper.id = id;
|
|
||||||
|
|
||||||
el = document.createElement('div');
|
|
||||||
el.classList.add('icon');
|
|
||||||
el.innerHTML = icon;
|
|
||||||
wrapper.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('div');
|
|
||||||
el.classList.add('slider');
|
|
||||||
el2 = document.createElement('div');
|
|
||||||
el2.classList.add('track');
|
|
||||||
el.appendChild(el2);
|
|
||||||
el2 = document.createElement('div');
|
|
||||||
el2.classList.add('thumb');
|
|
||||||
el.appendChild(el2);
|
|
||||||
el.dataset.min = min;
|
|
||||||
el.dataset.max = max;
|
|
||||||
el.dataset.value = value;
|
|
||||||
el.dataset.step = 0.01;
|
|
||||||
wrapper.appendChild(el);
|
|
||||||
|
|
||||||
el = document.createElement('input');
|
|
||||||
el.classList.add('value');
|
|
||||||
el.type = 'number';
|
|
||||||
el.min = min;
|
|
||||||
el.max = max;
|
|
||||||
el.step = 0.01;
|
|
||||||
el.value = parseFloat(Math.round(value * 100) / 100).toFixed(2);
|
|
||||||
wrapper.appendChild(el);
|
|
||||||
|
|
||||||
dom.appendChild(wrapper);
|
|
||||||
|
|
||||||
return dom;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createGroup (groupInfo) {
|
|
||||||
var group, node, subnode, i, member;
|
|
||||||
group = document.createElement('div');
|
|
||||||
group.classList.add('group');
|
|
||||||
if (groupInfo.collapsed) {
|
|
||||||
group.setAttribute('collapsed', 'true');
|
|
||||||
}
|
|
||||||
group.id = groupInfo.id;
|
|
||||||
|
|
||||||
node = document.createElement('div');
|
|
||||||
node.classList.add('header');
|
|
||||||
group.appendChild(node);
|
|
||||||
subnode = document.createElement('label');
|
|
||||||
subnode.innerHTML = groupInfo.title;
|
|
||||||
node.appendChild(subnode);
|
|
||||||
subnode = document.createElement('label');
|
|
||||||
subnode.innerHTML = groupInfo.subtitle;
|
|
||||||
node.appendChild(subnode);
|
|
||||||
|
|
||||||
node = document.createElement('ul');
|
|
||||||
group.appendChild(node);
|
|
||||||
for (i = 0; i < groupInfo.members.length; i++) {
|
|
||||||
member = groupInfo.members[i];
|
|
||||||
subnode = createLine(member.id, member.type, member.icon, member.label, member.value, member.min,
|
|
||||||
member.max);
|
|
||||||
node.appendChild(subnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stapes.subclass(/** @lends TransformView.prototype */{
|
|
||||||
sliders: {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class TransformView
|
|
||||||
* @constructs
|
|
||||||
*/
|
|
||||||
constructor: function () {
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the list
|
|
||||||
*/
|
|
||||||
clear: function () {
|
|
||||||
document.querySelector('#transform .values').innerHTML = '';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param change
|
|
||||||
*/
|
|
||||||
onSliderChange: function (event) {
|
|
||||||
var data = {}, idparts, value;
|
|
||||||
|
|
||||||
idparts = event.target.parentNode.id.split('_');
|
|
||||||
value = parseFloat(Math.round(parseFloat(event.value) * 100) / 100);
|
|
||||||
|
|
||||||
event.target.parentNode.querySelector('.value').value = value.toFixed(2);
|
|
||||||
|
|
||||||
data[idparts[1]] = value;
|
|
||||||
this.emit(idparts[0], data);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param change
|
|
||||||
*/
|
|
||||||
onValueChange: function (event) {
|
|
||||||
var data = {}, idparts, value;
|
|
||||||
|
|
||||||
idparts = event.target.parentNode.id.split('_');
|
|
||||||
value = parseFloat(Math.round(parseFloat(event.target.value) * 100) / 100);
|
|
||||||
|
|
||||||
if (parseFloat(event.target.value) < parseFloat(event.target.min)) {
|
|
||||||
event.target.value = event.target.min;
|
|
||||||
} else if (parseFloat(event.target.value) > parseFloat(event.target.max)) {
|
|
||||||
event.target.value = event.target.max;
|
|
||||||
}
|
|
||||||
this.sliders[event.target.parentNode.id].setValue(value);
|
|
||||||
|
|
||||||
data[idparts[1]] = value;
|
|
||||||
this.emit(idparts[0], data);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fill the list
|
|
||||||
* @param {object} transform - Object containing transform information
|
|
||||||
*/
|
|
||||||
fillList: function (transform) {
|
|
||||||
var dom, group, els, i, slider;
|
|
||||||
|
|
||||||
if (!transform) {
|
|
||||||
document.querySelector('#transform .info').classList.remove('hidden');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dom = document.createDocumentFragment();
|
|
||||||
|
|
||||||
group = createGroup({
|
|
||||||
collapsed: true,
|
|
||||||
id: 'HSV',
|
|
||||||
title: 'HSV',
|
|
||||||
subtitle: 'HSV color corrections',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
id: 'hsv_saturationGain',
|
|
||||||
type: 'saturation',
|
|
||||||
icon: '',
|
|
||||||
label: 'Saturation gain',
|
|
||||||
value: transform.saturationGain,
|
|
||||||
min: 0,
|
|
||||||
max: 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'hsv_valueGain',
|
|
||||||
type: 'value',
|
|
||||||
icon: '',
|
|
||||||
label: 'Value gain',
|
|
||||||
value: transform.valueGain,
|
|
||||||
min: 0,
|
|
||||||
max: 5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
dom.appendChild(group);
|
|
||||||
|
|
||||||
group = createGroup({
|
|
||||||
collapsed: true,
|
|
||||||
id: 'Gamma',
|
|
||||||
title: 'Gamma',
|
|
||||||
subtitle: 'Gamma correction',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
id: 'gamma_r',
|
|
||||||
type: 'red',
|
|
||||||
icon: '',
|
|
||||||
label: 'Red',
|
|
||||||
value: transform.gamma[0],
|
|
||||||
min: 0,
|
|
||||||
max: 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'gamma_g',
|
|
||||||
type: 'green',
|
|
||||||
icon: '',
|
|
||||||
label: 'Green',
|
|
||||||
value: transform.gamma[1],
|
|
||||||
min: 0,
|
|
||||||
max: 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'gamma_b',
|
|
||||||
type: 'blue',
|
|
||||||
icon: '',
|
|
||||||
label: 'Blue',
|
|
||||||
value: transform.gamma[2],
|
|
||||||
min: 0,
|
|
||||||
max: 5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
dom.appendChild(group);
|
|
||||||
|
|
||||||
group = createGroup({
|
|
||||||
collapsed: true,
|
|
||||||
id: 'Whitelevel',
|
|
||||||
title: 'Whitelevel',
|
|
||||||
subtitle: 'Value when RGB channel is fully on',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
id: 'whitelevel_r',
|
|
||||||
type: 'red',
|
|
||||||
icon: '',
|
|
||||||
label: 'Red',
|
|
||||||
value: transform.whitelevel[0],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'whitelevel_g',
|
|
||||||
type: 'green',
|
|
||||||
icon: '',
|
|
||||||
label: 'Green',
|
|
||||||
value: transform.whitelevel[1],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'whitelevel_b',
|
|
||||||
type: 'blue',
|
|
||||||
icon: '',
|
|
||||||
label: 'Blue',
|
|
||||||
value: transform.whitelevel[2],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
dom.appendChild(group);
|
|
||||||
|
|
||||||
group = createGroup({
|
|
||||||
collapsed: true,
|
|
||||||
id: 'Blacklevel',
|
|
||||||
title: 'Blacklevel',
|
|
||||||
subtitle: 'Value when RGB channel is fully off',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
id: 'blacklevel_r',
|
|
||||||
type: 'red',
|
|
||||||
icon: '',
|
|
||||||
label: 'Red',
|
|
||||||
value: transform.blacklevel[0],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'blacklevel_g',
|
|
||||||
type: 'green',
|
|
||||||
icon: '',
|
|
||||||
label: 'Green',
|
|
||||||
value: transform.blacklevel[1],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'blacklevel_b',
|
|
||||||
type: 'blue',
|
|
||||||
icon: '',
|
|
||||||
label: 'Blue',
|
|
||||||
value: transform.blacklevel[2],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
dom.appendChild(group);
|
|
||||||
|
|
||||||
group = createGroup({
|
|
||||||
collapsed: true,
|
|
||||||
id: 'Threshold',
|
|
||||||
title: 'Threshold',
|
|
||||||
subtitle: 'Threshold for a channel',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
id: 'threshold_r',
|
|
||||||
type: 'red',
|
|
||||||
icon: '',
|
|
||||||
label: 'Red',
|
|
||||||
value: transform.threshold[0],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'threshold_g',
|
|
||||||
type: 'green',
|
|
||||||
icon: '',
|
|
||||||
label: 'Green',
|
|
||||||
value: transform.threshold[1],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'threshold_b',
|
|
||||||
type: 'blue',
|
|
||||||
icon: '',
|
|
||||||
label: 'Blue',
|
|
||||||
value: transform.threshold[2],
|
|
||||||
min: 0,
|
|
||||||
max: 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
dom.appendChild(group);
|
|
||||||
|
|
||||||
els = dom.querySelectorAll('.slider');
|
|
||||||
for (i = 0; i < els.length; i++) {
|
|
||||||
slider = new Slider({
|
|
||||||
element: els[i],
|
|
||||||
min: els[i].dataset.min,
|
|
||||||
max: els[i].dataset.max,
|
|
||||||
step: els[i].dataset.step,
|
|
||||||
value: els[i].dataset.value
|
|
||||||
});
|
|
||||||
slider.on('changeValue', this.onSliderChange, this);
|
|
||||||
this.sliders[els[i].parentNode.id] = slider;
|
|
||||||
}
|
|
||||||
|
|
||||||
els = dom.querySelectorAll('input');
|
|
||||||
for (i = 0; i < els.length; i++) {
|
|
||||||
els[i].addEventListener('input', this.onValueChange.bind(this), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
els = dom.querySelectorAll('.header');
|
|
||||||
for (i = 0; i < els.length; i++) {
|
|
||||||
window.addClickHandler(els[i], onHeaderClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.querySelector('#transform .info').classList.add('hidden');
|
|
||||||
document.querySelector('#transform .values').appendChild(dom);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
/*global chrome */
|
|
||||||
chrome.app.runtime.onLaunched.addListener(function () {
|
|
||||||
'use strict';
|
|
||||||
chrome.app.window.create('index.html', {
|
|
||||||
'id': 'fakeIdForSingleton',
|
|
||||||
'innerBounds': {
|
|
||||||
'width': 320,
|
|
||||||
'height': 480,
|
|
||||||
'minWidth': 320,
|
|
||||||
'minHeight': 480
|
|
||||||
},
|
|
||||||
resizable: false
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
2054
assets/webconfig/remote/js/vendor/require.js
vendored
2054
assets/webconfig/remote/js/vendor/require.js
vendored
File diff suppressed because it is too large
Load Diff
594
assets/webconfig/remote/js/vendor/stapes.js
vendored
594
assets/webconfig/remote/js/vendor/stapes.js
vendored
@ -1,594 +0,0 @@
|
|||||||
//
|
|
||||||
// ____ _ _
|
|
||||||
// / ___|| |_ __ _ _ __ ___ ___ (_)___ (*)
|
|
||||||
// \___ \| __/ _` | '_ \ / _ \/ __| | / __|
|
|
||||||
// ___) | || (_| | |_) | __/\__ \_ | \__ \
|
|
||||||
// |____/ \__\__,_| .__/ \___||___(_)/ |___/
|
|
||||||
// |_| |__/
|
|
||||||
//
|
|
||||||
// (*) a (really) tiny Javascript MVC microframework
|
|
||||||
//
|
|
||||||
// (c) Hay Kranen < hay@bykr.org >
|
|
||||||
// Released under the terms of the MIT license
|
|
||||||
// < http://en.wikipedia.org/wiki/MIT_License >
|
|
||||||
//
|
|
||||||
// Stapes.js : http://hay.github.com/stapes
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var VERSION = "0.8.0";
|
|
||||||
|
|
||||||
// Global counter for all events in all modules (including mixed in objects)
|
|
||||||
var guid = 1;
|
|
||||||
|
|
||||||
// Makes _.create() faster
|
|
||||||
if (!Object.create) {
|
|
||||||
var CachedFunction = function(){};
|
|
||||||
}
|
|
||||||
|
|
||||||
// So we can use slice.call for arguments later on
|
|
||||||
var slice = Array.prototype.slice;
|
|
||||||
|
|
||||||
// Private attributes and helper functions, stored in an object so they
|
|
||||||
// are overwritable by plugins
|
|
||||||
var _ = {
|
|
||||||
// Properties
|
|
||||||
attributes : {},
|
|
||||||
|
|
||||||
eventHandlers : {
|
|
||||||
"-1" : {} // '-1' is used for the global event handling
|
|
||||||
},
|
|
||||||
|
|
||||||
guid : -1,
|
|
||||||
|
|
||||||
// Methods
|
|
||||||
addEvent : function(event) {
|
|
||||||
// If we don't have any handlers for this type of event, add a new
|
|
||||||
// array we can use to push new handlers
|
|
||||||
if (!_.eventHandlers[event.guid][event.type]) {
|
|
||||||
_.eventHandlers[event.guid][event.type] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push an event object
|
|
||||||
_.eventHandlers[event.guid][event.type].push({
|
|
||||||
"guid" : event.guid,
|
|
||||||
"handler" : event.handler,
|
|
||||||
"scope" : event.scope,
|
|
||||||
"type" : event.type
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
addEventHandler : function(argTypeOrMap, argHandlerOrScope, argScope) {
|
|
||||||
var eventMap = {},
|
|
||||||
scope;
|
|
||||||
|
|
||||||
if (typeof argTypeOrMap === "string") {
|
|
||||||
scope = argScope || false;
|
|
||||||
eventMap[ argTypeOrMap ] = argHandlerOrScope;
|
|
||||||
} else {
|
|
||||||
scope = argHandlerOrScope || false;
|
|
||||||
eventMap = argTypeOrMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var eventString in eventMap) {
|
|
||||||
var handler = eventMap[eventString];
|
|
||||||
var events = eventString.split(" ");
|
|
||||||
|
|
||||||
for (var i = 0, l = events.length; i < l; i++) {
|
|
||||||
var eventType = events[i];
|
|
||||||
_.addEvent.call(this, {
|
|
||||||
"guid" : this._guid || this._.guid,
|
|
||||||
"handler" : handler,
|
|
||||||
"scope" : scope,
|
|
||||||
"type" : eventType
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
addGuid : function(object, forceGuid) {
|
|
||||||
if (object._guid && !forceGuid) return;
|
|
||||||
|
|
||||||
object._guid = guid++;
|
|
||||||
|
|
||||||
_.attributes[object._guid] = {};
|
|
||||||
_.eventHandlers[object._guid] = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
// This is a really small utility function to save typing and produce
|
|
||||||
// better optimized code
|
|
||||||
attr : function(guid) {
|
|
||||||
return _.attributes[guid];
|
|
||||||
},
|
|
||||||
|
|
||||||
clone : function(obj) {
|
|
||||||
var type = _.typeOf(obj);
|
|
||||||
|
|
||||||
if (type === 'object') {
|
|
||||||
return _.extend({}, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'array') {
|
|
||||||
return obj.slice(0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
create : function(proto) {
|
|
||||||
if (Object.create) {
|
|
||||||
return Object.create(proto);
|
|
||||||
} else {
|
|
||||||
CachedFunction.prototype = proto;
|
|
||||||
return new CachedFunction();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
createSubclass : function(props, includeEvents) {
|
|
||||||
props = props || {};
|
|
||||||
includeEvents = includeEvents || false;
|
|
||||||
|
|
||||||
var superclass = props.superclass.prototype;
|
|
||||||
|
|
||||||
// Objects always have a constructor, so we need to be sure this is
|
|
||||||
// a property instead of something from the prototype
|
|
||||||
var realConstructor = props.hasOwnProperty('constructor') ? props.constructor : function(){};
|
|
||||||
|
|
||||||
function constructor() {
|
|
||||||
// Be kind to people forgetting new
|
|
||||||
if (!(this instanceof constructor)) {
|
|
||||||
throw new Error("Please use 'new' when initializing Stapes classes");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this class has events add a GUID as well
|
|
||||||
if (this.on) {
|
|
||||||
_.addGuid( this, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
realConstructor.apply(this, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeEvents) {
|
|
||||||
_.extend(superclass, Events);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor.prototype = _.create(superclass);
|
|
||||||
constructor.prototype.constructor = constructor;
|
|
||||||
|
|
||||||
_.extend(constructor, {
|
|
||||||
extend : function() {
|
|
||||||
return _.extendThis.apply(this, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
// We can't call this 'super' because that's a reserved keyword
|
|
||||||
// and fails in IE8
|
|
||||||
'parent' : superclass,
|
|
||||||
|
|
||||||
proto : function() {
|
|
||||||
return _.extendThis.apply(this.prototype, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
subclass : function(obj) {
|
|
||||||
obj = obj || {};
|
|
||||||
obj.superclass = this;
|
|
||||||
return _.createSubclass(obj);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Copy all props given in the definition to the prototype
|
|
||||||
for (var key in props) {
|
|
||||||
if (key !== 'constructor' && key !== 'superclass') {
|
|
||||||
constructor.prototype[key] = props[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return constructor;
|
|
||||||
},
|
|
||||||
|
|
||||||
emitEvents : function(type, data, explicitType, explicitGuid) {
|
|
||||||
explicitType = explicitType || false;
|
|
||||||
explicitGuid = explicitGuid || this._guid;
|
|
||||||
|
|
||||||
// #30: make a local copy of handlers to prevent problems with
|
|
||||||
// unbinding the event while unwinding the loop
|
|
||||||
var handlers = slice.call(_.eventHandlers[explicitGuid][type]);
|
|
||||||
|
|
||||||
for (var i = 0, l = handlers.length; i < l; i++) {
|
|
||||||
// Clone the event to prevent issue #19
|
|
||||||
var event = _.extend({}, handlers[i]);
|
|
||||||
var scope = (event.scope) ? event.scope : this;
|
|
||||||
|
|
||||||
if (explicitType) {
|
|
||||||
event.type = explicitType;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.scope = scope;
|
|
||||||
event.handler.call(event.scope, data, event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Extend an object with more objects
|
|
||||||
extend : function() {
|
|
||||||
var args = slice.call(arguments);
|
|
||||||
var object = args.shift();
|
|
||||||
|
|
||||||
for (var i = 0, l = args.length; i < l; i++) {
|
|
||||||
var props = args[i];
|
|
||||||
for (var key in props) {
|
|
||||||
object[key] = props[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return object;
|
|
||||||
},
|
|
||||||
|
|
||||||
// The same as extend, but uses the this value as the scope
|
|
||||||
extendThis : function() {
|
|
||||||
var args = slice.call(arguments);
|
|
||||||
args.unshift(this);
|
|
||||||
return _.extend.apply(this, args);
|
|
||||||
},
|
|
||||||
|
|
||||||
// from http://stackoverflow.com/a/2117523/152809
|
|
||||||
makeUuid : function() {
|
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
||||||
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
|
|
||||||
return v.toString(16);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeAttribute : function(keys, silent) {
|
|
||||||
silent = silent || false;
|
|
||||||
|
|
||||||
// Split the key, maybe we want to remove more than one item
|
|
||||||
var attributes = _.trim(keys).split(" ");
|
|
||||||
|
|
||||||
// Actually delete the item
|
|
||||||
for (var i = 0, l = attributes.length; i < l; i++) {
|
|
||||||
var key = _.trim(attributes[i]);
|
|
||||||
|
|
||||||
if (key) {
|
|
||||||
delete _.attr(this._guid)[key];
|
|
||||||
|
|
||||||
// If 'silent' is set, do not throw any events
|
|
||||||
if (!silent) {
|
|
||||||
this.emit('change', key);
|
|
||||||
this.emit('change:' + key);
|
|
||||||
this.emit('remove', key);
|
|
||||||
this.emit('remove:' + key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
removeEventHandler : function(type, handler) {
|
|
||||||
var handlers = _.eventHandlers[this._guid];
|
|
||||||
|
|
||||||
if (type && handler) {
|
|
||||||
// Remove a specific handler
|
|
||||||
handlers = handlers[type];
|
|
||||||
if (!handlers) return;
|
|
||||||
|
|
||||||
for (var i = 0, l = handlers.length, h; i < l; i++) {
|
|
||||||
h = handlers[i].handler;
|
|
||||||
if (h && h === handler) {
|
|
||||||
handlers.splice(i--, 1);
|
|
||||||
l--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type) {
|
|
||||||
// Remove all handlers for a specific type
|
|
||||||
delete handlers[type];
|
|
||||||
} else {
|
|
||||||
// Remove all handlers for this module
|
|
||||||
_.eventHandlers[this._guid] = {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setAttribute : function(key, value, silent) {
|
|
||||||
silent = silent || false;
|
|
||||||
|
|
||||||
// We need to do this before we actually add the item :)
|
|
||||||
var itemExists = this.has(key);
|
|
||||||
var oldValue = _.attr(this._guid)[key];
|
|
||||||
|
|
||||||
// Is the value different than the oldValue? If not, ignore this call
|
|
||||||
if (value === oldValue) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually add the item to the attributes
|
|
||||||
_.attr(this._guid)[key] = value;
|
|
||||||
|
|
||||||
// If 'silent' flag is set, do not throw any events
|
|
||||||
if (silent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throw a generic event
|
|
||||||
this.emit('change', key);
|
|
||||||
|
|
||||||
// And a namespaced event as well, NOTE that we pass value instead of
|
|
||||||
// key here!
|
|
||||||
this.emit('change:' + key, value);
|
|
||||||
|
|
||||||
// Throw namespaced and non-namespaced 'mutate' events as well with
|
|
||||||
// the old value data as well and some extra metadata such as the key
|
|
||||||
var mutateData = {
|
|
||||||
"key" : key,
|
|
||||||
"newValue" : value,
|
|
||||||
"oldValue" : oldValue || null
|
|
||||||
};
|
|
||||||
|
|
||||||
this.emit('mutate', mutateData);
|
|
||||||
this.emit('mutate:' + key, mutateData);
|
|
||||||
|
|
||||||
// Also throw a specific event for this type of set
|
|
||||||
var specificEvent = itemExists ? 'update' : 'create';
|
|
||||||
|
|
||||||
this.emit(specificEvent, key);
|
|
||||||
|
|
||||||
// And a namespaced event as well, NOTE that we pass value instead of key
|
|
||||||
this.emit(specificEvent + ':' + key, value);
|
|
||||||
},
|
|
||||||
|
|
||||||
trim : function(str) {
|
|
||||||
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
|
||||||
},
|
|
||||||
|
|
||||||
typeOf : function(val) {
|
|
||||||
if (val === null || typeof val === "undefined") {
|
|
||||||
// This is a special exception for IE, in other browsers the
|
|
||||||
// method below works all the time
|
|
||||||
return String(val);
|
|
||||||
} else {
|
|
||||||
return Object.prototype.toString.call(val).replace(/\[object |\]/g, '').toLowerCase();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
updateAttribute : function(key, fn, silent) {
|
|
||||||
var item = this.get(key);
|
|
||||||
|
|
||||||
// In previous versions of Stapes we didn't have the check for object,
|
|
||||||
// but still this worked. In 0.7.0 it suddenly doesn't work anymore and
|
|
||||||
// we need the check. Why? I have no clue.
|
|
||||||
var type = _.typeOf(item);
|
|
||||||
|
|
||||||
if (type === 'object' || type === 'array') {
|
|
||||||
item = _.clone(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
var newValue = fn.call(this, item, key);
|
|
||||||
_.setAttribute.call(this, key, newValue, silent || false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Can be mixed in later using Stapes.mixinEvents(object);
|
|
||||||
var Events = {
|
|
||||||
emit : function(types, data) {
|
|
||||||
data = (typeof data === "undefined") ? null : data;
|
|
||||||
|
|
||||||
var splittedTypes = types.split(" ");
|
|
||||||
|
|
||||||
for (var i = 0, l = splittedTypes.length; i < l; i++) {
|
|
||||||
var type = splittedTypes[i];
|
|
||||||
|
|
||||||
// First 'all' type events: is there an 'all' handler in the
|
|
||||||
// global stack?
|
|
||||||
if (_.eventHandlers[-1].all) {
|
|
||||||
_.emitEvents.call(this, "all", data, type, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catch all events for this type?
|
|
||||||
if (_.eventHandlers[-1][type]) {
|
|
||||||
_.emitEvents.call(this, type, data, type, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof this._guid === 'number') {
|
|
||||||
// 'all' event for this specific module?
|
|
||||||
if (_.eventHandlers[this._guid].all) {
|
|
||||||
_.emitEvents.call(this, "all", data, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, normal events :)
|
|
||||||
if (_.eventHandlers[this._guid][type]) {
|
|
||||||
_.emitEvents.call(this, type, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
off : function() {
|
|
||||||
_.removeEventHandler.apply(this, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
on : function() {
|
|
||||||
_.addEventHandler.apply(this, arguments);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_.Module = function() {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
_.Module.prototype = {
|
|
||||||
each : function(fn, ctx) {
|
|
||||||
var attr = _.attr(this._guid);
|
|
||||||
for (var key in attr) {
|
|
||||||
var value = attr[key];
|
|
||||||
fn.call(ctx || this, value, key);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
extend : function() {
|
|
||||||
return _.extendThis.apply(this, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
filter : function(fn) {
|
|
||||||
var filtered = [];
|
|
||||||
var attributes = _.attr(this._guid);
|
|
||||||
|
|
||||||
for (var key in attributes) {
|
|
||||||
if ( fn.call(this, attributes[key], key)) {
|
|
||||||
filtered.push( attributes[key] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
},
|
|
||||||
|
|
||||||
get : function(input) {
|
|
||||||
if (typeof input === "string") {
|
|
||||||
return this.has(input) ? _.attr(this._guid)[input] : null;
|
|
||||||
} else if (typeof input === "function") {
|
|
||||||
var items = this.filter(input);
|
|
||||||
return (items.length) ? items[0] : null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getAll : function() {
|
|
||||||
return _.clone( _.attr(this._guid) );
|
|
||||||
},
|
|
||||||
|
|
||||||
getAllAsArray : function() {
|
|
||||||
var arr = [];
|
|
||||||
var attributes = _.attr(this._guid);
|
|
||||||
|
|
||||||
for (var key in attributes) {
|
|
||||||
var value = attributes[key];
|
|
||||||
|
|
||||||
if (_.typeOf(value) === "object" && !value.id) {
|
|
||||||
value.id = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
arr.push(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return arr;
|
|
||||||
},
|
|
||||||
|
|
||||||
has : function(key) {
|
|
||||||
return (typeof _.attr(this._guid)[key] !== "undefined");
|
|
||||||
},
|
|
||||||
|
|
||||||
map : function(fn, ctx) {
|
|
||||||
var mapped = [];
|
|
||||||
this.each(function(value, key) {
|
|
||||||
mapped.push( fn.call(ctx || this, value, key) );
|
|
||||||
}, ctx || this);
|
|
||||||
return mapped;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Akin to set(), but makes a unique id
|
|
||||||
push : function(input, silent) {
|
|
||||||
if (_.typeOf(input) === "array") {
|
|
||||||
for (var i = 0, l = input.length; i < l; i++) {
|
|
||||||
_.setAttribute.call(this, _.makeUuid(), input[i], silent || false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_.setAttribute.call(this, _.makeUuid(), input, silent || false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
remove : function(input, silent) {
|
|
||||||
if (typeof input === 'undefined') {
|
|
||||||
// With no arguments, remove deletes all attributes
|
|
||||||
_.attributes[this._guid] = {};
|
|
||||||
this.emit('change remove');
|
|
||||||
} else if (typeof input === "function") {
|
|
||||||
this.each(function(item, key) {
|
|
||||||
if (input(item)) {
|
|
||||||
_.removeAttribute.call(this, key, silent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// nb: checking for exists happens in removeAttribute
|
|
||||||
_.removeAttribute.call(this, input, silent || false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
set : function(objOrKey, valueOrSilent, silent) {
|
|
||||||
if (typeof objOrKey === "object") {
|
|
||||||
for (var key in objOrKey) {
|
|
||||||
_.setAttribute.call(this, key, objOrKey[key], valueOrSilent || false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_.setAttribute.call(this, objOrKey, valueOrSilent, silent || false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
size : function() {
|
|
||||||
var size = 0;
|
|
||||||
var attr = _.attr(this._guid);
|
|
||||||
|
|
||||||
for (var key in attr) {
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
},
|
|
||||||
|
|
||||||
update : function(keyOrFn, fn, silent) {
|
|
||||||
if (typeof keyOrFn === "string") {
|
|
||||||
_.updateAttribute.call(this, keyOrFn, fn, silent || false);
|
|
||||||
} else if (typeof keyOrFn === "function") {
|
|
||||||
this.each(function(value, key) {
|
|
||||||
_.updateAttribute.call(this, key, keyOrFn);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var Stapes = {
|
|
||||||
"_" : _, // private helper functions and properties
|
|
||||||
|
|
||||||
"extend" : function() {
|
|
||||||
return _.extendThis.apply(_.Module.prototype, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
"mixinEvents" : function(obj) {
|
|
||||||
obj = obj || {};
|
|
||||||
|
|
||||||
_.addGuid(obj);
|
|
||||||
|
|
||||||
return _.extend(obj, Events);
|
|
||||||
},
|
|
||||||
|
|
||||||
"on" : function() {
|
|
||||||
_.addEventHandler.apply(this, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
"subclass" : function(obj, classOnly) {
|
|
||||||
classOnly = classOnly || false;
|
|
||||||
obj = obj || {};
|
|
||||||
obj.superclass = classOnly ? function(){} : _.Module;
|
|
||||||
return _.createSubclass(obj, !classOnly);
|
|
||||||
},
|
|
||||||
|
|
||||||
"version" : VERSION
|
|
||||||
};
|
|
||||||
|
|
||||||
// This library can be used as an AMD module, a Node.js module, or an
|
|
||||||
// old fashioned global
|
|
||||||
if (typeof exports !== "undefined") {
|
|
||||||
// Server
|
|
||||||
if (typeof module !== "undefined" && module.exports) {
|
|
||||||
exports = module.exports = Stapes;
|
|
||||||
}
|
|
||||||
exports.Stapes = Stapes;
|
|
||||||
} else if (typeof define === "function" && define.amd) {
|
|
||||||
// AMD
|
|
||||||
define(function() {
|
|
||||||
return Stapes;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Global scope
|
|
||||||
window.Stapes = Stapes;
|
|
||||||
}
|
|
||||||
})();
|
|
1107
assets/webconfig/remote/js/vendor/tinycolor.js
vendored
1107
assets/webconfig/remote/js/vendor/tinycolor.js
vendored
File diff suppressed because it is too large
Load Diff
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "hyperion remote control",
|
|
||||||
"short_name": "hyperion remote",
|
|
||||||
"description": "Client side app for controlling the hyperion server over the local network.",
|
|
||||||
"author": {
|
|
||||||
"name": "Daniel Wiese",
|
|
||||||
"email": "gamadril.dev@gmail.com"
|
|
||||||
},
|
|
||||||
"manifest_version": 2,
|
|
||||||
"version": "0.6.0",
|
|
||||||
"minimum_chrome_version": "36",
|
|
||||||
"permissions": [
|
|
||||||
"storage", "system.network"
|
|
||||||
],
|
|
||||||
"app": {
|
|
||||||
"background": {
|
|
||||||
"scripts": ["js/background.js"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sockets": {
|
|
||||||
"tcp": {
|
|
||||||
"connect": "*"
|
|
||||||
},
|
|
||||||
"udp": {
|
|
||||||
"send": "*",
|
|
||||||
"bind": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"icons": {
|
|
||||||
"128": "res/icon_128.png"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "hyperion remote control",
|
|
||||||
"description": "Client side app for controlling the hyperion server over the local network.",
|
|
||||||
"launch_path": "/hyperion-remote/index.html",
|
|
||||||
"icons": {
|
|
||||||
"128": "/hyperion-remote/res/icon_128.png"
|
|
||||||
},
|
|
||||||
"developer": {
|
|
||||||
"name": "Daniel Wiese",
|
|
||||||
"email": "gamadril.dev@gmail.com",
|
|
||||||
"url": "https://github.com/Gamadril"
|
|
||||||
},
|
|
||||||
"default_locale": "en"
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 487 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 17 KiB |
@ -21,14 +21,12 @@ echo create $outfile
|
|||||||
tar --create --gzip --absolute-names --show-transformed-names --ignore-failed-read\
|
tar --create --gzip --absolute-names --show-transformed-names --ignore-failed-read\
|
||||||
--file "$outfile" \
|
--file "$outfile" \
|
||||||
--transform "s:$builddir/bin/:hyperion/bin/:" \
|
--transform "s:$builddir/bin/:hyperion/bin/:" \
|
||||||
--transform "s:$repodir/effects/:hyperion/effects/:" \
|
|
||||||
--transform "s:$repodir/config/:hyperion/config/:" \
|
--transform "s:$repodir/config/:hyperion/config/:" \
|
||||||
--transform "s:$repodir/bin/service/hyperion.init.sh:hyperion/services/hyperion.init.sh:" \
|
--transform "s:$repodir/bin/service/hyperion.init.sh:hyperion/services/hyperion.init.sh:" \
|
||||||
--transform "s:$repodir/bin/service/hyperion.systemd.sh:hyperion/services/hyperion.systemd.sh:" \
|
--transform "s:$repodir/bin/service/hyperion.systemd.sh:hyperion/services/hyperion.systemd.sh:" \
|
||||||
--transform "s:$repodir/bin/service/hyperion.initctl.sh:hyperion/services/hyperion.initctl.sh:" \
|
--transform "s:$repodir/bin/service/hyperion.initctl.sh:hyperion/services/hyperion.initctl.sh:" \
|
||||||
--transform "s://:/:g" \
|
--transform "s://:/:g" \
|
||||||
"$builddir/bin/hyperion"* \
|
"$builddir/bin/hyperion"* \
|
||||||
"$repodir/effects/"* \
|
|
||||||
"$repodir/bin/service/hyperion.init.sh" \
|
"$repodir/bin/service/hyperion.init.sh" \
|
||||||
"$repodir/bin/service/hyperion.systemd.sh" \
|
"$repodir/bin/service/hyperion.systemd.sh" \
|
||||||
"$repodir/bin/service/hyperion.initctl.sh" \
|
"$repodir/bin/service/hyperion.initctl.sh" \
|
||||||
|
@ -134,7 +134,8 @@ fi
|
|||||||
if [ -f "/opt/hyperion/bin/hyperiond" ]; then
|
if [ -f "/opt/hyperion/bin/hyperiond" ]; then
|
||||||
echo '---> Old installation found, move configs to /etc/hyperion/ and move hyperion to /usr/share/hyperion/'
|
echo '---> Old installation found, move configs to /etc/hyperion/ and move hyperion to /usr/share/hyperion/'
|
||||||
mv /opt/hyperion/config/*.json /etc/hyperion 2>/dev/null
|
mv /opt/hyperion/config/*.json /etc/hyperion 2>/dev/null
|
||||||
sed -i "s|/opt/hyperion/effects|/usr/share/hyperion/effects|g" /etc/hyperion/*.json
|
|
||||||
|
sed -i "s|/opt/hyperion/effects||g; s|/usr/share/hyperion/effects||g" /etc/hyperion/*.json
|
||||||
CPO1=/etc/hyperion.config.json
|
CPO1=/etc/hyperion.config.json
|
||||||
CPO2=/opt/hyperion/config/hyperion.config.json
|
CPO2=/opt/hyperion/config/hyperion.config.json
|
||||||
CPN=/etc/hyperion/hyperion.config.json
|
CPN=/etc/hyperion/hyperion.config.json
|
||||||
@ -213,7 +214,7 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get and extract the Hyperion binaries and effects
|
# Get and extract the Hyperion binaries
|
||||||
echo '---> Downloading the appropriate Hyperion release'
|
echo '---> Downloading the appropriate Hyperion release'
|
||||||
if [ $OS_OPENELEC -eq 1 ]; then
|
if [ $OS_OPENELEC -eq 1 ]; then
|
||||||
# OpenELEC has a readonly file system. Use alternative location
|
# OpenELEC has a readonly file system. Use alternative location
|
||||||
|
@ -357,6 +357,7 @@
|
|||||||
|
|
||||||
/// The configuration of the effect engine, contains the following items:
|
/// The configuration of the effect engine, contains the following items:
|
||||||
/// * paths : An array with absolute/relative location(s) of directories with effects
|
/// * paths : An array with absolute/relative location(s) of directories with effects
|
||||||
|
/// * disable : An array with effect names that shouldn't be loaded
|
||||||
"effects" :
|
"effects" :
|
||||||
{
|
{
|
||||||
"paths" :
|
"paths" :
|
||||||
@ -364,6 +365,11 @@
|
|||||||
"/storage/hyperion/effects",
|
"/storage/hyperion/effects",
|
||||||
"/usr/share/hyperion/effects"
|
"/usr/share/hyperion/effects"
|
||||||
]
|
]
|
||||||
|
"disable" :
|
||||||
|
[
|
||||||
|
"Rainbow swirl",
|
||||||
|
"X-Mas"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The configuration for each individual led. This contains the specification of the area
|
/// The configuration for each individual led. This contains the specification of the area
|
||||||
|
@ -203,8 +203,6 @@
|
|||||||
{
|
{
|
||||||
"paths" :
|
"paths" :
|
||||||
[
|
[
|
||||||
"/storage/hyperion/effects",
|
|
||||||
"/usr/share/hyperion/effects"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
struct ActiveEffectDefinition
|
struct ActiveEffectDefinition
|
||||||
{
|
{
|
||||||
std::string script;
|
std::string script;
|
||||||
|
std::string name;
|
||||||
int priority;
|
int priority;
|
||||||
int timeout;
|
int timeout;
|
||||||
Json::Value args;
|
Json::Value args;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
// Json includes
|
// Json includes
|
||||||
#include <json/value.h>
|
#include <json/value.h>
|
||||||
@ -30,7 +31,7 @@ public:
|
|||||||
|
|
||||||
const std::list<ActiveEffectDefinition> & getActiveEffects();
|
const std::list<ActiveEffectDefinition> & getActiveEffects();
|
||||||
|
|
||||||
static bool loadEffectDefinition(const std::string & path, const std::string & effectConfigFile, EffectDefinition &effectDefinition);
|
static bool loadEffectDefinition(const QString & path, const QString & effectConfigFile, EffectDefinition &effectDefinition);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/// Run the specified effect on the given priority channel and optionally specify a timeout
|
/// Run the specified effect on the given priority channel and optionally specify a timeout
|
||||||
@ -50,7 +51,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/// Run the specified effect on the given priority channel and optionally specify a timeout
|
/// Run the specified effect on the given priority channel and optionally specify a timeout
|
||||||
int runEffectScript(const std::string &script, const Json::Value & args, int priority, int timeout = -1);
|
int runEffectScript(const std::string &script, const std::string &name, const Json::Value & args, int priority, int timeout = -1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Hyperion * _hyperion;
|
Hyperion * _hyperion;
|
||||||
|
@ -26,7 +26,16 @@ SET(EffectEngineSOURCES
|
|||||||
${CURRENT_SOURCE_DIR}/Effect.cpp
|
${CURRENT_SOURCE_DIR}/Effect.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(EffectEngine_RESOURCES ${CURRENT_SOURCE_DIR}/EffectEngine.qrc)
|
|
||||||
|
FILE ( GLOB effectFiles RELATIVE ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/effects/* )
|
||||||
|
SET ( HYPERION_EFFECTS_RES "")
|
||||||
|
FOREACH( f ${effectFiles} )
|
||||||
|
GET_FILENAME_COMPONENT(fname ${f} NAME)
|
||||||
|
SET(HYPERION_EFFECTS_RES "${HYPERION_EFFECTS_RES}\n\t\t<file alias=\"/effects/${fname}\">${f}</file>")
|
||||||
|
ENDFOREACH()
|
||||||
|
CONFIGURE_FILE(${CURRENT_SOURCE_DIR}/EffectEngine.qrc.in ${CMAKE_BINARY_DIR}/EffectEngine.qrc )
|
||||||
|
|
||||||
|
SET(EffectEngine_RESOURCES ${CMAKE_BINARY_DIR}/EffectEngine.qrc)
|
||||||
|
|
||||||
QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS})
|
QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS})
|
||||||
qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress")
|
qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress")
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
// effect engin eincludes
|
// effect engin eincludes
|
||||||
#include "Effect.h"
|
#include "Effect.h"
|
||||||
@ -50,12 +51,13 @@ void Effect::registerHyperionExtensionModule()
|
|||||||
PyImport_AppendInittab("hyperion", &PyInit_hyperion);
|
PyImport_AppendInittab("hyperion", &PyInit_hyperion);
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const std::string & script, const Json::Value & args)
|
Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const QString & script, const QString & name, const Json::Value & args)
|
||||||
: QThread()
|
: QThread()
|
||||||
, _mainThreadState(mainThreadState)
|
, _mainThreadState(mainThreadState)
|
||||||
, _priority(priority)
|
, _priority(priority)
|
||||||
, _timeout(timeout)
|
, _timeout(timeout)
|
||||||
, _script(script)
|
, _script(script)
|
||||||
|
, _name(name)
|
||||||
, _args(args)
|
, _args(args)
|
||||||
, _endTime(-1)
|
, _endTime(-1)
|
||||||
, _interpreterThreadState(nullptr)
|
, _interpreterThreadState(nullptr)
|
||||||
@ -70,6 +72,7 @@ Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const
|
|||||||
|
|
||||||
// connect the finished signal
|
// connect the finished signal
|
||||||
connect(this, SIGNAL(finished()), this, SLOT(effectFinished()));
|
connect(this, SIGNAL(finished()), this, SLOT(effectFinished()));
|
||||||
|
Q_INIT_RESOURCE(EffectEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect::~Effect()
|
Effect::~Effect()
|
||||||
@ -106,16 +109,22 @@ void Effect::run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run the effect script
|
// Run the effect script
|
||||||
FILE* file = fopen(_script.c_str(), "r");
|
QFile file (_script);
|
||||||
if (file != nullptr)
|
QByteArray python_code;
|
||||||
|
if (file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
PyRun_SimpleFile(file, _script.c_str());
|
python_code = file.readAll();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Error(Logger::getInstance("EFFECTENGINE"), "Unable to open script file %s", _script.c_str());
|
Error(Logger::getInstance("EFFECTENGINE"), "Unable to open script file %s", _script.toUtf8().constData());
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
if (!python_code.isEmpty())
|
||||||
|
{
|
||||||
|
PyRun_SimpleString(python_code.constData());
|
||||||
}
|
}
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
// Clean up the thread state
|
// Clean up the thread state
|
||||||
Py_EndInterpreter(_interpreterThreadState);
|
Py_EndInterpreter(_interpreterThreadState);
|
||||||
|
@ -14,14 +14,15 @@ class Effect : public QThread
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Effect(PyThreadState * mainThreadState, int priority, int timeout, const std::string & script, const Json::Value & args = Json::Value());
|
Effect(PyThreadState * mainThreadState, int priority, int timeout, const QString & script, const QString & name, const Json::Value & args = Json::Value());
|
||||||
virtual ~Effect();
|
virtual ~Effect();
|
||||||
|
|
||||||
virtual void run();
|
virtual void run();
|
||||||
|
|
||||||
int getPriority() const;
|
int getPriority() const;
|
||||||
|
|
||||||
std::string getScript() const { return _script; }
|
QString getScript() const { return _script; }
|
||||||
|
QString getName() const { return _name; }
|
||||||
|
|
||||||
int getTimeout() const {return _timeout; }
|
int getTimeout() const {return _timeout; }
|
||||||
|
|
||||||
@ -67,7 +68,8 @@ private:
|
|||||||
|
|
||||||
const int _timeout;
|
const int _timeout;
|
||||||
|
|
||||||
const std::string _script;
|
const QString _script;
|
||||||
|
const QString _name;
|
||||||
|
|
||||||
const Json::Value _args;
|
const Json::Value _args;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo
|
|||||||
, _mainThreadState(nullptr)
|
, _mainThreadState(nullptr)
|
||||||
, _log(Logger::getInstance("EFFECTENGINE"))
|
, _log(Logger::getInstance("EFFECTENGINE"))
|
||||||
{
|
{
|
||||||
|
Q_INIT_RESOURCE(EffectEngine);
|
||||||
qRegisterMetaType<std::vector<ColorRgb>>("std::vector<ColorRgb>");
|
qRegisterMetaType<std::vector<ColorRgb>>("std::vector<ColorRgb>");
|
||||||
|
|
||||||
// connect the Hyperion channel clear feedback
|
// connect the Hyperion channel clear feedback
|
||||||
@ -34,10 +35,25 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo
|
|||||||
|
|
||||||
// read all effects
|
// read all effects
|
||||||
const Json::Value & paths = jsonEffectConfig["paths"];
|
const Json::Value & paths = jsonEffectConfig["paths"];
|
||||||
|
const Json::Value & disabledEfx = jsonEffectConfig["disable"];
|
||||||
|
|
||||||
|
QStringList efxPathList;
|
||||||
|
efxPathList << ":/effects/";
|
||||||
for (Json::UInt i = 0; i < paths.size(); ++i)
|
for (Json::UInt i = 0; i < paths.size(); ++i)
|
||||||
{
|
{
|
||||||
const std::string & path = paths[i].asString();
|
efxPathList << QString::fromStdString(paths[i].asString());
|
||||||
QDir directory(QString::fromStdString(path));
|
}
|
||||||
|
|
||||||
|
QStringList disableList;
|
||||||
|
for (Json::UInt i = 0; i < disabledEfx.size(); ++i)
|
||||||
|
{
|
||||||
|
disableList << QString::fromStdString(disabledEfx[i].asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, EffectDefinition> availableEffects;
|
||||||
|
foreach (const QString & path, efxPathList )
|
||||||
|
{
|
||||||
|
QDir directory(path);
|
||||||
if (directory.exists())
|
if (directory.exists())
|
||||||
{
|
{
|
||||||
int efxCount = 0;
|
int efxCount = 0;
|
||||||
@ -45,14 +61,31 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo
|
|||||||
foreach (const QString & filename, filenames)
|
foreach (const QString & filename, filenames)
|
||||||
{
|
{
|
||||||
EffectDefinition def;
|
EffectDefinition def;
|
||||||
if (loadEffectDefinition(path, filename.toStdString(), def))
|
if (loadEffectDefinition(path, filename, def))
|
||||||
{
|
{
|
||||||
_availableEffects.push_back(def);
|
if (availableEffects.find(def.name) != availableEffects.end())
|
||||||
|
{
|
||||||
|
Info(_log, "effect overload effect '%s' is now taken from %s'", def.name.c_str(), path.toUtf8().constData() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( disableList.contains(QString::fromStdString(def.name)) )
|
||||||
|
{
|
||||||
|
Info(_log, "effect '%s' not loaded, because it is disabled in hyperion config", def.name.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
availableEffects[def.name] = def;
|
||||||
efxCount++;
|
efxCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Info(_log, "%d effects loaded from directory %s", efxCount, path.c_str());
|
|
||||||
}
|
}
|
||||||
|
Info(_log, "%d effects loaded from directory %s", efxCount, path.toUtf8().constData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(auto item, availableEffects)
|
||||||
|
{
|
||||||
|
_availableEffects.push_back(item.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_availableEffects.size() == 0)
|
if (_availableEffects.size() == 0)
|
||||||
@ -88,7 +121,8 @@ const std::list<ActiveEffectDefinition> &EffectEngine::getActiveEffects()
|
|||||||
for (Effect * effect : _activeEffects)
|
for (Effect * effect : _activeEffects)
|
||||||
{
|
{
|
||||||
ActiveEffectDefinition activeEffectDefinition;
|
ActiveEffectDefinition activeEffectDefinition;
|
||||||
activeEffectDefinition.script = effect->getScript();
|
activeEffectDefinition.script = effect->getScript().toStdString();
|
||||||
|
activeEffectDefinition.name = effect->getName().toStdString();
|
||||||
activeEffectDefinition.priority = effect->getPriority();
|
activeEffectDefinition.priority = effect->getPriority();
|
||||||
activeEffectDefinition.timeout = effect->getTimeout();
|
activeEffectDefinition.timeout = effect->getTimeout();
|
||||||
activeEffectDefinition.args = effect->getArgs();
|
activeEffectDefinition.args = effect->getArgs();
|
||||||
@ -98,26 +132,29 @@ const std::list<ActiveEffectDefinition> &EffectEngine::getActiveEffects()
|
|||||||
return _availableActiveEffects;
|
return _availableActiveEffects;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EffectEngine::loadEffectDefinition(const std::string &path, const std::string &effectConfigFile, EffectDefinition & effectDefinition)
|
bool EffectEngine::loadEffectDefinition(const QString &path, const QString &effectConfigFile, EffectDefinition & effectDefinition)
|
||||||
{
|
{
|
||||||
std::string fileName = path + QDir::separator().toLatin1() + effectConfigFile;
|
QString fileName = path + QDir::separator() + effectConfigFile;
|
||||||
std::ifstream file(fileName.c_str());
|
QFile file(fileName);
|
||||||
|
|
||||||
Logger * log = Logger::getInstance("EFFECTENGINE");
|
Logger * log = Logger::getInstance("EFFECTENGINE");
|
||||||
if (!file.is_open())
|
if (!file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
Error( log, "Effect file '%s' could not be loaded", fileName.c_str());
|
Error( log, "Effect file '%s' could not be loaded", fileName.toUtf8().constData());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
QByteArray fileContent = file.readAll();
|
||||||
// Read the json config file
|
// Read the json config file
|
||||||
Json::Reader jsonReader;
|
Json::Reader jsonReader;
|
||||||
Json::Value config;
|
Json::Value config;
|
||||||
if (!jsonReader.parse(file, config, false))
|
const char* fileContent_cStr = reinterpret_cast<const char *>(fileContent.constData());
|
||||||
|
|
||||||
|
if (! Json::Reader().parse(fileContent_cStr, fileContent_cStr+fileContent.size(), config, false) )
|
||||||
{
|
{
|
||||||
Error( log, "Error while reading effect '%s': %s", fileName.c_str(), jsonReader.getFormattedErrorMessages().c_str());
|
Error( log, "Error while reading effect '%s': %s", fileName.toUtf8().constData(), jsonReader.getFormattedErrorMessages().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
file.close();
|
||||||
|
|
||||||
// Read the json schema file
|
// Read the json schema file
|
||||||
QResource schemaData(":effect-schema");
|
QResource schemaData(":effect-schema");
|
||||||
@ -129,14 +166,22 @@ bool EffectEngine::loadEffectDefinition(const std::string &path, const std::stri
|
|||||||
{
|
{
|
||||||
const std::list<std::string> & errors = schemaChecker.getMessages();
|
const std::list<std::string> & errors = schemaChecker.getMessages();
|
||||||
foreach (const std::string & error, errors) {
|
foreach (const std::string & error, errors) {
|
||||||
Error( log, "Error while checking '%s':%s", fileName.c_str(), error.c_str());
|
Error( log, "Error while checking '%s':%s", fileName.toUtf8().constData(), error.c_str());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the definition
|
// setup the definition
|
||||||
|
std::string scriptName = config["script"].asString();
|
||||||
effectDefinition.name = config["name"].asString();
|
effectDefinition.name = config["name"].asString();
|
||||||
effectDefinition.script = path + QDir::separator().toLatin1() + config["script"].asString();
|
if (scriptName.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (scriptName[0] == ':' )
|
||||||
|
effectDefinition.script = ":/effects/"+scriptName.substr(1);
|
||||||
|
else
|
||||||
|
effectDefinition.script = path.toStdString() + QDir::separator().toLatin1() + scriptName;
|
||||||
|
|
||||||
effectDefinition.args = config["args"];
|
effectDefinition.args = config["args"];
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -167,22 +212,22 @@ int EffectEngine::runEffect(const std::string &effectName, const Json::Value &ar
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return runEffectScript(effectDefinition->script, args.isNull() ? effectDefinition->args : args, priority, timeout);
|
return runEffectScript(effectDefinition->script, effectName, args.isNull() ? effectDefinition->args : args, priority, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
int EffectEngine::runEffectScript(const std::string &script, const Json::Value &args, int priority, int timeout)
|
int EffectEngine::runEffectScript(const std::string &script, const std::string &name, const Json::Value &args, int priority, int timeout)
|
||||||
{
|
{
|
||||||
// clear current effect on the channel
|
// clear current effect on the channel
|
||||||
channelCleared(priority);
|
channelCleared(priority);
|
||||||
|
|
||||||
// create the effect
|
// create the effect
|
||||||
Effect * effect = new Effect(_mainThreadState, priority, timeout, script, args);
|
Effect * effect = new Effect(_mainThreadState, priority, timeout, QString::fromStdString(script), QString::fromStdString(name), args);
|
||||||
connect(effect, SIGNAL(setColors(int,std::vector<ColorRgb>,int,bool)), _hyperion, SLOT(setColors(int,std::vector<ColorRgb>,int,bool)), Qt::QueuedConnection);
|
connect(effect, SIGNAL(setColors(int,std::vector<ColorRgb>,int,bool)), _hyperion, SLOT(setColors(int,std::vector<ColorRgb>,int,bool)), Qt::QueuedConnection);
|
||||||
connect(effect, SIGNAL(effectFinished(Effect*)), this, SLOT(effectFinished(Effect*)));
|
connect(effect, SIGNAL(effectFinished(Effect*)), this, SLOT(effectFinished(Effect*)));
|
||||||
_activeEffects.push_back(effect);
|
_activeEffects.push_back(effect);
|
||||||
|
|
||||||
// start the effect
|
// start the effect
|
||||||
_hyperion->registerPriority("EFFECT: "+FileUtils::getBaseName(script), priority);
|
_hyperion->registerPriority("EFFECT: "+name, priority);
|
||||||
effect->start();
|
effect->start();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -227,5 +272,5 @@ void EffectEngine::effectFinished(Effect *effect)
|
|||||||
|
|
||||||
// cleanup the effect
|
// cleanup the effect
|
||||||
effect->deleteLater();
|
effect->deleteLater();
|
||||||
_hyperion->unRegisterPriority("EFFECT: " + FileUtils::getBaseName(effect->getScript()));
|
_hyperion->unRegisterPriority("EFFECT: " + effect->getName().toStdString());
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file alias="effect-schema">EffectDefinition.schema.json</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
6
libsrc/effectengine/EffectEngine.qrc.in
Normal file
6
libsrc/effectengine/EffectEngine.qrc.in
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file alias="effect-schema">${CURRENT_SOURCE_DIR}/EffectDefinition.schema.json</file>
|
||||||
|
${HYPERION_EFFECTS_RES}
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
@ -502,7 +502,7 @@ LinearColorSmoothing * Hyperion::createColorSmoothing(const Json::Value & smooth
|
|||||||
Logger * log = Logger::getInstance("Core");
|
Logger * log = Logger::getInstance("Core");
|
||||||
std::string type = smoothingConfig.get("type", "linear").asString();
|
std::string type = smoothingConfig.get("type", "linear").asString();
|
||||||
std::transform(type.begin(), type.end(), type.begin(), ::tolower);
|
std::transform(type.begin(), type.end(), type.begin(), ::tolower);
|
||||||
LinearColorSmoothing * device;
|
LinearColorSmoothing * device = nullptr;
|
||||||
type = "linear"; // TODO currently hardcoded type, delete it if we have more types
|
type = "linear"; // TODO currently hardcoded type, delete it if we have more types
|
||||||
|
|
||||||
if (type == "linear")
|
if (type == "linear")
|
||||||
@ -524,6 +524,7 @@ LinearColorSmoothing * Hyperion::createColorSmoothing(const Json::Value & smooth
|
|||||||
device->setEnable(smoothingConfig.get("enable", true).asBool());
|
device->setEnable(smoothingConfig.get("enable", true).asBool());
|
||||||
InfoIf(!device->enabled(), log,"Smoothing disabled");
|
InfoIf(!device->enabled(), log,"Smoothing disabled");
|
||||||
|
|
||||||
|
assert(device == nullptr);
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,6 +1034,10 @@
|
|||||||
"properties" :
|
"properties" :
|
||||||
{
|
{
|
||||||
"paths" :
|
"paths" :
|
||||||
|
{
|
||||||
|
"type" : "array"
|
||||||
|
},
|
||||||
|
"disable" :
|
||||||
{
|
{
|
||||||
"type" : "array"
|
"type" : "array"
|
||||||
}
|
}
|
||||||
|
@ -571,6 +571,7 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &, const st
|
|||||||
{
|
{
|
||||||
Json::Value activeEffect;
|
Json::Value activeEffect;
|
||||||
activeEffect["script"] = activeEffectDefinition.script;
|
activeEffect["script"] = activeEffectDefinition.script;
|
||||||
|
activeEffect["name"] = activeEffectDefinition.name;
|
||||||
activeEffect["priority"] = activeEffectDefinition.priority;
|
activeEffect["priority"] = activeEffectDefinition.priority;
|
||||||
activeEffect["timeout"] = activeEffectDefinition.timeout;
|
activeEffect["timeout"] = activeEffectDefinition.timeout;
|
||||||
activeEffect["args"] = activeEffectDefinition.args;
|
activeEffect["args"] = activeEffectDefinition.args;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"output" : {
|
"output" : {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"title":"Target IP",
|
"title":"Target IP",
|
||||||
|
"default" : "127.0.0.1",
|
||||||
"propertyOrder" : 1
|
"propertyOrder" : 1
|
||||||
},
|
},
|
||||||
"port" : {
|
"port" : {
|
||||||
@ -52,6 +53,7 @@
|
|||||||
"whitepoint" : {
|
"whitepoint" : {
|
||||||
"type" : "array",
|
"type" : "array",
|
||||||
"propertyOrder" : 9,
|
"propertyOrder" : 9,
|
||||||
|
"default" : [1.0,1.0,1.0],
|
||||||
"items" : {
|
"items" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"minimum" : 0.0,
|
"minimum" : 0.0,
|
||||||
|
@ -40,7 +40,6 @@ if (ENABLE_X11)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
install ( TARGETS hyperiond DESTINATION "share/hyperion/bin/" COMPONENT "${PLATFORM}" )
|
install ( TARGETS hyperiond DESTINATION "share/hyperion/bin/" COMPONENT "${PLATFORM}" )
|
||||||
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "share/hyperion/" COMPONENT "${PLATFORM}" )
|
|
||||||
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT "${PLATFORM}" )
|
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT "${PLATFORM}" )
|
||||||
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/config DESTINATION "share/hyperion/" COMPONENT "${PLATFORM}" )
|
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/config DESTINATION "share/hyperion/" COMPONENT "${PLATFORM}" )
|
||||||
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/assets/webconfig DESTINATION "share/hyperion/" COMPONENT "${PLATFORM}" )
|
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/assets/webconfig DESTINATION "share/hyperion/" COMPONENT "${PLATFORM}" )
|
||||||
|
Loading…
Reference in New Issue
Block a user