36#include <wx/datetime.h>
40#include "ais_decoder.h"
41#include "ais_info_gui.h"
42#include "AISTargetAlertDialog.h"
43#include "ais_target_data.h"
45#include "ocpn_frame.h"
46#include "OCPNPlatform.h"
48#include "routemanagerdialog.h"
49#include "route_point.h"
50#include "SoundFactory.h"
53wxDEFINE_EVENT(EVT_AIS_DEL_TRACK, wxCommandEvent);
55wxDEFINE_EVENT(EVT_AIS_NEW_TRACK, wxCommandEvent);
56wxDEFINE_EVENT(EVT_AIS_TOUCH, wxCommandEvent);
57wxDEFINE_EVENT(EVT_AIS_WP, wxCommandEvent);
58wxDEFINE_EVENT(SOUND_PLAYED_EVTYPE, wxCommandEvent);
62extern ArrayOfMmsiProperties g_MMSI_Props_Array;
63extern bool g_bAIS_CPA_Alert;
64extern bool g_bAIS_CPA_Alert_Audio;
65extern bool g_bAIS_DSC_Alert_Audio;
66extern bool g_bAIS_GCPA_Alert_Audio;
67extern bool g_bAIS_SART_Alert_Audio;
68extern bool g_bquiting;
69extern int g_iSoundDeviceIndex;
71extern Route *pAISMOBRoute;
72extern wxString g_AIS_sound_file;
73extern wxString g_CmdSoundString;
74extern wxString g_DSC_sound_file;
75extern wxString g_SART_sound_file;
82static void onSoundFinished(
void *ptr) {
84 wxCommandEvent ev(SOUND_PLAYED_EVTYPE);
85 wxPostEvent(g_pAISGUI, ev);
90 pConfig->AddNewWayPoint(pWP, -1);
91 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
92 pRouteManagerDialog->UpdateWptListCtrl();
93 if (gFrame->GetPrimaryCanvas()) {
94 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
95 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
96 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
97 gFrame->RefreshAllCanvas(
false);
98 gFrame->InvalidateAllGL();
102const static char*
const kDeleteTrackPrompt =
104This AIS target has Persistent Tracking selected by MMSI properties
105A Persistent track recording will therefore be restarted for this target.
107Do you instead want to stop Persistent Tracking for this target?
112 if (wxID_NO == OCPNMessageBox(NULL, kDeleteTrackPrompt, _(
"OpenCPN Info"),
113 wxYES_NO | wxCENTER, 60))
115 props->m_bPersistentTrack =
true;
120AisInfoGui::AisInfoGui() {
124 auto ptr = ev.GetSharedPtr();
125 auto palert_target = std::static_pointer_cast<const AisTargetData>(ptr);
126 ShowAisInfo(palert_target); }
130 Bind(EVT_AIS_TOUCH, [&](wxCommandEvent ev) { gFrame->TouchAISActive(); });
133 Bind(EVT_AIS_WP, [&](wxCommandEvent ev) {
134 auto pWP =
static_cast<RoutePoint*
>(ev.GetClientData());
135 OnNewAisWaypoint(pWP); });
139 Bind(EVT_AIS_NEW_TRACK, [&](wxCommandEvent ev) {
140 auto t =
static_cast<Track*
>(ev.GetClientData());
141 pConfig->AddNewTrack(t); });
145 Bind(EVT_AIS_DEL_TRACK, [&](wxCommandEvent ev) {
147 OnDeleteTrack(t); });
149 Bind(SOUND_PLAYED_EVTYPE, [&](wxCommandEvent ev) {
150 OnSoundFinishedAISAudio(ev); });
153 m_bAIS_Audio_Alert_On =
false;
154 m_bAIS_AlertPlaying =
false;
158void AisInfoGui::OnSoundFinishedAISAudio(wxCommandEvent &event) {
161 m_bAIS_AlertPlaying =
false;
164void AisInfoGui::ShowAisInfo(std::shared_ptr<const AisTargetData> palert_target) {
165 int audioType = AISAUDIO_NONE;
166 if (!palert_target)
return;
169 if (!g_pais_alert_dialog_active) {
170 bool b_jumpto = (palert_target->Class == AIS_SART) ||
171 (palert_target->Class == AIS_DSC);
172 bool b_createWP = palert_target->Class == AIS_DSC;
173 bool b_ack = palert_target->Class != AIS_DSC;
186 if (gFrame->IsIconized() || !gFrame->IsActive())
187 gFrame->RequestUserAttention();
190 if (!gFrame->IsIconized()) {
192 pAISAlertDialog->Create(palert_target->MMSI, gFrame, g_pAIS,
193 b_jumpto, b_createWP, b_ack, -1,
195 g_pais_alert_dialog_active = pAISAlertDialog;
197 wxTimeSpan alertLifeTime(0, 1, 0,
199 g_pais_alert_dialog_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
200 g_Platform->PositionAISAlert(pAISAlertDialog);
202 pAISAlertDialog->Show();
206 m_bAIS_Audio_Alert_On =
true;
214 double tcpa_min = 1e6;
216 const auto& current_targets = g_pAIS->GetTargetList();
217 for (
auto& it : current_targets) {
220 if ((td->Class != AIS_SART) && (td->Class != AIS_DSC)) {
221 if (g_bAIS_CPA_Alert && td->b_active) {
222 if ((AIS_ALERT_SET == td->n_alert_state) && !td->b_in_ack_timeout) {
223 if (td->TCPA < tcpa_min) {
225 palert_target_lowestcpa = td.get();
234 palert_target = g_pAIS->Get_Target_Data_From_MMSI(
235 g_pais_alert_dialog_active->Get_Dialog_MMSI());
241 if (AIS_NO_ALERT == palert_target->n_alert_state) {
242 if (palert_target_lowestcpa) {
243 palert_target = NULL;
249 wxDateTime now = wxDateTime::Now();
250 if (((AIS_ALERT_SET == palert_target->n_alert_state) &&
251 !palert_target->b_in_ack_timeout) ||
252 (palert_target->Class == AIS_SART) ) {
253 g_pais_alert_dialog_active->UpdateText();
255 wxTimeSpan alertLifeTime(0, 1, 0,
257 g_pais_alert_dialog_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
260 else if (!palert_target->b_in_ack_timeout &&
261 (now.IsEarlierThan(g_pais_alert_dialog_active->dtAlertExpireTime))) {
262 g_pais_alert_dialog_active->UpdateText();
264 g_pais_alert_dialog_active->Close();
265 m_bAIS_Audio_Alert_On =
false;
268 if (
true == palert_target->b_suppress_audio)
269 m_bAIS_Audio_Alert_On =
false;
271 m_bAIS_Audio_Alert_On =
true;
273 g_pais_alert_dialog_active->Close();
274 m_bAIS_Audio_Alert_On =
false;
280 if (!g_bAIS_CPA_Alert_Audio) m_bAIS_Audio_Alert_On =
false;
282 if (m_bAIS_Audio_Alert_On) {
284 m_AIS_Sound = SoundFactory(g_CmdSoundString.mb_str(wxConvUTF8));
286 if (!AIS_AlertPlaying()) {
287 m_bAIS_AlertPlaying =
true;
292 if (g_bAIS_GCPA_Alert_Audio) soundFile = g_AIS_sound_file;
295 if (g_bAIS_DSC_Alert_Audio) soundFile = g_DSC_sound_file;
298 if (g_bAIS_SART_Alert_Audio) soundFile = g_SART_sound_file;
302 m_AIS_Sound->Load(soundFile, g_iSoundDeviceIndex);
303 if (m_AIS_Sound->IsOk()) {
304 m_AIS_Sound->SetFinishedCallback(onSoundFinished,
this);
305 if (!m_AIS_Sound->Play()) m_bAIS_AlertPlaying =
false;
307 m_bAIS_AlertPlaying =
false;
312 if (palert_target && (palert_target->Class == AIS_SART)) {
313 for (
unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
314 if (palert_target->MMSI == g_MMSI_Props_Array[i]->MMSI) {
316 gFrame->UpdateAISMOBRoute(palert_target.get());
318 gFrame->ActivateAISMOBRoute(palert_target.get());
EventVar new_ais_wp
Notified when new AIS wp is created.
EventVar info_update
Notified when AIS user dialogs should update.
EventVar touch_state
Notified when gFrame->TouchAISActive() should be invoked.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
Adds a std::shared<void> element to wxCommandEvent.