<commit_before>/**
 * Zeal integration for Brackets
 *
 * @version 1.0.0
 * @copyright © 2014 anephew, http://github.com/anephew
 * @license http://opensource.org/licenses/MIT The MIT License (MIT)
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 2, maxerr: 50, browser: true */
/*global $, define, brackets */

define(function (require, exports, module) {

  "use strict";

  // Core modules
  var
    ExtensionUtils    = brackets.getModule("utils/ExtensionUtils"),
    NodeDomain        = brackets.getModule("utils/NodeDomain"),
    KeyBindingManager = brackets.getModule("command/KeyBindingManager"),
    CommandManager    = brackets.getModule("command/CommandManager"),
    EditorManager     = brackets.getModule("editor/EditorManager"),
    DocumentManager   = brackets.getModule("document/DocumentManager"),
    Menus             = brackets.getModule("command/Menus");

  // Variables
  var CMD_ZEAL_SEARCH = "anephew.brackets-zeal";
  var zealDomain = new NodeDomain("zeal", ExtensionUtils.getModulePath(module, "node/ZealDomain"));

  /**
   *  Process the selected text or word under the cursor
   */
  function handleZealSearch() {

    var editor = EditorManager.getActiveEditor();
    var selection = editor.getSelection();
    var lang = DocumentManager.getCurrentDocument().language._id;
    var text = editor.getSelectedText();

    // Select a word if not selected
    if (selection.start.ch === selection.end.ch) {
      editor.selectWordAt(editor.getCursorPos());
      text = editor.getSelectedText();
    }

    // Check for empty text
    if (!text) {
      editor.displayErrorMessageAtCursor("Place cursor under the word or select any text");
      return;
    }

    // Search string
    var searchString = lang + ":" + text;

    // Execute node domain
    zealDomain.exec("zealSearch", searchString);

  }

  // Register command
  CommandManager.register("LookUp in Zeal", CMD_ZEAL_SEARCH, handleZealSearch);

  // Binding shortcut
  KeyBindingManager.addBinding(CMD_ZEAL_SEARCH, "Ctrl-Alt-Z");

  // Context menu
  var contextMenu = Menus.getContextMenu(Menus.ContextMenuIds.EDITOR_MENU);
  contextMenu.addMenuItem(CMD_ZEAL_SEARCH);

});<commit_msg>1.0.1 [added modal bar for custom search]<commit_after>/**
 * Zeal integration for Brackets
 *
 * @version 1.0.1
 * @copyright © 2014 anephew, http://github.com/anephew
 * @license http://opensource.org/licenses/MIT The MIT License (MIT)
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 2, maxerr: 50, browser: true */
/*global $, define, brackets */

define(function (require, exports, module) {

  "use strict";

  // Core modules
  var
    ExtensionUtils    = brackets.getModule("utils/ExtensionUtils"),
    NodeDomain        = brackets.getModule("utils/NodeDomain"),
    KeyBindingManager = brackets.getModule("command/KeyBindingManager"),
    KeyEvent          = brackets.getModule("utils/KeyEvent"),
    CommandManager    = brackets.getModule("command/CommandManager"),
    EditorManager     = brackets.getModule("editor/EditorManager"),
    DocumentManager   = brackets.getModule("document/DocumentManager"),
    Menus             = brackets.getModule("command/Menus"),
    ModalBar          = brackets.getModule("widgets/ModalBar").ModalBar;

  // Commands id
  var CMD_ZEAL_SEARCH = "anephew.zeal-search";
  var CMD_ZEAL_BAR = "anephew.zeal-bar";

  var zealDomain = new NodeDomain("zeal", ExtensionUtils.getModulePath(module, "node/ZealDomain"));

  /**
   *  Process the selected text or word under the cursor
   */
  function handleZealSearch() {

    var
      editor    = EditorManager.getActiveEditor(),
      selection = editor.getSelection(),
      lang      = DocumentManager.getCurrentDocument().language._id,
      text      = editor.getSelectedText();

    // Select a word if not selected
    if (selection.start.ch === selection.end.ch) {
      editor.selectWordAt(editor.getCursorPos());
      text = editor.getSelectedText();
    }

    // Check for empty text
    if (!text) {
      editor.displayErrorMessageAtCursor("Place cursor under the word or select any text");
      return;
    }

    // Execute Zeal
    zealDomain.exec("zealSearch", lang + ":" + text);

  }

  /**
  *  Quick bar fo custom search in Zeal
  */
  function handleZealBar() {

    var
      html    = "LookUp in Zeal <input type='text' id='searchZealBar' placeholder='docset:string' style='width: 15em' /><button id='searchZealBar-btn' class='btn no-focus' disabled>Go</button>",
      modal   = new ModalBar(html, true),
      $input  = $("#searchZealBar"),
      $button = $("#searchZealBar-btn");

    // Check for empty input, bind ENTER key
    $input.on("input keydown", function (e) {
      $button.prop("disabled", $(this).val() !== "" ? false : true);
      if (e.keyCode === KeyEvent.DOM_VK_RETURN) {
        $button.triggerHandler("click");
      }
    });

    // Execute Zeal
    $button.click(function () {
      zealDomain.exec("zealSearch", $input.val());
    });

  }

  // Register commands
  CommandManager.register("LookUp in Zeal", CMD_ZEAL_SEARCH, handleZealSearch);
  CommandManager.register("Quick Zeal", CMD_ZEAL_BAR, handleZealBar);

  // Binding shortcuts
  KeyBindingManager.addBinding(CMD_ZEAL_SEARCH, "Ctrl-Alt-Z");
  KeyBindingManager.addBinding(CMD_ZEAL_BAR, "Ctrl-Shift-Z");

  // Context menu
  var contextMenu = Menus.getContextMenu(Menus.ContextMenuIds.EDITOR_MENU);
  contextMenu.addMenuItem(CMD_ZEAL_SEARCH);

});<|endoftext|>


<commit_before>var context = new (window.AudioContext || window.webkitAudioContext)();
var analyser = context.createAnalyser();

var buf = new Float32Array( 1024 );
var MIN_SAMPLES = 0; // To be initailzed when context is set
var mediaStreamSource = null;
var analyser = null;

var alphabet = "^\n abcdefghijklmnopqrstuvwxyz$";
var emoticons = ["^", "smile", "cry", "cool", "sad", "sleep", "sob", "uneasy", "kiss", "$"];
var start = '^';
var end = '$';

var supersonic = false;
var freqMin = 440;
var freqMax = 1760;

var range = freqMax - freqMin;
var processing = false;
var listening = false;

var message = "";
var emoji = "";
var capturing = false;
var finished_capturing = false;

function submit() {
  if(processing)
    return;
  var message = document.getElementById('message').value;
  if(message.length === 0)
    return;
  processing = true;
  document.getElementById('submit').disabled = true;
  process(message.toLowerCase());
}

function listen() {
  if(!document.getElementById('emoji_box').checked) {
    var message = document.getElementById('message');
    message.value = "";

    var listen_text = document.getElementById('listen').innerText;
    if(listen_text == "Cancel") {
      listening = false;
      processing = false;
      document.getElementById('message_listen').innerText = "Listen";
      document.getElementById('submit').disabled = false;
      message.placeholder = "Type Message";
    } else {
      listening = true;
      processing = true;
      document.getElementById('message_listen').innerText = "Cancel";
      document.getElementById('submit').disabled = true;
      message.placeholder = "Listening...";
      liveInput();
    }
  } else {
    if(listening) {
      listening = false;
      processing = false;
      document.getElementById('emoji_listen').innerText = "Listen";
    } else {
      listening = true;
      processing = true;
      document.getElementById('emoji_listen').innerText = "Cancel";
      liveInput();
    }
  }
}

window.onload = function() {
  document.getElementById("emoji_wrapper").style.display = "none";
}

document.getElementById('supersonic').onclick = function() {
  if(supersonic) {
    supersonic = false;
    freqMin = 440;
    freqMax = 1760;
  } else {
    supersonic = true;
    freqMin = 18500;
    freqMax = 19500;
  }
}

document.getElementById('emoji_box').onclick = function() {
  if(document.getElementById('emoji_box').checked) {
    document.getElementById("message_wrapper").style.display = "none";
    document.getElementById("emoji_wrapper").style.display = "block";
  }
  else {
    document.getElementById("message_wrapper").style.display = "block";
    document.getElementById("emoji_wrapper").style.display = "none";
  }
}

function selected(emoji) {
  processEmoji(emoji.name);
}

function stopListening() {
  listening = false;
  processing = false;
  document.getElementById('listen').innerText = "Listen";
  document.getElementById('submit').disabled = false;
  message.placeholder = "Type Message";
  message = "";
  capturing = false;
  finished_capturing = false;
}

function error() {
  alert('Stream generation failed.');
}

function getUserMedia(dictionary, callback) {
  try {
    navigator.getUserMedia =
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia;
      navigator.getUserMedia(dictionary, callback, error);
  } catch (e) {
      alert('getUserMedia threw exception :' + e);
  }
}

function gotStream(stream) {
  // Create an AudioNode from the stream.
  mediaStreamSource = context.createMediaStreamSource(stream);

  // Connect it to the destination.
  analyser = context.createAnalyser();
  analyser.fftSize = 2048;
  mediaStreamSource.connect(analyser);
  if(document.getElementById('emoji_box').checked) {
    updateEmoji();
  } else {
    updatePitch();
  }
}

function output() {
  var result = arguments.join("");
  var message = document.getElementById('message');
  message.value = result;
}

function liveInput() {
  getUserMedia(
    {
      "audio": {
        "mandatory": {
          "googEchoCancellation": "false",
          "googAutoGainControl": "false",
          "googNoiseSuppression": "false",
          "googHighpassFilter": "false"
        },
        "optional": []
      },
    }, gotStream);
}

function autoCorrelate(buf, sampleRate) {
  var SIZE = buf.length;
  var MAX_SAMPLES = Math.floor(SIZE/2);
  var best_offset = -1;
  var best_correlation = 0;
  var rms = 0;
  var foundGoodCorrelation = false;
  var correlations = new Array(MAX_SAMPLES);

  for(var i = 0; i < SIZE; i++) {
    var val = buf[i];
    rms += Math.pow(val, 2);
  }

  rms = Math.sqrt(rms/SIZE);
  if(rms < 0.01) {
    //Not enough signal
    return -1;
  }

  var lastCorrelation = 1;
  for(var offset = MIN_SAMPLES; offset < MAX_SAMPLES; offset++) {
    var correlation = 0;

    for(var i = 0; i < MAX_SAMPLES; i++) {
      correlation += Math.abs((buf[i]) - (buf[i + offset]));
    }
    correlation = 1 - (correlation/MAX_SAMPLES);
    correlations[offset] = correlation; // Store for later

    if((correlation > 0.9) && (correlation > lastCorrelation)) {
      foundGoodCorrelation = true;
      if(correlation > best_correlation) {
        best_correlation = correlation;
        best_offset = offset;
      }
    } else if (foundGoodCorrelation) {
      var shift = (correlations[best_offset+1] - correlations[best_offset-1])/correlations[best_offset];
      return sampleRate/(best_offset + (8 * shift));
    }
    lastCorrelation = correlation;
  }

  if(best_correlation > 0.01) {
    return sampleRate/best_offset;
  }
  return -1;
}

function updateEmoji() {
  var cycles = new Array;
  analyser.getFloatTimeDomainData(buf);
  var ac = autoCorrelate(buf, context.sampleRate);

  var freq = null;

  console.log(freq);

  if(ac !== -1 && ac < freqMax && ac > freqMin) {
    freq = ac;
    var note = toEmoji(freq);
    if(note === "^") {
      capturing = true;
    }
    if(note === "$") {
      capturing = false;
      finished_capturing = true;
    }
    if(capturing && note != "^") {
      emoji = note;
    }
    console.log(note);
  }
  if(finished_capturing) {
    selectEmoji(emoji);
  }
  if(listening) {
    setTimeout(function() {
      window.requestAnimationFrame(updatePitch);
    }, 190);
  }
}

function updatePitch() {
  var cycles = new Array;
  analyser.getFloatTimeDomainData(buf);
  var ac = autoCorrelate(buf, context.sampleRate);

  var freq = null;

  // console.log(freq);

  if(ac !== -1 && ac < freqMax && ac > freqMin) {
    freq = ac;
    var note = toChar(freq);
    if(note === "^") {
      capturing = true;
    }
    if(note === "$") {
      capturing = false;
      finished_capturing = true;
    }
    if(capturing && note != "^") {
      message += note;
    }
    console.log(note);
  } else {
    //console.log("ac is -1");
  }
  if(finished_capturing) {
    output("Received: \"", message, "\""   );
    stopListening();
  }
  if(listening) {
    setTimeout(function() {
      window.requestAnimationFrame(updatePitch);
    }, 190)
  }
}

function selectEmoji(emoji) {
  console.log(emoji);
  // var selected_emoji = document.getElementsByName(emoji);
  // selected_emoji[0].src = "images/" + emoji + ".png";
}

function process(message) {
  var message = start + message + end;

  var i = 0;
  for(i; i < message.length; i++) {
    var tone;
    var char = message[i];
    var time = context.currentTime + 0.2*i;
    if(char === start) {
      tone = freqMin;
    }
    else if(char === end) {
      tone = freqMax;
    }
    else {
      tone = toFreq(char);
    }
    emit(tone, time);
  }
  setTimeout(function() {
    processing = false;
    document.getElementById('submit').disabled = false;
  }, 200 * message.length);
}

function processEmoji(emoji) {

  emit(freqMin, context.currentTime);
  emit(toEmojiFreq(emoji), context.currentTime + 0.2);
  emit(freqMax, context.currentTime + 0.4);

}

function toFreq(char) {
  var index = alphabet.indexOf(char);
  if(index === -1) {
    console.error('Invalid character: ', char);
    index = alphabet.length - 1;
  }
  var percent = index / alphabet.length;
  var offset = Math.round(range * percent);
  return freqMin + offset;
}

function toEmojiFreq(emoji) {
  var index = emoticons.indexOf(emoji);
  if(index === -1) {
    console.error("Invalid emoji: ", emoji);
    index = emoticons.length - 1;
  }
  var percent = index / emoticons.length;
  var offset = Math.round(range * percent);
  return freqMin + offset;
}

function toChar(freq, emoji) {
  if(!(freqMin < freq && freq < freqMax)) {
    if(freqMin - freq < 50) {
      freq = freqMin;
    } else if (freq - freqMax < 50) {
      freq = freqMax;
    } else {
      console.error("Invalid frequency: ", freq);
      return;
    }
  }

  var percent = (freq - freqMin) / range;
  var index = Math.round(alphabet.length * percent);
  if(index == alphabet.length)
    return alphabet[index-1];
  return alphabet[index];
}

function toEoji(freq) {
  if(!(freqMin < freq && freq < freqMax)) {
    if(freqMin - freq < 50) {
      freq = freqMin;
    } else if (freq - freqMax < 50) {
      freq = freqMax;
    } else {
      console.error("Invalid frequency: ", freq);
      return;
    }
  }

  var percent = (freq - freqMin) / range;
  var index = Math.round(emoticons.length * percent);
  if(index == emoticons.length)
    return emoticons[index-1];
  return emoticons[index];
}

function emit(tone, time) {
  console.log(tone + " " + time);
  // GainNode
  var gainNode = context.createGain();
  gainNode.gain.value = 0;
  gainNode.gain.setValueAtTime(0, time);
  gainNode.gain.linearRampToValueAtTime(1, time + 0.001);
  gainNode.gain.setValueAtTime(1, time + 0.2 - 0.001);
  gainNode.gain.linearRampToValueAtTime(0, time + 0.2);
  gainNode.connect(context.destination);

  // Oscillator
  var oscillator = context.createOscillator();
  oscillator.frequency.value = tone;
  oscillator.connect(gainNode);
  oscillator.start();
}

function restart() {
  window.location.reload();
}<commit_msg>Fixing how javascript works<commit_after>var context = new (window.AudioContext || window.webkitAudioContext)();
var analyser = context.createAnalyser();

var buf = new Float32Array( 1024 );
var MIN_SAMPLES = 0; // To be initailzed when context is set
var mediaStreamSource = null;
var analyser = null;

var alphabet = "^\n abcdefghijklmnopqrstuvwxyz$";
var emoticons = ["^", "smile", "cry", "cool", "sad", "sleep", "sob", "uneasy", "kiss", "$"];
var start = '^';
var end = '$';

var supersonic = false;
var freqMin = 440;
var freqMax = 1760;

var range = freqMax - freqMin;
var processing = false;
var listening = false;

var message = "";
var emoji = "";
var capturing = false;
var finished_capturing = false;

function submit() {
  if(processing)
    return;
  var message = document.getElementById('message').value;
  if(message.length === 0)
    return;
  processing = true;
  document.getElementById('submit').disabled = true;
  process(message.toLowerCase());
}

function listen() {
  if(!document.getElementById('emoji_box').checked) {
    var message = document.getElementById('message');
    message.value = "";

    var listen_text = document.getElementById('listen').innerText;
    if(listen_text == "Cancel") {
      listening = false;
      processing = false;
      document.getElementById('message_listen').innerText = "Listen";
      document.getElementById('submit').disabled = false;
      message.placeholder = "Type Message";
    } else {
      listening = true;
      processing = true;
      document.getElementById('message_listen').innerText = "Cancel";
      document.getElementById('submit').disabled = true;
      message.placeholder = "Listening...";
      liveInput();
    }
  } else {
    if(listening) {
      listening = false;
      processing = false;
      document.getElementById('emoji_listen').innerText = "Listen";
    } else {
      listening = true;
      processing = true;
      document.getElementById('emoji_listen').innerText = "Cancel";
      liveEmojiInput();
    }
  }
}

window.onload = function() {
  document.getElementById("emoji_wrapper").style.display = "none";
}

document.getElementById('supersonic').onclick = function() {
  if(supersonic) {
    supersonic = false;
    freqMin = 440;
    freqMax = 1760;
  } else {
    supersonic = true;
    freqMin = 18500;
    freqMax = 19500;
  }
}

document.getElementById('emoji_box').onclick = function() {
  if(document.getElementById('emoji_box').checked) {
    document.getElementById("message_wrapper").style.display = "none";
    document.getElementById("emoji_wrapper").style.display = "block";
  }
  else {
    document.getElementById("message_wrapper").style.display = "block";
    document.getElementById("emoji_wrapper").style.display = "none";
  }
}

function selected(emoji) {
  processEmoji(emoji.name);
}

function stopListening() {
  listening = false;
  processing = false;
  document.getElementById('listen').innerText = "Listen";
  document.getElementById('submit').disabled = false;
  message.placeholder = "Type Message";
  message = "";
  capturing = false;
  finished_capturing = false;
}

function error() {
  alert('Stream generation failed.');
}

function getUserMedia(dictionary, callback) {
  try {
    navigator.getUserMedia =
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia;
      navigator.getUserMedia(dictionary, callback, error);
  } catch (e) {
      alert('getUserMedia threw exception :' + e);
  }
}

function gotStream(stream) {
  // Create an AudioNode from the stream.
  mediaStreamSource = context.createMediaStreamSource(stream);

  // Connect it to the destination.
  analyser = context.createAnalyser();
  analyser.fftSize = 2048;
  mediaStreamSource.connect(analyser);
  if(document.getElementById('emoji_box').checked) {
    updateEmoji();
  } else {
    updatePitch();
  }
}

function output() {
  if(typeof arguments !== undefined && arguments.length > 0) {
    var result = arguments.join("");
    var message = document.getElementById('message');
    message.value = result;
  }
}

function liveInput() {
  getUserMedia(
    {
      "audio": {
        "mandatory": {
          "googEchoCancellation": "false",
          "googAutoGainControl": "false",
          "googNoiseSuppression": "false",
          "googHighpassFilter": "false"
        },
        "optional": []
      },
    }, gotStream);
}

function autoCorrelate(buf, sampleRate) {
  var SIZE = buf.length;
  var MAX_SAMPLES = Math.floor(SIZE/2);
  var best_offset = -1;
  var best_correlation = 0;
  var rms = 0;
  var foundGoodCorrelation = false;
  var correlations = new Array(MAX_SAMPLES);

  for(var i = 0; i < SIZE; i++) {
    var val = buf[i];
    rms += Math.pow(val, 2);
  }

  rms = Math.sqrt(rms/SIZE);
  if(rms < 0.01) {
    //Not enough signal
    return -1;
  }

  var lastCorrelation = 1;
  for(var offset = MIN_SAMPLES; offset < MAX_SAMPLES; offset++) {
    var correlation = 0;

    for(var i = 0; i < MAX_SAMPLES; i++) {
      correlation += Math.abs((buf[i]) - (buf[i + offset]));
    }
    correlation = 1 - (correlation/MAX_SAMPLES);
    correlations[offset] = correlation; // Store for later

    if((correlation > 0.9) && (correlation > lastCorrelation)) {
      foundGoodCorrelation = true;
      if(correlation > best_correlation) {
        best_correlation = correlation;
        best_offset = offset;
      }
    } else if (foundGoodCorrelation) {
      var shift = (correlations[best_offset+1] - correlations[best_offset-1])/correlations[best_offset];
      return sampleRate/(best_offset + (8 * shift));
    }
    lastCorrelation = correlation;
  }

  if(best_correlation > 0.01) {
    return sampleRate/best_offset;
  }
  return -1;
}

function updateEmoji() {
  var cycles = new Array;
  analyser.getFloatTimeDomainData(buf);
  var ac = autoCorrelate(buf, context.sampleRate);

  var freq = null;

  console.log(freq);

  if(ac !== -1 && ac < freqMax && ac > freqMin) {
    freq = ac;
    var note = toEmoji(freq);
    if(note === "^") {
      capturing = true;
    }
    if(note === "$") {
      capturing = false;
      finished_capturing = true;
    }
    if(capturing && note != "^") {
      emoji = note;
    }
    console.log(note);
  }
  if(finished_capturing) {
    selectEmoji(emoji);
  }
  if(listening) {
    setTimeout(function() {
      window.requestAnimationFrame(updatePitch);
    }, 190);
  }
}

function updatePitch() {
  var cycles = new Array;
  analyser.getFloatTimeDomainData(buf);
  var ac = autoCorrelate(buf, context.sampleRate);

  var freq = null;

  // console.log(freq);

  if(ac !== -1 && ac < freqMax && ac > freqMin) {
    freq = ac;
    var note = toChar(freq);
    if(note === "^") {
      capturing = true;
    }
    if(note === "$") {
      capturing = false;
      finished_capturing = true;
    }
    if(capturing && note != "^") {
      message += note;
    }
    console.log(note);
  } else {
    //console.log("ac is -1");
  }
  if(finished_capturing) {
    output("Received: \"", message, "\""   );
    stopListening();
  }
  if(listening) {
    setTimeout(function() {
      window.requestAnimationFrame(updatePitch);
    }, 190)
  }
}

function selectEmoji(emoji) {
  console.log(emoji);
  // var selected_emoji = document.getElementsByName(emoji);
  // selected_emoji[0].src = "images/" + emoji + ".png";
}

function process(message) {
  var message = start + message + end;

  var i = 0;
  for(i; i < message.length; i++) {
    var tone;
    var char = message[i];
    var time = context.currentTime + 0.2*i;
    if(char === start) {
      tone = freqMin;
    }
    else if(char === end) {
      tone = freqMax;
    }
    else {
      tone = toFreq(char);
    }
    emit(tone, time);
  }
  setTimeout(function() {
    processing = false;
    document.getElementById('submit').disabled = false;
  }, 200 * message.length);
}

function processEmoji(emoji) {

  emit(freqMin, context.currentTime);
  emit(toEmojiFreq(emoji), context.currentTime + 0.2);
  emit(freqMax, context.currentTime + 0.4);

}

function toFreq(char) {
  var index = alphabet.indexOf(char);
  if(index === -1) {
    console.error('Invalid character: ', char);
    index = alphabet.length - 1;
  }
  var percent = index / alphabet.length;
  var offset = Math.round(range * percent);
  return freqMin + offset;
}

function toEmojiFreq(emoji) {
  var index = emoticons.indexOf(emoji);
  if(index === -1) {
    console.error("Invalid emoji: ", emoji);
    index = emoticons.length - 1;
  }
  var percent = index / emoticons.length;
  var offset = Math.round(range * percent);
  return freqMin + offset;
}

function toChar(freq, emoji) {
  if(!(freqMin < freq && freq < freqMax)) {
    if(freqMin - freq < 50) {
      freq = freqMin;
    } else if (freq - freqMax < 50) {
      freq = freqMax;
    } else {
      console.error("Invalid frequency: ", freq);
      return;
    }
  }

  var percent = (freq - freqMin) / range;
  var index = Math.round(alphabet.length * percent);
  if(index == alphabet.length)
    return alphabet[index-1];
  return alphabet[index];
}

function toEoji(freq) {
  if(!(freqMin < freq && freq < freqMax)) {
    if(freqMin - freq < 50) {
      freq = freqMin;
    } else if (freq - freqMax < 50) {
      freq = freqMax;
    } else {
      console.error("Invalid frequency: ", freq);
      return;
    }
  }

  var percent = (freq - freqMin) / range;
  var index = Math.round(emoticons.length * percent);
  if(index == emoticons.length)
    return emoticons[index-1];
  return emoticons[index];
}

function emit(tone, time) {
  console.log(tone + " " + time);
  // GainNode
  var gainNode = context.createGain();
  gainNode.gain.value = 0;
  gainNode.gain.setValueAtTime(0, time);
  gainNode.gain.linearRampToValueAtTime(1, time + 0.001);
  gainNode.gain.setValueAtTime(1, time + 0.2 - 0.001);
  gainNode.gain.linearRampToValueAtTime(0, time + 0.2);
  gainNode.connect(context.destination);

  // Oscillator
  var oscillator = context.createOscillator();
  oscillator.frequency.value = tone;
  oscillator.connect(gainNode);
  oscillator.start();
}

function restart() {
  window.location.reload();
}<|endoftext|>


<commit_before>/* global __dirname, process */

const {
    BrowserWindow,
    Menu,
    app,
    shell
} = require('electron');
const isDev = require('electron-is-dev');
const { autoUpdater } = require('electron-updater');
const windowStateKeeper = require('electron-window-state');
const {
    initPopupsConfigurationMain,
    getPopupTarget,
    setupAlwaysOnTopMain,
    setupPowerMonitorMain,
    setupScreenSharingMain
} = require('jitsi-meet-electron-utils');
const path = require('path');
const URL = require('url');
const config = require('./app/features/config');

// We need this because of https://github.com/electron/electron/issues/18214
app.commandLine.appendSwitch('disable-site-isolation-trials');

autoUpdater.logger = require('electron-log');
autoUpdater.logger.transports.file.level = 'info';

/**
 * When in development mode:
 * - Load debug utilities (don't open the DevTools window by default though)
 * - Enable automatic reloads
 */
if (isDev) {
    require('electron-debug')({ showDevTools: false });
    require('electron-reload')(path.join(__dirname, 'build'));
}

/**
 * The window object that will load the iframe with Jitsi Meet.
 * IMPORTANT: Must be defined as global in order to not be garbage collected
 * acidentally.
 */
let mainWindow = null;

/**
 * Sets the application menu. It is hidden on all platforms except macOS because
 * otherwise copy and paste functionality is not available.
 */
function setApplicationMenu() {
    if (process.platform === 'darwin') {
        const template = [ {
            label: app.name,
            submenu: [ {
                label: 'Quit',
                accelerator: 'Command+Q',
                click() {
                    app.quit();
                }
            } ]
        }, {
            label: 'Edit',
            submenu: [ {
                label: 'Undo',
                accelerator: 'CmdOrCtrl+Z',
                selector: 'undo:'
            },
            {
                label: 'Redo',
                accelerator: 'Shift+CmdOrCtrl+Z',
                selector: 'redo:'
            },
            {
                type: 'separator'
            },
            {
                label: 'Cut',
                accelerator: 'CmdOrCtrl+X',
                selector: 'cut:'
            },
            {
                label: 'Copy',
                accelerator: 'CmdOrCtrl+C',
                selector: 'copy:'
            },
            {
                label: 'Paste',
                accelerator: 'CmdOrCtrl+V',
                selector: 'paste:'
            },
            {
                label: 'Select All',
                accelerator: 'CmdOrCtrl+A',
                selector: 'selectAll:'
            }
            ]
        } ];

        Menu.setApplicationMenu(Menu.buildFromTemplate(template));
    } else {
        Menu.setApplicationMenu(null);
    }
}

/**
 * Opens new window with index.html(Jitsi Meet is loaded in iframe there).
 */
function createJitsiMeetWindow() {
    // Application menu.
    setApplicationMenu();

    // Check for Updates.
    autoUpdater.checkForUpdatesAndNotify();

    // Load the previous window state with fallback to defaults.
    const windowState = windowStateKeeper({
        defaultWidth: 800,
        defaultHeight: 600
    });

    // Path to root directory.
    const basePath = isDev ? __dirname : app.getAppPath();

    // URL for index.html which will be our entry point.
    const indexURL = URL.format({
        pathname: path.resolve(basePath, './build/index.html'),
        protocol: 'file:',
        slashes: true
    });

    // Options used when creating the main Jitsi Meet window.
    // Use a preload script in order to provide node specific functionality
    // to a isolated BrowserWindow in accordance with electron security
    // guideline.
    const options = {
        x: windowState.x,
        y: windowState.y,
        width: windowState.width,
        height: windowState.height,
        icon: path.resolve(basePath, './resources/icons/icon_512x512.png'),
        minWidth: 800,
        minHeight: 600,
        show: false,
        webPreferences: {
            nativeWindowOpen: true,
            nodeIntegration: false,
            preload: path.resolve(basePath, './build/preload.js')
        }
    };

    mainWindow = new BrowserWindow(options);
    windowState.manage(mainWindow);
    mainWindow.loadURL(indexURL);

    initPopupsConfigurationMain(mainWindow);
    setupAlwaysOnTopMain(mainWindow);
    setupPowerMonitorMain(mainWindow);
    setupScreenSharingMain(mainWindow, config.default.appName);

    mainWindow.webContents.on('new-window', (event, url, frameName) => {
        const target = getPopupTarget(url, frameName);

        if (!target || target === 'browser') {
            event.preventDefault();
            shell.openExternal(url);
        }
    });
    mainWindow.on('closed', () => {
        mainWindow = null;
    });
    mainWindow.once('ready-to-show', () => {
        mainWindow.show();
    });
}

/**
 * Force Single Instance Application.
 */
const gotInstanceLock = app.requestSingleInstanceLock();

if (!gotInstanceLock) {
    app.quit();
    process.exit(0);
}

/**
 * Run the application.
 */

app.on('activate', () => {
    if (mainWindow === null) {
        createJitsiMeetWindow();
    }
});

app.on('certificate-error',
    // eslint-disable-next-line max-params
    (event, webContents, url, error, certificate, callback) => {
        if (isDev) {
            event.preventDefault();
            callback(true);
        } else {
            callback(false);
        }
    }
);

app.on('ready', createJitsiMeetWindow);

app.on('second-instance', () => {
    /**
     * If someone creates second instance of the application, set focus on
     * existing window.
     */
    if (mainWindow) {
        mainWindow.isMinimized() && mainWindow.restore();
        mainWindow.focus();
    }
});

app.on('window-all-closed', () => {
    // Don't quit the application on macOS.
    if (process.platform !== 'darwin') {
        app.quit();
    }
});
<commit_msg>Fix shortcuts on macOS<commit_after>/* global __dirname, process */

const {
    BrowserWindow,
    Menu,
    app,
    shell
} = require('electron');
const isDev = require('electron-is-dev');
const { autoUpdater } = require('electron-updater');
const windowStateKeeper = require('electron-window-state');
const {
    initPopupsConfigurationMain,
    getPopupTarget,
    setupAlwaysOnTopMain,
    setupPowerMonitorMain,
    setupScreenSharingMain
} = require('jitsi-meet-electron-utils');
const path = require('path');
const URL = require('url');
const config = require('./app/features/config');

// We need this because of https://github.com/electron/electron/issues/18214
app.commandLine.appendSwitch('disable-site-isolation-trials');

autoUpdater.logger = require('electron-log');
autoUpdater.logger.transports.file.level = 'info';

/**
 * When in development mode:
 * - Load debug utilities (don't open the DevTools window by default though)
 * - Enable automatic reloads
 */
if (isDev) {
    require('electron-debug')({ showDevTools: false });
    require('electron-reload')(path.join(__dirname, 'build'));
}

/**
 * The window object that will load the iframe with Jitsi Meet.
 * IMPORTANT: Must be defined as global in order to not be garbage collected
 * acidentally.
 */
let mainWindow = null;

/**
 * Sets the application menu. It is hidden on all platforms except macOS because
 * otherwise copy and paste functionality is not available.
 */
function setApplicationMenu() {
    if (process.platform === 'darwin') {
        const template = [ {
            label: app.name,
            submenu: [
                {
                    role: 'services',
                    submenu: []
                },
                { type: 'separator' },
                { role: 'hide' },
                { role: 'hideothers' },
                { role: 'unhide' },
                { type: 'separator' },
                { role: 'quit' }
            ]
        }, {
            label: 'Edit',
            submenu: [ {
                label: 'Undo',
                accelerator: 'CmdOrCtrl+Z',
                selector: 'undo:'
            },
            {
                label: 'Redo',
                accelerator: 'Shift+CmdOrCtrl+Z',
                selector: 'redo:'
            },
            {
                type: 'separator'
            },
            {
                label: 'Cut',
                accelerator: 'CmdOrCtrl+X',
                selector: 'cut:'
            },
            {
                label: 'Copy',
                accelerator: 'CmdOrCtrl+C',
                selector: 'copy:'
            },
            {
                label: 'Paste',
                accelerator: 'CmdOrCtrl+V',
                selector: 'paste:'
            },
            {
                label: 'Select All',
                accelerator: 'CmdOrCtrl+A',
                selector: 'selectAll:'
            } ]
        }, {
            label: '&Window',
            role: 'window',
            submenu: [
                { role: 'minimize' },
                { role: 'close' }
            ]
        } ];

        Menu.setApplicationMenu(Menu.buildFromTemplate(template));
    } else {
        Menu.setApplicationMenu(null);
    }
}

/**
 * Opens new window with index.html(Jitsi Meet is loaded in iframe there).
 */
function createJitsiMeetWindow() {
    // Application menu.
    setApplicationMenu();

    // Check for Updates.
    autoUpdater.checkForUpdatesAndNotify();

    // Load the previous window state with fallback to defaults.
    const windowState = windowStateKeeper({
        defaultWidth: 800,
        defaultHeight: 600
    });

    // Path to root directory.
    const basePath = isDev ? __dirname : app.getAppPath();

    // URL for index.html which will be our entry point.
    const indexURL = URL.format({
        pathname: path.resolve(basePath, './build/index.html'),
        protocol: 'file:',
        slashes: true
    });

    // Options used when creating the main Jitsi Meet window.
    // Use a preload script in order to provide node specific functionality
    // to a isolated BrowserWindow in accordance with electron security
    // guideline.
    const options = {
        x: windowState.x,
        y: windowState.y,
        width: windowState.width,
        height: windowState.height,
        icon: path.resolve(basePath, './resources/icons/icon_512x512.png'),
        minWidth: 800,
        minHeight: 600,
        show: false,
        webPreferences: {
            nativeWindowOpen: true,
            nodeIntegration: false,
            preload: path.resolve(basePath, './build/preload.js')
        }
    };

    mainWindow = new BrowserWindow(options);
    windowState.manage(mainWindow);
    mainWindow.loadURL(indexURL);

    initPopupsConfigurationMain(mainWindow);
    setupAlwaysOnTopMain(mainWindow);
    setupPowerMonitorMain(mainWindow);
    setupScreenSharingMain(mainWindow, config.default.appName);

    mainWindow.webContents.on('new-window', (event, url, frameName) => {
        const target = getPopupTarget(url, frameName);

        if (!target || target === 'browser') {
            event.preventDefault();
            shell.openExternal(url);
        }
    });
    mainWindow.on('closed', () => {
        mainWindow = null;
    });
    mainWindow.once('ready-to-show', () => {
        mainWindow.show();
    });
}

/**
 * Force Single Instance Application.
 */
const gotInstanceLock = app.requestSingleInstanceLock();

if (!gotInstanceLock) {
    app.quit();
    process.exit(0);
}

/**
 * Run the application.
 */

app.on('activate', () => {
    if (mainWindow === null) {
        createJitsiMeetWindow();
    }
});

app.on('certificate-error',
    // eslint-disable-next-line max-params
    (event, webContents, url, error, certificate, callback) => {
        if (isDev) {
            event.preventDefault();
            callback(true);
        } else {
            callback(false);
        }
    }
);

app.on('ready', createJitsiMeetWindow);

app.on('second-instance', () => {
    /**
     * If someone creates second instance of the application, set focus on
     * existing window.
     */
    if (mainWindow) {
        mainWindow.isMinimized() && mainWindow.restore();
        mainWindow.focus();
    }
});

app.on('window-all-closed', () => {
    // Don't quit the application on macOS.
    if (process.platform !== 'darwin') {
        app.quit();
    }
});
<|endoftext|>


<commit_before>const ROMVID = 0x0451;
const ROMPID = 0x6141;
const BOOTPS = 67;
const BOOTPC = 68;
const IPUDP = 17;
const SPLVID = 0x0525;
const SPLPID = 0xA4A2;
const ETHIPP = 0x0800;
const ETHARPP = 0x0806;
const MAXBUF = 450;
const server_hwaddr = [0x9a, 0x1f, 0x85, 0x1c, 0x3d, 0x0e];
const server_ip = [0xc0, 0xa8, 0x01, 0x09];     // 192.168.1.9
const BB_ip = [0xc0, 0xa8, 0x01, 0x03];         // 192.168.1.3
const servername = [66, 69, 65, 71, 76, 69, 66, 79, 79, 84];       // ASCII ['B','E','A','G','L','E','B','O','O','T']
const file_spl = [83, 80, 76, 0, 0];                             // ASCII ['S','P','L']
const file_uboot = [85, 66, 79, 79, 84];                           // ASCII ['U','B','O','O','T']

// Size of all packets
var rndisSize = 44;
var etherSize = 14;
var arp_Size = 28;
var ipSize = 20;
var udpSize = 8;
var bootpSize = 300;
var tftpSize = 4;
var fullSize = 386;

// Include modules
var usb = require('usb');
var protocols = require('./src/protocols');
var deasync = require('deasync');
var fs = require('fs');

// Set usb debug log
usb.setDebugLevel(4);

// Connect to BeagleBone
var device = usb.findByIds(ROMVID, ROMPID);
device.open();
var interface = device.interface(1);    // Select interface 1

// Detach Kernel Driver
if(interface.isKernelDriverActive()){
    interface.detachKernelDriver();
}

interface.claim();

// Set endpoints for usb transfer
var inEndpoint = interface.endpoint(0x81);
var outEndpoint = interface.endpoint(0x02);

// Set endpoint transfer type
inEndpoint.transferType = usb.LIBUSB_TRANSFER_TYPE_BULK;
outEndpoint.transferType = usb.LIBUSB_TRANSFER_TYPE_BULK;

// Receive BOOTP
var bootp_buf = Buffer.alloc(MAXBUF-rndisSize);     // Buffer for InEnd transfer
inEndpoint.timeout = 0;
inEndpoint.transfer(MAXBUF, onFirstIn);             // InEnd transfer
var done = false;                                   // Boolean for sync function
function onFirstIn(error, data) {                   // Callback for InEnd transfer
        data.copy(bootp_buf, 0, rndisSize, MAXBUF);
        done = true;
}
deasync.loopWhile(function(){return !done;});       // Synchronize InEnd transfer function

var ether = protocols.decode_ether(bootp_buf);      // Gets decoded ether packet data

var rndis = protocols.make_rndis(fullSize-rndisSize);   // Make RNDIS

var eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHIPP);    // Make ether2

var ip = protocols.make_ipv4(server_ip, BB_ip, IPUDP, 0, ipSize + udpSize + bootpSize, 0); // Make ipv4

var udp = protocols.make_udp(bootpSize, BOOTPS, BOOTPC);    // Make udp

var bootreply = protocols.make_bootp(servername, file_spl, 1, ether.h_source, BB_ip, server_ip);    // Make BOOTP for reply

var data = Buffer.concat([rndis, eth2, ip, udp, bootreply], fullSize);      // BOOT Reply

// Send BOOT reply
outEndpoint.timeout = 0;
done = false;
outEndpoint.transfer(data, function(error){
    done = true;
});
deasync.loopWhile(function(){return !done;});           // Synchronize OutEnd transfer

// Receive ARP request
var arp_buf = Buffer.alloc(arp_Size);
inEndpoint.timeout = 0;
done = false;
inEndpoint.transfer(MAXBUF, function(error, data){
    data.copy(arp_buf, 0, rndisSize + etherSize, rndisSize + etherSize + arp_Size);
    done = true;
});
deasync.loopWhile(function(){ return !done;});

var receivedARP = protocols.parse_arp(arp_buf);         // Parsed received ARP request

// ARP response
var arpResponse = protocols.make_arp(2, server_hwaddr, receivedARP.ip_dest, receivedARP.hw_source, receivedARP.ip_source );

rndis = protocols.make_rndis(etherSize + arp_Size);

eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHARPP);

data = Buffer.concat([rndis, eth2, arpResponse], rndisSize + etherSize + arp_Size);

// Send ARP response
outEndpoint.timeout = 0;
done = false;
outEndpoint.transfer(data, function(error){
    done = true;
});
deasync.loopWhile(function(){return !done;});

// Receive SPL TFTP request
var udpSPL_buf = Buffer.alloc(udpSize);
inEndpoint.timeout = 0;
done = false;
inEndpoint.transfer(MAXBUF, function(error, data){
    data.copy(udpSPL_buf, 0, rndisSize + etherSize + ipSize, rndisSize + etherSize + ipSize + udpSize);
    done = true;
});
deasync.loopWhile(function(){ return !done;});

var udpSPL = protocols.parse_udp(udpSPL_buf);           // Received UDP packet for SPL tftp

////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////// SPL File Transfer ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
console.log("SPL transfer starts");

var spl = fs.readFileSync("./bin/spl");
var blocks = Math.ceil(spl.length/512);         // Total number of blocks of file

eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHIPP);

var start = 0;                                  // Source start for copy

for(var i=1; i<=blocks; i++){                   // i is block number

    var blk_size = (i==blocks)? spl.length - (blocks-1)*512 : 512;  // Different block size for last block

    var blk_data = Buffer.alloc(blk_size);
    spl.copy(blk_data, 0, start, start + blk_size);                 // Copying data to block
    start += blk_size;

    rndis = protocols.make_rndis(etherSize + ipSize + udpSize + tftpSize + blk_size);
    ip = protocols.make_ipv4(server_ip, BB_ip, IPUDP, 0, ipSize + udpSize + tftpSize + blk_size, 0);
    udp = protocols.make_udp(tftpSize + blk_size, udpSPL.udpDest, udpSPL.udpSrc);
    tftp = protocols.make_tftp(3, i);

    var spl_data = Buffer.concat([rndis, eth2, ip, udp, tftp, blk_data], rndisSize + etherSize + ipSize + udpSize + tftpSize + blk_size);

    // Send SPL file data
    outEndpoint.timeout = 0;
    done = false;
    outEndpoint.transfer(spl_data, function(error){
    done = true;
    });
    deasync.loopWhile(function(){return !done;});

    // Receive buffer back
    inEndpoint.timeout = 0;
    done = false;
    inEndpoint.transfer(MAXBUF, function(error, data){
    done = true;
    });
    deasync.loopWhile(function(){ return !done;});
}

// Wait for SPL initialization
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
sleep(2000);

// Connect to BeagleBone via SPL
device = usb.findByIds(SPLVID, SPLPID);
device.open();
interface = device.interface(1);

// Detach Kernel Driver
if(interface.isKernelDriverActive()){
    interface.detachKernelDriver();
}

interface.claim();
console.log("SPL started running");

// Set endpoints for usb transfer
inEndpoint = interface.endpoint(0x81);
outEndpoint = interface.endpoint(0x01);

// Set endpoint transfer type
inEndpoint.transferType = usb.LIBUSB_TRANSFER_TYPE_BULK;
outEndpoint.transferType = usb.LIBUSB_TRANSFER_TYPE_BULK;

// Receive BOOTP
var udpUboot_buf = Buffer.alloc(udpSize);
var spl_bootp_buf = Buffer.alloc(bootpSize);
inEndpoint.timeout = 0;
var done = false;
inEndpoint.transfer(MAXBUF, function (error, data) {
        data.copy(udpUboot_buf, 0, rndisSize + etherSize + ipSize, MAXBUF);
        data.copy(spl_bootp_buf, 0, rndisSize + etherSize + ipSize + udpSize, MAXBUF);
        done = true;
});
deasync.loopWhile(function(){return !done;});

var udpUboot = protocols.parse_udp(udpUboot_buf);       // parsed udp header
var spl_bootp = protocols.parse_bootp(spl_bootp_buf);   // parsed bootp header

rndis = protocols.make_rndis(fullSize - rndisSize);
eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHIPP);
ip = protocols.make_ipv4(server_ip, BB_ip, IPUDP, 0, ipSize + udpSize + bootpSize, 0);
udp = protocols.make_udp(bootpSize, udpUboot.udpDest, udpUboot.udpSrc);
bootreply = protocols.make_bootp(servername, file_uboot, spl_bootp.xid, ether.h_source, BB_ip, server_ip);

data = Buffer.concat([rndis, eth2, ip, udp, bootreply], fullSize);

// Send BOOT reply
outEndpoint.timeout = 0;
done = false;
outEndpoint.transfer(data, function(error){
    done = true;
});
deasync.loopWhile(function(){return !done;});

// Receive ARP request
inEndpoint.timeout = 0;
done = false;
inEndpoint.transfer(MAXBUF, function(error, data){
    //data.copy(arp_buf, 0, rndisSize + etherSize, rndisSize + etherSize + arp_Size);
    done = true;
});
deasync.loopWhile(function(){ return !done;});

// ARP response
arpResponse = protocols.make_arp(2, server_hwaddr, receivedARP.ip_dest, receivedARP.hw_source, receivedARP.ip_source );

rndis = protocols.make_rndis(etherSize + arp_Size);

eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHARPP);

data = Buffer.concat([rndis, eth2, arpResponse], rndisSize + etherSize + arp_Size);

// Send ARP response
outEndpoint.timeout = 0;
done = false;
outEndpoint.transfer(data, function(error){
    done = true;
});
deasync.loopWhile(function(){return !done;});

// Receive UBOOT TFTP request
var udpUBOOT_buf = Buffer.alloc(udpSize);
inEndpoint.timeout = 0;
done = false;
inEndpoint.transfer(MAXBUF, function(error, data){
    data.copy(udpUBOOT_buf, 0, rndisSize + etherSize + ipSize, rndisSize + etherSize + ipSize + udpSize);
    done = true;
});
deasync.loopWhile(function(){ return !done;});

var udpUBOOT = protocols.parse_udp(udpUBOOT_buf);           // Received UDP packet for UBOOT tftp

////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////// UBOOT File Transfer ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
console.log("Uboot transfer starts");

var uboot = fs.readFileSync("./bin/uboot");
blocks = Math.ceil(uboot.length/512);         // Total number of blocks of file

eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHIPP);

start = 0;                                  // Source start for copy

for(var i=1; i<=blocks; i++){                   // i is block number

    blk_size = (i==blocks)? uboot.length - (blocks-1)*512 : 512;  // Different block size for last block

    blk_data = Buffer.alloc(blk_size);
    uboot.copy(blk_data, 0, start, start + blk_size);                 // Copying data to block
    start += blk_size;

    rndis = protocols.make_rndis(etherSize + ipSize + udpSize + tftpSize + blk_size);
    ip = protocols.make_ipv4(server_ip, BB_ip, IPUDP, 0, ipSize + udpSize + tftpSize + blk_size, 0);
    udp = protocols.make_udp(tftpSize + blk_size, udpUBOOT.udpDest, udpUBOOT.udpSrc);
    tftp = protocols.make_tftp(3, i);

    uboot_data = Buffer.concat([rndis, eth2, ip, udp, tftp, blk_data], rndisSize + etherSize + ipSize + udpSize + tftpSize + blk_size);

    // Send SPL file data
    outEndpoint.timeout = 0;
    done = false;
    outEndpoint.transfer(uboot_data, function(error){
    done = true;
    });
    deasync.loopWhile(function(){return !done;});

    // Receive buffer back
    inEndpoint.timeout = 0;
    done = false;
    inEndpoint.transfer(MAXBUF, function(error, data){
    done = true;
    });
    deasync.loopWhile(function(){ return !done;});
}

console.log("Ready for flashing in a bit..");<commit_msg>initilaize windows specific code<commit_after>const ROMVID = 0x0451;
const ROMPID = 0x6141;
const BOOTPS = 67;
const BOOTPC = 68;
const IPUDP = 17;
const SPLVID = 0x0525;
const SPLPID = 0xA4A2;
const ETHIPP = 0x0800;
const ETHARPP = 0x0806;
const MAXBUF = 450;
const server_hwaddr = [0x9a, 0x1f, 0x85, 0x1c, 0x3d, 0x0e];
const server_ip = [0xc0, 0xa8, 0x01, 0x09];     // 192.168.1.9
const BB_ip = [0xc0, 0xa8, 0x01, 0x03];         // 192.168.1.3
const servername = [66, 69, 65, 71, 76, 69, 66, 79, 79, 84];       // ASCII ['B','E','A','G','L','E','B','O','O','T']
const file_spl = [83, 80, 76, 0, 0];                             // ASCII ['S','P','L']
const file_uboot = [85, 66, 79, 79, 84];                           // ASCII ['U','B','O','O','T']

// Size of all packets
var rndisSize = 44;
var etherSize = 14;
var arp_Size = 28;
var ipSize = 20;
var udpSize = 8;
var bootpSize = 300;
var tftpSize = 4;
var fullSize = 386;

// Include modules
var usb = require('usb');
var protocols = require('./src/protocols');
var deasync = require('deasync');
var fs = require('fs');
var os = require('os');
var platform = os.platform();

// Set usb debug log
usb.setDebugLevel(4);

// Connect to BeagleBone
var device = usb.findByIds(ROMVID, ROMPID);
device.open();
var interface = device.interface(1);    // Select interface 1 for BULK transfers

if(platform != 'win32'){                // Not supported in Windows
// Detach Kernel Driver
if(interface.isKernelDriverActive()){
    interface.detachKernelDriver();
}
}

interface.claim();

// Windows specific code to initialize RNDIS device
if(platform = 'win32'){
    var intf0 = device.interface(0);    // Select interface 0 for CONTROL transfer
    intf0.claim();
}

// Set endpoints for usb transfer
var inEndpoint = interface.endpoint(0x81);
var outEndpoint = interface.endpoint(0x02);

// Set endpoint transfer type
inEndpoint.transferType = usb.LIBUSB_TRANSFER_TYPE_BULK;
outEndpoint.transferType = usb.LIBUSB_TRANSFER_TYPE_BULK;

// Receive BOOTP
var bootp_buf = Buffer.alloc(MAXBUF-rndisSize);     // Buffer for InEnd transfer
inEndpoint.timeout = 0;
inEndpoint.transfer(MAXBUF, onFirstIn);             // InEnd transfer
var done = false;                                   // Boolean for sync function
function onFirstIn(error, data) {                   // Callback for InEnd transfer
        data.copy(bootp_buf, 0, rndisSize, MAXBUF);
        done = true;
}
deasync.loopWhile(function(){return !done;});       // Synchronize InEnd transfer function

var ether = protocols.decode_ether(bootp_buf);      // Gets decoded ether packet data

var rndis = protocols.make_rndis(fullSize-rndisSize);   // Make RNDIS

var eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHIPP);    // Make ether2

var ip = protocols.make_ipv4(server_ip, BB_ip, IPUDP, 0, ipSize + udpSize + bootpSize, 0); // Make ipv4

var udp = protocols.make_udp(bootpSize, BOOTPS, BOOTPC);    // Make udp

var bootreply = protocols.make_bootp(servername, file_spl, 1, ether.h_source, BB_ip, server_ip);    // Make BOOTP for reply

var data = Buffer.concat([rndis, eth2, ip, udp, bootreply], fullSize);      // BOOT Reply

// Send BOOT reply
outEndpoint.timeout = 0;
done = false;
outEndpoint.transfer(data, function(error){
    done = true;
});
deasync.loopWhile(function(){return !done;});           // Synchronize OutEnd transfer

// Receive ARP request
var arp_buf = Buffer.alloc(arp_Size);
inEndpoint.timeout = 0;
done = false;
inEndpoint.transfer(MAXBUF, function(error, data){
    data.copy(arp_buf, 0, rndisSize + etherSize, rndisSize + etherSize + arp_Size);
    done = true;
});
deasync.loopWhile(function(){ return !done;});

var receivedARP = protocols.parse_arp(arp_buf);         // Parsed received ARP request

// ARP response
var arpResponse = protocols.make_arp(2, server_hwaddr, receivedARP.ip_dest, receivedARP.hw_source, receivedARP.ip_source );

rndis = protocols.make_rndis(etherSize + arp_Size);

eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHARPP);

data = Buffer.concat([rndis, eth2, arpResponse], rndisSize + etherSize + arp_Size);

// Send ARP response
outEndpoint.timeout = 0;
done = false;
outEndpoint.transfer(data, function(error){
    done = true;
});
deasync.loopWhile(function(){return !done;});

// Receive SPL TFTP request
var udpSPL_buf = Buffer.alloc(udpSize);
inEndpoint.timeout = 0;
done = false;
inEndpoint.transfer(MAXBUF, function(error, data){
    data.copy(udpSPL_buf, 0, rndisSize + etherSize + ipSize, rndisSize + etherSize + ipSize + udpSize);
    done = true;
});
deasync.loopWhile(function(){ return !done;});

var udpSPL = protocols.parse_udp(udpSPL_buf);           // Received UDP packet for SPL tftp

////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////// SPL File Transfer ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
console.log("SPL transfer starts");

var spl = fs.readFileSync("./bin/spl");
var blocks = Math.ceil(spl.length/512);         // Total number of blocks of file

eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHIPP);

var start = 0;                                  // Source start for copy

for(var i=1; i<=blocks; i++){                   // i is block number

    var blk_size = (i==blocks)? spl.length - (blocks-1)*512 : 512;  // Different block size for last block

    var blk_data = Buffer.alloc(blk_size);
    spl.copy(blk_data, 0, start, start + blk_size);                 // Copying data to block
    start += blk_size;

    rndis = protocols.make_rndis(etherSize + ipSize + udpSize + tftpSize + blk_size);
    ip = protocols.make_ipv4(server_ip, BB_ip, IPUDP, 0, ipSize + udpSize + tftpSize + blk_size, 0);
    udp = protocols.make_udp(tftpSize + blk_size, udpSPL.udpDest, udpSPL.udpSrc);
    tftp = protocols.make_tftp(3, i);

    var spl_data = Buffer.concat([rndis, eth2, ip, udp, tftp, blk_data], rndisSize + etherSize + ipSize + udpSize + tftpSize + blk_size);

    // Send SPL file data
    outEndpoint.timeout = 0;
    done = false;
    outEndpoint.transfer(spl_data, function(error){
    done = true;
    });
    deasync.loopWhile(function(){return !done;});

    // Receive buffer back
    inEndpoint.timeout = 0;
    done = false;
    inEndpoint.transfer(MAXBUF, function(error, data){
    done = true;
    });
    deasync.loopWhile(function(){ return !done;});
}

// Wait for SPL initialization
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
sleep(2000);

// Connect to BeagleBone via SPL
device = usb.findByIds(SPLVID, SPLPID);
device.open();
interface = device.interface(1);

// Detach Kernel Driver
if(interface.isKernelDriverActive()){
    interface.detachKernelDriver();
}

interface.claim();
console.log("SPL started running");

// Set endpoints for usb transfer
inEndpoint = interface.endpoint(0x81);
outEndpoint = interface.endpoint(0x01);

// Set endpoint transfer type
inEndpoint.transferType = usb.LIBUSB_TRANSFER_TYPE_BULK;
outEndpoint.transferType = usb.LIBUSB_TRANSFER_TYPE_BULK;

// Receive BOOTP
var udpUboot_buf = Buffer.alloc(udpSize);
var spl_bootp_buf = Buffer.alloc(bootpSize);
inEndpoint.timeout = 0;
var done = false;
inEndpoint.transfer(MAXBUF, function (error, data) {
        data.copy(udpUboot_buf, 0, rndisSize + etherSize + ipSize, MAXBUF);
        data.copy(spl_bootp_buf, 0, rndisSize + etherSize + ipSize + udpSize, MAXBUF);
        done = true;
});
deasync.loopWhile(function(){return !done;});

var udpUboot = protocols.parse_udp(udpUboot_buf);       // parsed udp header
var spl_bootp = protocols.parse_bootp(spl_bootp_buf);   // parsed bootp header

rndis = protocols.make_rndis(fullSize - rndisSize);
eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHIPP);
ip = protocols.make_ipv4(server_ip, BB_ip, IPUDP, 0, ipSize + udpSize + bootpSize, 0);
udp = protocols.make_udp(bootpSize, udpUboot.udpDest, udpUboot.udpSrc);
bootreply = protocols.make_bootp(servername, file_uboot, spl_bootp.xid, ether.h_source, BB_ip, server_ip);

data = Buffer.concat([rndis, eth2, ip, udp, bootreply], fullSize);

// Send BOOT reply
outEndpoint.timeout = 0;
done = false;
outEndpoint.transfer(data, function(error){
    done = true;
});
deasync.loopWhile(function(){return !done;});

// Receive ARP request
inEndpoint.timeout = 0;
done = false;
inEndpoint.transfer(MAXBUF, function(error, data){
    //data.copy(arp_buf, 0, rndisSize + etherSize, rndisSize + etherSize + arp_Size);
    done = true;
});
deasync.loopWhile(function(){ return !done;});

// ARP response
arpResponse = protocols.make_arp(2, server_hwaddr, receivedARP.ip_dest, receivedARP.hw_source, receivedARP.ip_source );

rndis = protocols.make_rndis(etherSize + arp_Size);

eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHARPP);

data = Buffer.concat([rndis, eth2, arpResponse], rndisSize + etherSize + arp_Size);

// Send ARP response
outEndpoint.timeout = 0;
done = false;
outEndpoint.transfer(data, function(error){
    done = true;
});
deasync.loopWhile(function(){return !done;});

// Receive UBOOT TFTP request
var udpUBOOT_buf = Buffer.alloc(udpSize);
inEndpoint.timeout = 0;
done = false;
inEndpoint.transfer(MAXBUF, function(error, data){
    data.copy(udpUBOOT_buf, 0, rndisSize + etherSize + ipSize, rndisSize + etherSize + ipSize + udpSize);
    done = true;
});
deasync.loopWhile(function(){ return !done;});

var udpUBOOT = protocols.parse_udp(udpUBOOT_buf);           // Received UDP packet for UBOOT tftp

////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////// UBOOT File Transfer ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
console.log("Uboot transfer starts");

var uboot = fs.readFileSync("./bin/uboot");
blocks = Math.ceil(uboot.length/512);         // Total number of blocks of file

eth2 = protocols.make_ether2(ether.h_source, server_hwaddr, ETHIPP);

start = 0;                                  // Source start for copy

for(var i=1; i<=blocks; i++){                   // i is block number

    blk_size = (i==blocks)? uboot.length - (blocks-1)*512 : 512;  // Different block size for last block

    blk_data = Buffer.alloc(blk_size);
    uboot.copy(blk_data, 0, start, start + blk_size);                 // Copying data to block
    start += blk_size;

    rndis = protocols.make_rndis(etherSize + ipSize + udpSize + tftpSize + blk_size);
    ip = protocols.make_ipv4(server_ip, BB_ip, IPUDP, 0, ipSize + udpSize + tftpSize + blk_size, 0);
    udp = protocols.make_udp(tftpSize + blk_size, udpUBOOT.udpDest, udpUBOOT.udpSrc);
    tftp = protocols.make_tftp(3, i);

    uboot_data = Buffer.concat([rndis, eth2, ip, udp, tftp, blk_data], rndisSize + etherSize + ipSize + udpSize + tftpSize + blk_size);

    // Send SPL file data
    outEndpoint.timeout = 0;
    done = false;
    outEndpoint.transfer(uboot_data, function(error){
    done = true;
    });
    deasync.loopWhile(function(){return !done;});

    // Receive buffer back
    inEndpoint.timeout = 0;
    done = false;
    inEndpoint.transfer(MAXBUF, function(error, data){
    done = true;
    });
    deasync.loopWhile(function(){ return !done;});
}

console.log("Ready for flashing in a bit..");<|endoftext|>


<commit_before>let updateBindings = [];
/**
 * Returns array of objects in module
 * @param {*} mod
 */
function parseModule(mod) {
    return mod.match(/\{([\S\s]*)\}/).map((item) => {
        let obj;
        try {
        obj = eval('(' + item.trim() + ')');
        }
        finally {
            return obj;
        }
    });
}

/**
 * Adds list of bindings to update for components
 * @param {*} objects
 */
function parseComponents(objects) {
    objects.forEach(function(obj) {
        //look for component signature
        if (obj && obj.bindings) {
            for (const i in obj.bindings) {
                if (obj.bindings[i].indexOf('::') > -1) {
                    updateBindings.push({name: obj.name, binding: i})
                }
            }
        }
    }, this);
}

function stripModule(mod) {
    const supportedBindings = ['::=', '::<', '::@'];
    return supportedBindings.reduce((item, binding) => item.replace(binding, binding.substr(2)), mod);
}
module.exports = function(content) {
    parseComponents(parseModule(content));
    const strippedModule = stripModule(content);
    return content;
}<commit_msg>Setup one-time binding parsing and persisted state.<commit_after>const esprima = require('esprima');
const get = require('lodash/get');

function isExportSupported(mod) {
    return (mod.type === 'ExportNamedDeclaration' || mod.type === 'ExportDefaultDeclaration') && mod.declaration.type === 'ObjectExpression';
}

function getOneTimeBindings(bindings) {
    const supportedBindings = ['::=', '::=?', '::<', '::<?', '::@', '::@?'];
    return bindings.reduce((oneTimeBindings, binding) => {
        if (supportedBindings.includes(binding.value.value)) {
            oneTimeBindings.push(binding.key.name);
            return oneTimeBindings;
        }
        return oneTimeBindings;
    }, []);
}

function getComponentToUpdate(properties) {
    return properties.reduce((props, property) => {
        if (property.key.name === 'name'){
            props.name = property.value.value;
        }
        else if (property.key.name === 'bindings') {
            props.bindings = getOneTimeBindings(property.value.properties);

        };
        return props;
    }, {});

}

/**
 * Returns array of objects in module
 * @param {*} mod
 */
function parseModule(mod) {
    const parsedMod = esprima.parseModule(mod, { tolerant: true });
    return parsedMod.body.reduce((componentList, modItem) => {
        if (isExportSupported(modItem)) {
            const component = getComponentToUpdate(modItem.declaration.properties);
            if (component && component.name && component.bindings && component.bindings.length > 0) {
                componentList.push(component);
            }
        }
        return componentList;
    },[]);

}

module.exports = function(content) {
    module.updateBindings = module.updateBindings || [];
    module.updateBindings.push(...parseModule(content));
    return content;
}<|endoftext|>


<commit_before>var app = require('app');
var BrowserWindow = require('browser-window');
var ipc = require('ipc');
global.storage = require(__dirname+'/lib/storage/storage');
global.i18n = require(__dirname+'/lib/i18n');
var environment = storage.get('environment');
require('crash-reporter').start();

var mainWindow = null;

var Menu = require("menu");

app.on('window-all-closed', function(){
  if (process.platform != 'darwin') {
    app.quit();
  }
});
app.on('ready', function(){
  mainWindow = new BrowserWindow({width: 800, height: 600});
  mainWindow.loadUrl('file://'+ __dirname + '/index.html');
  if (environment == 'development')
    mainWindow.openDevTools();

  var template = require(__dirname+'/lib/menus/main_menu')(app, BrowserWindow, mainWindow);

  Menu.setApplicationMenu(Menu.buildFromTemplate(template));
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});

<commit_msg>ADD : app_root global variable<commit_after>var app = require('app');
var BrowserWindow = require('browser-window');
var ipc = require('ipc');
global.app_root = __dirname+'/app';
global.storage = require(app_root+'/lib/storage/storage');
global.i18n = require(app_root+'/lib/i18n');
var environment = storage.get('environment');
require('crash-reporter').start();

var mainWindow = null;

var Menu = require("menu");

app.on('window-all-closed', function(){
  if (process.platform != 'darwin') {
    app.quit();
  }
});
app.on('ready', function(){
  mainWindow = new BrowserWindow({width: 800, height: 600});
  mainWindow.loadUrl('file://'+ app_root +'/views/index.html');
  if (environment == 'development')
    mainWindow.openDevTools();

  var template = require(app_root+'/lib/menus/main_menu')(app, BrowserWindow, mainWindow);

  Menu.setApplicationMenu(Menu.buildFromTemplate(template));
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});

<|endoftext|>


<commit_before>#!/usr/bin/env node

let transpilations = {};
let zwitterionJSON = {
    files: {}
};
let io;

const builder = createBuilder();

const chokidar = require('chokidar');
const program = require('commander');
const fs = require('fs');
const mkdirp = require('mkdirp');

program
    .version('0.0.8')
    .option('-s, --serve-dir [serveDir]', 'The directory to serve files from; the root directory of the server')
    .option('-h, --http', 'Use HTTP 1.x (the default is HTTP 2)')
    .option('-c, --cert-path [certPath]', 'Specify path to SSL certificate')
    .option('-k, --key-path [keyPath]', 'Specify path to SSL key')
    .option('-o, --output-dir [outputDir]', 'Specify the output directory for transpiled files (the default is in-memory transpilation only)')
    .option('-b, --build', 'Transpile all files specified in the files property in zwitterion.json to the corresponding location in the specified output directory (--output-dir)')
    .option('-t, --type-check-level [typeCheckLevel]', 'Specify the level of type checking (none, warn, error)')
    .parse(process.argv);

const serveDir = program.serveDir || '';
const httpVersion = program.http ? 1 : 2;
const keyPath = program.keyPath;
const certPath = program.certPath;
const outputDir = program.outputDir;
const typeCheckLevel = program.typeCheckLevel;
const build = program.build;

try {
    zwitterionJSON = JSON.parse(fs.readFileSync('zwitterion.json'));
}
catch(error) {
    fs.writeFileSync('zwitterion.json', JSON.stringify(zwitterionJSON, null, 4));
}

if (build) {
    if (!outputDir) {
        throw new Error('You must specify an output directory from the command line, --output-dir [outputDir]');
    }

    mkdirp.sync(outputDir);
    const filePaths = Object.keys(zwitterionJSON.files);
    filePaths.forEach((filePath) => {
        try {
            const directoriesWithFile = filePath.split('/');
            if (directoriesWithFile.length > 1) {
                const directories = directoriesWithFile.slice(0, -1).join('/');
                mkdirp.sync(`${outputDir}/${directories}`);
            }

            if (filePath === `browser-config.js`) {
                fs.writeFileSync(`${outputDir}/browser-config.js`, getBrowserConfig());
            }
            else if (filePath === `system.js.map`) {
                fs.writeFileSync(`${outputDir}/system.js.map`, getSystemJSSourceMap());
            }
            else {
                const fileEnding = filePath.slice(filePath.lastIndexOf('.'));
                if (fileEnding === '.ts') {
                    const isChildImport = !zwitterionJSON.files[filePath].parentImport;
                    compile(isChildImport, serveDir, filePath).then((source) => {
                        fs.writeFileSync(`${outputDir}/${filePath}`, source);
                    });
                }
                else {
                    fs.writeFileSync(`${outputDir}/${filePath}`, fs.readFileSync(`${serveDir}/${filePath}`));
                }
            }
        }
        catch(error) {
            console.log(error);
        }
    });

    return;
}

let watcher = configureFileWatching(serveDir);
createServer(builder, httpVersion, keyPath, certPath, outputDir, typeCheckLevel, serveDir);

function writeZwitterionJSON() {
    fs.writeFileSync('zwitterion.json', JSON.stringify(zwitterionJSON, null, 4));
}

function configureFileWatching(serveDir) {
    return chokidar.watch([]).on('change', (path) => {
        const fileEnding = path.slice(path.lastIndexOf('.'));

        if (fileEnding === '.ts') {
            const relativeFilePath = path.replace(`${serveDir}/`, '');
            const isChildImport = !zwitterionJSON.files[relativeFilePath].parentImport;
            compile(isChildImport, serveDir, relativeFilePath).then((source) => {
                transpilations[relativeFilePath] = source;
                reloadBrowser();
            });
        }
        else {
            reloadBrowser();
        }
    });
}

function reloadBrowser() {
    io.emit('reload');
}

function createServer(builder, httpVersion, keyPath, certPath, outputDir, typeCheckLevel, serveDir) {
    const static = require('node-static');
    const fileServer = new static.Server(`${process.cwd()}/${serveDir}`);
    const httpServerPromise = httpVersion === 2 ? createHTTP2Server(builder, fileServer, keyPath, certPath) : createHTTPServer(builder, fileServer);
    httpServerPromise.then((httpServer) => {
        io = require('socket.io')(httpServer);
        httpServer.listen(8000, (error) => {
            if (error) {
                console.log(error);
            }
            else {
                console.log('zwitterion server listening on port 8000');
            }
        });
    }, (error) => {
        console.log(error);
    });
}

function createHTTPServer(builder, fileServer) {
    return new Promise((resolve, reject) => {
        resolve(require('http').createServer(handler(fileServer)));
    });
}

function createHTTP2Server(builder, fileServer, keyPath, certPath) {
    return new Promise((resolve, reject) => {
        getCertAndKey(keyPath, certPath).then((certAndKey) => {
            const options = {
                key: certAndKey.key,
                cert: certAndKey.cert
            };

            resolve(require('http2').createServer(options, handler(fileServer)));
        }, (error) => {
            console.log(error);
        });
    });
}

function getCertAndKey(keyPath, certPath) {
    return new Promise((resolve, reject) => {
        const fs = require('fs');
        const defaultKeyPath = `localhost.key`;
        const defaultCertPath = `localhost.cert`;

        try {
            const key = fs.readFileSync(keyPath || defaultKeyPath);
            const cert = fs.readFileSync(certPath || defaultCertPath);

            resolve({
                key,
                cert
            });
        }
        catch(error) {
            if (!keyPath && !certPath) {
                createCertAndKey(defaultKeyPath, defaultCertPath).then((certAndKey) => {
                    resolve(certAndKey);
                }, (error) => {
                    console.log(error);
                });
            }
            else {
                throw error;
            }
        }
    });
}

function handler(fileServer) {
    return (req, res) => {
        const absoluteFilePath = `${process.cwd()}${req.url}`;
        const relativeFilePath = req.url.slice(1);
        const fileExtension = relativeFilePath.slice(relativeFilePath.lastIndexOf('.'));

        const isChildImport = isSystemImportRequest(req);
        writeRelativeFilePathToZwitterionJSON(relativeFilePath || 'index.html', isChildImport);
        watcher.add(`${serveDir}/${relativeFilePath}` || `${serveDir}/index.html`);
        fileExtension === '.ts' ? buildAndServe(req, res, relativeFilePath) : serveWithoutBuild(fileServer, req, res);
    };
}

function writeRelativeFilePathToZwitterionJSON(relativeFilePath, isChildImport) {
    const newRelativeFilePath = relativeFilePath.indexOf(serveDir) === 0 ? relativeFilePath.replace(`${serveDir}/`, '') : relativeFilePath;

    zwitterionJSON.files[newRelativeFilePath] = {
        parentImport: !isChildImport
    };
    writeZwitterionJSON();
}

function buildAndServe(req, res, relativeFilePath) {
    const transpilation = transpilations[relativeFilePath];
    if (transpilation) {
        res.end(transpilation);
    }
    else {
        const isChildImport = isSystemImportRequest(req);
        compile(isChildImport, serveDir, relativeFilePath).then((source) => {
            transpilations[relativeFilePath] = source;
            res.end(transpilations[relativeFilePath]);
        });
    }
}

function compile(isChildImport, serveDir, relativeFilePath) {
    return new Promise((resolve, reject) => {
        builder.compile(`${serveDir}/${relativeFilePath}`, null, {
            minify: true
        }).then((output) => {
            const source = prepareSource(isChildImport, relativeFilePath, output.source);
            resolve(source);
        }, (error) => {
            console.log(error);
        });
    });
}

function prepareSource(isChildImport, relativeFilePath, rawSource) {
    if (isChildImport) {
        return rawSource;
    }
    else {
        const escapedSource = rawSource.replace(/\\/g, '\\\\');
        const preparedSource = `
            System.define(System.normalizeSync('${relativeFilePath}'), \`
                ${escapedSource}
            \`);
        `;
        return preparedSource;
    }
}

function isSystemImportRequest(req) {
    return req.headers.accept && req.headers.accept.includes('application/x-es-module');
}

function serveWithoutBuild(fileServer, req, res) {
    req.addListener('end', () => {
        if (req.url === '/browser-config.js') {
            res.end(getBrowserConfig());
        }
        else if (req.url === '/system.js.map') {
            res.end(getSystemJSSourceMap());
        }
        else {
            fileServer.serve(req, res, (error, result) => {
                if (error && error.status === 404) {
                    fileServer.serveFile('/index.html', 200, {}, req, res);
                }
            });
        }
    }).resume();
}

function getBrowserConfig() {
    const systemJS = fs.readFileSync('node_modules/systemjs/dist/system.js');
    const socketIO = fs.readFileSync('node_modules/socket.io-client/dist/socket.io.min.js');
    const tsImportsConfig = fs.readFileSync('node_modules/zwitterion/ts-imports-config.js');
    const socketIOConfig = fs.readFileSync('node_modules/zwitterion/socket-io-config.js');

    return `${systemJS}${socketIO}${tsImportsConfig}${socketIOConfig}`;
}

function getSystemJSSourceMap() {
    return fs.readFileSync('node_modules/systemjs/dist/system.js.map');
}

function createBuilder() {
    const Builder = require('systemjs-builder');

    const builder = new Builder();

    //TODO redo this config, get rid of everything that is unnecessary, becuase I believe there might be quite a bit of it
    builder.config({
        transpiler: 'ts',
        typescriptOptions: {
            target: 'es5',
            module: 'system'
        },
        meta: {
            '*.ts': {
                loader: 'ts'
            }
        },
        packages: {
            '/': {
                defaultExtension: 'ts'
            },
            ts: {
                main: 'plugin.js'
            },
            typescript: {
                main: 'typescript.js',
                meta: {
                    'typescript.js': {
                        exports: 'ts'
                    }
                }
            }
        },
        map: {
            ts: './node_modules/plugin-typescript/lib/',
            typescript: './node_modules/typescript/lib/'
        }
    });

    return builder;
}

function createCertAndKey(keyPath, certPath) {
    return new Promise((resolve, reject) => {
        const pem = require('pem');

        pem.createCertificate({
            selfSigned: true
        }, (error, keys) => {
            if (error) {
                console.log(error);
            }
            else {
                fs.writeFileSync(keyPath, keys.serviceKey);
                fs.writeFileSync(certPath, keys.certificate);

                resolve({
                    key: keys.serviceKey,
                    cert: keys.certificate
                });
            }
        });
    });
}
<commit_msg>ensure serveDir can be ommitted<commit_after>#!/usr/bin/env node

let transpilations = {};
let zwitterionJSON = {
    files: {}
};
let io;

const builder = createBuilder();

const chokidar = require('chokidar');
const program = require('commander');
const fs = require('fs');
const mkdirp = require('mkdirp');

program
    .version('0.0.8')
    .option('-s, --serve-dir [serveDir]', 'The directory to serve files from; the root directory of the server')
    .option('-h, --http', 'Use HTTP 1.x (the default is HTTP 2)')
    .option('-c, --cert-path [certPath]', 'Specify path to SSL certificate')
    .option('-k, --key-path [keyPath]', 'Specify path to SSL key')
    .option('-o, --output-dir [outputDir]', 'Specify the output directory for transpiled files (the default is in-memory transpilation only)')
    .option('-b, --build', 'Transpile all files specified in the files property in zwitterion.json to the corresponding location in the specified output directory (--output-dir)')
    .option('-t, --type-check-level [typeCheckLevel]', 'Specify the level of type checking (none, warn, error)')
    .parse(process.argv);

const serveDir = program.serveDir ? `${program.serveDir}/` : '';
const httpVersion = program.http ? 1 : 2;
const keyPath = program.keyPath;
const certPath = program.certPath;
const outputDir = program.outputDir;
const typeCheckLevel = program.typeCheckLevel;
const build = program.build;

try {
    zwitterionJSON = JSON.parse(fs.readFileSync('zwitterion.json'));
}
catch(error) {
    fs.writeFileSync('zwitterion.json', JSON.stringify(zwitterionJSON, null, 4));
}

if (build) {
    if (!outputDir) {
        throw new Error('You must specify an output directory from the command line, --output-dir [outputDir]');
    }

    mkdirp.sync(outputDir);
    const filePaths = Object.keys(zwitterionJSON.files);
    filePaths.forEach((filePath) => {
        try {
            const directoriesWithFile = filePath.split('/');
            if (directoriesWithFile.length > 1) {
                const directories = directoriesWithFile.slice(0, -1).join('/');
                mkdirp.sync(`${outputDir}/${directories}`);
            }

            if (filePath === `browser-config.js`) {
                fs.writeFileSync(`${outputDir}/browser-config.js`, getBrowserConfig());
            }
            else if (filePath === `system.js.map`) {
                fs.writeFileSync(`${outputDir}/system.js.map`, getSystemJSSourceMap());
            }
            else {
                const fileEnding = filePath.slice(filePath.lastIndexOf('.'));
                if (fileEnding === '.ts') {
                    const isChildImport = !zwitterionJSON.files[filePath].parentImport;
                    compile(isChildImport, serveDir, filePath).then((source) => {
                        fs.writeFileSync(`${outputDir}/${filePath}`, source);
                    });
                }
                else {
                    fs.writeFileSync(`${outputDir}/${filePath}`, fs.readFileSync(`${serveDir}${filePath}`));
                }
            }
        }
        catch(error) {
            console.log(error);
        }
    });

    return;
}

let watcher = configureFileWatching(serveDir);
createServer(builder, httpVersion, keyPath, certPath, outputDir, typeCheckLevel, serveDir);

function writeZwitterionJSON() {
    fs.writeFileSync('zwitterion.json', JSON.stringify(zwitterionJSON, null, 4));
}

function configureFileWatching(serveDir) {
    return chokidar.watch([]).on('change', (path) => {
        const fileEnding = path.slice(path.lastIndexOf('.'));

        if (fileEnding === '.ts') {
            const relativeFilePath = path.replace(`${serveDir}`, '');
            const isChildImport = !zwitterionJSON.files[relativeFilePath].parentImport;
            compile(isChildImport, serveDir, relativeFilePath).then((source) => {
                transpilations[relativeFilePath] = source;
                reloadBrowser();
            });
        }
        else {
            reloadBrowser();
        }
    });
}

function reloadBrowser() {
    io.emit('reload');
}

function createServer(builder, httpVersion, keyPath, certPath, outputDir, typeCheckLevel, serveDir) {
    const static = require('node-static');
    const fileServer = new static.Server(`${process.cwd()}/${serveDir}`);
    const httpServerPromise = httpVersion === 2 ? createHTTP2Server(builder, fileServer, keyPath, certPath) : createHTTPServer(builder, fileServer);
    httpServerPromise.then((httpServer) => {
        io = require('socket.io')(httpServer);
        httpServer.listen(8000, (error) => {
            if (error) {
                console.log(error);
            }
            else {
                console.log('zwitterion server listening on port 8000');
            }
        });
    }, (error) => {
        console.log(error);
    });
}

function createHTTPServer(builder, fileServer) {
    return new Promise((resolve, reject) => {
        resolve(require('http').createServer(handler(fileServer)));
    });
}

function createHTTP2Server(builder, fileServer, keyPath, certPath) {
    return new Promise((resolve, reject) => {
        getCertAndKey(keyPath, certPath).then((certAndKey) => {
            const options = {
                key: certAndKey.key,
                cert: certAndKey.cert
            };

            resolve(require('http2').createServer(options, handler(fileServer)));
        }, (error) => {
            console.log(error);
        });
    });
}

function getCertAndKey(keyPath, certPath) {
    return new Promise((resolve, reject) => {
        const fs = require('fs');
        const defaultKeyPath = `localhost.key`;
        const defaultCertPath = `localhost.cert`;

        try {
            const key = fs.readFileSync(keyPath || defaultKeyPath);
            const cert = fs.readFileSync(certPath || defaultCertPath);

            resolve({
                key,
                cert
            });
        }
        catch(error) {
            if (!keyPath && !certPath) {
                createCertAndKey(defaultKeyPath, defaultCertPath).then((certAndKey) => {
                    resolve(certAndKey);
                }, (error) => {
                    console.log(error);
                });
            }
            else {
                throw error;
            }
        }
    });
}

function handler(fileServer) {
    return (req, res) => {
        const absoluteFilePath = `${process.cwd()}${req.url}`;
        const relativeFilePath = req.url.slice(1);
        const fileExtension = relativeFilePath.slice(relativeFilePath.lastIndexOf('.'));

        const isChildImport = isSystemImportRequest(req);
        writeRelativeFilePathToZwitterionJSON(relativeFilePath || 'index.html', isChildImport);
        watcher.add(`${serveDir}${relativeFilePath}` || `${serveDir}index.html`);
        fileExtension === '.ts' ? buildAndServe(req, res, relativeFilePath) : serveWithoutBuild(fileServer, req, res);
    };
}

function writeRelativeFilePathToZwitterionJSON(relativeFilePath, isChildImport) {
    const newRelativeFilePath = relativeFilePath.indexOf(serveDir) === 0 ? relativeFilePath.replace(`${serveDir}`, '') : relativeFilePath;

    zwitterionJSON.files[newRelativeFilePath] = {
        parentImport: !isChildImport
    };
    writeZwitterionJSON();
}

function buildAndServe(req, res, relativeFilePath) {
    const transpilation = transpilations[relativeFilePath];
    if (transpilation) {
        res.end(transpilation);
    }
    else {
        const isChildImport = isSystemImportRequest(req);
        compile(isChildImport, serveDir, relativeFilePath).then((source) => {
            transpilations[relativeFilePath] = source;
            res.end(transpilations[relativeFilePath]);
        });
    }
}

function compile(isChildImport, serveDir, relativeFilePath) {
    return new Promise((resolve, reject) => {
        builder.compile(`${serveDir}${relativeFilePath}`, null, {
            minify: true
        }).then((output) => {
            const source = prepareSource(isChildImport, relativeFilePath, output.source);
            resolve(source);
        }, (error) => {
            console.log(error);
        });
    });
}

function prepareSource(isChildImport, relativeFilePath, rawSource) {
    if (isChildImport) {
        return rawSource;
    }
    else {
        const escapedSource = rawSource.replace(/\\/g, '\\\\');
        const preparedSource = `
            System.define(System.normalizeSync('${relativeFilePath}'), \`
                ${escapedSource}
            \`);
        `;
        return preparedSource;
    }
}

function isSystemImportRequest(req) {
    return req.headers.accept && req.headers.accept.includes('application/x-es-module');
}

function serveWithoutBuild(fileServer, req, res) {
    req.addListener('end', () => {
        if (req.url === '/browser-config.js') {
            res.end(getBrowserConfig());
        }
        else if (req.url === '/system.js.map') {
            res.end(getSystemJSSourceMap());
        }
        else {
            fileServer.serve(req, res, (error, result) => {
                if (error && error.status === 404) {
                    fileServer.serveFile('/index.html', 200, {}, req, res);
                }
            });
        }
    }).resume();
}

function getBrowserConfig() {
    const systemJS = fs.readFileSync('node_modules/systemjs/dist/system.js');
    const socketIO = fs.readFileSync('node_modules/socket.io-client/dist/socket.io.min.js');
    const tsImportsConfig = fs.readFileSync('node_modules/zwitterion/ts-imports-config.js');
    const socketIOConfig = fs.readFileSync('node_modules/zwitterion/socket-io-config.js');

    return `${systemJS}${socketIO}${tsImportsConfig}${socketIOConfig}`;
}

function getSystemJSSourceMap() {
    return fs.readFileSync('node_modules/systemjs/dist/system.js.map');
}

function createBuilder() {
    const Builder = require('systemjs-builder');

    const builder = new Builder();

    //TODO redo this config, get rid of everything that is unnecessary, becuase I believe there might be quite a bit of it
    builder.config({
        transpiler: 'ts',
        typescriptOptions: {
            target: 'es5',
            module: 'system'
        },
        meta: {
            '*.ts': {
                loader: 'ts'
            }
        },
        packages: {
            '/': {
                defaultExtension: 'ts'
            },
            ts: {
                main: 'plugin.js'
            },
            typescript: {
                main: 'typescript.js',
                meta: {
                    'typescript.js': {
                        exports: 'ts'
                    }
                }
            }
        },
        map: {
            ts: './node_modules/plugin-typescript/lib/',
            typescript: './node_modules/typescript/lib/'
        }
    });

    return builder;
}

function createCertAndKey(keyPath, certPath) {
    return new Promise((resolve, reject) => {
        const pem = require('pem');

        pem.createCertificate({
            selfSigned: true
        }, (error, keys) => {
            if (error) {
                console.log(error);
            }
            else {
                fs.writeFileSync(keyPath, keys.serviceKey);
                fs.writeFileSync(certPath, keys.certificate);

                resolve({
                    key: keys.serviceKey,
                    cert: keys.certificate
                });
            }
        });
    });
}
<|endoftext|>