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"
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);
63extern ArrayOfMmsiProperties g_MMSI_Props_Array;
64extern bool g_bquiting;
65extern int g_iSoundDeviceIndex;
67extern Route *pAISMOBRoute;
68extern wxString g_CmdSoundString;
74static void onSoundFinished(
void *ptr) {
76 wxCommandEvent ev(SOUND_PLAYED_EVTYPE);
77 wxPostEvent(g_pAISGUI, ev);
82 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
84 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
85 pRouteManagerDialog->UpdateWptListCtrl();
86 if (gFrame->GetPrimaryCanvas()) {
87 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
88 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
89 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
90 gFrame->RefreshAllCanvas(
false);
91 gFrame->InvalidateAllGL();
95const static char *
const kDeleteTrackPrompt = _(R
"(
96This AIS target has Persistent Tracking selected by MMSI properties
97A Persistent track recording will therefore be restarted for this target.
99Do you instead want to stop Persistent Tracking for this target?
103 if (wxID_NO == OCPNMessageBox(NULL, kDeleteTrackPrompt, _(
"OpenCPN Info"),
104 wxYES_NO | wxCENTER, 60)) {
105 props->m_bPersistentTrack =
true;
109AisInfoGui::AisInfoGui() {
114 auto palert_target = std::static_pointer_cast<const AisTargetData>(ptr);
115 ShowAisInfo(palert_target);
119 Bind(EVT_AIS_TOUCH, [&](wxCommandEvent ev) { gFrame->TouchAISActive(); });
122 Bind(EVT_AIS_WP, [&](wxCommandEvent ev) {
123 auto pWP =
static_cast<RoutePoint *
>(ev.GetClientData());
124 OnNewAisWaypoint(pWP);
128 Bind(EVT_AIS_NEW_TRACK, [&](wxCommandEvent ev) {
129 auto t =
static_cast<Track *
>(ev.GetClientData());
130 NavObj_dB::GetInstance().InsertTrack(t);
134 Bind(EVT_AIS_DEL_TRACK, [&](wxCommandEvent ev) {
139 Bind(SOUND_PLAYED_EVTYPE,
140 [&](wxCommandEvent ev) { OnSoundFinishedAISAudio(ev); });
143 m_bAIS_Audio_Alert_On =
false;
144 m_bAIS_AlertPlaying =
false;
147void AisInfoGui::OnSoundFinishedAISAudio(wxCommandEvent &event) {
152 m_AIS_Sound->UnLoad();
154 m_bAIS_AlertPlaying =
false;
157void AisInfoGui::ShowAisInfo(
158 std::shared_ptr<const AisTargetData> palert_target) {
159 if (!palert_target)
return;
161 int audioType = AISAUDIO_NONE;
163 switch (palert_target->Class) {
165 audioType = AISAUDIO_DSC;
168 audioType = AISAUDIO_SART;
171 audioType = AISAUDIO_CPA;
176 if (!g_pais_alert_dialog_active) {
178 (palert_target->Class == AIS_SART) || (palert_target->Class == AIS_DSC);
179 bool b_createWP = palert_target->Class == AIS_DSC;
180 bool b_ack = palert_target->Class != AIS_DSC;
193 if (gFrame->IsIconized() || !gFrame->IsActive())
194 gFrame->RequestUserAttention();
197 if (!gFrame->IsIconized()) {
199 pAISAlertDialog->Create(palert_target->MMSI, gFrame, g_pAIS, b_jumpto,
200 b_createWP, b_ack, -1, _(
"AIS Alert"));
202 g_pais_alert_dialog_active = pAISAlertDialog;
204 wxTimeSpan alertLifeTime(0, 1, 0,
206 auto alert_dlg_active =
208 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
209 g_Platform->PositionAISAlert(pAISAlertDialog);
211 pAISAlertDialog->Show();
215 m_bAIS_Audio_Alert_On =
true;
222 double tcpa_min = 1e6;
224 const auto ¤t_targets = g_pAIS->GetTargetList();
225 for (
auto &it : current_targets) {
228 if ((td->Class != AIS_SART) && (td->Class != AIS_DSC)) {
229 if (g_bAIS_CPA_Alert && td->b_active) {
230 if ((AIS_ALERT_SET == td->n_alert_state) && !td->b_in_ack_timeout) {
231 if (td->TCPA < tcpa_min) {
233 palert_target_lowestcpa = td.get();
242 auto alert_dlg_active =
245 g_pAIS->Get_Target_Data_From_MMSI(alert_dlg_active->Get_Dialog_MMSI());
251 if (AIS_NO_ALERT == palert_target->n_alert_state) {
252 if (palert_target_lowestcpa) {
253 palert_target = NULL;
259 wxDateTime now = wxDateTime::Now();
260 if (((AIS_ALERT_SET == palert_target->n_alert_state) &&
261 !palert_target->b_in_ack_timeout) ||
262 (palert_target->Class == AIS_SART)) {
263 alert_dlg_active->UpdateText();
265 wxTimeSpan alertLifeTime(0, 1, 0,
267 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
270 else if (!palert_target->b_in_ack_timeout &&
271 (now.IsEarlierThan(alert_dlg_active->dtAlertExpireTime))) {
272 alert_dlg_active->UpdateText();
274 alert_dlg_active->Close();
275 m_bAIS_Audio_Alert_On =
false;
278 if (
true == palert_target->b_suppress_audio)
279 m_bAIS_Audio_Alert_On =
false;
281 m_bAIS_Audio_Alert_On =
true;
283 alert_dlg_active->Close();
284 m_bAIS_Audio_Alert_On =
false;
290 if (!g_bAIS_CPA_Alert_Audio) m_bAIS_Audio_Alert_On =
false;
292 if (m_bAIS_Audio_Alert_On) {
294 m_AIS_Sound = SoundFactory();
296 if (!AIS_AlertPlaying()) {
297 m_bAIS_AlertPlaying =
true;
301 if (g_bAIS_DSC_Alert_Audio) soundFile = g_DSC_sound_file;
304 if (g_bAIS_SART_Alert_Audio) soundFile = g_SART_sound_file;
308 if (g_bAIS_GCPA_Alert_Audio) soundFile = g_AIS_sound_file;
312 m_AIS_Sound->Load(soundFile, g_iSoundDeviceIndex);
313 if (m_AIS_Sound->IsOk()) {
314 m_AIS_Sound->SetFinishedCallback(onSoundFinished,
this);
315 if (!m_AIS_Sound->Play()) {
318 m_bAIS_AlertPlaying =
false;
323 m_bAIS_AlertPlaying =
false;
329 if (palert_target && (palert_target->Class == AIS_SART)) {
330 for (
unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
331 if (palert_target->MMSI == g_MMSI_Props_Array[i]->MMSI) {
333 gFrame->UpdateAISMOBRoute(palert_target.get());
335 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.
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.