|
|
|
/** Modified from original Node-Red source, for audio system visualization
|
|
|
|
* vim: set ts=4:
|
|
|
|
* Copyright 2013 IBM Corp.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
**/
|
|
|
|
var RED = (function() {
|
|
|
|
|
|
|
|
$('#btn-keyboard-shortcuts').click(function(){showHelp();});
|
|
|
|
|
|
|
|
function hideDropTarget() {
|
|
|
|
$("#dropTarget").hide();
|
|
|
|
RED.keyboard.remove(/* ESCAPE */ 27);
|
|
|
|
}
|
|
|
|
|
|
|
|
$('#chart').on("dragenter",function(event) {
|
|
|
|
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
|
|
|
$("#dropTarget").css({display:'table'});
|
|
|
|
RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$('#dropTarget').on("dragover",function(event) {
|
|
|
|
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.on("dragleave",function(event) {
|
|
|
|
hideDropTarget();
|
|
|
|
})
|
|
|
|
.on("drop",function(event) {
|
|
|
|
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
|
|
|
hideDropTarget();
|
|
|
|
RED.view.importNodes(data);
|
|
|
|
event.preventDefault();
|
|
|
|
});
|
|
|
|
function make_name(n) {
|
|
|
|
var name = (n.name ? n.name : n.id);
|
|
|
|
name = name.replace(" ", "_").replace("+", "_").replace("-", "_");
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
|
|
|
function save(force) {
|
|
|
|
RED.storage.update();
|
|
|
|
|
|
|
|
if (RED.nodes.hasIO()) {
|
|
|
|
var nns = RED.nodes.createCompleteNodeSet();
|
|
|
|
// sort by horizontal position, plus slight vertical position,
|
|
|
|
// for well defined update order that follows signal flow
|
|
|
|
nns.sort(function(a,b){ return (a.x + a.y/250) - (b.x + b.y/250); });
|
|
|
|
//console.log(JSON.stringify(nns));
|
|
|
|
|
|
|
|
//add the include files first
|
|
|
|
var cpp = "#include <OpenAudio_ArduinoLibrary.h>\n#include <Audio.h>\n"
|
|
|
|
+ "#include <Wire.h>\n"
|
|
|
|
+ "#include <SPI.h>\n#include <SD.h>\n#include <SerialFlash.h>\n\n"
|
|
|
|
+ "// GUItool: begin automatically generated code\n";
|
|
|
|
// generate code for all audio processing nodes
|
|
|
|
for (var i=0; i<nns.length; i++) {
|
|
|
|
var n = nns[i];
|
|
|
|
var node = RED.nodes.node(n.id);
|
|
|
|
if (node && (node.outputs > 0 || node._def.inputs > 0)) {
|
|
|
|
cpp += n.type + " ";
|
|
|
|
for (var j=n.type.length; j<24; j++) cpp += " ";
|
|
|
|
var name = make_name(n)
|
|
|
|
cpp += name + "; ";
|
|
|
|
for (var j=n.id.length; j<14; j++) cpp += " ";
|
|
|
|
cpp += "//xy=" + n.x + "," + n.y + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// generate code for all connections (aka wires or links)
|
|
|
|
var cordcount = 1;
|
|
|
|
for (var i=0; i<nns.length; i++) {
|
|
|
|
var n = nns[i];
|
|
|
|
if (n.wires) {
|
|
|
|
for (var j=0; j<n.wires.length; j++) {
|
|
|
|
var wires = n.wires[j];
|
|
|
|
if (!wires) continue;
|
|
|
|
for (var k=0; k<wires.length; k++) {
|
|
|
|
var wire = n.wires[j][k];
|
|
|
|
if (wire) {
|
|
|
|
var parts = wire.split(":");
|
|
|
|
if (parts.length == 2) {
|
|
|
|
cpp += "AudioConnection_F32 patchCord" + cordcount + "(";
|
|
|
|
var src = RED.nodes.node(n.id);
|
|
|
|
var dst = RED.nodes.node(parts[0]);
|
|
|
|
var src_name = make_name(src);
|
|
|
|
var dst_name = make_name(dst);
|
|
|
|
if (j == 0 && parts[1] == 0 && src && src.outputs == 1 && dst && dst._def.inputs == 1) {
|
|
|
|
cpp += src_name + ", " + parts[0];
|
|
|
|
} else {
|
|
|
|
cpp += src_name + ", " + j + ", " + dst_name + ", " + parts[1];
|
|
|
|
}
|
|
|
|
cpp += ");\n";
|
|
|
|
cordcount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// generate code for all control nodes (no inputs or outputs)
|
|
|
|
for (var i=0; i<nns.length; i++) {
|
|
|
|
var n = nns[i];
|
|
|
|
var node = RED.nodes.node(n.id);
|
|
|
|
if (node && node.outputs == 0 && node._def.inputs == 0) {
|
|
|
|
cpp += n.type + " ";
|
|
|
|
for (var j=n.type.length; j<24; j++) cpp += " ";
|
|
|
|
cpp += n.id + "; ";
|
|
|
|
for (var j=n.id.length; j<14; j++) cpp += " ";
|
|
|
|
cpp += "//xy=" + n.x + "," + n.y + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cpp += "// GUItool: end automatically generated code\n";
|
|
|
|
|
|
|
|
// generate setup()
|
|
|
|
cpp += "\n";
|
|
|
|
cpp += "\n";
|
|
|
|
cpp += "//The setup function is called once when the system starts up\n";
|
|
|
|
cpp += "void setup(void) {\n";
|
|
|
|
cpp += "\t" + "//Start the USB serial link (to enable debugging)\n";
|
|
|
|
cpp += "\t" + "Serial.begin(115200); delay(500);\n";
|
|
|
|
cpp += "\t" + "Serial.println(\"Setup starting...\");\n";
|
|
|
|
cpp += "\t" + "\n"
|
|
|
|
cpp += "\t" + "//Allocate dynamically shuffled memory for the audio subsystem\n";
|
|
|
|
cpp += "\t" + "AudioMemory(10); AudioMemory_F32(10);\n";
|
|
|
|
cpp += "\t" + "\n";
|
|
|
|
cpp += "\t" + "//Put your own setup code here\n";
|
|
|
|
cpp += "\t" + "\n";
|
|
|
|
cpp += "\t" + "//End of setup\n";
|
|
|
|
cpp += "\t" + "Serial.println(\"Setup complete.\");\n";
|
|
|
|
cpp += "};\n";
|
|
|
|
|
|
|
|
// generate loop()
|
|
|
|
cpp += "\n";
|
|
|
|
cpp += "\n";
|
|
|
|
cpp += "//After setup(), the loop function loops forever.\n";
|
|
|
|
cpp += "//Note that the audio modules are called in the background.\n";
|
|
|
|
cpp += "//They do not need to be serviced by the loop() function.\n"
|
|
|
|
cpp += "void loop(void) {\n";
|
|
|
|
cpp += "\n";
|
|
|
|
cpp += "};";
|
|
|
|
//console.log(cpp);
|
|
|
|
|
|
|
|
RED.view.state(RED.state.EXPORT);
|
|
|
|
RED.view.getForm('dialog-form', 'export-clipboard-dialog', function (d, f) {
|
|
|
|
$("#node-input-export").val(cpp).focus(function() {
|
|
|
|
var textarea = $(this);
|
|
|
|
textarea.select();
|
|
|
|
textarea.mouseup(function() {
|
|
|
|
textarea.unbind("mouseup");
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}).focus();
|
|
|
|
$( "#dialog" ).dialog("option","title","Export to Arduino").dialog("option","width",600).dialog( "open" );
|
|
|
|
});
|
|
|
|
//RED.view.dirty(false);
|
|
|
|
} else {
|
|
|
|
$( "#node-dialog-error-deploy" ).dialog({
|
|
|
|
title: "Error exporting data to Arduino IDE",
|
|
|
|
modal: true,
|
|
|
|
autoOpen: false,
|
|
|
|
width: 410,
|
|
|
|
height: 245,
|
|
|
|
buttons: [{
|
|
|
|
text: "Ok",
|
|
|
|
click: function() {
|
|
|
|
$( this ).dialog( "close" );
|
|
|
|
}
|
|
|
|
}]
|
|
|
|
}).dialog("open");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$('#btn-deploy').click(function() { save(); });
|
|
|
|
|
|
|
|
|
|
|
|
$( "#node-dialog-confirm-deploy" ).dialog({
|
|
|
|
title: "Confirm deploy",
|
|
|
|
modal: true,
|
|
|
|
autoOpen: false,
|
|
|
|
width: 530,
|
|
|
|
height: 230,
|
|
|
|
buttons: [
|
|
|
|
{
|
|
|
|
text: "Confirm deploy",
|
|
|
|
click: function() {
|
|
|
|
save(true);
|
|
|
|
$( this ).dialog( "close" );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text: "Cancel",
|
|
|
|
click: function() {
|
|
|
|
$( this ).dialog( "close" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
});
|
|
|
|
|
|
|
|
// from http://css-tricks.com/snippets/javascript/get-url-variables/
|
|
|
|
function getQueryVariable(variable) {
|
|
|
|
var query = window.location.search.substring(1);
|
|
|
|
var vars = query.split("&");
|
|
|
|
for (var i=0;i<vars.length;i++) {
|
|
|
|
var pair = vars[i].split("=");
|
|
|
|
if(pair[0] == variable){return pair[1];}
|
|
|
|
}
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
function loadNodes() {
|
|
|
|
$(".palette-scroll").show();
|
|
|
|
$("#palette-search").show();
|
|
|
|
RED.storage.load();
|
|
|
|
RED.view.redraw();
|
|
|
|
setTimeout(function() {
|
|
|
|
$("#btn-deploy").removeClass("disabled").addClass("btn-danger");
|
|
|
|
$("#btn-import").removeClass("disabled").addClass("btn-success");
|
|
|
|
}, 1500);
|
|
|
|
$('#btn-deploy').click(function() { save(); });
|
|
|
|
// if the query string has ?info=className, populate info tab
|
|
|
|
var info = getQueryVariable("info");
|
|
|
|
if (info) {
|
|
|
|
RED.sidebar.info.setHelpContent('', info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$('#btn-node-status').click(function() {toggleStatus();});
|
|
|
|
|
|
|
|
var statusEnabled = false;
|
|
|
|
function toggleStatus() {
|
|
|
|
var btnStatus = $("#btn-node-status");
|
|
|
|
statusEnabled = btnStatus.toggleClass("active").hasClass("active");
|
|
|
|
RED.view.status(statusEnabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
function showHelp() {
|
|
|
|
|
|
|
|
var dialog = $('#node-help');
|
|
|
|
|
|
|
|
//$("#node-help").draggable({
|
|
|
|
// handle: ".modal-header"
|
|
|
|
//});
|
|
|
|
|
|
|
|
dialog.on('show',function() {
|
|
|
|
RED.keyboard.disable();
|
|
|
|
});
|
|
|
|
dialog.on('hidden',function() {
|
|
|
|
RED.keyboard.enable();
|
|
|
|
});
|
|
|
|
|
|
|
|
dialog.modal();
|
|
|
|
}
|
|
|
|
|
|
|
|
$(function() {
|
|
|
|
$(".palette-spinner").show();
|
|
|
|
|
|
|
|
// server test switched off - test purposes only
|
|
|
|
var patt = new RegExp(/^[http|https]/);
|
|
|
|
var server = false && patt.test(location.protocol);
|
|
|
|
|
|
|
|
if (!server) {
|
|
|
|
var data = $.parseJSON($("script[data-container-name|='NodeDefinitions']").html());
|
|
|
|
var nodes = data["nodes"];
|
|
|
|
$.each(nodes, function (key, val) {
|
|
|
|
RED.nodes.registerType(val["type"], val["data"]);
|
|
|
|
});
|
|
|
|
RED.keyboard.add(/* ? */ 191, {shift: true}, function () {
|
|
|
|
showHelp();
|
|
|
|
d3.event.preventDefault();
|
|
|
|
});
|
|
|
|
loadNodes();
|
|
|
|
$(".palette-spinner").hide();
|
|
|
|
} else {
|
|
|
|
$.ajaxSetup({beforeSend: function(xhr){
|
|
|
|
if (xhr.overrideMimeType) {
|
|
|
|
xhr.overrideMimeType("application/json");
|
|
|
|
}
|
|
|
|
}});
|
|
|
|
$.getJSON( "resources/nodes_def.json", function( data ) {
|
|
|
|
var nodes = data["nodes"];
|
|
|
|
$.each(nodes, function(key, val) {
|
|
|
|
RED.nodes.registerType(val["type"], val["data"]);
|
|
|
|
});
|
|
|
|
RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();});
|
|
|
|
loadNodes();
|
|
|
|
$(".palette-spinner").hide();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return {
|
|
|
|
};
|
|
|
|
})();
|