private static void display_unhandled_exception(Exception e)
 {
     ExceptionViewerDialog dial = new ExceptionViewerDialog(e);
     dial.ShowDialog();
     System.Console.WriteLine("Caught an unhandled exception. " + e.Message + e.InnerException + e.Source + e.StackTrace);
       //  throw e;
 }
        /// <summary>
        /// This method is to be called on the server side, and is not open to use via remoting. Its purpose
        /// is to update the servers internal list of hardware channels by querying the National Instruments drivers.
        /// </summary>
        public void refreshHardwareLists()
        {
            System.Console.WriteLine("Running refreshHardwareLists()...");

            try
            {

                // Set all the devices to disconnected. They will be set back to connected if they are detecter later in this method.
                foreach (DeviceSettings ds in serverSettings.myDevicesSettings.Values)
                    ds.deviceConnected = false;

                myHardwareChannels = new List<HardwareChannel>();

                //List of string identifiers for all devices detected in the process.
                detectedDevices = new List<string>();

                Dictionary<string, string> myDeviceDescriptions = new Dictionary<string, string>();

                // Detect National Instruments analog and digital channels.

                #region detect NI analog and digital  (daqMx)

                System.Console.WriteLine("Accessing DaqSystem devices list...");

                DaqSystem daqSystem = DaqSystem.Local;
                string[] devices = daqSystem.Devices;

                System.Console.WriteLine("...done.");

                System.Console.WriteLine("Found " + devices.Length.ToString() + " devices.");

                bool niDaqDevicesExistThatAreNotNamedDevSomething = false;

                for (int i = 0; i < devices.Length; i++)
                {
                    if (!devices[i].ToUpper().Contains("DEV"))
                    {
                        niDaqDevicesExistThatAreNotNamedDevSomething = true;
                    }

                    System.Console.WriteLine("Querying device " + i + "...");

                    detectedDevices.Add(devices[i]);

                    Device device = daqSystem.LoadDevice(devices[i]);

                    myDeviceDescriptions.Add(devices[i], device.ProductType);
                    string[] analogs = device.AOPhysicalChannels;
                    string[] digitalLines = device.DOLines;

                    if (!serverSettings.myDevicesSettings.ContainsKey(devices[i]))
                    {
                        serverSettings.myDevicesSettings.Add(devices[i], new DeviceSettings(devices[i], myDeviceDescriptions[devices[i]]));
                    }

                    // Special case: 6259 cards use 32-bit wide ports instead of 16 bit wide.
                    if (myDeviceDescriptions[devices[i]].Contains("6259"))
                    {
                        serverSettings.myDevicesSettings[devices[i]].use32BitDigitalPorts = true;
                    }

                    // Add all the analog channels, but only if the device settings say this card is enabled

                    if (serverSettings.myDevicesSettings.ContainsKey(devices[i]) && serverSettings.myDevicesSettings[devices[i]].DeviceEnabled)
                    {

                        if (serverSettings.myDevicesSettings[devices[i]].AnalogChannelsEnabled)
                        {
                            for (int j = 0; j < analogs.Length; j++)
                            {
                                string channelName = justTheChannelName(analogs[j], devices[i]);
                                HardwareChannel hc = new HardwareChannel(this.myServerSettings.ServerName, devices[i], channelName, HardwareChannel.HardwareConstants.ChannelTypes.analog);
                                if (!serverSettings.ExcludedChannels.Contains(hc))
                                {
                                    myHardwareChannels.Add(hc);
                                }
                            }
                        }

                        if (serverSettings.myDevicesSettings[devices[i]].DigitalChannelsEnabled)
                        {
                            for (int j = 0; j < digitalLines.Length; j++)
                            {
                                string channelName = justTheChannelName(digitalLines[j], devices[i]);
                                HardwareChannel hc = new HardwareChannel(this.myServerSettings.ServerName, devices[i], channelName, HardwareChannel.HardwareConstants.ChannelTypes.digital);
                                if (!serverSettings.ExcludedChannels.Contains(hc))
                                {
                                    myHardwareChannels.Add(hc);
                                }
                            }
                        }
                    }

                    System.Console.WriteLine("...done.");

                }

                #endregion

                #region "detect" RFSG cards

                foreach (ServerSettings.rfsgDeviceName rfsgDevName in serverSettings.RfsgDeviceNames)
                {

                    System.Console.WriteLine("Querying RFSG devices...");

                    string devName = rfsgDevName.DeviceName;
                    HardwareChannel hc = new HardwareChannel(serverSettings.ServerName, devName, "rf_out", HardwareChannel.HardwareConstants.ChannelTypes.gpib);
                    hc.gpibMasquerade = true;
                    hc.myGpibMasqueradeType = HardwareChannel.GpibMasqueradeType.RFSG;

                    myHardwareChannels.Add(hc);

                    if (!serverSettings.myDevicesSettings.ContainsKey(devName))
                    {
                        DeviceSettings devSettings = new DeviceSettings(devName, "RFSG driver library signal generator");
                        serverSettings.myDevicesSettings.Add(devName, devSettings);
                    }

                    System.Console.WriteLine("...done.");

                }

                #endregion

                #region detect NI GBIB

                // try a maxumimum of 10 GPIB boards... this is a totally arbitrary number.
                for (int i = 0; i < 10; i++)
                {

                    System.Console.WriteLine("Querying or detecting GPIB Board Number " + i + "...");

                    try
                    {
                        NationalInstruments.NI4882.Board board = new NationalInstruments.NI4882.Board(i);
                        board.SendInterfaceClear();
                        //              board.BecomeActiveController(false);
                        NationalInstruments.NI4882.AddressCollection listeners = board.FindListeners();

                        if (listeners.Count != 0)
                        {
                            foreach (NationalInstruments.NI4882.Address address in listeners)
                            {

                                int wait_delay = 100;

                                try
                                {
                                    NationalInstruments.NI4882.Device dev = new NationalInstruments.NI4882.Device(i, address);
                                    dev.Clear();

                                    // ask the device for its identity
                                    Action<string> writeDelegate = new Action<string>(dev.Write);
                                    IAsyncResult result = writeDelegate.BeginInvoke("*IDN?\n", null, null);
                                    result.AsyncWaitHandle.WaitOne(wait_delay, true);

                                    if (!result.IsCompleted)
                                    {
                                        messageLog(this, new MessageEvent("GPIB device took longer than " + wait_delay + " ms to respond to id request. Aborting."));
                                        dev.AbortAsynchronousIO();
                                        continue;
                                    }

                                    string deviceDescription = dev.ReadString();

                                    string deviceName = "GPIB" + i + "/" + gpibAddressToShortString(address);
                                    detectedDevices.Add(deviceName);

                                    myDeviceDescriptions.Add(deviceName, deviceDescription);

                                    HardwareChannel.HardwareConstants.GPIBDeviceType gpibDeviceType = new HardwareChannel.HardwareConstants.GPIBDeviceType();

                                    // VERY IMPORTANT!!!!!!!!!!
                                    // *******************  THIS IS WHERE YOU ADD DEVICE-DETECTION CODE FOR NEW GPIB DEVICES *********************/
                                    // detect the gpib device type
                                    if (deviceDescription.Contains("ESG-4000B"))
                                    {
                                        gpibDeviceType = HardwareChannel.HardwareConstants.GPIBDeviceType.Agilent_ESG_SIG_Generator;
                                    }
                                    // place any other device type detection code here as else ifs.
                                    else if (deviceDescription.Contains("N5181"))
                                    {
                                        gpibDeviceType = HardwareChannel.HardwareConstants.GPIBDeviceType.Agilent_ESG_SIG_Generator;
                                    }
                                    else
                                    {
                                        gpibDeviceType = HardwareChannel.HardwareConstants.GPIBDeviceType.Unknown;
                                    }

                                    HardwareChannel hc = new HardwareChannel(this.myServerSettings.ServerName,
                                        deviceName,
                                        gpibAddressToShortString(address),
                                        deviceDescription,
                                        HardwareChannel.HardwareConstants.ChannelTypes.gpib, dsAddress(address), gpibDeviceType);
                                    if (!serverSettings.ExcludedChannels.Contains(hc))
                                    {
                                        myHardwareChannels.Add(hc);
                                    }
                                }
                                catch (Exception e)
                                {
                                    messageLog(this, new MessageEvent("Exception when attempting to communicate with GPIB device " + "GPIB" + i + "/" + gpibAddressToShortString(address) + ". " + e.Message + "\n" + e.StackTrace));
                                }
                            }
                        }
                    }
                    catch (Exception)
                    {
                        // throw e;
                    }

                    System.Console.WriteLine("...done.");

                }

                /*
                NationalInstruments.NI4882.Board board = new NationalInstruments.NI4882.Board();
                board.FindListeners(
                */

                #endregion

                #region Detect NI RS232 ports

                System.Console.WriteLine("Querying NI VisaNS Serial Resources...");

                string[] resourceNames = null;
                NationalInstruments.VisaNS.ResourceManager VisaRescources = null;

                System.Console.WriteLine("...done.");

                try
                {
                    VisaRescources = NationalInstruments.VisaNS.ResourceManager.GetLocalManager();
                    resourceNames = VisaRescources.FindResources("/?*");
                }
                catch (Exception e)
                {
                    if (messageLogHandler != null)
                    {
                        messageLogHandler(this, new MessageEvent("Caught exception when attempting to detect serial ports: " + e.Message + e.StackTrace));
                    }
                    else
                    {
                        MessageBox.Show("Caught exception when attempting to detect serial ports: " + e.Message + e.StackTrace);
                    }
                }

                if (resourceNames != null)
                {

                    foreach (string s in resourceNames)
                    {

                        try
                        {

                            System.Console.WriteLine("Querying Resource " + s);

                            NationalInstruments.VisaNS.HardwareInterfaceType hType;
                            short chanNum;
                            VisaRescources.ParseResource(s, out hType, out chanNum);
                            if (hType == NationalInstruments.VisaNS.HardwareInterfaceType.Serial)
                            {
                                NationalInstruments.VisaNS.SerialSession ss = (NationalInstruments.VisaNS.SerialSession)NationalInstruments.VisaNS.ResourceManager.GetLocalManager().Open(s);

                                string description = ss.HardwareInterfaceName;

                                HardwareChannel hc = new HardwareChannel(this.serverSettings.ServerName, "Serial", s, description, HardwareChannel.HardwareConstants.ChannelTypes.rs232);
                                if (!serverSettings.ExcludedChannels.Contains(hc))
                                {
                                    MyHardwareChannels.Add(hc);
                                }
                                if (!detectedDevices.Contains("Serial"))
                                {
                                    detectedDevices.Add("Serial");
                                    myDeviceDescriptions.Add("Serial", "All local RS232 devices.");
                                }

                                ss.Dispose();

                            }
                        }
                        catch (Exception e)
                        {
                            System.Console.WriteLine("Caught exception when attempting to query serial resource named " + s + ". Displaying exception and then skipping this device.");
                            ExceptionViewerDialog ev = new ExceptionViewerDialog(e);
                            ev.ShowDialog();

                        }

                        System.Console.WriteLine("...done.");
                    }
                }

                #endregion

                // If necessary, add DeviceSettings entries for devices.
                foreach (string device in detectedDevices)
                {
                    // If this device does not already have a settings object...
                    if (!myServerSettings.myDevicesSettings.ContainsKey(device))
                    {
                        myServerSettings.myDevicesSettings.Add(device,
                            new DeviceSettings(device, myDeviceDescriptions[device]));
                    }
                    else
                    {
                        myServerSettings.myDevicesSettings[device].deviceConnected = true;
                    }
                }

                #region FPGA Detection and configuration

                if (this.serverSettings.UseOpalKellyFPGA)
                {
                    try
                    {
                        System.Console.WriteLine("Scanning for Opal Kelly FPGA devices...");

                        opalKellyDevices = new List<com.opalkelly.frontpanel.okCFrontPanel>();
                        opalKellyDeviceNames = new List<string>();

                        com.opalkelly.frontpanel.okCFrontPanel ok = new com.opalkelly.frontpanel.okCFrontPanel();
                        int fpgaDeviceCount = ok.GetDeviceCount();

                        System.Console.WriteLine("Found " + fpgaDeviceCount + " fpga device(s).");

                        for (int i = 0; i < fpgaDeviceCount; i++)
                        {
                            string name = ok.GetDeviceListSerial(i);
                            com.opalkelly.frontpanel.okCFrontPanel fpgaDevice = new com.opalkelly.frontpanel.okCFrontPanel();

                            com.opalkelly.frontpanel.okCFrontPanel.ErrorCode errorCode;

                            errorCode = fpgaDevice.OpenBySerial(name);

                            if (errorCode != com.opalkelly.frontpanel.okCFrontPanel.ErrorCode.NoError)
                            {
                                System.Console.WriteLine("Unable to open FPGA device " + name + " due to error code " + errorCode.ToString());
                                continue;
                            }

                            if (!this.detectedDevices.Contains(name))
                            {
                                this.detectedDevices.Add(name);
                            }

                            if (!myServerSettings.myDevicesSettings.ContainsKey(name))
                            {
                                DeviceSettings newSettings = new DeviceSettings(name, "Opal Kelly FPGA Device");
                                newSettings.deviceConnected = true;
                                newSettings.isFPGADevice = true;
                                myServerSettings.myDevicesSettings.Add(name, newSettings);
                            }
                            else
                            {
                                myServerSettings.myDevicesSettings[name].deviceConnected = true;
                            }

                            bool deviceProgrammed = false;

                            if (myServerSettings.myDevicesSettings[name].DeviceEnabled)
                            {
                                if (myServerSettings.myDevicesSettings[name].UsingVariableTimebase)
                                {
                                    deviceProgrammed = true;
                                    if (myServerSettings.myDevicesSettings[name].MySampleClockSource == DeviceSettings.SampleClockSource.DerivedFromMaster)
                                    {
                                        errorCode = fpgaDevice.ConfigureFPGA("variable_timebase_fpga_internal.bit");
                                    }
                                    else
                                    {
                                        errorCode = fpgaDevice.ConfigureFPGA("variable_timebase_fpga_external.bit");
                                    }

                                    if (errorCode == com.opalkelly.frontpanel.okCFrontPanel.ErrorCode.NoError)
                                    {

                                        System.Console.WriteLine("Programmed fpga device " + name + ". Used fpga code version based on sample clock source " + myServerSettings.myDevicesSettings[name].MySampleClockSource.ToString());

                                        opalKellyDeviceNames.Add(name);
                                        opalKellyDevices.Add(fpgaDevice);
                                    }
                                    else
                                    {
                                        System.Console.WriteLine("Error when attempting to program fpga device, error code " + errorCode.ToString());
                                    }
                                }
                            }
                            if (!deviceProgrammed)
                                System.Console.WriteLine("Fpga device " + name + " not programmed, as it is not enable or varible timebase on that device is not enabled.");

                        }
                    }
                    catch (Exception e)
                    {
                        if (e.InnerException != null && e.InnerException.InnerException != null)
                        {
                            Exception innerInner = e.InnerException.InnerException;
                            if (innerInner is System.BadImageFormatException)
                            {
                                MessageBox.Show("You are probably running the wrong build of Atticus. As of version 1.56 Atticus now comes in a 64-bit or 32-bit versions (in the bin\\Release-x64 and bin\\Release-x86 subdirectories respectively). These builds make use of different versions of the Opal Kelly Frontpanel libraries. Please ensure you are using the correct Atticus build. The exception which gave rise to this error will now be displayed.", "Wrong build of Atticus?");
                                DataStructures.ExceptionViewerDialog dial = new ExceptionViewerDialog(e);
                                dial.ShowDialog();
                            }
                            else if (innerInner is System.DllNotFoundException)
                            {
                                MessageBox.Show("As of version 1.56, Atticus is now built to use the 4.0.8 version of the Opal Kelly Frontpanel libraries/drivers. Perhaps you have the wrong version of the libraries installed? You can find a driver-only installer for 4.0.8 in the \\Opal Kelly\\Opal Kelly 4.0.8\\ directory of the Cicero distribution. Please install the newer drivers from there, or contact Opal Kelly to receive a CD with the newest full Frontpanel distribution (or go to the download section of github page for the Cicero Word generator, and download and install Opal-Kelly-CD-4.0.8.zip. You may also need to plug an Opal Kelly device into this computer during installation of the drivers, to insure that the WINUSB windows subsystem gets installed. The exception which gave rise to this error will now be displayed.", "Wrong version of FrontPanel drivers installed?");
                                DataStructures.ExceptionViewerDialog dial = new ExceptionViewerDialog(e);
                                dial.ShowDialog();
                            }
                            else
                            {
                                MessageBox.Show("An unrecognized exception was encountered when scanning for Opal Kelly FPGA devices. The exception will now be displayed.", "Unrecognized exception.");
                                DataStructures.ExceptionViewerDialog dial = new ExceptionViewerDialog(e);
                                dial.ShowDialog();
                            }
                        }
                        else
                        {
                            MessageBox.Show("An unrecognized exception was encountered when scanning for Opal Kelly FPGA devices. The exception will now be displayed.", "Unrecognized exception.");
                            DataStructures.ExceptionViewerDialog dial = new ExceptionViewerDialog(e);
                            dial.ShowDialog();
                        }

                        System.Console.WriteLine("Caught exceptions when attempting to scan for Opal Kelly FPGA devices. Aborted FPGA scan.");
                        opalKellyDevices = null;

                    }
                }
                else
                {
                    System.Console.WriteLine("Opal Kelly FPGA not enabled, so not scanning for them.");
                    opalKellyDevices = null;
                }

                #endregion

                System.Console.WriteLine("...done running refreshHardwareLists().");

                if (niDaqDevicesExistThatAreNotNamedDevSomething)
                {
                    System.Console.WriteLine("!! NOTE !! Some NI devices were detected whose name does not follow the Dev1, Dev2, Dev3, naming convention. This will cause problems.");
                    MessageBox.Show("National Instruments cards were detected whose names do not corresponding to the Dev1, Dev2, Dev3, etc. naming convention. This convention is relied upon by Atticus. Not following this convention will cause problems when attempting to run sequences on these devices. Please use MAX (the NI-supplied program) to rename your NI devices to follow the convention.", "Invalid niDaq Device Names");
                }

            }
            catch (Exception e)
            {
                System.Console.WriteLine("Unhandled exception when scanning connected hardware. Displaying exception, and then continuing to attempt to start Atticus.");
                ExceptionViewerDialog ev = new ExceptionViewerDialog(e);
                ev.ShowDialog();
                MessageBox.Show("Atticus encountered an unhandled exception when scanning for connected hardware. Atticus will continue to run. It is unlikely to function correctly for driving outputs, but will allow you to edit your settings to disable whatever is causing the unhandled exception.");
            }
        }
Example #3
0
        private void showInner_Click(object sender, EventArgs e)
        {
            ExceptionViewerDialog diag = new ExceptionViewerDialog(exp.InnerException);

            diag.ShowDialog();
        }
 private void showInner_Click(object sender, EventArgs e)
 {
     ExceptionViewerDialog diag = new ExceptionViewerDialog(exp.InnerException);
     diag.ShowDialog();
 }
 private void compareSequenceMenuItem_Click(object sender, EventArgs e)
 {
     try
         {
             SequenceData other = Storage.SaveAndLoad.LoadSequenceWithFileDialog();
             List<SequenceComparer.SequenceDifference> differences = SequenceComparer.CompareSequences(
                 Storage.sequenceData, other);
             SequenceDifferencesForm frm = new SequenceDifferencesForm(differences);
             frm.ShowDialog();
         }
         catch (Exception ex)
         {
             MessageBox.Show("Caught an exception when attempting to compare the sequences. Sequence comparison is still in its early stages. Please copy the following exception information and send it to the author. Don't worry, Cicero is not about to crash.");
             ExceptionViewerDialog view = new ExceptionViewerDialog(ex);
             view.ShowDialog();
         }
 }
        public bool do_run(int iterationNumber, SequenceData sequence, bool calibrationShot)
        {
            this.runningThread = Thread.CurrentThread;
            bool keepGoing = true;
            while (keepGoing)
            {
                MainClientForm.instance.CurrentlyOutputtingTimestep = null;

                setStatus(RunFormStatus.StartingRun);

                lic_chk();

                if (RunForm.backgroundIsRunning() && !this.isBackgroundRunform)
                {
                    addMessageLogText(this, new MessageEvent("A background run is still running. Waiting for it to terminate..."));
                    RunForm.abortAtEndOfNextBackgroundRun();
                    setStatus(RunFormStatus.ClosableOnly);
                    while (RunForm.backgroundIsRunning())
                    {
                        Thread.Sleep(50);
                    }

                    if (this.IsDisposed)
                    {
                        addMessageLogText(this, new MessageEvent("Foreground run form was closed before background run terminated. Aborting foreground run."));
                        return false;
                    }

                    setStatus(RunFormStatus.StartingRun);

                }

                addMessageLogText(this, new MessageEvent("Starting Run."));

                updateTitleBar(calibrationShot);

                // Begin section of undocumented Paris code that Aviv doesn't understand.
                bool wrongSavePath = false;
                try
                {
                    if (Storage.settingsData.SavePath != "")
                        System.IO.Directory.GetFiles(Storage.settingsData.SavePath);

                }
                catch
                {
                    wrongSavePath = true;
                }

                if (wrongSavePath)
                {
                    addMessageLogText(this, new MessageEvent("Unable to locate save path. Aborting run. See the SavePath setting (under Advanced->Settings Explorer)."));

                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }
                // End section of undocumented Paris code that Aviv doesn't understand

                if (!sequence.Lists.ListLocked)
                {
                    if (calibrationShot)
                    {
                        addMessageLogText(this, new MessageEvent("Calibration shot error -- Lists in the calibration shot are not locked. They must be locked manually. Please open your calibration sequence file, lock the lists, save your calibration sequence, and then re-import the calibration shot in this sequence."));
                        addMessageLogText(this, new MessageEvent("Skipping calibration shot and aborting run as a result of previous error."));
                        ErrorDetected = true;
                        setStatus(RunFormStatus.FinishedRun);
                        return false;
                    }

                    addMessageLogText(this, new MessageEvent("Lists not locked, attempting to lock them..."));

                    WordGenerator.MainClientForm.instance.variablesEditor.tryLockLists();

                    if (!sequence.Lists.ListLocked)
                    {
                        addMessageLogText(this, new MessageEvent("Unable to lock lists. Aborting run. See the Variables tab."));
                        ErrorDetected = true;

                        setStatus(RunFormStatus.FinishedRun);
                        return false;
                    }
                    addMessageLogText(this, new MessageEvent("Lists locked successfully."));
                }

                sequence.ListIterationNumber = iterationNumber;

                string listBoundVariableValues = "";

                foreach (Variable var in sequence.Variables)
                {
                    if (Storage.settingsData.PermanentVariables.ContainsKey(var.VariableName))
                    {
                        var.PermanentVariable = true;
                        var.PermanentValue = Storage.settingsData.PermanentVariables[var.VariableName];
                    }
                    else
                    {
                        var.PermanentVariable = false;
                    }
                }

                foreach (Variable var in sequence.Variables)
                {

                    if (var.ListDriven && !var.PermanentVariable)
                    {
                        if (listBoundVariableValues == "")
                        {
                            listBoundVariableValues = "List bound variable values: ";
                        }
                        listBoundVariableValues += var.VariableName + " = " + var.VariableValue.ToString() + ", ";
                    }
                }

                if (listBoundVariableValues != "")
                {
                    addMessageLogText(this, new MessageEvent(listBoundVariableValues));
                }

                foreach (Variable var in sequence.Variables)
                {
                    if (var.DerivedVariable)
                    {
                        if (var.parseVariableFormula(sequence.Variables) != null)
                        {
                            addMessageLogText(this, new MessageEvent("Warning! Derived variable " + var.ToString() + " has an an error. Will default to 0 for this run."));
                            ErrorDetected = true;
                        }
                    }
                }
                if (!calibrationShot)
                {
                    foreach (Variable var in sequence.Variables)
                    {
                        if (var.VariableName == "SeqMode")
                        {
                            addMessageLogText(this, new MessageEvent("Detected a variable with special name SeqMode. Nearest integer value " + (int)var.VariableValue + "."));
                            int i = (int)var.VariableValue;
                            if (i >= 0 && i < runningSequence.SequenceModes.Count)
                            {
                                SequenceMode mode = runningSequence.SequenceModes[i];
                                if (runningSequence == Storage.sequenceData)
                                {
                                    addMessageLogText(this, new MessageEvent("Settings sequence to sequence mode " + mode.ModeName + "."));
                                    WordGenerator.MainClientForm.instance.sequencePage.setMode(mode);
                                }
                                else
                                {
                                    addMessageLogText(this, new MessageEvent("Currently running sequence is either a calibration shot or background running sequence. Cannot change the sequence mode of a background sequence. Skipping mode change."));
                                }
                            }
                            else
                            {
                                addMessageLogText(this, new MessageEvent("Warning! Invalid sequence mode index. Ignoring the SeqMode variable."));
                                ErrorDetected = true;
                            }
                        }
                    }
                }

                if (variablePreviewForm != null)
                {
                    addMessageLogText(this, new MessageEvent("Updating variables according to variable preview window..."));
                    int nChanged = variablePreviewForm.refresh(sequence);
                    addMessageLogText(this, new MessageEvent("... " + nChanged + " variable values changed."));
                }

                // Create timestep "loop copies" if there are timestep loops in use
                bool useLoops = false;
                foreach (TimestepGroup tsg in sequence.TimestepGroups)
                {
                    if (tsg.LoopTimestepGroup && sequence.TimestepGroupIsLoopable(tsg) && tsg.LoopCountInt > 1)
                    {
                        useLoops = true;
                    }
                }
                if (useLoops)
                {
                    addMessageLogText(this, new MessageEvent("This sequence makes use of looping timestep groups. Creating temporary loop copies..."));
                    sequence.createLoopCopies();
                    addMessageLogText(this, new MessageEvent("...done"));
                }

                List<string> missingServers = Storage.settingsData.unconnectedRequiredServers();

                if (missingServers.Count != 0)
                {

                    string missingServerList = ServerManager.convertListOfServersToOneString(missingServers);

                    addMessageLogText(this, new MessageEvent("Unable to start run. The following required servers are not connected: " + missingServerList + "."));
                    ErrorDetected = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                List<LogicalChannel> overriddenDigitals = new List<LogicalChannel>();
                List<LogicalChannel> overriddenAnalogs = new List<LogicalChannel>();

                foreach (LogicalChannel lc in Storage.settingsData.logicalChannelManager.Digitals.Values)
                {
                    if (lc.overridden)
                        overriddenDigitals.Add(lc);
                }

                foreach (LogicalChannel lc in Storage.settingsData.logicalChannelManager.Analogs.Values)
                {
                    if (lc.overridden)
                        overriddenAnalogs.Add(lc);
                }

                if (overriddenDigitals.Count != 0)
                {
                    string list = "";
                    foreach (LogicalChannel lc in overriddenDigitals)
                    {
                        string actingName;
                        if (lc.Name != "" & lc.Name != null)
                        {
                            actingName = lc.Name;
                        }
                        else
                        {
                            actingName = "[Unnamed]";
                        }
                        list += actingName + ", ";
                    }
                    list = list.Remove(list.Length - 2);
                    list += ".";
                    addMessageLogText(this, new MessageEvent("Reminder. The following " + overriddenDigitals.Count + " digital channel(s) are being overridden: " + list));
                }

                if (overriddenAnalogs.Count != 0)
                {
                    string list = "";
                    foreach (LogicalChannel lc in overriddenAnalogs)
                    {
                        string actingName;
                        if (lc.Name != "" & lc.Name != null)
                        {
                            actingName = lc.Name;
                        }
                        else
                        {
                            actingName = "[Unnamed]";
                        }

                        list += actingName + ", ";
                    }
                    list = list.Remove(list.Length - 2);
                    list += ".";
                    addMessageLogText(this, new MessageEvent("Reminder. The following " + overriddenAnalogs.Count + " analog channel(s) are being overridden: " + list));
                }

                runStartTime = DateTime.Now;

                #region Sending camera instructions
                if (Storage.settingsData.UseCameras)
                {

                    byte[] msg;// = Encoding.ASCII.GetBytes(get_fileStamp(sequence));
                    string shot_name = NamingFunctions.get_fileStamp(sequence, Storage.settingsData, runStartTime);
                    string sequenceTime = sequence.SequenceDuration.ToString();
                    string FCamera;
                    string UCamera;

                    foreach (Socket theSocket in CameraPCsSocketList)
                    {
                        try
                        {
                            int index = CameraPCsSocketList.IndexOf(theSocket);
                            FCamera = connectedPCs[index].useFWCamera.ToString();
                            UCamera = connectedPCs[index].useUSBCamera.ToString();
                            msg = Encoding.ASCII.GetBytes(shot_name + "@" + sequenceTime + "@" + FCamera + "@" + UCamera + "@" + isCameraSaving.ToString() + "@\0");
                            theSocket.Send(msg, 0, msg.Length, SocketFlags.None);
                        }
                        catch { }
                    }
                }
                #endregion

                ServerManager.ServerActionStatus actionStatus;

                // send start timestamp
                addMessageLogText(this, new MessageEvent("Sending run start timestamp."));
                actionStatus = Storage.settingsData.serverManager.setNextRunTimestampOnConnectedServers(runStartTime, addMessageLogText);
                if (actionStatus != ServerManager.ServerActionStatus.Success)
                {
                    addMessageLogText(this, new MessageEvent("Unable to set start timestamp. " + actionStatus.ToString()));
                    ErrorDetected = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                // send settings data.
                addMessageLogText(this, new MessageEvent("Sending settings data."));
                actionStatus = Storage.settingsData.serverManager.setSettingsOnConnectedServers(Storage.settingsData, addMessageLogText);
                if (actionStatus != ServerManager.ServerActionStatus.Success)
                {
                    addMessageLogText(this, new MessageEvent("Unable to send settings data. " + actionStatus.ToString()));
                    ErrorDetected = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                // send sequence data.
                addMessageLogText(this, new MessageEvent("Sending sequence data."));
                actionStatus = Storage.settingsData.serverManager.setSequenceOnConnectedServers(sequence, addMessageLogText);
                if (actionStatus != ServerManager.ServerActionStatus.Success)
                {
                    addMessageLogText(this, new MessageEvent("Unable to send sequence data. " + actionStatus.ToString()));
                    ErrorDetected = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                // generate buffers.
                addMessageLogText(this, new MessageEvent("Generating buffers."));
                actionStatus = Storage.settingsData.serverManager.generateBuffersOnConnectedServers(iterationNumber, addMessageLogText);
                if (actionStatus != ServerManager.ServerActionStatus.Success)
                {
                    addMessageLogText(this, new MessageEvent("Unable to generate buffers. " + actionStatus.ToString()));
                    ErrorDetected = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                // arm tasks.

                Random rnd = new Random();
                clockID = (uint)rnd.Next();

                if (softwareClockProvider != null || networkClockProvider!=null)
                {
                    addMessageLogText(this, new MessageEvent("A software clock provider already exists, unexpectedly. Aborting."));
                    return false;
                }

                if (!Storage.settingsData.AlwaysUseNetworkClock)
                {
                    softwareClockProvider = new ComputerClockSoftwareClockProvider(10);
                    softwareClockProvider.addSubscriber(this, 41, 0);
                    softwareClockProvider.ArmClockProvider();
                }

                networkClockProvider = new NetworkClockProvider(clockID);
                networkClockProvider.addSubscriber(this, 41, 1);
                networkClockProvider.ArmClockProvider();

                currentSoftwareclockPriority = 0;

                addMessageLogText(this, new MessageEvent("Arming tasks."));
                actionStatus = Storage.settingsData.serverManager.armTasksOnConnectedServers(clockID, addMessageLogText);
                if (actionStatus != ServerManager.ServerActionStatus.Success)
                {
                    addMessageLogText(this, new MessageEvent("Unable to arm tasks. " + actionStatus.ToString()));
                    ErrorDetected = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                // generate triggers

                addMessageLogText(this, new MessageEvent("Generating triggers."));
                actionStatus = Storage.settingsData.serverManager.generateTriggersOnConnectedServers(addMessageLogText);
                if (actionStatus != ServerManager.ServerActionStatus.Success)
                {
                    addMessageLogText(this, new MessageEvent("Unable to generate triggers. " + actionStatus.ToString()));
                    ErrorDetected = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                setStatus(RunFormStatus.Running);

                // async call to progress bar initialization

                Action<double> initProgressBarAction = initializeProgressBar;
                Invoke(initProgressBarAction, new object[] { sequence.SequenceDuration });

                double duration = sequence.SequenceDuration;
                addMessageLogText(this, new MessageEvent("Sequence duration " + duration + " s. Running."));

                // start software clock
                if (softwareClockProvider!=null)
                    softwareClockProvider.StartClockProvider();
                networkClockProvider.StartClockProvider();

                while (true)
                {
                    if (currentSoftwareclockPriority == 0)
                    {
                        if (softwareClockProvider != null && (softwareClockProvider.getElapsedTime() >= (200 + duration * 1000.0)))
                            break;
                    }
                    else
                        if (networkClockProvider != null && (networkClockProvider.getElapsedTime() >= (duration * 1000.0)))
                            break;

                    Thread.Sleep(100);
                }

                if (softwareClockProvider!=null)
                    softwareClockProvider.AbortClockProvider();
                softwareClockProvider = null;
                networkClockProvider.AbortClockProvider();
                networkClockProvider = null;

                MainClientForm.instance.CurrentlyOutputtingTimestep = sequence.dwellWord();

                actionStatus = Storage.settingsData.serverManager.getRunSuccessOnConnectedServers(addMessageLogText);
                if (actionStatus != ServerManager.ServerActionStatus.Success)
                {
                    addMessageLogText(this, new MessageEvent("Run failed, possibly due to a buffer underrun. Please check the server event logs."));
                    ErrorDetected = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                if (useLoops)
                    sequence.cleanupLoopCopies();

                addMessageLogText(this, new MessageEvent("Finished run. Writing log file..."));
                RunLog runLog = new RunLog(runStartTime, formCreationTime, sequence, Storage.settingsData, WordGenerator.MainClientForm.instance.OpenSequenceFileName, WordGenerator.MainClientForm.instance.OpenSettingsFileName);
                string fileName = runLog.WriteLogFile();

                if (fileName != null)
                {
                    addMessageLogText(this, new MessageEvent("Log written to " + fileName));
                }
                else
                {
                    addMessageLogText(this, new MessageEvent("Log not written! Perhaps a file with this name already exists?"));
                    ErrorDetected = true;
                }

                foreach (RunLogDatabaseSettings rset in Storage.settingsData.RunlogDatabaseSettings)
                {

                    if (rset.Enabled)
                    {
                        RunlogDatabaseHandler handler = null;
                        try
                        {
                            handler = new RunlogDatabaseHandler(rset);
                            handler.addRunLog(fileName, runLog);
                            addMessageLogText(this, new MessageEvent("Run log added to mysql database at url " + rset.Url + " successfully."));
                        }
                        catch (RunLogDatabaseException e)
                        {
                            addMessageLogText(this, new MessageEvent("Caught exception when attempting to add runlog to mysqldatabase at " + rset.Url + "."));
                            if (rset.VerboseErrorReporting)
                            {
                                addMessageLogText(this, new MessageEvent("Displaying runlogdatabase exception. To disable this display, turn off verbose error reporting for this runlog database in Cicero settings (under Advanced->Settings Explorer)"));
                                ExceptionViewerDialog ev = new ExceptionViewerDialog(e);
                                ev.ShowDialog();
                            }
                            else
                            {
                                addMessageLogText(this, new MessageEvent("Exception was " + e.Message + ". For more detailed information, turn on verbose error reporting for this runlog database in Cicero settings (under Advanced->Settings Explorer)"));
                            }
                        }

                        if (handler != null)
                            handler.closeConnection();
                    }
                }

                if (runRepeat)
                    keepGoing = true;
                else
                    keepGoing = false;

                repeatCount++;

                if (abortAfterThis.Checked)
                {
                    userAborted = true;
                    setStatus(RunFormStatus.FinishedRun);
                    return false;
                }

                setStatus(RunFormStatus.FinishedRun);
            }

            return true;
        }