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
487void MyApp::OnUnhandledException() {
488 // Copied from src/common/appbase.cpp in wxWidgets source, just fix a
489 // #ifdef. We're called from an exception handler so we can re-throw the
490 // exception to recover its type
491 wxString what;
492 try {
493 throw;
494 } catch (std::exception &e) {
495#ifdef wxNO_RTTI
496 what.Printf("standard exception with message \"%s\"", e.what());
497#else
498 what.Printf("standard exception of type \"%s\" with message \"%s\"",
499 typeid(e).name(), e.what());
500#endif
501 } catch (...) {
502 what = "unknown exception";
503 }
504 wxMessageOutputBest().Printf(
505 "Unhandled %s; terminating %s.\n", what,
506 wxIsMainThread() ? "the application" : "the thread in which it happened");
507}
508
509bool MyApp::OpenFile(const std::string &path) {
510 NavObjectCollection1 nav_objects;
511 auto result = nav_objects.load_file(path.c_str());
512 if (!result) {
513 std::string s(_("Cannot load route or waypoint file: "));
514 s += std::string("\"") + path + "\"";
515 wxMessageBox(s, "OpenCPN", wxICON_WARNING | wxOK);
516 return false;
517 }
518
519 int wpt_dups;
520 // Import with full vizibility of names and objects
521 nav_objects.LoadAllGPXObjects(!nav_objects.IsOpenCPN(), wpt_dups, true);
522
523 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
524 pRouteManagerDialog->UpdateLists();
525 LLBBox box = nav_objects.GetBBox();
526 if (box.GetValid()) {
527 gFrame->CenterView(gFrame->GetPrimaryCanvas(), box);
528 }
529 return true;
530}
531
532#ifndef __ANDROID__
533void MyApp::OnInitCmdLine(wxCmdLineParser &parser) {
534 // Add OpenCPN specific command line options. Help message
535 // is hardcoded in kUsage;
536 parser.AddSwitch("h", "help", "", wxCMD_LINE_OPTION_HELP);
537 parser.AddSwitch("p", "portable");
538 parser.AddOption("c", "configdir", "", wxCMD_LINE_VAL_STRING,
539 wxCMD_LINE_PARAM_OPTIONAL);
540 parser.AddSwitch("f", "fullscreen");
541 parser.AddSwitch("G", "no_opengl");
542 parser.AddSwitch("W", "config_wizard");
543 parser.AddSwitch("g", "rebuild_gl_raster_cache");
544 parser.AddSwitch("D", "rebuild_chart_db");
545 parser.AddSwitch("P", "parse_all_enc");
546 parser.AddOption("l", "loglevel");
547 parser.AddOption("u", "unit_test_1", "", wxCMD_LINE_VAL_NUMBER);
548 parser.AddSwitch("U", "unit_test_2");
549 parser.AddParam("import GPX files", wxCMD_LINE_VAL_STRING,
550 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
551 parser.AddSwitch("s", "safe_mode");
552 parser.AddSwitch("r", "remote");
553 parser.AddSwitch("R", "raise");
554 parser.AddSwitch("q", "quit");
555 parser.AddSwitch("e", "get_rest_endpoint");
556 parser.AddOption("o", "open", "", wxCMD_LINE_VAL_STRING,
557 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
558}
559#endif // __ANDROID__
560
562#ifdef __ANDROID__
563static void ParseLoglevel(wxCmdLineParser &parser) {
564 wxLog::SetLogLevel(wxLOG_Message);
565}
566#else
567static void ParseLoglevel(wxCmdLineParser &parser) {
568 const char *strLevel = std::getenv("OPENCPN_LOGLEVEL");
569 strLevel = strLevel ? strLevel : "info";
570 wxString wxLevel;
571 if (parser.Found("l", &wxLevel)) {
572 strLevel = wxLevel.c_str();
573 }
574 wxLogLevel level = OcpnLog::str2level(strLevel);
575 if (level == OcpnLog::LOG_BADLEVEL) {
576 fprintf(stderr, "Bad loglevel %s, using \"info\"", strLevel);
577 level = wxLOG_Info;
578 }
579 wxLog::SetLogLevel(level);
580}
581#endif // __ANDROID__
582
583#ifndef __ANDROID__
584bool MyApp::OnCmdLineHelp(wxCmdLineParser &parser) {
585 std::cout << kUsage;
586 return false;
587}
588#endif
589
590#ifndef __ANDROID__
591bool MyApp::OnCmdLineParsed(wxCmdLineParser &parser) {
592 long number;
593 wxString repo;
594 wxString plugin;
595
596 g_unit_test_2 = parser.Found("unit_test_2");
597 g_bportable = parser.Found("p");
598 g_start_fullscreen = parser.Found("fullscreen");
599 g_bdisable_opengl = parser.Found("no_opengl");
600 g_rebuild_gl_cache = parser.Found("rebuild_gl_raster_cache");
601 g_NeedDBUpdate = parser.Found("rebuild_chart_db") ? 2 : 0;
602 g_parse_all_enc = parser.Found("parse_all_enc");
603 g_config_wizard = parser.Found("config_wizard");
604 if (parser.Found("unit_test_1", &number)) {
605 g_unit_test_1 = static_cast<int>(number);
606 if (g_unit_test_1 == 0) g_unit_test_1 = -1;
607 }
608 safe_mode::set_mode(parser.Found("safe_mode"));
609 ParseLoglevel(parser);
610 wxString wxstr;
611 if (parser.Found("configdir", &wxstr)) {
612 g_configdir = wxstr.ToStdString();
613 fs::path path(g_configdir);
614 if (!fs::exists(path) || !fs::is_directory(path)) {
615 std::cerr << g_configdir << " is not an existing directory.\n";
616 return false;
617 }
618 }
619
620 bool has_start_options = false;
621 static const std::vector<std::string> kStartOptions = {
622 "unit_test_2",
623 "p",
624 "fullscreen",
625 "no_opengl",
626 "rebuild_gl_raster_cache",
627 "rebuild_chart_db",
628 "parse_all_enc",
629 "unit_test_1",
630 "safe_mode",
631 "loglevel"};
632 for (const auto &opt : kStartOptions) {
633 if (parser.Found(opt)) has_start_options = true;
634 }
635 if (has_start_options && parser.Found("remote")) {
636 std::cerr << "this option is not compatible with --remote\n";
637 return false;
638 }
639
640 bool has_remote_options = false;
641 static const std::vector<std::string> kRemoteOptions = {
642 "raise", "quit", "open", "get_rest_endpoint"};
643 for (const auto &opt : kRemoteOptions) {
644 if (parser.Found(opt)) has_remote_options = true;
645 }
646 if (has_remote_options && !parser.Found("remote")) {
647 std::cerr << "This option requires --remote\n";
648 return false;
649 }
650
651 for (size_t paramNr = 0; paramNr < parser.GetParamCount(); ++paramNr)
652 g_params.push_back(parser.GetParam(paramNr).ToStdString());
653
654 wxString optarg;
655 if (!parser.Found("remote"))
656 m_parsed_cmdline = ParsedCmdline();
657 else if (parser.Found("raise"))
658 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Raise);
659 else if (parser.Found("quit"))
660 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Quit);
661 else if (parser.Found("get_rest_endpoint"))
662 m_parsed_cmdline = ParsedCmdline(CmdlineAction::GetRestEndpoint);
663 else if (parser.Found("open", &optarg))
664 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Open, optarg.ToStdString());
665 else if (parser.GetParamCount() == 1)
666 m_parsed_cmdline =
667 ParsedCmdline(CmdlineAction::Open, parser.GetParam(0).ToStdString());
668 else if (!has_start_options && !has_remote_options) {
669 // Neither arguments nor options
670 m_parsed_cmdline = ParsedCmdline(CmdlineAction::Raise);
671 }
672 return true;
673}
674#endif // __ANDROID__
675
676#ifdef __WXMSW__
677// Handle any exception not handled by CrashRpt
678// Most probable: Malloc/new failure
679
680bool MyApp::OnExceptionInMainLoop() {
681 wxLogWarning("Caught MainLoopException, continuing...");
682 return true;
683}
684#endif
685
686void MyApp::OnActivateApp(wxActivateEvent &event) { return; }
687
688static wxStopWatch init_sw;
689
690int MyApp::OnRun() {
691 if (m_exitcode != -2) return m_exitcode;
692 return wxAppConsole::OnRun();
693}
694
695MyApp::MyApp()
696 : m_checker(InstanceCheck::GetInstance()),
697 m_rest_server(PINCreateDialog::GetDlgCtx(), RouteCtxFactory(),
698 g_bportable),
699 m_usb_watcher(UsbWatchDaemon::GetInstance()),
700 m_exitcode(-2) {
701#ifdef __linux__
702 // Handle e. g., wayland default display -- see #1166.
703 if (!wxGetEnv("OCPN_DISABLE_X11_GDK_BACKEND", NULL)) {
704 if (wxGetEnv("WAYLAND_DISPLAY", NULL)) {
705 setenv("GDK_BACKEND", "x11", 1);
706 }
707 }
708 setenv(
709 "mesa_glthread", "false",
710 1); // Explicitly disable glthread. This may have some impact on OpenGL
711 // performance, but we know it is problematic for us. See #2889
712#endif // __linux__
713}
714
715WallpaperFrame *g_wallpaper;
716
718 if (!wxApp::OnInit()) return false;
719
720#ifdef __ANDROID__
721 androidEnableBackButton(false);
722 androidEnableOptionItems(false);
723#endif
724
726
727#if defined(__WXGTK__) && defined(ocpnUSE_GLES) && defined(__ARM_ARCH)
728 // There is a race condition between cairo which is used for text rendering
729 // by gtk and EGL which without the below code causes a bus error and the
730 // program aborts before startup
731 // this hack forces cairo to load right now by rendering some text
732
733 wxBitmap bmp(10, 10, -1);
734 wxMemoryDC dc;
735 dc.SelectObject(bmp);
736 dc.DrawText("X", 0, 0);
737#endif
738
739 // Instantiate the global OCPNPlatform class
740 g_Platform = new OCPNPlatform;
741 g_BasePlatform = g_Platform;
742#ifndef __ANDROID__
743 // We allow only one instance unless the portable option is used
744 if (!g_bportable && wxDirExists(g_Platform->GetPrivateDataDir())) {
745 m_checker.WaitUntilValid();
746 if (m_checker.IsMainInstance()) {
747 // Server is created on first call to GetInstance()
748 if (m_parsed_cmdline.action == CmdlineAction::Skip) {
749 // Server starts running when referenced.
750 [[maybe_unused]] auto &server = LocalServerApi::GetInstance();
751 } else {
752 std::cerr << "No remote opencpn found. Giving up.\n";
753 m_exitcode = 1;
754 return true;
755 }
756 } else {
757 std::unique_ptr<LocalClientApi> client;
758 try {
759 client = LocalClientApi::GetClient();
760 } catch (LocalApiException &ie) {
761 WARNING_LOG << "Ipc client exception: " << ie.str();
762 // If we get here it means that the instance_chk found another
763 // running instance. But that instance is for some reason not
764 // reachable. The safe thing to do is delete the lockfile and exit.
765 // Next start will proceed normally. This may leave a zombie OpenCPN,
766 // but at least O starts.
767 m_checker.CleanUp();
768 wxMessageBox(_("Sorry, an existing instance of OpenCPN may be too busy "
769 "to respond.\nPlease retry."),
770 "OpenCPN", wxICON_INFORMATION | wxOK);
771 m_exitcode = 2;
772 return true; // main program quiet exit.
773 }
774 if (client) {
775 auto result = client->HandleCmdline(m_parsed_cmdline.action,
776 m_parsed_cmdline.arg);
777 if (result.first) {
778 m_exitcode = 0;
779 } else {
780 wxLogDebug("Error running remote command: %s", result.second.c_str());
781 m_exitcode = 1;
782 }
783 return true;
784 }
785 }
786 }
787#endif // __ANDROID__
788
789 if (getenv("OPENCPN_FATAL_ERROR") != 0) {
790 wxLogFatalError(getenv("OPENCPN_FATAL_ERROR"));
791 }
792
793#ifndef __ANDROID__
794 // Check if last run failed, set up safe_mode.
795 if (!safe_mode::get_mode()) {
797 }
798#endif
799
800 // Perform first stage initialization
801 OCPNPlatform::Initialize_1();
802
803 // Set the name of the app as displayed to the user.
804 // This is necessary at least on OS X, for the capitalisation to be correct in
805 // the system menus.
806 MyApp::SetAppDisplayName("OpenCPN");
807
808 // Seed the random number generator
809 wxDateTime x = wxDateTime::UNow();
810 long seed = x.GetMillisecond();
811 seed *= x.GetTicks();
812 srand(seed);
813
814 // Fulup: force floating point to use dot as separation.
815 // This needs to be set early to catch numerics in config file.
816 setlocale(LC_NUMERIC, "C");
817
818 g_start_time = wxDateTime::Now();
819
820 g_loglast_time = g_start_time;
821 g_loglast_time.MakeGMT();
822 g_loglast_time.Subtract(
823 wxTimeSpan(0, 29, 0, 0)); // give 1 minute for GPS to get a fix
824
825 AnchorPointMinDist = 5.0;
826
827 // Init the private memory manager
828 malloc_max = 0;
829
830 // Record initial memory status
831 platform::GetMemoryStatus(&g_mem_total, &g_mem_initial);
832
833 // Set up default FONT encoding, which should have been done by wxWidgets some
834 // time before this......
835 wxFont temp_font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
836 wxFONTWEIGHT_NORMAL, FALSE, wxString(""),
837 wxFONTENCODING_SYSTEM);
838 temp_font.SetDefaultEncoding(wxFONTENCODING_SYSTEM);
839
840 // Start the Notification Manager and remove old persisted messages
841 auto &noteman = NotificationManager::GetInstance();
842 noteman.ScrubNotificationDirectory(30);
843
844 // Establish Log File location
845 if (!g_Platform->InitializeLogFile()) {
846 return false;
847 };
848
849#ifdef __WXMSW__
850
851 // Un-comment the following to establish a separate console window as a
852 // target for printf() in Windows RedirectIOToConsole();
853
854#endif
855
856 // Send init message
857 wxLogMessage("\n\n________\n");
858
859 wxDateTime now = wxDateTime::Now();
860 LOG_INFO("------- OpenCPN version %s restarted at %s -------\n", VERSION_FULL,
861 now.FormatISODate().mb_str().data());
862 wxLogLevel level = wxLog::GetLogLevel();
863 LOG_INFO("Using loglevel %s", OcpnLog::level2str(level).c_str());
864
865 wxString wxver(wxVERSION_STRING);
866 wxver.Prepend("wxWidgets version: ");
867
868 wxPlatformInfo platforminfo = wxPlatformInfo::Get();
869
870 wxString os_name;
871#ifndef __ANDROID__
872 os_name = platforminfo.GetOperatingSystemIdName();
873#else
874 os_name = platforminfo.GetOperatingSystemFamilyName();
875#endif
876
877 wxString platform = os_name + " " + platforminfo.GetArchName() + " " +
878 platforminfo.GetPortIdName();
879
880 wxLogMessage(wxver + " " + platform);
881
882 ::wxGetOsVersion(&osMajor, &osMinor);
883 wxString osVersionMsg;
884 osVersionMsg.Printf("OS Version reports as: %d.%d", osMajor, osMinor);
885 wxLogMessage(osVersionMsg);
886
887 wxLogMessage("MemoryStatus: mem_total: %d mb, mem_initial: %d mb",
888 g_mem_total / 1024, g_mem_initial / 1024);
889
890 OCPN_OSDetail *detail = g_Platform->GetOSDetail();
891 wxString msgplat;
892 wxString like0;
893 if (!detail->osd_names_like.empty())
894 like0 = detail->osd_names_like[0].c_str();
895 msgplat.Printf("OCPN_OSDetail: %s ; %s ; %s ; %s ; %s",
896 detail->osd_arch.c_str(), detail->osd_name.c_str(),
897 detail->osd_version.c_str(), detail->osd_ID.c_str(),
898 like0.mb_str());
899 wxLogMessage(msgplat);
900
901 wxString imsg = "SData_Locn is ";
902 imsg += g_Platform->GetSharedDataDir();
903 wxLogMessage(imsg);
904
905 // Initialize embedded PNG icon graphics
906 ::wxInitAllImageHandlers();
907
908#ifdef __WXQT__
909 // Now we can configure the Qt StyleSheets, if present
910 prepareAndroidStyleSheets();
911#endif
912
913 // Create some static strings
914 pInit_Chart_Dir = new wxString();
915
916 // Establish an empty ChartCroupArray
917 g_pGroupArray = new ChartGroupArray;
918
919 imsg = "PrivateDataDir is ";
920 imsg += g_Platform->GetPrivateDataDir();
921 wxLogMessage(imsg);
922
923 // Create an array string to hold repeating messages, so they don't
924 // overwhelm the log
925 navutil::InitGlobals();
926
927 // Init the Route Manager
929 new Routeman(RoutePropDlg::GetDlgCtx(), RoutemanGui::GetDlgCtx());
930
931 // Init the Selectable Route Items List
932 pSelect = new Select();
933 pSelect->SetSelectPixelRadius(12);
934
935 // Init the Selectable Tide/Current Items List
936 pSelectTC = new Select();
937 // Increase the select radius for tide/current stations
938 pSelectTC->SetSelectPixelRadius(25);
939
940 // Init the Selectable AIS Target List
941 pSelectAIS = new Select();
942 pSelectAIS->SetSelectPixelRadius(12);
943
944 // Initially AIS display is always on
945 g_bShowAIS = true;
946 g_pais_query_dialog_active = NULL;
947
948 // Who am I?
949 g_hostname = ::wxGetHostName();
950 if (g_hostname.IsEmpty()) g_hostname = wxGetUserName();
951#ifdef __ANDROID__
952 androidGetDeviceInfo();
953 g_hostname = wxString("Android-") + g_android_Device_Model;
954 g_hostname.Replace(" ", "-", true);
955#endif
956
957 // A Portabel need a unique mDNS data hostname to share routes.
958 if (g_bportable) {
959 wxString p("Portable-");
960 g_hostname = p + g_hostname;
961 }
962
963 // Initialize some lists
964 // Layers
965 pLayerList = new LayerList;
966 // Routes
967 pRouteList = new RouteList;
968
969 // Initialize the NavObj_db
970 auto &navobj_db = NavObj_dB::GetInstance();
971
972 // (Optionally) Capture the user and file(effective) ids
973 // Some build environments may need root privileges for hardware
974 // port I/O, as in the NMEA data input class. Set that up here.
975
976#ifndef __WXMSW__
977#ifdef PROBE_PORTS__WITH_HELPER
978 user_user_id = getuid();
979 file_user_id = geteuid();
980#endif
981#endif
982
983 bool b_initial_load = false;
984
985 wxFileName config_test_file_name(g_Platform->GetConfigFileName());
986 if (config_test_file_name.FileExists())
987 wxLogMessage("Using existing Config_File: " +
988 g_Platform->GetConfigFileName());
989 else {
990 {
991 wxLogMessage("Creating new Config_File: " +
992 g_Platform->GetConfigFileName());
993
994 b_initial_load = true;
995
996 if (true !=
997 config_test_file_name.DirExists(config_test_file_name.GetPath()))
998 if (!config_test_file_name.Mkdir(config_test_file_name.GetPath()))
999 wxLogMessage("Cannot create config file directory for " +
1000 g_Platform->GetConfigFileName());
1001 }
1002 }
1003
1004 // Open/Create the Config Object
1005 pConfig = g_Platform->GetConfigObject();
1006 InitBaseConfig(pConfig);
1007 pConfig->LoadMyConfig();
1008
1009 if (g_kiosk_startup) {
1010 g_wallpaper = new WallpaperFrame();
1011 g_wallpaper->ShowFullScreen(true); // For a kiosk app, make it fullscreen
1012 g_wallpaper->Show();
1013 }
1014
1015 // Override for some safe and nice default values if the config file was
1016 // created from scratch
1017 if (b_initial_load) g_Platform->SetDefaultOptions();
1018
1019 g_Platform->applyExpertMode(g_bUIexpert);
1020
1021 // Now initialize UI Style.
1022 g_StyleManager = new ocpnStyle::StyleManager();
1023
1024 g_StyleManager->SetStyle("MUI_flat");
1025 if (!g_StyleManager->IsOK()) {
1026 wxString msg = _("Failed to initialize the user interface. ");
1027 msg << _("OpenCPN cannot start. ");
1028 msg << _("The necessary configuration files were not found. ");
1029 msg << _("See the log file at ") << g_Platform->GetLogFileName()
1030 << _(" for details.") << "\n\n";
1031 msg << g_Platform->GetSharedDataDir();
1032
1033 wxMessageDialog w(NULL, msg, _("Failed to initialize the user interface. "),
1034 wxCANCEL | wxICON_ERROR);
1035 w.ShowModal();
1036 exit(EXIT_FAILURE);
1037 }
1038
1039 if (g_useMUI) {
1040 ocpnStyle::Style *style = g_StyleManager->GetCurrentStyle();
1041 if (style) style->chartStatusWindowTransparent = true;
1042 }
1043
1044 // Init the WayPoint Manager
1045 pWayPointMan = NULL;
1046
1047 g_display_size_mm = wxMax(50, g_Platform->GetDisplaySizeMM());
1048 wxString msg;
1049 msg.Printf("Detected display size (horizontal): %d mm",
1050 (int)g_display_size_mm);
1051 wxLogMessage(msg);
1052
1053 // User override....
1054 if (g_config_display_size_manual &&
1058 wxString msg;
1059 msg.Printf("Display size (horizontal) config override: %d mm",
1060 (int)g_display_size_mm);
1061 wxLogMessage(msg);
1063 }
1064
1066
1067 if (g_btouch) {
1068 int SelectPixelRadius = 50;
1069
1070 pSelect->SetSelectPixelRadius(SelectPixelRadius);
1071 pSelectTC->SetSelectPixelRadius(wxMax(25, SelectPixelRadius));
1072 pSelectAIS->SetSelectPixelRadius(SelectPixelRadius);
1073 }
1074
1075 // Is this the first run after a clean installation?
1076 if (!n_NavMessageShown) {
1077 g_bFirstRun = true;
1078 }
1079
1080 // Now we can set the locale
1081 // using wxWidgets/gettext methodology....
1082
1083#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1084
1085 // Where are the opencpn.mo files?
1086 g_Platform->SetLocaleSearchPrefixes();
1087
1088 wxString def_lang_canonical = g_Platform->GetDefaultSystemLocale();
1089
1090 imsg = "System default Language: " + def_lang_canonical;
1091 wxLogMessage(imsg);
1092
1093 wxString cflmsg = "Config file language: " + g_locale;
1094 wxLogMessage(cflmsg);
1095
1096 if (g_locale.IsEmpty()) {
1097 g_locale = def_lang_canonical;
1098 cflmsg = "Config file language empty, using system default: " + g_locale;
1099 wxLogMessage(cflmsg);
1100 }
1101
1102 // Make any adjustments necessary
1103 g_locale = g_Platform->GetAdjustedAppLocale();
1104 cflmsg = "Adjusted App language: " + g_locale;
1105 wxLogMessage(cflmsg);
1106
1107 // Set the desired locale
1108 g_Platform->ChangeLocale(g_locale, plocale_def_lang, &plocale_def_lang);
1109
1110 imsg = "Opencpn language set to: ";
1111 imsg += g_locale;
1112 wxLogMessage(imsg);
1113
1114 // French language locale is assumed to include the AZERTY keyboard
1115 // This applies to either the system language, or to OpenCPN language
1116 // selection
1117 if (g_locale == "fr_FR") g_b_assume_azerty = true;
1118#else
1119 wxLogMessage("wxLocale support not available");
1120#endif
1121
1122#ifndef __ANDROID__
1123 // Now that locale is established, possibly run the startup wizard.
1124 if (g_config_wizard || b_initial_load) {
1125 FirstUseWizImpl wiz(gFrame, pConfig);
1126 auto res = wiz.Run();
1127 if (res) {
1128 g_NeedDBUpdate = 2;
1129 }
1130 }
1131#endif
1132
1133 // Instantiate and initialize the Config Manager
1134 ConfigMgr::Get();
1135
1136 // Is this an upgrade?
1137 wxString vs = wxString("Version ") + VERSION_FULL + " Build " + VERSION_DATE;
1138 g_bUpgradeInProcess = (vs != g_config_version_string);
1139
1140 g_Platform->SetUpgradeOptions(vs, g_config_version_string);
1141
1142 // log deferred log restart message, if it exists.
1143 if (!g_Platform->GetLargeLogMessage().IsEmpty()) {
1144 wxLogMessage(g_Platform->GetLargeLogMessage());
1145 }
1146
1147 // Validate OpenGL functionality, if selected
1148#ifndef ocpnUSE_GL
1149 g_bdisable_opengl = true;
1150#endif
1151
1152 if (g_bdisable_opengl) g_bopengl = false;
1153
1154#if defined(__linux__) && !defined(__ANDROID__)
1155 if (g_bSoftwareGL) {
1156 setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
1157 }
1158#endif
1159
1160 // FIXMW (dave) move to frame
1161 // g_bTransparentToolbarInOpenGLOK = isTransparentToolbarInOpenGLOK();
1162
1163 // On Windows platforms, establish a default cache managment policy
1164 // as allowing OpenCPN a percentage of available physical memory,
1165 // not to exceed 1 GB
1166 // Note that this logic implies that Windows platforms always use
1167 // the memCacheLimit policy, and never use the fallback nCacheLimit policy
1168#ifdef __WXMSW__
1169 if (0 == g_memCacheLimit) g_memCacheLimit = (int)(g_mem_total * 0.5);
1170 g_memCacheLimit =
1171 wxMin(g_memCacheLimit, 1024 * 1024); // math in kBytes, Max is 1 GB
1172#else
1173 // All other platforms will use the nCacheLimit policy
1174 // sinc on linux it is impossible to accurately measure the application memory
1175 // footprint without expensive methods such as malloc/free tracking, and such
1176
1177 g_memCacheLimit = 0;
1178 if (0 == g_nCacheLimit) // allow config file override
1179 g_nCacheLimit = CACHE_N_LIMIT_DEFAULT;
1180#endif
1181
1182 // Establish location and name of chart database
1183 ChartListFileName = newPrivateFileName(g_Platform->GetPrivateDataDir(),
1184 "chartlist.dat", "CHRTLIST.DAT");
1185
1186 // Establish location and name of AIS MMSI -> Target Name mapping
1187 AISTargetNameFileName = newPrivateFileName(g_Platform->GetPrivateDataDir(),
1188 "mmsitoname.csv", "MMSINAME.CSV");
1189
1190 // Establish guessed location of chart tree
1191 if (pInit_Chart_Dir->IsEmpty()) {
1192 wxStandardPaths &std_path = g_Platform->GetStdPaths();
1193
1194 if (!g_bportable)
1195#ifndef __ANDROID__
1196 pInit_Chart_Dir->Append(std_path.GetDocumentsDir());
1197#else
1198 pInit_Chart_Dir->Append(androidGetExtStorageDir());
1199#endif
1200 }
1201
1202 InitRestListeners();
1203
1204 // Establish the GSHHS Dataset location
1205 gDefaultWorldMapLocation = "gshhs";
1206 gDefaultWorldMapLocation.Prepend(g_Platform->GetSharedDataDir());
1207 gDefaultWorldMapLocation.Append(wxFileName::GetPathSeparator());
1208 if (gWorldMapLocation == wxEmptyString) {
1209 gWorldMapLocation = gDefaultWorldMapLocation;
1210 }
1211
1212 // Check the global Tide/Current data source array
1213 // If empty, preset default (US + ROW) data sources
1214 wxString default_tcdata0 =
1215 (g_Platform->GetSharedDataDir() + "tcdata" +
1216 wxFileName::GetPathSeparator() + "harmonics-dwf-20210110-free.tcd");
1217 wxString default_tcdata1 =
1218 (g_Platform->GetSharedDataDir() + "tcdata" +
1219 wxFileName::GetPathSeparator() + "HARMONICS_NO_US.IDX");
1220
1221 if (TideCurrentDataSet.empty()) {
1222 TideCurrentDataSet.push_back(
1223 g_Platform->NormalizePath(default_tcdata0).ToStdString());
1224 TideCurrentDataSet.push_back(
1225 g_Platform->NormalizePath(default_tcdata1).ToStdString());
1226 }
1227
1228 // Check the global AIS alarm sound file
1229 // If empty, preset default
1230 if (g_sAIS_Alert_Sound_File.IsEmpty()) {
1231 wxString default_sound = (g_Platform->GetSharedDataDir() + "sounds" +
1232 wxFileName::GetPathSeparator() + "2bells.wav");
1233 g_sAIS_Alert_Sound_File = g_Platform->NormalizePath(default_sound);
1234 }
1235
1236 gpIDXn = 0;
1237
1238 g_Platform->Initialize_2();
1239
1240 LoadChartDatabase();
1241
1242 // Kiosk startup mode only available in linux/GTK builds.
1243#ifndef __WXGTK__
1244 g_kiosk_startup = false;
1245#endif
1246
1247 // Create and initialize the main application frame.
1248 if (!g_kiosk_startup) {
1250 SetTopWindow(gFrame); // Set the main frame as the new top window.
1251 gFrame->Show();
1252 gFrame->Raise();
1253
1254 // Start delayed initialization chain after some milliseconds
1255 gFrame->InitTimer.Start(50, wxTIMER_CONTINUOUS);
1256
1257 } else {
1258 wxTheApp->CallAfter(&MyApp::OnMainFrameReady);
1259 }
1260
1261 OCPNPlatform::Initialize_4();
1262
1263#ifdef __ANDROID__
1264 androidHideBusyIcon();
1265#endif
1266 wxLogMessage(
1267 wxString::Format(_("OpenCPN Initialized in %ld ms."), init_sw.Time()));
1268
1269 wxMilliSleep(100);
1270
1271 if (!g_kiosk_startup) {
1272 if (!DoNavMessage(vs)) {
1273 Exit();
1274 }
1275 }
1276
1277 // As an a.e. Raspberry does not have a hardwareclock we will have some
1278 // problems with date/time setting
1279 g_bHasHwClock = true; // by default most computers do have a hwClock
1280#if defined(__UNIX__) && !defined(__ANDROID__)
1281 struct stat buffer;
1282 g_bHasHwClock =
1283 ((stat("/dev/rtc", &buffer) == 0) || (stat("/dev/rtc0", &buffer) == 0) ||
1284 (stat("/dev/misc/rtc", &buffer) == 0));
1285#endif
1286
1287 g_config_version_string = vs;
1288
1289 // The user accepted the "not for navigation" nag, so persist it here...
1290 pConfig->UpdateSettings();
1291
1292 for (auto *cp : TheConnectionParams()) {
1293 if (cp->bEnabled) {
1294 if (cp->GetDSPort().Contains("Serial")) {
1295 std::string port(cp->Port.ToStdString());
1297 }
1298 }
1299 }
1301
1302 // Initialize the CommBridge
1303 m_comm_bridge.Initialize();
1304
1305 std::vector<std::string> ipv4_addrs = get_local_ipv4_addresses();
1306
1307 // If network connection is available, start the server and mDNS client
1308 if (ipv4_addrs.size()) {
1309 std::string ipAddr = ipv4_addrs[0];
1310
1311 wxString data_dir = g_Platform->GetPrivateDataDir();
1312 if (data_dir.Last() != wxFileName::GetPathSeparator())
1313 data_dir.Append(wxFileName::GetPathSeparator());
1314
1315 make_certificate(ipAddr, data_dir.ToStdString());
1316
1317 m_rest_server.StartServer(fs::path(data_dir.ToStdString()));
1318 StartMDNSService(g_hostname.ToStdString(), "opencpn-object-control-service",
1319 8000);
1320 }
1321 return TRUE;
1322}
1323
1326 gFrame->Hide();
1327
1328 // Hide the old frame and show the new one.
1329 g_wallpaper->Show(false);
1331
1332 gFrame->ShowFullScreen(true);
1333
1334 // Cleanup the wallpaper frame.
1335 g_wallpaper->Destroy();
1336 g_wallpaper = nullptr;
1337
1338 SetTopWindow(gFrame); // Set the main frame as the new top window.
1339 gFrame->Raise();
1340
1341 wxString vs = wxString("Version ") + VERSION_FULL + " Build " + VERSION_DATE;
1342 if (!DoNavMessage(vs)) {
1343 Exit();
1344 }
1345
1346 // Start delayed initialization chain after some milliseconds
1347 gFrame->InitTimer.Start(50, wxTIMER_CONTINUOUS);
1348}
1349
1351 // Set up the frame initial visual parameters
1352 // Default size, resized later
1353 wxSize new_frame_size(-1, -1);
1354 int cx, cy, cw, ch;
1355 ::wxClientDisplayRect(&cx, &cy, &cw, &ch);
1356
1357 InitializeUserColors();
1358
1359 if ((g_nframewin_x > 100) && (g_nframewin_y > 100) && (g_nframewin_x <= cw) &&
1360 (g_nframewin_y <= ch))
1361 new_frame_size.Set(g_nframewin_x, g_nframewin_y);
1362 else
1363 new_frame_size.Set(cw * 7 / 10, ch * 7 / 10);
1364
1365 // Try to detect any change in physical screen configuration
1366 // This can happen when drivers are changed, for instance....
1367 // and can confuse the WUI layout perspective stored in the config file.
1368 // If detected, force a nominal window size and position....
1369 if ((g_lastClientRectx != cx) || (g_lastClientRecty != cy) ||
1370 (g_lastClientRectw != cw) || (g_lastClientRecth != ch)) {
1371 new_frame_size.Set(cw * 7 / 10, ch * 7 / 10);
1372 g_bframemax = false;
1373 }
1374
1375 g_lastClientRectx = cx;
1376 g_lastClientRecty = cy;
1377 g_lastClientRectw = cw;
1378 g_lastClientRecth = ch;
1379
1380 // Validate config file position
1381 wxPoint position(0, 0);
1382 wxSize dsize = wxGetDisplaySize();
1383
1384#ifdef __WXMAC__
1385 g_nframewin_posy = wxMax(g_nframewin_posy, 22);
1386#endif
1387
1388 if ((g_nframewin_posx < dsize.x) && (g_nframewin_posy < dsize.y))
1389 position = wxPoint(g_nframewin_posx, g_nframewin_posy);
1390
1391#ifdef __WXMSW__
1392 // Support MultiMonitor setups which can allow negative window positions.
1393 RECT frame_rect;
1394 frame_rect.left = position.x;
1395 frame_rect.top = position.y;
1396 frame_rect.right = position.x + new_frame_size.x;
1397 frame_rect.bottom = position.y + new_frame_size.y;
1398
1399 // If the requested frame window does not intersect any installed monitor,
1400 // then default to simple primary monitor positioning.
1401 if (NULL == MonitorFromRect(&frame_rect, MONITOR_DEFAULTTONULL))
1402 position = wxPoint(10, 10);
1403#endif
1404
1405#ifdef __WXOSX__
1406 // Support MultiMonitor setups which can allow negative window positions.
1407 const wxPoint ptScreen(position.x, position.y);
1408 const int displayIndex = wxDisplay::GetFromPoint(ptScreen);
1409
1410 if (displayIndex == wxNOT_FOUND) position = wxPoint(10, 30);
1411#endif
1412
1413 g_nframewin_posx = position.x;
1414 g_nframewin_posy = position.y;
1415
1416#ifdef __ANDROID__
1417 wxSize asz = getAndroidDisplayDimensions();
1418 ch = asz.y;
1419 cw = asz.x;
1420 // qDebug() << cw << ch;
1421
1422 if ((cw > 200) && (ch > 200))
1423 new_frame_size.Set(cw, ch);
1424 else
1425 new_frame_size.Set(800, 400);
1426#endif
1427
1428 // For Windows and GTK, provide the expected application Minimize/Close bar
1429 long app_style = wxDEFAULT_FRAME_STYLE;
1430 app_style |= wxWANTS_CHARS;
1431
1432 // Create the main frame window
1433
1434 // Strip the commit SHA number from the string to be shown in frame title.
1435 wxString short_version_name = wxString(PACKAGE_VERSION).BeforeFirst('+');
1436 wxString myframe_window_title = wxString("OpenCPN " + short_version_name);
1437
1438 if (g_bportable) {
1439 myframe_window_title += _(" -- [Portable(-p) executing from ");
1440 myframe_window_title += g_Platform->GetHomeDir();
1441 myframe_window_title += "]";
1442 }
1443
1444 wxString fmsg;
1445 fmsg.Printf("Creating MyFrame...size(%d, %d) position(%d, %d)",
1446 new_frame_size.x, new_frame_size.y, position.x, position.y);
1447 wxLogMessage(fmsg);
1448
1450 auto dockart = new wxAuiDefaultDockArt;
1451 g_pauimgr->SetArtProvider(dockart);
1452
1453 gFrame = new MyFrame(NULL, myframe_window_title, position, new_frame_size,
1454 app_style, dockart);
1455
1456 // Initialize the Plugin Manager
1457 g_pi_manager = new PlugInManager(gFrame);
1458
1459 g_pauimgr->SetDockSizeConstraint(.9, .9);
1460
1461 // tell wxAuiManager to manage the frame
1462 g_pauimgr->SetManagedWindow(gFrame);
1463
1464 // Do those platform specific initialization things that need gFrame
1465 g_Platform->Initialize_3();
1466
1467 gFrame->CreateCanvasLayout();
1468
1469 // gFrame->RequestNewMasterToolbar( true );
1470
1471 gFrame->SetChartUpdatePeriod(); // Reasonable default
1472
1473 pthumbwin = new ThumbWin(gFrame->GetPrimaryCanvas());
1474
1475 gFrame->ApplyGlobalSettings(false); // done once on init with resize
1476 gFrame->SetAllToolbarScale();
1477 gFrame->SetAndApplyColorScheme(global_color_scheme);
1478 if (g_bframemax) gFrame->Maximize(true);
1479
1480#ifdef __ANDROID__
1481 if (g_bresponsive && (gFrame->GetPrimaryCanvas()->GetPixPerMM() > 4.0))
1482 gFrame->Maximize(true);
1483#endif
1484
1485 // All set to go.....
1486
1487 // Process command line option to rebuild cache
1488#ifdef ocpnUSE_GL
1489 extern ocpnGLOptions g_GLOptions;
1490
1491 if (g_rebuild_gl_cache && g_bopengl && g_GLOptions.m_bTextureCompression &&
1492 g_GLOptions.m_bTextureCompressionCaching) {
1493 gFrame->ReloadAllVP(); // Get a nice chart background loaded
1494
1495 // Turn off the toolbar as a clear signal that the system is busy right
1496 // now.
1497 // Note: I commented this out because the toolbar never comes back for me
1498 // and is unusable until I restart opencpn without generating the cache
1499 // if( g_MainToolbar )
1500 // g_MainToolbar->Hide();
1501
1502 if (g_glTextureManager) g_glTextureManager->BuildCompressedCache();
1503 }
1504#endif
1505
1506 // FIXME (dave)
1507 // move method to frame
1508 // if (g_parse_all_enc) ParseAllENC(gFrame);
1509
1510 // establish GPS timeout value as multiple of frame timer
1511 // This will override any nonsense or unset value from the config file
1512 if ((gps_watchdog_timeout_ticks > 60) || (gps_watchdog_timeout_ticks <= 0))
1513 gps_watchdog_timeout_ticks = (GPS_TIMEOUT_SECONDS * 1000) / TIMER_GFRAME_1;
1514
1515 wxString dogmsg;
1516 dogmsg.Printf("GPS Watchdog Timeout is: %d sec.", gps_watchdog_timeout_ticks);
1517 wxLogMessage(dogmsg);
1518
1519 sat_watchdog_timeout_ticks = gps_watchdog_timeout_ticks;
1520
1521 g_priSats = 99;
1522
1523 // Most likely installations have no ownship heading information
1524 g_bVAR_Rx = false;
1525
1526 // Start up a new track if enabled in config file
1527 if (g_bTrackCarryOver) g_bDeferredStartTrack = true;
1528
1529 pAnchorWatchPoint1 = NULL;
1530 pAnchorWatchPoint2 = NULL;
1531
1532 gFrame->DoChartUpdate();
1533
1534 // Load comm connections
1535 for (auto *cp : TheConnectionParams()) {
1536 if (cp->bEnabled) {
1537 MakeCommDriver(cp);
1538 cp->b_IsSetup = TRUE;
1539 }
1540 }
1542
1543 // Load and initialize plugins
1544 auto style = g_StyleManager->GetCurrentStyle();
1545 auto bitmap = new wxBitmap(style->GetIcon("default_pi", 32, 32));
1546 if (bitmap->IsOk())
1547 PluginLoader::GetInstance()->SetPluginDefaultIcon(bitmap);
1548 else
1549 wxLogWarning("Cannot initiate plugin default jigsaw icon.");
1550
1552 PluginLoader::GetInstance()->LoadAllPlugIns(true);
1554
1555 // A Plugin (e.g. Squiddio) may have redefined some routepoint icons...
1556 // Reload all icons, to be sure.
1558
1559 wxString perspective;
1560 pConfig->SetPath("/AUI");
1561 pConfig->Read("AUIPerspective", &perspective);
1562
1563 // Make sure the perspective saved in the config file is "reasonable"
1564 // In particular, the perspective should have an entry for every
1565 // windows added to the AUI manager so far.
1566 // If any are not found, then use the default layout
1567
1568 bool bno_load = false;
1569
1570 wxArrayString name_array;
1571 wxStringTokenizer st(perspective, "|;");
1572 while (st.HasMoreTokens()) {
1573 wxString s1 = st.GetNextToken();
1574 if (s1.StartsWith("name=")) {
1575 wxString sc = s1.AfterFirst('=');
1576 name_array.Add(sc);
1577 }
1578 }
1579
1580 wxAuiPaneInfoArray pane_array_val = g_pauimgr->GetAllPanes();
1581 for (unsigned int i = 0; i < pane_array_val.GetCount(); i++) {
1582 wxAuiPaneInfo pane = pane_array_val.Item(i);
1583
1584 // If we find a pane that is not in the perspective,
1585 // then we should not load the perspective at all
1586 if (name_array.Index(pane.name) == wxNOT_FOUND) {
1587 bno_load = true;
1588 break;
1589 }
1590 }
1591
1592 if (!bno_load) g_pauimgr->LoadPerspective(perspective, false);
1593
1594 // Touch up the AUI manager
1595 // Make sure that any pane width is reasonable default value
1596#if 0 // TODO nees this?
1597 for (unsigned int i = 0; i < g_canvasArray.GetCount(); i++) {
1598 ChartCanvas *cc = g_canvasArray.Item(i);
1599 if (cc) {
1600 wxSize frameSize = GetClientSize();
1601 wxSize minSize = g_pauimgr->GetPane(cc).min_size;
1602 int width = wxMax(minSize.x, frameSize.x / 10);
1603 g_pauimgr->GetPane(cc).MinSize(frameSize.x * 1 / 5, frameSize.y);
1604 }
1605 }
1606 g_pauimgr->Update();
1607#endif
1608 g_pauimgr->Update();
1609
1610 // Notify all the AUI PlugIns so that they may syncronize with the
1611 // Perspective
1612 g_pi_manager->NotifyAuiPlugIns();
1613
1614 // Give the user dialog on any blacklisted PlugIns
1615 g_pi_manager->ShowDeferredBlacklistMessages();
1616 g_pi_manager->CallLateInit();
1617
1618 return;
1619
1620 // This little hack fixes a problem seen with some UniChrome OpenGL drivers
1621 // We need a deferred resize to get glDrawPixels() to work right.
1622 // So we set a trigger to generate a resize after 5 seconds....
1623 // See the "UniChrome" hack elsewhere
1624#ifdef ocpnUSE_GL
1625 if (!g_bdisable_opengl) {
1626 glChartCanvas *pgl =
1627 (glChartCanvas *)gFrame->GetPrimaryCanvas()->GetglCanvas();
1628 if (pgl && (pgl->GetRendererString().Find("UniChrome") != wxNOT_FOUND)) {
1629 gFrame->m_defer_size = gFrame->GetSize();
1630 gFrame->SetSize(gFrame->m_defer_size.x - 10, gFrame->m_defer_size.y);
1631 g_pauimgr->Update();
1632 gFrame->m_bdefer_resize = true;
1633 }
1634 }
1635#endif
1636
1637 // Horrible Hack (tm): Make sure the RoutePoint destructor can invoke
1638 // glDeleteTextures. Truly awful.
1639#ifdef ocpnUSE_GL
1640 if (g_bopengl)
1641 RoutePoint::delete_gl_textures = [](unsigned n, const unsigned *texts) {
1642 glDeleteTextures(n, texts);
1643 };
1644#else
1645 RoutePoint::delete_gl_textures = [](unsigned n, const unsigned *texts) {};
1646#endif
1647
1648#ifdef __ANDROID__
1649 // We need a resize to pick up height adjustment after building android
1650 // ActionBar
1651 gFrame->SetSize(getAndroidDisplayDimensions());
1652 androidSetFollowTool(gFrame->GetPrimaryCanvas()->m_bFollow ? 1 : 0, true);
1653#endif
1654
1655 // Setup Tides/Currents to settings present at last shutdown
1656 // TODO
1657 // gFrame->ShowTides( g_bShowTide );
1658 // gFrame->ShowCurrents( g_bShowCurrent );
1659
1660 // wxLogMessage( wxString::Format("OpenCPN Initialized in %ld ms.",
1661 // init_sw.Time() ) );
1662}
1663
1664void MyApp::LoadChartDatabase() {
1665 // Build the initial chart dir array
1666 ArrayOfCDI ChartDirArray;
1667 pConfig->LoadChartDirArray(ChartDirArray);
1668
1669 // Windows installer may have left hints regarding the initial chart dir
1670 // selection
1671#ifdef __WXMSW__
1672 if (g_bFirstRun && (ChartDirArray.GetCount() == 0)) {
1673 int ndirs = 0;
1674
1675 wxRegKey RegKey(wxString("HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenCPN"));
1676 if (RegKey.Exists()) {
1677 wxLogMessage(
1678 _("Retrieving initial Chart Directory set from Windows Registry"));
1679 wxString dirs;
1680 RegKey.QueryValue(wxString("ChartDirs"), dirs);
1681
1682 wxStringTokenizer tkz(dirs, ";");
1683 while (tkz.HasMoreTokens()) {
1684 wxString token = tkz.GetNextToken();
1685
1686 ChartDirInfo cdi;
1687 cdi.fullpath = token.Trim();
1688 cdi.magic_number = "";
1689
1690 ChartDirArray.Add(cdi);
1691 ndirs++;
1692 }
1693 }
1694
1695 if (g_bportable) {
1696 ChartDirInfo cdi;
1697 cdi.fullpath = "charts";
1698 cdi.fullpath.Prepend(g_Platform->GetSharedDataDir());
1699 cdi.magic_number = "";
1700 ChartDirArray.Add(cdi);
1701 ndirs++;
1702 }
1703
1704 if (ndirs) pConfig->UpdateChartDirs(ChartDirArray);
1705 }
1706#endif
1707
1708 // If the ChartDirArray is empty at this point, any existing chart database
1709 // file must be declared invalid, So it is best to simply delete it if
1710 // present.
1711 // TODO There is a possibility of recreating the dir list from the
1712 // database itself......
1713
1714 if (!ChartDirArray.GetCount())
1715 if (::wxFileExists(ChartListFileName)) ::wxRemoveFile(ChartListFileName);
1716
1717 // Try to load the current chart list Data file
1718 ChartData = new ChartDB();
1719 if (g_NeedDBUpdate == 0 &&
1720 !ChartData->LoadBinary(ChartListFileName, ChartDirArray)) {
1721 g_NeedDBUpdate = 1;
1722 }
1723
1724 // Verify any saved chart database startup index
1725 if (g_restore_dbindex >= 0) {
1726 if (ChartData->GetChartTableEntries() == 0)
1727 g_restore_dbindex = -1;
1728
1729 else if (g_restore_dbindex > (ChartData->GetChartTableEntries() - 1))
1730 g_restore_dbindex = 0;
1731 }
1732
1733 // Apply the inital Group Array structure to the chart database
1734 ChartData->ApplyGroupArray(g_pGroupArray);
1735}
1736
1738 wxLogMessage("opencpn::MyApp starting exit.");
1739 m_checker.OnExit();
1740 m_usb_watcher.Stop();
1741 // Send current nav status data to log file // pjotrc 2010.02.09
1742
1743 wxDateTime lognow = wxDateTime::Now();
1744 lognow.MakeGMT();
1745 wxString day = lognow.FormatISODate();
1746 wxString utc = lognow.FormatISOTime();
1747 wxString navmsg = "LOGBOOK: ";
1748 navmsg += day;
1749 navmsg += " ";
1750 navmsg += utc;
1751 navmsg += " UTC ";
1752
1753 if (bGPSValid) {
1754 wxString data;
1755 data.Printf("OFF: Lat %10.5f Lon %10.5f ", gLat, gLon);
1756 navmsg += data;
1757
1758 wxString cog;
1759 if (std::isnan(gCog))
1760 cog.Printf("COG ----- ");
1761 else
1762 cog.Printf("COG %10.5f ", gCog);
1763
1764 wxString sog;
1765 if (std::isnan(gSog))
1766 sog.Printf("SOG ----- ");
1767 else
1768 sog.Printf("SOG %6.2f " + getUsrSpeedUnit(), toUsrSpeed(gSog));
1769
1770 navmsg += cog;
1771 navmsg += sog;
1772
1773 } else {
1774 wxString data;
1775 data.Printf("OFF: Lat %10.5f Lon %10.5f", gLat, gLon);
1776 navmsg += data;
1777 }
1778 wxLogMessage(navmsg);
1779 g_loglast_time = lognow;
1780
1781 if (ptcmgr) delete ptcmgr;
1782
1783 for (Track *track : g_TrackList) {
1784 delete track;
1785 }
1786 g_TrackList.clear();
1787
1788 delete pConfig;
1789 delete pSelect;
1790 delete pSelectTC;
1791 delete pSelectAIS;
1792
1793 delete ps52plib;
1794 delete g_SencThreadManager;
1795
1796 if (g_pGroupArray) {
1797 for (unsigned int igroup = 0; igroup < g_pGroupArray->GetCount();
1798 igroup++) {
1799 delete g_pGroupArray->Item(igroup);
1800 }
1801
1802 g_pGroupArray->Clear();
1803 delete g_pGroupArray;
1804 }
1805
1806 wxLogMessage("opencpn::MyApp exiting cleanly...\n");
1807 wxLog::FlushActive();
1808
1809 g_Platform->CloseLogFile();
1810
1811 delete pInit_Chart_Dir;
1812
1813 for (Track *track : g_TrackList) {
1814 delete track;
1815 }
1816 g_TrackList.clear();
1817
1818 delete g_pRouteMan;
1819 delete pWayPointMan;
1820
1821 navutil::DeinitGlobals();
1822
1823 DeInitializeUserColors();
1824
1825 delete pLayerList;
1826
1827 delete m_pRegistrarMan;
1828 CSVDeaccess(NULL);
1829
1830 delete g_StyleManager;
1831
1832 // Restore any changed system colors
1833
1834#ifdef __WXMSW__
1835 void RestoreSystemColors();
1836 RestoreSystemColors();
1837#endif
1838
1839#ifdef __MSVC__LEAK
1840 DeInitAllocCheck();
1841#endif
1842
1843#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1845#endif
1846
1847 FontMgr::Shutdown();
1848
1849 g_Platform->OnExit_2();
1851 delete g_Platform;
1852
1853 return TRUE;
1854}
1855
1856#ifdef LINUX_CRASHRPT
1857void MyApp::OnFatalException() { g_crashprint.Report(); }
1858#endif
1859
1860//----------------------------------------------------------------------------------------------------------
1861// Application-wide CPL Error handler
1862//----------------------------------------------------------------------------------------------------------
1863void MyCPLErrorHandler(CPLErr eErrClass, int nError, const char *pszErrorMsg)
1864
1865{
1866 char msg[256];
1867
1868 if (eErrClass == CE_Debug)
1869 snprintf(msg, 255, "CPL: %s", pszErrorMsg);
1870 else if (eErrClass == CE_Warning)
1871 snprintf(msg, 255, "CPL Warning %d: %s", nError, pszErrorMsg);
1872 else
1873 snprintf(msg, 255, "CPL ERROR %d: %s", nError, pszErrorMsg);
1874
1875 wxString str(msg, wxConvUTF8);
1876 wxLogMessage(str);
1877}
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:717
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.