Example #1
0
void GEUIDialog::SetCursorLatLon(double lat, double lon)
{
      LogDebugMessage(wxString::Format(_T("Following the cursor to %f, %f requested"), lat, lon));
      DetachIfNeeded(m_camera_azimuth, m_camera_range, m_camera_tilt);
      if (!m_cbConnected->GetValue())
      {
            LogDebugMessage(_T("Not following as the checkbox is not checked"));
            return;
      }
      m_hotspot_lon = lon;
      m_hotspot_lat = lat;

      GEMoveCamera();
}
Example #2
0
int RunSystemCommand(const gxString &input_command, const gxString &user, const gxString &group)
{
  gxString superuser = "******";
  gxString command;
  if(servercfg->cluster_user == superuser) {
#ifdef __HAS_SU_DASH_G__
    command << clear << "su -g " << group << " -c \'" << input_command << "\' - " << user << " >/dev/null 2>&1";
#else
    command << clear << "su -c \'" << input_command << "\' - " << user << " >/dev/null 2>&1";
#endif
  }
  else {
#ifdef __HAS_SU_DASH_G__
    command << clear << servercfg->sudo_command 
	    << " \"su -g " << group << " -c \'" << input_command << "\' - " << user << "\""; 
#else
    command << clear << servercfg->sudo_command 
	    << " \"su -c \'" << input_command << "\' - " << user << "\""; 
#endif
  }

  if(servercfg->debug && servercfg->debug_level >= 5) {
    LogDebugMessage(command.c_str());
  }

  return system(command.c_str());
} 
// Discover the components that should be explicitly included.
// These are any included top components.
void GoogleVssClient::DiscoverExplicitelyIncludedComponents() {
  LogDebugMessage(L"Discover explicitly included components ...");
  // Enumerate all writers.
  for (unsigned idx = 0; idx < writers_.size(); idx++) {
    VssWriter* writer = &writers_[idx];
    if (writer->isExcluded) {
      continue;
    }
    // Compute the roots of included components.
    for (unsigned i = 0; i < writer->components.size(); i++) {
      VssComponent* component = &(writer->components[i]);
      if (!component->CanBeExplicitlyIncluded()) {
        continue;
      }
      // Test if our component has a parent that is also included.
      component->isExplicitlyIncluded = true;
      for (unsigned j = 0; j < writer->components.size(); j++) {
        VssComponent* ancestor = &(writer->components[j]);
        if (ancestor->IsAncestorOf(*component) &&
            ancestor->CanBeExplicitlyIncluded()) {
          // This cannot be explicitely included since we have another
          // ancestor that that must be implictely or explicitely included.
          component->isExplicitlyIncluded = false;
          break;
        }
      }
    }
  }
}
Example #4
0
bool gecomapi_pi::LoadConfig(void)
{
      wxFileConfig *pConf = (wxFileConfig *)m_pconfig;

      if(pConf)
      {
            pConf->SetPath( _T("/PlugIns/GoogleEarth") );

            wxString config;

            pConf->Read( _T( "WindowWidth" ), &m_iWindowWidth, DEFAULT_WIDTH );
            pConf->Read( _T( "WindowHeight" ), &m_iWindowHeight, DEFAULT_HEIGHT );
            pConf->Read( _T( "WindowFloating" ), &m_bWindowFloating, DEFAULT_FLOATING );
            pConf->Read( _T( "AlwaysStartHidden" ), &m_bstartHidden, true );
            pConf->Read( _T( "DisconnectOnGEAction" ), &m_bdisconnectOnGEAction, true );
            pConf->Read( _T( "UpdateSettingsFromGE" ), &m_bupdateSettingsFromGE, true );
            pConf->Read( _T( "ShowBoatInGE" ), &m_bShowBoatInGE, true );
            pConf->Read( _T( "WhatToFollow" ), &m_iWhatToFollow, GECOMAPI_FOLLOW_VIEW ); //1-Cursor, 2-boat, 3-View, 0-Nothing
            pConf->Read( _T( "CameraAzimuth" ), &m_iCameraAzimuth, 0 );
            pConf->Read( _T( "CameraTilt" ), &m_iCameraTilt, 0 );
            pConf->Read( _T( "CameraRange" ), &m_iCameraRange, 0 );
            pConf->Read( _T( "WindowOpacity" ), &m_iOpacity, 255 );
            LogDebugMessage(wxString::Format(_T("Config params loaded: WW=%d, ASH=%d, DGA=%d, USG=%d, SB=%d, WF=%d, Az=%d, Ti=%d, Ra=%d, Opa=%d"), 
                  m_iWindowWidth, m_bstartHidden, m_bdisconnectOnGEAction, m_bupdateSettingsFromGE, m_bShowBoatInGE, 
                  m_iWhatToFollow, m_iCameraAzimuth, m_iCameraTilt, m_iCameraRange, m_iOpacity));
            return true;
      }
      else
            return false;
}
Example #5
0
bool gecomapi_pi::SaveConfig(void)
{
      wxFileConfig *pConf = (wxFileConfig *)m_pconfig;

      if(pConf)
      {
            pConf->SetPath( _T( "/PlugIns/GoogleEarth" ) );
            pConf->Write( _T( "WindowWidth" ), m_iWindowWidth );
            pConf->Write( _T( "WindowHeight" ), m_iWindowHeight );
            pConf->Write( _T( "WindowFloating" ), m_bWindowFloating );
            pConf->Write( _T( "AlwaysStartHidden" ), m_bstartHidden );
            pConf->Write( _T( "DisconnectOnGEAction" ), m_bdisconnectOnGEAction );
            pConf->Write( _T( "UpdateSettingsFromGE" ), m_bupdateSettingsFromGE );
            pConf->Write( _T( "ShowBoatInGE" ), m_bShowBoatInGE );
            pConf->Write( _T( "WhatToFollow" ), m_iWhatToFollow );
            pConf->Write( _T( "CameraAzimuth" ), m_iCameraAzimuth );
            pConf->Write( _T( "CameraTilt" ), m_iCameraTilt );
            pConf->Write( _T( "CameraRange" ), m_iCameraRange );
            pConf->Write( _T( "WindowOpacity" ), m_iOpacity );
            LogDebugMessage(wxString::Format(_T("Config params saved: WW=%d, ASH=%d, DGA=%d, USG=%d, SB=%d, WF=%d, Az=%d, Ti=%d, Ra=%d, Opa=%d"), 
                  m_iWindowWidth, m_bstartHidden, m_bdisconnectOnGEAction, m_bupdateSettingsFromGE, m_bShowBoatInGE, 
                  m_iWhatToFollow, m_iCameraAzimuth, m_iCameraTilt, m_iCameraRange, m_iOpacity));
            return true;
      }
      else
            return false;
}
Example #6
0
GEUIDialog::GEUIDialog(wxWindow *pparent, wxWindowID id, wxAuiManager *auimgr, int tbitem, gecomapi_pi *ppi)
      :wxPanel(pparent, id, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE, _T("GoogleEarth"))
{
      pPlugIn = ppi;
      LogDebugMessage(_T("Constructing the GE plugin window"));
      m_pauimgr = auimgr;
      m_toolbar_item_id = tbitem;
      m_ballowStart = false;
      m_bshouldcatchup = true;
      m_bbusy = false;

      m_pfocusedwindow = FindFocus();
      GEParentHwnd = NULL;

      this->SetSizeHints( wxDefaultSize, wxDefaultSize );

      itemBoxSizer = new wxBoxSizer(wxVERTICAL);
      SetSizerAndFit(itemBoxSizer);

      m_panel1 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
	itemBoxSizer->Add( m_panel1, 1, wxEXPAND | wxALL, 5 );

      itemBoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
      itemBoxSizer->Add(itemBoxSizer1, 0, wxEXPAND);

      m_cbConnected = new wxCheckBox( this, wxID_ANY, _("Connected to chart viewport"), wxDefaultPosition, wxDefaultSize, 0 );
	itemBoxSizer1->Add( m_cbConnected, 0, wxALIGN_RIGHT|wxALL, 10 );

      m_buttonSave = new wxButton( this, wxID_ANY, _("Save view..."), wxDefaultPosition, wxDefaultSize, 0 );
      itemBoxSizer1->Add( m_buttonSave, 0, wxALIGN_RIGHT|wxBOTTOM|wxLEFT|wxRIGHT|wxTOP, 5 );
	
	this->Layout();
	
	this->Centre( wxBOTH );

      Connect(this->GetId(), wxEVT_SIZE, wxSizeEventHandler(GEUIDialog::OnSize));
      Connect(this->GetId(), wxEVT_SHOW, wxShowEventHandler(GEUIDialog::OnShow));
      
      app = NULL;

      m_bgeisuseable = false;
      m_binitializing = false;
      m_bclosed = false;
      m_bisfollowingboat = false;

      //LogDebugMessage(_T("GE plugin window created, going to start GE"));
      //GEInitialize();
      m_buttonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GEUIDialog::SaveView ), NULL, this );
      m_cbConnected->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( GEUIDialog::ConnectedClicked ), NULL, this );

      ConnectToGE();

      m_stopwatch.Start();
      m_stopwatch_boat.Start();
      m_pPositions = new PositionsList();
      m_sEnvelopeKmlFilename = wxStandardPaths::Get().GetTempDir() + _T("\\gecomapi.kml");
      m_sLiveKmlFilename = wxStandardPaths::Get().GetTempDir() + _T("\\gecomapilive.kml");

      m_pdialog = new GESaveViewDlgImpl(this,  wxID_ANY, _("Save view"), wxDefaultPosition, wxSize( -1,-1 ), wxDEFAULT_DIALOG_STYLE );
}
Example #7
0
void GEUIDialog::OnShow(wxShowEvent& event)
{
      LogDebugMessage(_T("GE plugin - OnShow event"));
      if(m_ballowStart)
            GEInitialize();
      SetToolbarItemState(m_toolbar_item_id, IsShown());
      
      event.Skip();
}
// Discover excluded writers. These are writers that:
// - either have a top-level nonselectable excluded component,
// - do not have any included components while all its components are excluded.
void GoogleVssClient::DiscoverExcludedWriters() {
  LogDebugMessage(L"Discover excluded writers ...");
  // Enumerate writers.
  for (unsigned idx = 0; idx < writers_.size(); idx++) {
    VssWriter* writer = &writers_[idx];
    if (writer->isExcluded) {
      continue;
    }
    // Discover if we have any:
    // - non-excluded selectable components,
    // - non-excluded top-level non-selectable components.
    // If we have none, then the whole writer must be excluded from the backup.
    writer->isExcluded = true;
    for (unsigned i = 0; i < writer->components.size(); i++) {
      VssComponent* component = &(writer->components[i]);
      if (component->CanBeExplicitlyIncluded()) {
        writer->isExcluded = false;
        break;
      }
    }
    // No included components were found.
    if (writer->isExcluded) {
      LogDebugMessage(
          L"The writer '%s' is now excluded from the backup (it does not "
          L"contain any components that should be included in the backup).",
          writer->name.c_str());
      continue;
    }
    // Now, discover if we have any top-level excluded non-selectable component.
    // If this is true, then the whole writer must be excluded from the backup.
    for (unsigned i = 0; i < writer->components.size(); i++) {
      VssComponent* component = &(writer->components[i]);
      if (component->isTopLevel && !component->isSelectable &&
          component->isExcluded) {
        LogDebugMessage(
            L"The writer '%s' is now excluded from the backup (the top-level "
            L"non-selectable component '%s' is an excluded component).",
            writer->name.c_str(), component->fullPath.c_str());
        writer->isExcluded = true;
        break;
      }
    }
  }
}
Example #9
0
void GEUIDialog::OnSize ( wxSizeEvent& event )
{
      LogDebugMessage(_T("GE plugin - OnSize event"));
      GEResize();
      if (m_pfocusedwindow)
            m_pfocusedwindow->SetFocus(); //returns focus - don't know why, but seems needed

      pPlugIn->m_iWindowWidth = this->GetSize().GetWidth();
      pPlugIn->m_iWindowHeight = this->GetSize().GetHeight();
      event.Skip();
}
Example #10
0
bool GEUIDialog::GEReadViewParameters(double& lat, double& lon, double& alt, double& azimuth, double& range, double& tilt)
{
      LogDebugMessage(_T("GE View parameters requested"));
      while ( m_bbusy ) ;
      m_bbusy = true;
      int interval = m_stopwatch.Time();
      if (interval > CAMERA_MOVE_INTERVAL * 10)
            m_stopwatch.Start(); //Things got crazy, it's time to let it settle down...
      if(NULL != app && m_bgeisuseable)
      {
            LogDebugMessage(_T("Getting GE view parameters"));
            try
            {
                  ICameraInfoGE* camera;
                  app->raw_GetCamera(false, &camera);
                  if (NULL != camera)
                  {
                        lat = camera->FocusPointLatitude;
                        lon = camera->FocusPointLongitude;
                        alt = camera->FocusPointAltitude;
                        azimuth = camera->Azimuth;
                        range = camera->Range;
                        tilt = camera->Tilt;
                  }
                  else
                  {
                        m_bgeisuseable = false;
                        app = NULL;
                  }
            }
            catch(...) {
                  LogDebugMessage(_T("Error geting GE view parameters"));
            }
            LogDebugMessage(wxString::Format(_T("GE view parameters obtained: lat=%f, lon=%f, alt=%f, azimuth=%f, range=%f, tilt=%f"), lat, lon, alt, azimuth, range, tilt));
            m_bbusy = false;
            return true;
      }
      m_bbusy = false;
      return false;
}
Example #11
0
void gecomapi_pi::SetCurrentViewPort(PlugIn_ViewPort &vp)
{
      if (vp.clat == m_pastVp.clat && vp.clon == m_pastVp.clon && vp.pix_height == m_pastVp.pix_height && vp.pix_width == m_pastVp.pix_width && vp.rotation == m_pastVp.rotation && vp.chart_scale == m_pastVp.chart_scale && 
            vp.lat_max == m_pastVp.lat_max && vp.lat_min == m_pastVp.lat_min && vp.lon_max == m_pastVp.lon_max && vp.lon_min == m_pastVp.lon_min && vp.view_scale_ppm == m_pastVp.view_scale_ppm)
      {
            return; //Prevents event storm killing the responsiveness. At least in course-up it looks needed.
      }
      m_pastVp = vp;
      if (m_bshuttingDown)
            return;
      LogDebugMessage(_T("SetCurrentViewPort called by OpenCPN"));
      if(m_iWhatToFollow == GECOMAPI_FOLLOW_VIEW && m_pgecomapi_window)
      {
            m_pgecomapi_window->SetViewPort(vp.clat, vp.clon, vp.lat_max - vp.lat_min, vp.lon_max - vp.lon_min, vp.rotation);
      }
}
// Removes entries from the system registry.
STDAPI DllUnregisterServer(void) {
  CComPtr<IVssAdmin> vssAdmin;
  HRESULT hr = CoCreateInstance(
      CLSID_VSSCoordinator, NULL, CLSCTX_ALL, IID_IVssAdmin,
      reinterpret_cast<void**>(&vssAdmin));
  if (SUCCEEDED(hr)) {
    hr = vssAdmin->UnregisterProvider(kGooglsVssProviderId);
    if (FAILED(hr)) {
      LogDebugMessage(L"Error(%x) was returned calling UnregisterProvider.",
                      hr);
    }
  }
  hr = _AtlModule.DllUnregisterServer();
  vssAdmin.Release();
  return hr;
}
Example #13
0
int RunSystemCommand(const gxString &input_command)
{
  gxString superuser = "******";
  gxString command;
  if(servercfg->cluster_user == superuser) {
    command = input_command;
  }
  else {
    command << clear << servercfg->sudo_command << " \'" << input_command << "\'";
  }

  if(servercfg->debug && servercfg->debug_level >= 5) {
    LogDebugMessage(command.c_str());
  }

  return system(command.c_str());
} 
Example #14
0
BOOL RTT4TCPAccessor::SetConnectingSocket(const SOCKET& socketHandler, const struct sockaddr_in* pAddress)
{
	BOOL bUse = TRUE;
	setsockopt(socketHandler, SOL_SOCKET, SO_REUSEADDR, (const char*)&bUse, sizeof(bUse));
	int nResult = 0;

	TCHAR szError[BUFFER_SIZE] = {0};

	nResult = connect(socketHandler, (const sockaddr*)pAddress, sizeof(*pAddress));
	if (nResult == SOCKET_ERROR) {
		_stprintf_s(szError, _countof(szError), _T("[ERROR] connect() : %d"), WSAGetLastError());
		ReportError(szError);
		LogDebugMessage(Log_Error, szError);
		closesocket(socketHandler);
		return FALSE;
	}
	return TRUE;
}
Example #15
0
bool GEUIDialog::GEMoveCamera()
{
      LogDebugMessage(wxString::Format(_T("GE camera move to %f, %f requested"), m_hotspot_lat, m_hotspot_lon, m_camera_range, m_camera_tilt, m_camera_azimuth));
      int interval = m_stopwatch.Time();
      m_prev_camera_azimuth = m_camera_azimuth;
      m_prev_camera_range = m_camera_range;
      m_prev_camera_tilt = m_camera_tilt;
      if (m_bbusy)
      {
            LogDebugMessage(_T("GE camera move request discarded, GE busy"));
            m_bshouldcatchup = true;
            return false;
      }
      if (interval < CAMERA_MOVE_INTERVAL) // If it is less than CAMERA_MOVE_INTERVAL since last request, don't move the camera
      {
            LogDebugMessage(_T("GE camera move request discarded, too soon after a previous action"));
            m_bshouldcatchup = true;
            return false;
      }
      m_stopwatch.Start();
      if(NULL != app && m_bgeisuseable)
      {
            LogDebugMessage(_T("Moving GE camera"));
            //app->raw_GetCamera(false, &camera);
            //camera->PutFocusPointLatitude(m_hotspot_lat);
            //camera->PutFocusPointLongitude(m_hotspot_lon);
            //camera->PutAzimuth(m_camera_azimuth); //north up
            //camera->PutFocusPointAltitude(0.0); //focus point on sea level
            //camera->PutRange(m_camera_range); //camera 1000 meters high
            //camera->PutTilt(0.0); //camera directly over a focus point
            //app->raw_SetCamera(camera, 1.0); //1.0 - how fast the camera gets there

            try 
            {
                  app->SetCameraParams(m_hotspot_lat, m_hotspot_lon, 0.0, AbsoluteAltitudeGE, m_camera_range, m_camera_tilt, m_camera_azimuth, 5.0);
                  LogDebugMessage(_T("GE camera moved"));
            }
            catch(...) {
                  LogDebugMessage(_T("Error moving GE camera"));
                  return false;
            }
            return true;
      }
      LogDebugMessage(_T("Not moving the camera, GE looks unusable"));
      return false;
}
Example #16
0
SOCKET RTT4TCPAccessor::InitializeTCPSocket(struct sockaddr_in* pAddress, LPCSTR szAddress, BOOL bSend, USHORT uPort)
{
	SOCKET socketHandler;
	TCHAR szError[BUFFER_SIZE];

	socketHandler = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (socketHandler == INVALID_SOCKET) {
		_stprintf_s(szError, _countof(szError), _T("[ERROR] socket() : %d"), WSAGetLastError());
		ReportError(szError);
		LogDebugMessage(Log_Error, szError);
		return socketHandler;
	}

	pAddress->sin_family = AF_INET;
	pAddress->sin_port = htons(uPort);
	if (bSend) {
		pAddress->sin_addr.S_un.S_addr = inet_addr(szAddress);
	} else {
		pAddress->sin_addr.S_un.S_addr = INADDR_ANY;
	}
	return socketHandler;
}
// Check the status for all selected writers.
HRESULT GoogleVssClient::CheckSelectedWriterStatus() {
  // Gather writer status to detect potential errors.
  HRESULT hr = GatherWriterStatus();
  if (SUCCEEDED(hr)) {
    // Gets the number of writers in the gathered status info
    // (WARNING: GatherWriterStatus must be called before).
    unsigned writers = 0;
    hr = vss_object_->GetWriterStatusCount(&writers);
    if (FAILED(hr)) {
      LogDebugMessage(L"GetWriterStatusCount failed with error %x ", hr);
    } else {
      // Enumerate each writer.
      HRESULT hrWriterFailure = S_OK;
      for (unsigned writer = 0; writer < writers; writer++) {
        VSS_ID idInstance = GUID_NULL;
        VSS_ID idWriter = GUID_NULL;
        VSS_WRITER_STATE writerStatus = VSS_WS_UNKNOWN;
        CComBSTR bstrWriterName;
        // Get writer status.
        hr = vss_object_->GetWriterStatus(writer, &idInstance, &idWriter,
                                          &bstrWriterName, &writerStatus,
                                          &hrWriterFailure);
        // If the writer is not selected, just continue.
        if (!IsWriterSelected(idInstance)) {
          continue;
        }
        // If the writer is in non-stable state, break.
        switch (writerStatus) {
          case VSS_WS_FAILED_AT_IDENTIFY:
          case VSS_WS_FAILED_AT_PREPARE_BACKUP:
          case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT:
          case VSS_WS_FAILED_AT_FREEZE:
          case VSS_WS_FAILED_AT_THAW:
          case VSS_WS_FAILED_AT_POST_SNAPSHOT:
          case VSS_WS_FAILED_AT_BACKUP_COMPLETE:
          case VSS_WS_FAILED_AT_PRE_RESTORE:
          case VSS_WS_FAILED_AT_POST_RESTORE:
            // Print writer status.
            LogDebugMessage(
                L"ERROR: Selected writer '%s' is in failed state."
                L" Status: %d (%s), Writer Failure code: 0x%08lx,"
                L" Writer ID: " WSTR_GUID_FMT L" Instance ID: " WSTR_GUID_FMT,
                BstrToWString(bstrWriterName).c_str(), writerStatus,
                GetStringFromWriterStatus(writerStatus).c_str(),
                hrWriterFailure,
                GUID_PRINTF_ARG(idWriter), GUID_PRINTF_ARG(idInstance));
            // Stop here.
            hr = E_UNEXPECTED;
            break;
          default:
            break;
        }
        if (FAILED(hr)) {
          break;
        }
      }
    }
  }
  LogDebugMessage(L"CheckSelectedWriterStatus returned with %x", hr);
  return hr;
}
Example #18
0
void GEUIDialog::GEInitialize()
{
      LogDebugMessage(_T("GE initialization requested"));
      if (NULL == app && !m_bgeisuseable & !m_binitializing & !m_bclosed) 
      {
            m_binitializing = true;
            LogDebugMessage(_T("Initializing GE"));
            if (pPlugIn->IsProcessRunningByName(_T("googleearth.exe")))
            {
                  LogDebugMessage(_T("GE found running, killing it"));
                  if (pPlugIn->KillProcessByName(_T("googleearth.exe")))
                        LogDebugMessage(_T("GE killed"));
                  else
                        LogDebugMessage(_T("GE kill attempt failed"));
            }
            try
            {
                  CoInitialize(NULL);
                  HRESULT	hr;

                  hr = CoCreateInstance(
		            CLSID_ApplicationGE,
		            NULL, //0,
		            CLSCTX_LOCAL_SERVER,
		            IID_IApplicationGE,
		            (void**) &app); //reinterpret_cast<LPVOID *>( &app ));
	            if ( FAILED( hr )) {
		            LogDebugMessage(_T("Error %i while initializing GE"));
                        return;
	            }
                  LogDebugMessage(_T("We survived CoCreateInstance"));
                  Sleep(500);
                  long	is_initialized;
                  do {
	                  is_initialized = app->IsInitialized();
                  } while ( is_initialized == 0 );
                  LogDebugMessage(_T("We survived waiting for IsInitialized"));
                  Sleep(500);
                  m_bgeisuseable = true;
                  m_binitializing = false;
            }
            catch(...) {
                  LogDebugMessage(_T("Error initializing GE, we caught an exception"));
                  return;
            }
            LogDebugMessage(_T("GE Initialized, attaching to the window"));
            GEAttachWindow();
      }
      else
      {
            LogDebugMessage(_T("Not even trying to initialize GE"));
      }
}
Example #19
0
void GEUIDialog::GEShowBoat(double lat, double lon)
{
      LogDebugMessage(wxString::Format(_T("Show boat at %f, %f requested"), lat, lon));
      if ( m_bbusy )
      {
            LogDebugMessage(_T("Not showing, busy"));
            return;
      }
      int interval = m_stopwatch_boat.Time();
      if (interval < CAMERA_MOVE_INTERVAL * 5) // If it is less than CAMERA_MOVE_INTERVAL * 5 since last request, don't move the boat
      {
            LogDebugMessage(_T("Boat display request discarded, too soon after a previous action"));
            return;
      }
      m_stopwatch_boat.Start();
      if (m_pPositions->GetCount() > BOAT_POSITIONS_STORED)
            m_pPositions->Erase(m_pPositions->GetFirst());
      m_pPositions->Append(new PositionReport(lat, lon, wxDateTime::Now()));
      wxTextFile kml(m_sLiveKmlFilename);
      if(wxFile::Exists(m_sLiveKmlFilename))
      {
            kml.Open();
            kml.Clear();
      }
      else
      {
            kml.Create();
      }
      wxString coords;
      wxPositionsListNode *posn = m_pPositions->GetFirst();
      do
      {
            coords += wxString::Format(_T("%f,%f,0.000000\n"), posn->GetData()->longitude, posn->GetData()->latitude);
      } while (posn = posn->GetNext());
      if (pPlugIn->ShouldShowBoat())
            kml.AddLine(wxString::Format(LiveKml, 1, lon, lat, 1, coords));
      else
            kml.AddLine(wxString::Format(LiveKml, 0, lon, lat, 0, coords));
      kml.Write();
      kml.Close();
      if(NULL != app && m_bgeisuseable)
      {
            if (!m_bisfollowingboat && pPlugIn->ShouldShowBoat())
            {
                  if(wxFile::Exists(m_sEnvelopeKmlFilename))
                        wxRemoveFile(m_sEnvelopeKmlFilename);
                  wxTextFile kml(m_sEnvelopeKmlFilename);
                  kml.Create();
                  kml.AddLine(wxString::Format(EnvelopeKml, m_sLiveKmlFilename));
                  kml.Write();
                  kml.Close();
                  BSTR pdata = wxConvertStringToOle(m_sEnvelopeKmlFilename);
                  m_bbusy = true;
                  app->OpenKmlFile(pdata, 1);
                  m_bisfollowingboat = true;
            } 
            else if (m_bisfollowingboat && !pPlugIn->ShouldShowBoat())
            {
                  if(wxFile::Exists(m_sEnvelopeKmlFilename))
                        wxRemoveFile(m_sEnvelopeKmlFilename);
                  wxTextFile kml(m_sEnvelopeKmlFilename);
                  kml.Create();
                  kml.AddLine(EmptyKml);
                  kml.Write();
                  kml.Close();
                  BSTR pdata = wxConvertStringToOle(m_sEnvelopeKmlFilename);
                  m_bbusy = true;
                  app->OpenKmlFile(pdata, 1);
                  m_bisfollowingboat = false;
            }
            /*
            IFeatureGE* tp;
            app->raw_GetTemporaryPlaces(&tp);
            if ( tp )
            {
                  IFeatureCollectionGE* tps;
                  tp->raw_GetChildren(&tps);
                  if ( tps && tps->GetCount() > 0 )
                  {
                        //for (int i = 0; i < tps->Count; i++)
                        //{
                        //      tps->Item[i]->PutVisibility(0);
                        //}
                        try {
                              //FIXME: This works, BUT GE consumes enormous amounts of memory - really there is no way to change the properties of existing waypoint?
                              //Looks like ther isn't, so some trick like from http://groups.google.com/group/kml-support-com-api/browse_thread/thread/76c9f9f3ab5ff28f/4244ff5df01c5c25?lnk=gst&q=temporary+places# and http://bbs.keyhole.com/ubb/ubbthreads.php?ubb=showflat&Number=816832&site_id=1#import will be necessary
                              //Tutorial: http://code.google.com/intl/cs/apis/kml/documentation/kml_21tutorial.html#updates
                              tps->GetItem(tps->GetCount() - 1)->PutVisibility(false);
                        }
                        catch (...) {}
                  }
            }
            wxString kml = wxString::Format(_T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://earth.google.com/kml/2.0\">\n<Placemark>\n  <name>BOAT</name>\n  <visibility>1</visibility>\n  <Style>\n    <IconStyle>\n      <Icon>\n        <href>root://icons/palette-4.png</href>\n        <x>32</x>\n        <y>0</y>\n        <w>32</w>\n        <h>32</h>\n      </Icon>\n    </IconStyle>\n  </Style>\n  <Point>\n    <extrude>1</extrude>\n    <altitudeMode>relativeToGround</altitudeMode>\n    <coordinates>%f,%f,0</coordinates>\n  </Point>\n</Placemark>\n</kml>"), lon, lat);
            BSTR pdata = wxConvertStringToOle(kml);
            try 
            {
                  app->LoadKmlData(&pdata);
                  LogDebugMessage(_T("Shown"));
            }
            catch (...) 
            {
                  LogDebugMessage(_T("There was an error showing the boat"));
            }
            */
      }
      m_bbusy = false;
}