Beispiel #1
0
/**
 * Searches the FLARM_Traffic array for the TeamMate and updates TeamMate
 * position and TeamCode if found.
 */
void
GlideComputer::FLARM_ScanTraffic()
{
  // If (not FLARM available) cancel
  if (!Basic().flarm.FLARM_Available || !SettingsComputer().TeamFlarmTracking)
    return;

  if (SettingsComputer().TeamCodeRefWaypoint < 0)
    return;

  // Get bearing and distance to the reference waypoint
  const Waypoint *wp =
      way_points.lookup_id(SettingsComputer().TeamCodeRefWaypoint);

  if (!wp)
    return;

  const FLARM_TRAFFIC *traffic =
      Basic().flarm.FindTraffic(SettingsComputer().TeamFlarmIdTarget);

  if (!traffic)
    return;

  // Set Teammate location to FLARM contact location
  SetCalculated().TeammateLocation = traffic->Location;

  // Calculate distance and bearing from teammate to reference waypoint

  Angle bearing = wp->Location.bearing(traffic->Location);
  fixed distance = wp->Location.distance(traffic->Location);

  // Calculate TeamCode and save it in Calculated
  XCSoarInterface::SetSettingsComputer().TeammateCode.Update(bearing, distance);
  XCSoarInterface::SetSettingsComputer().TeammateCodeValid = true;
}
void
GlueMapWindow::DrawThermalBand(Canvas &canvas, const PixelRect &rc) const
{
  if (Calculated().task_stats.total.solution_remaining.IsOk() &&
      Calculated().task_stats.total.solution_remaining.altitude_difference > fixed(50)
      && GetDisplayMode() == DM_FINAL_GLIDE)
    return;

  PixelRect tb_rect;
  tb_rect.left = rc.left;
  tb_rect.right = rc.left+Layout::Scale(20);
  tb_rect.top = Layout::Scale(4);
  tb_rect.bottom = tb_rect.top+(rc.bottom-rc.top)/2-Layout::Scale(30);

  const ThermalBandRenderer &renderer = thermal_band_renderer;
  if (task != NULL) {
    ProtectedTaskManager::Lease task_manager(*task);
    renderer.DrawThermalBand(Basic(),
                             Calculated(),
                             SettingsComputer(),
                             canvas,
                             tb_rect,
                             SettingsComputer().task,
                             true,
                             &task_manager->get_ordered_task_behaviour());
  } else {
    renderer.DrawThermalBand(Basic(),
                             Calculated(),
                             SettingsComputer(),
                             canvas,
                             tb_rect,
                             SettingsComputer().task,
                             true);
  }
}
Beispiel #3
0
/**
 * Logs GPS fixes for stats
 * @return True if valid fix (fix distance <= 200m), False otherwise
 */
bool
GlideComputerStats::DoLogging()
{
  /// @todo consider putting this sanity check inside Parser
  if (Distance(Basic().location, LastBasic().location) > fixed(200))
    // prevent bad fixes from being logged or added to OLC store
    return false;

  // log points more often in circling mode
  if (Calculated().circling)
    log_clock.set_dt(fixed(SettingsComputer().LoggerTimeStepCircling));
  else
    log_clock.set_dt(fixed(SettingsComputer().LoggerTimeStepCruise));

  if (FastLogNum) {
    log_clock.set_dt(fixed_one);
    FastLogNum--;
  }

  if (log_clock.check_advance(Basic().time) && logger != NULL)
      logger->LogPoint(Basic());

  if (Calculated().flight.flying &&
      stats_clock.check_advance(Basic().time)) {
    flightstats.AddAltitudeTerrain(Calculated().flight.flight_time,
                                   Calculated().terrain_altitude);
    flightstats.AddAltitude(Calculated().flight.flight_time,
                            Basic().NavAltitude);
    flightstats.AddTaskSpeed(Calculated().flight.flight_time,
                             Calculated().task_stats.get_pirker_speed());
  }

  return true;
}
Beispiel #4
0
void
MapWindow::DrawWaypoints(Canvas &canvas)
{
  GlidePolar polar = get_glide_polar();
  polar.set_mc(min(Calculated().common_stats.current_risk_mc,
                   SettingsComputer().safety_mc));

  way_point_renderer.render(canvas, label_block,
                            render_projection, SettingsMap(),
                            SettingsComputer(), polar,
                            ToAircraftState(Basic()),
                            task);
}
Beispiel #5
0
/**
 * Calls the SearchBestAlternate() method if a certain time has passed since the last call
 * @author Paolo Ventafridda
 */
void GlideComputerTask::DoBestAlternateSlow() {
  static double LastSearchBestTime = 0; // VENTA3

  // VENTA3 best landing slow calculation
#ifdef WINDOWSPC
  if ( (SettingsComputer().EnableBestAlternate) && (Basic().Time > LastSearchBestTime+10.0) ) // VENTA3
#else
  if ((SettingsComputer().EnableBestAlternate) && (Basic().Time
      > LastSearchBestTime + BESTALTERNATEINTERVAL)) // VENTA3
#endif
  {
    LastSearchBestTime = Basic().Time;
    SearchBestAlternate();
  }
}
Beispiel #6
0
void
MapWindow::DrawGlideThroughTerrain(Canvas &canvas) const
{
  if (SettingsComputer().FinalGlideTerrain) {
    canvas.hollow_brush();

#ifndef ENABLE_OPENGL
    canvas.select(Graphics::hpTerrainLineBg);
    canvas.polygon(Groundline, TERRAIN_ALT_INFO::NUMTERRAINSWEEPS);
#endif

    canvas.select(Graphics::hpTerrainLine);
    canvas.polygon(Groundline, TERRAIN_ALT_INFO::NUMTERRAINSWEEPS);
  }

  if (!Basic().flight.Flying)
    return;

  if (!Calculated().TerrainWarningLocation.is_null()) {
    RasterPoint sc;
    if (render_projection.GeoToScreenIfVisible(Calculated().TerrainWarningLocation,
                                                 sc))
      Graphics::hTerrainWarning.draw(canvas, sc.x, sc.y);
  }
}
Beispiel #7
0
/*
 * Do not disturb too much. Play alert sound only once every x minutes, not more.
 */
void GlideComputerTask::AlertBestAlternate(short soundmode) {
  static double LastAlertTime = 0;

  if (Basic().Time > LastAlertTime + 180.0) {
    if (SettingsComputer().EnableSoundModes) {
      LastAlertTime = Basic().Time;
      switch (soundmode) {
      case 0:
        break;
      case 1:
        PlayResource(TEXT("IDR_WAV_GREEN"));
        break;
      case 2:
        PlayResource(TEXT("IDR_WAV_RED"));
        break;
      case 11:
        PlayResource(TEXT("IDR_WAV_GREEN"));
        PlayResource(TEXT("IDR_WAV_GREEN"));
        break;
      default:
        break;
      }
    }
  }
}
Beispiel #8
0
void ActionInterface::SendSettingsComputer() {
  ScopeLock protect(mutexBlackboard);
  // send computer settings to the device because we know
  // that it won't be reading from them if we lock it, and
  // then others can retrieve from it at their convenience.
  device_blackboard.ReadSettingsComputer(SettingsComputer());
  // TODO: trigger refresh if the settings are changed
}
Beispiel #9
0
void
GlideComputer::CalculateTeammateBearingRange()
{
  static bool InTeamSector = false;

  // No reference waypoint for teamcode calculation chosen -> cancel
  if (SettingsComputer().TeamCodeRefWaypoint < 0)
    return;

  // Get bearing and distance to the reference waypoint
  const Waypoint *wp =
      way_points.lookup_id(SettingsComputer().TeamCodeRefWaypoint);

  if (!wp)
    return;

  Angle ownBearing = wp->Location.bearing(Basic().Location);

  // If (TeamCode exists and is valid)
  if (SettingsComputer().TeammateCodeValid) {
    // Calculate bearing and distance to teammate
    SetCalculated().TeammateLocation =
        SettingsComputer().TeammateCode.GetLocation(wp->Location);

    GeoVector team_vector(Basic().Location, Calculated().TeammateLocation);

    // Save bearing and distance to teammate in Calculated
    SetCalculated().TeammateBearing = team_vector.Bearing;
    SetCalculated().TeammateRange = team_vector.Distance;

    // Hysteresis for GlideComputerEvent
    // If (closer than 100m to the teammates last position and "event" not reset)
    if (Calculated().TeammateRange < fixed(100) && InTeamSector == false) {
      InTeamSector = true;
      // Raise GCE_TEAM_POS_REACHED event
      InputEvents::processGlideComputer(GCE_TEAM_POS_REACHED);
    } else if (Calculated().TeammateRange > fixed(300)) {
      // Reset "event" when distance is greater than 300m again
      InTeamSector = false;
    }
  } else {
    SetCalculated().TeammateBearing = Angle::degrees(fixed_zero);
    SetCalculated().TeammateRange = fixed_zero;
  }
}
Beispiel #10
0
/**
 * Draws the teammate icon to the given canvas
 * @param canvas Canvas for drawing
 */
void
MapWindow::DrawTeammate(Canvas &canvas) const
{
  if (SettingsComputer().TeammateCodeValid) {
    RasterPoint sc;
    if (render_projection.GeoToScreenIfVisible(Calculated().TeammateLocation,
                                                 sc))
      Graphics::hBmpTeammatePosition.draw(canvas, sc);
  }
}
Beispiel #11
0
void
TargetMapWindow::DrawWaypoints(Canvas &canvas)
{
  const SETTINGS_MAP &settings_map = SettingsMap();
  WaypointRendererSettings settings = settings_map.waypoint;
  settings.display_text_type = DISPLAYNAME;

  way_point_renderer.render(canvas, label_block,
                            projection, settings,
                            SettingsComputer().task,
                            task, NULL);
}
Beispiel #12
0
void
TargetMapWindow::RenderAirspace(Canvas &canvas)
{
  if (SettingsMap().airspace.enable)
    airspace_renderer.Draw(canvas,
#ifndef ENABLE_OPENGL
                           buffer_canvas, stencil_canvas,
#endif
                           projection,
                           Basic(), Calculated(),
                           SettingsComputer(), SettingsMap());
}
Beispiel #13
0
void
MapWindow::DrawGlideThroughTerrain(Canvas &canvas)
{
  canvas.select(MapGfx.hpTerrainLineBg);
  canvas.polyline(Groundline, NUMTERRAINSWEEPS + 1);
  if ((SettingsComputer().FinalGlideTerrain==1) ||
      ((!SettingsMap().EnableTerrain || !Calculated().Flying) &&
       (SettingsComputer().FinalGlideTerrain==2))) {
    canvas.select(MapGfx.hpTerrainLine);
    canvas.polyline(Groundline, NUMTERRAINSWEEPS + 1);
  }

  if (Calculated().Flying && task.Valid()) {
    if ((Calculated().TerrainWarningLocation.Latitude != 0.0)
        &&(Calculated().TerrainWarningLocation.Longitude != 0.0)) {

      draw_masked_bitmap_if_visible(canvas, MapGfx.hTerrainWarning,
				    Calculated().TerrainWarningLocation,
				    10, 10);
    }
  }
}
Beispiel #14
0
void
DeviceBlackboard::tick()
{
  SetBasic().expire();

  // calculate fast data to complete aircraft state

  computer.Compute(SetBasic(), LastBasic(),
                   Calculated(), SettingsComputer());

  if (Basic().Time!= LastBasic().Time) {
    state_last = Basic();
  }
}
Beispiel #15
0
/**
 * Calculates the own TeamCode and saves it to Calculated
 */
void
GlideComputer::CalculateOwnTeamCode()
{
  // No reference waypoint for teamcode calculation chosen -> cancel
  if (SettingsComputer().TeamCodeRefWaypoint < 0)
    return;

  // Only calculate every 10sec otherwise cancel calculation
  if (!last_team_code_update.check_update(10000))
    return;

  // Get bearing and distance to the reference waypoint
  const Waypoint *wp =
      way_points.lookup_id(SettingsComputer().TeamCodeRefWaypoint);

  if (!wp)
    return;

  Angle bearing = wp->Location.bearing(Basic().Location);
  fixed distance = wp->Location.distance(Basic().Location);

  // Save teamcode to Calculated
  SetCalculated().OwnTeamCode.Update(bearing, distance);
}
Beispiel #16
0
/**
 * Calculates the screen positions of all important features
 * @param canvas The drawing canvas
 * @param rc The area to draw in
 */
void
MapWindow::RenderStart(Canvas &canvas, const RECT &rc)
{
  // Calculate screen position of the aircraft
  projection.CalculateOrigin(rc, Basic(), Calculated(),
                             SettingsComputer(), SettingsMap());

  // Calculate screen positions of the thermal sources
  CalculateScreenPositionsThermalSources();

  // Calculate screen positions of the final glide groundline
  CalculateScreenPositionsGroundline();

  // reset label over-write preventer
  label_block.reset();
}
Beispiel #17
0
/*
 * VENTA3 Alternates destinations
 *
 * Used by Alternates and BestAlternate
 *
 * Colors VGR are disabled, but available
 */
void GlideComputerTask::DoAlternates(int AltWaypoint) {
  if (!way_points.verify_index(AltWaypoint)) {
    return;
  }

  const WAYPOINT &way_point = way_points.get(AltWaypoint);
  WPCALC &way_point_calc = way_points.set_calc(AltWaypoint);
  GEOPOINT w1 = way_point.Location;
  GEOPOINT w0 = Basic().Location;
  double *altwp_dist = &way_point_calc.Distance;
  double *altwp_gr = &way_point_calc.GR;
  double *altwp_arrival = &way_point_calc.AltArrival;
  short *altwp_vgr = &way_point_calc.VGR;

  *altwp_dist = Distance(w1, w0);

  double GRsafecalc = Calculated().NavAltitude - (way_point.Altitude
      + SettingsComputer().SafetyAltitudeArrival);

  if (GRsafecalc <= 0) {
    *altwp_gr = INVALID_GR;
  } else {
    *altwp_gr = *altwp_dist / GRsafecalc;
    if (*altwp_gr > ALTERNATE_MAXVALIDGR || *altwp_gr < 0) {
      *altwp_gr = INVALID_GR;
    } else if (*altwp_gr < 1) {
      *altwp_gr = 1;
    }
  }

  // We need to calculate arrival also for BestAlternate, since the last "reachable" could be
  // even 60 seconds old and things may have changed drastically

  *altwp_arrival = CalculateWaypointArrivalAltitude(way_point, way_point_calc);
  if ((*altwp_arrival - ALTERNATE_OVERSAFETY) > 0) {
    if (*altwp_gr <= (GlidePolar::bestld * SAFELD_FACTOR)) {
      *altwp_vgr = 1; // full green vgr
    } else if (*altwp_gr <= GlidePolar::bestld) {
      *altwp_vgr = 2; // yellow vgr
    } else
      *altwp_vgr = 3; // RED vgr
  } else {
    *altwp_vgr = 3; // full red
  }
}
Beispiel #18
0
void
MapWindow::DrawGlideThroughTerrain(Canvas &canvas) const
{
  if (SettingsComputer().FinalGlideTerrain) {
    canvas.select(MapGfx.hpTerrainLineBg);
    canvas.polyline(Groundline, TERRAIN_ALT_INFO::NUMTERRAINSWEEPS + 1);

    canvas.select(MapGfx.hpTerrainLine);
    canvas.polyline(Groundline, TERRAIN_ALT_INFO::NUMTERRAINSWEEPS + 1);
  }

  if (!Basic().flight.Flying)
    return;

  if (!Calculated().TerrainWarningLocation.is_null()) {
    POINT sc;
    if (projection.LonLat2ScreenIfVisible(Calculated().TerrainWarningLocation,
                                          &sc))
      MapGfx.hTerrainWarning.draw(canvas, bitmap_canvas, sc.x, sc.y);
  }
}
Beispiel #19
0
/**
 * Is called by the CalculationThread and processes the received GPS data in Basic()
 */
bool
GlideComputer::ProcessGPS()
{
  PeriodClock clock;
  clock.update();

  // Process basic information
  ProcessBasic();

  // Process basic task information
  ProcessBasicTask();
  ProcessMoreTask();

  // Check if everything is okay with the gps time and process it
  if (!FlightTimes()) {
    return false;
  }

  // Process extended information
  ProcessVertical();

  // Calculate the team code
  CalculateOwnTeamCode();

  // Calculate the bearing and range of the teammate
  CalculateTeammateBearingRange();

  // Calculate the bearing and range of the teammate
  // (if teammate is a FLARM target)
  FLARM_ScanTraffic();

  vegavoice.Update(&Basic(), &Calculated(), SettingsComputer());

  // Update the ConditionMonitors
  ConditionMonitorsUpdate(*this);

  SetCalculated().time_process_gps = clock.elapsed();

  return true;
}
Beispiel #20
0
/**
 * Renders the terrain background, the groundline and the topology
 * @param canvas The drawing canvas
 * @param rc The area to draw in
 */
void
MapWindow::RenderMapLayer(Canvas &canvas)
{
  m_background.sun_from_wind(projection, Basic().wind);
  m_background.Draw(canvas, projection, SettingsMap());

  // Select black brush/pen and the MapWindowFont
  canvas.black_brush();
  canvas.black_pen();
  canvas.select(Fonts::Map);

  if (terrain != NULL) {
    if ((SettingsComputer().FinalGlideTerrain == 2) && 
        Calculated().TerrainValid)
      // Draw the groundline (and shading)
      DrawTerrainAbove(canvas, buffer_canvas);
  }

  if (topology != NULL && SettingsMap().EnableTopology)
    // Draw the topology
    topology->Draw(canvas, bitmap_canvas, projection);
}
Beispiel #21
0
void
DeviceBlackboard::Merge()
{
  real_data.reset();
  for (unsigned i = 0; i < NUMDEV; ++i) {
    per_device_data[i].expire();
    real_data.complement(per_device_data[i]);
  }

  if (replay_data.Connected) {
    replay_data.expire();
    SetBasic() = replay_data;
  } else if (simulator_data.Connected) {
    simulator_data.expire();
    SetBasic() = simulator_data;
  } else {
    SetBasic() = real_data;
  }

  computer.Fill(SetBasic(), SettingsComputer());

  ProcessFLARM();

  if (last_location_available != Basic().LocationAvailable) {
    last_location_available = Basic().LocationAvailable;
    TriggerGPSUpdate();
  } else if (last_vario_counter != Basic().VarioCounter) {
    last_vario_counter = Basic().VarioCounter;
    TriggerGPSUpdate();
  }

  if (last_te_vario_available != Basic().TotalEnergyVarioAvailable ||
      last_netto_vario_available != Basic().NettoVarioAvailable) {
    last_te_vario_available = Basic().TotalEnergyVarioAvailable;
    last_netto_vario_available = Basic().NettoVarioAvailable;
    TriggerVarioUpdate();
  }
}
Beispiel #22
0
void
GlueMapWindow::QuickRedraw(const SETTINGS_MAP &_settings_map)
{
  assert(&_settings_map != &SettingsMap());

  ReadSettingsMap(_settings_map);

  /* update the Projection */

  visible_projection.CalculateOrigin(get_client_rect(),
                                     Basic(), Calculated(),
                                     SettingsComputer(),
                                     SettingsMap());

  visible_projection.ExchangeBlackboard(Calculated(), SettingsMap());

  ++ui_generation;

  /* quickly stretch the existing buffer into the window */

  scale_buffer = 2;
  invalidate();
}
Beispiel #23
0
void XCSoarInterface::AfterStartup() {
  static bool first = true;
  if (!first) {
    return;
  }
  first = false;

  StartupStore(TEXT("ProgramStarted=3\n"));
  StartupLogFreeRamAndStorage();

  status_messages.Startup(true);

  if (is_simulator()) {
    StartupStore(TEXT("GCE_STARTUP_SIMULATOR\n"));
    InputEvents::processGlideComputer(GCE_STARTUP_SIMULATOR);
  } else {
    StartupStore(TEXT("GCE_STARTUP_REAL\n"));
    InputEvents::processGlideComputer(GCE_STARTUP_REAL);
  }

  // Create default task if none exists
  StartupStore(TEXT("Create default task\n"));
  task.DefaultTask(SettingsComputer());

  StartupStore(TEXT("CloseProgressDialog\n"));
  CloseProgressDialog();

  main_window.full_screen();
  InfoBoxManager::SetDirty(true);
  TriggerAll();

  status_messages.Startup(false);
#ifdef _INPUTDEBUG_
  InputEvents::showErrors();
#endif
}
Beispiel #24
0
void MapWindow::CalculateScreenPositionsGroundline(void) {
  if (SettingsComputer().FinalGlideTerrain) {
    LonLat2Screen(Calculated().GlideFootPrint,
		  Groundline, NUMTERRAINSWEEPS+1, 1);
  }
}
Beispiel #25
0
void XCSoarInterface::Shutdown(void) {
  CreateProgressDialog(gettext(TEXT("Shutdown, please wait...")));
  StartHourglassCursor();

  StartupStore(TEXT("Entering shutdown...\n"));
  StartupLogFreeRamAndStorage();

  // turn off all displays
  globalRunningEvent.reset();

  StartupStore(TEXT("dlgAirspaceWarningDeInit\n"));
  dlgAirspaceWarningDeInit();

  CreateProgressDialog(gettext(TEXT("Shutdown, saving logs...")));
  // stop logger
  logger.guiStopLogger(Basic(),true);

  CreateProgressDialog(gettext(TEXT("Shutdown, saving profile...")));
  // Save settings
  Profile::StoreRegistry();

  // Stop sound

  StartupStore(TEXT("SaveSoundSettings\n"));
  Profile::SaveSoundSettings();

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

  // Stop drawing
  CreateProgressDialog(gettext(TEXT("Shutdown, please wait...")));

  StartupStore(TEXT("CloseDrawingThread\n"));
  closeTriggerEvent.trigger();

  calculation_thread->join();
  StartupStore(TEXT("- calculation thread returned\n"));

  instrument_thread->join();
  StartupStore(TEXT("- instrument thread returned\n"));

  draw_thread->join();
  StartupStore(TEXT("- draw thread returned\n"));

  delete draw_thread;

  // Clear data

  CreateProgressDialog(gettext(TEXT("Shutdown, saving task...")));
  StartupStore(TEXT("Resume abort task\n"));
  task.ResumeAbortTask(SettingsComputer(), -1); // turn off abort if it was on.
  StartupStore(TEXT("Save default task\n"));
  task.SaveDefaultTask();
  StartupStore(TEXT("Clear task data\n"));
  task.ClearTask();
  StartupStore(TEXT("Close airspace\n"));
  CloseAirspace();

  StartupStore(TEXT("Close waypoints\n"));
  way_points.clear();

  CreateProgressDialog(gettext(TEXT("Shutdown, please wait...")));

  StartupStore(TEXT("CloseTerrainTopology\n"));

  RASP.Close();
  terrain.CloseTerrain();

  delete topology;
  delete marks;

  devShutdown();

  SaveCalculationsPersist(Basic(),Calculated());
#if (EXPERIMENTAL > 0)
  //  CalibrationSave();
#endif

  #if defined(GNAV) && !defined(PCGNAV)
    StartupStore(TEXT("Altair shutdown\n"));
    Sleep(2500);
    StopHourglassCursor();
    InputEvents::eventDLLExecute(TEXT("altairplatform.dll SetShutdown 1"));
    while(1) {
      Sleep(100); // free time up for processor to perform shutdown
    }
  #endif

  CloseFLARMDetails();

  // Kill windows

  StartupStore(TEXT("Destroy Info Boxes\n"));
  InfoBoxManager::Destroy();

  StartupStore(TEXT("Destroy Button Labels\n"));
  ButtonLabel::Destroy();

  StartupStore(TEXT("Delete Objects\n"));

  // Kill graphics objects

  DeleteFonts();

  DeleteAirspace();

  StartupStore(TEXT("Close Progress Dialog\n"));

  CloseProgressDialog();

  CloseGeoid();

  StartupStore(TEXT("Close Windows - main \n"));
  main_window.reset();
  StartupStore(TEXT("Close Graphics\n"));
  MapGfx.Destroy();

#ifdef DEBUG_TRANSLATIONS
  StartupStore(TEXT("Writing missing translations\n"));
  WriteMissingTranslations();
#endif

  StartupLogFreeRamAndStorage();
  StartupStore(TEXT("Finished shutdown\n"));
  StopHourglassCursor();

}
Beispiel #26
0
/**
 * "Boots" up XCSoar
 * @param hInstance Instance handle
 * @param lpCmdLine Command line string
 * @return True if bootup successful, False otherwise
 */
bool XCSoarInterface::Startup(HINSTANCE hInstance, LPTSTR lpCmdLine)
{
  // The title bar text
  TCHAR szTitle[MAX_LOADSTRING];

  // Store instance handle in our global variable
  hInst = hInstance;

  // IDS_APP_TITLE = XCSoar (see XCSoar.rc)
  LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

  //If it is already running, then focus on the window
  if (MainWindow::find(szTitle))
    return false;

  // Send the SettingsMap to the DeviceBlackboard
  SendSettingsMap();

  // Register window classes
  PaintWindow::register_class(hInst);
  MainWindow::register_class(hInst);
  MapWindow::register_class(hInst);

  // Fill the fast(co)sine table
  InitSineTable();

  PreloadInitialisation(true);

  // Send the SettingsMap to the DeviceBlackboard
  SendSettingsMap();

  // Creates the main window
  StartupStore(TEXT("Create main window\n"));
  RECT WindowSize = SystemWindowSize();
  main_window.set(szTitle,
		  WindowSize.left, WindowSize.top,
		  WindowSize.right, WindowSize.bottom);

  if (!main_window.defined()) {
    return false;
  }
  main_window.install_timer();

  // Initialize DeviceBlackboard
  device_blackboard.Initialise();

  // Initialize Marks
  marks = new Marks("xcsoar-marks");
  topology = new TopologyStore(marks->GetTopology());

  // Show the main and map windows
  StartupStore(TEXT("Create map window\n"));
  main_window.show();
  main_window.map.show();

#ifdef HAVE_ACTIVATE_INFO
  SHSetAppKeyWndAssoc(VK_APP1, main_window);
  SHSetAppKeyWndAssoc(VK_APP2, main_window);
  SHSetAppKeyWndAssoc(VK_APP3, main_window);
  SHSetAppKeyWndAssoc(VK_APP4, main_window);
  // Typical Record Button
  //	Why you can't always get this to work
  //	http://forums.devbuzz.com/m_1185/mpage_1/key_/tm.htm
  //	To do with the fact it is a global hotkey, but you can with code above
  //	Also APPA is record key on some systems
  SHSetAppKeyWndAssoc(VK_APP5, main_window);
  SHSetAppKeyWndAssoc(VK_APP6, main_window);
#endif

  // Initialize main blackboard data
  task.ClearTask();
  glide_computer.Initialise();
  logger.LinkGRecordDLL(); // try to link DLL if it exists

  // Load the EGM96 geoid data
  OpenGeoid();

  PreloadInitialisation(false);

  Profile::LoadWindFromRegistry();

  // TODO TB: seems to be out of date?!
  CalculateNewPolarCoef();

  // Calculate polar-related data and saves it to the cache
  StartupStore(TEXT("GlidePolar::UpdatePolar\n"));
  GlidePolar::UpdatePolar(false, SettingsComputer());

  // Show startup info depending on device
  StartupInfo();

  // Read the topology file(s)
  topology->Open();

  // Read the terrain file
  terrain.OpenTerrain();

  // Read the waypoint files
  ReadWayPoints(way_points, terrain);

  // Read and parse the airfield info file
  ReadAirfieldFile();

  // Set the home waypoint
  SetHome(way_points, terrain, SetSettingsComputer(), false, true);

  // ReSynchronise the blackboards here since SetHome touches them
  ReadBlackboardBasic(device_blackboard.Basic());

  terrain.ServiceFullReload(Basic().Location);

  // Scan for weather forecast
  CreateProgressDialog(gettext(TEXT("Scanning weather forecast")));
  StartupStore(TEXT("RASP load\n"));
  RASP.ScanAll(Basic().Location);

  // Reads the airspace files
  ReadAirspace();
  // Sorts the airspaces by priority
  SortAirspace();

  // Read the FLARM details file
  OpenFLARMDetails();

#ifndef DISABLEAUDIOVARIO
  /*
  VarioSound_Init();
  VarioSound_EnableSound(EnableSoundVario);
  VarioSound_SetVdead(SoundDeadband);
  VarioSound_SetV(0);
  VarioSound_SetSoundVolume(SoundVolume);
  */
#endif

  // Start the device thread(s)
  CreateProgressDialog(gettext(TEXT("Starting devices")));
  devStartup(lpCmdLine);

  // Reset polar in case devices need the data
  StartupStore(TEXT("GlidePolar::UpdatePolar\n"));
  GlidePolar::UpdatePolar(true, SettingsComputer());

  CreateProgressDialog(gettext(TEXT("Initialising display")));

  // Finally ready to go.. all structures must be present before this.

  // Create the drawing thread
  StartupStore(TEXT("CreateDrawingThread\n"));
  draw_thread = new DrawThread(main_window.map, main_window.flarm);
  draw_thread->start();

  // Show the infoboxes
  StartupStore(TEXT("ShowInfoBoxes\n"));
  InfoBoxManager::Show();

  // Create the calculation thread
  StartupStore(TEXT("CreateCalculationThread\n"));
  CreateCalculationThread();

#ifdef NEWTASK  
  { // NEWTASK
    PeriodClock t;
    t.reset(); t.update();
    CreateProgressDialog(gettext(TEXT("Running test 0")));
    test_newtask(0);
    StartupStore(TEXT("test 0 %d\n"),t.elapsed());

    /*
    t.update();
    CreateProgressDialog(gettext(TEXT("Running test 1")));
    test_newtask(1);
    StartupStore(TEXT("test 1 %d\n"),t.elapsed());

    t.update();
    CreateProgressDialog(gettext(TEXT("Running test 2")));
    test_newtask(2);
    StartupStore(TEXT("test 2 %d\n"),t.elapsed());

    t.update();
    CreateProgressDialog(gettext(TEXT("Running test 3")));
    test_newtask(3);
    StartupStore(TEXT("test 3 %d\n"),t.elapsed());

    t.update();
    CreateProgressDialog(gettext(TEXT("Running test 4")));
    test_newtask(4);
    StartupStore(TEXT("test 4 %d\n"),t.elapsed());
    */
    CreateProgressDialog(gettext(TEXT("test complete")));
  }
#endif

  // Initialise the airspace warning dialog
  StartupStore(TEXT("dlgAirspaceWarningInit\n"));
  dlgAirspaceWarningInit();

  // Find unique ID of this PDA
  ReadAssetNumber();

  StartupStore(TEXT("ProgramStarted\n"));

  // Give focus to the map
  main_window.map.set_focus();

  // Start calculation thread
  calculation_thread->start();

  // Start instrument thread
  instrument_thread->start();

  globalRunningEvent.trigger();

  return true;
}
Beispiel #27
0
void MapWindow::DrawFlightMode(Canvas &canvas, const RECT rc)
{
  static bool flip= true;
  static double LastTime = 0;
  bool drawlogger = true;
  static bool lastLoggerActive=false;
  int offset = -1;

  if (!Appearance.DontShowLoggerIndicator){

    // has GPS time advanced?
    if(Basic().Time <= LastTime) {
      LastTime = Basic().Time;
    } else {
      flip = !flip;

      // don't bother drawing logger if not active for more than one second
      if ((!logger.isLoggerActive())&&(!lastLoggerActive)) {
        drawlogger = false;
      }
      lastLoggerActive = logger.isLoggerActive();
    }

    if (drawlogger) {
      offset -= 7;

      draw_masked_bitmap(canvas,
			 (logger.isLoggerActive() && flip)
			 ? MapGfx.hLogger : MapGfx.hLoggerOff,
			 rc.right + IBLSCALE(offset + Appearance.FlightModeOffset.x),
			 rc.bottom + IBLSCALE(-7 + Appearance.FlightModeOffset.y),
			 7, 7, false);
    }
  }

  if (Appearance.FlightModeIcon == apFlightModeIconDefault){
    Bitmap *bmp;
    if (task.isTaskAborted()) {
      bmp = &MapGfx.hAbort;
    } else if (DisplayMode == dmCircling) {
      bmp = &MapGfx.hClimb;
    } else if (DisplayMode == dmFinalGlide) {
      bmp = &MapGfx.hFinalGlide;
    } else {
      bmp = &MapGfx.hCruise;
    }

    offset -= 24;

    draw_masked_bitmap(canvas, *bmp,
		       rc.right + IBLSCALE(offset - 1 + Appearance.FlightModeOffset.x),
		       rc.bottom + IBLSCALE(-20 - 1 + Appearance.FlightModeOffset.y),
		       24, 20, false);

  } else if (Appearance.FlightModeIcon == apFlightModeIconAltA){

#define SetPoint(Idx,X,Y) Arrow[Idx].x = X; Arrow[Idx].y = Y

    POINT Arrow[3];
    POINT Center;

    Center.x = rc.right-10;
    Center.y = rc.bottom-10;

    if (DisplayMode == dmCircling) {

      SetPoint(0,
               Center.x,
               Center.y-IBLSCALE(4));
      SetPoint(1,
               Center.x-IBLSCALE(8),
               Center.y+IBLSCALE(4));
      SetPoint(2,
               Center.x+IBLSCALE(8),
               Center.y+IBLSCALE(4));

    } else if (DisplayMode == dmFinalGlide) {

      SetPoint(0,
               Center.x,
               Center.y+IBLSCALE(4));
      SetPoint(1,
               Center.x-IBLSCALE(8),
               Center.y-IBLSCALE(4));
      SetPoint(2,
               Center.x+IBLSCALE(8),
               Center.y-IBLSCALE(4));
    } else {

      SetPoint(0,
               Center.x+IBLSCALE(4),
               Center.y);
      SetPoint(1,
               Center.x-IBLSCALE(4),
               Center.y+IBLSCALE(8));
      SetPoint(2,
               Center.x-IBLSCALE(4),
               Center.y-IBLSCALE(8));

    }

    if (task.isTaskAborted())
      canvas.select(MapGfx.hBrushFlyingModeAbort);
    else
      canvas.select(MapGfx.hbCompass);

    canvas.select(MapGfx.hpCompassBorder);
    canvas.polygon(Arrow, 3);

    canvas.select(MapGfx.hpCompass);
    canvas.polygon(Arrow, 3);
  }


  if (!Appearance.DontShowAutoMacCready && SettingsComputer().AutoMacCready) {

    offset -= 24;

    //changed draw mode & icon for higher opacity 12aug -st

    draw_masked_bitmap(canvas, MapGfx.hAutoMacCready,
		       rc.right + IBLSCALE(offset - 3 + Appearance.FlightModeOffset.x),
		       rc.bottom + IBLSCALE(-20 - 3 + Appearance.FlightModeOffset.y),
		       24, 20, false);
  };

}
Beispiel #28
0
void InfoBoxFormatter::AssignValue(int i) {
  switch (i) {
  case 0:
    Value = ALTITUDEMODIFY*Basic().Altitude;
    break;
  case 1:
    Value = ALTITUDEMODIFY*Calculated().AltitudeAGL  ;
    Valid = Calculated().TerrainValid;
    break;
  case 2:
    Value = LIFTMODIFY*Calculated().Average30s;
    break;
  case 3:
    Value = Calculated().WaypointBearing;
    Valid = Calculated().WaypointDistance > 10.0;
    break;
  case 4:
    if (Calculated().LD== 999) {
      Valid = false;
    } else {
      Valid = true;
      Value = Calculated().LD;
    }
    break;
  case 5:
    if (Calculated().CruiseLD== 999) {
      Valid = false;
    } else {
      Valid = true;
      Value = Calculated().CruiseLD;
    }
    break;
  case 6:
    Value = SPEEDMODIFY*Basic().Speed;
    break;
  case 7:
    Value = LIFTMODIFY*Calculated().LastThermalAverage;
    break;
  case 8:
    Value = ALTITUDEMODIFY*Calculated().LastThermalGain;
    break;
  case 10:
    Value = iround(LIFTMODIFY*GlidePolar::GetMacCready()*10)/10.0;
    break;
  case 11:
    Value = DISTANCEMODIFY*Calculated().WaypointDistance;
    Valid = task.ValidTaskPoint(task.getActiveIndex());
    break;
  case 12:
    Value = ALTITUDEMODIFY*Calculated().NextAltitudeDifference;
    Valid = task.ValidTaskPoint(task.getActiveIndex());
    break;
  case 13:
    Value = ALTITUDEMODIFY*Calculated().NextAltitudeRequired;
    Valid = task.ValidTaskPoint(task.getActiveIndex());
    break;
  case 14:
    Value = 0; // Next Waypoint Text
    break;
  case 15:
    Value = ALTITUDEMODIFY*Calculated().TaskAltitudeDifference;
    Valid = task.ValidTaskPoint(task.getActiveIndex());
    break;
  case 16:
    Value = ALTITUDEMODIFY*Calculated().TaskAltitudeRequired;
    Valid = task.ValidTaskPoint(task.getActiveIndex());
    break;
  case 17:
    Value = TASKSPEEDMODIFY*Calculated().TaskSpeed;
    if (task.getActiveIndex()>=1) {
      Valid = task.ValidTaskPoint(task.getActiveIndex());
    } else {
      Valid = false;
    }
    break;
  case 18:
    if (Calculated().ValidFinish) {
      Value = DISTANCEMODIFY*Calculated().WaypointDistance;
    } else {
      Value = DISTANCEMODIFY*Calculated().TaskDistanceToGo;
    }
    Valid = task.ValidTaskPoint(task.getActiveIndex());
    break;
  case 19:
    if (Calculated().LDFinish== 999) {
      Valid = false;
    } else {
      Valid = task.ValidTaskPoint(task.getActiveIndex());
      if (Calculated().ValidFinish) {
        Value = 0;
      } else {
        Value = Calculated().LDFinish;
      }
    }
    break;
  case 20:
    Value = ALTITUDEMODIFY*Calculated().TerrainAlt ;
    Valid = Calculated().TerrainValid;
    break;
  case 21:
    Value = LIFTMODIFY*Calculated().AverageThermal;
    break;
  case 22:
    Value = ALTITUDEMODIFY*Calculated().ThermalGain;
    break;
  case 23:
    Value = Basic().TrackBearing;
    break;
  case 24:
    if (Basic().VarioAvailable) {
      Value = LIFTMODIFY*Basic().Vario;
    } else {
      Value = LIFTMODIFY*Calculated().Vario;
    }
    break;
  case 25:
    Value = SPEEDMODIFY*Calculated().WindSpeed;
    break;
  case 26:
    Value = Calculated().WindBearing;
    break;
  case 28:
    Value = DISTANCEMODIFY*Calculated().AATMaxDistance ;
    Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled;
    break;
  case 29:
    Value = DISTANCEMODIFY*Calculated().AATMinDistance ;
    Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled;
    break;
  case 30:
    Value = TASKSPEEDMODIFY*Calculated().AATMaxSpeed;
    Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled;
    if (Calculated().AATTimeToGo<1) {
      Valid = false;
    }
    break;
  case 31:
    Value = TASKSPEEDMODIFY*Calculated().AATMinSpeed;
    Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled;
    if (Calculated().AATTimeToGo<1) {
      Valid = false;
    }
    break;
  case 32:
    Valid = Basic().AirspeedAvailable;
    Value = SPEEDMODIFY*Basic().IndicatedAirspeed;
    break;
  case 33:
    Valid = Basic().BaroAltitudeAvailable;
    Value = ALTITUDEMODIFY*Basic().BaroAltitude;
    break;
  case 34:
    Value = SPEEDMODIFY*Calculated().VMacCready;
    break;
  case 35:
    Value = Calculated().PercentCircling;
    break;
  case 37:
    Valid = Basic().AccelerationAvailable;
    Value = Basic().Gload;
    break;
  case 38:
    if (Calculated().LDNext== 999) {
      Valid = false;
    } else {
      Valid = task.ValidTaskPoint(task.getActiveIndex());
      Value = Calculated().LDNext;
    }
    break;
  case 43:
    //    Valid = Basic().AirspeedAvailable;
    Value = Calculated().VOpt*SPEEDMODIFY;
    break;
  case 44:
    //    Valid = Basic().AirspeedAvailable;
    Value = Calculated().NettoVario*LIFTMODIFY;
    break;
  case 48:
    Value = Basic().OutsideAirTemperature;
    break;
  case 49:
    Value = Basic().RelativeHumidity;
    break;
  case 50:
    Value = CuSonde::maxGroundTemperature;
    break;
  case 51:
    Value = DISTANCEMODIFY*Calculated().AATTargetDistance ;
    Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled;
    break;
  case 52:
    Value = TASKSPEEDMODIFY*Calculated().AATTargetSpeed;
    Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled;
    if (Calculated().AATTimeToGo<1) {
      Valid = false;
    }
    break;
  case 53:
    if (Calculated().LDvario== 999) {
      Valid = false;
    } else {
      Valid = Basic().VarioAvailable && Basic().AirspeedAvailable;
      Value = Calculated().LDvario;
    }
    break;
  case 54:
    Valid = Basic().AirspeedAvailable;
    Value = SPEEDMODIFY*Basic().TrueAirspeed;
    break;
  case 56: // team bearing
    Value = Calculated().TeammateBearing;
    Valid = true;
  case 58: // team range
    if (SettingsComputer().TeammateCodeValid)
      {
	Value = DISTANCEMODIFY*Calculated().TeammateRange;
	if (Value > 100)
	  {
	    _tcscpy(Format, _T("%.0lf"));
	  }
	else
	  {
	    _tcscpy(Format, _T("%.1lf"));
	  }
	Valid = true;
      }
    else
      {
	Valid = false;
      }
    break;
  case 59:
    Value = TASKSPEEDMODIFY*Calculated().TaskSpeedInstantaneous;
    if (task.getActiveIndex()>=1) {
      Valid = task.ValidTaskPoint(task.getActiveIndex());
    } else {
      Valid = false;
    }
    break;
  case 60:
    Value = DISTANCEMODIFY*Calculated().HomeDistance ;
    if (SettingsComputer().HomeWaypoint>=0) {
      Valid = way_points.verify_index(SettingsComputer().HomeWaypoint);
    } else {
      Valid = false;
    }
    break;
  case 61:
    Value = TASKSPEEDMODIFY*Calculated().TaskSpeedAchieved;
    if (task.getActiveIndex()>=1) {
      Valid = task.ValidTaskPoint(task.getActiveIndex());
    } else {
      Valid = false;
    }
    break;
  case 63:
    if (Calculated().timeCircling>0) {
      Value = LIFTMODIFY*Calculated().TotalHeightClimb
        /Calculated().timeCircling;
      Valid = true;
    } else {
      Value = 0.0;
      Valid = false;
    }
    break;
  case 64:
    Value = LIFTMODIFY*Calculated().DistanceVario;
    if (task.getActiveIndex()>=1) {
      Valid = task.ValidTaskPoint(task.getActiveIndex());
    } else {
      Valid = false;
    }
    break;
  case 65: // battery voltage
#if !defined(WINDOWSPC) && !defined(HAVE_POSIX)
    if (!is_altair()) {
      Value = PDABatteryPercent;
      Valid = true;
    } else {
      Value = Basic().SupplyBatteryVoltage;
      if (Value>0.0) {
        Valid = true;
      } else {
        Valid = false;
      }
    }
#else
    Value = 0.0;
    Valid = false;
#endif
    break;
  case 66: // VENTA-ADDON added GR Final
    if (Calculated().GRFinish== 999) {
      Valid = false;
    } else {
      Valid = task.ValidTaskPoint(task.getActiveIndex());
      if (Calculated().ValidFinish) {
	Value = 0;
      } else {
	Value = Calculated().GRFinish;
	if (Value >100 )
	  {
	    _tcscpy(Format, _T("%1.0f"));
	  }
	else
	  {
	    _tcscpy(Format, _T("%1.1f"));
	  }
      }
    }
    break;
  case 70:	// VENTA3 QFE
//    Valid = Basic().Altitude;
    Value = ALTITUDEMODIFY* (Basic().Altitude-QFEAltitudeOffset);
    break;
  case 71:
    if ( Calculated().AverageLD == 0) {
      Valid = false;
    } else {
      Valid = true;
      Value = Calculated().AverageLD;
      if (Value<0)
	    _tcscpy(Format, _T("^^^"));
      else if (Value>=999)
	    _tcscpy(Format, _T("+++"));
      else
	    _tcscpy(Format, _T("%2.0f"));

    }
    break;
  case 72:
    Value = Calculated().Experimental;
    Valid = true;
    break;
    /* TODO feature: add extra infoboxes from Lars
  case 68: // distance flown
    if (Calculated().TaskDistanceCovered != 0)
      {
	Value = DISTANCEMODIFY*Calculated().TaskDistanceCovered;
	Valid = true;
      }
    else
      {
	Value = 0.0;
	Valid = false;
      }
    break;
  case 67: // termik liga points
    if (Calculated().TermikLigaPoints != 0)
      {
	Value = Calculated().TermikLigaPoints;
	Valid = true;
      }
    else
      {
	Value = 0.0;
	Valid = false;
      }
    break;
    */
  default:
    break;
  };
}
Beispiel #29
0
void
GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc,
                            const MapWindowProjection &projection) const
{
  TCHAR buffer[80];

  fixed MapWidth = projection.GetScreenWidthMeters();

  canvas.select(Fonts::MapBold);
  Units::FormatUserMapScale(MapWidth, buffer,
                            sizeof(buffer) / sizeof(TCHAR), true);
  PixelSize TextSize = canvas.text_size(buffer);

  int Height = Fonts::MapBold.get_capital_height() + Layout::Scale(2);
  // 2: add 1pix border

  canvas.fill_rectangle(Layout::Scale(4), rc.bottom - Height,
                        TextSize.cx + Layout::Scale(11), rc.bottom,
                        COLOR_WHITE);

  canvas.background_transparent();
  canvas.set_text_color(COLOR_BLACK);

  canvas.text(Layout::Scale(7),
              rc.bottom - Fonts::MapBold.get_ascent_height() - Layout::Scale(1),
              buffer);

  Graphics::hBmpMapScaleLeft.draw(canvas, 0, rc.bottom - Height);
  Graphics::hBmpMapScaleRight.draw(canvas, Layout::Scale(9) + TextSize.cx,
                                   rc.bottom - Height);

  buffer[0] = '\0';
  if (SettingsMap().AutoZoom)
    _tcscat(buffer, _T("AUTO "));

  switch (follow_mode) {
  case FOLLOW_SELF:
    break;

  case FOLLOW_PAN:
    _tcscat(buffer, _T("PAN "));
    break;
  }

  const UIState &ui_state = CommonInterface::GetUIState();
  if (ui_state.auxiliary_enabled) {
    _tcscat(buffer, InfoBoxManager::GetCurrentPanelName());
    _tcscat(buffer, _T(" "));
  }

  if (Basic().gps.replay)
    _tcscat(buffer, _T("REPLAY "));
  else if (Basic().gps.simulator) {
    _tcscat(buffer, _("Simulator"));
    _tcscat(buffer, _T(" "));
  }

  if (SettingsComputer().BallastTimerActive) {
    TCHAR TEMP[20];
    _stprintf(TEMP, _T("BALLAST %d LITERS "),
              (int)SettingsComputer().glide_polar_task.GetBallastLitres());
    _tcscat(buffer, TEMP);
  }

  if (weather != NULL && weather->GetParameter() > 0) {
    const TCHAR *label = weather->ItemLabel(weather->GetParameter());
    if (label != NULL)
      _tcscat(buffer, label);
  }

  if (buffer[0]) {
    int y = rc.bottom - Height;

    canvas.select(Fonts::Title);
    canvas.background_opaque();
    canvas.set_background_color(COLOR_WHITE);

    canvas.text(0, y - canvas.text_size(buffer).cy, buffer);
  }
}
Beispiel #30
0
/**
 * "Boots" up XCSoar
 * @param hInstance Instance handle
 * @param lpCmdLine Command line string
 * @return True if bootup successful, False otherwise
 */
bool
XCSoarInterface::Startup(HINSTANCE hInstance)
{
  // Set the application title to "XCSoar"
  TCHAR szTitle[] = _T("XCSoar");

  // Store instance handle in our global variable
#ifdef WIN32
  ResourceLoader::Init(hInstance);
#endif

  //If "XCSoar" is already running, stop this instance
  if (MainWindow::find(szTitle))
    return false;

  // Register window classes
  PaintWindow::register_class(hInstance);
  MainWindow::register_class(hInstance);

  // Creates the main window
  LogStartUp(_T("Create main window"));
  PixelRect WindowSize = SystemWindowSize();
  main_window.set(szTitle,
                  WindowSize.left, WindowSize.top,
                  WindowSize.right, WindowSize.bottom);
  if (!main_window.defined())
    return false;

  main_window.Initialise();

#ifdef SIMULATOR_AVAILABLE
  // prompt for simulator if not set by command line argument "-simulator" or "-fly"
  if (!sim_set_in_cmd_line_flag) {
    SimulatorPromptResult result = dlgSimulatorPromptShowModal();
    switch (result) {
    case SPR_QUIT:
      return false;

    case SPR_FLY:
      global_simulator_flag = false;
      break;

    case SPR_SIMULATOR:
      global_simulator_flag = true;
      break;
    }
  }
#endif

  if (!LoadProfile())
    return false;

  ProgressGlue::Create(_("Initialising"));

  LoadDisplayOrientation();

  main_window.InitialiseConfigured();

  TCHAR path[MAX_PATH];
  LocalPath(path, _T("cache"));
  file_cache = new FileCache(path);

  Graphics::InitialiseConfigured(SettingsMap());

  ReadLanguageFile();

  status_messages.LoadFile();
  InputEvents::readFile();

  // Initialize DeviceBlackboard
  device_blackboard.Initialise();

  // Initialize Marks
  marks = new Marks();

  // Send the SettingsMap to the DeviceBlackboard
  SendSettingsMap();

  // Show the main and map windows
  LogStartUp(_T("Create map window"));
  main_window.show();
  main_window.map.show();

#ifdef HAVE_AYGSHELL_DLL
  const AYGShellDLL &ayg = main_window.ayg_shell_dll;
  ayg.SHSetAppKeyWndAssoc(VK_APP1, main_window);
  ayg.SHSetAppKeyWndAssoc(VK_APP2, main_window);
  ayg.SHSetAppKeyWndAssoc(VK_APP3, main_window);
  ayg.SHSetAppKeyWndAssoc(VK_APP4, main_window);
  // Typical Record Button
  //	Why you can't always get this to work
  //	http://forums.devbuzz.com/m_1185/mpage_1/key_/tm.htm
  //	To do with the fact it is a global hotkey, but you can with code above
  //	Also APPA is record key on some systems
  ayg.SHSetAppKeyWndAssoc(VK_APP5, main_window);
  ayg.SHSetAppKeyWndAssoc(VK_APP6, main_window);
#endif

  // Initialize main blackboard data
  task_manager = new TaskManager(task_events, way_points);
  task_manager->reset();

  protected_task_manager =
    new ProtectedTaskManager(*task_manager,
                             XCSoarInterface::SettingsComputer(),
                             task_events, airspace_database);

  airspace_warning = new AirspaceWarningManager(airspace_database,
                                                *task_manager);
  airspace_warnings = new ProtectedAirspaceWarningManager(*airspace_warning);

  // Read the terrain file
  ProgressGlue::Create(_("Loading Terrain File..."));
  LogStartUp(_T("OpenTerrain"));
  terrain = RasterTerrain::OpenTerrain(file_cache);

  glide_computer = new GlideComputer(way_points, *protected_task_manager,
                                     *airspace_warnings,
                                     task_events);
  glide_computer->set_terrain(terrain);
  glide_computer->SetLogger(&logger);
  glide_computer->Initialise();

  replay = new Replay(*protected_task_manager);

  // Load the EGM96 geoid data
  OpenGeoid();

  GlidePolar &gp = SetSettingsComputer().glide_polar_task;
  gp = GlidePolar(fixed_zero);
  PolarGlue::LoadFromProfile(gp, SetSettingsComputer());
  task_manager->set_glide_polar(gp);

  task_manager->set_contest(SettingsComputer().contest);

  // Read the topography file(s)
  topography = new TopographyStore();
  LoadConfiguredTopography(*topography);

  // Read the waypoint files
  WayPointGlue::LoadWaypoints(way_points, terrain);

  // Read and parse the airfield info file
  ReadAirfieldFile(way_points);

  // Set the home waypoint
  WayPointGlue::SetHome(way_points, terrain, SetSettingsComputer(),
                        false);

  // ReSynchronise the blackboards here since SetHome touches them
  ReadBlackboardBasic(device_blackboard.Basic());

  // Scan for weather forecast
  ProgressGlue::Create(_("Scanning weather forecast"));
  LogStartUp(_T("RASP load"));
  RASP.ScanAll(Basic().Location);

  // Reads the airspace files
  ReadAirspace(airspace_database, terrain, SettingsComputer().pressure);

  const AIRCRAFT_STATE aircraft_state =
    ToAircraftState(device_blackboard.Basic(), device_blackboard.Calculated());
  airspace_warning->reset(aircraft_state);
  airspace_warning->set_config(CommonInterface::SettingsComputer().airspace.warnings);

  // Read the FLARM details file
  FlarmDetails::Load();

#ifndef DISABLEAUDIOVARIO
  /*
  VarioSound_Init();
  VarioSound_EnableSound(EnableSoundVario);
  VarioSound_SetVdead(SoundDeadband);
  VarioSound_SetV(0);
  VarioSound_SetSoundVolume(SoundVolume);
  */
#endif

  // Start the device thread(s)
  ProgressGlue::Create(_("Starting devices"));
  devStartup();

/*
  -- Reset polar in case devices need the data
  LogStartUp(_T("GlidePolar::UpdatePolar"));
  GlidePolar::UpdatePolar(true, SettingsComputer());

  This should be done inside devStartup if it is really required
*/

  ProgressGlue::Create(_("Initialising display"));

  main_window.map.set_way_points(&way_points);
  main_window.map.set_task(protected_task_manager);
  main_window.map.set_airspaces(&airspace_database, airspace_warnings);

  main_window.map.set_topography(topography);
  main_window.map.set_terrain(terrain);
  main_window.map.set_weather(&RASP);
  main_window.map.set_marks(marks);
  main_window.map.SetLogger(&logger);

  // Finally ready to go.. all structures must be present before this.

  // Create the drawing thread
#ifndef ENABLE_OPENGL
  LogStartUp(_T("CreateDrawingThread"));
  draw_thread = new DrawThread(main_window.map, main_window.flarm,
                               main_window.ta);
  draw_thread->start();
#endif

  // Show the infoboxes
  LogStartUp(_T("ShowInfoBoxes"));
  InfoBoxManager::Show();

  // Create the calculation thread
  LogStartUp(_T("CreateCalculationThread"));
  CreateCalculationThread();

  // Find unique ID of this PDA
  ReadAssetNumber();

  LogStartUp(_T("ProgramStarted"));

  // Give focus to the map
  main_window.map.set_focus();

  Pages::LoadFromProfile();

  // Start calculation thread
  calculation_thread->start();

  globalRunningEvent.trigger();

  AfterStartup();

#ifndef ENABLE_OPENGL
  draw_thread->resume();
#endif

  return true;
}