Esempio n. 1
0
void
Shutdown()
{
  VerboseOperationEnvironment operation;
  gcc_unused ScopeBusyIndicator busy;

  MainWindow *const main_window = CommonInterface::main_window;
  auto &live_blackboard = CommonInterface::GetLiveBlackboard();

  // Show progress dialog
  operation.SetText(_("Shutdown, please wait..."));

  // Log shutdown information
  LogFormat("Entering shutdown...");

  main_window->BeginShutdown();

  StartupLogFreeRamAndStorage();

  Lua::StopAllBackground();

  // Turn off all displays
  global_running = false;

#ifdef HAVE_TRACKING
  if (tracking != nullptr)
    tracking->StopAsync();
#endif

  // Stop logger and save igc file
  operation.SetText(_("Shutdown, saving logs..."));
  if (logger != nullptr)
    logger->GUIStopLogger(CommonInterface::Basic(), true);

  delete flight_logger;
  flight_logger = nullptr;

  delete all_monitors;
  all_monitors = nullptr;

  if (glide_computer_events != nullptr) {
    live_blackboard.RemoveListener(*glide_computer_events);
    delete glide_computer_events;
    glide_computer_events = nullptr;
  }

  SaveFlarmColors();

  // Save settings to profile
  operation.SetText(_("Shutdown, saving profile..."));
  Profile::Save();

  operation.SetText(_("Shutdown, please wait..."));

  // Stop threads
  LogFormat("Stop threads");
#ifdef HAVE_DOWNLOAD_MANAGER
  Net::DownloadManager::BeginDeinitialise();
#endif
#ifndef ENABLE_OPENGL
  if (draw_thread != nullptr)
    draw_thread->BeginStop();
#endif

  if (calculation_thread != nullptr)
    calculation_thread->BeginStop();

  if (merge_thread != nullptr)
    merge_thread->BeginStop();

  // Wait for the calculations thread to finish
  LogFormat("Waiting for calculation thread");

  if (merge_thread != nullptr) {
    merge_thread->Join();
    delete merge_thread;
    merge_thread = nullptr;
  }

  if (calculation_thread != nullptr) {
    calculation_thread->Join();
    delete calculation_thread;
    calculation_thread = nullptr;
  }

  //  Wait for the drawing thread to finish
#ifndef ENABLE_OPENGL
  LogFormat("Waiting for draw thread");

  if (draw_thread != nullptr) {
    draw_thread->Join();
    delete draw_thread;
    draw_thread = nullptr;
  }
#endif

  LogFormat("delete MapWindow");
  main_window->Deinitialise();

  // Stop sound
  AudioVarioGlue::Deinitialise();

  // Save the task for the next time
  operation.SetText(_("Shutdown, saving task..."));

  LogFormat("Save default task");
  if (protected_task_manager != nullptr) {
    try {
      protected_task_manager->TaskSaveDefault();
    } catch (const std::runtime_error &e) {
      LogError(e);
    }
  }

  // Clear waypoint database
  way_points.Clear();

  operation.SetText(_("Shutdown, please wait..."));

  // Clear terrain database

  delete terrain;
  terrain = nullptr;
  delete topography;
  topography = nullptr;

  // Close any device connections
  devShutdown();

  NMEALogger::Shutdown();

  delete replay;
  replay = nullptr;

  delete devices;
  devices = nullptr;
  delete device_blackboard;
  device_blackboard = nullptr;

  if (protected_task_manager != nullptr) {
    protected_task_manager->SetRoutePlanner(nullptr);
    delete protected_task_manager;
    protected_task_manager = nullptr;
  }

  delete task_manager;
  task_manager = nullptr;

#ifdef HAVE_NOAA
  delete noaa_store;
  noaa_store = nullptr;
#endif

#ifdef HAVE_TRACKING
  if (tracking != nullptr) {
    tracking->WaitStopped();
    delete tracking;
    tracking = nullptr;
  }
#endif

#ifdef HAVE_DOWNLOAD_MANAGER
  Net::DownloadManager::Deinitialise();
#endif

  // Close the progress dialog
  LogFormat("Close Progress Dialog");
  operation.Hide();

  delete glide_computer;
  glide_computer = nullptr;
  delete task_events;
  task_events = nullptr;
  delete logger;
  logger = nullptr;

  // Clear airspace database
  airspace_database.Clear();

  // Destroy FlarmNet records
  DeinitTrafficGlobals();

  delete file_cache;
  file_cache = nullptr;

  LogFormat("Close Windows - main");
  main_window->Destroy();

  CloseLanguageFile();

  Display::RestoreOrientation();

  StartupLogFreeRamAndStorage();

  LogFormat("Finished shutdown");
}
Esempio n. 2
0
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
#ifdef _WIN32_WCE
        gcc_unused LPWSTR lpCmdLine,
#else
        gcc_unused LPSTR lpCmdLine2,
#endif
        int nCmdShow)
#endif
{
#ifdef WIN32
  ResourceLoader::Init(hInstance);
#endif

  Net::Initialise();

  InitialiseDataPath();
  StartupLogFreeRamAndStorage();

  // Write startup note + version to logfile
  LogFormat(_T("Starting XCSoar %s"), XCSoar_ProductToken);

  // Read options from the command line
  {
#ifdef WIN32
    Args args(GetCommandLine(), Usage);
#else
    Args args(argc, argv, Usage);
#endif
    CommandLine::Parse(args);
  }

  ScreenGlobalInit screen_init;

#ifdef WIN32
  /* try to make the UI most responsive */
  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
#endif

  AllowLanguage();
  InitLanguage();

  InitialiseIOThread();

  // Perform application initialization and run loop
  int ret = EXIT_FAILURE;
  if (Startup())
    ret = CommonInterface::main_window->RunEventLoop();

  if (CommonInterface::main_window != nullptr) {
    CommonInterface::main_window->Destroy();
    delete CommonInterface::main_window;
  }

  DeinitialiseIOThread();

  DisallowLanguage();

  Fonts::Deinitialize();

  DeinitialiseDataPath();
  Net::Deinitialise();

  assert(!ExistsAnyThread());

  return ret;
}
Esempio n. 3
0
void
Shutdown()
{
  VerboseOperationEnvironment operation;
  gcc_unused ScopeBusyIndicator busy;

  MainWindow *const main_window = CommonInterface::main_window;
  auto &live_blackboard = CommonInterface::GetLiveBlackboard();

  // Show progress dialog
  operation.SetText(_("Shutdown, please wait..."));

  // Log shutdown information
  LogFormat("Entering shutdown...");

  main_window->BeginShutdown();

  StartupLogFreeRamAndStorage();

  // Turn off all displays
  global_running = false;

#ifdef HAVE_TRACKING
  if (tracking != NULL)
    tracking->StopAsync();
#endif

  // Stop logger and save igc file
  operation.SetText(_("Shutdown, saving logs..."));
  logger->GUIStopLogger(CommonInterface::Basic(), true);

  delete flight_logger;
  flight_logger = NULL;

  live_blackboard.RemoveListener(*glide_computer_events);
  delete glide_computer_events;

  FlarmFriends::Save();

  // Save settings to profile
  operation.SetText(_("Shutdown, saving profile..."));
  Profile::Save();

  // Stop sound

  AudioVarioGlue::Deinitialise();

  operation.SetText(_("Shutdown, please wait..."));

  // Stop threads
  LogFormat("Stop threads");
#ifdef HAVE_DOWNLOAD_MANAGER
  Net::DownloadManager::BeginDeinitialise();
#endif
#ifndef ENABLE_OPENGL
  draw_thread->BeginStop();
#endif
  calculation_thread->BeginStop();
  merge_thread->BeginStop();

  // Wait for the calculations thread to finish
  LogFormat("Waiting for calculation thread");

  merge_thread->Join();
  delete merge_thread;
  merge_thread = NULL;

  calculation_thread->Join();
  delete calculation_thread;
  calculation_thread = NULL;

  //  Wait for the drawing thread to finish
#ifndef ENABLE_OPENGL
  LogFormat("Waiting for draw thread");

  draw_thread->Join();
  delete draw_thread;
#endif

  LogFormat("delete MapWindow");
  main_window->Deinitialise();

  // Save the task for the next time
  operation.SetText(_("Shutdown, saving task..."));

  LogFormat("Save default task");
  protected_task_manager->TaskSaveDefault();

  // Clear waypoint database
  way_points.Clear();

  operation.SetText(_("Shutdown, please wait..."));

  // Clear weather database
  RASP.Close();

  // Clear terrain database

  delete terrain;
  delete topography;

  delete protected_marks;
  delete marks;

  // Close any device connections
  devShutdown();

  NMEALogger::Shutdown();

  delete replay;

  DeviceListDeinitialise();

  delete device_blackboard;
  device_blackboard = NULL;

  protected_task_manager->SetRoutePlanner(NULL);

  delete protected_task_manager;
  delete task_manager;

#ifdef HAVE_NOAA
  delete noaa_store;
#endif

#ifdef HAVE_TRACKING
  if (tracking != NULL) {
    tracking->WaitStopped();
    delete tracking;
  }
#endif

#ifdef HAVE_DOWNLOAD_MANAGER
  Net::DownloadManager::Deinitialise();
#endif

  // Close the progress dialog
  LogFormat("Close Progress Dialog");
  operation.Hide();

  // Clear the EGM96 database
  EGM96::Close();

  delete glide_computer;
  delete task_events;
  delete logger;

  // Clear airspace database
  airspace_database.clear();

  // Destroy FlarmNet records
  FlarmNet::Destroy();

  delete file_cache;

  LogFormat("Close Windows - main");
  main_window->Destroy();

  CloseLanguageFile();

  Display::RestoreOrientation();

  StartupLogFreeRamAndStorage();

  LogFormat("Finished shutdown");
}
Esempio n. 4
0
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  long wdata;

  switch (message)
    {

    case WM_ERASEBKGND:
      return TRUE; // JMW trying to reduce screen flicker
      break;
    case WM_COMMAND:
      return MainMenu(hWnd, message, wParam, lParam);
      break;
    case WM_CTLCOLORSTATIC:
      wdata = GetWindowLong((HWND)lParam, GWL_USERDATA);
      switch(wdata) {
      case 0:
        SetBkColor((HDC)wParam, ColorUnselected);
        SetTextColor((HDC)wParam, RGB(0x00,0x00,0x00));
        return (LRESULT)hBrushUnselected;
      case 1:
        SetBkColor((HDC)wParam, ColorSelected);
        SetTextColor((HDC)wParam, RGB(0x00,0x00,0x00));
        return (LRESULT)hBrushSelected;
      case 2:
	SetBkColor((HDC)wParam, ColorUnselected);
        SetTextColor((HDC)wParam, ColorWarning);
	return (LRESULT)hBrushUnselected;
      case 3:
	SetBkColor((HDC)wParam, ColorUnselected);
        SetTextColor((HDC)wParam, ColorOK);
	return (LRESULT)hBrushUnselected;
      case 4:
	// black on light green
        SetTextColor((HDC)wParam, RGB_BLACK); 
	SetBkColor((HDC)wParam, ColorButton);
	return (LRESULT)hBrushButton;
      case 5:
	// grey on light green
	SetBkColor((HDC)wParam, ColorButton);
        SetTextColor((HDC)wParam, RGB(0x80,0x80,0x80));
	return (LRESULT)hBrushButton;
#ifdef LXMINIMAP
      case 6:
        // black on dark yellow
        SetTextColor((HDC)wParam, RGB_BLACK);
        SetBkColor((HDC)wParam, ColorButtonHasFocus);
        return (LRESULT)hBrushButtonHasFocus;
      case 7:
        // grey on dark yellow
        SetTextColor((HDC)wParam, RGB(0x80,0x80,0x80));
        SetBkColor((HDC)wParam, ColorButtonHasFocus);
        return (LRESULT)hBrushButtonHasFocus;
#endif

      }
      break;
    case WM_CREATE:
#ifdef HAVE_ACTIVATE_INFO
      memset (&s_sai, 0, sizeof (s_sai));
      s_sai.cbSize = sizeof (s_sai);
#endif
      if (iTimerID == 0) {
        iTimerID = SetTimer(hWnd,1000,500,NULL); // 500ms  2 times per second
      }

      break;

    case WM_ACTIVATE:

      if(LOWORD(wParam) != WA_INACTIVE)
        {
          SetWindowPos(hWndMainWindow,HWND_TOP,
                 0, 0, 0, 0,
                 SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE);

#ifdef HAVE_ACTIVATE_INFO
         SHFullScreen(hWndMainWindow,SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON|SHFS_HIDESTARTICON);
#endif

        }
#ifdef HAVE_ACTIVATE_INFO
      if (api_has_SHHandleWMActivate) {
        SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE);
      } else {
        #ifdef TESTBENCH
        StartupStore(TEXT("... SHHandleWMActivate not available%s"),NEWLINE);
        #endif
        return DefWindowProc(hWnd, message, wParam, lParam);
      }
#endif
      break;

    case WM_SETTINGCHANGE:
#ifdef HAVE_ACTIVATE_INFO
      if (api_has_SHHandleWMSettingChange) {
        SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
      } else {
        #ifdef TESTBENCH
        StartupStore(TEXT("... SHHandleWMSettingChange not available%s"),NEWLINE);
        #endif
        return DefWindowProc(hWnd, message, wParam, lParam);
      }
#endif
      break;

	#if DEBUG_FOCUS
    case WM_KILLFOCUS:
	// This is happening when focus is given to another window, either internally inside LK
	// or externally, for example to explorer..
	// SO: if we select MapWindow, we get here a KILLFOCUS from it.
	// When we select another process/program, or click on the desktop, the old window having focus is
	// receiving KILLFOCUS. So in case MapWindow was working, the signal will be sent over there, not here.
	// 
	StartupStore(_T("............ WNDPROC LOST FOCUS (KILLFOCUS)\n"));
	break;
	#endif

    case WM_SETFOCUS:
	// When explorer/desktop is giving focus to LK, this is where we get the signal.
	// But we must return focus to previous windows otherwise keys will not be working.
	// Mouse is another story, because mouse click is pertinent to a screen area which is mapped.
	// A mouse click will be sent to the window in the background, whose handler will receive the event.
	//
	// Each event handler receiving focus has to save it in hWndWithFocus, in LK.
	// Each event handler must thus handle SETFOCUS!
	//
	#if DEBUG_FOCUS
	StartupStore(_T("............ WNDPROC HAS FOCUS  (SETFOCUS)\n"));
	if (hWndWithFocus==NULL)
		StartupStore(_T(".....(no Wnd to give focus to)\n"));
	else
		StartupStore(_T(".....(passing focus to other window)\n"));
	#endif
	if (hWndWithFocus!=NULL) SetFocus(hWndWithFocus);
      break;

    case WM_KEYUP:
      break;

    case WM_TIMER:
	// WM_TIMER is run at about 2hz.
	LKHearthBeats++; // 100213
      //      ASSERT(hWnd==hWndMainWindow);
      if (ProgramStarted > psInitInProgress) {
	if (SIMMODE)
		SIMProcessTimer();
	else
		ProcessTimer();
	if (ProgramStarted==psFirstDrawDone) {
	  AfterStartup();
	  ProgramStarted = psNormalOp;
          StartupStore(_T(". ProgramStarted=NormalOp %s%s"), WhatTimeIsIt(),NEWLINE);
          StartupLogFreeRamAndStorage();

	}
      }
      break;

    case WM_INITMENUPOPUP:
      if (ProgramStarted > psInitInProgress) {
	  CheckMenuItem((HMENU) wParam,IDM_FILE_LOCK,MF_CHECKED|MF_BYCOMMAND);
	
	if(LoggerActive)
	  CheckMenuItem((HMENU) wParam,IDM_FILE_LOGGER,MF_CHECKED|MF_BYCOMMAND);
	else
	  CheckMenuItem((HMENU) wParam,IDM_FILE_LOGGER,MF_UNCHECKED|MF_BYCOMMAND);
      }
      break;

    case WM_CLOSE:

      LKASSERT(hWnd==hWndMainWindow);
      if((hWnd==hWndMainWindow) && 
         (MessageBoxX(hWndMainWindow,
		// LKTOKEN  _@M198_ = "Confirm Exit?"
               	gettext(TEXT("_@M198_")),
                      TEXT("LK8000"),
                      MB_YESNO|MB_ICONQUESTION) == IDYES)) 
        {
          if(iTimerID) {
            KillTimer(hWnd,iTimerID);
            iTimerID = 0;
          }

          Shutdown();
        }
      break;

    case WM_DESTROY:
      if (hWnd==hWndMainWindow) {
        PostQuitMessage(0);
      }
      break;

    default:
      return DefWindowProc(hWnd, message, wParam, lParam);
    }
  return 0;
}
Esempio n. 5
0
void Shutdown(void) {
  int i;

  LKSound(_T("LK_DISCONNECT.WAV")); Sleep(500); // real WAV length is 410+ms
  if (!GlobalRunning) { // shutdown on startup (before sim/fly or clicking on the window X)
	#if TESTBENCH
	StartupStore(_T(". Quick shutdown requested before terminating startup%s"),NEWLINE);
	#endif
	// force exit mode for the case of being in welcome screen: OnTimerNotify will catch it
	RUN_MODE=RUN_SHUTDOWN;
	CloseCalculations();
	CloseGeoid();
	DeInitCustomHardware();
	LKRunStartEnd(false);
	return;
  }
  // LKTOKEN _@M1219_ "Shutdown, please wait..."
  CreateProgressDialog(gettext(TEXT("_@M1219_")));

  StartupStore(_T(". Entering shutdown %s%s"), WhatTimeIsIt(),NEWLINE);
  #if TESTBENCH
  StartupLogFreeRamAndStorage();
  #endif

  // turn off all displays
  GlobalRunning = false;

  // LKTOKEN _@M1220_ "Shutdown, saving logs..."
  CreateProgressDialog(gettext(TEXT("_@M1220_")));

  // In case we quit while are still flying
  UpdateLogBook(false); // false=only log if still flying
  // stop logger
  guiStopLogger(true);

  // LKTOKEN _@M1221_ "Shutdown, saving profile..."
  CreateProgressDialog(gettext(TEXT("_@M1221_")));
  extern void LKAircraftSave(const TCHAR *szFile);
  extern void LKPilotSave(const TCHAR *szFile);
  extern void LKDeviceSave(const TCHAR *szFile);
  LKPilotSave(defaultPilotFile);
  LKAircraftSave(defaultAircraftFile);
  LKProfileSave(defaultProfileFile);
  LKDeviceSave(defaultDeviceFile);

  #if TESTBENCH
  StartupStore(TEXT(". Save_Recent_WP_history%s"),NEWLINE);
  #endif
  SaveRecentList();
  // Stop sound

  // Stop drawing
  // LKTOKEN _@M1219_ "Shutdown, please wait..."
  CreateProgressDialog(gettext(TEXT("_@M1219_")));
 
  StartupStore(TEXT(". CloseDrawingThread%s"),NEWLINE);
  // 100526 this is creating problem in SIM mode when quit is called from X button, and we are in waypoint details
  // or probably in other menu related screens. However it cannot happen from real PNA or PDA because we don't have
  // that X button.
  MapWindow::CloseDrawingThread();

  // Stop calculating too (wake up)
  SetEvent(dataTriggerEvent);
  SetEvent(drawTriggerEvent);

  // Clear data
  // LKTOKEN _@M1222_ "Shutdown, saving task..."
  CreateProgressDialog(gettext(TEXT("_@M1222_")));

  #if TESTBENCH
  StartupStore(TEXT(".... Save default task%s"),NEWLINE);
  #endif

  SaveDefaultTask();

  #if TESTBENCH
  StartupStore(TEXT(".... Clear task data%s"),NEWLINE);
  #endif

  LockTaskData();
  Task[0].Index = -1;  ActiveWayPoint = -1; 
  AATEnabled = FALSE;
  CloseWayPoints();
  UnlockTaskData();

  // LKTOKEN _@M1219_ "Shutdown, please wait..."
  CreateProgressDialog(gettext(TEXT("_@M1219_")));
  #if TESTBENCH
  StartupStore(TEXT(".... CloseTerrainTopology%s"),NEWLINE);
  #endif

  RasterTerrain::CloseTerrain();

  CloseTopology();
  #if USETOPOMARKS
  TopologyCloseMarks();
  #endif
  CloseTerrainRenderer();

  LiveTrackerShutdown();

  extern void CloseFlightDataRecorder(void);
  CloseFlightDataRecorder();
  
  // Stop COM devices
  StartupStore(TEXT(". Stop COM devices%s"),NEWLINE);
  devCloseAll();

  CloseFLARMDetails();

  ProgramStarted = psInitInProgress;

  // Kill windows
  #if TESTBENCH
  StartupStore(TEXT(".... Close Messages%s"),NEWLINE);
  #endif
  Message::Destroy();
  #if TESTBENCH 
  StartupStore(TEXT(".... Destroy Button Labels%s"),NEWLINE);
  #endif
  ButtonLabel::Destroy();

  #if TESTBENCH
  StartupStore(TEXT(".... Delete Objects%s"),NEWLINE);
  #endif
  
  // Kill graphics objects

  DeleteObject(hBrushSelected);
  DeleteObject(hBrushUnselected);
  DeleteObject(hBrushButton);
  #ifdef LXMINIMAP
  DeleteObject(hBrushButtonHasFocus);
  #endif

  extern void DeInitialiseFonts(void);
  DeInitialiseFonts();  
  CAirspaceManager::Instance().CloseAirspaces();
  #if TESTBENCH
  StartupStore(TEXT(".... Delete Critical Sections%s"),NEWLINE);
  #endif

  // Wait end of Calculation thread before deinit critical section.
  WaitForSingleObject(hCalculationThread, INFINITE);
  CloseHandle(hCalculationThread);

  #if TESTBENCH
  StartupStore(TEXT(".... Close Progress Dialog%s"),NEWLINE);
  #endif
  CloseProgressDialog();
  #if TESTBENCH
  StartupStore(TEXT(".... Close Calculations%s"),NEWLINE);
  #endif
  CloseCalculations();

  CloseGeoid();
  DeInitCustomHardware();

  #if TESTBENCH
  StartupStore(TEXT(".... Close Windows%s"),NEWLINE);
  #endif
  DestroyWindow(hWndMapWindow);
  DestroyWindow(hWndMainWindow);
  #if TESTBENCH
  StartupStore(TEXT(".... Close Event Handles%s"),NEWLINE);
  #endif
  CloseHandle(drawTriggerEvent);
  CloseHandle(dataTriggerEvent);

  #if TESTBENCH
  StartupLogFreeRamAndStorage();
  #endif
  for (i=0;i<NUMDEV;i++) {
	if (ComPortStatus[i]!=0) {
		StartupStore(_T(". ComPort %d: status=%d Rx=%d Tx=%d ErrRx=%d + ErrTx=%d (==%d)%s"), i,
		ComPortStatus[i], ComPortRx[i],ComPortTx[i], ComPortErrRx[i],ComPortErrTx[i],ComPortErrors[i],NEWLINE);
	}
  }
  StartupStore(_T(". Finished shutdown %s%s"), WhatTimeIsIt(),NEWLINE);
  LKRunStartEnd(false);

#ifdef DEBUG
  TCHAR foop[80];
  TASK_POINT wp;
  TASK_POINT *wpr = &wp;
  _stprintf(foop,TEXT(". Sizes %d %d %d%s"),
	    sizeof(TASK_POINT), 
	    ((long)&wpr->AATTargetLocked)-((long)wpr),
	    ((long)&wpr->Target)-((long)wpr), NEWLINE
	    );
  StartupStore(foop);
#endif
}
Esempio n. 6
0
void
XCSoarInterface::Shutdown()
{
  VerboseOperationEnvironment operation;
  gcc_unused ScopeBusyIndicator busy;

  // Show progress dialog
  operation.SetText(_("Shutdown, please wait..."));

  // Log shutdown information
  LogStartUp(_T("Entering shutdown..."));
  StartupLogFreeRamAndStorage();

  // Turn off all displays
  globalRunningEvent.Reset();

#ifdef HAVE_TRACKING
  if (tracking != NULL)
    tracking->StopAsync();
#endif

  // Stop logger and save igc file
  operation.SetText(_("Shutdown, saving logs..."));
  logger.GUIStopLogger(Basic(), true);

  delete flight_logger;
  flight_logger = NULL;

  GetLiveBlackboard().RemoveListener(glide_computer_events);

  // Save settings to profile
  operation.SetText(_("Shutdown, saving profile..."));
  Profile::Save();

  // Stop sound

#ifndef DISABLEAUDIOVARIO
  //  VarioSound_EnableSound(false);
  //  VarioSound_Close();
#endif

  operation.SetText(_("Shutdown, please wait..."));

  // Stop threads
  LogStartUp(_T("Stop threads"));
#ifndef ENABLE_OPENGL
  draw_thread->BeginStop();
#endif
  calculation_thread->BeginStop();
  merge_thread->BeginStop();

  // Wait for the calculations thread to finish
  LogStartUp(_T("Waiting for calculation thread"));

  merge_thread->Join();
  delete merge_thread;
  merge_thread = NULL;

  calculation_thread->Join();
  delete calculation_thread;
  calculation_thread = NULL;

  //  Wait for the drawing thread to finish
#ifndef ENABLE_OPENGL
  LogStartUp(_T("Waiting for draw thread"));

  draw_thread->Join();
  delete draw_thread;
#endif

  LogStartUp(_T("delete MapWindow"));
  main_window.Deinitialise();

  // Save the task for the next time
  operation.SetText(_("Shutdown, saving task..."));

  LogStartUp(_T("Save default task"));
  protected_task_manager->TaskSaveDefault();

  // Clear waypoint database
  LogStartUp(_T("Close waypoints"));
  way_points.Clear();

  operation.SetText(_("Shutdown, please wait..."));

  // Clear weather database
  LogStartUp(_T("CloseRASP"));
  RASP.Close();

  // Clear terrain database
  LogStartUp(_T("CloseTerrain"));

  delete terrain;

  LogStartUp(_T("CloseTopography"));
  delete topography;

  delete protected_marks;
  delete marks;

  // Close any device connections
  devShutdown();

  NMEALogger::Shutdown();

  delete replay;

  delete device_blackboard;
  device_blackboard = NULL;

  protected_task_manager->SetRoutePlanner(NULL);

  delete protected_task_manager;
  delete task_manager;

#ifdef HAVE_NET
  delete noaa_store;
#endif

#ifdef HAVE_TRACKING
  if (tracking != NULL) {
    tracking->WaitStopped();
    delete tracking;
  }
#endif

  // Close the progress dialog
  LogStartUp(_T("Close Progress Dialog"));
  operation.Hide();

  // Clear the EGM96 database
  EGM96::Close();

  delete glide_computer;

  // Clear airspace database
  LogStartUp(_T("Close airspace"));
  airspace_database.clear();

  // Destroy FlarmNet records
  FlarmNet::Destroy();

  delete file_cache;

  LogStartUp(_T("Close Windows - main "));
  main_window.reset();

  CloseLanguageFile();

  Display::RestoreOrientation();

  StartupLogFreeRamAndStorage();

  LogStartUp(_T("Finished shutdown"));
}