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