      var SOUNDC_1_IN = "Sound card 1 IN";
      var SOUNDC_1_OUT = "Sound card 1 OUT";
      var SOUNDC_2_IN = "Sound card 2 IN";
      var SOUNDC_2_OUT = "Sound card 2 OUT";
      var SOUNDC_3_IN = "Sound card 3 IN";
      var SOUNDC_3_OUT = "Sound card 3 OUT";
      var SOUNDC_4_IN = "Sound card 4 IN";
      var SOUNDC_4_OUT = "Sound card 4 OUT";
      var SOUNDC_5_IN = "Sound card 5 IN";
      var SOUNDC_5_OUT = "Sound card 5 OUT";
      var SOUNDC_6_IN = "Sound card 6 IN";
      var SOUNDC_6_OUT = "Sound card 6 out";

      // external ports
      var MIXER_IN_1 = "Mixer IN 1";
      var MIXER_IN_2 = "Mixer IN 2";
      var MIXER_IN_3 = "Mixer IN 3";
      var MIXER_OUT_1 = "Mixer OUT 1";
      var MIXER_OUT_2 = "Mixer OUT 2";
      var MIXER_OUT_3 = "Mixer OUT 3";
      var MIXER_MIC = "Mixer mic";
      var MIC_OUT = "Mic OUT";
      var HEAD_IN = "Headphone IN";
      var TRANS_IN = "Transmitter IN";
      var TELEPHONELINE_OUT = "Phone line";

      // services
      var PLAYOUT = "Playout service";
      var PREVIEW = "Preview service";
      var MONITOR = "Monitor service";
      var MIC = "Mic service";
      var ARCHIVER = "Archiver service";
      var LIBRARY = "Library service";
      var UI = "UI service";
      var TELEPHONY = "Telephony service";

      // connections going in/out of external devices
      var mixerIn1 = new Array();
      var mixerIn2 = new Array();
      var mixerIn3 = new Array();
      var mixerOut1 = new Array();
      var mixerOut2 = new Array();
      var mixerOut3 = new Array();
      var mixerMicOut = new Array();
      var micOut = new Array();
      var headphonesIn = new Array();
      var transmitterIn = new Array();

      // alsa-to-alsa within a soundcard
      var soundcard1redir = false;
      var soundcard2redir = false;
      var soundcard3redir = false;
      var soundcard4redir = false;
      var soundcard5redir = false;
      var soundcard6redir = false;

      // services running on machines
      var machine0services = new Array();
      var machine1services = new Array();
      var machine2services = new Array();

      // ports installed on machines
      var machine0ports = new Array();
      var machine1ports = new Array();
      var machine2ports = new Array();
      
      // ports going in/out of services
      var playoutServiceOut = new Array();
      var previewServiceOut = new Array();
      var archiverServiceIn = new Array();
      var micServiceIn = new Array();
      var micServiceOut = new Array();
      var monitorServiceIn = new Array();
      var monitorServiceOut = new Array();
      var telephonyServiceOut = new Array();

      // connections
      var coords = new Array();

      // parameters
      var mixer;
      var mic;
      var numMachines;
      var mixermic;
      var playout;
      var pcifm;
      var telephony;

      // machine names
      var machine0name;
      var machine1name;
      var machine2name;

      // IP addresses
      var machine0ip;
      var machine1ip;
      var machine2ip;

      // machine platforms
      var machin0platform;
      var machine1platform;
      var machine2platform;

      // hardware requirements
      var numSoundCards;
      var numMixerIn;
      var numMixerOut;
      var cableConnections = new Array();

      // line drawing
      var xLinesCovered = new Array();
      var yLinesCovered = new Array();

      // features supported
      var inputOnWindows = false;

      function gup(name) {
          name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
          var regexS = "[\\?&]" + name + "=([^&#]*)";
          var regex = new RegExp(regexS);
          var results = regex.exec(window.location.href);
          if(results == null) {
              return "";
          } else {
              return results[1];
          }
      }

      function generateConfig() {
         mixerIn1 = new Array();
         mixerIn2 = new Array();
	 mixerIn3 = new Array();
         mixerOut1 = new Array();
         mixerOut2 = new Array();
	 mixerOut3 = new Array();
         mixerMicOut = new Array();
         micOut = new Array();
         headphonesIn = new Array();
         transmitterIn = new Array();

         machine0services = new Array();
         machine1services = new Array();
         machine2services = new Array();

         machine0ports = new Array();
         machine1ports = new Array();
         machine2ports = new Array();
      
         playoutServiceOut = new Array();
         previewServiceOut = new Array();
         archiverServiceIn = new Array();
         micServiceIn = new Array();
         micServiceOut = new Array();
         monitorServiceIn = new Array();
         monitorServiceOut = new Array();
	 telephonyServiceOut = new Array();

         xLinesCovered = new Array();
         yLinesCovered = new Array();

         coords = new Array();

         numSoundCards = 0;
	 numMixerIn = 0;
	 numMixerOut = 0;
         cableConnections = new Array();

         mixer = getValue(document.configuration.mixer);
         mic = getValue(document.configuration.mic);
         numMachines = getValue(document.configuration.nummachines);
         mixermic = getValue(document.configuration.mixermic);
         playout = getValue(document.configuration.playout);
         pcifm = getValue(document.configuration.pcifm);
	 telephony = getValue(document.configuration.telephony);

         machine0services.push(UI);
      
         if(mixer == "true" && mic == "xlr" && pcifm == "no") {

             mixerIn1.push(MIC_OUT); micOut.push(MIXER_IN_1);
	     numMixerIn++;
             mixerIn2.push(SOUNDC_1_OUT);
	     numMixerIn++;
             numSoundCards++;
             cableConnections.push("XLR Mic to input 1 of mixer");
             cableConnections.push("TRS Jack for out of  sound card 1 to input 2 of mixer");
             
             if(playout == "ui") {
                 machine0services.push(PLAYOUT);
                 machine0ports.push(SOUNDC_1_OUT);
                 playoutServiceOut.push(SOUNDC_1_OUT);
             } else {
                 if(numMachines > 0) {
                     machine1services.push(PLAYOUT);
                     machine1ports.push(SOUNDC_1_OUT);
                     playoutServiceOut.push(SOUNDC_1_OUT);
                 } else {
                     alert("You need to have at least 1 more machine for playout, if you do not want to run playout on your UI machine");
                     return;
                 }
             }

             transmitterIn.push(MIXER_OUT_1);
             mixerOut1.push(TRANS_IN);
	     numMixerOut++;
             cableConnections.push("Output 1 of mixer to FM Transmitter")

             if(mixermic == "yes") {
                 if(numMachines == 0) {
                     mixerMicOut.push(SOUNDC_1_IN);
                     machine0ports.push(SOUNDC_1_IN);
                     machine0services.push(ARCHIVER);
                     archiverServiceIn.push(SOUNDC_1_IN);
                     cableConnections.push("Mixer-Mic Output to TRS jack for in of sound card 1");
                 } else if(playout == "nonui") {
                     mixerMicOut.push(SOUNDC_1_IN);
                     machine1ports.push(SOUNDC_1_IN);
                     machine1services.push(ARCHIVER);
                     archiverServiceIn.push(SOUNDC_1_IN);
                     cableConnections.push("Mixer-Mic Output to TRS jack for in of sound card 1");
                 } else {
                     mixerMicOut.push(SOUNDC_2_IN);
                     machine1ports.push(SOUNDC_2_IN);
                     machine1services.push(ARCHIVER);
                     archiverServiceIn.push(SOUNDC_2_IN);
                     cableConnections.push("Mixer-Mic Output to TRS jack for in of sound card 2");
                     numSoundCards++;
                 }
             } else {
                 if(numMachines == 0) {
                     mixerOut2.push(SOUNDC_1_IN);
		     numMixerOut++;
                     machine0ports.push(SOUNDC_1_IN);
                     machine0services.push(ARCHIVER);
                     archiverServiceIn.push(SOUNDC_1_IN);
                     cableConnections.push("Output 2 of mixer to TRS jack for in of sound card 1");
                 } else if(playout == "nonui") {
                     mixerOut2.push(SOUNDC_1_IN);
		     numMixerOut++;
                     machine1ports.push(SOUNDC_1_IN);
                     machine1services.push(ARCHIVER);
                     archiverServiceIn.push(SOUNDC_1_IN);
                     cableConnections.push("Output 2 of mixer to TRS jack for in of sound card 1");
                 } else {
                     mixerOut2.push(SOUNDC_2_IN);
		     numMixerOut++;
                     machine1ports.push(SOUNDC_2_IN);
                     machine1services.push(ARCHIVER);
                     archiverServiceIn.push(SOUNDC_2_IN);
                     cableConnections.push("Output 2 of mixer to TRS jack for in of sound card 2");
                     numSoundCards++;
                 }
             }
             
             if(numMachines == 0) {
                 machine0ports.push(SOUNDC_2_IN);
                 machine0ports.push(SOUNDC_2_OUT);
                 mixerOut2.push(SOUNDC_2_IN);
		 numMixerOut++;
                 machine0services.push(MONITOR);
                 monitorServiceIn.push(SOUNDC_2_IN);
                 monitorServiceOut.push(SOUNDC_2_OUT);
		 soundcard2redir = true;
                 machine0services.push(PREVIEW);
                 headphonesIn.push(SOUNDC_2_OUT);
                 previewServiceOut.push(SOUNDC_2_OUT);
                 machine0services.push(LIBRARY);
                 numSoundCards++;
                 cableConnections.push("TRS Jack for out of sound card 2 to headphones");
                 cableConnections.push("Output 2 of mixer to TRS Jack for in of sound card 2");
             } else if(numMachines == 1) {
                 if(entryExists(machine1ports, SOUNDC_2_IN) == -1) {
                     machine1ports.push(SOUNDC_2_IN); // probably duplicate entries are inserted
                     machine1ports.push(SOUNDC_2_OUT);
                     mixerOut2.push(SOUNDC_2_IN);
		     numMixerOut++;
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_2_OUT);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     machine1services.push(LIBRARY);

                     cableConnections.push("TRS Jack for out of sound card 2 to headphones");
                     cableConnections.push("Output 2 of mixer to TRS Jack for in of sound card 2");                 

                     numSoundCards++;
                 } else {
                     machine1ports.push(SOUNDC_3_OUT);
                     mixerOut2.push(SOUNDC_3_IN);
		     numMixerOut++;
                     machine1ports.push(SOUNDC_3_IN);
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_3_IN);
                     monitorServiceOut.push(SOUNDC_3_OUT);
		     soundcard3redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_3_OUT);
                     previewServiceOut.push(SOUNDC_3_OUT);
                     machine1services.push(LIBRARY);

                     cableConnections.push("TRS Jack for out of sound card 3 to headphones");
                     cableConnections.push("Output 2 of mixer to TRS Jack for in of sound card 3");                 

                     numSoundCards++;
                 }
             } else if(numMachines == 2) {
                 if(entryExists(machine1ports, SOUNDC_2_IN) == -1) {
                     machine1ports.push(SOUNDC_2_IN); // probably duplicate entries are inserted
                     machine1ports.push(SOUNDC_2_OUT);
                     mixerOut2.push(SOUNDC_2_IN);
		     numMixerOut++;
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_2_OUT);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     machine2services.push(LIBRARY);

                     cableConnections.push("TRS Jack for out of sound card 2 to headphones");
                     cableConnections.push("Output 2 of mixer to TRS Jack for in of sound card 2");

                     numSoundCards++;
                 } else {
                     machine1ports.push(SOUNDC_3_OUT);
                     machine1ports.push(SOUNDC_3_IN);
                     mixerOut2.push(SOUNDC_3_IN);
		     numMixerOut++;
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_3_IN);
                     monitorServiceOut.push(SOUNDC_3_OUT);
		     soundcard3redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_3_OUT);
                     previewServiceOut.push(SOUNDC_3_OUT);
                     machine2services.push(LIBRARY);

                     cableConnections.push("TRS Jack for out of sound card 3 to headphones");
                     cableConnections.push("Output 2 of mixer to TRS Jack for in of sound card 3");

                     numSoundCards++;
                 }
             }
      
         } else if(mixer == "true" && mic == "jack" && pcifm == "no") {

             mixerIn1.push(SOUNDC_1_OUT);
	     numMixerIn++;
             numSoundCards++;
             cableConnections.push("TRS Jack output for sound card 1 to input 1 of mixer");
             cableConnections.push("Jack Mic to TRS input for sound card 1");

             if(playout == "ui") {
                 machine0services.push(PLAYOUT);
                 machine0ports.push(SOUNDC_1_OUT);
                 playoutServiceOut.push(SOUNDC_1_OUT);
             } else {
                 if(numMachines > 0) {
                     machine1services.push(PLAYOUT);
                     machine1ports.push(SOUNDC_1_OUT);
                     playoutServiceOut.push(SOUNDC_1_OUT);
                 } else {
                     alert("You need to have at least 1 more machine for playout, if you do not want to run playout on your UI machine");
                     return;
                 }
             }

             transmitterIn.push(MIXER_OUT_1);
             mixerOut1.push(TRANS_IN);
	     numMixerOut++;
             cableConnections.push("Output 1 of mixer to FM Transmitter")

             if(numMachines == 0) {
                 micOut.push(SOUNDC_1_IN);
                 machine0ports.push(SOUNDC_1_IN);
                 machine0services.push(MIC);
                 micServiceOut.push(SOUNDC_1_OUT);
                 micServiceIn.push(SOUNDC_1_IN);
		 soundcard1redir = true;
                 machine0services.push(ARCHIVER);
                 archiverServiceIn.push(SOUNDC_1_IN);
             } else if(playout == "nonui") {
                 micOut.push(SOUNDC_1_IN);
                 machine1ports.push(SOUNDC_1_IN);
                 machine1services.push(MIC);
                 micServiceOut.push(SOUNDC_1_OUT);
                 micServiceIn.push(SOUNDC_1_IN);
		 soundcard1redir = true;
                 machine1services.push(ARCHIVER);
                 archiverServiceIn.push(SOUNDC_1_IN);
             } else {
                 mixerIn2.push(SOUNDC_2_OUT);
		 numMixerIn++;
                 micOut.push(SOUNDC_2_IN);
                 machine1ports.push(SOUNDC_2_IN);
                 machine1ports.push(SOUNDC_2_OUT);
                 machine1services.push(MIC);
                 micServiceOut.push(SOUNDC_2_OUT);
                 micServiceIn.push(SOUNDC_2_IN);
		 soundcard1redir = true;
                 machine1services.push(ARCHIVER);
                 archiverServiceIn.push(SOUNDC_2_IN);
                 numSoundCards++;
             }

             if(numMachines == 0) {
                 machine0ports.push(SOUNDC_2_IN);
                 machine0ports.push(SOUNDC_2_OUT);
                 mixerOut2.push(SOUNDC_2_IN);
		 numMixerOut++;
                 machine0services.push(MONITOR);
                 monitorServiceIn.push(SOUNDC_2_IN);
                 monitorServiceOut.push(SOUNDC_2_OUT);
		 soundcard2redir = true;
                 machine0services.push(PREVIEW);
                 headphonesIn.push(SOUNDC_2_OUT);
                 previewServiceOut.push(SOUNDC_2_OUT);
                 machine0services.push(LIBRARY);                 
                 numSoundCards++;

                 cableConnections.push("TRS Jack for output of sound card 2 to headphones");
                 cableConnections.push("Output 2 of mixer to TRS Jack input for sound card 2");
             } else if(numMachines == 1) {
                 if(entryExists(machine1ports, SOUNDC_2_OUT) == -1) {
                     machine1ports.push(SOUNDC_2_OUT); // probably duplicate entries are inserted
                     machine1ports.push(SOUNDC_2_IN); // probably duplicate entries are inserted
                     mixerOut2.push(SOUNDC_2_IN);
		     numMixerOut++;
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_2_OUT);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     machine1services.push(LIBRARY);                 

                     cableConnections.push("TRS Jack for output of sound card 2 to headphones");
                     cableConnections.push("Output 2 of mixer to TRS Jack input for sound card 2");

                     numSoundCards++;
                 } else {
                     machine1ports.push(SOUNDC_3_OUT);
                     machine1ports.push(SOUNDC_3_IN);
                     mixerOut2.push(SOUNDC_3_IN);
		     numMixerOut++;
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_3_IN);
                     monitorServiceOut.push(SOUNDC_3_OUT);
		     soundcard3redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_3_OUT);
                     previewServiceOut.push(SOUNDC_3_OUT);
                     machine1services.push(LIBRARY);

                     cableConnections.push("TRS Jack for output of sound card 3 to headphones");
                     cableConnections.push("Output 2 of mixer to TRS Jack input for sound card 3");

                     numSoundCards++;
                 }
             } else if(numMachines == 2) {
                 if(entryExists(machine1ports, SOUNDC_2_OUT) == -1) {
                     machine1ports.push(SOUNDC_2_OUT); // probably duplicate entries are inserted
                     machine1ports.push(SOUNDC_2_IN); // probably duplicate entries are inserted
                     mixerOut2.push(SOUNDC_2_IN);
		     numMixerOut++;
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_2_OUT);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     machine2services.push(LIBRARY);

                     cableConnections.push("TRS Jack for output of sound card 2 to headphones");
                     cableConnections.push("Output 2 of mixer to TRS Jack input for sound card 2");

                     numSoundCards++;
                 } else {
                     machine1ports.push(SOUNDC_3_OUT);
                     machine1ports.push(SOUNDC_3_IN);
                     mixerOut2.push(SOUNDC_3_IN);
		     numMixerOut++;
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_3_IN);
                     monitorServiceOut.push(SOUNDC_3_OUT);
		     soundcard3redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_3_OUT);
                     previewServiceOut.push(SOUNDC_3_OUT);
                     machine2services.push(LIBRARY);

                     cableConnections.push("TRS Jack for output of sound card 3 to headphones");
                     cableConnections.push("Output 2 of mixer to TRS Jack input for sound card 3");

                     numSoundCards++;
                 }
             }
             
         } else if(mixer == "false" && pcifm == "no") {

             cableConnections.push("Jack Mic to TRS Jack for input of sound card 1");

             if(playout == "ui") {
                 machine0services.push(PLAYOUT);
                 machine0ports.push(SOUNDC_1_OUT);
                 playoutServiceOut.push(SOUNDC_1_OUT);

                 micOut.push(SOUNDC_1_IN);
                 machine0ports.push(SOUNDC_1_IN);
                 machine0services.push(MIC);
                 micServiceOut.push(SOUNDC_1_OUT);
                 micServiceIn.push(SOUNDC_1_IN);
		 soundcard1redir = true;
                 machine0services.push(ARCHIVER);
                 archiverServiceIn.push(SOUNDC_1_IN);

             } else {
                 if(numMachines > 0) {
                     machine1services.push(PLAYOUT);
                     machine1ports.push(SOUNDC_1_OUT);
                     playoutServiceOut.push(SOUNDC_1_OUT);

                     micOut.push(SOUNDC_1_IN);
                     machine1ports.push(SOUNDC_1_IN);
                     machine1services.push(MIC);
                     micServiceOut.push(SOUNDC_1_OUT);
                     micServiceIn.push(SOUNDC_1_IN);
		     soundcard1redir = true;
                     machine1services.push(ARCHIVER);
                     archiverServiceIn.push(SOUNDC_1_IN);

                 } else {
                     alert("You need to have at least 1 more machine for playout, if you do not want to run playout on your UI machine");
                     return;
                 }
             }

             transmitterIn.push(SOUNDC_1_OUT);

             cableConnections.push("TRS Jack for output of sound card 1 to FM transmitter");
             cableConnections.push("TRS Jack for output of sound card 2 to Headphones");

             if(numMachines == 0) {
                 machine0ports.push(SOUNDC_2_OUT);
                 machine0ports.push(SOUNDC_2_IN);
                 machine0services.push(MONITOR);
                 monitorServiceIn.push(SOUNDC_2_IN);
                 monitorServiceOut.push(SOUNDC_2_OUT);
		 soundcard2redir = true;
                 machine0services.push(PREVIEW);
                 headphonesIn.push(SOUNDC_2_OUT);
                 previewServiceOut.push(SOUNDC_2_OUT);
                 machine0services.push(LIBRARY);                 
                 numSoundCards++;
             } else if(numMachines == 1) {
                 if(playout == "ui") {
                     machine0ports.push(SOUNDC_2_OUT);
                     machine0ports.push(SOUNDC_2_IN);
                     machine0services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine0services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_2_OUT);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     machine1services.push(LIBRARY);
                     numSoundCards++;
                 } else {
                     machine1ports.push(SOUNDC_2_OUT);
                     machine1ports.push(SOUNDC_2_IN);
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_2_OUT);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     machine1services.push(LIBRARY);                 
                     numSoundCards++;
                 }
             } else if(numMachines == 2) {
                 if(playout == "ui") {
                     machine0ports.push(SOUNDC_2_OUT);
                     machine0ports.push(SOUNDC_2_IN);
                     machine0services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine0services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_2_OUT);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     machine2services.push(LIBRARY);
                     numSoundCards++;
                 } else {
                     machine1ports.push(SOUNDC_2_OUT);
                     machine1ports.push(SOUNDC_2_IN);
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine1services.push(PREVIEW);
                     headphonesIn.push(SOUNDC_2_OUT);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     machine2services.push(LIBRARY);
                     numSoundCards++;
                 }
             }

         } else if(pcifm == "yes") {

   	     cableConnections.push("Jack output for sound card 1 to PCI FM transmitter card");
   	     cableConnections.push("Jack output for sound card 2 to headphones");

             if(playout == "ui") {
                 machine0services.push(PLAYOUT);
                 machine0ports.push(SOUNDC_1_OUT);
                 playoutServiceOut.push(SOUNDC_1_OUT);
                 numSoundCards++;

                 machine0ports.push(SOUNDC_1_IN);
                 machine0services.push(ARCHIVER);
                 archiverServiceIn.push(SOUNDC_1_IN);
                 machine0services.push(MIC);
                 micServiceIn.push(SOUNDC_1_IN);
                 micServiceOut.push(SOUNDC_1_OUT);
		 soundcard1redir = true;

                 machine0ports.push(SOUNDC_2_OUT);
                 machine0ports.push(SOUNDC_2_IN);
                 machine0services.push(MONITOR);
                 monitorServiceIn.push(SOUNDC_2_IN);
                 monitorServiceOut.push(SOUNDC_2_OUT);
		 soundcard2redir = true;
                 machine0services.push(PREVIEW);
                 previewServiceOut.push(SOUNDC_2_OUT);
                 numSoundCards++;

                 headphonesIn.push(SOUNDC_2_OUT);
                 
             } else {
                 if(numMachines > 0) {
                     machine1services.push(PLAYOUT);
                     machine1ports.push(SOUNDC_1_OUT);
                     playoutServiceOut.push(SOUNDC_1_OUT);
                     numSoundCards++;

                     machine1ports.push(SOUNDC_1_IN);
                     machine1services.push(ARCHIVER);
                     archiverServiceIn.push(SOUNDC_1_IN);
                     machine1services.push(MIC);
                     micServiceIn.push(SOUNDC_1_IN);
                     micServiceOut.push(SOUNDC_1_OUT);
		     soundcard1redir = true;

                     machine1ports.push(SOUNDC_2_OUT);
                     machine1ports.push(SOUNDC_2_IN);
                     machine1services.push(MONITOR);
                     monitorServiceIn.push(SOUNDC_2_IN);
                     monitorServiceOut.push(SOUNDC_2_OUT);
		     soundcard2redir = true;
                     machine1services.push(PREVIEW);
                     previewServiceOut.push(SOUNDC_2_OUT);
                     numSoundCards++;

                     headphonesIn.push(SOUNDC_2_OUT);

                 } else {
                     alert("You need to have at least 1 more machine for playout, if you do not want to run playout on your UI machine");
                     return;
                 }
             }

             transmitterIn.push(SOUNDC_1_OUT);

             if(mixer == "true" && mic == "xlr" && playout != "ui" && numMachines == 0) {
                 micOut.push(MIXER_IN_1); mixerIn1.push(MIC_OUT);
		 numMixerIn++;
	         cableConnections.push("XLR Mic to input 1 of mixer");
		 if(mixermic == "yes") {
                     mixerMicOut.push(SOUNDC_1_IN);
    	             cableConnections.push("Mixer-Mic output to TRS Jack input for soundcard 1");
                 } else {
		     mixerOut1.push(SOUNDC_1_IN);
		     numMixerOut++;
    	             cableConnections.push("Output 1 of mixer to TRS Jack input for soundcard 1");
                 }
             } else {
                 micOut.push(SOUNDC_1_IN); 
      	         cableConnections.push("Mic to Jack input for sound card 1");
             }

             if(numMachines == 0) {
                 machine0services.push(LIBRARY);
             } else if(numMachines == 1) {
                 machine1services.push(LIBRARY)
             } else if(numMachines == 2) {
                 machine2services.push(LIBRARY);
             }
         }

	 if(transmitterIn != MIXER_OUT_1 && transmitterIn != MIXER_OUT_2) {
	     if(monitorServiceIn[0] != "") {
	       cableConnections.push("TRS Jack audio cable from output of soundcard 1 to input of soundcard 2");
	     }
	 }

	 if(telephony != "no") {
	   var telephonyMachineServices;
	   var telephonyMachinePorts;

	   if(entryExists(machine0services, PREVIEW) != -1) {
	     telephonyMachineServices = machine0services;
	     telephonyMachinePorts = machine0ports;
	   } else if(entryExists(machine1services, PREVIEW) != -1) {
	     telephonyMachineServices = machine1services;
	     telephonyMachinePorts = machine1ports;
	   } else if(entryExists(machine2services, PREVIEW) != -1) {
	     telephonyMachineServices = machine2services;
	     telephonyMachinePorts = machine2ports;
	   }

	   telephonyMachineServices.push(TELEPHONY);
	   //	   if(entryExists(telephonyMachineServices, PLAYOUT) == -1) {
	     var soundcardName;
	     if(entryExists(telephonyMachineServices, ARCHIVER) != -1) {
	       var archiverSoundcard = archiverServiceIn[0];
	       var possiblyVacantSoundcard = archiverSoundcard.substring(0, archiverSoundcard.length - 2) + "OUT";
	       if(entryExists(telephonyMachinePorts, possiblyVacantSoundcard) == -1) {
		 soundcardName = possiblyVacantSoundcard;
	       } else {
		 numSoundCards++;
		 soundcardName = "Sound card " + numSoundCards + " OUT";
	       }
	     } else {
	       numSoundCards++;
	       soundcardName = "Sound card " + numSoundCards + " OUT";
	     }
	     telephonyServiceOut.push(soundcardName);
	     telephonyMachinePorts.push(soundcardName);
	     if(numMixerIn == 0) {
	       mixerIn1.push(soundcardName);
	     } else if(numMixerIn == 1) {
	       mixerIn2.push(soundcardName);
	     } else if(numMixerIn == 2) {
	       mixerIn3.push(soundcardName);
	     }
	     cableConnections.push("TRS Jack output for " + soundcardName.substring(0, soundcardName.length - 4) + " to input " + numMixerIn + " of mixer.");
	     numMixerIn++;
	     //	   }

	   telephonyMachinePorts.push(TELEPHONELINE_OUT);
	 }

         updateGraphics(mixer, mic, numMachines, mixermic, playout, pcifm, telephony);
	 updateVarious();
         updateHardwareReq(mixer, mic, numMachines, mixermic, playout, pcifm, telephony);
      }

      function entryExists(arrayOut, elementName) {
         var i;
         for(i = 0; i < arrayOut.length; i++) {
             if(arrayOut[i] == elementName)
                return i;
         }
         return -1;
      }

      function getValue(radioList) {
         var i;
         for(i = 0; i < radioList.length; i++) {
            if(radioList[i].checked) {
               return radioList[i].value;
            }
         }
         return "null";
      }

      function setValue(value, radioList) {
         var i;
         for(i = 0; i < radioList.length; i++) {
            if(radioList[i].value == value) {
               radioList[i].checked = true;
            } else {
               radioList[i].checked = false;
            }
         }
      }
      
      function updateGraphics(mixer, mic, numMachines, mixermic, playout, pcifm, telephony) {
         var jg = new jsGraphics('Canvas');
         jg.clear();
         jg.paint();
      
         jg.setFont("Times New Roman", "18px", Font.PLAIN);
      
         if(mixer == "true") {
             drawMixer(jg, 200, 0, mixermic);
         }

         drawMic(jg, 50, 0);
         drawHeadphones(jg, 450, 90);
         drawTransmitter(jg, 450, 0);
         
         if(numMachines >= 0) {
             drawMachine(jg, 150, 250, 0, machine0services, machine0ports);
         }
         if(numMachines >= 1) {
             drawMachine(jg, 520, 250, 1, machine1services, machine1ports);
         }
         if(numMachines >= 2) {
             drawMachine(jg, 890, 250, 2, machine2services, machine2ports);
         }

         drawConnections(jg, numMachines);

         jg.paint();
      }

      function drawMixer(jg, xPos, yPos, mixermic) {
//         jg.setColor('#dcdcdc');
//         jg.fillRect(xPos, yPos, 50, 80);
//         jg.setColor('black');
//         jg.drawRect(xPos, yPos, 50, 80);
   	 jg.drawImage(getImagePrefix() + "mixer.png", xPos - 10, yPos, 70, 120);
         if(mixermic == "yes") {
             jg.setColor('blue');
             jg.fillRect(xPos + 21, yPos + 115, 8, 20);
             jg.setColor('red');
             jg.drawString("Mixer mic", xPos + 30, yPos + 130);
       
             coords.push(MIXER_MIC + ":" + (xPos + 25) + ":" + (yPos + 125));
         }

         jg.setColor('blue');
         jg.fillRect(xPos -15, yPos + 15, 20, 8);
         jg.setColor('red');
         jg.drawString("Mixer IN 1", xPos - 95, yPos);
         coords.push(MIXER_IN_1 + ":" + (xPos - 15) + ":" + (yPos + 19));

         jg.setColor('blue');
         jg.fillRect(xPos -15, yPos + 55, 20, 8);
         jg.setColor('red');
         jg.drawString("Mixer IN 2", xPos - 95, yPos + 40);
         coords.push(MIXER_IN_2 + ":" + (xPos - 15) + ":" + (yPos + 59));

         jg.setColor('blue');
         jg.fillRect(xPos -15, yPos + 95, 20, 8);
         jg.setColor('red');
         jg.drawString("Mixer IN 3", xPos - 95, yPos + 80);
         coords.push(MIXER_IN_3 + ":" + (xPos - 15) + ":" + (yPos + 99));

         jg.setColor('blue');
         jg.fillRect(xPos + 45, yPos + 15, 20, 8);
         jg.setColor('red');
         jg.drawString("Mixer OUT 1", xPos + 60, yPos);
         coords.push(MIXER_OUT_1 + ":" + (xPos + 65) + ":" + (yPos + 19));

         jg.setColor('blue');
         jg.fillRect(xPos + 45, yPos + 55, 20, 8);
         jg.setColor('red');
         jg.drawString("Mixer OUT 2", xPos + 60, yPos + 40);
         coords.push(MIXER_OUT_2 + ":" + (xPos + 65) + ":" + (yPos + 59));

         jg.setColor('blue');
         jg.fillRect(xPos + 45, yPos + 95, 20, 8);
         jg.setColor('red');
         jg.drawString("Mixer OUT 3", xPos + 60, yPos + 80);
         coords.push(MIXER_OUT_3 + ":" + (xPos + 65) + ":" + (yPos + 99));
      }

      function drawMic(jg, xPos, yPos) {
	jg.drawImage(getImagePrefix() + "golive.png", xPos, yPos, 50, 50);
         coords.push(MIC_OUT + ":" + (xPos + 40) + ":" + (yPos + 19));
      }

      function drawHeadphones(jg, xPos, yPos) {
         jg.drawImage(getImagePrefix() + "preview.png", xPos, yPos, 30, 30);
         coords.push(HEAD_IN + ":" + (xPos - 5) + ":" + (yPos + 20));
      }

      function drawTransmitter(jg, xPos, yPos) {
         jg.drawImage(getImagePrefix() + "transmitter.png", xPos, yPos, 50, 80);
         coords.push(TRANS_IN + ":" + (xPos - 15) + ":" + (yPos + 19));
      }

      function drawMachine(jg, xPos, yPos, machineNum, machineServices, machinePorts) {
//         jg.setColor('#dcdcdc');
//         jg.fillRect(xPos, yPos, 50, 80);
//         jg.setColor('black');
//         jg.drawRect(xPos, yPos, 50, 80);
         if(machineNum == 0) {
           jg.drawImage(getImagePrefix() + "uimachine.png", xPos - 6, yPos, 60, 150);
         } else {
           jg.drawImage(getImagePrefix() + "server.png", xPos - 10, yPos, 60, 150);
         }


         var inCount = 0;
         var outCount = 0;
         var i;

         for(i = 0; i < machinePorts.length; i++) {
             jg.setColor('blue');
             if(machinePorts[i].indexOf('OUT') != -1 || machinePorts[i].indexOf('Phone') != -1) {
	       jg.fillRect(xPos + 45, yPos + 10 + outCount * 40, 20, 8);
	       jg.setColor('red');
	       if(machinePorts[i].indexOf('Sound') != -1) {
                 jg.drawString(machinePorts[i], xPos + 65, yPos + outCount*40 - 10);
	       } else if(telephony == "fxo") {
                 jg.drawString("FXO card with phone line", xPos + 65, yPos + outCount*40 - 10);
		 jg.drawImage(getImagePrefix() + "phoneline.png", xPos + 80, yPos + outCount*40 + 5, 30, 30);
	       } else if(telephony == "ata") {
		 jg.drawString("ATA with phone line", xPos + 65, yPos + outCount*40 - 10);
		 jg.drawImage(getImagePrefix() + "ata.png", xPos + 80, yPos + outCount*40 + 10, 30, 30);
		 jg.drawImage(getImagePrefix() + "phoneline.png", xPos + 110, yPos + outCount*40 + 10, 30, 30);
	       }
	       coords.push(machinePorts[i] + ":" + (xPos + 65) + ":" + (yPos + 14 + outCount * 40));
	       outCount = outCount + 1;
             } else {
                 jg.fillRect(xPos -15, yPos + 10 + inCount * 40, 20, 8);
                 jg.setColor('red');
                 jg.drawString(machinePorts[i], xPos -140, yPos + inCount*40 - 10);
                 coords.push(machinePorts[i] + ":" + (xPos - 15) + ":" + (yPos + inCount*40 + 14));
                 inCount = inCount + 1;
             }
         }

         jg.setColor('black');
         jg.drawString("Machine " + machineNum + ":", xPos, yPos + 165);
         jg.drawLine(xPos, yPos + 185, xPos + 70, yPos + 185);
         for(i = 0; i < machineServices.length; i++) {
             jg.drawString(machineServices[i], xPos, yPos + 190 + (i + 1) * 20);
         }

         if(machineNum == 0 && numMachines == 0) {
             jg.drawString("IPC server", xPos, yPos + 190 + (i + 1) * 20);
         } else if(machineNum == 1 && numMachines > 0) {
             jg.drawString("IPC server", xPos, yPos + 190 + (i + 1) * 20);
         }
      }

      function drawConnections(jg, numMachines) {
         jg.setColor('maroon');
         jg.setStroke(2);

         drawLinks(jg, micOut, MIC_OUT);
         drawLinks(jg, transmitterIn, TRANS_IN);
         drawLinks(jg, headphonesIn, HEAD_IN);
         drawLinks(jg, mixerMicOut, MIXER_MIC);

	 if(transmitterIn != MIXER_OUT_1 && transmitterIn != MIXER_OUT_2) {
	     if(monitorServiceIn[0] != "") {
	        drawLinks(jg, transmitterIn, monitorServiceIn[0]);
	     }
	 }

         if(numMachines >= 0) {
             drawMachineLinks(jg, machine0ports, 0);
         }
         if(numMachines >= 1) {
             drawMachineLinks(jg, machine1ports, 1);
         }
         if(numMachines >= 2) {
             drawMachineLinks(jg, machine2ports, 2);
         }
      }

      function drawMachineLinks(jg, machinePorts, machineNum) {
         var k;

         for(k = 0; k < machinePorts.length; k++) {
             checkAndDrawLinks(jg, machinePorts[k], mixerIn1, MIXER_IN_1);
             checkAndDrawLinks(jg, machinePorts[k], mixerIn2, MIXER_IN_2);
             checkAndDrawLinks(jg, machinePorts[k], mixerIn3, MIXER_IN_3);
             checkAndDrawLinks(jg, machinePorts[k], mixerOut1, MIXER_OUT_1);
             checkAndDrawLinks(jg, machinePorts[k], mixerOut2, MIXER_OUT_2);
             checkAndDrawLinks(jg, machinePorts[k], mixerOut3, MIXER_OUT_3);
         }
      }

      function checkAndDrawLinks(jg, elementName, arrayOut, destElementName) {
         var coordStr = elementStr(elementName);
         var startX = xCoord(coordStr);
         var startY = yCoord(coordStr);
         var i;

         for(i = 0; i < arrayOut.length; i++) {
            if(arrayOut[i] == elementName) {
                var endCoordStr = elementStr(destElementName);
                var endX = xCoord(endCoordStr);
                var endY = yCoord(endCoordStr);

                drawSegmentedLine(jg, parseInt(startX), parseInt(startY), parseInt(endX), parseInt(endY));
                break;
            }
         }         
      }

      function drawLinks(jg, arrayOut, elementName) {
         var coordStr = elementStr(elementName);
         var startX = xCoord(coordStr);
         var startY = yCoord(coordStr);
         var i;

         for(i = 0; i < arrayOut.length; i++) {
            var endCoordStr = elementStr(arrayOut[i]);
            var endX = xCoord(endCoordStr);
            var endY = yCoord(endCoordStr);

            drawSegmentedLine(jg, parseInt(startX), parseInt(startY), parseInt(endX), parseInt(endY));
         }
      }

      function elementStr(elementName) {
         var i;

         for(i = 0; i < coords.length; i++) {
             if(coords[i].indexOf(elementName) != -1) {
                 return coords[i];
             }
         }
         return "null:0:0";
      }

      function xCoord(coordStr) {
         return coordStr.split(":")[1];
      }

      function yCoord(coordStr) {
         return coordStr.split(":")[2];
      }

      function lineCovered(arrayOut, elementName) {
         var i;
         for(i = 0; i < arrayOut.length; i++) {
             if(Math.abs(arrayOut[i] - elementName) <= 4) {
                return true;
             }
         }
         return false;
      }

      function drawSegmentedLine(jg, x1, y1, x2, y2) {
         var dispX, dispY;
         var attempts;

         if(x1 == x2) {
             jg.drawLine(x1, y1, x2, y2);
             xLinesCovered.push(x1);
         } else if(y1 == y2) {
             jg.drawLine(x1, y1, x2, y2);
             yLinesCovered.push(y1);
         } else if(x1 < x2) {             
             attempts = 0;
             while(attempts < 5) {
                 dispY = (y2 - y1) / 2 + (15 * Math.random()) - 8;
                 dispX1 = 15 * Math.random() - 8;
                 dispX2 = 15 * Math.random() - 8;
                 if(!lineCovered(xLinesCovered, x1 - dispX1) && !lineCovered(xLinesCovered, x2 + dispX2) && !lineCovered(yLinesCovered, y1 + dispY)) {
                     jg.drawLine(x1 - dispX1, y1, x1 - dispX1, y1 + dispY);
                     jg.drawLine(x1 - dispX1, y1 + dispY, x2 + dispX2, y1 + dispY);
                     jg.drawLine(x2 + dispX2, y1 + dispY, x2 + dispX2, y2);            
                     xLinesCovered.push(x1 - dispX1);
                     xLinesCovered.push(x2 + dispX2);
                     yLinesCovered.push(y1 + dispY);
                     break;
                 }
                 attempts ++;
             }
         } else if(x1 > x2) {
             attempts = 0;
             while(attempts < 5) {
                 dispY = (y1 - y2) / 2 + (15 * Math.random()) - 8;
                 dispX1 = 15 * Math.random() - 8;
                 dispX2 = 15 * Math.random() - 8;
                 if(!lineCovered(xLinesCovered, x1 + dispX1) && !lineCovered(xLinesCovered, x2 - dispX2) && !lineCovered(yLinesCovered, y2 + dispY)) {
                     jg.drawLine(x2 - dispX2, y2, x2 - dispX2, y2 + dispY);
                     jg.drawLine(x2 - dispX2, y2 + dispY, x1 + dispX1, y2 + dispY);
                     jg.drawLine(x1 + dispX1, y2 + dispY, x1 + dispX1, y1);
                     xLinesCovered.push(x1 + dispX1);
                     xLinesCovered.push(x2 - dispX2);
                     yLinesCovered.push(y2 + dispY);
                     break;
                 }
                 attempts ++;
             }
         }
      }

      function getMachineName(elementName) {
         if(entryExists(machine0services, elementName) != -1) { return machine0name; }
         else if(entryExists(machine1services, elementName) != -1) { return machine1name; }
         else if(entryExists(machine2services, elementName) != -1) { return machine2name; }
         else { return "null"; }
      }

      function getMachineIP(elementName) {
         if(entryExists(machine0services, elementName) != -1) { return machine0ip; }
         else if(entryExists(machine1services, elementName) != -1) { return machine1ip; }
         else if(entryExists(machine2services, elementName) != -1) { return machine2ip; }
         else { return "null"; }
      }

      function getMachinePlatform(elementName) {
         if(entryExists(machine0services, elementName) != -1) { return machine0platform; }
         else if(entryExists(machine1services, elementName) != -1) { return machine1platform; }
         else if(entryExists(machine2services, elementName) != -1) { return machine2platform; }
         else { return "null"; }
      }

function getNextAvailableResourceNumber(platformPrefix, elementNumber, elementDir, arrayOut) {
  if(elementDir == "in")
    return elementNumber;

  var count = entryExists(arrayOut, platformPrefix + elementNumber + "_" + elementDir);
  if(count == -1) {
    return elementNumber;
  } else {
    elementNumber++;
    while(entryExists(arrayOut, platformPrefix + elementNumber + "_" + elementDir) > -1)
      elementNumber++;
    return elementNumber;
  }
}

function getMachinePorts(elementName) {
  if(entryExists(machine0services, elementName) != -1) { return machine0ports; }
  else if(entryExists(machine1services, elementName) != -1) { return machine1ports; }
  else if(entryExists(machine2services, elementName) != -1) { return machine2ports; }
  else { return "null"; }
}

function getSoundCardResourceName(elementName, platform, arrayOut) {
  if(platform == "linux") {
    if(elementName == SOUNDC_1_IN) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 1, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_1_OUT) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 1, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_2_IN) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 2, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_2_OUT) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 2, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_3_IN) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 3, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_3_OUT) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 3, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_4_IN) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 4, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_4_OUT) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 4, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_5_IN) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 5, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_5_OUT) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 5, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_6_OUT) { return "soundcardalsa" + getNextAvailableResourceNumber("soundcardalsa", 6, "out", arrayOut) + "_out"; }
  } else {
    if(elementName == SOUNDC_1_IN) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 1, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_1_OUT) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 1, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_2_IN) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 2, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_2_OUT) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 2, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_3_IN) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 3, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_3_OUT) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 3, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_4_IN) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 4, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_4_OUT) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 4, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_5_IN) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 5, "in", arrayOut) + "_in"; }
    else if(elementName == SOUNDC_5_OUT) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 5, "out", arrayOut) + "_out"; }
    else if(elementName == SOUNDC_6_OUT) { return "soundcardwin" + getNextAvailableResourceNumber("soundcardwin", 6, "out", arrayOut) + "_out"; }
  }
}

function getSoundCardDeviceName(elementName, platform, soundcardNum) {
  if(platform == "linux") {
    return "ALSA, default:" + soundcardNum; 
  } else {
    return "WIN, " + soundcardNum; 
  }
}

      function getSoundCardNum(arrayOut, elementName) {
         var i;
         var count = 0;
         var seen = new Array();
	 var corresElementName;

	 if(elementName == SOUNDC_1_IN) { corresElementName = SOUNDC_1_OUT; }
	 else if(elementName == SOUNDC_2_IN) { corresElementName = SOUNDC_2_OUT; }
	 else if(elementName == SOUNDC_3_IN) { corresElementName = SOUNDC_3_OUT; }
	 else if(elementName == SOUNDC_4_IN) { corresElementName = SOUNDC_4_OUT; }
	 else if(elementName == SOUNDC_5_IN) { corresElementName = SOUNDC_5_OUT; }
	 else if(elementName == SOUNDC_1_OUT) { corresElementName = SOUNDC_1_IN; }
	 else if(elementName == SOUNDC_2_OUT) { corresElementName = SOUNDC_2_IN; }
	 else if(elementName == SOUNDC_3_OUT) { corresElementName = SOUNDC_3_IN; }
	 else if(elementName == SOUNDC_4_OUT) { corresElementName = SOUNDC_4_IN; }
	 else if(elementName == SOUNDC_5_OUT) { corresElementName = SOUNDC_5_IN; }
	 else if(elementName == SOUNDC_6_OUT) { corresElementName = SOUNDC_6_IN; }

         for(i = 0; i < arrayOut.length; i++) {
             if(arrayOut[i] == elementName || arrayOut[i] == corresElementName) {
                return count;
             } else {
                if(entryExists(seen, arrayOut[i]) == -1) {
                    count++;
                    seen.push(arrayOut[i]);
                    if(arrayOut[i] == SOUNDC_1_IN) { seen.push(SOUNDC_1_OUT); }
                    else if(arrayOut[i] == SOUNDC_2_IN) { seen.push(SOUNDC_2_OUT); }
                    else if(arrayOut[i] == SOUNDC_3_IN) { seen.push(SOUNDC_3_OUT); }
                    else if(arrayOut[i] == SOUNDC_4_IN) { seen.push(SOUNDC_4_OUT); }
                    else if(arrayOut[i] == SOUNDC_5_IN) { seen.push(SOUNDC_5_OUT); }
                    else if(arrayOut[i] == SOUNDC_1_OUT) { seen.push(SOUNDC_1_IN); }
                    else if(arrayOut[i] == SOUNDC_2_OUT) { seen.push(SOUNDC_2_IN); }
                    else if(arrayOut[i] == SOUNDC_3_OUT) { seen.push(SOUNDC_3_IN); }
                    else if(arrayOut[i] == SOUNDC_4_OUT) { seen.push(SOUNDC_4_IN); }
                    else if(arrayOut[i] == SOUNDC_5_OUT) { seen.push(SOUNDC_5_IN); }
		    else if(arrayOut[i] == SOUNDC_6_OUT) { seen.push(SOUNDC_6_IN); }
                }
             }
         }

         return -1;
      }

      function isSoundCardShared(elementName) {
         var deviceName = elementName;
	 var redir = false;

         if(deviceName == SOUNDC_1_IN) { deviceName = SOUNDC_1_OUT; redir = soundcard1redir; }
         else if(deviceName == SOUNDC_2_IN) { deviceName = SOUNDC_2_OUT; redir = soundcard2redir; }
         else if(deviceName == SOUNDC_3_IN) { deviceName = SOUNDC_3_OUT; redir = soundcard3redir; }
         else if(deviceName == SOUNDC_4_IN) { deviceName = SOUNDC_4_OUT; redir = soundcard4redir; }
         else if(deviceName == SOUNDC_5_IN) { deviceName = SOUNDC_5_OUT; redir = soundcard5redir; }
	 else if(deviceName == SOUNDC_6_IN) { deviceName = SOUNDC_6_OUT; redir = soundcard6redit; }

         if(entryExists(monitorServiceOut, deviceName) != -1 || (redir && entryExists(playoutServiceOut, deviceName) == -1) ||
	    (entryExists(machine0services, MIC) == -1 && entryExists(machine1services, MIC) == -1 && entryExists(machine2services, MIC) == -1 &&
	     entryExists(micServiceOut, deviceName) == -1))
	   return false;
         return true;
      }

      function updateHardwareReq(mixer, mic, numMachines, mixermic, playout, pcifm, telephony) {
         var i;
         var str = "";

         if(mixer == "true") { str += "- Mixer. You probably already have one.\n"; }
         else { str += "- A mixer is recommended\n"; }

         if(pcifm == "yes") { str += "- FM PCI transmitter with amplifier\n"; }
         else { str += "- FM transmitter. You probably already have one.\n"; }

         str += ("- " + numSoundCards + " sound cards\n");
         str += "     Use USB sound cards in addition to the on-board sound cards\n";
         str += ("- " + cableConnections.length + " audio cables\n");
         for(i = 0 ; i < cableConnections.length; i++) {
             str += ("     " + (i + 1) + ". " + cableConnections[i] + "\n");
         }
         
         if(mic == "xlr") { str += "- XLR Mic\n"; }
         else { str += "- TRS Mic. An XLR Mic is recommended though\n"; }

         str += "- Headphones. You probably already have one.\n";
      
         if(navigator.userAgent.indexOf("MSIE") != -1) {
            document.hardwareform.hardwarereq.rows = 17;
         } else if(navigator.userAgent.indexOf("Firefox") != -1) {
    	    document.hardwareform.hardwarereq.rows = 14;
         } else {

	 }
         document.hardwareform.hardwarereq.value = str; 
      }

