NEWS: prepare for 6.6.1
[xcsoar.git] / src / Startup.cpp
blobdadd2a3e0e1c448846356e2eab838a7171408f85
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "Startup.hpp"
25 #include "Interface.hpp"
26 #include "Components.hpp"
27 #include "Profile/Profile.hpp"
28 #include "Profile/ProfileKeys.hpp"
29 #include "Asset.hpp"
30 #include "Simulator.hpp"
31 #include "InfoBoxes/InfoBoxManager.hpp"
32 #include "Terrain/RasterTerrain.hpp"
33 #include "Terrain/RasterWeather.hpp"
34 #include "Input/InputEvents.hpp"
35 #include "Input/InputQueue.hpp"
36 #include "Geo/Geoid.hpp"
37 #include "Dialogs/XML.hpp"
38 #include "Dialogs/Dialogs.h"
39 #include "Dialogs/dlgSimulatorPrompt.hpp"
40 #include "Language/LanguageGlue.hpp"
41 #include "Language/Language.hpp"
42 #include "Protection.hpp"
43 #include "LogFile.hpp"
44 #include "Math/FastMath.h"
45 #include "UtilsSystem.hpp"
46 #include "FLARM/Glue.hpp"
47 #include "MapSettings.hpp"
48 #include "Logger/Logger.hpp"
49 #include "Logger/NMEALogger.hpp"
50 #include "Logger/GlueFlightLogger.hpp"
51 #include "Waypoint/WaypointDetailsReader.hpp"
52 #include "Blackboard/DeviceBlackboard.hpp"
53 #include "MapWindow/GlueMapWindow.hpp"
54 #include "Markers/Markers.hpp"
55 #include "Markers/ProtectedMarkers.hpp"
56 #include "Device/device.hpp"
57 #include "Topography/TopographyStore.hpp"
58 #include "Topography/TopographyGlue.hpp"
59 #include "Audio/VarioGlue.hpp"
60 #include "Screen/Busy.hpp"
61 #include "Polar/PolarGlue.hpp"
62 #include "Polar/Polar.hpp"
63 #include "CommandLine.hpp"
64 #include "MainWindow.hpp"
65 #include "Look/Look.hpp"
66 #include "Look/Fonts.hpp"
67 #include "resource.h"
68 #include "Computer/GlideComputer.hpp"
69 #include "Computer/GlideComputerInterface.hpp"
70 #include "Computer/Events.hpp"
71 #include "StatusMessage.hpp"
72 #include "MergeThread.hpp"
73 #include "CalculationThread.hpp"
74 #include "Replay/Replay.hpp"
75 #include "LocalPath.hpp"
76 #include "IO/FileCache.hpp"
77 #include "Net/DownloadManager.hpp"
78 #include "Hardware/AltairControl.hpp"
79 #include "Hardware/Display.hpp"
80 #include "Hardware/DisplayGlue.hpp"
81 #include "Compiler.h"
82 #include "NMEA/Aircraft.hpp"
83 #include "Waypoint/Waypoints.hpp"
84 #include "Waypoint/WaypointGlue.hpp"
86 #include "Airspace/AirspaceWarningManager.hpp"
87 #include "Airspace/Airspaces.hpp"
88 #include "Airspace/AirspaceGlue.hpp"
89 #include "Airspace/ProtectedAirspaceWarningManager.hpp"
91 #include "Task/TaskManager.hpp"
92 #include "Task/ProtectedTaskManager.hpp"
93 #include "Engine/Task/Ordered/OrderedTask.hpp"
94 #include "GlideSolvers/GlidePolar.hpp"
95 #include "Operation/VerboseOperationEnvironment.hpp"
96 #include "PageActions.hpp"
97 #include "Weather/Features.hpp"
98 #include "Weather/NOAAGlue.hpp"
99 #include "Weather/NOAAStore.hpp"
100 #include "Plane/PlaneGlue.hpp"
101 #include "UIState.hpp"
102 #include "Tracking/TrackingGlue.hpp"
103 #include "Units/Units.hpp"
104 #include "Formatter/UserGeoPointFormatter.hpp"
105 #include "Thread/Debug.hpp"
107 #ifdef ENABLE_OPENGL
108 #include "Screen/OpenGL/Globals.hpp"
109 #else
110 #include "DrawThread.hpp"
111 #endif
113 static Markers *marks;
114 static TaskManager *task_manager;
115 static GlideComputerEvents *glide_computer_events;
116 static GlideComputerTaskEvents *task_events;
118 static bool
119 LoadProfile()
121 if (StringIsEmpty(Profile::GetPath()) &&
122 !dlgStartupShowModal())
123 return false;
125 Profile::Load();
126 Profile::Use();
128 Units::SetConfig(CommonInterface::GetUISettings().units);
129 SetUserCoordinateFormat(CommonInterface::GetUISettings().coordinate_format);
131 #ifdef HAVE_MODEL_TYPE
132 global_model_type = CommonInterface::GetSystemSettings().model_type;
133 #endif
135 return true;
138 static void
139 AfterStartup()
141 StartupLogFreeRamAndStorage();
143 CommonInterface::status_messages.Startup(true);
145 if (is_simulator()) {
146 InputEvents::processGlideComputer(GCE_STARTUP_SIMULATOR);
147 } else {
148 InputEvents::processGlideComputer(GCE_STARTUP_REAL);
151 const TaskFactoryType task_type_default =
152 CommonInterface::GetComputerSettings().task.task_type_default;
153 OrderedTask *defaultTask =
154 protected_task_manager->TaskCreateDefault(&way_points, task_type_default);
155 if (defaultTask) {
157 ScopeSuspendAllThreads suspend;
158 defaultTask->CheckDuplicateWaypoints(way_points);
159 way_points.Optimise();
162 defaultTask->FillMatPoints(way_points);
163 protected_task_manager->TaskCommit(*defaultTask);
164 delete defaultTask;
167 task_manager->Resume();
169 CommonInterface::main_window->Fullscreen();
170 InfoBoxManager::SetDirty();
172 ForceCalculation();
174 CommonInterface::status_messages.Startup(false);
178 * "Boots" up XCSoar
179 * @param hInstance Instance handle
180 * @param lpCmdLine Command line string
181 * @return True if bootup successful, False otherwise
183 bool
184 Startup()
186 VerboseOperationEnvironment operation;
188 #ifdef USE_GDI
189 //If "XCSoar" is already running, stop this instance
190 if (MainWindow::Find())
191 return false;
192 #endif
194 #ifdef HAVE_DOWNLOAD_MANAGER
195 Net::DownloadManager::Initialise();
196 #endif
198 LogFormat("Display dpi=%u,%u", Display::GetXDPI(), Display::GetYDPI());
200 // Creates the main window
202 TopWindowStyle style;
203 if (CommandLine::full_screen)
204 style.FullScreen();
205 if (CommandLine::resizable)
206 style.Resizable();
208 MainWindow *const main_window = CommonInterface::main_window =
209 new MainWindow(CommonInterface::status_messages);
210 main_window->Create(SystemWindowSize(), style);
211 if (!main_window->IsDefined())
212 return false;
214 #ifdef ENABLE_OPENGL
215 LogFormat("OpenGL: "
216 #ifdef HAVE_EGL
217 "egl=%d "
218 #endif
219 "npot=%d vbo=%d fbo=%d stencil=%#x",
220 #ifdef HAVE_EGL
221 OpenGL::egl,
222 #endif
223 OpenGL::texture_non_power_of_two,
224 OpenGL::vertex_buffer_object,
225 OpenGL::frame_buffer_object,
226 OpenGL::render_buffer_stencil);
227 #endif
229 main_window->Initialise();
231 #ifdef SIMULATOR_AVAILABLE
232 // prompt for simulator if not set by command line argument "-simulator" or "-fly"
233 if (!sim_set_in_cmd_line_flag) {
234 DialogLook white_look;
235 white_look.Initialise(Fonts::map_bold, Fonts::map, Fonts::map_label,
236 Fonts::map_bold, Fonts::map_bold, Fonts::map_bold);
237 white_look.SetBackgroundColor(COLOR_WHITE);
238 SetXMLDialogLook(white_look);
240 SimulatorPromptResult result = dlgSimulatorPromptShowModal();
241 switch (result) {
242 case SPR_QUIT:
243 return false;
245 case SPR_FLY:
246 global_simulator_flag = false;
247 break;
249 case SPR_SIMULATOR:
250 global_simulator_flag = true;
251 break;
254 #endif
256 SetXMLDialogLook(main_window->GetLook().dialog);
258 CommonInterface::SetSystemSettings().SetDefaults();
259 CommonInterface::SetComputerSettings().SetDefaults();
260 CommonInterface::SetUISettings().SetDefaults();
261 CommonInterface::SetUIState().Clear();
263 const auto &computer_settings = CommonInterface::GetComputerSettings();
264 const auto &ui_settings = CommonInterface::GetUISettings();
265 auto &live_blackboard = CommonInterface::GetLiveBlackboard();
267 if (!LoadProfile())
268 return false;
270 operation.SetText(_("Initialising"));
272 /* create XCSoarData on the first start */
273 CreateDataPath();
275 Display::LoadOrientation(operation);
277 main_window->InitialiseConfigured();
279 TCHAR path[MAX_PATH];
280 LocalPath(path, _T("cache"));
281 file_cache = new FileCache(path);
283 ReadLanguageFile();
285 CommonInterface::status_messages.LoadFile();
286 InputEvents::readFile();
288 // Initialize DeviceBlackboard
289 device_blackboard = new DeviceBlackboard();
291 DeviceListInitialise();
293 // Initialize Markers
294 marks = new Markers();
295 protected_marks = new ProtectedMarkers(*marks);
297 #ifdef HAVE_AYGSHELL_DLL
298 const AYGShellDLL &ayg = main_window->ayg_shell_dll;
299 ayg.SHSetAppKeyWndAssoc(VK_APP1, *main_window);
300 ayg.SHSetAppKeyWndAssoc(VK_APP2, *main_window);
301 ayg.SHSetAppKeyWndAssoc(VK_APP3, *main_window);
302 ayg.SHSetAppKeyWndAssoc(VK_APP4, *main_window);
303 // Typical Record Button
304 // Why you can't always get this to work
305 // http://forums.devbuzz.com/m_1185/mpage_1/key_/tm.htm
306 // To do with the fact it is a global hotkey, but you can with code above
307 // Also APPA is record key on some systems
308 ayg.SHSetAppKeyWndAssoc(VK_APP5, *main_window);
309 ayg.SHSetAppKeyWndAssoc(VK_APP6, *main_window);
310 #endif
312 // Initialize main blackboard data
313 task_events = new GlideComputerTaskEvents();
314 task_manager = new TaskManager(computer_settings.task, way_points);
315 task_manager->SetTaskEvents(*task_events);
316 task_manager->Reset();
318 protected_task_manager =
319 new ProtectedTaskManager(*task_manager, computer_settings.task);
321 // Read the terrain file
322 operation.SetText(_("Loading Terrain File..."));
323 LogFormat("OpenTerrain");
324 terrain = RasterTerrain::OpenTerrain(file_cache, operation);
326 logger = new Logger();
328 glide_computer = new GlideComputer(way_points, airspace_database,
329 *protected_task_manager,
330 *task_events);
331 glide_computer->ReadComputerSettings(computer_settings);
332 glide_computer->SetTerrain(terrain);
333 glide_computer->SetLogger(logger);
334 glide_computer->Initialise();
336 replay = new Replay(logger, *protected_task_manager);
338 // Load the EGM96 geoid data
339 EGM96::Load();
341 GlidePolar &gp = CommonInterface::SetComputerSettings().polar.glide_polar_task;
342 gp = GlidePolar(fixed(0));
343 gp.SetMC(computer_settings.task.safety_mc);
344 gp.SetBugs(computer_settings.polar.degradation_factor);
345 PlaneGlue::FromProfile(CommonInterface::SetComputerSettings().plane);
346 PlaneGlue::Synchronize(computer_settings.plane,
347 CommonInterface::SetComputerSettings(), gp);
348 task_manager->SetGlidePolar(gp);
350 // Read the topography file(s)
351 topography = new TopographyStore();
352 LoadConfiguredTopography(*topography, operation);
354 // Read the waypoint files
355 WaypointGlue::LoadWaypoints(way_points, terrain, operation);
357 // Read and parse the airfield info file
358 WaypointDetails::ReadFileFromProfile(way_points, operation);
360 // Set the home waypoint
361 WaypointGlue::SetHome(way_points, terrain,
362 CommonInterface::SetComputerSettings().poi,
363 CommonInterface::SetComputerSettings().team_code,
364 device_blackboard, false);
366 // ReSynchronise the blackboards here since SetHome touches them
367 device_blackboard->Merge();
368 CommonInterface::ReadBlackboardBasic(device_blackboard->Basic());
370 // Scan for weather forecast
371 LogFormat("RASP load");
372 RASP.ScanAll(CommonInterface::Basic().location, operation);
374 // Reads the airspace files
375 ReadAirspace(airspace_database, terrain, computer_settings.pressure,
376 operation);
379 const AircraftState aircraft_state =
380 ToAircraftState(device_blackboard->Basic(),
381 device_blackboard->Calculated());
382 ProtectedAirspaceWarningManager::ExclusiveLease lease(glide_computer->GetAirspaceWarnings());
383 lease->Reset(aircraft_state);
386 #ifdef HAVE_NOAA
387 noaa_store = new NOAAStore();
388 noaa_store->LoadFromProfile();
389 #endif
391 AudioVarioGlue::Initialise();
392 AudioVarioGlue::Configure(ui_settings.sound.vario);
394 // Start the device thread(s)
395 operation.SetText(_("Starting devices"));
396 devStartup();
399 -- Reset polar in case devices need the data
400 GlidePolar::UpdatePolar(true, computer_settings);
402 This should be done inside devStartup if it is really required
405 operation.SetText(_("Initialising display"));
407 GlueMapWindow *map_window = main_window->GetMap();
408 if (map_window != NULL) {
409 map_window->SetWaypoints(&way_points);
410 map_window->SetTask(protected_task_manager);
411 map_window->SetRoutePlanner(&glide_computer->GetProtectedRoutePlanner());
412 map_window->SetGlideComputer(glide_computer);
413 map_window->SetAirspaces(&airspace_database);
415 map_window->SetTopography(topography);
416 map_window->SetTerrain(terrain);
417 map_window->SetWeather(&RASP);
418 map_window->SetMarks(protected_marks);
419 map_window->SetLogger(logger);
421 #ifdef HAVE_NOAA
422 map_window->SetNOAAStore(noaa_store);
423 #endif
425 /* show map at home waypoint until GPS fix becomes available */
426 if (computer_settings.poi.home_location_available)
427 map_window->SetLocation(computer_settings.poi.home_location);
430 // Finally ready to go.. all structures must be present before this.
432 // Create the drawing thread
433 #ifndef ENABLE_OPENGL
434 draw_thread = new DrawThread(*map_window);
435 draw_thread->Start(true);
436 #endif
438 // Show the infoboxes
439 InfoBoxManager::Show();
441 // Create the calculation thread
442 CreateCalculationThread();
444 // Find unique ID of this PDA
445 ReadAssetNumber();
447 glide_computer_events = new GlideComputerEvents();
448 glide_computer_events->Reset();
449 live_blackboard.AddListener(*glide_computer_events);
451 if (computer_settings.logger.enable_flight_logger) {
452 flight_logger = new GlueFlightLogger(live_blackboard);
453 LocalPath(path, _T("flights.log"));
454 flight_logger->SetPath(path);
457 if (computer_settings.logger.enable_nmea_logger)
458 NMEALogger::enabled = true;
460 LogFormat("ProgramStarted");
462 // Give focus to the map
463 main_window->SetDefaultFocus();
465 // Start calculation thread
466 merge_thread->Start();
467 calculation_thread->Start();
469 PageActions::Update();
471 #ifdef HAVE_TRACKING
472 tracking = new TrackingGlue();
473 tracking->SetSettings(computer_settings.tracking);
475 #ifdef HAVE_SKYLINES_TRACKING_HANDLER
476 if (map_window != nullptr)
477 map_window->SetSkyLinesData(&tracking->GetSkyLinesData());
478 #endif
479 #endif
481 assert(!global_running);
482 global_running = true;
484 AfterStartup();
486 operation.Hide();
488 main_window->FinishStartup();
490 return true;
493 void
494 Shutdown()
496 VerboseOperationEnvironment operation;
497 gcc_unused ScopeBusyIndicator busy;
499 MainWindow *const main_window = CommonInterface::main_window;
500 auto &live_blackboard = CommonInterface::GetLiveBlackboard();
502 // Show progress dialog
503 operation.SetText(_("Shutdown, please wait..."));
505 // Log shutdown information
506 LogFormat("Entering shutdown...");
508 main_window->BeginShutdown();
510 StartupLogFreeRamAndStorage();
512 // Turn off all displays
513 global_running = false;
515 #ifdef HAVE_TRACKING
516 if (tracking != NULL)
517 tracking->StopAsync();
518 #endif
520 // Stop logger and save igc file
521 operation.SetText(_("Shutdown, saving logs..."));
522 logger->GUIStopLogger(CommonInterface::Basic(), true);
524 delete flight_logger;
525 flight_logger = NULL;
527 live_blackboard.RemoveListener(*glide_computer_events);
528 delete glide_computer_events;
530 SaveFlarmColors();
532 // Save settings to profile
533 operation.SetText(_("Shutdown, saving profile..."));
534 Profile::Save();
536 // Stop sound
538 AudioVarioGlue::Deinitialise();
540 operation.SetText(_("Shutdown, please wait..."));
542 // Stop threads
543 LogFormat("Stop threads");
544 #ifdef HAVE_DOWNLOAD_MANAGER
545 Net::DownloadManager::BeginDeinitialise();
546 #endif
547 #ifndef ENABLE_OPENGL
548 draw_thread->BeginStop();
549 #endif
550 calculation_thread->BeginStop();
551 merge_thread->BeginStop();
553 // Wait for the calculations thread to finish
554 LogFormat("Waiting for calculation thread");
556 merge_thread->Join();
557 delete merge_thread;
558 merge_thread = NULL;
560 calculation_thread->Join();
561 delete calculation_thread;
562 calculation_thread = NULL;
564 // Wait for the drawing thread to finish
565 #ifndef ENABLE_OPENGL
566 LogFormat("Waiting for draw thread");
568 draw_thread->Join();
569 delete draw_thread;
570 #endif
572 LogFormat("delete MapWindow");
573 main_window->Deinitialise();
575 // Save the task for the next time
576 operation.SetText(_("Shutdown, saving task..."));
578 LogFormat("Save default task");
579 protected_task_manager->TaskSaveDefault();
581 // Clear waypoint database
582 way_points.Clear();
584 operation.SetText(_("Shutdown, please wait..."));
586 // Clear weather database
587 RASP.Close();
589 // Clear terrain database
591 delete terrain;
592 delete topography;
594 delete protected_marks;
595 delete marks;
597 // Close any device connections
598 devShutdown();
600 NMEALogger::Shutdown();
602 delete replay;
604 DeviceListDeinitialise();
606 delete device_blackboard;
607 device_blackboard = NULL;
609 protected_task_manager->SetRoutePlanner(NULL);
611 delete protected_task_manager;
612 delete task_manager;
614 #ifdef HAVE_NOAA
615 delete noaa_store;
616 #endif
618 #ifdef HAVE_TRACKING
619 if (tracking != NULL) {
620 tracking->WaitStopped();
621 delete tracking;
623 #endif
625 #ifdef HAVE_DOWNLOAD_MANAGER
626 Net::DownloadManager::Deinitialise();
627 #endif
629 // Close the progress dialog
630 LogFormat("Close Progress Dialog");
631 operation.Hide();
633 // Clear the EGM96 database
634 EGM96::Close();
636 delete glide_computer;
637 delete task_events;
638 delete logger;
640 // Clear airspace database
641 airspace_database.clear();
643 // Destroy FlarmNet records
644 DeinitTrafficGlobals();
646 delete file_cache;
648 LogFormat("Close Windows - main");
649 main_window->Destroy();
651 CloseLanguageFile();
653 Display::RestoreOrientation();
655 StartupLogFreeRamAndStorage();
657 LogFormat("Finished shutdown");