OpenCPN Partial API docs
Loading...
Searching...
No Matches
ocpn_app.cpp
1/***************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: OpenCPN Main wxWidgets Program
5 * Author: David Register
6 *
7 ***************************************************************************
8 * Copyright (C) 2010 by David S. Register *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24 **************************************************************************/
25#include "config.h"
26
27
28#ifdef __MINGW32__
29#undef IPV6STRICT // mingw FTBS fix: missing struct ip_mreq
30#include <windows.h>
31#endif
32
33#include <wx/wxprec.h>
34
35#ifndef WX_PRECOMP
36#include <wx/wx.h>
37#endif // precompiled headers
38#ifdef __WXMSW__
39//#include "c:\\Program Files\\visual leak detector\\include\\vld.h"
40#endif
41
42#include <algorithm>
43#include <limits.h>
44#include <memory>
45
46#ifdef __WXMSW__
47#include <math.h>
48#include <psapi.h>
49#include <stdlib.h>
50#include <time.h>
51#endif
52
53#ifndef __WXMSW__
54#include <setjmp.h>
55#include <signal.h>
56#endif
57
58#ifdef OCPN_HAVE_X11
59#include <X11/Xatom.h>
60#include <X11/Xlib.h>
61#endif
62
63#include <wx/apptrait.h>
64#include <wx/arrimpl.cpp>
65#include <wx/artprov.h>
66#include <wx/aui/aui.h>
67#include <wx/clrpicker.h>
68#include <wx/dialog.h>
69#include <wx/dialog.h>
70#include <wx/dir.h>
71#include <wx/image.h>
72#include <wx/intl.h>
73#include <wx/ipc.h>
74#include <wx/jsonreader.h>
75#include <wx/listctrl.h>
76#include <wx/printdlg.h>
77#include <wx/print.h>
78#include <wx/progdlg.h>
79#include <wx/settings.h>
80#include <wx/stdpaths.h>
81#include <wx/tokenzr.h>
82#include <wx/cmdline.h>
83
84#include "ocpn_app.h"
85#include "ocpn_frame.h"
86
87#include "AboutFrameImpl.h"
88#include "about.h"
89#include "AISTargetAlertDialog.h"
90#include "AISTargetQueryDialog.h"
91#include "ais_info_gui.h"
92
93#include "CanvasConfig.h"
94#include "chartdb.h"
95#include "chcanv.h"
96#include "cm93.h"
97#include "concanv.h"
98#include "config.h"
99#include "config_vars.h"
100#include "ConfigMgr.h"
101#include "DetailSlider.h"
102#include "dychart.h"
103#include "FontMgr.h"
104#include "GoToPositionDialog.h"
105#include "gdal/cpl_csv.h"
106#include "glTexCache.h"
107#include "Layer.h"
108#include "logger.h"
109#include "MarkInfo.h"
110#include "multiplexer.h"
111#include "nav_object_database.h"
112#include "navutil.h"
113#include "navutil_base.h"
114#include "OCPN_AUIManager.h"
115#include "OCPNPlatform.h"
116#include "options.h"
117#include "own_ship.h"
118#include "plugin_handler.h"
119#include "route.h"
120#include "routemanagerdialog.h"
121#include "routeman.h"
122#include "RoutePropDlgImpl.h"
123#include "s52plib.h"
124#include "s57chart.h"
125#include "S57QueryDialog.h"
126#include "safe_mode.h"
127#include "select.h"
128#include "SoundFactory.h"
129#include "styles.h"
130#include "tcmgr.h"
131#include "thumbwin.h"
132#include "track.h"
133#include "TrackPropDlg.h"
134#include "AISTargetListDialog.h"
135#include "comm_n0183_output.h"
136#include "comm_bridge.h"
137#include "certificates.h"
138#include "mDNS_query.h"
139
140//#include "usb_devices.h"
141//#include "comm_drv_registry.h"
142//#include "comm_navmsg_bus.h"
143//#include "N2KParser.h"
144//#include "comm_util.h"
145#include "comm_vars.h"
146
147#include "mDNS_service.h"
148
149#ifdef __linux__
150#include "udev_rule_mgr.h"
151#endif
152
153#ifdef ocpnUSE_GL
154#include "glChartCanvas.h"
155#endif
156
157#ifdef __WXOSX__
158#include "macutils.h"
159#endif
160
161#ifdef __WXMSW__
162#include "garmin_protocol_mgr.h" // Used for port probing on Windows
163void RedirectIOToConsole();
164#endif
165
166#if defined(__WXMSW__) && defined (__MSVC__LEAK)
167#include "Stackwalker.h"
168#endif
169
170#ifdef LINUX_CRASHRPT
171#include "crashprint.h"
172#endif
173
174#ifdef __OCPN__ANDROID__
175#include "androidUTIL.h"
176#else
177#include "serial/serial.h"
178#endif
179
180static void UpdatePositionCalculatedSogCog();
181
182
183// comm event definitions
184wxDEFINE_EVENT(EVT_N2K_129029, wxCommandEvent);
185wxDEFINE_EVENT(EVT_N2K_129026, wxCommandEvent);
186
187wxDEFINE_EVENT(EVT_N0183_RMC, wxCommandEvent);
188wxDEFINE_EVENT(EVT_N0183_HDT, wxCommandEvent);
189wxDEFINE_EVENT(EVT_N0183_HDG, wxCommandEvent);
190wxDEFINE_EVENT(EVT_N0183_HDM, wxCommandEvent);
191wxDEFINE_EVENT(EVT_N0183_VTG, wxCommandEvent);
192wxDEFINE_EVENT(EVT_N0183_GSV, wxCommandEvent);
193wxDEFINE_EVENT(EVT_N0183_GGA, wxCommandEvent);
194wxDEFINE_EVENT(EVT_N0183_GLL, wxCommandEvent);
195wxDEFINE_EVENT(EVT_N0183_AIVDO, wxCommandEvent);
196
197
198//------------------------------------------------------------------------------
199// Fwd Declarations
200//------------------------------------------------------------------------------
201
202//------------------------------------------------------------------------------
203// Static variable definition
204//------------------------------------------------------------------------------
205
206WX_DEFINE_OBJARRAY(ArrayOfCDI);
207
208OCPNPlatform *g_Platform;
209BasePlatform *g_BasePlatform; // points to g_platform, handles brain-dead MS linker.
210
211wxString g_vs;
212bool g_bFirstRun;
213bool g_bUpgradeInProcess;
214
215bool g_bPauseTest;
216
217wxString g_compatOS;
218wxString g_compatOsVersion;
219
220int g_unit_test_1;
221int g_unit_test_2;
222bool g_start_fullscreen;
223bool g_rebuild_gl_cache;
224bool g_parse_all_enc;
225
226// Files specified on the command line, if any.
227wxVector<wxString> g_params;
228
229MyFrame *gFrame;
230
231ConsoleCanvas *console;
232
233MyConfig *pConfig;
234ChartBase *Current_Vector_Ch;
235ChartDB *ChartData;
236wxString *pdir_list[20];
237int g_restore_stackindex;
238int g_restore_dbindex;
239double g_ChartNotRenderScaleFactor;
240int g_nDepthUnitDisplay;
241
242RouteList *pRouteList;
243std::vector<Track*> g_TrackList;
244LayerList *pLayerList;
245bool g_bIsNewLayer;
246int g_LayerIdx;
247bool g_bLayerViz;
248
249Select *pSelect;
250Select *pSelectTC;
251Select *pSelectAIS;
252
253Routeman *g_pRouteMan;
254WayPointman *pWayPointMan;
255MarkInfoDlg *g_pMarkInfoDialog;
256RoutePropDlgImpl *pRoutePropDialog;
257TrackPropDlg *pTrackPropDialog;
258RouteManagerDialog *pRouteManagerDialog;
259GoToPositionDialog *pGoToPositionDialog;
260
261double vLat, vLon;
262double initial_scale_ppm, initial_rotation;
263
264int g_nbrightness = 100;
265
266bool bDBUpdateInProgress;
267
268ThumbWin *pthumbwin;
269TCMgr *ptcmgr;
270
271bool g_bshowToolbar = true;
272bool g_bexpert = true;
273bool g_bBasicMenus = false;
274
275bool bDrawCurrentValues;
276
277wxString ChartListFileName;
278wxString AISTargetNameFileName;
279wxString gWorldMapLocation, gDefaultWorldMapLocation;
280wxString *pInit_Chart_Dir;
281wxString g_winPluginDir; // Base plugin directory on Windows.
282wxString g_csv_locn;
283wxString g_SENCPrefix;
284wxString g_UserPresLibData;
285wxString g_VisibleLayers;
286wxString g_InvisibleLayers;
287wxString g_VisiNameinLayers;
288wxString g_InVisiNameinLayers;
289
290bool g_bcompression_wait;
291bool g_FlushNavobjChanges;
292int g_FlushNavobjChangesTimeout;
293
294wxString g_uploadConnection;
295
296int user_user_id;
297int file_user_id;
298
299int quitflag;
300int g_tick = 0;
301int g_mem_total, g_mem_used, g_mem_initial;
302
303bool s_bSetSystemTime;
304
305static unsigned int malloc_max;
306
307wxDateTime g_start_time;
308wxDateTime g_loglast_time;
309static OcpnSound *_bells_sounds[] = {SoundFactory(), SoundFactory()};
310std::vector<OcpnSound *> bells_sound(_bells_sounds, _bells_sounds + 2);
311
312OcpnSound *g_anchorwatch_sound = SoundFactory();
313wxString g_anchorwatch_sound_file;
314wxString g_DSC_sound_file;
315wxString g_SART_sound_file;
316wxString g_AIS_sound_file;
317
318RoutePoint *pAnchorWatchPoint1;
319RoutePoint *pAnchorWatchPoint2;
320double AnchorPointMinDist;
321bool AnchorAlertOn1, AnchorAlertOn2;
322bool g_bCruising;
323
324ChartDummy *pDummyChart;
325
326ocpnStyle::StyleManager *g_StyleManager;
327
328// Global print data, to remember settings during the session
329wxPrintData *g_printData = (wxPrintData *)NULL;
330
331// Global page setup data
332wxPageSetupData *g_pageSetupData = (wxPageSetupData *)NULL;
333
334bool g_bShowOutlines;
335bool g_bShowDepthUnits;
336bool g_bDisplayGrid; // Flag indicating weather the lat/lon grid should be
337 // displayed
338bool g_bShowChartBar;
339bool g_bShowActiveRouteHighway;
340int g_nAWDefault;
341int g_nAWMax;
342bool g_bPlayShipsBells;
343bool g_bFullscreenToolbar;
344bool g_bShowLayers;
345bool g_bTransparentToolbar;
346bool g_bTransparentToolbarInOpenGLOK;
347int g_nAutoHideToolbar;
348bool g_bAutoHideToolbar;
349
350bool g_bPermanentMOBIcon;
351bool g_bTempShowMenuBar;
352
353int g_iSDMMFormat;
354int g_iDistanceFormat;
355int g_iSpeedFormat;
356int g_iTempFormat;
357
358int g_iNavAidRadarRingsNumberVisible;
359float g_fNavAidRadarRingsStep;
360int g_pNavAidRadarRingsStepUnits;
361int g_iWaypointRangeRingsNumber;
362float g_fWaypointRangeRingsStep;
363int g_iWaypointRangeRingsStepUnits;
364wxColour g_colourWaypointRangeRingsColour;
365bool g_bWayPointPreventDragging;
366bool g_bConfirmObjectDelete;
367wxColour g_colourOwnshipRangeRingsColour;
368int g_iWpt_ScaMin;
369bool g_bUseWptScaMin;
370bool g_bShowWptName;
371int g_maxzoomin;
372
373// Set default color scheme
374ColorScheme global_color_scheme = GLOBAL_COLOR_SCHEME_DAY;
375
376int Usercolortable_index;
377wxArrayPtrVoid *UserColorTableArray;
378wxArrayPtrVoid *UserColourHashTableArray;
379wxColorHashMap *pcurrent_user_color_hash;
380
381int gGPS_Watchdog;
382bool bGPSValid;
383bool bVelocityValid;
384
385int gHDx_Watchdog;
386int gHDT_Watchdog;
387int gVAR_Watchdog;
388
389int gSAT_Watchdog;
390
391bool g_bDebugCM93;
392bool g_bDebugS57;
393
394bool g_bfilter_cogsog;
395int g_COGFilterSec = 1;
396int g_SOGFilterSec;
397
398int g_ChartUpdatePeriod;
399int g_SkewCompUpdatePeriod;
400
401int g_lastClientRectx;
402int g_lastClientRecty;
403int g_lastClientRectw;
404int g_lastClientRecth;
405double g_display_size_mm;
406double g_config_display_size_mm;
407bool g_config_display_size_manual;
408float g_selection_radius_mm = 2.0;
409float g_selection_radius_touch_mm = 10.0;
410
411int g_GUIScaleFactor;
412int g_ChartScaleFactor;
413float g_ChartScaleFactorExp;
414float g_MarkScaleFactorExp;
415int g_last_ChartScaleFactor;
416int g_ShipScaleFactor;
417float g_ShipScaleFactorExp;
418int g_ENCSoundingScaleFactor;
419int g_ENCTextScaleFactor;
420
421bool g_bShowTide;
422bool g_bShowCurrent;
423
424s52plib *ps52plib;
425S57ClassRegistrar *g_poRegistrar;
426s57RegistrarMgr *m_pRegistrarMan;
427
428CM93OffsetDialog *g_pCM93OffsetDialog;
429
430#ifdef __WXOSX__
431#include "macutils.h"
432#endif
433
434// begin rms
435#ifdef __WXOSX__
436#ifdef __WXMSW__
437#ifdef USE_GLU_TESS
438#ifdef USE_GLU_DLL
439// end rms
440extern bool s_glu_dll_ready;
441extern HINSTANCE s_hGLU_DLL; // Handle to DLL
442#endif
443#endif
444#endif
445#endif
446
447double g_ownship_predictor_minutes;
448double g_ownship_HDTpredictor_miles;
449
450bool g_own_ship_sog_cog_calc;
451int g_own_ship_sog_cog_calc_damp_sec;
452wxDateTime last_own_ship_sog_cog_calc_ts;
453double last_own_ship_sog_cog_calc_lat, last_own_ship_sog_cog_calc_lon;
454
455Multiplexer *g_pMUX;
456
457AisDecoder *g_pAIS;
458AisInfoGui *g_pAISGUI;
459
460bool g_bAIS_CPA_Alert;
461bool g_bAIS_CPA_Alert_Audio;
462AISTargetAlertDialog *g_pais_alert_dialog_active;
463AISTargetQueryDialog *g_pais_query_dialog_active;
464int g_iSoundDeviceIndex;
465
466int g_ais_alert_dialog_x, g_ais_alert_dialog_y;
467int g_ais_alert_dialog_sx, g_ais_alert_dialog_sy;
468int g_ais_query_dialog_x, g_ais_query_dialog_y;
469
470int g_S57_dialog_sx, g_S57_dialog_sy;
471
472int g_nframewin_x;
473int g_nframewin_y;
474int g_nframewin_posx;
475int g_nframewin_posy;
476bool g_bframemax;
477
478bool g_bAutoAnchorMark;
479
480wxRect g_blink_rect;
481double g_PlanSpeed;
482wxDateTime g_StartTime;
483int g_StartTimeTZ;
484IDX_entry *gpIDX;
485int gpIDXn;
486long gStart_LMT_Offset;
487
488wxArrayString *pMessageOnceArray;
489
490FILE *s_fpdebug;
491bool bAutoOpen;
492
493bool g_bUseGLL = true;
494
495int g_nCacheLimit;
496int g_memCacheLimit;
497bool g_bGDAL_Debug;
498
499double g_VPRotate; // Viewport rotation angle, used on "Course Up" mode
500bool g_bCourseUp;
501int g_COGAvgSec = 15; // COG average period (sec.) for Course Up Mode
502double g_COGAvg;
503bool g_bLookAhead;
504bool g_bskew_comp;
505bool g_bopengl;
506bool g_bSoftwareGL;
507bool g_bShowFPS;
508bool g_bsmoothpanzoom;
509bool g_fog_overzoom;
510double g_overzoom_emphasis_base;
511bool g_oz_vector_scale;
512double g_plus_minus_zoom_factor;
513
514int g_nCOMPortCheck = 32;
515
516bool g_b_legacy_input_filter_behaviour; // Support original input filter
517 // process or new process
518
519bool g_bbigred;
520
521PlugInManager *g_pi_manager;
522
523bool g_bAISRolloverShowClass;
524bool g_bAISRolloverShowCOG;
525bool g_bAISRolloverShowCPA;
526
527bool g_bDebugGPSD;
528
529bool g_bFullScreenQuilt = true;
530bool g_bQuiltEnable;
531bool g_bQuiltStart;
532
533bool g_bportable;
534
535bool g_bdisable_opengl;
536
537ChartGroupArray *g_pGroupArray;
538
539S57QueryDialog *g_pObjectQueryDialog;
540
541wxArrayString TideCurrentDataSet;
542wxString g_TCData_Dir;
543
544bool g_boptionsactive;
545options *g_options;
546bool g_bDeferredInitDone;
547int options_lastPage = 0;
548int options_subpage = 0;
549
550wxPoint options_lastWindowPos(0, 0);
551wxSize options_lastWindowSize(0, 0);
552
553bool g_bSleep;
554bool g_bsimplifiedScalebar;
555
556int g_grad_default;
557wxColour g_border_color_default;
558int g_border_size_default;
559int g_sash_size_default;
560wxColour g_caption_color_default;
561wxColour g_sash_color_default;
562wxColour g_background_color_default;
563
564int osMajor, osMinor;
565
566bool GetMemoryStatus(int *mem_total, int *mem_used);
567bool g_bHasHwClock;
568
569
570// AIS Global configuration
571bool g_bShowAIS;
572bool g_bCPAMax;
573double g_CPAMax_NM;
574bool g_bCPAWarn;
575double g_CPAWarn_NM;
576bool g_bTCPA_Max;
577double g_TCPA_Max;
578bool g_bMarkLost;
579double g_MarkLost_Mins;
580bool g_bRemoveLost;
581double g_RemoveLost_Mins;
582bool g_bShowCOG;
583bool g_bSyncCogPredictors;
584double g_ShowCOG_Mins;
585bool g_bAISShowTracks;
586double g_AISShowTracks_Mins;
587double g_AISShowTracks_Limit;
588bool g_bHideMoored;
589bool g_bAllowShowScaled;
590double g_ShowMoored_Kts;
591wxString g_sAIS_Alert_Sound_File;
592bool g_bAIS_CPA_Alert_Suppress_Moored;
593bool g_bAIS_ACK_Timeout;
594double g_AckTimeout_Mins;
595bool g_bShowScaled;
596bool g_bShowAreaNotices;
597bool g_bDrawAISSize;
598bool g_bDrawAISRealtime;
599double g_AIS_RealtPred_Kts;
600bool g_bShowAISName;
601int g_Show_Target_Name_Scale;
602int g_WplAction;
603
604int g_nAIS_activity_timer;
605
606bool g_bEnableZoomToCursor;
607
608bool g_bTrackActive;
609bool g_bTrackCarryOver;
610bool g_bDeferredStartTrack;
611bool g_bTrackDaily;
612int g_track_rotate_time;
613int g_track_rotate_time_type;
614bool g_bHighliteTracks;
615int g_route_line_width;
616int g_track_line_width;
617wxColour g_colourTrackLineColour;
618wxString g_default_wp_icon;
619wxString g_default_routepoint_icon;
620
621ActiveTrack *g_pActiveTrack;
622double g_TrackIntervalSeconds;
623double g_TrackDeltaDistance;
624int g_nTrackPrecision;
625
626int g_total_NMEAerror_messages;
627
628int g_cm93_zoom_factor;
629PopUpDSlide *pPopupDetailSlider;
630bool g_bShowDetailSlider;
631int g_detailslider_dialog_x, g_detailslider_dialog_y;
632
633bool g_bUseGreenShip;
634
635wxString g_AW1GUID;
636wxString g_AW2GUID;
637
638bool g_b_overzoom_x = true; // Allow high overzoom
639
640int g_OwnShipIconType;
641double g_n_ownship_length_meters;
642double g_n_ownship_beam_meters;
643double g_n_gps_antenna_offset_y;
644double g_n_gps_antenna_offset_x;
645int g_n_ownship_min_mm;
646
647double g_n_arrival_circle_radius;
648
649bool g_bNeedDBUpdate;
650bool g_bPreserveScaleOnX;
651
652AboutFrameImpl *g_pAboutDlg;
653about *g_pAboutDlgLegacy;
654
655#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
656wxLocale *plocale_def_lang;
657#endif
658
659wxString g_locale;
660wxString g_localeOverride;
661bool g_b_assume_azerty;
662
663bool g_bUseRaster;
664bool g_bUseVector;
665bool g_bUseCM93;
666
667int g_click_stop;
668
669int g_MemFootSec;
670int g_MemFootMB;
671
672wxStaticBitmap *g_pStatBoxTool;
673bool g_bShowStatusBar;
674
675bool g_bquiting;
676int g_BSBImgDebug;
677
678AISTargetListDialog *g_pAISTargetList;
679wxString g_AisTargetList_perspective;
680int g_AisTargetList_range;
681int g_AisTargetList_sortColumn;
682bool g_bAisTargetList_sortReverse;
683wxString g_AisTargetList_column_spec;
684wxString g_AisTargetList_column_order;
685int g_AisTargetList_count;
686bool g_bAisTargetList_autosort;
687
688bool g_bFullscreen;
689
690OCPN_AUIManager *g_pauimgr;
691wxAuiDefaultDockArt *g_pauidockart;
692
693wxString g_toolbarConfig = _T("XXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
694wxString g_toolbarConfigSecondary = _T("....XX..X........XXXXXXXXXXXX");
695
696ocpnFloatingToolbarDialog *g_MainToolbar;
697int g_maintoolbar_x;
698int g_maintoolbar_y;
699long g_maintoolbar_orient;
700float g_toolbar_scalefactor;
701
702float g_compass_scalefactor;
703bool g_bShowMenuBar;
704bool g_bShowCompassWin;
705
706bool g_benable_rotate;
707
708bool g_bShowTrue = true;
709bool g_bShowMag;
710
711bool g_bMagneticAPB;
712
713bool g_bInlandEcdis;
714
715int g_GPU_MemSize;
716
717wxString g_uiStyle;
718
719// Values returned from WMM_PI for variation computation request
720// Initialize to invalid value so we don't use if if WMM hasn't updated yet
721double gQueryVar = 361.0;
722
723char bells_sound_file_name[2][12] = {"1bells.wav", "2bells.wav"};
724
725int portaudio_initialized;
726
727bool g_bAIS_GCPA_Alert_Audio;
728bool g_bAIS_SART_Alert_Audio;
729bool g_bAIS_DSC_Alert_Audio;
730bool g_bAnchor_Alert_Audio;
731
732char nmea_tick_chars[] = {'|', '/', '-', '\\', '|', '/', '-', '\\'};
733
734int g_sticky_chart;
735int g_sticky_projection;
736
737bool g_benableUDPNullHeader;
738
739int n_NavMessageShown;
740wxString g_config_version_string;
741
742wxString g_CmdSoundString;
743
744bool g_btouch;
745bool g_bresponsive;
746bool g_bRollover;
747
748bool b_inCompressAllCharts;
749bool g_bGLexpert;
750bool g_bUIexpert;
751
752int g_chart_zoom_modifier_raster;
753int g_chart_zoom_modifier_vector;
754
755int g_NMEAAPBPrecision;
756
757bool g_bAdvanceRouteWaypointOnArrivalOnly;
758
759bool g_bSpaceDropMark;
760
761wxArrayString g_locale_catalog_array;
762bool b_reloadForPlugins;
763bool g_btrackContinuous;
764
765unsigned int g_canvasConfig;
766bool g_useMUI;
767bool g_bmasterToolbarFull = true;
768
769int g_AndroidVersionCode;
770
771int g_memUsed;
772SENCThreadManager *g_SencThreadManager;
773
774WX_DEFINE_ARRAY_PTR(ChartCanvas *, arrayofCanvasPtr);
775
776arrayofCanvasPtr g_canvasArray;
777arrayofCanvasConfigPtr g_canvasConfigArray;
778wxString g_lastAppliedTemplateGUID;
779
780ChartCanvas *g_focusCanvas;
781ChartCanvas *g_overlayCanvas;
782
783bool b_inCloseWindow;
784
785#ifdef LINUX_CRASHRPT
786wxCrashPrint g_crashprint;
787#endif
788
789#ifndef __WXMSW__
790sigjmp_buf env; // the context saved by sigsetjmp();
791#endif
792
793// {2C9C45C2-8E7D-4C08-A12D-816BBAE722C0}
794#ifdef __WXMSW__
795DEFINE_GUID(GARMIN_DETECT_GUID, 0x2c9c45c2L, 0x8e7d, 0x4c08, 0xa1, 0x2d, 0x81,
796 0x6b, 0xba, 0xe7, 0x22, 0xc0);
797#endif
798
799#ifdef __MSVC__
800#define _CRTDBG_MAP_ALLOC
801#include <stdlib.h>
802#include <crtdbg.h>
803#define DEBUG_NEW new (_NORMAL_BLOCK, __FILE__, __LINE__)
804#define new DEBUG_NEW
805#endif
806
807#if !defined(NAN)
808static const long long lNaN = 0xfff8000000000000;
809#define NAN (*(double *)&lNaN)
810#endif
811
812// Some static helpers
813void appendOSDirSlash(wxString *pString);
814
815void InitializeUserColors(void);
816void DeInitializeUserColors(void);
817void SetSystemColors(ColorScheme cs);
818
819static bool LoadAllPlugIns(bool load_enabled) {
820 g_Platform->ShowBusySpinner();
821 bool b = PluginLoader::getInstance()->LoadAllPlugIns(load_enabled);
822 g_Platform->HideBusySpinner();
823 return b;
824}
825
826
827
828
829#ifndef __OCPN__ANDROID__
830// Connection class, for use by both communicating instances
831class stConnection : public wxConnection {
832public:
833 stConnection() {}
834 ~stConnection() {}
835 bool OnExec(const wxString &topic, const wxString &data);
836};
837
838// Opens a file passed from another instance
839bool stConnection::OnExec(const wxString &topic, const wxString &data) {
840 // not setup yet
841 if (!gFrame) return false;
842
843 wxString path(data);
844 if (path.IsEmpty()) {
845 gFrame->InvalidateAllGL();
846 gFrame->RefreshAllCanvas(false);
847 gFrame->Raise();
848 } else {
850 pSet->load_file(path.fn_str());
851 int wpt_dups;
852 pSet->LoadAllGPXObjects(
853 !pSet->IsOpenCPN(), wpt_dups,
854 true); // Import with full vizibility of names and objects
855 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
856 pRouteManagerDialog->UpdateLists();
857
858 LLBBox box = pSet->GetBBox();
859 if (box.GetValid()) {
860 gFrame->CenterView(gFrame->GetPrimaryCanvas(), box);
861 }
862 delete pSet;
863 return true;
864 }
865 return true;
866}
867
868// Server class, for listening to connection requests
869class stServer : public wxServer {
870public:
871 wxConnectionBase *OnAcceptConnection(const wxString &topic);
872};
873
874// Accepts a connection from another instance
875wxConnectionBase *stServer::OnAcceptConnection(const wxString &topic) {
876 if (topic.Lower() == wxT("opencpn")) {
877 // Check that there are no modal dialogs active
878 wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
879 while (node) {
880 wxDialog *dialog = wxDynamicCast(node->GetData(), wxDialog);
881 if (dialog && dialog->IsModal()) {
882 return 0;
883 }
884 node = node->GetNext();
885 }
886 return new stConnection();
887 }
888 return 0;
889}
890
891// Client class, to be used by subsequent instances in OnInit
892class stClient : public wxClient {
893public:
894 stClient(){};
895 wxConnectionBase *OnMakeConnection() { return new stConnection; }
896};
897
898#endif
899
900//------------------------------------------------------------------------------
901// PNG Icon resources
902//------------------------------------------------------------------------------
903
904#if defined(__WXGTK__) || defined(__WXQT__)
905#include "bitmaps/opencpn.xpm"
906#endif
907
908
909
910wxString newPrivateFileName(wxString home_locn, const char *name,
911 const char *windowsName) {
912 wxString fname = wxString::FromUTF8(name);
913 wxString fwname = wxString::FromUTF8(windowsName);
914 wxString filePathAndName;
915
916 filePathAndName = g_Platform->GetPrivateDataDir();
917 if (filePathAndName.Last() != wxFileName::GetPathSeparator())
918 filePathAndName.Append(wxFileName::GetPathSeparator());
919
920#ifdef __WXMSW__
921 filePathAndName.Append(fwname);
922#else
923 filePathAndName.Append(fname);
924#endif
925
926 return filePathAndName;
927}
928
929
930// `Main program' equivalent, creating windows and returning main app frame
931//------------------------------------------------------------------------------
932// MyApp
933//------------------------------------------------------------------------------
934IMPLEMENT_APP(MyApp)
935
936BEGIN_EVENT_TABLE(MyApp, wxApp)
937EVT_ACTIVATE_APP(MyApp::OnActivateApp)
938END_EVENT_TABLE()
939
940#include <wx/dynlib.h>
941
942#if wxUSE_CMDLINE_PARSER
943void MyApp::OnInitCmdLine(wxCmdLineParser &parser) {
944 // Add some OpenCPN specific command line options
945 parser.AddSwitch(_T("h"), _T("help"), _("Show usage syntax."),
946 wxCMD_LINE_OPTION_HELP);
947 parser.AddSwitch(_T("p"), wxEmptyString, _("Run in portable mode."));
948 parser.AddSwitch(_T("fullscreen"), wxEmptyString,
949 _("Switch to full screen mode on start."));
950 parser.AddSwitch(
951 _T("no_opengl"), wxEmptyString,
952 _("Disable OpenGL video acceleration. This setting will be remembered."));
953 parser.AddSwitch(_T("rebuild_gl_raster_cache"), wxEmptyString,
954 _T("Rebuild OpenGL raster cache on start."));
955 parser.AddSwitch(
956 _T("parse_all_enc"), wxEmptyString,
957 _T("Convert all S-57 charts to OpenCPN's internal format on start."));
958 parser.AddOption(
959 _T("l"), _T("loglevel"),
960 _("Amount of logging: error, warning, message, info, debug or trace"));
961 parser.AddOption(_T("unit_test_1"), wxEmptyString,
962 _("Display a slideshow of <num> charts and then exit. Zero "
963 "or negative <num> specifies no limit."),
964 wxCMD_LINE_VAL_NUMBER);
965 parser.AddSwitch(_T("unit_test_2"));
966 parser.AddParam("import GPX files", wxCMD_LINE_VAL_STRING,
967 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
968 parser.AddLongSwitch("unit_test_2");
969 parser.AddSwitch("safe_mode");
970}
971
973static void ParseLoglevel(wxCmdLineParser &parser) {
974 const char *strLevel = std::getenv("OPENCPN_LOGLEVEL");
975 strLevel = strLevel ? strLevel : "info";
976 wxString wxLevel;
977 if (parser.Found("l", &wxLevel)) {
978 strLevel = wxLevel.c_str();
979 }
980 wxLogLevel level = OcpnLog::str2level(strLevel);
981 if (level == OcpnLog::LOG_BADLEVEL) {
982 fprintf(stderr, "Bad loglevel %s, using \"info\"", strLevel);
983 strLevel = "info";
984 level = wxLOG_Info;
985 }
986 wxLog::SetLogLevel(level);
987}
988
989bool MyApp::OnCmdLineParsed(wxCmdLineParser &parser) {
990 long number;
991 wxString repo;
992 wxString plugin;
993
994 g_unit_test_2 = parser.Found(_T("unit_test_2"));
995 g_bportable = parser.Found(_T("p"));
996 g_start_fullscreen = parser.Found(_T("fullscreen"));
997 g_bdisable_opengl = parser.Found(_T("no_opengl"));
998 g_rebuild_gl_cache = parser.Found(_T("rebuild_gl_raster_cache"));
999 g_parse_all_enc = parser.Found(_T("parse_all_enc"));
1000 if (parser.Found(_T("unit_test_1"), &number)) {
1001 g_unit_test_1 = static_cast<int>(number);
1002 if (g_unit_test_1 == 0) g_unit_test_1 = -1;
1003 }
1004 safe_mode::set_mode(parser.Found("safe_mode"));
1005 ParseLoglevel(parser);
1006
1007 for (size_t paramNr = 0; paramNr < parser.GetParamCount(); ++paramNr)
1008 g_params.push_back(parser.GetParam(paramNr));
1009
1010 return true;
1011}
1012#endif
1013
1014#ifdef __WXMSW__
1015// Handle any exception not handled by CrashRpt
1016// Most probable: Malloc/new failure
1017
1018bool MyApp::OnExceptionInMainLoop() {
1019 wxLogWarning(_T("Caught MainLoopException, continuing..."));
1020 return true;
1021}
1022#endif
1023
1024void MyApp::OnActivateApp(wxActivateEvent &event) {
1025 return;
1026 // Code carefully in this method.
1027 // It is called in some unexpected places,
1028 // such as on closure of dialogs, etc.
1029
1030 if (!event.GetActive()) {
1031 // Remove a temporary Menubar when the application goes inactive
1032 // This is one way to handle properly ALT-TAB navigation on the Windows
1033 // desktop without accidentally leaving an unwanted Menubar shown.
1034#ifdef __WXMSW__
1035 if (g_bTempShowMenuBar) {
1036 g_bTempShowMenuBar = false;
1037 if (gFrame) gFrame->ApplyGlobalSettings(false);
1038 }
1039#endif
1040 }
1041 event.Skip();
1042}
1043
1044
1045
1046static wxStopWatch init_sw;
1047
1048MyApp::MyApp() {
1049#ifdef __linux__
1050// Handle e. g., wayland default display -- see #1166.
1051
1052 if (wxGetEnv( "WAYLAND_DISPLAY", NULL))
1053 setenv("GDK_BACKEND", "x11", 1);
1054
1055#endif // __linux__
1056}
1057
1058bool MyApp::OnInit() {
1059 if (!wxApp::OnInit()) return false;
1060#ifdef __OCPN__ANDROID__
1061 androidEnableBackButton(false);
1062 androidEnableOptionItems(false);
1063#endif
1064
1065 GpxDocument::SeedRandom();
1066 safe_mode::set_mode(false);
1067
1068 last_own_ship_sog_cog_calc_ts = wxInvalidDateTime;
1069
1070#if defined(__WXGTK__) && defined(ocpnUSE_GLES) && defined(__ARM_ARCH)
1071 // There is a race condition between cairo which is used for text rendering
1072 // by gtk and EGL which without the below code causes a bus error and the
1073 // program aborts before startup
1074 // this hack forces cairo to load right now by rendering some text
1075
1076 wxBitmap bmp(10, 10, -1);
1077 wxMemoryDC dc;
1078 dc.SelectObject(bmp);
1079 dc.DrawText(_T("X"), 0, 0);
1080#endif
1081 m_checker = 0;
1082
1083 // Instantiate the global OCPNPlatform class
1084 g_Platform = new OCPNPlatform;
1085 g_BasePlatform = g_Platform;
1086
1087#ifndef __OCPN__ANDROID__
1088 // On Windows
1089 // We allow only one instance unless the portable option is used
1090 if (!g_bportable && wxDirExists(g_Platform->GetPrivateDataDir())) {
1091 wxChar separator = wxFileName::GetPathSeparator();
1092 wxString service_name =
1093 g_Platform->GetPrivateDataDir() + separator + _T("opencpn-ipc");
1094
1095 m_checker = new wxSingleInstanceChecker(_T("_OpenCPN_SILock"),
1096 g_Platform->GetPrivateDataDir());
1097 if (!m_checker->IsAnotherRunning()) {
1098 stServer *m_server = new stServer;
1099 if (!m_server->Create(service_name)) {
1100 wxLogDebug(wxT("Failed to create an IPC service."));
1101 }
1102 } else {
1103 wxLogNull logNull;
1104 stClient *client = new stClient;
1105 // ignored under DDE, host name in TCP/IP based classes
1106 wxString hostName = wxT("localhost");
1107 // Create the connection service, topic
1108 wxConnectionBase *connection =
1109 client->MakeConnection(hostName, service_name, _T("OpenCPN"));
1110 if (connection) {
1111 // Ask the other instance to open a file or raise itself
1112 if (!g_params.empty()) {
1113 for (size_t n = 0; n < g_params.size(); n++) {
1114 wxString path = g_params[n];
1115 if (::wxFileExists(path)) {
1116 connection->Execute(path);
1117 }
1118 }
1119 }
1120 connection->Execute(wxT(""));
1121 connection->Disconnect();
1122 delete connection;
1123 } else {
1124 // If we get here, it means that the wxWidgets single-instance-detect
1125 // logic found the lock file, And so thinks another instance is
1126 // running. But that instance is not reachable, for some reason. So,
1127 // the safe thing to do is delete the lockfile, and exit. Next start
1128 // will proceed normally. This may leave a zombie OpenCPN, but at least
1129 // O starts.
1130 wxString lockFile = wxString(g_Platform->GetPrivateDataDir() +
1131 separator + _T("_OpenCPN_SILock"));
1132 if (wxFileExists(lockFile)) wxRemoveFile(lockFile);
1133
1134 wxMessageBox(_("Sorry, an existing instance of OpenCPN may be too busy "
1135 "too respond.\nPlease retry."),
1136 wxT("OpenCPN"), wxICON_INFORMATION | wxOK);
1137 }
1138 delete client;
1139 return false; // exit quietly
1140 }
1141 }
1142#endif // __OCPN__ANDROID__
1143
1144 if (getenv("OPENCPN_FATAL_ERROR") != 0) {
1145 wxLogFatalError(getenv("OPENCPN_FATAL_ERROR"));
1146 }
1147 // Check if last run failed, set up safe_mode.
1148 if (!safe_mode::get_mode()) {
1150 }
1151
1152 // Perform first stage initialization
1153 OCPNPlatform::Initialize_1();
1154
1155#if wxCHECK_VERSION(3, 0, 0)
1156 // Set the name of the app as displayed to the user.
1157 // This is necessary at least on OS X, for the capitalisation to be correct in
1158 // the system menus.
1159 MyApp::SetAppDisplayName("OpenCPN");
1160#endif
1161
1162 // Seed the random number generator
1163 wxDateTime x = wxDateTime::UNow();
1164 long seed = x.GetMillisecond();
1165 seed *= x.GetTicks();
1166 srand(seed);
1167
1168 // Fulup: force floating point to use dot as separation.
1169 // This needs to be set early to catch numerics in config file.
1170 setlocale(LC_NUMERIC, "C");
1171
1172 g_start_time = wxDateTime::Now();
1173
1174 g_loglast_time = g_start_time;
1175 g_loglast_time.MakeGMT();
1176 g_loglast_time.Subtract(
1177 wxTimeSpan(0, 29, 0, 0)); // give 1 minute for GPS to get a fix
1178
1179 AnchorPointMinDist = 5.0;
1180
1181 // Init the private memory manager
1182 malloc_max = 0;
1183
1184 // Record initial memory status
1185 GetMemoryStatus(&g_mem_total, &g_mem_initial);
1186
1187 // Set up default FONT encoding, which should have been done by wxWidgets some
1188 // time before this......
1189 wxFont temp_font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
1190 wxFONTWEIGHT_NORMAL, FALSE, wxString(_T("")),
1191 wxFONTENCODING_SYSTEM);
1192 temp_font.SetDefaultEncoding(wxFONTENCODING_SYSTEM);
1193
1194 // Establish Log File location
1195 if (!g_Platform->InitializeLogFile()) return false;
1196
1197#ifdef __WXMSW__
1198
1199 // Un-comment the following to establish a separate console window as a
1200 // target for printf() in Windows
1201 // RedirectIOToConsole();
1202
1203#endif
1204
1205 // Send init message
1206 wxLogMessage(_T("\n\n________\n"));
1207
1208 g_vs = wxString(VERSION_FULL).Trim(true).Trim(false);
1209 wxDateTime now = wxDateTime::Now();
1210 LOG_INFO("------- OpenCPN version %s restarted at %s -------\n", VERSION_FULL,
1211 now.FormatISODate().mb_str().data());
1212 wxLogLevel level = wxLog::GetLogLevel();
1213 LOG_INFO("Using loglevel %s", OcpnLog::level2str(level).c_str());
1214
1215 wxString wxver(wxVERSION_STRING);
1216 wxver.Prepend(_T("wxWidgets version: "));
1217
1218 wxPlatformInfo platforminfo = wxPlatformInfo::Get();
1219
1220 wxString os_name;
1221#ifndef __OCPN__ANDROID__
1222 os_name = platforminfo.GetOperatingSystemIdName();
1223#else
1224 os_name = platforminfo.GetOperatingSystemFamilyName();
1225#endif
1226
1227 wxString platform = os_name + _T(" ") + platforminfo.GetArchName() + _T(" ") +
1228 platforminfo.GetPortIdName();
1229
1230 wxLogMessage(wxver + _T(" ") + platform);
1231
1232 ::wxGetOsVersion(&osMajor, &osMinor);
1233 wxString osVersionMsg;
1234 osVersionMsg.Printf(_T("OS Version reports as: %d.%d"), osMajor, osMinor);
1235 wxLogMessage(osVersionMsg);
1236
1237 wxLogMessage(_T("MemoryStatus: mem_total: %d mb, mem_initial: %d mb"),
1238 g_mem_total / 1024, g_mem_initial / 1024);
1239
1240 OCPN_OSDetail *detail = g_Platform->GetOSDetail();
1241 wxString msgplat;
1242 wxString like0;
1243 if (!detail->osd_names_like.empty())
1244 like0 = detail->osd_names_like[0].c_str();
1245 msgplat.Printf("OCPN_OSDetail: %s ; %s ; %s ; %s ; %s",
1246 detail->osd_arch.c_str(), detail->osd_name.c_str(),
1247 detail->osd_version.c_str(), detail->osd_ID.c_str(),
1248 like0.mb_str());
1249 wxLogMessage(msgplat);
1250
1251 // Initialize embedded PNG icon graphics
1252 ::wxInitAllImageHandlers();
1253
1254 wxString imsg = _T("SData_Locn is ");
1255 imsg += g_Platform->GetSharedDataDir();
1256 wxLogMessage(imsg);
1257
1258#ifdef __WXQT__
1259 // Now we can configure the Qt StyleSheets, if present
1260 prepareAndroidStyleSheets();
1261#endif
1262
1263 // Create some static strings
1264 pInit_Chart_Dir = new wxString();
1265
1266 // Establish an empty ChartCroupArray
1267 g_pGroupArray = new ChartGroupArray;
1268
1269 imsg = _T("PrivateDataDir is ");
1270 imsg += g_Platform->GetPrivateDataDir();
1271 wxLogMessage(imsg);
1272
1273 // Create an array string to hold repeating messages, so they don't
1274 // overwhelm the log
1275 pMessageOnceArray = new wxArrayString;
1276
1277 // Init the Route Manager
1278
1279 struct RoutePropDlgCtx ctx;
1280 ctx.SetRouteAndUpdate = [&](Route* r) {
1281 if (pRoutePropDialog && (pRoutePropDialog->IsShown())) {
1282 pRoutePropDialog->SetRouteAndUpdate(r, true);
1283 }
1284 };
1285 ctx.SetEnroutePoint = [&](Route* r, RoutePoint* rt) {
1286 if (pRoutePropDialog && pRoutePropDialog->IsShown()) {
1287 if (pRoutePropDialog->GetRoute() == r) {
1288 pRoutePropDialog->SetEnroutePoint(rt);
1289 }
1290 }
1291 };
1292 ctx.Hide = [&](Route* r) {
1293 if (pRoutePropDialog && (pRoutePropDialog->IsShown()) &&
1294 (r == pRoutePropDialog->GetRoute())) {
1295 pRoutePropDialog->Hide();
1296 }
1297 };
1298 auto RouteMgrDlgUpdateListCtrl = [&]() {
1299 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
1300 pRouteManagerDialog->UpdateRouteListCtrl();
1301 };
1302
1303 g_pRouteMan = new Routeman(ctx, RouteMgrDlgUpdateListCtrl);
1304
1305 // Init the Selectable Route Items List
1306 pSelect = new Select();
1307 pSelect->SetSelectPixelRadius(12);
1308
1309 // Init the Selectable Tide/Current Items List
1310 pSelectTC = new Select();
1311 // Increase the select radius for tide/current stations
1312 pSelectTC->SetSelectPixelRadius(25);
1313
1314 // Init the Selectable AIS Target List
1315 pSelectAIS = new Select();
1316 pSelectAIS->SetSelectPixelRadius(12);
1317
1318 // Initially AIS display is always on
1319 g_bShowAIS = true;
1320 g_pais_query_dialog_active = NULL;
1321
1322 // Who am I?
1323 g_hostname = ::wxGetHostName();
1324 if(g_hostname.IsEmpty())
1325 g_hostname = wxGetUserName();
1326
1327 // A Portabel need a unique mDNS data hostname to share routes.
1328 if (g_bportable) {
1329 wxString p("Portable-");
1330 g_hostname = p + g_hostname;
1331 }
1332
1333
1334 // Initialize some lists
1335 // Layers
1336 pLayerList = new LayerList;
1337 // Routes
1338 pRouteList = new RouteList;
1339
1340 // (Optionally) Capture the user and file(effective) ids
1341 // Some build environments may need root privileges for hardware
1342 // port I/O, as in the NMEA data input class. Set that up here.
1343
1344#ifndef __WXMSW__
1345#ifdef PROBE_PORTS__WITH_HELPER
1346 user_user_id = getuid();
1347 file_user_id = geteuid();
1348#endif
1349#endif
1350
1351 bool b_initial_load = false;
1352
1353 wxFileName config_test_file_name(g_Platform->GetConfigFileName());
1354 if (config_test_file_name.FileExists())
1355 wxLogMessage(_T("Using existing Config_File: ") +
1356 g_Platform->GetConfigFileName());
1357 else {
1358 {
1359 wxLogMessage(_T("Creating new Config_File: ") +
1360 g_Platform->GetConfigFileName());
1361
1362 b_initial_load = true;
1363
1364 if (true !=
1365 config_test_file_name.DirExists(config_test_file_name.GetPath()))
1366 if (!config_test_file_name.Mkdir(config_test_file_name.GetPath()))
1367 wxLogMessage(_T("Cannot create config file directory for ") +
1368 g_Platform->GetConfigFileName());
1369 }
1370 }
1371
1372 // Open/Create the Config Object
1373 pConfig = g_Platform->GetConfigObject();
1374 InitBaseConfig(pConfig);
1375 pConfig->LoadMyConfig();
1376
1377 // Override for some safe and nice default values if the config file was
1378 // created from scratch
1379 if (b_initial_load) g_Platform->SetDefaultOptions();
1380
1381 g_Platform->applyExpertMode(g_bUIexpert);
1382
1383 // Now initialize UI Style.
1384 g_StyleManager = new ocpnStyle::StyleManager();
1385
1386 // if(g_useMUI)
1387 // g_uiStyle = _T("MUI_flat");
1388
1389 g_StyleManager->SetStyle(_T("MUI_flat"));
1390 if (!g_StyleManager->IsOK()) {
1391 wxString msg = _("Failed to initialize the user interface. ");
1392 msg << _("OpenCPN cannot start. ");
1393 msg << _("The necessary configuration files were not found. ");
1394 msg << _("See the log file at ") << g_Platform->GetLogFileName()
1395 << _(" for details.") << _T("\n\n");
1396 msg << g_Platform->GetSharedDataDir();
1397
1398 wxMessageDialog w(NULL, msg, _("Failed to initialize the user interface. "),
1399 wxCANCEL | wxICON_ERROR);
1400 w.ShowModal();
1401 exit(EXIT_FAILURE);
1402 }
1403
1404 if (g_useMUI) {
1405 ocpnStyle::Style *style = g_StyleManager->GetCurrentStyle();
1406 if (style) style->chartStatusWindowTransparent = true;
1407 }
1408
1409 // Init the WayPoint Manager
1410 pWayPointMan = NULL;
1411
1412 g_display_size_mm = wxMax(100, g_Platform->GetDisplaySizeMM());
1413 wxString msg;
1414 msg.Printf(_T("Detected display size (horizontal): %d mm"),
1415 (int)g_display_size_mm);
1416 wxLogMessage(msg);
1417
1418 // User override....
1419 if ((g_config_display_size_mm > 0) && (g_config_display_size_manual)) {
1420 g_display_size_mm = g_config_display_size_mm;
1421 wxString msg;
1422 msg.Printf(_T("Display size (horizontal) config override: %d mm"),
1423 (int)g_display_size_mm);
1424 wxLogMessage(msg);
1425 g_Platform->SetDisplaySizeMM(g_display_size_mm);
1426 }
1427
1428 g_display_size_mm = wxMax(80, g_display_size_mm);
1429
1430 if (g_btouch) {
1431 int SelectPixelRadius = 50;
1432
1433 pSelect->SetSelectPixelRadius(SelectPixelRadius);
1434 pSelectTC->SetSelectPixelRadius(wxMax(25, SelectPixelRadius));
1435 pSelectAIS->SetSelectPixelRadius(SelectPixelRadius);
1436 }
1437
1438 // Is this the first run after a clean install?
1439 if (!n_NavMessageShown) g_bFirstRun = true;
1440
1441 // Now we can set the locale
1442 // using wxWidgets/gettext methodology....
1443
1444#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
1445
1446 // Where are the opencpn.mo files?
1447 g_Platform->SetLocaleSearchPrefixes();
1448
1449 wxString def_lang_canonical = g_Platform->GetDefaultSystemLocale();
1450
1451 imsg = _T("System default Language: ") + def_lang_canonical;
1452 wxLogMessage(imsg);
1453
1454 wxString cflmsg = _T("Config file language: ") + g_locale;
1455 wxLogMessage(cflmsg);
1456
1457 // Make any adjustments necessary
1458 g_locale = g_Platform->GetAdjustedAppLocale();
1459 cflmsg = _T("Adjusted App language: ") + g_locale;
1460 wxLogMessage(cflmsg);
1461
1462 // Set the desired locale
1463 g_Platform->ChangeLocale(g_locale, plocale_def_lang, &plocale_def_lang);
1464
1465 imsg = _T("Opencpn language set to: ");
1466 imsg += g_locale;
1467 wxLogMessage(imsg);
1468
1469 // French language locale is assumed to include the AZERTY keyboard
1470 // This applies to either the system language, or to OpenCPN language
1471 // selection
1472 if (g_locale == _T("fr_FR")) g_b_assume_azerty = true;
1473#else
1474 wxLogMessage(_T("wxLocale support not available"));
1475#endif
1476
1477 // Instantiate and initialize the Config Manager
1478 ConfigMgr::Get();
1479
1480 // Is this an upgrade?
1481 wxString vs = wxString("Version ") + VERSION_FULL + " Build " + VERSION_DATE;
1482 g_bUpgradeInProcess = (vs != g_config_version_string);
1483
1484 g_Platform->SetUpgradeOptions(vs, g_config_version_string);
1485
1486 // log deferred log restart message, if it exists.
1487 if (!g_Platform->GetLargeLogMessage().IsEmpty())
1488 wxLogMessage(g_Platform->GetLargeLogMessage());
1489
1490 // Validate OpenGL functionality, if selected
1491#ifdef ocpnUSE_GL
1492
1493#ifdef __WXMSW__
1494#if !wxCHECK_VERSION( \
1495 2, 9, 0) // The OpenGL test app only runs on wx 2.8, unavailable on wx3.x
1496
1497 if (/*g_bopengl &&*/ !g_bdisable_opengl) {
1498 wxFileName fn(g_Platform->GetExePath());
1499 bool b_test_result = TestGLCanvas(fn.GetPathWithSep());
1500
1501 if (!b_test_result)
1502 wxLogMessage(_T("OpenGL disabled due to test app failure."));
1503
1504 g_bdisable_opengl = !b_test_result;
1505 }
1506#endif
1507#endif
1508
1509#else
1510 g_bdisable_opengl = true;
1511 ;
1512#endif
1513
1514 if (g_bdisable_opengl) g_bopengl = false;
1515
1516#if defined(__UNIX__) && !defined(__OCPN__ANDROID__) && !defined(__WXOSX__)
1517 if (g_bSoftwareGL) setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
1518#endif
1519
1520 //FIXMW (dave) move to frame
1521 //g_bTransparentToolbarInOpenGLOK = isTransparentToolbarInOpenGLOK();
1522
1523 // On Windows platforms, establish a default cache managment policy
1524 // as allowing OpenCPN a percentage of available physical memory,
1525 // not to exceed 1 GB
1526 // Note that this logic implies that Windows platforms always use
1527 // the memCacheLimit policy, and never use the fallback nCacheLimit policy
1528#ifdef __WXMSW__
1529 if (0 == g_memCacheLimit) g_memCacheLimit = (int)(g_mem_total * 0.5);
1530 g_memCacheLimit =
1531 wxMin(g_memCacheLimit, 1024 * 1024); // math in kBytes, Max is 1 GB
1532#else
1533 // All other platforms will use the nCacheLimit policy
1534 // sinc on linux it is impossible to accurately measure the application memory
1535 // footprint without expensive methods such as malloc/free tracking, and such
1536
1537 g_memCacheLimit = 0;
1538 if (0 == g_nCacheLimit) // allow config file override
1539 g_nCacheLimit = CACHE_N_LIMIT_DEFAULT;
1540#endif
1541
1542 // Establish location and name of chart database
1543 ChartListFileName = newPrivateFileName(g_Platform->GetPrivateDataDir(),
1544 "chartlist.dat", "CHRTLIST.DAT");
1545
1546 // Establish location and name of AIS MMSI -> Target Name mapping
1547 AISTargetNameFileName = newPrivateFileName(g_Platform->GetPrivateDataDir(),
1548 "mmsitoname.csv", "MMSINAME.CSV");
1549
1550 // Establish guessed location of chart tree
1551 if (pInit_Chart_Dir->IsEmpty()) {
1552 wxStandardPaths &std_path = g_Platform->GetStdPaths();
1553
1554 if (!g_bportable)
1555#ifndef __OCPN__ANDROID__
1556 pInit_Chart_Dir->Append(std_path.GetDocumentsDir());
1557#else
1558 pInit_Chart_Dir->Append(androidGetExtStorageDir());
1559#endif
1560 }
1561
1562 // Establish the GSHHS Dataset location
1563 gDefaultWorldMapLocation = "gshhs";
1564 gDefaultWorldMapLocation.Prepend(g_Platform->GetSharedDataDir());
1565 gDefaultWorldMapLocation.Append(wxFileName::GetPathSeparator());
1566 if (gWorldMapLocation == wxEmptyString) {
1567 gWorldMapLocation = gDefaultWorldMapLocation;
1568 }
1569
1570 // Check the global Tide/Current data source array
1571 // If empty, preset default (US + ROW) data sources
1572 wxString default_tcdata0 =
1573 (g_Platform->GetSharedDataDir() + _T("tcdata") +
1574 wxFileName::GetPathSeparator() + _T("harmonics-dwf-20210110-free.tcd"));
1575 wxString default_tcdata1 =
1576 (g_Platform->GetSharedDataDir() + _T("tcdata") +
1577 wxFileName::GetPathSeparator() + _T("HARMONICS_NO_US.IDX"));
1578
1579 if (!TideCurrentDataSet.GetCount()) {
1580 TideCurrentDataSet.Add(g_Platform->NormalizePath(default_tcdata0));
1581 TideCurrentDataSet.Add(g_Platform->NormalizePath(default_tcdata1));
1582 } else {
1583 wxString first_tide = TideCurrentDataSet[0];
1584 wxFileName ft(first_tide);
1585 if (!ft.FileExists()) {
1586 TideCurrentDataSet.RemoveAt(0);
1587 TideCurrentDataSet.Insert(g_Platform->NormalizePath(default_tcdata0), 0);
1588 TideCurrentDataSet.Add(g_Platform->NormalizePath(default_tcdata1));
1589 }
1590 }
1591
1592 // Check the global AIS alarm sound file
1593 // If empty, preset default
1594 if (g_sAIS_Alert_Sound_File.IsEmpty()) {
1595 wxString default_sound =
1596 (g_Platform->GetSharedDataDir() + _T("sounds") +
1597 wxFileName::GetPathSeparator() + _T("2bells.wav"));
1598 g_sAIS_Alert_Sound_File = g_Platform->NormalizePath(default_sound);
1599 }
1600
1601 gpIDX = NULL;
1602 gpIDXn = 0;
1603
1604 g_Platform->Initialize_2();
1605
1606 // Set up the frame initial visual parameters
1607 // Default size, resized later
1608 wxSize new_frame_size(-1, -1);
1609 int cx, cy, cw, ch;
1610 ::wxClientDisplayRect(&cx, &cy, &cw, &ch);
1611
1612 InitializeUserColors();
1613
1614 auto style = g_StyleManager->GetCurrentStyle();
1615 auto bitmap = new wxBitmap(style->GetIcon("default_pi", 32, 32));
1616 if (bitmap->IsOk())
1617 PluginLoader::getInstance()->SetPluginDefaultIcon(bitmap);
1618 else
1619 wxLogWarning("Cannot initiate plugin default jigsaw icon.");
1620
1621
1622 if ((g_nframewin_x > 100) && (g_nframewin_y > 100) && (g_nframewin_x <= cw) &&
1623 (g_nframewin_y <= ch))
1624 new_frame_size.Set(g_nframewin_x, g_nframewin_y);
1625 else
1626 new_frame_size.Set(cw * 7 / 10, ch * 7 / 10);
1627
1628 // Try to detect any change in physical screen configuration
1629 // This can happen when drivers are changed, for instance....
1630 // and can confuse the WUI layout perspective stored in the config file.
1631 // If detected, force a nominal window size and position....
1632 if ((g_lastClientRectx != cx) || (g_lastClientRecty != cy) ||
1633 (g_lastClientRectw != cw) || (g_lastClientRecth != ch)) {
1634 new_frame_size.Set(cw * 7 / 10, ch * 7 / 10);
1635 g_bframemax = false;
1636 }
1637
1638 g_lastClientRectx = cx;
1639 g_lastClientRecty = cy;
1640 g_lastClientRectw = cw;
1641 g_lastClientRecth = ch;
1642
1643 // Validate config file position
1644 wxPoint position(0, 0);
1645 wxSize dsize = wxGetDisplaySize();
1646
1647#ifdef __WXMAC__
1648 g_nframewin_posy = wxMax(g_nframewin_posy, 22);
1649#endif
1650
1651 if ((g_nframewin_posx < dsize.x) && (g_nframewin_posy < dsize.y))
1652 position = wxPoint(g_nframewin_posx, g_nframewin_posy);
1653
1654#ifdef __WXMSW__
1655 // Support MultiMonitor setups which an allow negative window positions.
1656 RECT frame_rect;
1657 frame_rect.left = position.x;
1658 frame_rect.top = position.y;
1659 frame_rect.right = position.x + new_frame_size.x;
1660 frame_rect.bottom = position.y + new_frame_size.y;
1661
1662 // If the requested frame window does not intersect any installed monitor,
1663 // then default to simple primary monitor positioning.
1664 if (NULL == MonitorFromRect(&frame_rect, MONITOR_DEFAULTTONULL))
1665 position = wxPoint(10, 10);
1666#endif
1667
1668#ifdef __OCPN__ANDROID__
1669 wxSize asz = getAndroidDisplayDimensions();
1670 ch = asz.y;
1671 cw = asz.x;
1672 // qDebug() << cw << ch;
1673
1674 if ((cw > 200) && (ch > 200))
1675 new_frame_size.Set(cw, ch);
1676 else
1677 new_frame_size.Set(800, 400);
1678#endif
1679
1680 // For Windows and GTK, provide the expected application Minimize/Close bar
1681 long app_style = wxDEFAULT_FRAME_STYLE;
1682 app_style |= wxWANTS_CHARS;
1683
1684 // Create the main frame window
1685 wxString myframe_window_title = wxString::Format(wxT("OpenCPN %s"),
1686 VERSION_FULL); // Gunther
1687
1688 if (g_bportable) {
1689 myframe_window_title += _(" -- [Portable(-p) executing from ");
1690 myframe_window_title += g_Platform->GetHomeDir();
1691 myframe_window_title += _T("]");
1692 }
1693
1694 wxString fmsg;
1695 fmsg.Printf(_T("Creating MyFrame...size(%d, %d) position(%d, %d)"),
1696 new_frame_size.x, new_frame_size.y, position.x, position.y);
1697 wxLogMessage(fmsg);
1698
1699 gFrame = new MyFrame(NULL, myframe_window_title, position, new_frame_size,
1700 app_style); // Gunther
1701
1702 // Do those platform specific initialization things that need gFrame
1703 g_Platform->Initialize_3();
1704
1705 // Initialize the Plugin Manager
1706 g_pi_manager = new PlugInManager(gFrame);
1707
1708 // g_pauimgr = new wxAuiManager;
1709 g_pauimgr = new OCPN_AUIManager;
1710 g_pauidockart = new wxAuiDefaultDockArt;
1711 g_pauimgr->SetArtProvider(g_pauidockart);
1712 g_pauimgr->SetDockSizeConstraint(.9, .9);
1713
1714 // g_pauimgr->SetFlags(g_pauimgr->GetFlags() | wxAUI_MGR_LIVE_RESIZE);
1715
1716 g_grad_default = g_pauidockart->GetMetric(wxAUI_DOCKART_GRADIENT_TYPE);
1717 g_border_color_default =
1718 g_pauidockart->GetColour(wxAUI_DOCKART_BORDER_COLOUR);
1719 g_border_size_default =
1720 g_pauidockart->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE);
1721 g_sash_size_default = g_pauidockart->GetMetric(wxAUI_DOCKART_SASH_SIZE);
1722 g_caption_color_default =
1723 g_pauidockart->GetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR);
1724 g_sash_color_default = g_pauidockart->GetColour(wxAUI_DOCKART_SASH_COLOUR);
1725 g_background_color_default =
1726 g_pauidockart->GetColour(wxAUI_DOCKART_BACKGROUND_COLOUR);
1727
1728 // tell wxAuiManager to manage the frame
1729 g_pauimgr->SetManagedWindow(gFrame);
1730
1731 gFrame->CreateCanvasLayout();
1732
1733 // gFrame->RequestNewMasterToolbar( true );
1734
1735 gFrame->SetChartUpdatePeriod(); // Reasonable default
1736
1737 gFrame->Enable();
1738
1739 gFrame->GetPrimaryCanvas()->SetFocus();
1740
1741 pthumbwin = new ThumbWin(gFrame->GetPrimaryCanvas());
1742
1743 gFrame->ApplyGlobalSettings(false); // done once on init with resize
1744
1745 gFrame->SetAllToolbarScale();
1746
1747 // Show the frame
1748
1749 gFrame->Show(TRUE);
1750
1751 gFrame->SetAndApplyColorScheme(global_color_scheme);
1752
1753 if (g_bframemax) gFrame->Maximize(true);
1754
1755#ifdef __OCPN__ANDROID__
1756 if (g_bresponsive && (gFrame->GetPrimaryCanvas()->GetPixPerMM() > 4.0))
1757 gFrame->Maximize(true);
1758#endif
1759
1760 // Yield to pick up the OnSize() calls that result from Maximize()
1761 Yield();
1762
1763 // Build the initial chart dir array
1764 ArrayOfCDI ChartDirArray;
1765 pConfig->LoadChartDirArray(ChartDirArray);
1766
1767 // Windows installer may have left hints regarding the initial chart dir
1768 // selection
1769#ifdef __WXMSW__
1770 if (g_bFirstRun && (ChartDirArray.GetCount() == 0)) {
1771 int ndirs = 0;
1772
1773 wxRegKey RegKey(wxString(_T("HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenCPN")));
1774 if (RegKey.Exists()) {
1775 wxLogMessage(
1776 _("Retrieving initial Chart Directory set from Windows Registry"));
1777 wxString dirs;
1778 RegKey.QueryValue(wxString(_T("ChartDirs")), dirs);
1779
1780 wxStringTokenizer tkz(dirs, _T(";"));
1781 while (tkz.HasMoreTokens()) {
1782 wxString token = tkz.GetNextToken();
1783
1784 ChartDirInfo cdi;
1785 cdi.fullpath = token.Trim();
1786 cdi.magic_number = _T("");
1787
1788 ChartDirArray.Add(cdi);
1789 ndirs++;
1790 }
1791 }
1792
1793 if (g_bportable) {
1794 ChartDirInfo cdi;
1795 cdi.fullpath = _T("charts");
1796 cdi.fullpath.Prepend(g_Platform->GetSharedDataDir());
1797 cdi.magic_number = _T("");
1798 ChartDirArray.Add(cdi);
1799 ndirs++;
1800 }
1801
1802 if (ndirs) pConfig->UpdateChartDirs(ChartDirArray);
1803 }
1804#endif
1805
1806 // If the ChartDirArray is empty at this point, any existing chart database
1807 // file must be declared invalid, So it is best to simply delete it if
1808 // present.
1809 // TODO There is a possibility of recreating the dir list from the
1810 // database itself......
1811
1812 if (!ChartDirArray.GetCount())
1813 if (::wxFileExists(ChartListFileName)) ::wxRemoveFile(ChartListFileName);
1814
1815 // Try to load the current chart list Data file
1816 ChartData = new ChartDB();
1817 if (!ChartData->LoadBinary(ChartListFileName, ChartDirArray)) {
1818 g_bNeedDBUpdate = true;
1819 }
1820
1821 // Verify any saved chart database startup index
1822 if (g_restore_dbindex >= 0) {
1823 if (ChartData->GetChartTableEntries() == 0)
1824 g_restore_dbindex = -1;
1825
1826 else if (g_restore_dbindex > (ChartData->GetChartTableEntries() - 1))
1827 g_restore_dbindex = 0;
1828 }
1829
1830 // Apply the inital Group Array structure to the chart data base
1831 ChartData->ApplyGroupArray(g_pGroupArray);
1832
1833 // All set to go.....
1834
1835 // Process command line option to rebuild cache
1836#ifdef ocpnUSE_GL
1837 extern ocpnGLOptions g_GLOptions;
1838
1839 if (g_rebuild_gl_cache && g_bopengl && g_GLOptions.m_bTextureCompression &&
1840 g_GLOptions.m_bTextureCompressionCaching) {
1841 gFrame->ReloadAllVP(); // Get a nice chart background loaded
1842
1843 // Turn off the toolbar as a clear signal that the system is busy right
1844 // now.
1845 // Note: I commented this out because the toolbar never comes back for me
1846 // and is unusable until I restart opencpn without generating the cache
1847 // if( g_MainToolbar )
1848 // g_MainToolbar->Hide();
1849
1850 if (g_glTextureManager) g_glTextureManager->BuildCompressedCache();
1851 }
1852#endif
1853
1854 //FIXME (dave)
1855 // move method to frame
1856 //if (g_parse_all_enc) ParseAllENC(gFrame);
1857
1858 // establish GPS timeout value as multiple of frame timer
1859 // This will override any nonsense or unset value from the config file
1860 if ((gps_watchdog_timeout_ticks > 60) || (gps_watchdog_timeout_ticks <= 0))
1861 gps_watchdog_timeout_ticks = (GPS_TIMEOUT_SECONDS * 1000) / TIMER_GFRAME_1;
1862
1863 wxString dogmsg;
1864 dogmsg.Printf(_T("GPS Watchdog Timeout is: %d sec."),
1865 gps_watchdog_timeout_ticks);
1866 wxLogMessage(dogmsg);
1867
1868 sat_watchdog_timeout_ticks = gps_watchdog_timeout_ticks;
1869
1870 g_priSats = 99;
1871
1872 // Most likely installations have no ownship heading information
1873 g_bVAR_Rx = false;
1874
1875 // Start up a new track if enabled in config file
1876 if (g_bTrackCarryOver) g_bDeferredStartTrack = true;
1877
1878 pAnchorWatchPoint1 = NULL;
1879 pAnchorWatchPoint2 = NULL;
1880
1881 Yield();
1882
1883 gFrame->DoChartUpdate();
1884
1885 FontMgr::Get()
1886 .ScrubList(); // Clean the font list, removing nonsensical entries
1887
1888 gFrame->ReloadAllVP(); // once more, and good to go
1889
1890 gFrame->Refresh(false);
1891 gFrame->Raise();
1892
1893 gFrame->GetPrimaryCanvas()->Enable();
1894 gFrame->GetPrimaryCanvas()->SetFocus();
1895
1896 // This little hack fixes a problem seen with some UniChrome OpenGL drivers
1897 // We need a deferred resize to get glDrawPixels() to work right.
1898 // So we set a trigger to generate a resize after 5 seconds....
1899 // See the "UniChrome" hack elsewhere
1900#ifdef ocpnUSE_GL
1901 if (!g_bdisable_opengl) {
1902 glChartCanvas *pgl =
1903 (glChartCanvas *)gFrame->GetPrimaryCanvas()->GetglCanvas();
1904 if (pgl &&
1905 (pgl->GetRendererString().Find(_T("UniChrome")) != wxNOT_FOUND)) {
1906 gFrame->m_defer_size = gFrame->GetSize();
1907 gFrame->SetSize(gFrame->m_defer_size.x - 10, gFrame->m_defer_size.y);
1908 g_pauimgr->Update();
1909 gFrame->m_bdefer_resize = true;
1910 }
1911 }
1912#endif
1913
1914 if (g_start_fullscreen) gFrame->ToggleFullScreen();
1915
1916#ifdef __OCPN__ANDROID__
1917 // We need a resize to pick up height adjustment after building android
1918 // ActionBar
1919 gFrame->SetSize(getAndroidDisplayDimensions());
1920 androidSetFollowTool(gFrame->GetPrimaryCanvas()->m_bFollow ? 1 : 0, true);
1921#endif
1922
1923 gFrame->Raise();
1924 gFrame->GetPrimaryCanvas()->Enable();
1925 gFrame->GetPrimaryCanvas()->SetFocus();
1926
1927 // Setup Tides/Currents to settings present at last shutdown
1928 // TODO
1929 // gFrame->ShowTides( g_bShowTide );
1930 // gFrame->ShowCurrents( g_bShowCurrent );
1931
1932 // Start up the ticker....
1933 gFrame->FrameTimer1.Start(TIMER_GFRAME_1, wxTIMER_CONTINUOUS);
1934
1935 // Start up the ViewPort Rotation angle Averaging Timer....
1936 gFrame->FrameCOGTimer.Start(2000, wxTIMER_CONTINUOUS);
1937
1938 // wxLogMessage( wxString::Format(_T("OpenCPN Initialized in %ld ms."),
1939 // init_sw.Time() ) );
1940
1941 OCPNPlatform::Initialize_4();
1942
1943#ifdef __OCPN__ANDROID__
1944 androidHideBusyIcon();
1945#endif
1946 wxLogMessage(
1947 wxString::Format(_("OpenCPN Initialized in %ld ms."), init_sw.Time()));
1948
1949 wxMilliSleep(500);
1950
1951#ifdef __OCPN__ANDROID__
1952 // We defer the startup message to here to allow the app frame to be
1953 // contructed, thus avoiding a dialog with NULL parent which might not work
1954 // on some devices.
1955 if (!n_NavMessageShown || (vs != g_config_version_string) ||
1956 (g_AndroidVersionCode != androidGetVersionCode())) {
1957 // qDebug() << "Showing NavWarning";
1958 wxMilliSleep(500);
1959 //FIXME (dave) Move to frame
1960/*
1961 if (wxID_CANCEL == ShowNavWarning()) {
1962 qDebug() << "Closing due to NavWarning Cancel";
1963 gFrame->Close();
1964 androidTerminate();
1965 return true;
1966 }
1967*/
1968 n_NavMessageShown = 1;
1969 }
1970
1971 // Finished with upgrade checking, so persist the currect Version Code
1972 g_AndroidVersionCode = androidGetVersionCode();
1973 qDebug() << "Persisting Version Code: " << g_AndroidVersionCode;
1974#else
1975 // Send the Welcome/warning message if it has never been sent before,
1976 // or if the version string has changed at all
1977 // We defer until here to allow for localization of the message
1978 if (!n_NavMessageShown || (vs != g_config_version_string)) {
1979 //FIXME (dave) Move to frame
1980 //if (wxID_CANCEL == ShowNavWarning()) return false;
1981 n_NavMessageShown = 1;
1982 }
1983#endif
1984
1985 // As an a.e. Raspberry does not have a hardwareclock we will have some
1986 // problems with date/time setting
1987 g_bHasHwClock = true; // by default most computers do have a hwClock
1988#if defined(__UNIX__) && !defined(__OCPN__ANDROID__)
1989 struct stat buffer;
1990 g_bHasHwClock =
1991 ((stat("/dev/rtc", &buffer) == 0) || (stat("/dev/rtc0", &buffer) == 0) ||
1992 (stat("/dev/misc/rtc", &buffer) == 0));
1993#endif
1994
1995 g_config_version_string = vs;
1996
1997 // The user accepted the "not for navigation" nag, so persist it here...
1998 pConfig->UpdateSettings();
1999
2000 // Start delayed initialization chain after some milliseconds
2001 gFrame->InitTimer.Start(5, wxTIMER_CONTINUOUS);
2002
2003 g_pauimgr->Update();
2004
2005#if defined(__linux__) && !defined(__OCPN__ANDROID__)
2006 for (size_t i = 0; i < TheConnectionParams()->Count(); i++) {
2007 ConnectionParams *cp = TheConnectionParams()->Item(i);
2008 if (cp->bEnabled) {
2009 if (cp->GetDSPort().Contains(_T("Serial"))) {
2010 std::string port(cp->Port.ToStdString());
2011 CheckSerialAccess(gFrame, port);
2012 }
2013 }
2014 }
2015 CheckDongleAccess(gFrame);
2016#endif
2017
2018 // Initialize the CommBridge
2019 m_comm_bridge.Initialize();
2020
2021 std::vector<std::string> ipv4_addrs = get_local_ipv4_addresses();
2022
2023 //If network connection is available, start the server and mDNS client
2024 if (ipv4_addrs.size()) {
2025 std::string ipAddr = ipv4_addrs[0];
2026
2027 wxString data_dir = g_Platform->GetPrivateDataDir();
2028 if (data_dir.Last() != wxFileName::GetPathSeparator())
2029 data_dir.Append(wxFileName::GetPathSeparator());
2030
2031 make_certificate(ipAddr, data_dir.ToStdString());
2032
2033 m_RESTserver.StartServer(data_dir.ToStdString());
2034
2035 StartMDNSService(g_hostname.ToStdString(), "opencpn-object-control-service", 8000);
2036 }
2037
2038 return TRUE;
2039}
2040
2041int MyApp::OnExit() {
2042 wxLogMessage(_T("opencpn::MyApp starting exit."));
2043
2044 // Send current nav status data to log file // pjotrc 2010.02.09
2045
2046 wxDateTime lognow = wxDateTime::Now();
2047 lognow.MakeGMT();
2048 wxString day = lognow.FormatISODate();
2049 wxString utc = lognow.FormatISOTime();
2050 wxString navmsg = _T("LOGBOOK: ");
2051 navmsg += day;
2052 navmsg += _T(" ");
2053 navmsg += utc;
2054 navmsg += _T(" UTC ");
2055
2056 if (bGPSValid) {
2057 wxString data;
2058 data.Printf(_T("OFF: Lat %10.5f Lon %10.5f "), gLat, gLon);
2059 navmsg += data;
2060
2061 wxString cog;
2062 if (std::isnan(gCog))
2063 cog.Printf(_T("COG ----- "));
2064 else
2065 cog.Printf(_T("COG %10.5f "), gCog);
2066
2067 wxString sog;
2068 if (std::isnan(gSog))
2069 sog.Printf(_T("SOG ----- "));
2070 else
2071 sog.Printf(_T("SOG %6.2f ") + getUsrSpeedUnit(), toUsrSpeed(gSog));
2072
2073 navmsg += cog;
2074 navmsg += sog;
2075
2076 } else {
2077 wxString data;
2078 data.Printf(_T("OFF: Lat %10.5f Lon %10.5f"), gLat, gLon);
2079 navmsg += data;
2080 }
2081 wxLogMessage(navmsg);
2082 g_loglast_time = lognow;
2083
2084 if (ptcmgr) delete ptcmgr;
2085
2086 delete pConfig;
2087 delete pSelect;
2088 delete pSelectTC;
2089 delete pSelectAIS;
2090
2091 delete ps52plib;
2092
2093 if (g_pGroupArray) {
2094 for (unsigned int igroup = 0; igroup < g_pGroupArray->GetCount();
2095 igroup++) {
2096 delete g_pGroupArray->Item(igroup);
2097 }
2098
2099 g_pGroupArray->Clear();
2100 delete g_pGroupArray;
2101 }
2102
2103 wxLogMessage(_T("opencpn::MyApp exiting cleanly...\n"));
2104 wxLog::FlushActive();
2105
2106 g_Platform->CloseLogFile();
2107
2108 delete pInit_Chart_Dir;
2109
2110 for (Track* track : g_TrackList) {
2111 delete track;
2112 }
2113 g_TrackList.clear();
2114
2115 delete g_pRouteMan;
2116 delete pWayPointMan;
2117
2118 delete pMessageOnceArray;
2119
2120 DeInitializeUserColors();
2121
2122 delete pLayerList;
2123
2124 delete m_pRegistrarMan;
2125 CSVDeaccess(NULL);
2126
2127 delete g_StyleManager;
2128
2129#ifdef __WXMSW__
2130#ifdef USE_GLU_TESS
2131#ifdef USE_GLU_DLL
2132 if (s_glu_dll_ready) FreeLibrary(s_hGLU_DLL); // free the glu32.dll
2133#endif
2134#endif
2135#endif
2136
2137 // Restore any changed system colors
2138
2139
2140#ifdef __WXMSW__
2141void RestoreSystemColors(void);
2142 RestoreSystemColors();
2143#endif
2144
2145#ifdef __MSVC__LEAK
2146 DeInitAllocCheck();
2147#endif
2148
2149#if wxUSE_XLOCALE || !wxCHECK_VERSION(3, 0, 0)
2150 delete plocale_def_lang;
2151#endif
2152
2153 FontMgr::Shutdown();
2154
2155 delete m_checker;
2156
2157 g_Platform->OnExit_2();
2159
2160 return TRUE;
2161}
2162
2163#ifdef LINUX_CRASHRPT
2164void MyApp::OnFatalException() { g_crashprint.Report(); }
2165#endif
2166
2167Track* MyApp::TrackOff(void) {
2168 if (gFrame)
2169 return gFrame->TrackOff();
2170 else
2171 return nullptr;
2172}
2173
2174#include <wx/power.h>
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186//----------------------------------------------------------------------------------------------------------
2187// Application-wide CPL Error handler
2188//----------------------------------------------------------------------------------------------------------
2189void MyCPLErrorHandler(CPLErr eErrClass, int nError, const char *pszErrorMsg)
2190
2191{
2192 char msg[256];
2193
2194 if (eErrClass == CE_Debug)
2195 snprintf(msg, 255, "CPL: %s", pszErrorMsg);
2196 else if (eErrClass == CE_Warning)
2197 snprintf(msg, 255, "CPL Warning %d: %s", nError, pszErrorMsg);
2198 else
2199 snprintf(msg, 255, "CPL ERROR %d: %s", nError, pszErrorMsg);
2200
2201 wxString str(msg, wxConvUTF8);
2202 wxLogMessage(str);
2203}
2204
2205
Definition: IDX_entry.h:41
Class MarkInfoDef.
Definition: MarkInfo.h:197
Definition: ocpn_app.h:44
Definition: route.h:70
Definition: select.h:51
Definition: tcmgr.h:86
Class TrackPropDlg.
Definition: TrackPropDlg.h:87
Definition: track.h:79
Definition: about.h:48
s57RegistrarMgr Definition This is a class holding the ctor and dtor for the global registrar
wxCrashPrint
Definition: crashprint.h:37
void check_last_start()
Check if the last start failed, possibly invoke user dialog and set safe mode state.
Definition: safe_mode.cpp:53
void clear_check()
Mark last run as successful.
Definition: safe_mode.cpp:71