36#include <wx/datetime.h>
40#include "o_sound/o_sound.h"
47#include "ais_info_gui.h"
57wxDEFINE_EVENT(EVT_AIS_DEL_TRACK, wxCommandEvent);
59wxDEFINE_EVENT(EVT_AIS_NEW_TRACK, wxCommandEvent);
60wxDEFINE_EVENT(EVT_AIS_TOUCH, wxCommandEvent);
61wxDEFINE_EVENT(EVT_AIS_WP, wxCommandEvent);
62wxDEFINE_EVENT(SOUND_PLAYED_EVTYPE, wxCommandEvent);
65extern bool g_bquiting;
66extern int g_iSoundDeviceIndex;
69extern wxString g_CmdSoundString;
76static void onSoundFinished(
void *ptr) {
78 wxCommandEvent ev(SOUND_PLAYED_EVTYPE);
79 wxPostEvent(g_pAISGUI, ev);
84 NavObj_dB::GetInstance().InsertRoutePoint(pWP);
86 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
87 pRouteManagerDialog->UpdateWptListCtrl();
88 if (gFrame->GetPrimaryCanvas()) {
89 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
90 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
91 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
92 gFrame->RefreshAllCanvas(
false);
93 gFrame->InvalidateAllGL();
97const static char *
const kDeleteTrackPrompt = _(R
"(
98This AIS target has Persistent Tracking selected by MMSI properties
99A Persistent track recording will therefore be restarted for this target.
101Do you instead want to stop Persistent Tracking for this target?
105 if (wxID_NO == OCPNMessageBox(NULL, kDeleteTrackPrompt, _(
"OpenCPN Info"),
106 wxYES_NO | wxCENTER, 60)) {
107 props->m_bPersistentTrack =
true;
111AisInfoGui::AisInfoGui() {
116 auto palert_target = std::static_pointer_cast<const AisTargetData>(ptr);
117 ShowAisInfo(palert_target);
121 Bind(EVT_AIS_TOUCH, [&](wxCommandEvent ev) { gFrame->TouchAISActive(); });
124 Bind(EVT_AIS_WP, [&](wxCommandEvent ev) {
125 auto pWP =
static_cast<RoutePoint *
>(ev.GetClientData());
126 OnNewAisWaypoint(pWP);
130 Bind(EVT_AIS_NEW_TRACK, [&](wxCommandEvent ev) {
131 auto t =
static_cast<Track *
>(ev.GetClientData());
132 NavObj_dB::GetInstance().InsertTrack(t);
136 Bind(EVT_AIS_DEL_TRACK, [&](wxCommandEvent ev) {
141 Bind(SOUND_PLAYED_EVTYPE,
142 [&](wxCommandEvent ev) { OnSoundFinishedAISAudio(ev); });
145 m_bAIS_Audio_Alert_On =
false;
146 m_bAIS_AlertPlaying =
false;
149void AisInfoGui::OnSoundFinishedAISAudio(wxCommandEvent &event) {
154 m_AIS_Sound->UnLoad();
156 m_bAIS_AlertPlaying =
false;
159void AisInfoGui::ShowAisInfo(
160 std::shared_ptr<const AisTargetData> palert_target) {
161 if (!palert_target)
return;
163 int audioType = AISAUDIO_NONE;
165 switch (palert_target->Class) {
167 audioType = AISAUDIO_DSC;
170 audioType = AISAUDIO_SART;
173 audioType = AISAUDIO_CPA;
178 if (!g_pais_alert_dialog_active) {
180 (palert_target->Class == AIS_SART) || (palert_target->Class == AIS_DSC);
181 bool b_createWP = palert_target->Class == AIS_DSC;
182 bool b_ack = palert_target->Class != AIS_DSC;
195 if (gFrame->IsIconized() || !gFrame->IsActive())
196 gFrame->RequestUserAttention();
199 if (!gFrame->IsIconized()) {
201 pAISAlertDialog->Create(palert_target->MMSI, gFrame,
g_pAIS, b_jumpto,
202 b_createWP, b_ack, -1, _(
"AIS Alert"));
204 g_pais_alert_dialog_active = pAISAlertDialog;
206 wxTimeSpan alertLifeTime(0, 1, 0,
208 auto alert_dlg_active =
210 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
211 g_Platform->PositionAISAlert(pAISAlertDialog);
213 pAISAlertDialog->Show();
217 m_bAIS_Audio_Alert_On =
true;
224 double tcpa_min = 1e6;
226 const auto ¤t_targets =
g_pAIS->GetTargetList();
227 for (
auto &it : current_targets) {
230 if ((td->Class != AIS_SART) && (td->Class != AIS_DSC)) {
231 if (g_bAIS_CPA_Alert && td->b_active) {
232 if ((AIS_ALERT_SET == td->n_alert_state) && !td->b_in_ack_timeout) {
233 if (td->TCPA < tcpa_min) {
235 palert_target_lowestcpa = td.get();
244 auto alert_dlg_active =
247 g_pAIS->Get_Target_Data_From_MMSI(alert_dlg_active->Get_Dialog_MMSI());
253 if (AIS_NO_ALERT == palert_target->n_alert_state) {
254 if (palert_target_lowestcpa) {
255 palert_target = NULL;
261 wxDateTime now = wxDateTime::Now();
262 if (((AIS_ALERT_SET == palert_target->n_alert_state) &&
263 !palert_target->b_in_ack_timeout) ||
264 (palert_target->Class == AIS_SART)) {
265 alert_dlg_active->UpdateText();
267 wxTimeSpan alertLifeTime(0, 1, 0,
269 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
272 else if (!palert_target->b_in_ack_timeout &&
273 (now.IsEarlierThan(alert_dlg_active->dtAlertExpireTime))) {
274 alert_dlg_active->UpdateText();
276 alert_dlg_active->Close();
277 m_bAIS_Audio_Alert_On =
false;
280 if (
true == palert_target->b_suppress_audio)
281 m_bAIS_Audio_Alert_On =
false;
283 m_bAIS_Audio_Alert_On =
true;
285 alert_dlg_active->Close();
286 m_bAIS_Audio_Alert_On =
false;
292 if (!g_bAIS_CPA_Alert_Audio) m_bAIS_Audio_Alert_On =
false;
294 if (m_bAIS_Audio_Alert_On) {
296 m_AIS_Sound = o_sound::Factory();
298 if (!AIS_AlertPlaying()) {
299 m_bAIS_AlertPlaying =
true;
303 if (g_bAIS_DSC_Alert_Audio) soundFile = g_DSC_sound_file;
306 if (g_bAIS_SART_Alert_Audio) soundFile = g_SART_sound_file;
310 if (g_bAIS_GCPA_Alert_Audio) soundFile = g_AIS_sound_file;
314 m_AIS_Sound->Load(soundFile, g_iSoundDeviceIndex);
315 if (m_AIS_Sound->IsOk()) {
316 m_AIS_Sound->SetFinishedCallback(onSoundFinished,
this);
317 if (!m_AIS_Sound->Play()) {
320 m_bAIS_AlertPlaying =
false;
325 m_bAIS_AlertPlaying =
false;
331 if (palert_target && (palert_target->Class == AIS_SART)) {
335 gFrame->UpdateAISMOBRoute(palert_target.get());
337 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.