36#include <wx/datetime.h>
40#include "model/ais_decoder.h"
42#include "model/ais_target_data.h"
43#include "model/route_point.h"
45#include "ais_info_gui.h"
46#include "AISTargetAlertDialog.h"
49#include "ocpn_frame.h"
50#include "OCPNPlatform.h"
51#include "routemanagerdialog.h"
52#include "SoundFactory.h"
55wxDEFINE_EVENT(EVT_AIS_DEL_TRACK, wxCommandEvent);
57wxDEFINE_EVENT(EVT_AIS_NEW_TRACK, wxCommandEvent);
58wxDEFINE_EVENT(EVT_AIS_TOUCH, wxCommandEvent);
59wxDEFINE_EVENT(EVT_AIS_WP, wxCommandEvent);
60wxDEFINE_EVENT(SOUND_PLAYED_EVTYPE, wxCommandEvent);
62extern ArrayOfMmsiProperties g_MMSI_Props_Array;
63extern bool g_bquiting;
64extern int g_iSoundDeviceIndex;
66extern Route *pAISMOBRoute;
67extern wxString g_CmdSoundString;
73static void onSoundFinished(
void *ptr) {
75 wxCommandEvent ev(SOUND_PLAYED_EVTYPE);
76 wxPostEvent(g_pAISGUI, ev);
81 pConfig->AddNewWayPoint(pWP, -1);
82 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
83 pRouteManagerDialog->UpdateWptListCtrl();
84 if (gFrame->GetPrimaryCanvas()) {
85 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
86 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
87 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
88 gFrame->RefreshAllCanvas(
false);
89 gFrame->InvalidateAllGL();
93const static char *
const kDeleteTrackPrompt = _(R
"(
94This AIS target has Persistent Tracking selected by MMSI properties
95A Persistent track recording will therefore be restarted for this target.
97Do you instead want to stop Persistent Tracking for this target?
101 if (wxID_NO == OCPNMessageBox(NULL, kDeleteTrackPrompt, _(
"OpenCPN Info"),
102 wxYES_NO | wxCENTER, 60)) {
103 props->m_bPersistentTrack =
true;
107AisInfoGui::AisInfoGui() {
111 auto ptr = ev.GetSharedPtr();
112 auto palert_target = std::static_pointer_cast<const AisTargetData>(ptr);
113 ShowAisInfo(palert_target);
117 Bind(EVT_AIS_TOUCH, [&](wxCommandEvent ev) { gFrame->TouchAISActive(); });
120 Bind(EVT_AIS_WP, [&](wxCommandEvent ev) {
121 auto pWP =
static_cast<RoutePoint *
>(ev.GetClientData());
122 OnNewAisWaypoint(pWP);
126 Bind(EVT_AIS_NEW_TRACK, [&](wxCommandEvent ev) {
127 auto t =
static_cast<Track *
>(ev.GetClientData());
128 pConfig->AddNewTrack(t);
132 Bind(EVT_AIS_DEL_TRACK, [&](wxCommandEvent ev) {
137 Bind(SOUND_PLAYED_EVTYPE,
138 [&](wxCommandEvent ev) { OnSoundFinishedAISAudio(ev); });
141 m_bAIS_Audio_Alert_On =
false;
142 m_bAIS_AlertPlaying =
false;
145void AisInfoGui::OnSoundFinishedAISAudio(wxCommandEvent &event) {
150 m_AIS_Sound->UnLoad();
152 m_bAIS_AlertPlaying =
false;
155void AisInfoGui::ShowAisInfo(
156 std::shared_ptr<const AisTargetData> palert_target) {
157 if (!palert_target)
return;
159 int audioType = AISAUDIO_NONE;
161 switch (palert_target->Class) {
163 audioType = AISAUDIO_DSC;
166 audioType = AISAUDIO_SART;
169 audioType = AISAUDIO_CPA;
174 if (!g_pais_alert_dialog_active) {
176 (palert_target->Class == AIS_SART) || (palert_target->Class == AIS_DSC);
177 bool b_createWP = palert_target->Class == AIS_DSC;
178 bool b_ack = palert_target->Class != AIS_DSC;
191 if (gFrame->IsIconized() || !gFrame->IsActive())
192 gFrame->RequestUserAttention();
195 if (!gFrame->IsIconized()) {
197 pAISAlertDialog->Create(palert_target->MMSI, gFrame, g_pAIS, b_jumpto,
198 b_createWP, b_ack, -1, _(
"AIS Alert"));
200 g_pais_alert_dialog_active = pAISAlertDialog;
202 wxTimeSpan alertLifeTime(0, 1, 0,
204 auto alert_dlg_active =
206 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
207 g_Platform->PositionAISAlert(pAISAlertDialog);
209 pAISAlertDialog->Show();
213 m_bAIS_Audio_Alert_On =
true;
220 double tcpa_min = 1e6;
222 const auto ¤t_targets = g_pAIS->GetTargetList();
223 for (
auto &it : current_targets) {
226 if ((td->Class != AIS_SART) && (td->Class != AIS_DSC)) {
227 if (g_bAIS_CPA_Alert && td->b_active) {
228 if ((AIS_ALERT_SET == td->n_alert_state) && !td->b_in_ack_timeout) {
229 if (td->TCPA < tcpa_min) {
231 palert_target_lowestcpa = td.get();
240 auto alert_dlg_active =
243 g_pAIS->Get_Target_Data_From_MMSI(alert_dlg_active->Get_Dialog_MMSI());
249 if (AIS_NO_ALERT == palert_target->n_alert_state) {
250 if (palert_target_lowestcpa) {
251 palert_target = NULL;
257 wxDateTime now = wxDateTime::Now();
258 if (((AIS_ALERT_SET == palert_target->n_alert_state) &&
259 !palert_target->b_in_ack_timeout) ||
260 (palert_target->Class == AIS_SART)) {
261 alert_dlg_active->UpdateText();
263 wxTimeSpan alertLifeTime(0, 1, 0,
265 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
268 else if (!palert_target->b_in_ack_timeout &&
269 (now.IsEarlierThan(alert_dlg_active->dtAlertExpireTime))) {
270 alert_dlg_active->UpdateText();
272 alert_dlg_active->Close();
273 m_bAIS_Audio_Alert_On =
false;
276 if (
true == palert_target->b_suppress_audio)
277 m_bAIS_Audio_Alert_On =
false;
279 m_bAIS_Audio_Alert_On =
true;
281 alert_dlg_active->Close();
282 m_bAIS_Audio_Alert_On =
false;
288 if (!g_bAIS_CPA_Alert_Audio) m_bAIS_Audio_Alert_On =
false;
290 if (m_bAIS_Audio_Alert_On) {
292 m_AIS_Sound = SoundFactory();
294 if (!AIS_AlertPlaying()) {
295 m_bAIS_AlertPlaying =
true;
299 if (g_bAIS_DSC_Alert_Audio) soundFile = g_DSC_sound_file;
302 if (g_bAIS_SART_Alert_Audio) soundFile = g_SART_sound_file;
306 if (g_bAIS_GCPA_Alert_Audio) soundFile = g_AIS_sound_file;
310 m_AIS_Sound->Load(soundFile, g_iSoundDeviceIndex);
311 if (m_AIS_Sound->IsOk()) {
312 m_AIS_Sound->SetFinishedCallback(onSoundFinished,
this);
313 if (!m_AIS_Sound->Play()) {
316 m_bAIS_AlertPlaying =
false;
321 m_bAIS_AlertPlaying =
false;
327 if (palert_target && (palert_target->Class == AIS_SART)) {
328 for (
unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
329 if (palert_target->MMSI == g_MMSI_Props_Array[i]->MMSI) {
331 gFrame->UpdateAISMOBRoute(palert_target.get());
333 gFrame->ActivateAISMOBRoute(palert_target.get());
Global state for AIS decoder.
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.
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.
Represents a track, which is a series of connected track points.