You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 line
8.9KB

  1. /** Modified from original Node-Red source, for audio system visualization
  2. * vim: set ts=4:
  3. * Copyright 2013 IBM Corp.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. **/
  17. var RED = (function() {
  18. $('#btn-keyboard-shortcuts').click(function(){showHelp();});
  19. function hideDropTarget() {
  20. $("#dropTarget").hide();
  21. RED.keyboard.remove(/* ESCAPE */ 27);
  22. }
  23. $('#chart').on("dragenter",function(event) {
  24. if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
  25. $("#dropTarget").css({display:'table'});
  26. RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
  27. }
  28. });
  29. $('#dropTarget').on("dragover",function(event) {
  30. if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
  31. event.preventDefault();
  32. }
  33. })
  34. .on("dragleave",function(event) {
  35. hideDropTarget();
  36. })
  37. .on("drop",function(event) {
  38. var data = event.originalEvent.dataTransfer.getData("text/plain");
  39. hideDropTarget();
  40. RED.view.importNodes(data);
  41. event.preventDefault();
  42. });
  43. function save(force) {
  44. if (RED.view.dirty()) {
  45. if (!force) {
  46. var invalid = false;
  47. var unknownNodes = [];
  48. RED.nodes.eachNode(function(node) {
  49. invalid = invalid || !node.valid;
  50. if (node.type === "unknown") {
  51. if (unknownNodes.indexOf(node.name) == -1) {
  52. unknownNodes.push(node.name);
  53. }
  54. invalid = true;
  55. }
  56. });
  57. if (invalid) {
  58. if (unknownNodes.length > 0) {
  59. $( "#node-dialog-confirm-deploy-config" ).hide();
  60. $( "#node-dialog-confirm-deploy-unknown" ).show();
  61. var list = "<li>"+unknownNodes.join("</li><li>")+"</li>";
  62. $( "#node-dialog-confirm-deploy-unknown-list" ).html(list);
  63. } else {
  64. $( "#node-dialog-confirm-deploy-config" ).show();
  65. $( "#node-dialog-confirm-deploy-unknown" ).hide();
  66. }
  67. $( "#node-dialog-confirm-deploy" ).dialog( "open" );
  68. return;
  69. }
  70. }
  71. var nns = RED.nodes.createCompleteNodeSet();
  72. // sort by horizontal position, plus slight vertical position,
  73. // for well defined update order that follows signal flow
  74. nns.sort(function(a,b){ return (a.x + a.y/250) - (b.x + b.y/250); });
  75. //console.log(JSON.stringify(nns));
  76. var cpp = "// GUItool: begin automatically generated code\n";
  77. // generate code for all audio processing nodes
  78. for (var i=0; i<nns.length; i++) {
  79. var n = nns[i];
  80. var node = RED.nodes.node(n.id);
  81. if (node && (node.outputs > 0 || node._def.inputs > 0)) {
  82. cpp += n.type + " ";
  83. for (var j=n.type.length; j<24; j++) cpp += " ";
  84. cpp += n.id + "; ";
  85. for (var j=n.id.length; j<14; j++) cpp += " ";
  86. cpp += "//xy=" + n.x + "," + n.y + "\n";
  87. }
  88. }
  89. // generate code for all connections (aka wires or links)
  90. var cordcount = 1;
  91. for (var i=0; i<nns.length; i++) {
  92. var n = nns[i];
  93. if (n.wires) {
  94. for (var j=0; j<n.wires.length; j++) {
  95. var wires = n.wires[j];
  96. if (!wires) continue;
  97. for (var k=0; k<wires.length; k++) {
  98. var wire = n.wires[j][k];
  99. if (wire) {
  100. var parts = wire.split(":");
  101. if (parts.length == 2) {
  102. cpp += "AudioConnection patchCord" + cordcount + "(";
  103. var src = RED.nodes.node(n.id);
  104. var dst = RED.nodes.node(parts[0]);
  105. if (j == 0 && parts[1] == 0 && src && src.outputs == 1 && dst && dst._def.inputs == 1) {
  106. cpp += n.id + ", " + parts[0];
  107. } else {
  108. cpp += n.id + ", " + j + ", " + parts[0] + ", " + parts[1];
  109. }
  110. cpp += ");\n";
  111. cordcount++;
  112. }
  113. }
  114. }
  115. }
  116. }
  117. }
  118. // generate code for all control nodes (no inputs or outputs)
  119. for (var i=0; i<nns.length; i++) {
  120. var n = nns[i];
  121. var node = RED.nodes.node(n.id);
  122. if (node && node.outputs == 0 && node._def.inputs == 0) {
  123. cpp += n.type + " ";
  124. for (var j=n.type.length; j<24; j++) cpp += " ";
  125. cpp += n.id + "; ";
  126. for (var j=n.id.length; j<14; j++) cpp += " ";
  127. cpp += "//xy=" + n.x + "," + n.y + "\n";
  128. }
  129. }
  130. cpp += "// GUItool: end automatically generated code\n";
  131. //console.log(cpp);
  132. RED.view.state(RED.state.EXPORT);
  133. //mouse_mode = RED.state.EXPORT;
  134. $("#dialog-form").html($("script[data-template-name='export-clipboard-dialog']").html());
  135. $("#node-input-export").val(cpp);
  136. $("#node-input-export").focus(function() {
  137. var textarea = $(this);
  138. textarea.select();
  139. textarea.mouseup(function() {
  140. textarea.unbind("mouseup");
  141. return false;
  142. });
  143. });
  144. $( "#dialog" ).dialog("option","title","Export nodes to clipboard").dialog( "open" );
  145. $("#node-input-export").focus();
  146. /*
  147. $("#btn-icn-deploy").removeClass('icon-upload');
  148. $("#btn-icn-deploy").addClass('spinner');
  149. RED.view.dirty(false);
  150. $.ajax({
  151. url:"flows",
  152. type: "POST",
  153. data: JSON.stringify(nns),
  154. contentType: "application/json; charset=utf-8"
  155. }).done(function(data,textStatus,xhr) {
  156. RED.notify("Successfully deployed","success");
  157. RED.nodes.eachNode(function(node) {
  158. if (node.changed) {
  159. node.dirty = true;
  160. node.changed = false;
  161. }
  162. if(node.credentials) {
  163. delete node.credentials;
  164. }
  165. });
  166. RED.nodes.eachConfig(function (confNode) {
  167. if (confNode.credentials) {
  168. delete confNode.credentials;
  169. }
  170. });
  171. // Once deployed, cannot undo back to a clean state
  172. RED.history.markAllDirty();
  173. RED.view.redraw();
  174. }).fail(function(xhr,textStatus,err) {
  175. RED.view.dirty(true);
  176. if (xhr.responseText) {
  177. RED.notify("<strong>Error</strong>: "+xhr.responseText,"error");
  178. } else {
  179. RED.notify("<strong>Error</strong>: no response from server","error");
  180. }
  181. }).always(function() {
  182. $("#btn-icn-deploy").removeClass('spinner');
  183. $("#btn-icn-deploy").addClass('icon-upload');
  184. });
  185. */
  186. }
  187. }
  188. $('#btn-deploy').click(function() { save(); });
  189. $( "#node-dialog-confirm-deploy" ).dialog({
  190. title: "Confirm deploy",
  191. modal: true,
  192. autoOpen: false,
  193. width: 530,
  194. height: 230,
  195. buttons: [
  196. {
  197. text: "Confirm deploy",
  198. click: function() {
  199. save(true);
  200. $( this ).dialog( "close" );
  201. }
  202. },
  203. {
  204. text: "Cancel",
  205. click: function() {
  206. $( this ).dialog( "close" );
  207. }
  208. }
  209. ]
  210. });
  211. function loadSettings() {
  212. /*
  213. $.get('settings', function(data) {
  214. RED.settings = data;
  215. console.log("Node-RED: "+data.version);
  216. loadNodes();
  217. });
  218. */
  219. loadNodes();
  220. }
  221. function loadNodes() {
  222. console.log("loadNodes");
  223. $.get('list.html', function(data) {
  224. console.log("loadNodes complete");
  225. $("body").append(data);
  226. $(".palette-spinner").hide();
  227. $(".palette-scroll").show();
  228. $("#palette-search").show();
  229. //loadFlows();
  230. }, "html");
  231. }
  232. function loadFlows() {
  233. $.getJSON("flows",function(nodes) {
  234. RED.nodes.import(nodes);
  235. RED.view.dirty(false);
  236. RED.view.redraw();
  237. RED.comms.subscribe("status/#",function(topic,msg) {
  238. var parts = topic.split("/");
  239. var node = RED.nodes.node(parts[1]);
  240. if (node) {
  241. node.status = msg;
  242. if (statusEnabled) {
  243. node.dirty = true;
  244. RED.view.redraw();
  245. }
  246. }
  247. });
  248. RED.comms.subscribe("node/#",function(topic,msg) {
  249. var i;
  250. if (topic == "node/added") {
  251. for (i=0;i<msg.length;i++) {
  252. var m = msg[i];
  253. var id = m.id;
  254. $.get('nodes/'+id, function(data) {
  255. $("body").append(data);
  256. var typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>";
  257. RED.notify("Node"+(m.types.length!=1 ? "s":"")+" added to palette:"+typeList,"success");
  258. });
  259. }
  260. } else if (topic == "node/removed") {
  261. if (msg.types) {
  262. for (i=0;i<msg.types.length;i++) {
  263. RED.palette.remove(msg.types[i]);
  264. }
  265. var typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
  266. RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" removed from palette:"+typeList,"success");
  267. }
  268. }
  269. });
  270. });
  271. }
  272. $('#btn-node-status').click(function() {toggleStatus();});
  273. var statusEnabled = false;
  274. function toggleStatus() {
  275. var btnStatus = $("#btn-node-status");
  276. statusEnabled = btnStatus.toggleClass("active").hasClass("active");
  277. RED.view.status(statusEnabled);
  278. }
  279. function showHelp() {
  280. var dialog = $('#node-help');
  281. //$("#node-help").draggable({
  282. // handle: ".modal-header"
  283. //});
  284. dialog.on('show',function() {
  285. RED.keyboard.disable();
  286. });
  287. dialog.on('hidden',function() {
  288. RED.keyboard.enable();
  289. });
  290. dialog.modal();
  291. }
  292. $(function() {
  293. RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();});
  294. loadSettings();
  295. RED.comms.connect();
  296. });
  297. return {
  298. };
  299. })();