Exemple #1
0
        public void run()
        {
            // debug messages
            #if (DEBUG_KEEP_SAMPLES)
            logger.Error("DEBUG_KEEP_SAMPLES is enabled");
            #endif

            // check if there is no application instance
            if (application == null)
            {
                logger.Error("No application instance could be created");
            }

            // log message
            logger.Debug("Thread started");

            // local variables
            double[] samplePackage = null;

            #if (DEBUG_SAMPLES_LOG_PERFORMANCE)
            samplePackagesProcessed = 0;
            #endif

            // flag as running
            running = true;

            // check if the sytem should be configured and initialized at startup
            if (startupConfigAndInit)
            {
                if (MainThread.configureSystem())
                {
                    // successfully configured

                    // initialize
                    MainThread.initializeSystem();
                }
                else
                {
                    // check if there is no gui
                    if (noGUI)
                    {
                        // message and do not start the process
                        MessageBox.Show("Error during configuration, check log file", "Error during configuration", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        running = false;
                    }
                }
            }
            else
            {
                // check if there is no gui
                if (noGUI)
                {
                    // message and do not start the process
                    MessageBox.Show("Error during startup, without a GUI and automatic startup arguments there is no way to run the program, check startup arguments", "Error during startup", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    running = false;
                }
            }

            // check if the system should be started at startup (and is ready to start)
            if (startupStartRun && systemConfigured && systemInitialized)
            {
                // start the run
                MainThread.start();
            }

            // set an initial output time
            nextOutputTime = Stopwatch.GetTimestamp() + Stopwatch.Frequency;

            // loop while running
            while (running)
            {
                // lock for thread safety
                // (very much needed, else it will make calls to other modules and indirectly the data module, which already might have stopped at that point)
                lock (lockStarted) {
                    // check if we are processing samples
                    if (process)
                    {
                        // processing

                        // see if there samples in the queue, pick the sample for processing
                        samplePackage = null;
                        lock (samplePackagesBuffer.SyncRoot) {
                            // performance watch
                            if (Stopwatch.GetTimestamp() > nextOutputTime)
                            {
                                // check if there were sample discarded the last second
                                if (numSamplePackagesDiscarded > 0)
                                {
                                    // message missed
                                    logger.Error("Missed " + numSamplePackagesDiscarded + " samples, because the sample buffer was full, the roundtrip of a sample through the filter and application takes longer than the sample frequency of the source");

                                    // reset counter
                                    numSamplePackagesDiscarded = 0;
                                }

                                //
                                #if (DEBUG_SAMPLES_LOG_PERFORMANCE)
                                logger.Info("----------");
                                logger.Info("samples processed: " + samplePackagesProcessed);
                                logger.Info("number of samples left in buffer: " + numSamplePackagesInBuffer);
                                samplePackagesProcessed = 0;
                                #endif

                                // set the next time to output messages
                                nextOutputTime = Stopwatch.GetTimestamp() + Stopwatch.Frequency;
                            }


                            // check if there are samples in the buffer to process
                            if (numSamplePackagesInBuffer > 0)
                            {
                                // retrieve the sample to process (pointer to from array)
                                samplePackage = samplePackagesBuffer[sampleBufferReadIndex];

                                #if (!DEBUG_KEEP_SAMPLES)
                                // set the read index to the next item
                                sampleBufferReadIndex++;
                                if (sampleBufferReadIndex == sampleBufferSize)
                                {
                                    sampleBufferReadIndex = 0;
                                }

                                // decrease the itemcounter as it will be processed (to make space for another item in the samples buffer)
                                numSamplePackagesInBuffer--;
                                #endif
                            }
                        }

                        // check if there is a sample to process
                        if (samplePackage != null)
                        {
                            double[] output = null;

                            // Announce the sample at the beginning of the pipeline
                            Data.pipelineProcessingStart();

                            // keep?
                            for (int i = 0; i < plugins.Count; i++)
                            {
                                plugins[i].preFiltersProcess();
                            }

                            // log data (the 'LogPipelineInputStreamValue' function will not log the samples if pipeline input logging is disabled)
                            Data.logPipelineInputStreamValues(samplePackage);

                            // TODO:
                            // log for visualization (the 'LogVisualizationStreamValue' function will discard the sample if visualization is disabled)
                            //Data.logVisualizationStreamValue(sample);

                            // process the sample (filters)
                            for (int i = 0; i < filters.Count; i++)
                            {
                                filters[i].process(samplePackage, out output);
                                samplePackage = output;
                                output        = null;
                            }

                            // keep?
                            for (int i = 0; i < plugins.Count; i++)
                            {
                                plugins[i].postFiltersProcess();
                            }

                            // process the sample (application)
                            if (application != null)
                            {
                                application.process(samplePackage);
                            }

                            // Announce the sample at the end of the pipeline
                            Data.pipelineProcessingEnd();

                            // flush all plugin buffers to file
                            Data.writePluginData(-1);

                            #if (DEBUG_SAMPLES_LOG_PERFORMANCE)
                            samplePackagesProcessed++;
                            #endif
                        }

                        // sleep (when there are no samples) to allow for other processes
                        if (threadLoopDelayProc != -1 && numSamplePackagesInBuffer == 0)
                        {
                            // reset the manual reset event, so it is sure to block on the next call to WaitOne
                            //
                            // Note: not using AutoResetEvent because it could happen that .Set is called while not in WaitOne yet, when
                            // using AutoResetEvent this will cause it to skip the next WaitOne call
                            loopManualResetEvent.Reset();

                            // Sleep wait
                            loopManualResetEvent.WaitOne(threadLoopDelayProc);      // using WaitOne because this wait is interruptable (in contrast to sleep)
                        }
                    }
                    else
                    {
                        // not processing

                        // reset the manual reset event, so it is sure to block on the next call to WaitOne
                        //
                        // Note: not using AutoResetEvent because it could happen that .Set is called while not in WaitOne yet, when
                        // using AutoResetEvent this will cause it to skip the next WaitOne call
                        loopManualResetEvent.Reset();

                        // Sleep wait
                        loopManualResetEvent.WaitOne(threadLoopDelayNoProc); // using WaitOne because this wait is interruptable (in contrast to sleep)
                    }
                }                                                            // end lock

                // check if a stop delegate wants the processing to stop
                if (stopDataDelegateFlag)
                {
                    // stop the data
                    Data.stop();

                    // reset flag
                    stopDataDelegateFlag = false;
                }
            }   // end loop (running)

            // stop the source, filter, view and data (if these were running)
            stop(true);

            // destroy the source
            if (source != null)
            {
                source.destroy();
                source = null;
            }

            // destroy the filters
            for (int i = 0; i < filters.Count; i++)
            {
                filters[i].destroy();
            }

            // destroy the view
            if (application != null)
            {
                application.destroy();
            }

            // destroy the plugins
            for (int i = 0; i < plugins.Count; i++)
            {
                plugins[i].destroy();
            }

            // destroy the data class
            Data.destroy();

            // log message
            logger.Debug("Thread stopped");
        }
Exemple #2
0
        public static void Run(string[] args, Type applicationType)
        {
            // check the endianness
            if (!BitConverter.IsLittleEndian)
            {
                logger.Error("This software assumes a little-endianness OS, your OS uses a big-endian system. Exiting");
                return;
            }

            // TODO: check if all dependencies exists
            // TODO: also 32/64 bit (freetype or other dlls)

            // retrieve the current thread's culture as the initial culture
            CultureInfo culture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();

            // startup argument variables
            bool            nogui = false;
            bool            startupConfigAndInit = false;
            bool            startupStartRun      = false;
            string          parameterFile        = @"";
            string          source  = "";
            List <string[]> filters = new List <string[]>();

            // See if we are providing a graphical user interface (GUI)
            //
            // Note: done seperately because it will detemine whether error messages are
            //       also show as message dialogs, instead of only written to the log file
            for (int i = 0; i < args.Length; i++)
            {
                string argument = args[i].ToLower();
                if (argument == "-nogui")
                {
                    nogui = true;
                }
            }

            // process all startup arguments
            for (int i = 0; i < args.Length; i++)
            {
                string argument = args[i].ToLower();

                // check if the configuration and initialization should be done automatically at startup
                if (argument == "-startupconfigandinit")
                {
                    startupConfigAndInit = true;
                }

                // check if the run should be started automatically at startup
                if (argument == "-startupstartrun")
                {
                    startupStartRun = true;
                }

                // check if the source is given
                if (argument == "-source")
                {
                    // the next element should be the source, try to retrieve
                    if (args.Length >= i + 1 && !string.IsNullOrEmpty(args[i + 1]))
                    {
                        // check if valid source
                        int[] sourceIdx = ArrayHelper.jaggedArrayCompare(args[i + 1], availableSources, null, new int[] { 0 }, true);
                        if (sourceIdx == null)
                        {
                            string errMessage = "Could not find the source module '" + args[i + 1] + "' requested as startup argument), choose one of the following: " + ArrayHelper.jaggedArrayJoin(", ", availableSources, 0);
                            logger.Error(errMessage);
                            if (!nogui)
                            {
                                MessageBox.Show(errMessage, "Requested source module not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }

                            return;
                        }
                        else
                        {
                            // store the source-type as a string
                            source = availableSources[sourceIdx[0]][1];
                        }
                    }
                }

                // check if the parameterfile is given
                if (argument == "-parameterfile")
                {
                    // the next element should be the parameter file, try to retrieve
                    if (args.Length >= i + 1 && !string.IsNullOrEmpty(args[i + 1]))
                    {
                        parameterFile = args[i + 1];
                    }
                }

                // check if the language is given
                if (argument == "-language")
                {
                    // the next element should contain the culture name
                    if (args.Length >= i + 1 && !string.IsNullOrEmpty(args[i + 1]))
                    {
                        try {
                            // overwrite the culture with the given argument, this will cause the respective language
                            // resource file to be used (unless it does not exists, then it will revert to english)
                            culture = new CultureInfo(args[i + 1]);

                            // message
                            logger.Info("Language/culture set to '" + args[i + 1] + "'");
                        } catch (Exception) {
                            // with an exception the original culture object is ruined
                            // therefore re(clone) the current culture from the thread
                            culture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();

                            // message
                            logger.Error("Language argument given but unknown culture, using the local culture (language)");
                        }
                    }
                }
            }

            // adjust decimal seperator and group seperator
            culture.NumberFormat.NumberDecimalSeparator = ".";
            culture.NumberFormat.NumberGroupSeparator   = "";
            culture.NumberFormat.NumberGroupSizes       = new int[] { 0 };

            // set the culture for every future thread and the current thread
            CultureInfo.DefaultThreadCurrentCulture   = culture;
            CultureInfo.DefaultThreadCurrentUICulture = culture;
            Thread.CurrentThread.CurrentCulture       = culture;
            Thread.CurrentThread.CurrentUICulture     = culture;

            // try to read the pipeline modules (source and filters) from the <AppName>.Config file
            try {
                // if no valid source was parsed from a command-line argument, then try to retrieve a valid source from the <appname>.config file
                KeyValueConfigurationElement appConfigSource = PipelineConfigurationSection.Pipeline.Source;
                if (string.IsNullOrEmpty(source) && !string.IsNullOrEmpty(appConfigSource.Value))
                {
                    int[] sourceIdx = ArrayHelper.jaggedArrayCompare(appConfigSource.Value, availableSources, null, new int[] { 0 }, true);
                    if (sourceIdx != null)
                    {
                        // store the source-type as a string
                        source = availableSources[sourceIdx[0]][1];
                    }
                    else
                    {
                        string errMessage = "Could not find the source module '" + appConfigSource.Value + "' requested in the <appname>.config file, choose one of the following: " + ArrayHelper.jaggedArrayJoin(", ", availableSources, 0);
                        logger.Error(errMessage);
                        if (!nogui)
                        {
                            MessageBox.Show(errMessage, "Requested source module not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        return;
                    }
                }

                // if no valid filters were parsed from a command-line argument, then try to retrieve valid filters from the <appname>.config file
                List <FilterConfigurationElement> appConfigFilters = PipelineConfigurationSection.Pipeline.Filters.All;
                if (filters.Count == 0 && appConfigFilters.Count > 0)
                {
                    for (int iFilter = 0; iFilter < appConfigFilters.Count; iFilter++)
                    {
                        string filterName = appConfigFilters[iFilter].Name;
                        string filterType = appConfigFilters[iFilter].Type;

                        // check if valid filter
                        int[] filterIdx = ArrayHelper.jaggedArrayCompare(filterType, availableFilters, null, new int[] { 0 }, true);
                        if (filterIdx == null)
                        {
                            string errMessage = "A filter-module of the type '" + filterType + "' was requested in the <appname>.config file, but could not be found. The following filter-types are available: " + ArrayHelper.jaggedArrayJoin(", ", availableFilters, 0);
                            logger.Error(errMessage);
                            if (!nogui)
                            {
                                MessageBox.Show(errMessage, "Requested filter module not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                            return;
                        }
                        else
                        {
                            // add the filter as a string array with two values (filter-type and filter-name)
                            filters.Add(new string[] { availableFilters[filterIdx[0]][1], filterName });
                        }
                    }
                }
            } catch (Exception e) {
                string errMessage = "Error while reading the Pipeline config section in the <appname>.config file: " + e.Message;
                logger.Error(errMessage);
                if (!nogui)
                {
                    MessageBox.Show(errMessage, "Error in the <appname>.config file", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }

            // if no source passed using command-line or <appname>.config file then allow the user to choose a source by popup
            if (string.IsNullOrEmpty(source))
            {
                source = ListMessageBox.ShowSingle("Source", availableSources);
                if (string.IsNullOrEmpty(source))
                {
                    return;
                }
            }


            //
            // Setup and initialize Palmtree
            //

            // name this thread
            if (Thread.CurrentThread.Name == null)
            {
                Thread.CurrentThread.Name = "Main Thread";
            }

            // create the main (control) object
            MainThread mainThread = new MainThread(startupConfigAndInit, startupStartRun, nogui);

            // variable for the GUI interface object
            GUIMain gui = null;

            // check if the GUI should be loaded/shown
            if (!nogui)
            {
                // create the GUI interface object
                gui = new GUIMain();

                // create a GUI (as a separate process)
                // and pass a reference to the experiment for the GUI to pull information from and push commands to the experiment object
                Thread thread = new Thread(() => {
                    // name this thread
                    if (Thread.CurrentThread.Name == null)
                    {
                        Thread.CurrentThread.Name = "GUI Thread";
                    }

                    // setup the GUI
                    Application.EnableVisualStyles();

                    // start and run the GUI
                    //try {
                    Application.Run(gui);
                    //} catch (Exception e) {
                    //logger.Error("Exception in GUI: " + e.Message);
                    //}

                    // message
                    logger.Info("GUI (thread) stopped");
                });
                thread.SetApartmentState(ApartmentState.STA);
                thread.Start();

                // wait for the GUI to start or a maximum amount of 5 seconds (5.000 / 50 = 100)
                int waitCounter = 100;
                while (!gui.isLoaded() && waitCounter > 0)
                {
                    Thread.Sleep(50);
                    waitCounter--;
                }
            }

            // message versions
            logger.Info("MainBoot version " + MainBoot.getClassVersion());
            logger.Info("MainThread version " + MainThread.getClassVersion());

            // message
            if (Environment.Is64BitProcess)
            {
                logger.Debug("Processes are run in a 64 bit environment");
            }
            else
            {
                logger.Debug("Processes are run in a 32 bit environment");
            }

            // setup and initialize the pipeline
            if (mainThread.initPipeline(source, filters, applicationType))
            {
                // check if a parameter file was given to load at startup
                if (!String.IsNullOrEmpty(parameterFile))
                {
                    // load parameter file to the applications parametersets
                    ParameterManager.loadParameterFile(parameterFile, ParameterManager.getParameterSets());
                }

                // continue to run as the main thread
                mainThread.run();
            }
            else
            {
                // on failure

                string errMessage = "Error while initializing modules, inspect the log for more information";
                logger.Error(errMessage);
                if (!nogui)
                {
                    gui.modalMessageDelegate(errMessage, "Initialization error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }


            // check if there is a gui, and close it by delegate
            if (gui != null)
            {
                gui.closeDelegate();
                gui = null;
                Thread.Sleep(100);   // allow GUI threads to terminate, before calling Application.Exit()
            }

            // stop all the winforms (Informs all message pumps that they must terminate, and then closes all application windows after the messages have been processed.)
            Application.Exit();

            // exit the environment
            Environment.Exit(0);
        }