36#include <wx/datetime.h>
45#include "ais_info_gui.h"
52#include "SoundFactory.h"
56wxDEFINE_EVENT(EVT_AIS_DEL_TRACK, wxCommandEvent);
58wxDEFINE_EVENT(EVT_AIS_NEW_TRACK, wxCommandEvent);
59wxDEFINE_EVENT(EVT_AIS_TOUCH, wxCommandEvent);
60wxDEFINE_EVENT(EVT_AIS_WP, wxCommandEvent);
61wxDEFINE_EVENT(SOUND_PLAYED_EVTYPE, wxCommandEvent);
64extern bool g_bquiting;
65extern int g_iSoundDeviceIndex;
68extern wxString g_CmdSoundString;
75static void onSoundFinished(
void *ptr) {
77 wxCommandEvent ev(SOUND_PLAYED_EVTYPE);
78 wxPostEvent(g_pAISGUI, ev);
83 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
85 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
86 pRouteManagerDialog->UpdateWptListCtrl();
87 if (gFrame->GetPrimaryCanvas()) {
88 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
89 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
90 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
91 gFrame->RefreshAllCanvas(
false);
92 gFrame->InvalidateAllGL();
96const static char *
const kDeleteTrackPrompt = _(R
"(
97This AIS target has Persistent Tracking selected by MMSI properties
98A Persistent track recording will therefore be restarted for this target.
100Do you instead want to stop Persistent Tracking for this target?
104 if (wxID_NO == OCPNMessageBox(NULL, kDeleteTrackPrompt, _(
"OpenCPN Info"),
105 wxYES_NO | wxCENTER, 60)) {
106 props->m_bPersistentTrack =
true;
110AisInfoGui::AisInfoGui() {
115 auto palert_target = std::static_pointer_cast<const AisTargetData>(ptr);
116 ShowAisInfo(palert_target);
120 Bind(EVT_AIS_TOUCH, [&](wxCommandEvent ev) { gFrame->TouchAISActive(); });
123 Bind(EVT_AIS_WP, [&](wxCommandEvent ev) {
124 auto pWP =
static_cast<RoutePoint *
>(ev.GetClientData());
125 OnNewAisWaypoint(pWP);
129 Bind(EVT_AIS_NEW_TRACK, [&](wxCommandEvent ev) {
130 auto t =
static_cast<Track *
>(ev.GetClientData());
131 NavObj_dB::GetInstance().InsertTrack(t);
135 Bind(EVT_AIS_DEL_TRACK, [&](wxCommandEvent ev) {
140 Bind(SOUND_PLAYED_EVTYPE,
141 [&](wxCommandEvent ev) { OnSoundFinishedAISAudio(ev); });
144 m_bAIS_Audio_Alert_On =
false;
145 m_bAIS_AlertPlaying =
false;
148void AisInfoGui::OnSoundFinishedAISAudio(wxCommandEvent &event) {
153 m_AIS_Sound->UnLoad();
155 m_bAIS_AlertPlaying =
false;
158void AisInfoGui::ShowAisInfo(
159 std::shared_ptr<const AisTargetData> palert_target) {
160 if (!palert_target)
return;
162 int audioType = AISAUDIO_NONE;
164 switch (palert_target->Class) {
166 audioType = AISAUDIO_DSC;
169 audioType = AISAUDIO_SART;
172 audioType = AISAUDIO_CPA;
177 if (!g_pais_alert_dialog_active) {
179 (palert_target->Class == AIS_SART) || (palert_target->Class == AIS_DSC);
180 bool b_createWP = palert_target->Class == AIS_DSC;
181 bool b_ack = palert_target->Class != AIS_DSC;
194 if (gFrame->IsIconized() || !gFrame->IsActive())
195 gFrame->RequestUserAttention();
198 if (!gFrame->IsIconized()) {
200 pAISAlertDialog->Create(palert_target->MMSI, gFrame,
g_pAIS, b_jumpto,
201 b_createWP, b_ack, -1, _(
"AIS Alert"));
203 g_pais_alert_dialog_active = pAISAlertDialog;
205 wxTimeSpan alertLifeTime(0, 1, 0,
207 auto alert_dlg_active =
209 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
210 g_Platform->PositionAISAlert(pAISAlertDialog);
212 pAISAlertDialog->Show();
216 m_bAIS_Audio_Alert_On =
true;
223 double tcpa_min = 1e6;
225 const auto ¤t_targets =
g_pAIS->GetTargetList();
226 for (
auto &it : current_targets) {
229 if ((td->Class != AIS_SART) && (td->Class != AIS_DSC)) {
230 if (g_bAIS_CPA_Alert && td->b_active) {
231 if ((AIS_ALERT_SET == td->n_alert_state) && !td->b_in_ack_timeout) {
232 if (td->TCPA < tcpa_min) {
234 palert_target_lowestcpa = td.get();
243 auto alert_dlg_active =
246 g_pAIS->Get_Target_Data_From_MMSI(alert_dlg_active->Get_Dialog_MMSI());
252 if (AIS_NO_ALERT == palert_target->n_alert_state) {
253 if (palert_target_lowestcpa) {
254 palert_target = NULL;
260 wxDateTime now = wxDateTime::Now();
261 if (((AIS_ALERT_SET == palert_target->n_alert_state) &&
262 !palert_target->b_in_ack_timeout) ||
263 (palert_target->Class == AIS_SART)) {
264 alert_dlg_active->UpdateText();
266 wxTimeSpan alertLifeTime(0, 1, 0,
268 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
271 else if (!palert_target->b_in_ack_timeout &&
272 (now.IsEarlierThan(alert_dlg_active->dtAlertExpireTime))) {
273 alert_dlg_active->UpdateText();
275 alert_dlg_active->Close();
276 m_bAIS_Audio_Alert_On =
false;
279 if (
true == palert_target->b_suppress_audio)
280 m_bAIS_Audio_Alert_On =
false;
282 m_bAIS_Audio_Alert_On =
true;
284 alert_dlg_active->Close();
285 m_bAIS_Audio_Alert_On =
false;
291 if (!g_bAIS_CPA_Alert_Audio) m_bAIS_Audio_Alert_On =
false;
293 if (m_bAIS_Audio_Alert_On) {
295 m_AIS_Sound = SoundFactory();
297 if (!AIS_AlertPlaying()) {
298 m_bAIS_AlertPlaying =
true;
302 if (g_bAIS_DSC_Alert_Audio) soundFile = g_DSC_sound_file;
305 if (g_bAIS_SART_Alert_Audio) soundFile = g_SART_sound_file;
309 if (g_bAIS_GCPA_Alert_Audio) soundFile = g_AIS_sound_file;
313 m_AIS_Sound->Load(soundFile, g_iSoundDeviceIndex);
314 if (m_AIS_Sound->IsOk()) {
315 m_AIS_Sound->SetFinishedCallback(onSoundFinished,
this);
316 if (!m_AIS_Sound->Play()) {
319 m_bAIS_AlertPlaying =
false;
324 m_bAIS_AlertPlaying =
false;
330 if (palert_target && (palert_target->Class == AIS_SART)) {
334 gFrame->UpdateAISMOBRoute(palert_target.get());
336 gFrame->ActivateAISMOBRoute(palert_target.get());
ArrayOfMmsiProperties g_MMSI_Props_Array
Global instance.
AisDecoder * g_pAIS
Global instance.
Class AisDecoder and helpers.
Global state for AIS decoder.
Class AISTargetAlertDialog and helpers.
Generic Chart canvas base.
Dialog for displaying AIS target alerts.
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.
Handles the AIS information GUI and sound alerts.
Process incoming AIS messages.
void Listen(const std::string &key, wxEvtHandler *listener, wxEventType evt)
Set object to send wxEventType ev to listener on changes in key.
Custom event class for OpenCPN's notification system.
std::shared_ptr< const void > GetSharedPtr() const
Gets the event's payload data.
Represents a waypoint or mark within the navigation system.
Represents a navigational route in the navigation system.
Represents a track, which is a series of connected track points.
MySQL based storage for routes, tracks, etc.
Waypoint or mark abstraction.
Route * pAISMOBRoute
Global instance.
Framework for Undo features.