OpenCPN Partial API docs
Loading...
Searching...
No Matches
ocpn_app.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2010 by David S. Register *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 **************************************************************************/
19
26#include "config.h"
27
28#include <algorithm>
29#include <limits.h>
30#include <memory>
31#include <thread>
32
33#ifdef __WXMSW__
34#include <math.h>
35#include <psapi.h>
36#include <stdlib.h>
37#include <time.h>
38#endif
39
40#ifndef __WXMSW__
41#include <setjmp.h>
42#include <signal.h>
43#endif
44
45#ifdef OCPN_HAVE_X11
46#include <X11/Xatom.h>
47#include <X11/Xlib.h>
48#endif
49
50#include "gl_headers.h" // Must be included before anything using GL stuff
51
52#ifdef __VISUALC__
53#include <wx/msw/msvcrt.h>
54#endif
55
56#ifdef __MINGW32__
57#undef IPV6STRICT // mingw FTBS fix: missing struct ip_mreq
58#include <windows.h>
59#endif
60
61#ifdef __WXMSW__
62// #include "c:\\Program Files\\visual leak detector\\include\\vld.h"
63#endif
64
65#if defined(__WXMSW__) && defined(__MSVC__LEAK)
66#include "Stackwalker.h"
67#endif
68
69#include <wx/wxprec.h>
70
71#ifndef WX_PRECOMP
72#include <wx/wx.h>
73#endif // precompiled headers
74
75#include <wx/apptrait.h>
76#include <wx/arrimpl.cpp>
77#include <wx/artprov.h>
78#include <wx/aui/aui.h>
79#include <wx/aui/dockart.h>
80#include <wx/clrpicker.h>
81#include <wx/cmdline.h>
82#include <wx/dialog.h>
83#include <wx/dialog.h>
84#include <wx/dir.h>
85#include <wx/display.h>
86#include <wx/dynlib.h>
87#include <wx/image.h>
88#include <wx/intl.h>
89#include <wx/ipc.h>
90#include <wx/jsonreader.h>
91#include <wx/listctrl.h>
92#include <wx/power.h>
93#include <wx/printdlg.h>
94#include <wx/print.h>
95#include <wx/progdlg.h>
96#include <wx/settings.h>
97#include <wx/stdpaths.h>
98#include <wx/tokenzr.h>
99
100#include "o_sound/o_sound.h"
101
102#include "model/ais_decoder.h"
103#include "model/ais_state_vars.h"
104#include "model/certificates.h"
105#include "model/cmdline.h"
106#include "model/comm_bridge.h"
108#include "model/comm_vars.h"
109#include "model/config_vars.h"
110#include "model/gui_vars.h"
111#include "model/instance_check.h"
112#include "model/local_api.h"
113#include "model/logger.h"
114#include "model/mdns_query.h"
115#include "model/mdns_service.h"
116#include "model/multiplexer.h"
117#include "model/navobj_db.h"
118#include "model/nav_object_database.h"
119#include "model/navutil_base.h"
121#include "model/own_ship.h"
122#include "model/plugin_handler.h"
123#include "model/route.h"
124#include "model/routeman.h"
125#include "model/select.h"
126#include "model/track.h"
127
128#include "about_frame_impl.h"
129#include "about.h"
130#include "ais_info_gui.h"
131#include "ais_target_alert_dlg.h"
132#include "ais_target_list_dlg.h"
133#include "ais_target_query_dlg.h"
134#include "canvas_config.h"
135#include "chartdb.h"
136#include "chcanv.h"
137#include "cm93.h"
138#include "concanv.h"
139#include "config.h"
140#include "config_mgr.h"
141#include "detail_slider.h"
142#include "dialog_alert.h"
143#include "dychart.h"
144#include "font_mgr.h"
145#include "gdal/cpl_csv.h"
146#include "gl_tex_cache.h"
147#include "go_to_position_dlg.h"
148#include "layer.h"
149#include "mark_info.h"
150#include "navutil.h"
151#include "observable.h"
152#include "ocpn_app.h"
153#include "ocpn_aui_manager.h"
154#include "ocpn_frame.h"
155#include "ocpn_platform.h"
156#include "o_senc.h"
157#include "options.h"
158#include "rest_server_gui.h"
159#include "route_ctx_factory.h"
160#include "routemanagerdialog.h"
161#include "routeman_gui.h"
162#include "route_prop_dlg_impl.h"
163#include "s52plib.h"
164#include "s57chart.h"
165#include "s57_query_dlg.h"
166#include "safe_mode_gui.h"
167#include "std_filesystem.h"
168#include "styles.h"
169#include "tcmgr.h"
170#include "thumbwin.h"
171#include "track_prop_dlg.h"
172#include "udev_rule_mgr.h"
173#include "wiz_ui.h"
174
175#ifdef ocpnUSE_GL
176#include "gl_chart_canvas.h"
177#endif
178
179#ifdef __WXOSX__
180#include "model/macutils.h"
181#endif
182
183#ifdef __WXMSW__
184#include "model/garmin_protocol_mgr.h" // Used for port probing on Windows
185void RedirectIOToConsole();
186#endif
187
188#ifdef LINUX_CRASHRPT
189#include "crashprint.h"
190#endif
191
192#ifdef __WXOSX__
193#include "model/macutils.h"
194#endif
195
196#ifdef __ANDROID__
197#include "androidUTIL.h"
198#else
199#include "serial/serial.h"
200#endif
201
202using namespace std::literals::chrono_literals;
203
204const char *const kUsage =
205 R"(Usage:
206 opencpn -h | --help
207 opencpn [-p] [-f] [-G] [-g] [-P] [-l <str>] [-u <num>] [-U] [-s] [GPX file ...]
208 opencpn --remote [-R] | -q] | -e] |-o <str>]
209
210Options for starting opencpn
211
212 -c, --configdir=<dirpath> Use alternative configuration directory.
213 -p, --portable Run in portable mode.
214 -f, --fullscreen Switch to full screen mode on start.
215 -G, --no_opengl Disable OpenGL video acceleration. This setting will
216 be remembered.
217 -g, --rebuild_gl_raster_cache Rebuild OpenGL raster cache on start.
218 -D, --rebuild_chart_db Rescan chart directories and rebuild the chart database
219 -P, --parse_all_enc Convert all S-57 charts to OpenCPN's internal format on start.
220 -l, --loglevel=<str> Amount of logging: error, warning, message, info, debug or trace
221 -u, --unit_test_1=<num> Display a slideshow of <num> charts and then exit.
222 Zero or negative <num> specifies no limit.
223 -U, --unit_test_2
224 -s, --safe_mode Run without plugins, opengl and other "dangerous" stuff
225 -W, --config_wizard Start with initial configuration wizard
226
227Options manipulating already started opencpn
228 -r, --remote Execute commands on already running instance
229 -R, --raise Make running OpenCPN visible if hidden
230 -q, --quit Terminate already running opencpn
231 -e, --get_rest_endpoint Print rest server endpoint and exit.
232 -o, --open=<GPX file> Open file in running opencpn
233
234Arguments:
235 GPX file GPX-formatted file with waypoints or routes.
236)";
237
238// comm event definitions
239wxDEFINE_EVENT(EVT_N2K_129029, wxCommandEvent);
240wxDEFINE_EVENT(EVT_N2K_129026, wxCommandEvent);
241
242wxDEFINE_EVENT(EVT_N0183_RMC, wxCommandEvent);
243wxDEFINE_EVENT(EVT_N0183_HDT, wxCommandEvent);
244wxDEFINE_EVENT(EVT_N0183_HDG, wxCommandEvent);
245wxDEFINE_EVENT(EVT_N0183_HDM, wxCommandEvent);
246wxDEFINE_EVENT(EVT_N0183_VTG, wxCommandEvent);
247wxDEFINE_EVENT(EVT_N0183_GSV, wxCommandEvent);
248wxDEFINE_EVENT(EVT_N0183_GGA, wxCommandEvent);
249wxDEFINE_EVENT(EVT_N0183_GLL, wxCommandEvent);
250wxDEFINE_EVENT(EVT_N0183_AIVDO, wxCommandEvent);
251
252//------------------------------------------------------------------------------
253// Fwd Declarations
254//------------------------------------------------------------------------------
255
256//------------------------------------------------------------------------------
257// Static variable definition
258//------------------------------------------------------------------------------
259
260WX_DEFINE_OBJARRAY(ArrayOfCDI);
261
262static int user_user_id;
263static int file_user_id;
264
265static int g_mem_total, g_mem_initial;
266
267static unsigned int malloc_max;
268
269static int osMajor, osMinor;
270
271static bool g_bHasHwClock;
272
273#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
274// FIXME (leamas) find a new home
275wxLocale *plocale_def_lang = 0;
276#endif
277
278#ifdef LINUX_CRASHRPT
279static wxCrashPrint g_crashprint;
280#endif
281
282#ifndef __WXMSW__
283extern sigjmp_buf env; // the context saved by sigsetjmp();
284#endif // FIXME (leamas) Use exceptions
285
286// {2C9C45C2-8E7D-4C08-A12D-816BBAE722C0}
287#ifdef __WXMSW__
288DEFINE_GUID(GARMIN_DETECT_GUID, 0x2c9c45c2L, 0x8e7d, 0x4c08, 0xa1, 0x2d, 0x81,
289 0x6b, 0xba, 0xe7, 0x22, 0xc0);
290#endif
291
292#if !defined(NAN)
293static const long long lNaN = 0xfff8000000000000;
294#define NAN (*(double *)&lNaN)
295#endif
296
297// Some static helpers
298void appendOSDirSlash(wxString *pString);
299
300void InitializeUserColors();
301void DeInitializeUserColors();
302void SetSystemColors(ColorScheme cs);
303
304static bool LoadAllPlugIns(bool load_enabled) {
305 g_Platform->ShowBusySpinner();
306 bool b = PluginLoader::GetInstance()->LoadAllPlugIns(load_enabled);
307 g_Platform->HideBusySpinner();
308 return b;
309}
310
311//------------------------------------------------------------------------------
312// PNG Icon resources
313//------------------------------------------------------------------------------
314
315#if defined(__WXGTK__) || defined(__WXQT__)
316#include "bitmaps/opencpn.xpm"
317#endif
318
319wxString newPrivateFileName(wxString, const char *name,
320 [[maybe_unused]] const char *windowsName) {
321 wxString fname = wxString::FromUTF8(name);
322 wxString filePathAndName;
323
324 filePathAndName = g_Platform->GetPrivateDataDir();
325 if (filePathAndName.Last() != wxFileName::GetPathSeparator())
326 filePathAndName.Append(wxFileName::GetPathSeparator());
327
328#ifdef __WXMSW__
329 wxString fwname = wxString::FromUTF8(windowsName);
330 filePathAndName.Append(fwname);
331#else
332 filePathAndName.Append(fname);
333#endif
334
335 return filePathAndName;
336}
337
338class WallpaperFrame : public wxFrame {
339public:
341 : wxFrame(nullptr, wxID_ANY, "Loading...", wxDefaultPosition,
342 wxSize(900, 600), wxSTAY_ON_TOP) {
343 // Customize the wallpaper appearance
344 SetBackgroundColour(wxColour(0, 0, 0)); // Black background
345
346 // Add a text message
347 wxStaticText *text =
348 new wxStaticText(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize,
349 wxALIGN_CENTRE_HORIZONTAL);
350 text->SetForegroundColour(wxColour(255, 255, 255));
351
352 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
353 sizer->Add(text, 1, wxALIGN_CENTER);
354 SetSizerAndFit(sizer);
355
356 Center(); // Center the wallpaper frame
357 }
358};
359
360bool ShowNavWarning() {
361 wxString msg(
362 _("\n\
363OpenCPN is distributed in the hope that it will be useful, \
364but WITHOUT ANY WARRANTY; without even the implied \
365warranty of MERCHANTABILITY or FITNESS FOR A \
366PARTICULAR PURPOSE.\n\n\
367See the GNU General Public License for more details.\n\n\
368OpenCPN must only be used in conjunction with approved \
369paper charts and traditional methods of navigation.\n\n\
370DO NOT rely upon OpenCPN for safety of life or property.\n\n\
371Please click \"Agree\" and proceed, or \"Cancel\" to quit.\n"));
372
373 wxString vs = wxString::Format(" .. Version %s", VERSION_FULL);
374
375#ifdef __ANDROID__
376 androidShowDisclaimer(_("OpenCPN for Android") + vs, msg);
377 return true;
378#else
379 msg.Replace("\n", "<br>");
380
381 std::stringstream html;
382 html << "<html><body><p>";
383 html << msg.ToStdString();
384 html << "</p></body></html>";
385
386 std::string title = _("Welcome to OpenCPN").ToStdString();
387 std::string action = _("Agree").ToStdString();
388 AlertDialog info_dlg(gFrame, title, action);
389 info_dlg.SetInitialSize();
390 info_dlg.AddHtmlContent(html);
391 int agreed = info_dlg.ShowModal();
392 return agreed == wxID_OK;
393#endif
394}
395
396bool DoNavMessage(wxString &new_version_string) {
397#ifdef __ANDROID__
398 // We defer the startup message to here to allow the app frame to be
399 // contructed, thus avoiding a dialog with NULL parent which might not work
400 // on some devices.
401 if (!n_NavMessageShown || (new_version_string != g_config_version_string) ||
402 (g_AndroidVersionCode != androidGetVersionCode())) {
403 // qDebug() << "Showing NavWarning";
404 wxMilliSleep(500);
405
406 if (!ShowNavWarning()) {
407 qDebug() << "Closing due to NavWarning Cancel";
408 gFrame->Close();
409 androidTerminate();
410 return true;
411 }
412
413 n_NavMessageShown = 1;
414 }
415
416 // Finished with upgrade checking, so persist the currect Version Code
417 g_AndroidVersionCode = androidGetVersionCode();
418 qDebug() << "Persisting Version Code: " << g_AndroidVersionCode;
419#else
420 // Send the Welcome/warning message if it has never been sent before,
421 // or if the version string has changed at all
422 // We defer until here to allow for localization of the message
423 if (!n_NavMessageShown || (new_version_string != g_config_version_string)) {
424 if (!ShowNavWarning()) return false;
425 n_NavMessageShown = 1;
426 pConfig->Flush();
427 }
428#endif
429 return true;
430}
431
432// `Main program` equivalent, creating windows and returning main app frame
433//------------------------------------------------------------------------------
434// MyApp
435//------------------------------------------------------------------------------
436IMPLEMENT_APP(MyApp)
437
438BEGIN_EVENT_TABLE(MyApp, wxApp)
439EVT_ACTIVATE_APP(MyApp::OnActivateApp)
440END_EVENT_TABLE()
441
442static void ActivateRoute(const std::string &guid) {
443 Route *route = g_pRouteMan->FindRouteByGUID(guid);
444 if (!route) {
445 wxLogMessage("Cannot activate guid: no such route");
446 return;
447 }
448 if (g_pRouteMan->GetpActiveRoute()) g_pRouteMan->DeactivateRoute();
449 // If this is an auto-created MOB route, always select the second point
450 // (the MOB)
451 // as the destination.
452 RoutePoint *point;
453 if (wxNOT_FOUND == route->m_RouteNameString.Find("MOB")) {
454 point = g_pRouteMan->FindBestActivatePoint(route, gLat, gLon, gCog, gSog);
455 } else {
456 point = route->GetPoint(2);
457 }
458 g_pRouteMan->ActivateRoute(route, point);
460 route->m_bRtIsSelected = false;
461}
462
463static void ReverseRoute(const std::string &guid) {
464 Route *route = g_pRouteMan->FindRouteByGUID(guid);
465 if (!route) {
466 wxLogMessage("Cannot activate guid: no such route");
467 return;
468 }
469 route->Reverse();
471}
472
473void MyApp::InitRestListeners() {
474 auto activate_route = [&](wxCommandEvent ev) {
475 auto guid = ev.GetString().ToStdString();
476 ActivateRoute(guid);
477 };
478 rest_activate_listener.Init(m_rest_server.activate_route, activate_route);
479 auto reverse_route = [&](wxCommandEvent ev) {
480 auto guid = ev.GetString().ToStdString();
481 ReverseRoute(guid);
482 };
483 rest_reverse_listener.Init(m_rest_server.reverse_route, reverse_route);
484}
485
486bool MyApp::OpenFile(const std::string &path) {
487 NavObjectCollection1 nav_objects;
488 auto result = nav_objects.load_file(path.c_str());
489 if (!result) {
490 std::string s(_("Cannot load route or waypoint file: "));
491 s += std::string("\"") + path + "\"";
492 wxMessageBox(s, "OpenCPN", wxICON_WARNING | wxOK);
493 return false;
494 }
495
496 int wpt_dups;
497 // Import with full vizibility of names and objects
498 nav_objects.LoadAllGPXObjects(!nav_objects.IsOpenCPN(), wpt_dups, true);
499
500 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
501 pRouteManagerDialog->UpdateLists();
502 LLBBox box = nav_objects.GetBBox();
503 if (box.GetValid()) {
504 gFrame->CenterView(gFrame->GetPrimaryCanvas(), box);
505 }
506 return true;
507}
508
509#ifndef __ANDROID__
510void MyApp::OnInitCmdLine(wxCmdLineParser &parser) {
511 // Add OpenCPN specific command line options. Help message
512 // is hardcoded in kUsage;
513 parser.AddSwitch("h", "help", "", wxCMD_LINE_OPTION_HELP);
514 parser.AddSwitch("p", "portable");
515 parser.AddOption("c", "configdir", "", wxCMD_LINE_VAL_STRING,
516 wxCMD_LINE_PARAM_OPTIONAL);
517 parser.AddSwitch("f", "fullscreen");
518 parser.AddSwitch("G", "no_opengl");
519 parser.AddSwitch("W", "config_wizard");
520 parser.AddSwitch("g", "rebuild_gl_raster_cache");
521 parser.AddSwitch("D", "rebuild_chart_db");
522 parser.AddSwitch("P", "parse_all_enc");
523 parser.AddOption("l", "loglevel");
524 parser.AddOption("u", "unit_test_1", "", wxCMD_LINE_VAL_NUMBER);
525 parser.AddSwitch("U", "unit_test_2");
526 parser.AddParam("import GPX files", wxCMD_LINE_VAL_STRING,
527 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
528 parser.AddSwitch("s", "safe_mode");
529 parser.AddSwitch("r", "remote");
530 parser.AddSwitch("R", "raise");
531 parser.AddSwitch("q", "quit");
532 parser.AddSwitch("e", "get_rest_endpoint");
533 parser.AddOption("o", "open", "", wxCMD_LINE_VAL_STRING,
534 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
535}
536#endif // __ANDROID__
537
539#ifdef __ANDROID__
540static void ParseLoglevel(wxCmdLineParser &parser) {
541 wxLog::SetLogLevel(wxLOG_Message);
542}
543#else
544static void ParseLoglevel(wxCmdLineParser &parser) {
545 const char *strLevel = std::getenv("OPENCPN_LOGLEVEL");
546 strLevel = strLevel ? strLevel : "info";
547 wxString wxLevel;
548 if (parser.Found("l", &wxLevel)) {
549 strLevel = wxLevel.c_str();
550 }
551 wxLogLevel level = OcpnLog::str2level(strLevel);
552 if (level == OcpnLog::LOG_BADLEVEL) {
553 fprintf(stderr, "Bad loglevel %s, using \"info\"", strLevel);
554 level = wxLOG_Info;
555 }
556 wxLog::SetLogLevel(level);
557}
558#endif // __ANDROID__
559
560#ifndef __ANDROID__
561bool MyApp::OnCmdLineHelp(wxCmdLineParser &parser) {
562 std::cout << kUsage;
563 return false;
564}
565#endif
566
567#ifndef __ANDROID__
568bool MyApp::OnCmdLineParsed(wxCmdLineParser &parser) {
569 long number;
570 wxString repo;
571 wxString plugin;
572
573 g_unit_test_2 = parser.Found("unit_test_2");
574 g_bportable = parser.Found("p");
575 g_start_fullscreen = parser.Found("fullscreen");
576 g_bdisable_opengl = parser.Found("no_opengl");
577 g_rebuild_gl_cache = parser.Found("rebuild_gl_raster_cache");
578 g_NeedDBUpdate = parser.Found("rebuild_chart_db") ? 2 : 0;
579 g_parse_all_enc = parser.Found("parse_all_enc");
580 g_config_wizard = parser.Found("config_wizard");
581 if (parser.Found("unit_test_1", &number)) {
582 g_unit_test_1 = static_cast<int>(number);
583 if (g_unit_test_1 == 0) g_unit_test_1 = -1;
584 }
585 safe_mode::set_mode(parser.Found("safe_mode"));
586 ParseLoglevel(parser);
587 wxString wxstr;
588 if (parser.Found("configdir", &wxstr)) {
589 g_configdir = wxstr.ToStdString();
590 fs::path path(g_configdir);
591 if (!fs::exists(path) || !fs::is_directory(path)) {
592 std::cerr << g_configdir << " is not an existing directory.\n";
593 return false;
594 }
595 }
596
597 bool has_start_options = false;
598 static const std::vector<std::string> kStartOptions = {
599 "unit_test_2",
600 "p",
601 "fullscreen",
602 "no_opengl",
603 "rebuild_gl_raster_cache",
604 "rebuild_chart_db",
605 "parse_all_enc",
606 "unit_test_1",
607 "safe_mode",
608 "loglevel"};
609 for (const auto &opt : kStartOptions) {
610 if (parser.Found(opt)) has_start_options = true;
611 }
612 if (has_start_options && parser.Found("remote")) {
613 std::cerr << "this option is not compatible with --remote\n";
614 return false;
615 }
616
617 bool has_remote_options = false;
618 static const std::vector<std::string> kRemoteOptions = {
619 "raise", "quit", "open", "get_rest_endpoint"};
620 for (const auto &opt : kRemoteOptions) {
621 if (parser.Found(opt)) has_remote_options = true;
622 }
623 if (has_remote_options && !parser.Found("remote")) {
624 std::cerr << "This option requires --remote\n";
625 return false;
626 }
627
628 for (size_t paramNr = 0; paramNr < parser.GetParamCount(); ++paramNr)
629 g_params.push_back(parser.GetParam(paramNr).ToStdString());
630
631 wxString optarg;
632 if (!parser.Found("remote"))
633 m_parsed_cmdline = ParsedCmdline();
634 else if (parser.Found("raise"))
635 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Raise);
636 else if (parser.Found("quit"))
637 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Quit);
638 else if (parser.Found("get_rest_endpoint"))
639 m_parsed_cmdline = ParsedCmdline(CmdlineAction::GetRestEndpoint);
640 else if (parser.Found("open", &optarg))
641 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Open, optarg.ToStdString());
642 else if (parser.GetParamCount() == 1)
643 m_parsed_cmdline =
644 ParsedCmdline(CmdlineAction::Open, parser.GetParam(0).ToStdString());
645 else if (!has_start_options && !has_remote_options) {
646 // Neither arguments nor options
647 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Raise);
648 }
649 return true;
650}
651#endif // __ANDROID__
652
653#ifdef __WXMSW__
654// Handle any exception not handled by CrashRpt
655// Most probable: Malloc/new failure
656
657bool MyApp::OnExceptionInMainLoop() {
658 wxLogWarning("Caught MainLoopException, continuing...");
659 return true;
660}
661#endif
662
663void MyApp::OnActivateApp(wxActivateEvent &event) { return; }
664
665static wxStopWatch init_sw;
666
667int MyApp::OnRun() {
668 if (m_exitcode != -2) return m_exitcode;
669 return wxAppConsole::OnRun();
670}
671
672MyApp::MyApp()
673 : m_checker(InstanceCheck::GetInstance()),
674 m_rest_server(PINCreateDialog::GetDlgCtx(), RouteCtxFactory(),
675 g_bportable),
676 m_usb_watcher(UsbWatchDaemon::GetInstance()),
677 m_exitcode(-2) {
678#ifdef __linux__
679 // Handle e. g., wayland default display -- see #1166.
680 if (!wxGetEnv("OCPN_DISABLE_X11_GDK_BACKEND", NULL)) {
681 if (wxGetEnv("WAYLAND_DISPLAY", NULL)) {
682 setenv("GDK_BACKEND", "x11", 1);
683 }
684 }
685 setenv(
686 "mesa_glthread", "false",
687 1); // Explicitly disable glthread. This may have some impact on OpenGL
688 // performance, but we know it is problematic for us. See #2889
689#endif // __linux__
690}
691
692WallpaperFrame *g_wallpaper;
693
695 if (!wxApp::OnInit()) return false;
696
697#ifdef __ANDROID__
698 androidEnableBackButton(false);
699 androidEnableOptionItems(false);
700#endif
701
703
704#if defined(__WXGTK__) && defined(ocpnUSE_GLES) && defined(__ARM_ARCH)
705 // There is a race condition between cairo which is used for text rendering
706 // by gtk and EGL which without the below code causes a bus error and the
707 // program aborts before startup
708 // this hack forces cairo to load right now by rendering some text
709
710 wxBitmap bmp(10, 10, -1);
711 wxMemoryDC dc;
712 dc.SelectObject(bmp);
713 dc.DrawText("X", 0, 0);
714#endif
715
716 // Instantiate the global OCPNPlatform class
717 g_Platform = new OCPNPlatform;
718 g_BasePlatform = g_Platform;
719#ifndef __ANDROID__
720 // We allow only one instance unless the portable option is used
721 if (!g_bportable && wxDirExists(g_Platform->GetPrivateDataDir())) {
722 m_checker.WaitUntilValid();
723 if (m_checker.IsMainInstance()) {
724 // Server is created on first call to GetInstance()
725 if (m_parsed_cmdline.action == CmdlineAction::Skip) {
726 // Server starts running when referenced.
727 [[maybe_unused]] auto &server = LocalServerApi::GetInstance();
728 } else {
729 std::cerr << "No remote opencpn found. Giving up.\n";
730 m_exitcode = 1;
731 return true;
732 }
733 } else {
734 std::unique_ptr<LocalClientApi> client;
735 try {
736 client = LocalClientApi::GetClient();
737 } catch (LocalApiException &ie) {
738 WARNING_LOG << "Ipc client exception: " << ie.str();
739 // If we get here it means that the instance_chk found another
740 // running instance. But that instance is for some reason not
741 // reachable. The safe thing to do is delete the lockfile and exit.
742 // Next start will proceed normally. This may leave a zombie OpenCPN,
743 // but at least O starts.
744 m_checker.CleanUp();
745 wxMessageBox(_("Sorry, an existing instance of OpenCPN may be too busy "
746 "to respond.\nPlease retry."),
747 "OpenCPN", wxICON_INFORMATION | wxOK);
748 m_exitcode = 2;
749 return true; // main program quiet exit.
750 }
751 if (client) {
752 auto result = client->HandleCmdline(m_parsed_cmdline.action,
753 m_parsed_cmdline.arg);
754 if (result.first) {
755 m_exitcode = 0;
756 } else {
757 wxLogDebug("Error running remote command: %s", result.second.c_str());
758 m_exitcode = 1;
759 }
760 return true;
761 }
762 }
763 }
764#endif // __ANDROID__
765
766 if (getenv("OPENCPN_FATAL_ERROR") != 0) {
767 wxLogFatalError(getenv("OPENCPN_FATAL_ERROR"));
768 }
769
770#ifndef __ANDROID__
771 // Check if last run failed, set up safe_mode.
772 if (!safe_mode::get_mode()) {
774 }
775#endif
776
777 // Perform first stage initialization
778 OCPNPlatform::Initialize_1();
779
780 // Set the name of the app as displayed to the user.
781 // This is necessary at least on OS X, for the capitalisation to be correct in
782 // the system menus.
783 MyApp::SetAppDisplayName("OpenCPN");
784
785 // Seed the random number generator
786 wxDateTime x = wxDateTime::UNow();
787 long seed = x.GetMillisecond();
788 seed *= x.GetTicks();
789 srand(seed);
790
791 // Fulup: force floating point to use dot as separation.
792 // This needs to be set early to catch numerics in config file.
793 setlocale(LC_NUMERIC, "C");
794
795 g_start_time = wxDateTime::Now();
796
797 g_loglast_time = g_start_time;
798 g_loglast_time.MakeGMT();
799 g_loglast_time.Subtract(
800 wxTimeSpan(0, 29, 0, 0)); // give 1 minute for GPS to get a fix
801
802 AnchorPointMinDist = 5.0;
803
804 // Init the private memory manager
805 malloc_max = 0;
806
807 // Record initial memory status
808 platform::GetMemoryStatus(&g_mem_total, &g_mem_initial);
809
810 // Set up default FONT encoding, which should have been done by wxWidgets some
811 // time before this......
812 wxFont temp_font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
813 wxFONTWEIGHT_NORMAL, FALSE, wxString(""),
814 wxFONTENCODING_SYSTEM);
815 temp_font.SetDefaultEncoding(wxFONTENCODING_SYSTEM);
816
817 // Start the Notification Manager and remove old persisted messages
818 auto &noteman = NotificationManager::GetInstance();
819 noteman.ScrubNotificationDirectory(30);
820
821 // Establish Log File location
822 if (!g_Platform->InitializeLogFile()) {
823 return false;
824 };
825
826#ifdef __WXMSW__
827
828 // Un-comment the following to establish a separate console window as a
829 // target for printf() in Windows RedirectIOToConsole();
830
831#endif
832
833 // Send init message
834 wxLogMessage("\n\n________\n");
835
836 wxDateTime now = wxDateTime::Now();
837 LOG_INFO("------- OpenCPN version %s restarted at %s -------\n", VERSION_FULL,
838 now.FormatISODate().mb_str().data());
839 wxLogLevel level = wxLog::GetLogLevel();
840 LOG_INFO("Using loglevel %s", OcpnLog::level2str(level).c_str());
841
842 wxString wxver(wxVERSION_STRING);
843 wxver.Prepend("wxWidgets version: ");
844
845 wxPlatformInfo platforminfo = wxPlatformInfo::Get();
846
847 wxString os_name;
848#ifndef __ANDROID__
849 os_name = platforminfo.GetOperatingSystemIdName();
850#else
851 os_name = platforminfo.GetOperatingSystemFamilyName();
852#endif
853
854 wxString platform = os_name + " " + platforminfo.GetArchName() + " " +
855 platforminfo.GetPortIdName();
856
857 wxLogMessage(wxver + " " + platform);
858
859 ::wxGetOsVersion(&osMajor, &osMinor);
860 wxString osVersionMsg;
861 osVersionMsg.Printf("OS Version reports as: %d.%d", osMajor, osMinor);
862 wxLogMessage(osVersionMsg);
863
864 wxLogMessage("MemoryStatus: mem_total: %d mb, mem_initial: %d mb",
865 g_mem_total / 1024, g_mem_initial / 1024);
866
867 OCPN_OSDetail *detail = g_Platform->GetOSDetail();
868 wxString msgplat;
869 wxString like0;
870 if (!detail->osd_names_like.empty())
871 like0 = detail->osd_names_like[0].c_str();
872 msgplat.Printf("OCPN_OSDetail: %s ; %s ; %s ; %s ; %s",
873 detail->osd_arch.c_str(), detail->osd_name.c_str(),
874 detail->osd_version.c_str(), detail->osd_ID.c_str(),
875 like0.mb_str());
876 wxLogMessage(msgplat);
877
878 wxString imsg = "SData_Locn is ";
879 imsg += g_Platform->GetSharedDataDir();
880 wxLogMessage(imsg);
881
882 // Initialize embedded PNG icon graphics
883 ::wxInitAllImageHandlers();
884
885#ifdef __WXQT__
886 // Now we can configure the Qt StyleSheets, if present
887 prepareAndroidStyleSheets();
888#endif
889
890 // Create some static strings
891 pInit_Chart_Dir = new wxString();
892
893 // Establish an empty ChartCroupArray
894 g_pGroupArray = new ChartGroupArray;
895
896 imsg = "PrivateDataDir is ";
897 imsg += g_Platform->GetPrivateDataDir();
898 wxLogMessage(imsg);
899
900 // Create an array string to hold repeating messages, so they don't
901 // overwhelm the log
902 navutil::InitGlobals();
903
904 // Init the Route Manager
906 new Routeman(RoutePropDlg::GetDlgCtx(), RoutemanGui::GetDlgCtx());
907
908 // Init the Selectable Route Items List
909 pSelect = new Select();
910 pSelect->SetSelectPixelRadius(12);
911
912 // Init the Selectable Tide/Current Items List
913 pSelectTC = new Select();
914 // Increase the select radius for tide/current stations
915 pSelectTC->SetSelectPixelRadius(25);
916
917 // Init the Selectable AIS Target List
918 pSelectAIS = new Select();
919 pSelectAIS->SetSelectPixelRadius(12);
920
921 // Initially AIS display is always on
922 g_bShowAIS = true;
923 g_pais_query_dialog_active = NULL;
924
925 // Who am I?
926 g_hostname = ::wxGetHostName();
927 if (g_hostname.IsEmpty()) g_hostname = wxGetUserName();
928#ifdef __ANDROID__
929 androidGetDeviceInfo();
930 g_hostname = wxString("Android-") + g_android_Device_Model;
931 g_hostname.Replace(" ", "-", true);
932#endif
933
934 // A Portabel need a unique mDNS data hostname to share routes.
935 if (g_bportable) {
936 wxString p("Portable-");
937 g_hostname = p + g_hostname;
938 }
939
940 // Initialize some lists
941 // Layers
942 pLayerList = new LayerList;
943 // Routes
944 pRouteList = new RouteList;
945
946 // Initialize the NavObj_db
947 auto &navobj_db = NavObj_dB::GetInstance();
948
949 // (Optionally) Capture the user and file(effective) ids
950 // Some build environments may need root privileges for hardware
951 // port I/O, as in the NMEA data input class. Set that up here.
952
953#ifndef __WXMSW__
954#ifdef PROBE_PORTS__WITH_HELPER
955 user_user_id = getuid();
956 file_user_id = geteuid();
957#endif
958#endif
959
960 bool b_initial_load = false;
961
962 wxFileName config_test_file_name(g_Platform->GetConfigFileName());
963 if (config_test_file_name.FileExists())
964 wxLogMessage("Using existing Config_File: " +
965 g_Platform->GetConfigFileName());
966 else {
967 {
968 wxLogMessage("Creating new Config_File: " +
969 g_Platform->GetConfigFileName());
970
971 b_initial_load = true;
972
973 if (true !=
974 config_test_file_name.DirExists(config_test_file_name.GetPath()))
975 if (!config_test_file_name.Mkdir(config_test_file_name.GetPath()))
976 wxLogMessage("Cannot create config file directory for " +
977 g_Platform->GetConfigFileName());
978 }
979 }
980
981 // Open/Create the Config Object
982 pConfig = g_Platform->GetConfigObject();
983 InitBaseConfig(pConfig);
984 pConfig->LoadMyConfig();
985
986 if (g_kiosk_startup) {
987 g_wallpaper = new WallpaperFrame();
988 g_wallpaper->ShowFullScreen(true); // For a kiosk app, make it fullscreen
989 g_wallpaper->Show();
990 }
991
992 // Override for some safe and nice default values if the config file was
993 // created from scratch
994 if (b_initial_load) g_Platform->SetDefaultOptions();
995
996 g_Platform->applyExpertMode(g_bUIexpert);
997
998 // Now initialize UI Style.
999 g_StyleManager = new ocpnStyle::StyleManager();
1000
1001 g_StyleManager->SetStyle("MUI_flat");
1002 if (!g_StyleManager->IsOK()) {
1003 wxString msg = _("Failed to initialize the user interface. ");
1004 msg << _("OpenCPN cannot start. ");
1005 msg << _("The necessary configuration files were not found. ");
1006 msg << _("See the log file at ") << g_Platform->GetLogFileName()
1007 << _(" for details.") << "\n\n";
1008 msg << g_Platform->GetSharedDataDir();
1009
1010 wxMessageDialog w(NULL, msg, _("Failed to initialize the user interface. "),
1011 wxCANCEL | wxICON_ERROR);
1012 w.ShowModal();
1013 exit(EXIT_FAILURE);
1014 }
1015
1016 if (g_useMUI) {
1017 ocpnStyle::Style *style = g_StyleManager->GetCurrentStyle();
1018 if (style) style->chartStatusWindowTransparent = true;
1019 }
1020
1021 // Init the WayPoint Manager
1022 pWayPointMan = NULL;
1023
1024 g_display_size_mm = wxMax(50, g_Platform->GetDisplaySizeMM());
1025 wxString msg;
1026 msg.Printf("Detected display size (horizontal): %d mm",
1027 (int)g_display_size_mm);
1028 wxLogMessage(msg);
1029
1030 // User override....
1031 if (g_config_display_size_manual &&
1035 wxString msg;
1036 msg.Printf("Display size (horizontal) config override: %d mm",
1037 (int)g_display_size_mm);
1038 wxLogMessage(msg);
1040 }
1041
1043
1044 if (g_btouch) {
1045 int SelectPixelRadius = 50;
1046
1047 pSelect->SetSelectPixelRadius(SelectPixelRadius);
1048 pSelectTC->SetSelectPixelRadius(wxMax(25, SelectPixelRadius));
1049 pSelectAIS->SetSelectPixelRadius(SelectPixelRadius);
1050 }
1051
1052 // Is this the first run after a clean installation?
1053 if (!n_NavMessageShown) {
1054 g_bFirstRun = true;
1055 }
1056
1057 // Now we can set the locale
1058 // using wxWidgets/gettext methodology....
1059
1060#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1061
1062 // Where are the opencpn.mo files?
1063 g_Platform->SetLocaleSearchPrefixes();
1064
1065 wxString def_lang_canonical = g_Platform->GetDefaultSystemLocale();
1066
1067 imsg = "System default Language: " + def_lang_canonical;
1068 wxLogMessage(imsg);
1069
1070 wxString cflmsg = "Config file language: " + g_locale;
1071 wxLogMessage(cflmsg);
1072
1073 if (g_locale.IsEmpty()) {
1074 g_locale = def_lang_canonical;
1075 cflmsg = "Config file language empty, using system default: " + g_locale;
1076 wxLogMessage(cflmsg);
1077 }
1078
1079 // Make any adjustments necessary
1080 g_locale = g_Platform->GetAdjustedAppLocale();
1081 cflmsg = "Adjusted App language: " + g_locale;
1082 wxLogMessage(cflmsg);
1083
1084 // Set the desired locale
1085 g_Platform->ChangeLocale(g_locale, plocale_def_lang, &plocale_def_lang);
1086
1087 imsg = "Opencpn language set to: ";
1088 imsg += g_locale;
1089 wxLogMessage(imsg);
1090
1091 // French language locale is assumed to include the AZERTY keyboard
1092 // This applies to either the system language, or to OpenCPN language
1093 // selection
1094 if (g_locale == "fr_FR") g_b_assume_azerty = true;
1095#else
1096 wxLogMessage("wxLocale support not available");
1097#endif
1098
1099#ifndef __ANDROID__
1100 // Now that locale is established, possibly run the startup wizard.
1101 if (g_config_wizard || b_initial_load) {
1102 FirstUseWizImpl wiz(gFrame, pConfig);
1103 auto res = wiz.Run();
1104 if (res) {
1105 g_NeedDBUpdate = 2;
1106 }
1107 }
1108#endif
1109
1110 // Instantiate and initialize the Config Manager
1111 ConfigMgr::Get();
1112
1113 // Is this an upgrade?
1114 wxString vs = wxString("Version ") + VERSION_FULL + " Build " + VERSION_DATE;
1115 g_bUpgradeInProcess = (vs != g_config_version_string);
1116
1117 g_Platform->SetUpgradeOptions(vs, g_config_version_string);
1118
1119 // log deferred log restart message, if it exists.
1120 if (!g_Platform->GetLargeLogMessage().IsEmpty()) {
1121 wxLogMessage(g_Platform->GetLargeLogMessage());
1122 }
1123
1124 // Validate OpenGL functionality, if selected
1125#ifndef ocpnUSE_GL
1126 g_bdisable_opengl = true;
1127#endif
1128
1129 if (g_bdisable_opengl) g_bopengl = false;
1130
1131#if defined(__linux__) && !defined(__ANDROID__)
1132 if (g_bSoftwareGL) {
1133 setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
1134 }
1135#endif
1136
1137 // FIXMW (dave) move to frame
1138 // g_bTransparentToolbarInOpenGLOK = isTransparentToolbarInOpenGLOK();
1139
1140 // On Windows platforms, establish a default cache managment policy
1141 // as allowing OpenCPN a percentage of available physical memory,
1142 // not to exceed 1 GB
1143 // Note that this logic implies that Windows platforms always use
1144 // the memCacheLimit policy, and never use the fallback nCacheLimit policy
1145#ifdef __WXMSW__
1146 if (0 == g_memCacheLimit) g_memCacheLimit = (int)(g_mem_total * 0.5);
1147 g_memCacheLimit =
1148 wxMin(g_memCacheLimit, 1024 * 1024); // math in kBytes, Max is 1 GB
1149#else
1150 // All other platforms will use the nCacheLimit policy
1151 // sinc on linux it is impossible to accurately measure the application memory
1152 // footprint without expensive methods such as malloc/free tracking, and such
1153
1154 g_memCacheLimit = 0;
1155 if (0 == g_nCacheLimit) // allow config file override
1156 g_nCacheLimit = CACHE_N_LIMIT_DEFAULT;
1157#endif
1158
1159 // Establish location and name of chart database
1160 ChartListFileName = newPrivateFileName(g_Platform->GetPrivateDataDir(),
1161 "chartlist.dat", "CHRTLIST.DAT");
1162
1163 // Establish location and name of AIS MMSI -> Target Name mapping
1164 AISTargetNameFileName = newPrivateFileName(g_Platform->GetPrivateDataDir(),
1165 "mmsitoname.csv", "MMSINAME.CSV");
1166
1167 // Establish guessed location of chart tree
1168 if (pInit_Chart_Dir->IsEmpty()) {
1169 wxStandardPaths &std_path = g_Platform->GetStdPaths();
1170
1171 if (!g_bportable)
1172#ifndef __ANDROID__
1173 pInit_Chart_Dir->Append(std_path.GetDocumentsDir());
1174#else
1175 pInit_Chart_Dir->Append(androidGetExtStorageDir());
1176#endif
1177 }
1178
1179 InitRestListeners();
1180
1181 // Establish the GSHHS Dataset location
1182 gDefaultWorldMapLocation = "gshhs";
1183 gDefaultWorldMapLocation.Prepend(g_Platform->GetSharedDataDir());
1184 gDefaultWorldMapLocation.Append(wxFileName::GetPathSeparator());
1185 if (gWorldMapLocation == wxEmptyString) {
1186 gWorldMapLocation = gDefaultWorldMapLocation;
1187 }
1188
1189 // Check the global Tide/Current data source array
1190 // If empty, preset default (US + ROW) data sources
1191 wxString default_tcdata0 =
1192 (g_Platform->GetSharedDataDir() + "tcdata" +
1193 wxFileName::GetPathSeparator() + "harmonics-dwf-20210110-free.tcd");
1194 wxString default_tcdata1 =
1195 (g_Platform->GetSharedDataDir() + "tcdata" +
1196 wxFileName::GetPathSeparator() + "HARMONICS_NO_US.IDX");
1197
1198 if (TideCurrentDataSet.empty()) {
1199 TideCurrentDataSet.push_back(
1200 g_Platform->NormalizePath(default_tcdata0).ToStdString());
1201 TideCurrentDataSet.push_back(
1202 g_Platform->NormalizePath(default_tcdata1).ToStdString());
1203 }
1204
1205 // Check the global AIS alarm sound file
1206 // If empty, preset default
1207 if (g_sAIS_Alert_Sound_File.IsEmpty()) {
1208 wxString default_sound = (g_Platform->GetSharedDataDir() + "sounds" +
1209 wxFileName::GetPathSeparator() + "2bells.wav");
1210 g_sAIS_Alert_Sound_File = g_Platform->NormalizePath(default_sound);
1211 }
1212
1213 gpIDXn = 0;
1214
1215 g_Platform->Initialize_2();
1216
1217 LoadChartDatabase();
1218
1219 // Kiosk startup mode only available in linux/GTK builds.
1220#ifndef __WXGTK__
1221 g_kiosk_startup = false;
1222#endif
1223
1224 // Create and initialize the main application frame.
1225 if (!g_kiosk_startup) {
1227 SetTopWindow(gFrame); // Set the main frame as the new top window.
1228 gFrame->Show();
1229 gFrame->Raise();
1230
1231 // Start delayed initialization chain after some milliseconds
1232 gFrame->InitTimer.Start(50, wxTIMER_CONTINUOUS);
1233
1234 } else {
1235 wxTheApp->CallAfter(&MyApp::OnMainFrameReady);
1236 }
1237
1238 OCPNPlatform::Initialize_4();
1239
1240#ifdef __ANDROID__
1241 androidHideBusyIcon();
1242#endif
1243 wxLogMessage(
1244 wxString::Format(_("OpenCPN Initialized in %ld ms."), init_sw.Time()));
1245
1246 wxMilliSleep(100);
1247
1248 if (!g_kiosk_startup) {
1249 if (!DoNavMessage(vs)) {
1250 Exit();
1251 }
1252 }
1253
1254 // As an a.e. Raspberry does not have a hardwareclock we will have some
1255 // problems with date/time setting
1256 g_bHasHwClock = true; // by default most computers do have a hwClock
1257#if defined(__UNIX__) && !defined(__ANDROID__)
1258 struct stat buffer;
1259 g_bHasHwClock =
1260 ((stat("/dev/rtc", &buffer) == 0) || (stat("/dev/rtc0", &buffer) == 0) ||
1261 (stat("/dev/misc/rtc", &buffer) == 0));
1262#endif
1263
1264 g_config_version_string = vs;
1265
1266 // The user accepted the "not for navigation" nag, so persist it here...
1267 pConfig->UpdateSettings();
1268
1269 for (auto *cp : TheConnectionParams()) {
1270 if (cp->bEnabled) {
1271 if (cp->GetDSPort().Contains("Serial")) {
1272 std::string port(cp->Port.ToStdString());
1274 }
1275 }
1276 }
1278
1279 // Initialize the CommBridge
1280 m_comm_bridge.Initialize();
1281
1282 std::vector<std::string> ipv4_addrs = get_local_ipv4_addresses();
1283
1284 // If network connection is available, start the server and mDNS client
1285 if (ipv4_addrs.size()) {
1286 std::string ipAddr = ipv4_addrs[0];
1287
1288 wxString data_dir = g_Platform->GetPrivateDataDir();
1289 if (data_dir.Last() != wxFileName::GetPathSeparator())
1290 data_dir.Append(wxFileName::GetPathSeparator());
1291
1292 make_certificate(ipAddr, data_dir.ToStdString());
1293
1294 m_rest_server.StartServer(fs::path(data_dir.ToStdString()));
1295 StartMDNSService(g_hostname.ToStdString(), "opencpn-object-control-service",
1296 8000);
1297 }
1298 return TRUE;
1299}
1300
1303 gFrame->Hide();
1304
1305 // Hide the old frame and show the new one.
1306 g_wallpaper->Show(false);
1308
1309 gFrame->ShowFullScreen(true);
1310
1311 // Cleanup the wallpaper frame.
1312 g_wallpaper->Destroy();
1313 g_wallpaper = nullptr;
1314
1315 SetTopWindow(gFrame); // Set the main frame as the new top window.
1316 gFrame->Raise();
1317
1318 wxString vs = wxString("Version ") + VERSION_FULL + " Build " + VERSION_DATE;
1319 if (!DoNavMessage(vs)) {
1320 Exit();
1321 }
1322
1323 // Start delayed initialization chain after some milliseconds
1324 gFrame->InitTimer.Start(50, wxTIMER_CONTINUOUS);
1325}
1326
1328 // Set up the frame initial visual parameters
1329 // Default size, resized later
1330 wxSize new_frame_size(-1, -1);
1331 int cx, cy, cw, ch;
1332 ::wxClientDisplayRect(&cx, &cy, &cw, &ch);
1333
1334 InitializeUserColors();
1335
1336 if ((g_nframewin_x > 100) && (g_nframewin_y > 100) && (g_nframewin_x <= cw) &&
1337 (g_nframewin_y <= ch))
1338 new_frame_size.Set(g_nframewin_x, g_nframewin_y);
1339 else
1340 new_frame_size.Set(cw * 7 / 10, ch * 7 / 10);
1341
1342 // Try to detect any change in physical screen configuration
1343 // This can happen when drivers are changed, for instance....
1344 // and can confuse the WUI layout perspective stored in the config file.
1345 // If detected, force a nominal window size and position....
1346 if ((g_lastClientRectx != cx) || (g_lastClientRecty != cy) ||
1347 (g_lastClientRectw != cw) || (g_lastClientRecth != ch)) {
1348 new_frame_size.Set(cw * 7 / 10, ch * 7 / 10);
1349 g_bframemax = false;
1350 }
1351
1352 g_lastClientRectx = cx;
1353 g_lastClientRecty = cy;
1354 g_lastClientRectw = cw;
1355 g_lastClientRecth = ch;
1356
1357 // Validate config file position
1358 wxPoint position(0, 0);
1359 wxSize dsize = wxGetDisplaySize();
1360
1361#ifdef __WXMAC__
1362 g_nframewin_posy = wxMax(g_nframewin_posy, 22);
1363#endif
1364
1365 if ((g_nframewin_posx < dsize.x) && (g_nframewin_posy < dsize.y))
1366 position = wxPoint(g_nframewin_posx, g_nframewin_posy);
1367
1368#ifdef __WXMSW__
1369 // Support MultiMonitor setups which can allow negative window positions.
1370 RECT frame_rect;
1371 frame_rect.left = position.x;
1372 frame_rect.top = position.y;
1373 frame_rect.right = position.x + new_frame_size.x;
1374 frame_rect.bottom = position.y + new_frame_size.y;
1375
1376 // If the requested frame window does not intersect any installed monitor,
1377 // then default to simple primary monitor positioning.
1378 if (NULL == MonitorFromRect(&frame_rect, MONITOR_DEFAULTTONULL))
1379 position = wxPoint(10, 10);
1380#endif
1381
1382#ifdef __WXOSX__
1383 // Support MultiMonitor setups which can allow negative window positions.
1384 const wxPoint ptScreen(position.x, position.y);
1385 const int displayIndex = wxDisplay::GetFromPoint(ptScreen);
1386
1387 if (displayIndex == wxNOT_FOUND) position = wxPoint(10, 30);
1388#endif
1389
1390 g_nframewin_posx = position.x;
1391 g_nframewin_posy = position.y;
1392
1393#ifdef __ANDROID__
1394 wxSize asz = getAndroidDisplayDimensions();
1395 ch = asz.y;
1396 cw = asz.x;
1397 // qDebug() << cw << ch;
1398
1399 if ((cw > 200) && (ch > 200))
1400 new_frame_size.Set(cw, ch);
1401 else
1402 new_frame_size.Set(800, 400);
1403#endif
1404
1405 // For Windows and GTK, provide the expected application Minimize/Close bar
1406 long app_style = wxDEFAULT_FRAME_STYLE;
1407 app_style |= wxWANTS_CHARS;
1408
1409 // Create the main frame window
1410
1411 // Strip the commit SHA number from the string to be shown in frame title.
1412 wxString short_version_name = wxString(PACKAGE_VERSION).BeforeFirst('+');
1413 wxString myframe_window_title = wxString("OpenCPN " + short_version_name);
1414
1415 if (g_bportable) {
1416 myframe_window_title += _(" -- [Portable(-p) executing from ");
1417 myframe_window_title += g_Platform->GetHomeDir();
1418 myframe_window_title += "]";
1419 }
1420
1421 wxString fmsg;
1422 fmsg.Printf("Creating MyFrame...size(%d, %d) position(%d, %d)",
1423 new_frame_size.x, new_frame_size.y, position.x, position.y);
1424 wxLogMessage(fmsg);
1425
1427 auto dockart = new wxAuiDefaultDockArt;
1428 g_pauimgr->SetArtProvider(dockart);
1429
1430 gFrame = new MyFrame(NULL, myframe_window_title, position, new_frame_size,
1431 app_style, dockart);
1432
1433 // Initialize the Plugin Manager
1434 g_pi_manager = new PlugInManager(gFrame);
1435
1436 g_pauimgr->SetDockSizeConstraint(.9, .9);
1437
1438 // tell wxAuiManager to manage the frame
1439 g_pauimgr->SetManagedWindow(gFrame);
1440
1441 // Do those platform specific initialization things that need gFrame
1442 g_Platform->Initialize_3();
1443
1444 gFrame->CreateCanvasLayout();
1445
1446 // gFrame->RequestNewMasterToolbar( true );
1447
1448 gFrame->SetChartUpdatePeriod(); // Reasonable default
1449
1450 pthumbwin = new ThumbWin(gFrame->GetPrimaryCanvas());
1451
1452 gFrame->ApplyGlobalSettings(false); // done once on init with resize
1453 gFrame->SetAllToolbarScale();
1454 gFrame->SetAndApplyColorScheme(global_color_scheme);
1455 if (g_bframemax) gFrame->Maximize(true);
1456
1457#ifdef __ANDROID__
1458 if (g_bresponsive && (gFrame->GetPrimaryCanvas()->GetPixPerMM() > 4.0))
1459 gFrame->Maximize(true);
1460#endif
1461
1462 // All set to go.....
1463
1464 // Process command line option to rebuild cache
1465#ifdef ocpnUSE_GL
1466 extern ocpnGLOptions g_GLOptions;
1467
1468 if (g_rebuild_gl_cache && g_bopengl && g_GLOptions.m_bTextureCompression &&
1469 g_GLOptions.m_bTextureCompressionCaching) {
1470 gFrame->ReloadAllVP(); // Get a nice chart background loaded
1471
1472 // Turn off the toolbar as a clear signal that the system is busy right
1473 // now.
1474 // Note: I commented this out because the toolbar never comes back for me
1475 // and is unusable until I restart opencpn without generating the cache
1476 // if( g_MainToolbar )
1477 // g_MainToolbar->Hide();
1478
1479 if (g_glTextureManager) g_glTextureManager->BuildCompressedCache();
1480 }
1481#endif
1482
1483 // FIXME (dave)
1484 // move method to frame
1485 // if (g_parse_all_enc) ParseAllENC(gFrame);
1486
1487 // establish GPS timeout value as multiple of frame timer
1488 // This will override any nonsense or unset value from the config file
1489 if ((gps_watchdog_timeout_ticks > 60) || (gps_watchdog_timeout_ticks <= 0))
1490 gps_watchdog_timeout_ticks = (GPS_TIMEOUT_SECONDS * 1000) / TIMER_GFRAME_1;
1491
1492 wxString dogmsg;
1493 dogmsg.Printf("GPS Watchdog Timeout is: %d sec.", gps_watchdog_timeout_ticks);
1494 wxLogMessage(dogmsg);
1495
1496 sat_watchdog_timeout_ticks = gps_watchdog_timeout_ticks;
1497
1498 g_priSats = 99;
1499
1500 // Most likely installations have no ownship heading information
1501 g_bVAR_Rx = false;
1502
1503 // Start up a new track if enabled in config file
1504 if (g_bTrackCarryOver) g_bDeferredStartTrack = true;
1505
1506 pAnchorWatchPoint1 = NULL;
1507 pAnchorWatchPoint2 = NULL;
1508
1509 gFrame->DoChartUpdate();
1510
1511 // Load and initialize plugins
1512 auto style = g_StyleManager->GetCurrentStyle();
1513 auto bitmap = new wxBitmap(style->GetIcon("default_pi", 32, 32));
1514 if (bitmap->IsOk())
1515 PluginLoader::GetInstance()->SetPluginDefaultIcon(bitmap);
1516 else
1517 wxLogWarning("Cannot initiate plugin default jigsaw icon.");
1518
1520 PluginLoader::GetInstance()->LoadAllPlugIns(true);
1522
1523 // A Plugin (e.g. Squiddio) may have redefined some routepoint icons...
1524 // Reload all icons, to be sure.
1526
1527 wxString perspective;
1528 pConfig->SetPath("/AUI");
1529 pConfig->Read("AUIPerspective", &perspective);
1530
1531 // Make sure the perspective saved in the config file is "reasonable"
1532 // In particular, the perspective should have an entry for every
1533 // windows added to the AUI manager so far.
1534 // If any are not found, then use the default layout
1535
1536 bool bno_load = false;
1537
1538 wxArrayString name_array;
1539 wxStringTokenizer st(perspective, "|;");
1540 while (st.HasMoreTokens()) {
1541 wxString s1 = st.GetNextToken();
1542 if (s1.StartsWith("name=")) {
1543 wxString sc = s1.AfterFirst('=');
1544 name_array.Add(sc);
1545 }
1546 }
1547
1548 wxAuiPaneInfoArray pane_array_val = g_pauimgr->GetAllPanes();
1549 for (unsigned int i = 0; i < pane_array_val.GetCount(); i++) {
1550 wxAuiPaneInfo pane = pane_array_val.Item(i);
1551
1552 // If we find a pane that is not in the perspective,
1553 // then we should not load the perspective at all
1554 if (name_array.Index(pane.name) == wxNOT_FOUND) {
1555 bno_load = true;
1556 break;
1557 }
1558 }
1559
1560 if (!bno_load) g_pauimgr->LoadPerspective(perspective, false);
1561
1562 // Touch up the AUI manager
1563 // Make sure that any pane width is reasonable default value
1564#if 0 // TODO nees this?
1565 for (unsigned int i = 0; i < g_canvasArray.GetCount(); i++) {
1566 ChartCanvas *cc = g_canvasArray.Item(i);
1567 if (cc) {
1568 wxSize frameSize = GetClientSize();
1569 wxSize minSize = g_pauimgr->GetPane(cc).min_size;
1570 int width = wxMax(minSize.x, frameSize.x / 10);
1571 g_pauimgr->GetPane(cc).MinSize(frameSize.x * 1 / 5, frameSize.y);
1572 }
1573 }
1574 g_pauimgr->Update();
1575#endif
1576 g_pauimgr->Update();
1577
1578 // Notify all the AUI PlugIns so that they may syncronize with the
1579 // Perspective
1580 g_pi_manager->NotifyAuiPlugIns();
1581
1582 // Give the user dialog on any blacklisted PlugIns
1583 g_pi_manager->ShowDeferredBlacklistMessages();
1584 g_pi_manager->CallLateInit();
1585
1586 return;
1587
1588 // This little hack fixes a problem seen with some UniChrome OpenGL drivers
1589 // We need a deferred resize to get glDrawPixels() to work right.
1590 // So we set a trigger to generate a resize after 5 seconds....
1591 // See the "UniChrome" hack elsewhere
1592#ifdef ocpnUSE_GL
1593 if (!g_bdisable_opengl) {
1594 glChartCanvas *pgl =
1595 (glChartCanvas *)gFrame->GetPrimaryCanvas()->GetglCanvas();
1596 if (pgl && (pgl->GetRendererString().Find("UniChrome") != wxNOT_FOUND)) {
1597 gFrame->m_defer_size = gFrame->GetSize();
1598 gFrame->SetSize(gFrame->m_defer_size.x - 10, gFrame->m_defer_size.y);
1599 g_pauimgr->Update();
1600 gFrame->m_bdefer_resize = true;
1601 }
1602 }
1603#endif
1604
1605 // Horrible Hack (tm): Make sure the RoutePoint destructor can invoke
1606 // glDeleteTextures. Truly awful.
1607#ifdef ocpnUSE_GL
1608 if (g_bopengl)
1609 RoutePoint::delete_gl_textures = [](unsigned n, const unsigned *texts) {
1610 glDeleteTextures(n, texts);
1611 };
1612#else
1613 RoutePoint::delete_gl_textures = [](unsigned n, const unsigned *texts) {};
1614#endif
1615
1616#ifdef __ANDROID__
1617 // We need a resize to pick up height adjustment after building android
1618 // ActionBar
1619 gFrame->SetSize(getAndroidDisplayDimensions());
1620 androidSetFollowTool(gFrame->GetPrimaryCanvas()->m_bFollow ? 1 : 0, true);
1621#endif
1622
1623 // Setup Tides/Currents to settings present at last shutdown
1624 // TODO
1625 // gFrame->ShowTides( g_bShowTide );
1626 // gFrame->ShowCurrents( g_bShowCurrent );
1627
1628 // wxLogMessage( wxString::Format("OpenCPN Initialized in %ld ms.",
1629 // init_sw.Time() ) );
1630}
1631
1632void MyApp::LoadChartDatabase() {
1633 // Build the initial chart dir array
1634 ArrayOfCDI ChartDirArray;
1635 pConfig->LoadChartDirArray(ChartDirArray);
1636
1637 // Windows installer may have left hints regarding the initial chart dir
1638 // selection
1639#ifdef __WXMSW__
1640 if (g_bFirstRun && (ChartDirArray.GetCount() == 0)) {
1641 int ndirs = 0;
1642
1643 wxRegKey RegKey(wxString("HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenCPN"));
1644 if (RegKey.Exists()) {
1645 wxLogMessage(
1646 _("Retrieving initial Chart Directory set from Windows Registry"));
1647 wxString dirs;
1648 RegKey.QueryValue(wxString("ChartDirs"), dirs);
1649
1650 wxStringTokenizer tkz(dirs, ";");
1651 while (tkz.HasMoreTokens()) {
1652 wxString token = tkz.GetNextToken();
1653
1654 ChartDirInfo cdi;
1655 cdi.fullpath = token.Trim();
1656 cdi.magic_number = "";
1657
1658 ChartDirArray.Add(cdi);
1659 ndirs++;
1660 }
1661 }
1662
1663 if (g_bportable) {
1664 ChartDirInfo cdi;
1665 cdi.fullpath = "charts";
1666 cdi.fullpath.Prepend(g_Platform->GetSharedDataDir());
1667 cdi.magic_number = "";
1668 ChartDirArray.Add(cdi);
1669 ndirs++;
1670 }
1671
1672 if (ndirs) pConfig->UpdateChartDirs(ChartDirArray);
1673 }
1674#endif
1675
1676 // If the ChartDirArray is empty at this point, any existing chart database
1677 // file must be declared invalid, So it is best to simply delete it if
1678 // present.
1679 // TODO There is a possibility of recreating the dir list from the
1680 // database itself......
1681
1682 if (!ChartDirArray.GetCount())
1683 if (::wxFileExists(ChartListFileName)) ::wxRemoveFile(ChartListFileName);
1684
1685 // Try to load the current chart list Data file
1686 ChartData = new ChartDB();
1687 if (g_NeedDBUpdate == 0 &&
1688 !ChartData->LoadBinary(ChartListFileName, ChartDirArray)) {
1689 g_NeedDBUpdate = 1;
1690 }
1691
1692 // Verify any saved chart database startup index
1693 if (g_restore_dbindex >= 0) {
1694 if (ChartData->GetChartTableEntries() == 0)
1695 g_restore_dbindex = -1;
1696
1697 else if (g_restore_dbindex > (ChartData->GetChartTableEntries() - 1))
1698 g_restore_dbindex = 0;
1699 }
1700
1701 // Apply the inital Group Array structure to the chart database
1702 ChartData->ApplyGroupArray(g_pGroupArray);
1703}
1704
1706 wxLogMessage("opencpn::MyApp starting exit.");
1707 m_checker.OnExit();
1708 m_usb_watcher.Stop();
1709 // Send current nav status data to log file // pjotrc 2010.02.09
1710
1711 wxDateTime lognow = wxDateTime::Now();
1712 lognow.MakeGMT();
1713 wxString day = lognow.FormatISODate();
1714 wxString utc = lognow.FormatISOTime();
1715 wxString navmsg = "LOGBOOK: ";
1716 navmsg += day;
1717 navmsg += " ";
1718 navmsg += utc;
1719 navmsg += " UTC ";
1720
1721 if (bGPSValid) {
1722 wxString data;
1723 data.Printf("OFF: Lat %10.5f Lon %10.5f ", gLat, gLon);
1724 navmsg += data;
1725
1726 wxString cog;
1727 if (std::isnan(gCog))
1728 cog.Printf("COG ----- ");
1729 else
1730 cog.Printf("COG %10.5f ", gCog);
1731
1732 wxString sog;
1733 if (std::isnan(gSog))
1734 sog.Printf("SOG ----- ");
1735 else
1736 sog.Printf("SOG %6.2f " + getUsrSpeedUnit(), toUsrSpeed(gSog));
1737
1738 navmsg += cog;
1739 navmsg += sog;
1740
1741 } else {
1742 wxString data;
1743 data.Printf("OFF: Lat %10.5f Lon %10.5f", gLat, gLon);
1744 navmsg += data;
1745 }
1746 wxLogMessage(navmsg);
1747 g_loglast_time = lognow;
1748
1749 if (ptcmgr) delete ptcmgr;
1750
1751 for (Track *track : g_TrackList) {
1752 delete track;
1753 }
1754 g_TrackList.clear();
1755
1756 delete pConfig;
1757 delete pSelect;
1758 delete pSelectTC;
1759 delete pSelectAIS;
1760
1761 delete ps52plib;
1762 delete g_SencThreadManager;
1763
1764 if (g_pGroupArray) {
1765 for (unsigned int igroup = 0; igroup < g_pGroupArray->GetCount();
1766 igroup++) {
1767 delete g_pGroupArray->Item(igroup);
1768 }
1769
1770 g_pGroupArray->Clear();
1771 delete g_pGroupArray;
1772 }
1773
1774 wxLogMessage("opencpn::MyApp exiting cleanly...\n");
1775 wxLog::FlushActive();
1776
1777 g_Platform->CloseLogFile();
1778
1779 delete pInit_Chart_Dir;
1780
1781 for (Track *track : g_TrackList) {
1782 delete track;
1783 }
1784 g_TrackList.clear();
1785
1786 delete g_pRouteMan;
1787 delete pWayPointMan;
1788
1789 navutil::DeinitGlobals();
1790
1791 DeInitializeUserColors();
1792
1793 delete pLayerList;
1794
1795 delete m_pRegistrarMan;
1796 CSVDeaccess(NULL);
1797
1798 delete g_StyleManager;
1799
1800 // Restore any changed system colors
1801
1802#ifdef __WXMSW__
1803 void RestoreSystemColors();
1804 RestoreSystemColors();
1805#endif
1806
1807#ifdef __MSVC__LEAK
1808 DeInitAllocCheck();
1809#endif
1810
1811#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1813#endif
1814
1815 FontMgr::Shutdown();
1816
1817 g_Platform->OnExit_2();
1819 delete g_Platform;
1820
1821 return TRUE;
1822}
1823
1824#ifdef LINUX_CRASHRPT
1825void MyApp::OnFatalException() { g_crashprint.Report(); }
1826#endif
1827
1828//----------------------------------------------------------------------------------------------------------
1829// Application-wide CPL Error handler
1830//----------------------------------------------------------------------------------------------------------
1831void MyCPLErrorHandler(CPLErr eErrClass, int nError, const char *pszErrorMsg)
1832
1833{
1834 char msg[256];
1835
1836 if (eErrClass == CE_Debug)
1837 snprintf(msg, 255, "CPL: %s", pszErrorMsg);
1838 else if (eErrClass == CE_Warning)
1839 snprintf(msg, 255, "CPL Warning %d: %s", nError, pszErrorMsg);
1840 else
1841 snprintf(msg, 255, "CPL ERROR %d: %s", nError, pszErrorMsg);
1842
1843 wxString str(msg, wxConvUTF8);
1844 wxLogMessage(str);
1845}
class About
Class AboutFrameImpl.
Select * pSelectAIS
Global instance.
wxString AISTargetNameFileName
Global instance.
Class AisDecoder and helpers.
Global state for AIS decoder.
Class AISTargetAlertDialog and helpers.
Class AISTargetListDialog.
Class AISTargetQueryDialog.
BasePlatform * g_BasePlatform
points to g_platform, handles brain-dead MS linker.
Chart canvas configuration state
Purpose: TLS Certificate support.
ChartDB * ChartData
Global instance.
Definition chartdb.cpp:70
Charts database management
ChartGroupArray * g_pGroupArray
Global instance.
Definition chartdbs.cpp:56
Generic Chart canvas base.
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
EventVar reverse_route
Notified with a string GUID when user wants to reverse a route.
EventVar activate_route
Notified with a string GUID when user wants to activate a route.
A modal message dialog with confirmation button and cancel button.
ChartCanvas - Main chart display and interaction component.
Definition chcanv.h:157
double GetPixPerMM()
Get the number of logical pixels per millimeter on the screen.
Definition chcanv.h:515
Manages the chart database and provides access to chart data.
Definition chartdb.h:95
bool LoadBinary(const wxString &filename, ArrayOfCDI &dir_array_check)
Load the chart database from a binary file.
Definition chartdb.cpp:229
void Notify() override
Notify all listeners, no data supplied.
static void SeedRandom()
Seed the random generator used by GetUUID().
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()
void BuildMainFrame()
bool OnInit() override
Definition ocpn_app.cpp:694
void OnMainFrameReady()
int OnExit() override
Main application frame.
Definition ocpn_frame.h:139
Provides platform-specific support utilities for OpenCPN.
void SetDisplaySizeMM(size_t monitor, double size)
Set the width of the monitor in millimeters.
double GetDisplaySizeMM()
Get the width of the screen in millimeters.
void Init(const KeyProvider &kp, const std::function< void(ObservedEvt &ev)> &action)
Initiate an object yet not listening.
Definition observable.h:295
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.
Represents a waypoint or mark within the navigation system.
Definition route_point.h:71
static std::function< void(unsigned, const unsigned *)> delete_gl_textures
Horrible Hack (tm).
Definition route_point.h:47
Represents a navigational route in the navigation system.
Definition route.h:99
bool m_bRtIsSelected
Flag indicating whether this route is currently selected in the UI.
Definition route.h:203
wxString m_RouteNameString
User-assigned name for the route.
Definition route.h:247
EventVar on_routes_update
Notified when list of routes is updated (no data in event)
Definition routeman.h:265
bool ActivateRoute(Route *pRouteToActivate, RoutePoint *pStartPoint=NULL)
Activates a route for navigation.
Definition routeman.cpp:222
Window for displaying chart thumbnails.
Definition thumbwin.h:47
Represents a track, which is a series of connected track points.
Definition track.h:117
Listen to hardware events and notifies SystemEvents when new devices are plugged in.
OpenGL chart rendering canvas.
Handles crash reporting in wxWidgets applications.
Definition crashprint.h:24
Class cm93chart and helpers – CM93 chart state.
Global variables reflecting command line options and arguments.
CommBridge class and helpers.
NMEA Data Multiplexer Object.
Variables maintained by comm stack, read-only access for others.
Primary navigation console display for route and vessel tracking.
Config file user configuration interface.
std::vector< size_t > g_config_display_size_mm
Size of pysical screen in millimeters.
double g_display_size_mm
Physical display width (mm)
Global variables stored in configuration file.
Dump debug info on crash.
Chart display details slider.
Font list manager.
NMEA Data Object.
OpenGL chart rendering canvas.
Platform independent GL includes.
glTextureManager * g_glTextureManager
Global instance.
OpenGL texture cache.
Go to position dialog...
size_t g_current_monitor
Current monitor displaying main application frame.
Definition gui_vars.cpp:75
int g_NeedDBUpdate
0 - No update needed, 1 - Update needed because there is no chart database, inform user 2 - Start upd...
Definition gui_vars.cpp:94
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
Instance check interface.
Chart object layer.
The local API has a server side handling commands and a client part issuing commands.
Enhanced logging interface on top of wx/log.h.
MacOS hardware probing functions.
Waypoint properties maintenance dialog.
mDNS lookup wrappers.
Start/stop mdns service routines.
Multiplexer class and helpers.
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.
Definition safe_mode.cpp:62
MySQL based storage for routes, tracks, etc.
Utility functions.
Navigation Utility Functions without GUI dependencies.
User notifications manager.
s57RegistrarMgr * m_pRegistrarMan
Global instance.
Definition o_senc.cpp:62
S57 SENC File Object.
General observable implementation with several specializations.
OpenCPN main program.
OCPN_AUIManager * g_pauimgr
Global instance.
OCPN_AUIManager.
OpenCPN top window.
OpenCPN Platform specific support utilities.
Options dialog.
bool bGPSValid
Indicate whether the Global Navigation Satellite System (GNSS) has a valid position.
Definition own_ship.cpp:34
double gLat
Vessel's current latitude in decimal degrees.
Definition own_ship.cpp:26
double gCog
Course over ground in degrees (0-359.99).
Definition own_ship.cpp:28
double gSog
Speed over ground in knots.
Definition own_ship.cpp:29
double gLon
Vessel's current longitude in decimal degrees.
Definition own_ship.cpp:27
Position, course, speed, etc.
Plugin remote repositories installation and Uninstall/list operations.
PlugInManager * g_pi_manager
Global instance.
REST server dialogs.
Route abstraction.
Route properties dialog.
RoutePoint * pAnchorWatchPoint2
Global instance.
Definition routeman.cpp:64
Routeman * g_pRouteMan
Global instance.
Definition routeman.cpp:60
RouteList * pRouteList
Global instance.
Definition routeman.cpp:66
RoutePoint * pAnchorWatchPoint1
Global instance.
Definition routeman.cpp:63
Route Manager.
Routeman drawing stuff.
Manage routes dialog.
S57 object query result window.
S57 Chart Object.
Select * pSelect
Global instance.
Definition select.cpp:36
Select * pSelectTC
Global instance.
Definition select.cpp:37
Selected route, segment, waypoint, etc.
SENCThreadManager * g_SencThreadManager
Global instance.
Chart Symbols.
TCMgr * ptcmgr
Global instance.
Definition tcmgr.cpp:42
Tide and Current Manager @TODO Add original author copyright.
ThumbWin * pthumbwin
Global instance.
Definition thumbwin.cpp:40
Chart thumbnail object.
std::vector< Track * > g_TrackList
Global instance.
Definition track.cpp:96
Recorded track abstraction.
Track Properties Dialog.
Access checks for comm devices and dongle.