public static void DoWatchStop(CrewChief cc)
 {
     // Thread does not need registration as it is watcher thread.
     new Thread(() =>
     {
         ThreadManager.WaitForRootAndTemporaryThreadsStop(cc);
     }).Start();
 }
 public SpeechRecogniser(CrewChief crewChief)
 {
     this.crewChief = crewChief;
     if (minimum_name_voice_recognition_confidence < 0 || minimum_name_voice_recognition_confidence > 1)
     {
         minimum_name_voice_recognition_confidence = 0.4f;
     }
     if (minimum_voice_recognition_confidence < 0 || minimum_voice_recognition_confidence > 1)
     {
         minimum_voice_recognition_confidence = 0.5f;
     }
 }
        void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            waitingForSpeech = false;
            Console.WriteLine("recognised : " + e.Result.Text + " confidence = " + e.Result.Confidence);
            try
            {
                if (opponentGrammarList.Contains(e.Result.Grammar))
                {
                    if (e.Result.Confidence > minimum_name_voice_recognition_confidence)
                    {
                        CrewChief.getEvent("Opponents").respond(e.Result.Text);
                    }
                    else
                    {
                        crewChief.youWot();
                    }
                }
                else if (e.Result.Confidence > minimum_voice_recognition_confidence)
                {
                    if (ResultContains(e.Result.Text, REPEAT_LAST_MESSAGE))
                    {
                        crewChief.audioPlayer.repeatLastMessage();
                    }
                    else
                    {
                        AbstractEvent abstractEvent = getEventForSpeech(e.Result.Text);
                        if (abstractEvent != null)
                        {
                            abstractEvent.respond(e.Result.Text);
                        }
                    }
                }
                else
                {
                    crewChief.youWot();
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine("Unable to respond - error message: " + exception.Message);
            }

            sre.RecognizeAsyncStop();
            Thread.Sleep(500);
            if (voiceOptionEnum == MainWindow.VoiceOptionEnum.ALWAYS_ON)
            {
                Console.WriteLine("restarting speech recognition");
                recognizeAsync();
            }
        }
 private AbstractEvent getEventForSpeech(String recognisedSpeech)
 {
     if (ResultContains(recognisedSpeech, RADIO_CHECK))
     {
         crewChief.respondToRadioCheck();
     }
     else if (ResultContains(recognisedSpeech, DONT_SPOT))
     {
         crewChief.disableSpotter();
     }
     else if (ResultContains(recognisedSpeech, SPOT))
     {
         crewChief.enableSpotter();
     }
     else if (ResultContains(recognisedSpeech, KEEP_QUIET))
     {
         crewChief.enableKeepQuietMode();
     }
     else if (ResultContains(recognisedSpeech, DONT_TELL_ME_THE_GAPS))
     {
         crewChief.disableDeltasMode();
     }
     else if (ResultContains(recognisedSpeech, TELL_ME_THE_GAPS))
     {
         crewChief.enableDeltasMode();
     }
     else if (ResultContains(recognisedSpeech, WHATS_THE_TIME))
     {
         crewChief.reportCurrentTime();
     }
     else if (ResultContains(recognisedSpeech, HOWS_MY_AERO) ||
              ResultContains(recognisedSpeech, HOWS_MY_TRANSMISSION) ||
              ResultContains(recognisedSpeech, HOWS_MY_ENGINE) ||
              ResultContains(recognisedSpeech, HOWS_MY_SUSPENSION) ||
              ResultContains(recognisedSpeech, HOWS_MY_BRAKES))
     {
         return(CrewChief.getEvent("DamageReporting"));
     }
     else if (ResultContains(recognisedSpeech, KEEP_ME_INFORMED))
     {
         crewChief.disableKeepQuietMode();
     }
     else if (ResultContains(recognisedSpeech, WHATS_MY_FUEL_LEVEL) || ResultContains(recognisedSpeech, HOWS_MY_FUEL))
     {
         return(CrewChief.getEvent("Fuel"));
     }
     else if (ResultContains(recognisedSpeech, WHATS_MY_GAP_IN_FRONT) ||
              ResultContains(recognisedSpeech, WHATS_MY_GAP_BEHIND))
     {
         return(CrewChief.getEvent("Timings"));
     }
     else if (ResultContains(recognisedSpeech, WHATS_MY_POSITION))
     {
         return(CrewChief.getEvent("Position"));
     }
     else if (ResultContains(recognisedSpeech, WHAT_WAS_MY_LAST_LAP_TIME) ||
              ResultContains(recognisedSpeech, WHATS_MY_BEST_LAP_TIME) ||
              ResultContains(recognisedSpeech, WHATS_THE_FASTEST_LAP_TIME) ||
              ResultContains(recognisedSpeech, HOWS_MY_PACE) ||
              ResultContains(recognisedSpeech, WHAT_ARE_MY_SECTOR_TIMES) ||
              ResultContains(recognisedSpeech, WHATS_MY_LAST_SECTOR_TIME))
     {
         return(CrewChief.getEvent("LapTimes"));
     }
     else if (ResultContains(recognisedSpeech, WHAT_ARE_MY_TYRE_TEMPS) ||
              ResultContains(recognisedSpeech, HOW_ARE_MY_TYRE_TEMPS) ||
              ResultContains(recognisedSpeech, HOWS_MY_TYRE_WEAR) ||
              ResultContains(recognisedSpeech, HOW_ARE_MY_BRAKE_TEMPS) ||
              ResultContains(recognisedSpeech, WHAT_ARE_MY_BRAKE_TEMPS))
     {
         return(CrewChief.getEvent("TyreMonitor"));
     }
     else if (ResultContains(recognisedSpeech, HOW_LONGS_LEFT))
     {
         return(CrewChief.getEvent("RaceTime"));
     }
     else if (ResultContains(recognisedSpeech, DO_I_STILL_HAVE_A_PENALTY) ||
              ResultContains(recognisedSpeech, DO_I_HAVE_A_PENALTY) ||
              ResultContains(recognisedSpeech, HAVE_I_SERVED_MY_PENALTY))
     {
         return(CrewChief.getEvent("Penalties"));
     }
     else if (ResultContains(recognisedSpeech, DO_I_HAVE_A_MANDATORY_PIT_STOP))
     {
         return(CrewChief.getEvent("MandatoryPitStops"));
     }
     else if (ResultContains(recognisedSpeech, HOW_ARE_MY_ENGINE_TEMPS))
     {
         return(CrewChief.getEvent("EngineMonitor"));
     }
     else if (ResultContains(recognisedSpeech, WHATS_THE_AIR_TEMP) ||
              ResultContains(recognisedSpeech, WHATS_THE_TRACK_TEMP))
     {
         return(CrewChief.getEvent("ConditionsMonitor"));
     }
     return(null);
 }
        //
        // This method waits for:
        // - Data file dump to complete.
        // - Root threads to stop
        // - Temporary threads to stop
        //
        // Upon exit, enables Start/Stop button and calls MainWindow.uiSyncAppStop to update UI controls.
        //
        private static bool WaitForRootAndTemporaryThreadsStop(CrewChief cc)
        {
            try
            {
                lock (MainWindow.instanceLock)
                {
                    if (MainWindow.instance != null &&
                        !MainWindow.instance.InvokeRequired)
                    {
                        Debug.Assert(false, "This method cannot be invoked from the UI thread.");
                        return(false);
                    }
                }

                var recordSessionChecked = false;
                lock (MainWindow.instanceLock)
                {
                    recordSessionChecked = MainWindow.instance != null && MainWindow.instance.recordSession.Checked;
                }

                if (recordSessionChecked)
                {
                    ThreadManager.Trace("Wating for run thread to dump data file...");
                    while (true)
                    {
                        if (cc.dataFileDumpDone)
                        {
                            ThreadManager.Trace("Run thread data file dump done");
                            break;
                        }

                        Thread.Sleep(ThreadManager.THREAD_ALIVE_CHECK_PERIOD_MILLIS);
                    }
                }

                var rootThreadsStopped = ThreadManager.ThreadWaitHelper(
                    ThreadManager.rootThreads,
                    ThreadManager.rootThreadsLock,
                    "Root",
                    ThreadManager.THREAD_ALIVE_WAIT_ITERATIONS,
                    ThreadManager.THREAD_ALIVE_CHECK_PERIOD_MILLIS,
                    false /*isShutdown*/);

                var tempThreadsStopped = ThreadManager.ThreadWaitHelper(
                    ThreadManager.temporaryThreads,
                    ThreadManager.temporaryThreadsLock,
                    "Temporary",
                    ThreadManager.THREAD_ALIVE_WAIT_ITERATIONS,
                    ThreadManager.THREAD_ALIVE_CHECK_PERIOD_MILLIS,
                    false /*isShutdown*/);

                return(rootThreadsStopped && tempThreadsStopped);
            }
            finally
            {
                lock (MainWindow.instanceLock)
                {
                    if (MainWindow.instance != null)
                    {
                        ThreadManager.UnregisterRootThreads();
                        MainWindow.instance.uiSyncAppStop();
                        MainWindow.instance.startApplicationButton.Enabled = true;
                    }
                }
            }
        }
        //
        // This method is not strictly necessary, because all it really does is makes sure .Start has been called on a thread, which is easy
        // to achieve.  Still, do this for symmetry.
        // For internal trace playback scenario, it waits for file read to complete.
        //
        // Upon exit, enables Start/Stop button.
        //
        private static bool WaitForRootThreadsStart(CrewChief cc)
        {
            try
            {
                lock (MainWindow.instanceLock)
                {
                    if (MainWindow.instance != null &&
                        !MainWindow.instance.InvokeRequired)
                    {
                        Debug.Assert(false, "This method cannot be invoked from the UI thread.");
                        return(false);
                    }
                }

                ThreadManager.Trace("Wating for root threads to start...");
                for (int i = 0; i < ThreadManager.THREAD_ALIVE_WAIT_ITERATIONS; ++i)
                {
                    var allThreadsRunning = true;
                    lock (ThreadManager.rootThreadsLock)
                    {
                        foreach (var t in ThreadManager.rootThreads)
                        {
                            if (!t.IsAlive)
                            {
                                allThreadsRunning = false;
                                break;
                            }
                        }
                    }

                    if (allThreadsRunning)
                    {
                        ThreadManager.Trace("Root threads started");
                        var isTraceFileSet = false;
                        lock (MainWindow.instanceLock)
                        {
                            isTraceFileSet = MainWindow.instance != null && !string.IsNullOrWhiteSpace(MainWindow.instance.filenameTextbox.Text);
                        }

                        if (isTraceFileSet)
                        {
                            ThreadManager.Trace("Wating for run thread to read data file...");
                            while (true)
                            {
                                if (cc.dataFileReadDone)
                                {
                                    ThreadManager.Trace("Run thread data file read done");
                                    break;
                                }

                                Thread.Sleep(ThreadManager.THREAD_ALIVE_CHECK_PERIOD_MILLIS);
                            }
                        }

                        return(true);
                    }

                    Thread.Sleep(ThreadManager.THREAD_ALIVE_CHECK_PERIOD_MILLIS);
                }

                ThreadManager.Trace("Wait for root threads start failed:");
                ThreadManager.TraceThreadSetStats(ThreadManager.rootThreads, ThreadManager.rootThreadsLock, "Root");

                return(false);
            }
            finally
            {
                lock (MainWindow.instanceLock)
                {
                    if (MainWindow.instance != null)
                    {
                        // Not entirely sure if Invoke is necessary here, seems to work well without it.  If we decide
                        // invoke is needed, Post might be best option here.
                        MainWindow.instance.startApplicationButton.Enabled = true;
                    }
                }
            }
        }