30 #include <wx/wxprec.h>
37 #include <wx/datetime.h>
39 #include <wx/string.h>
41 #include "model/ais_decoder.h"
43 #include "model/ais_target_data.h"
44 #include "model/route_point.h"
46 #include "ais_info_gui.h"
47 #include "AISTargetAlertDialog.h"
50 #include "ocpn_frame.h"
51 #include "OCPNPlatform.h"
52 #include "routemanagerdialog.h"
53 #include "SoundFactory.h"
63 extern ArrayOfMmsiProperties g_MMSI_Props_Array;
64 extern bool g_bquiting;
65 extern int g_iSoundDeviceIndex;
67 extern Route *pAISMOBRoute;
68 extern wxString g_CmdSoundString;
74 static void onSoundFinished(
void *ptr) {
76 wxCommandEvent ev(SOUND_PLAYED_EVTYPE);
77 wxPostEvent(g_pAISGUI, ev);
81 static void OnNewAisWaypoint(
RoutePoint* pWP) {
82 pConfig->AddNewWayPoint(pWP, -1);
83 if (pRouteManagerDialog && pRouteManagerDialog->IsShown())
84 pRouteManagerDialog->UpdateWptListCtrl();
85 if (gFrame->GetPrimaryCanvas()) {
86 gFrame->GetPrimaryCanvas()->undo->BeforeUndoableAction(
87 Undo_CreateWaypoint, pWP, Undo_HasParent, NULL);
88 gFrame->GetPrimaryCanvas()->undo->AfterUndoableAction(NULL);
89 gFrame->RefreshAllCanvas(
false);
90 gFrame->InvalidateAllGL();
94 const static char*
const kDeleteTrackPrompt =
96 This AIS target has Persistent Tracking selected by MMSI properties
97 A Persistent track recording will therefore be restarted for this target.
99 Do you instead want to stop Persistent Tracking for this target?
104 if (wxID_NO == OCPNMessageBox(NULL, kDeleteTrackPrompt, _(
"OpenCPN Info"),
105 wxYES_NO | wxCENTER, 60))
107 props->m_bPersistentTrack =
true;
112 AisInfoGui::AisInfoGui() {
116 auto ptr = ev.GetSharedPtr();
117 auto palert_target = std::static_pointer_cast<const AisTargetData>(ptr);
118 ShowAisInfo(palert_target); }
122 Bind(EVT_AIS_TOUCH, [&](wxCommandEvent ev) { gFrame->TouchAISActive(); });
125 Bind(EVT_AIS_WP, [&](wxCommandEvent ev) {
126 auto pWP =
static_cast<RoutePoint*
>(ev.GetClientData());
127 OnNewAisWaypoint(pWP); });
131 Bind(EVT_AIS_NEW_TRACK, [&](wxCommandEvent ev) {
132 auto t =
static_cast<Track*
>(ev.GetClientData());
133 pConfig->AddNewTrack(t); });
137 Bind(EVT_AIS_DEL_TRACK, [&](wxCommandEvent ev) {
139 OnDeleteTrack(t); });
141 Bind(SOUND_PLAYED_EVTYPE, [&](wxCommandEvent ev) {
142 OnSoundFinishedAISAudio(ev); });
145 m_bAIS_Audio_Alert_On =
false;
146 m_bAIS_AlertPlaying =
false;
150 void AisInfoGui::OnSoundFinishedAISAudio(wxCommandEvent &event) {
155 m_AIS_Sound->UnLoad();
157 m_bAIS_AlertPlaying =
false;
160 void AisInfoGui::ShowAisInfo(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) {
179 bool b_jumpto = (palert_target->Class == AIS_SART) ||
180 (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,
202 b_jumpto, b_createWP, b_ack, -1,
205 g_pais_alert_dialog_active = pAISAlertDialog;
207 wxTimeSpan alertLifeTime(0, 1, 0,
209 auto alert_dlg_active =
211 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
212 g_Platform->PositionAISAlert(pAISAlertDialog);
214 pAISAlertDialog->Show();
218 m_bAIS_Audio_Alert_On =
true;
226 double tcpa_min = 1e6;
228 const auto& current_targets = g_pAIS->GetTargetList();
229 for (
auto& it : current_targets) {
232 if ((td->Class != AIS_SART) && (td->Class != AIS_DSC)) {
233 if (g_bAIS_CPA_Alert && td->b_active) {
234 if ((AIS_ALERT_SET == td->n_alert_state) && !td->b_in_ack_timeout) {
235 if (td->TCPA < tcpa_min) {
237 palert_target_lowestcpa = td.get();
246 auto alert_dlg_active =
248 palert_target = g_pAIS->Get_Target_Data_From_MMSI(
249 alert_dlg_active->Get_Dialog_MMSI());
255 if (AIS_NO_ALERT == palert_target->n_alert_state) {
256 if (palert_target_lowestcpa) {
257 palert_target = NULL;
263 wxDateTime now = wxDateTime::Now();
264 if (((AIS_ALERT_SET == palert_target->n_alert_state) &&
265 !palert_target->b_in_ack_timeout) ||
266 (palert_target->Class == AIS_SART) ) {
267 alert_dlg_active->UpdateText();
269 wxTimeSpan alertLifeTime(0, 1, 0,
271 alert_dlg_active->dtAlertExpireTime = wxDateTime::Now() + alertLifeTime;
274 else if (!palert_target->b_in_ack_timeout &&
275 (now.IsEarlierThan(alert_dlg_active->dtAlertExpireTime))) {
276 alert_dlg_active->UpdateText();
278 alert_dlg_active->Close();
279 m_bAIS_Audio_Alert_On =
false;
282 if (
true == palert_target->b_suppress_audio)
283 m_bAIS_Audio_Alert_On =
false;
285 m_bAIS_Audio_Alert_On =
true;
287 alert_dlg_active->Close();
288 m_bAIS_Audio_Alert_On =
false;
294 if (!g_bAIS_CPA_Alert_Audio) m_bAIS_Audio_Alert_On =
false;
296 if (m_bAIS_Audio_Alert_On) {
298 m_AIS_Sound = SoundFactory();
300 if (!AIS_AlertPlaying()) {
301 m_bAIS_AlertPlaying =
true;
305 if (g_bAIS_DSC_Alert_Audio) soundFile = g_DSC_sound_file;
308 if (g_bAIS_SART_Alert_Audio) soundFile = g_SART_sound_file;
312 if (g_bAIS_GCPA_Alert_Audio) soundFile = g_AIS_sound_file;
316 m_AIS_Sound->Load(soundFile, g_iSoundDeviceIndex);
317 if (m_AIS_Sound->IsOk()) {
318 m_AIS_Sound->SetFinishedCallback(onSoundFinished,
this);
319 if (!m_AIS_Sound->Play()){
322 m_bAIS_AlertPlaying =
false;
327 m_bAIS_AlertPlaying =
false;
333 if (palert_target && (palert_target->Class == AIS_SART)) {
334 for (
unsigned int i = 0; i < g_MMSI_Props_Array.GetCount(); i++) {
335 if (palert_target->MMSI == g_MMSI_Props_Array[i]->MMSI) {
337 gFrame->UpdateAISMOBRoute(palert_target.get());
339 gFrame->ActivateAISMOBRoute(palert_target.get());
Global state for AIS decoder.
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.
wxDEFINE_EVENT(REST_IO_EVT, ObservedEvt)
Event from IO thread to main.