1. 1 : /*
  2. 2 : * This file is part of the Companion project
  3. 3 : * Copyright (c) 2018 Bitfocus AS
  4. 4 : * Authors: William Viker <william@bitfocus.io>, Håkon Nessjøen <haakon@bitfocus.io>
  5. 5 : *
  6. 6 : * This program is free software.
  7. 7 : * You should have received a copy of the MIT licence as well as the Bitfocus
  8. 8 : * Individual Contributor License Agreement for companion along with
  9. 9 : * this program.
  10. 10 : *
  11. 11 : * You can be released from the requirements of the license by purchasing
  12. 12 : * a commercial license. Buying such a license is mandatory as soon as you
  13. 13 : * develop commercial activities involving the Companion software without
  14. 14 : * disclosing the source code of your own applications.
  15. 15 : *
  16. 16 : */
  17. 17 :
  18. 18 :
  19. 19 : if (process.env.DEVELOPER !== undefined) {
  20. 20 : process.env['DEBUG'] = '*,-websocket*,-express*,-engine*,-socket.io*,-send*,-db,-NRC*,-follow-redirects,-electron-timer-fix';
  21. 21 : }
  22. 22 :
  23. 23 : // Fix timers in electron
  24. 24 : // require('./electron-timer-fix').fix();
  25. 25 :
  26. 26 : global.MAX_BUTTONS = 32;
  27. 27 : global.MAX_BUTTONS_PER_ROW = 8;
  28. 28 :
  29. 29 : var EventEmitter = require('events');
  30. 30 : /**
  31. 31 : * The application's event emitter for core functionality which allows for some point to multi-point calls
  32. 32 : * and `skeleton` to `app` functionality.
  33. 33 : * N.B. This is not the same `system` referenced by instances. See {@link InstanceSystem}.
  34. 34 : * @class System
  35. 35 : * @extends EventEmitter
  36. 36 : */
  37. 37 : var system = new EventEmitter();
  38. 38 : var fs = require("fs");
  39. 39 : var debug = require('debug')('app');
  40. 40 : var mkdirp = require('mkdirp');
  41. 41 : var stripAnsi = require('strip-ansi');
  42. 42 : var logbuffer = [];
  43. 43 : var logwriting = false;
  44. 44 : var skeleton_info = {};
  45. 45 :
  46. 46 : var config;
  47. 47 : var cfgDir;
  48. 48 :
  49. 49 : // Supress warnings for too many listeners to io_connect. This can be safely increased if the warning comes back at startup
  50. 50 : system.setMaxListeners(20)
  51. 51 :
  52. 52 : system.on('skeleton-info', function(key, val) {
  53. 53 : skeleton_info[key] = val;
  54. 54 : if (key == 'configDir') {
  55. 55 : debug('configuration directory', val);
  56. 56 : cfgDir = val + "/companion/";
  57. 57 : mkdirp(cfgDir, function(err) {
  58. 58 : debug("mkdirp",cfgDir,err);
  59. 59 : config = new (require('./lib/Data/Config'))(system, cfgDir, {
  60. 60 : http_port: 8888,
  61. 61 : bind_ip: "127.0.0.1",
  62. 62 : start_minimised: false,
  63. 63 : });
  64. 64 : });
  65. 65 : }
  66. 66 : });
  67. 67 :
  68. 68 : system.on('configdir_get', function (cb) {
  69. 69 : cb(cfgDir);
  70. 70 : });
  71. 71 :
  72. 72 : system.on('skeleton-info-info', function(cb) {
  73. 73 : cb(skeleton_info);
  74. 74 : });
  75. 75 :
  76. 76 : system.on('config_loaded', function(config) {
  77. 77 : system.emit('skeleton-info', 'appURL', 'Waiting for webserver..');
  78. 78 : system.emit('skeleton-info', 'appStatus', 'Starting');
  79. 79 : system.emit('skeleton-info', 'bindInterface', config.bind_ip);
  80. 80 : system.emit('skeleton-info', 'startMinimised', config.start_minimised);
  81. 81 : });
  82. 82 :
  83. 83 : system.on('exit', function() {
  84. 84 : console.log("somewhere, the system wants to exit. kthxbai");
  85. 85 :
  86. 86 : system.emit('instance_getall', function(instances, active) {
  87. 87 : try {
  88. 88 : for (var key in active) {
  89. 89 : if (instances[key].label !== 'internal') {
  90. 90 : try {
  91. 91 : active[key].destroy();
  92. 92 : } catch(e) {
  93. 93 : console.log("Could not destroy",instances[key].label);
  94. 94 : }
  95. 95 : }
  96. 96 : }
  97. 97 : } catch(e) {
  98. 98 : console.log("Could not destroy all instances");
  99. 99 : }
  100. 100 : });
  101. 101 :
  102. 102 : setImmediate(function(){
  103. 103 : process.exit();
  104. 104 : });
  105. 105 : });
  106. 106 :
  107. 107 :
  108. 108 : system.on('skeleton-bind-ip', function(ip) {
  109. 109 : config.bind_ip = ip;
  110. 110 : system.emit('config_set', 'bind_ip', ip);
  111. 111 : system.emit('ip_rebind');
  112. 112 : });
  113. 113 :
  114. 114 : system.on('skeleton-bind-port', function(port) {
  115. 115 : var p = parseInt(port);
  116. 116 : if (p >= 1024 && p <= 65535) {
  117. 117 : config.http_port = p;
  118. 118 : system.emit('config_set', 'http_port', p);
  119. 119 : system.emit('ip_rebind');
  120. 120 : }
  121. 121 : });
  122. 122 :
  123. 123 : system.on('skeleton-start-minimised', function(minimised) {
  124. 124 : config.start_minimised = minimised;
  125. 125 : system.emit('config_set', 'start_minimised', minimised);
  126. 126 : });
  127. 127 :
  128. 128 : system.on('skeleton-ready', function() {
  129. 129 :
  130. 130 : if (system.headless === true) {
  131. 131 : debug("Going into headless mode. Logs will be written to companion.log")
  132. 132 :
  133. 133 : setInterval(function() {
  134. 134 :
  135. 135 : if (logbuffer.length > 0 && logwriting == false) {
  136. 136 : var writestring = logbuffer.join("\n");
  137. 137 : logbuffer = [];
  138. 138 : logwriting = true;
  139. 139 : fs.appendFile('./companion.log', writestring + "\n", function(err) {
  140. 140 : if (err) {
  141. 141 : console.log("log write error", err);
  142. 142 : }
  143. 143 : logwriting = false;
  144. 144 : });
  145. 145 : }
  146. 146 : }, 1000)
  147. 147 :
  148. 148 : process.stderr.write = function() {
  149. 149 : var arr = [];
  150. 150 : for (var n in arguments) {
  151. 151 : arr.push(arguments[n]);
  152. 152 : }
  153. 153 : var line = new Date().toISOString() + " " + stripAnsi(arr.join(" ").trim() );
  154. 154 : logbuffer.push(line);
  155. 155 : };
  156. 156 :
  157. 157 :
  158. 158 : }
  159. 159 :
  160. 160 : debug('launching registry');
  161. 161 : var registry = new (require('./lib/registry'))(system, config);
  162. 162 :
  163. 163 : system.emit('modules_loaded');
  164. 164 :
  165. 165 : system.on('exit', function() {
  166. 166 : registry.elgatoDM.quit();
  167. 167 : });
  168. 168 :
  169. 169 : });
  170. 170 :
  171. 171 : system.on('skeleton-single-instance-only', function (response) {
  172. 172 : response(true);
  173. 173 : });
  174. 174 :
  175. 175 : exports = module.exports = function(headless) {
  176. 176 : if (headless !== undefined && headless === true) {
  177. 177 : system.headless = true;
  178. 178 : }
  179. 179 : return system;
  180. 180 : }