33 #include <wx/wxprec.h>
60 #include <X11/Xatom.h>
64 #if (defined(OCPN_GHC_FILESYSTEM) || (defined(__clang_major__) && (__clang_major__ < 15)))
66 #include <ghc/filesystem.hpp>
67 namespace fs = ghc::filesystem;
71 namespace fs = std::filesystem;
74 using namespace std::literals::chrono_literals;
76 #include <wx/apptrait.h>
77 #include <wx/arrimpl.cpp>
78 #include <wx/artprov.h>
79 #include <wx/aui/aui.h>
80 #include <wx/clrpicker.h>
81 #include <wx/cmdline.h>
82 #include <wx/dialog.h>
83 #include <wx/dialog.h>
85 #include <wx/display.h>
86 #include <wx/dynlib.h>
90 #include <wx/jsonreader.h>
91 #include <wx/listctrl.h>
93 #include <wx/printdlg.h>
95 #include <wx/progdlg.h>
96 #include <wx/settings.h>
97 #include <wx/stdpaths.h>
98 #include <wx/tokenzr.h>
100 #include "model/ais_decoder.h"
102 #include "model/certificates.h"
104 #include "model/comm_bridge.h"
105 #include "model/comm_n0183_output.h"
106 #include "model/comm_vars.h"
107 #include "model/config_vars.h"
108 #include "model/instance_check.h"
110 #include "model/logger.h"
111 #include "model/mDNS_query.h"
112 #include "model/mDNS_service.h"
113 #include "model/multiplexer.h"
114 #include "model/nav_object_database.h"
115 #include "model/navutil_base.h"
116 #include "model/own_ship.h"
117 #include "model/plugin_handler.h"
118 #include "model/route.h"
119 #include "model/routeman.h"
120 #include "model/select.h"
121 #include "model/track.h"
123 #include "AboutFrameImpl.h"
125 #include "ais_info_gui.h"
126 #include "AISTargetAlertDialog.h"
127 #include "AISTargetListDialog.h"
128 #include "AISTargetQueryDialog.h"
129 #include "CanvasConfig.h"
135 #include "ConfigMgr.h"
136 #include "DetailSlider.h"
139 #include "gdal/cpl_csv.h"
140 #include "glTexCache.h"
141 #include "GoToPositionDialog.h"
143 #include "MarkInfo.h"
145 #include "NMEALogWindow.h"
146 #include "observable.h"
147 #include "ocpn_app.h"
148 #include "OCPN_AUIManager.h"
149 #include "ocpn_frame.h"
150 #include "OCPNPlatform.h"
152 #include "rest_server_gui.h"
153 #include "route_ctx_factory.h"
154 #include "routemanagerdialog.h"
155 #include "routeman_gui.h"
156 #include "RoutePropDlgImpl.h"
158 #include "s57chart.h"
159 #include "S57QueryDialog.h"
160 #include "safe_mode_gui.h"
161 #include "SoundFactory.h"
164 #include "thumbwin.h"
165 #include "TrackPropDlg.h"
169 #include "glChartCanvas.h"
173 #include "model/macutils.h"
177 #include "model/garmin_protocol_mgr.h"
178 void RedirectIOToConsole();
181 #if defined(__WXMSW__) && defined (__MSVC__LEAK)
182 #include "Stackwalker.h"
185 #ifdef LINUX_CRASHRPT
186 #include "crashprint.h"
190 #include "androidUTIL.h"
192 #include "serial/serial.h"
197 const char*
const kUsage =
200 opencpn [-p] [-f] [-G] [-g] [-P] [-l <str>] [-u <num>] [-U] [-s] [GPX file ...]
201 opencpn --remote [-R] | -q] | -e] |-o <str>]
203 Options for starting opencpn
205 -c, --configdir=<dirpath> Use alternative configuration directory.
206 -p, --portable Run in portable mode.
207 -f, --fullscreen Switch to full screen mode on start.
208 -G, --no_opengl Disable OpenGL video acceleration. This setting will
210 -g, --rebuild_gl_raster_cache Rebuild OpenGL raster cache on start.
211 -D, --rebuild_chart_db Rescan chart directories and rebuild the chart database
212 -P, --parse_all_enc Convert all S-57 charts to OpenCPN's internal format on start.
213 -l, --loglevel=<str> Amount of logging: error, warning, message, info, debug or trace
214 -u, --unit_test_1=<num> Display a slideshow of <num> charts and then exit.
215 Zero or negative <num> specifies no limit.
217 -s, --safe_mode Run without plugins, opengl and other "dangerous" stuff
218 -W, --config_wizard Start with initial configuration wizard
220 Options manipulating already started opencpn
221 -r, --remote Execute commands on already running instance
222 -R, --raise Make running OpenCPN visible if hidden
223 -q, --quit Terminate already running opencpn
224 -e, --get_rest_endpoint Print rest server endpoint and exit.
225 -o, --open=<GPX file> Open file in running opencpn
228 GPX file GPX-formatted file with waypoints or routes.
255 WX_DEFINE_OBJARRAY(ArrayOfCDI);
260 bool g_bUpgradeInProcess;
273 int g_restore_stackindex;
274 int g_restore_dbindex;
275 double g_ChartNotRenderScaleFactor;
277 LayerList *pLayerList;
289 int g_nbrightness = 100;
291 bool bDBUpdateInProgress;
296 bool g_bshowToolbar =
true;
297 bool g_bexpert =
true;
298 bool g_bBasicMenus =
false;
300 bool bDrawCurrentValues;
302 wxString ChartListFileName;
303 wxString gWorldMapLocation, gDefaultWorldMapLocation;
304 wxString gWorldShapefileLocation;
305 wxString *pInit_Chart_Dir;
307 wxString g_SENCPrefix;
308 wxString g_UserPresLibData;
309 wxString g_VisibleLayers;
310 wxString g_InvisibleLayers;
311 wxString g_VisiNameinLayers;
312 wxString g_InVisiNameinLayers;
314 bool g_bcompression_wait;
315 bool g_FlushNavobjChanges;
316 int g_FlushNavobjChangesTimeout;
318 wxString g_uploadConnection;
325 int g_mem_total, g_mem_initial;
327 bool s_bSetSystemTime;
329 static unsigned int malloc_max;
331 wxDateTime g_start_time;
332 wxDateTime g_loglast_time;
333 static OcpnSound *_bells_sounds[] = {SoundFactory(), SoundFactory()};
334 std::vector<OcpnSound *> bells_sound(_bells_sounds, _bells_sounds + 2);
336 OcpnSound *g_anchorwatch_sound = SoundFactory();
338 double AnchorPointMinDist;
339 bool AnchorAlertOn1, AnchorAlertOn2;
347 wxPrintData *g_printData = (wxPrintData *)NULL;
350 wxPageSetupData *g_pageSetupData = (wxPageSetupData *)NULL;
352 bool g_bShowOutlines;
353 bool g_bShowDepthUnits;
356 bool g_bShowChartBar;
357 bool g_bShowActiveRouteHighway;
360 bool g_bPlayShipsBells;
361 bool g_bFullscreenToolbar;
363 bool g_bTransparentToolbar;
364 bool g_bTransparentToolbarInOpenGLOK;
365 int g_nAutoHideToolbar;
366 bool g_bAutoHideToolbar;
368 bool g_bPermanentMOBIcon;
369 bool g_bTempShowMenuBar;
371 int g_iNavAidRadarRingsNumberVisible;
372 bool g_bNavAidRadarRingsShown;
373 float g_fNavAidRadarRingsStep;
374 int g_pNavAidRadarRingsStepUnits;
375 bool g_bWayPointPreventDragging;
376 bool g_bConfirmObjectDelete;
377 wxColour g_colourOwnshipRangeRingsColour;
381 ColorScheme global_color_scheme = GLOBAL_COLOR_SCHEME_DAY;
383 wxArrayPtrVoid *UserColourHashTableArray;
384 wxColorHashMap *pcurrent_user_color_hash;
393 bool g_bfilter_cogsog;
394 int g_COGFilterSec = 1;
397 int g_ChartUpdatePeriod;
398 int g_SkewCompUpdatePeriod;
400 int g_lastClientRectx;
401 int g_lastClientRecty;
402 int g_lastClientRectw;
403 int g_lastClientRecth;
404 double g_display_size_mm;
405 std::vector<size_t> g_config_display_size_mm;
406 bool g_config_display_size_manual;
408 int g_GUIScaleFactor;
409 int g_ChartScaleFactor;
410 float g_MarkScaleFactorExp;
411 int g_last_ChartScaleFactor;
412 int g_ShipScaleFactor;
413 float g_ShipScaleFactorExp;
414 int g_ENCSoundingScaleFactor;
415 int g_ENCTextScaleFactor;
421 s57RegistrarMgr *m_pRegistrarMan;
426 #include "model/macutils.h"
435 extern bool s_glu_dll_ready;
436 extern HINSTANCE s_hGLU_DLL;
442 double g_ownship_predictor_minutes;
443 double g_ownship_HDTpredictor_miles;
444 int g_cog_predictor_style;
445 wxString g_cog_predictor_color;
446 int g_cog_predictor_endmarker;
447 int g_ownship_HDTpredictor_style;
448 wxString g_ownship_HDTpredictor_color;
449 int g_ownship_HDTpredictor_endmarker;
450 int g_ownship_HDTpredictor_width;
452 bool g_own_ship_sog_cog_calc;
453 int g_own_ship_sog_cog_calc_damp_sec;
458 int g_iSoundDeviceIndex;
460 int g_S57_dialog_sx, g_S57_dialog_sy;
464 int g_nframewin_posx;
465 int g_nframewin_posy;
468 bool g_bAutoAnchorMark;
471 long gStart_LMT_Offset;
473 wxArrayString *pMessageOnceArray;
475 bool g_bUseGLL =
true;
482 int g_COGAvgSec = 15;
488 bool g_bsmoothpanzoom;
490 double g_overzoom_emphasis_base;
491 bool g_oz_vector_scale;
492 double g_plus_minus_zoom_factor;
495 bool g_b_legacy_input_filter_behaviour;
502 bool g_bFullScreenQuilt =
true;
507 ChartGroupArray *g_pGroupArray;
511 std::vector<std::string> TideCurrentDataSet;
512 wxString g_TCData_Dir;
514 bool g_boptionsactive;
516 bool g_bDeferredInitDone;
517 int options_lastPage = 0;
518 int options_subpage = 0;
520 wxPoint options_lastWindowPos(0, 0);
521 wxSize options_lastWindowSize(0, 0);
524 bool g_bsimplifiedScalebar;
526 int osMajor, osMinor;
528 bool GetMemoryStatus(
int *mem_total,
int *mem_used);
532 int g_nAIS_activity_timer;
534 bool g_bEnableZoomToCursor;
537 bool g_bDeferredStartTrack;
538 bool g_bHighliteTracks;
539 wxColour g_colourTrackLineColour;
540 wxString g_default_wp_icon;
543 double g_TrackIntervalSeconds;
545 int g_cm93_zoom_factor;
547 bool g_bShowDetailSlider;
548 int g_detailslider_dialog_x, g_detailslider_dialog_y;
550 bool g_bUseGreenShip;
555 bool g_b_overzoom_x =
true;
557 int g_OwnShipIconType;
558 double g_n_ownship_length_meters;
559 double g_n_ownship_beam_meters;
560 double g_n_gps_antenna_offset_y;
561 double g_n_gps_antenna_offset_x;
562 int g_n_ownship_min_mm;
565 bool g_bPreserveScaleOnX;
568 about *g_pAboutDlgLegacy;
570 #if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
571 wxLocale *plocale_def_lang = 0;
575 wxString g_localeOverride;
576 bool g_b_assume_azerty;
582 bool g_bShowStatusBar;
588 int g_AisTargetList_count;
589 bool g_bAisTargetList_autosort;
594 wxAuiDefaultDockArt *g_pauidockart;
596 wxString g_toolbarConfig = _T(
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
601 long g_maintoolbar_orient;
602 float g_toolbar_scalefactor;
604 float g_compass_scalefactor;
606 bool g_bShowCompassWin;
608 bool g_benable_rotate;
616 double gQueryVar = 361.0;
618 char bells_sound_file_name[2][12] = {
"1bells.wav",
"2bells.wav"};
620 int portaudio_initialized;
622 char nmea_tick_chars[] = {
'|',
'/',
'-',
'\\',
'|',
'/',
'-',
'\\'};
625 int g_sticky_projection;
627 int n_NavMessageShown;
628 wxString g_config_version_string;
630 wxString g_CmdSoundString;
635 bool b_inCompressAllCharts;
639 int g_chart_zoom_modifier_raster;
640 int g_chart_zoom_modifier_vector;
643 bool g_bAdvanceRouteWaypointOnArrivalOnly;
645 bool g_bSpaceDropMark;
647 wxArrayString g_locale_catalog_array;
648 bool b_reloadForPlugins;
649 bool g_btrackContinuous;
651 unsigned int g_canvasConfig;
653 bool g_bmasterToolbarFull =
true;
655 int g_AndroidVersionCode;
660 WX_DEFINE_ARRAY_PTR(
ChartCanvas *, arrayofCanvasPtr);
662 arrayofCanvasPtr g_canvasArray;
663 wxString g_lastAppliedTemplateGUID;
668 bool b_inCloseWindow;
669 extern int ShowNavWarning();
671 #ifdef LINUX_CRASHRPT
681 DEFINE_GUID(GARMIN_DETECT_GUID, 0x2c9c45c2L, 0x8e7d, 0x4c08, 0xa1, 0x2d, 0x81,
682 0x6b, 0xba, 0xe7, 0x22, 0xc0);
686 #define _CRTDBG_MAP_ALLOC
689 #define DEBUG_NEW new (_NORMAL_BLOCK, __FILE__, __LINE__)
690 #define new DEBUG_NEW
694 static const long long lNaN = 0xfff8000000000000;
695 #define NAN (*(double *)&lNaN)
699 void appendOSDirSlash(wxString *pString);
701 void InitializeUserColors(
void);
702 void DeInitializeUserColors(
void);
703 void SetSystemColors(ColorScheme cs);
705 static bool LoadAllPlugIns(
bool load_enabled) {
706 g_Platform->ShowBusySpinner();
707 bool b = PluginLoader::getInstance()->
LoadAllPlugIns(load_enabled);
708 g_Platform->HideBusySpinner();
716 #if defined(__WXGTK__) || defined(__WXQT__)
717 #include "bitmaps/opencpn.xpm"
721 wxString newPrivateFileName(wxString,
const char *name,
722 [[maybe_unused]]
const char *windowsName) {
723 wxString fname = wxString::FromUTF8(name);
724 wxString filePathAndName;
727 if (filePathAndName.Last() != wxFileName::GetPathSeparator())
728 filePathAndName.Append(wxFileName::GetPathSeparator());
731 wxString fwname = wxString::FromUTF8(windowsName);
732 filePathAndName.Append(fwname);
734 filePathAndName.Append(fname);
737 return filePathAndName;
747 BEGIN_EVENT_TABLE(
MyApp, wxApp)
748 EVT_ACTIVATE_APP(MyApp::OnActivateApp)
751 static
void ActivateRoute(const std::
string &guid) {
752 Route *route = g_pRouteMan->FindRouteByGUID(guid);
754 wxLogMessage(
"Cannot activate guid: no such route");
757 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
762 if (wxNOT_FOUND == route->m_RouteNameString.Find(
"MOB")) {
763 point = g_pRouteMan->FindBestActivatePoint(route, gLat, gLon, gCog, gSog);
765 point = route->GetPoint(2);
767 g_pRouteMan->ActivateRoute(route, point);
769 route->m_bRtIsSelected =
false;
772 static void ReverseRoute(
const std::string &guid) {
773 Route *route = g_pRouteMan->FindRouteByGUID(guid);
775 wxLogMessage(
"Cannot activate guid: no such route");
783 void MyApp::InitRestListeners() {
784 auto activate_route = [&](wxCommandEvent ev) {
785 auto guid = ev.GetString().ToStdString();
786 ActivateRoute(guid); };
787 rest_activate_listener.Init(m_rest_server.activate_route, activate_route);
788 auto reverse_route = [&](wxCommandEvent ev) {
789 auto guid = ev.GetString().ToStdString();
790 ReverseRoute(guid); };
791 rest_reverse_listener.Init(m_rest_server.reverse_route, reverse_route);
794 bool MyApp::OpenFile(
const std::string& path) {
796 auto result = nav_objects.load_file(path.c_str());
798 std::string s(_(
"Cannot load route or waypoint file: "));
799 s += std::string(
"\"") + path +
"\"";
800 wxMessageBox(s,
"OpenCPN", wxICON_WARNING | wxOK);
806 nav_objects.LoadAllGPXObjects(!nav_objects.IsOpenCPN(), wpt_dups,
true);
808 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
809 pRouteManagerDialog->UpdateLists();
810 LLBBox box = nav_objects.GetBBox();
811 if (box.GetValid()) {
812 gFrame->CenterView(gFrame->GetPrimaryCanvas(), box);
818 void MyApp::OnInitCmdLine(wxCmdLineParser &parser) {
821 parser.AddSwitch(
"h",
"help",
"", wxCMD_LINE_OPTION_HELP);
822 parser.AddSwitch(
"p",
"portable");
823 parser.AddOption(
"c",
"configdir",
"", wxCMD_LINE_VAL_STRING,
824 wxCMD_LINE_PARAM_OPTIONAL);
825 parser.AddSwitch(
"f",
"fullscreen");
826 parser.AddSwitch(
"G",
"no_opengl");
827 parser.AddSwitch(
"W",
"config_wizard");
828 parser.AddSwitch(
"g",
"rebuild_gl_raster_cache");
829 parser.AddSwitch(
"D",
"rebuild_chart_db");
830 parser.AddSwitch(
"P",
"parse_all_enc");
831 parser.AddOption(
"l",
"loglevel");
832 parser.AddOption(
"u",
"unit_test_1",
"", wxCMD_LINE_VAL_NUMBER);
833 parser.AddSwitch(
"U",
"unit_test_2");
834 parser.AddParam(
"import GPX files", wxCMD_LINE_VAL_STRING,
835 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
836 parser.AddSwitch(
"s",
"safe_mode");
837 parser.AddSwitch(
"r",
"remote");
838 parser.AddSwitch(
"R",
"raise");
839 parser.AddSwitch(
"q",
"quit");
840 parser.AddSwitch(
"e",
"get_rest_endpoint");
841 parser.AddOption(
"o",
"open",
"", wxCMD_LINE_VAL_STRING,
842 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
848 static void ParseLoglevel(wxCmdLineParser &parser) {
849 wxLog::SetLogLevel(wxLOG_Message);
852 static void ParseLoglevel(wxCmdLineParser &parser) {
853 const char *strLevel = std::getenv(
"OPENCPN_LOGLEVEL");
854 strLevel = strLevel ? strLevel :
"info";
856 if (parser.Found(
"l", &wxLevel)) {
857 strLevel = wxLevel.c_str();
859 wxLogLevel level = OcpnLog::str2level(strLevel);
860 if (level == OcpnLog::LOG_BADLEVEL) {
861 fprintf(stderr,
"Bad loglevel %s, using \"info\"", strLevel);
864 wxLog::SetLogLevel(level);
869 bool MyApp::OnCmdLineHelp(wxCmdLineParser& parser) {
876 bool MyApp::OnCmdLineParsed(wxCmdLineParser &parser) {
881 g_unit_test_2 = parser.Found(
"unit_test_2");
882 g_bportable = parser.Found(
"p");
883 g_start_fullscreen = parser.Found(
"fullscreen");
884 g_bdisable_opengl = parser.Found(
"no_opengl");
885 g_rebuild_gl_cache = parser.Found(
"rebuild_gl_raster_cache");
886 g_NeedDBUpdate = parser.Found(
"rebuild_chart_db") ? 2 : 0;
887 g_parse_all_enc = parser.Found(
"parse_all_enc");
888 g_config_wizard = parser.Found(
"config_wizard");
889 if (parser.Found(
"unit_test_1", &number)) {
890 g_unit_test_1 =
static_cast<int>(number);
891 if (g_unit_test_1 == 0) g_unit_test_1 = -1;
893 safe_mode::set_mode(parser.Found(
"safe_mode"));
894 ParseLoglevel(parser);
896 if (parser.Found(
"configdir", &wxstr)) {
897 g_configdir = wxstr.ToStdString();
898 fs::path path(g_configdir);
899 if (!fs::exists(path) || !fs::is_directory(path)) {
900 std::cerr << g_configdir <<
" is not an existing directory.\n";
905 bool has_start_options =
false;
906 static const std::vector<std::string> kStartOptions = {
907 "unit_test_2",
"p",
"fullscreen",
"no_opengl",
"rebuild_gl_raster_cache",
908 "rebuild_chart_db",
"parse_all_enc",
"unit_test_1",
"safe_mode",
"loglevel" };
909 for (
const auto& opt : kStartOptions) {
910 if (parser.Found(opt)) has_start_options =
true;
912 if (has_start_options && parser.Found(
"remote")) {
913 std::cerr <<
"this option is not compatible with --remote\n";
917 bool has_remote_options =
false;
918 static const std::vector<std::string> kRemoteOptions = {
919 "raise",
"quit",
"open",
"get_rest_endpoint"};
920 for (
const auto& opt : kRemoteOptions) {
921 if (parser.Found(opt)) has_remote_options =
true;
923 if (has_remote_options && ! parser.Found(
"remote")) {
924 std::cerr <<
"This option requires --remote\n";
928 for (
size_t paramNr = 0; paramNr < parser.GetParamCount(); ++paramNr)
929 g_params.push_back(parser.GetParam(paramNr).ToStdString());
932 if (!parser.Found(
"remote"))
933 m_parsed_cmdline = ParsedCmdline();
934 else if (parser.Found(
"raise"))
935 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Raise);
936 else if (parser.Found(
"quit"))
937 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Quit);
938 else if (parser.Found(
"get_rest_endpoint"))
939 m_parsed_cmdline = ParsedCmdline(CmdlineAction::GetRestEndpoint);
940 else if (parser.Found(
"open", &optarg))
941 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Open,
942 optarg.ToStdString());
943 else if (parser.GetParamCount() == 1)
944 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Open,
945 parser.GetParam(0).ToStdString());
946 else if (!has_start_options && !has_remote_options) {
948 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Raise);
958 bool MyApp::OnExceptionInMainLoop() {
959 wxLogWarning(_T(
"Caught MainLoopException, continuing..."));
964 void MyApp::OnActivateApp(wxActivateEvent &event) {
969 static wxStopWatch init_sw;
972 if (m_exitcode != -2)
return m_exitcode;
973 return wxAppConsole::OnRun();
986 if (wxGetEnv(
"WAYLAND_DISPLAY", NULL)) {
987 setenv(
"GDK_BACKEND",
"x11", 1);
989 setenv(
"mesa_glthread",
"false", 1);
994 bool MyApp::OnInit() {
995 if (!wxApp::OnInit())
return false;
997 androidEnableBackButton(
false);
998 androidEnableOptionItems(
false);
1001 GpxDocument::SeedRandom();
1003 #if defined(__WXGTK__) && defined(ocpnUSE_GLES) && defined(__ARM_ARCH)
1009 wxBitmap bmp(10, 10, -1);
1011 dc.SelectObject(bmp);
1012 dc.DrawText(_T(
"X"), 0, 0);
1017 g_BasePlatform = g_Platform;
1024 if (m_parsed_cmdline.action == CmdlineAction::Skip) {
1028 std::cerr <<
"No remote opencpn found. Giving up.\n";
1033 std::unique_ptr<LocalClientApi> client;
1035 client = LocalClientApi::GetClient();
1037 WARNING_LOG <<
"Ipc client exception: " << ie.str();
1044 wxMessageBox(_(
"Sorry, an existing instance of OpenCPN may be too busy "
1045 "to respond.\nPlease retry."),
1046 "OpenCPN", wxICON_INFORMATION | wxOK);
1052 client->HandleCmdline(m_parsed_cmdline.action, m_parsed_cmdline.arg);
1056 wxLogDebug(
"Error running remote command: %s", result.second.c_str());
1065 if (getenv(
"OPENCPN_FATAL_ERROR") != 0) {
1066 wxLogFatalError(getenv(
"OPENCPN_FATAL_ERROR"));
1071 if (!safe_mode::get_mode()) {
1077 OCPNPlatform::Initialize_1();
1082 MyApp::SetAppDisplayName(
"OpenCPN");
1085 wxDateTime x = wxDateTime::UNow();
1086 long seed = x.GetMillisecond();
1087 seed *= x.GetTicks();
1092 setlocale(LC_NUMERIC,
"C");
1094 g_start_time = wxDateTime::Now();
1096 g_loglast_time = g_start_time;
1097 g_loglast_time.MakeGMT();
1098 g_loglast_time.Subtract(
1099 wxTimeSpan(0, 29, 0, 0));
1101 AnchorPointMinDist = 5.0;
1107 GetMemoryStatus(&g_mem_total, &g_mem_initial);
1111 wxFont temp_font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
1112 wxFONTWEIGHT_NORMAL, FALSE, wxString(_T(
"")),
1113 wxFONTENCODING_SYSTEM);
1114 temp_font.SetDefaultEncoding(wxFONTENCODING_SYSTEM);
1117 if (!g_Platform->InitializeLogFile())
return false;
1128 wxLogMessage(_T(
"\n\n________\n"));
1130 wxDateTime now = wxDateTime::Now();
1131 LOG_INFO(
"------- OpenCPN version %s restarted at %s -------\n", VERSION_FULL,
1132 now.FormatISODate().mb_str().data());
1133 wxLogLevel level = wxLog::GetLogLevel();
1134 LOG_INFO(
"Using loglevel %s", OcpnLog::level2str(level).c_str());
1136 wxString wxver(wxVERSION_STRING);
1137 wxver.Prepend(_T(
"wxWidgets version: "));
1139 wxPlatformInfo platforminfo = wxPlatformInfo::Get();
1143 os_name = platforminfo.GetOperatingSystemIdName();
1145 os_name = platforminfo.GetOperatingSystemFamilyName();
1148 wxString platform = os_name + _T(
" ") + platforminfo.GetArchName() + _T(
" ") +
1149 platforminfo.GetPortIdName();
1151 wxLogMessage(wxver + _T(
" ") + platform);
1153 ::wxGetOsVersion(&osMajor, &osMinor);
1154 wxString osVersionMsg;
1155 osVersionMsg.Printf(_T(
"OS Version reports as: %d.%d"), osMajor, osMinor);
1156 wxLogMessage(osVersionMsg);
1158 wxLogMessage(_T(
"MemoryStatus: mem_total: %d mb, mem_initial: %d mb"),
1159 g_mem_total / 1024, g_mem_initial / 1024);
1164 if (!detail->osd_names_like.empty())
1165 like0 = detail->osd_names_like[0].c_str();
1166 msgplat.Printf(
"OCPN_OSDetail: %s ; %s ; %s ; %s ; %s",
1167 detail->osd_arch.c_str(), detail->osd_name.c_str(),
1168 detail->osd_version.c_str(), detail->osd_ID.c_str(),
1170 wxLogMessage(msgplat);
1172 wxString imsg = _T(
"SData_Locn is ");
1173 imsg += g_Platform->GetSharedDataDir();
1177 ::wxInitAllImageHandlers();
1181 prepareAndroidStyleSheets();
1185 pInit_Chart_Dir =
new wxString();
1188 g_pGroupArray =
new ChartGroupArray;
1190 imsg = _T(
"PrivateDataDir is ");
1196 pMessageOnceArray =
new wxArrayString;
1200 g_pRouteMan =
new Routeman(RoutePropDlg::GetDlgCtx(), RoutemanGui::GetDlgCtx(),
1201 NMEALogWindow::GetInstance());
1205 pSelect->SetSelectPixelRadius(12);
1208 pSelectTC =
new Select();
1210 pSelectTC->SetSelectPixelRadius(25);
1213 pSelectAIS =
new Select();
1214 pSelectAIS->SetSelectPixelRadius(12);
1218 g_pais_query_dialog_active = NULL;
1221 g_hostname = ::wxGetHostName();
1222 if(g_hostname.IsEmpty())
1223 g_hostname = wxGetUserName();
1225 androidGetDeviceInfo();
1226 g_hostname = wxString(
"Android-") + g_android_Device_Model;
1227 g_hostname.Replace(
" ",
"-",
true);
1232 wxString p(
"Portable-");
1233 g_hostname = p + g_hostname;
1239 pLayerList =
new LayerList;
1241 pRouteList =
new RouteList;
1248 #ifdef PROBE_PORTS__WITH_HELPER
1249 user_user_id = getuid();
1250 file_user_id = geteuid();
1254 bool b_initial_load =
false;
1256 wxFileName config_test_file_name(g_Platform->GetConfigFileName());
1257 if (config_test_file_name.FileExists())
1258 wxLogMessage(_T(
"Using existing Config_File: ") +
1259 g_Platform->GetConfigFileName());
1262 wxLogMessage(_T(
"Creating new Config_File: ") +
1263 g_Platform->GetConfigFileName());
1265 b_initial_load =
true;
1268 config_test_file_name.DirExists(config_test_file_name.GetPath()))
1269 if (!config_test_file_name.Mkdir(config_test_file_name.GetPath()))
1270 wxLogMessage(_T(
"Cannot create config file directory for ") +
1271 g_Platform->GetConfigFileName());
1276 pConfig = g_Platform->GetConfigObject();
1277 InitBaseConfig(pConfig);
1278 pConfig->LoadMyConfig();
1282 if (b_initial_load) g_Platform->SetDefaultOptions();
1284 g_Platform->applyExpertMode(g_bUIexpert);
1292 g_StyleManager->SetStyle(_T(
"MUI_flat"));
1293 if (!g_StyleManager->IsOK()) {
1294 wxString msg = _(
"Failed to initialize the user interface. ");
1295 msg << _(
"OpenCPN cannot start. ");
1296 msg << _(
"The necessary configuration files were not found. ");
1297 msg << _(
"See the log file at ") << g_Platform->GetLogFileName()
1298 << _(
" for details.") << _T(
"\n\n");
1299 msg << g_Platform->GetSharedDataDir();
1301 wxMessageDialog w(NULL, msg, _(
"Failed to initialize the user interface. "),
1302 wxCANCEL | wxICON_ERROR);
1309 if (style) style->chartStatusWindowTransparent =
true;
1313 pWayPointMan = NULL;
1315 g_display_size_mm = wxMax(50, g_Platform->GetDisplaySizeMM());
1317 msg.Printf(_T(
"Detected display size (horizontal): %d mm"),
1318 (
int)g_display_size_mm);
1322 if (g_config_display_size_manual && g_config_display_size_mm.size() > g_current_monitor && g_config_display_size_mm[g_current_monitor] > 0) {
1323 g_display_size_mm = g_config_display_size_mm[g_current_monitor];
1325 msg.Printf(_T(
"Display size (horizontal) config override: %d mm"),
1326 (
int)g_display_size_mm);
1328 g_Platform->SetDisplaySizeMM(g_current_monitor, g_display_size_mm);
1331 g_display_size_mm = wxMax(50, g_display_size_mm);
1334 int SelectPixelRadius = 50;
1336 pSelect->SetSelectPixelRadius(SelectPixelRadius);
1337 pSelectTC->SetSelectPixelRadius(wxMax(25, SelectPixelRadius));
1338 pSelectAIS->SetSelectPixelRadius(SelectPixelRadius);
1342 if (!n_NavMessageShown) g_bFirstRun =
true;
1347 #if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1350 g_Platform->SetLocaleSearchPrefixes();
1352 wxString def_lang_canonical = g_Platform->GetDefaultSystemLocale();
1354 imsg = _T(
"System default Language: ") + def_lang_canonical;
1357 wxString cflmsg = _T(
"Config file language: ") + g_locale;
1358 wxLogMessage(cflmsg);
1360 if (g_locale.IsEmpty()) {
1361 g_locale = def_lang_canonical;
1362 cflmsg = _T(
"Config file language empty, using system default: ") + g_locale;
1363 wxLogMessage(cflmsg);
1367 g_locale = g_Platform->GetAdjustedAppLocale();
1368 cflmsg = _T(
"Adjusted App language: ") + g_locale;
1369 wxLogMessage(cflmsg);
1372 g_Platform->ChangeLocale(g_locale, plocale_def_lang, &plocale_def_lang);
1374 imsg = _T(
"Opencpn language set to: ");
1381 if (g_locale == _T(
"fr_FR")) g_b_assume_azerty =
true;
1383 wxLogMessage(_T(
"wxLocale support not available"));
1387 if (g_config_wizard || b_initial_load) {
1389 auto res = wiz.Run();
1399 wxString vs = wxString(
"Version ") + VERSION_FULL +
" Build " + VERSION_DATE;
1400 g_bUpgradeInProcess = (vs != g_config_version_string);
1402 g_Platform->SetUpgradeOptions(vs, g_config_version_string);
1405 if (!g_Platform->GetLargeLogMessage().IsEmpty())
1406 wxLogMessage(g_Platform->GetLargeLogMessage());
1410 g_bdisable_opengl =
true;
1414 if (g_bdisable_opengl) g_bopengl =
false;
1416 #if defined(__linux__) && !defined(__ANDROID__)
1417 if (g_bSoftwareGL) setenv(
"LIBGL_ALWAYS_SOFTWARE",
"1", 1);
1429 if (0 == g_memCacheLimit) g_memCacheLimit = (int)(g_mem_total * 0.5);
1431 wxMin(g_memCacheLimit, 1024 * 1024);
1437 g_memCacheLimit = 0;
1438 if (0 == g_nCacheLimit)
1439 g_nCacheLimit = CACHE_N_LIMIT_DEFAULT;
1444 "chartlist.dat",
"CHRTLIST.DAT");
1448 "mmsitoname.csv",
"MMSINAME.CSV");
1451 if (pInit_Chart_Dir->IsEmpty()) {
1452 wxStandardPaths &std_path = g_Platform->GetStdPaths();
1456 pInit_Chart_Dir->Append(std_path.GetDocumentsDir());
1458 pInit_Chart_Dir->Append(androidGetExtStorageDir());
1462 InitRestListeners();
1465 gDefaultWorldMapLocation =
"gshhs";
1466 gDefaultWorldMapLocation.Prepend(g_Platform->GetSharedDataDir());
1467 gDefaultWorldMapLocation.Append(wxFileName::GetPathSeparator());
1468 if (gWorldMapLocation == wxEmptyString) {
1469 gWorldMapLocation = gDefaultWorldMapLocation;
1474 wxString default_tcdata0 =
1475 (g_Platform->GetSharedDataDir() + _T(
"tcdata") +
1476 wxFileName::GetPathSeparator() + _T(
"harmonics-dwf-20210110-free.tcd"));
1477 wxString default_tcdata1 =
1478 (g_Platform->GetSharedDataDir() + _T(
"tcdata") +
1479 wxFileName::GetPathSeparator() + _T(
"HARMONICS_NO_US.IDX"));
1481 if (TideCurrentDataSet.empty()) {
1482 TideCurrentDataSet.push_back(g_Platform->NormalizePath(default_tcdata0).ToStdString());
1483 TideCurrentDataSet.push_back(g_Platform->NormalizePath(default_tcdata1).ToStdString());
1488 if (g_sAIS_Alert_Sound_File.IsEmpty()) {
1489 wxString default_sound =
1490 (g_Platform->GetSharedDataDir() + _T(
"sounds") +
1491 wxFileName::GetPathSeparator() + _T(
"2bells.wav"));
1492 g_sAIS_Alert_Sound_File = g_Platform->NormalizePath(default_sound);
1497 g_Platform->Initialize_2();
1501 wxSize new_frame_size(-1, -1);
1503 ::wxClientDisplayRect(&cx, &cy, &cw, &ch);
1505 InitializeUserColors();
1507 auto style = g_StyleManager->GetCurrentStyle();
1508 auto bitmap =
new wxBitmap(style->GetIcon(
"default_pi", 32, 32));
1510 PluginLoader::getInstance()->SetPluginDefaultIcon(bitmap);
1512 wxLogWarning(
"Cannot initiate plugin default jigsaw icon.");
1515 if ((g_nframewin_x > 100) && (g_nframewin_y > 100) && (g_nframewin_x <= cw) &&
1516 (g_nframewin_y <= ch))
1517 new_frame_size.Set(g_nframewin_x, g_nframewin_y);
1519 new_frame_size.Set(cw * 7 / 10, ch * 7 / 10);
1525 if ((g_lastClientRectx != cx) || (g_lastClientRecty != cy) ||
1526 (g_lastClientRectw != cw) || (g_lastClientRecth != ch)) {
1527 new_frame_size.Set(cw * 7 / 10, ch * 7 / 10);
1528 g_bframemax =
false;
1531 g_lastClientRectx = cx;
1532 g_lastClientRecty = cy;
1533 g_lastClientRectw = cw;
1534 g_lastClientRecth = ch;
1537 wxPoint position(0, 0);
1538 wxSize dsize = wxGetDisplaySize();
1541 g_nframewin_posy = wxMax(g_nframewin_posy, 22);
1544 if ((g_nframewin_posx < dsize.x) && (g_nframewin_posy < dsize.y))
1545 position = wxPoint(g_nframewin_posx, g_nframewin_posy);
1550 frame_rect.left = position.x;
1551 frame_rect.top = position.y;
1552 frame_rect.right = position.x + new_frame_size.x;
1553 frame_rect.bottom = position.y + new_frame_size.y;
1557 if (NULL == MonitorFromRect(&frame_rect, MONITOR_DEFAULTTONULL))
1558 position = wxPoint(10, 10);
1563 const wxPoint ptScreen(position.x, position.y);
1564 const int displayIndex = wxDisplay::GetFromPoint(ptScreen);
1566 if (displayIndex == wxNOT_FOUND)
1567 position = wxPoint(10, 30);
1570 g_nframewin_posx = position.x;
1571 g_nframewin_posy = position.y;
1574 wxSize asz = getAndroidDisplayDimensions();
1579 if ((cw > 200) && (ch > 200))
1580 new_frame_size.Set(cw, ch);
1582 new_frame_size.Set(800, 400);
1586 long app_style = wxDEFAULT_FRAME_STYLE;
1587 app_style |= wxWANTS_CHARS;
1592 wxString short_version_name = wxString(PACKAGE_VERSION).BeforeFirst(
'+');
1593 wxString myframe_window_title = wxString(wxT(
"OpenCPN ") + short_version_name);
1596 myframe_window_title += _(
" -- [Portable(-p) executing from ");
1597 myframe_window_title += g_Platform->GetHomeDir();
1598 myframe_window_title += _T(
"]");
1602 fmsg.Printf(_T(
"Creating MyFrame...size(%d, %d) position(%d, %d)"),
1603 new_frame_size.x, new_frame_size.y, position.x, position.y);
1606 gFrame =
new MyFrame(NULL, myframe_window_title, position, new_frame_size,
1610 g_Platform->Initialize_3();
1617 g_pauidockart =
new wxAuiDefaultDockArt;
1618 g_pauimgr->SetArtProvider(g_pauidockart);
1619 g_pauimgr->SetDockSizeConstraint(.9, .9);
1624 g_pauimgr->SetManagedWindow(gFrame);
1626 gFrame->CreateCanvasLayout();
1630 gFrame->SetChartUpdatePeriod();
1634 gFrame->GetPrimaryCanvas()->SetFocus();
1636 pthumbwin =
new ThumbWin(gFrame->GetPrimaryCanvas());
1638 gFrame->ApplyGlobalSettings(
false);
1640 gFrame->SetAllToolbarScale();
1646 gFrame->SetAndApplyColorScheme(global_color_scheme);
1648 if (g_bframemax) gFrame->Maximize(
true);
1651 if (g_bresponsive && (gFrame->GetPrimaryCanvas()->GetPixPerMM() > 4.0))
1652 gFrame->Maximize(
true);
1659 ArrayOfCDI ChartDirArray;
1660 pConfig->LoadChartDirArray(ChartDirArray);
1665 if (g_bFirstRun && (ChartDirArray.GetCount() == 0)) {
1668 wxRegKey RegKey(wxString(_T(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenCPN")));
1669 if (RegKey.Exists()) {
1671 _(
"Retrieving initial Chart Directory set from Windows Registry"));
1673 RegKey.QueryValue(wxString(_T(
"ChartDirs")), dirs);
1675 wxStringTokenizer tkz(dirs, _T(
";"));
1676 while (tkz.HasMoreTokens()) {
1677 wxString token = tkz.GetNextToken();
1680 cdi.fullpath = token.Trim();
1681 cdi.magic_number = _T(
"");
1683 ChartDirArray.Add(cdi);
1690 cdi.fullpath = _T(
"charts");
1691 cdi.fullpath.Prepend(g_Platform->GetSharedDataDir());
1692 cdi.magic_number = _T(
"");
1693 ChartDirArray.Add(cdi);
1697 if (ndirs) pConfig->UpdateChartDirs(ChartDirArray);
1707 if (!ChartDirArray.GetCount())
1708 if (::wxFileExists(ChartListFileName)) ::wxRemoveFile(ChartListFileName);
1712 if (g_NeedDBUpdate == 0 && !ChartData->LoadBinary(ChartListFileName, ChartDirArray)) {
1717 if (g_restore_dbindex >= 0) {
1718 if (ChartData->GetChartTableEntries() == 0)
1719 g_restore_dbindex = -1;
1721 else if (g_restore_dbindex > (ChartData->GetChartTableEntries() - 1))
1722 g_restore_dbindex = 0;
1726 ChartData->ApplyGroupArray(g_pGroupArray);
1734 if (g_rebuild_gl_cache && g_bopengl && g_GLOptions.m_bTextureCompression &&
1735 g_GLOptions.m_bTextureCompressionCaching) {
1736 gFrame->ReloadAllVP();
1745 if (g_glTextureManager) g_glTextureManager->BuildCompressedCache();
1755 if ((gps_watchdog_timeout_ticks > 60) || (gps_watchdog_timeout_ticks <= 0))
1756 gps_watchdog_timeout_ticks = (GPS_TIMEOUT_SECONDS * 1000) / TIMER_GFRAME_1;
1759 dogmsg.Printf(_T(
"GPS Watchdog Timeout is: %d sec."),
1760 gps_watchdog_timeout_ticks);
1761 wxLogMessage(dogmsg);
1763 sat_watchdog_timeout_ticks = gps_watchdog_timeout_ticks;
1771 if (g_bTrackCarryOver) g_bDeferredStartTrack =
true;
1773 pAnchorWatchPoint1 = NULL;
1774 pAnchorWatchPoint2 = NULL;
1778 gFrame->DoChartUpdate();
1783 gFrame->ReloadAllVP();
1785 gFrame->Refresh(
false);
1788 gFrame->GetPrimaryCanvas()->Enable();
1789 gFrame->GetPrimaryCanvas()->SetFocus();
1796 if (!g_bdisable_opengl) {
1800 (pgl->GetRendererString().Find(_T(
"UniChrome")) != wxNOT_FOUND)) {
1801 gFrame->m_defer_size = gFrame->GetSize();
1802 gFrame->SetSize(gFrame->m_defer_size.x - 10, gFrame->m_defer_size.y);
1803 g_pauimgr->Update();
1804 gFrame->m_bdefer_resize =
true;
1814 [](
unsigned n,
const unsigned* texts) { glDeleteTextures(n, texts); };
1820 if (g_start_fullscreen) gFrame->ToggleFullScreen();
1825 gFrame->SetSize(getAndroidDisplayDimensions());
1826 androidSetFollowTool(gFrame->GetPrimaryCanvas()->m_bFollow ? 1 : 0,
true);
1830 gFrame->GetPrimaryCanvas()->Enable();
1831 gFrame->GetPrimaryCanvas()->SetFocus();
1839 gFrame->FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
1842 gFrame->FrameCOGTimer.Start(2000, wxTIMER_CONTINUOUS);
1847 OCPNPlatform::Initialize_4();
1850 androidHideBusyIcon();
1853 wxString::Format(_(
"OpenCPN Initialized in %ld ms."), init_sw.Time()));
1861 if (!n_NavMessageShown || (vs != g_config_version_string) ||
1862 (g_AndroidVersionCode != androidGetVersionCode())) {
1866 if (wxID_CANCEL == ShowNavWarning()) {
1867 qDebug() <<
"Closing due to NavWarning Cancel";
1873 n_NavMessageShown = 1;
1877 g_AndroidVersionCode = androidGetVersionCode();
1878 qDebug() <<
"Persisting Version Code: " << g_AndroidVersionCode;
1883 if (!n_NavMessageShown || (vs != g_config_version_string)) {
1884 if (wxID_CANCEL == ShowNavWarning())
return false;
1885 n_NavMessageShown = 1;
1892 g_bHasHwClock =
true;
1893 #if defined(__UNIX__) && !defined(__ANDROID__)
1896 ((stat(
"/dev/rtc", &buffer) == 0) || (stat(
"/dev/rtc0", &buffer) == 0) ||
1897 (stat(
"/dev/misc/rtc", &buffer) == 0));
1900 g_config_version_string = vs;
1903 pConfig->UpdateSettings();
1906 gFrame->InitTimer.Start(5, wxTIMER_CONTINUOUS);
1908 g_pauimgr->Update();
1910 for (
size_t i = 0; i < TheConnectionParams()->Count(); i++) {
1913 if (cp->GetDSPort().Contains(
"Serial")) {
1914 std::string port(cp->Port.ToStdString());
1922 m_comm_bridge.Initialize();
1924 std::vector<std::string> ipv4_addrs = get_local_ipv4_addresses();
1927 if (ipv4_addrs.size()) {
1928 std::string ipAddr = ipv4_addrs[0];
1931 if (data_dir.Last() != wxFileName::GetPathSeparator())
1932 data_dir.Append(wxFileName::GetPathSeparator());
1934 make_certificate(ipAddr, data_dir.ToStdString());
1936 m_rest_server.
StartServer(fs::path(data_dir.ToStdString()));
1937 StartMDNSService(g_hostname.ToStdString(),
1938 "opencpn-object-control-service", 8000);
1943 int MyApp::OnExit() {
1945 wxLogMessage(_T(
"opencpn::MyApp starting exit."));
1947 m_usb_watcher.Stop();
1950 wxDateTime lognow = wxDateTime::Now();
1952 wxString day = lognow.FormatISODate();
1953 wxString utc = lognow.FormatISOTime();
1954 wxString navmsg = _T(
"LOGBOOK: ");
1958 navmsg += _T(
" UTC ");
1962 data.Printf(_T(
"OFF: Lat %10.5f Lon %10.5f "), gLat, gLon);
1966 if (std::isnan(gCog))
1967 cog.Printf(_T(
"COG ----- "));
1969 cog.Printf(_T(
"COG %10.5f "), gCog);
1972 if (std::isnan(gSog))
1973 sog.Printf(_T(
"SOG ----- "));
1975 sog.Printf(_T(
"SOG %6.2f ") + getUsrSpeedUnit(), toUsrSpeed(gSog));
1982 data.Printf(_T(
"OFF: Lat %10.5f Lon %10.5f"), gLat, gLon);
1985 wxLogMessage(navmsg);
1986 g_loglast_time = lognow;
1988 if (ptcmgr)
delete ptcmgr;
1990 for (
Track* track : g_TrackList) {
1993 g_TrackList.clear();
2001 delete g_SencThreadManager;
2003 if (g_pGroupArray) {
2004 for (
unsigned int igroup = 0; igroup < g_pGroupArray->GetCount();
2006 delete g_pGroupArray->Item(igroup);
2009 g_pGroupArray->Clear();
2010 delete g_pGroupArray;
2013 wxLogMessage(_T(
"opencpn::MyApp exiting cleanly...\n"));
2014 wxLog::FlushActive();
2016 g_Platform->CloseLogFile();
2018 delete pInit_Chart_Dir;
2020 for (
Track* track : g_TrackList) {
2023 g_TrackList.clear();
2026 delete pWayPointMan;
2028 delete pMessageOnceArray;
2030 DeInitializeUserColors();
2034 delete m_pRegistrarMan;
2037 delete g_StyleManager;
2042 if (s_glu_dll_ready) FreeLibrary(s_hGLU_DLL);
2051 void RestoreSystemColors(
void);
2052 RestoreSystemColors();
2059 #if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
2060 if (plocale_def_lang)
delete plocale_def_lang;
2063 FontMgr::Shutdown();
2065 g_Platform->OnExit_2();
2072 #ifdef LINUX_CRASHRPT
2073 void MyApp::OnFatalException() { g_crashprint.Report(); }
2079 void MyCPLErrorHandler(CPLErr eErrClass,
int nError,
const char *pszErrorMsg)
2084 if (eErrClass == CE_Debug)
2085 snprintf(msg, 255,
"CPL: %s", pszErrorMsg);
2086 else if (eErrClass == CE_Warning)
2087 snprintf(msg, 255,
"CPL Warning %d: %s", nError, pszErrorMsg);
2089 snprintf(msg, 255,
"CPL ERROR %d: %s", nError, pszErrorMsg);
2091 wxString str(msg, wxConvUTF8);
Global state for AIS decoder.
const void Notify()
Notify all listeners, no data supplied.
Common interface for all instance checkers.
virtual bool IsMainInstance()=0
Return true if this process is the primary opencpn instance.
virtual void CleanUp()
Remove all persistent instance state, including possible lock file and defunct opencpn processes.
virtual void OnExit()
Do whatever needed before wxWidget's checks triggers.
virtual void WaitUntilValid()
Wait until this object can be used for example for Dbus connection.
static LocalServerApi & GetInstance()
bool LoadAllPlugIns(bool enabled_plugins, bool keep_orphans=false)
Update catalog with imported metadata and load all plugin library files.
bool StartServer(const fs::path &certificate_location) override
Start the server thread.
static std::function< void(unsigned, const unsigned *)> delete_gl_textures
Horrible Hack (tm).
EventVar on_routes_update
Notified when list of routes is updated (no data in event)
Listen to hardware events and notifies SystemEvents when new devices are plugged in.
Global variables reflecting command line options and arguments.
The local API has a server side handling commands and a client part issuing commands.
void check_last_start()
Check if the last start failed, possibly invoke user dialog and set safe mode state.
void clear_check()
Mark last run as successful.
wxDEFINE_EVENT(REST_IO_EVT, ObservedEvt)
Event from IO thread to main.
bool CheckDongleAccess(wxWindow *parent)
Runs checks and if required dialogs to make dongle accessible.
bool CheckSerialAccess(wxWindow *parent, const std::string device)
Run checks and possible dialogs to ensure device is accessible.
Access checks for comm devices and dongle.